@myop/sdk 0.3.32 → 0.3.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundled-declarations.d.ts +199 -50
- package/dist/cjs/_IframeSDK.c2225e19.min.js +1 -0
- package/dist/cjs/{_IframeSDK.8ce25264.js → _IframeSDK.c7926c56.js} +262 -48
- package/dist/cjs/_IframeSDK.c7926c56.js.map +7 -0
- package/dist/cjs/{_MyopHelpers.95610381.js → _MyopHelpers.08d1cf5d.js} +68 -20
- package/dist/cjs/_MyopHelpers.08d1cf5d.js.map +7 -0
- package/dist/cjs/_MyopHelpers.59521d8f.min.js +1 -0
- package/dist/cjs/_WebComponentSDK.0caec562.min.js +1 -0
- package/dist/cjs/{_WebComponentSDK.1aa213d9.js → _WebComponentSDK.501a71f9.js} +262 -48
- package/dist/cjs/_WebComponentSDK.501a71f9.js.map +7 -0
- package/dist/cjs/_hostSDK.02edf3e2.min.js +1 -0
- package/dist/cjs/{_hostSDK.c7ca0fae.js → _hostSDK.cdbc1f60.js} +262 -48
- package/dist/cjs/_hostSDK.cdbc1f60.js.map +7 -0
- package/dist/cjs/myop_sdk.js +14 -14
- package/dist/cjs/myop_sdk.js.map +1 -1
- package/dist/cjs/myop_sdk.min.js +1 -1
- package/dist/cjs-bundled/myop_sdk.bundled.js +272 -50
- package/dist/cjs-bundled/myop_sdk.bundled.js.map +3 -3
- package/dist/cjs-bundled/myop_sdk.bundled.min.js +1 -1
- package/dist/module/Iframe/index.js +322 -49
- package/dist/module/Iframe/index.js.map +2 -2
- package/dist/module/SDK.js +331 -50
- package/dist/module/SDK.js.map +3 -3
- package/dist/module/common/index.d.ts +26 -0
- package/dist/module/common/index.js +1 -1
- package/dist/module/common/index.js.map +2 -2
- package/dist/module/embeddedSDK.js +1 -1
- package/dist/module/helpers/CloudRepository.d.ts +43 -0
- package/dist/module/helpers/cloudRepositoryHelpers.d.ts +21 -2
- package/dist/module/helpers/index.js +70 -21
- package/dist/module/helpers/index.js.map +2 -2
- package/dist/module/host/components/myopExtractedWebComponent.d.ts +1 -0
- package/dist/module/host/components/myopIframeComponent.d.ts +17 -0
- package/dist/module/host/embeddedSDK.js +1 -1
- package/dist/module/host/hostSDK.d.ts +15 -0
- package/dist/module/host/index.d.ts +1 -1
- package/dist/module/host/index.js +322 -49
- package/dist/module/host/index.js.map +2 -2
- package/dist/module/host/loaders/HTMLComponentLoader.d.ts +29 -1
- package/dist/module/webcomponent/index.js +322 -49
- package/dist/module/webcomponent/index.js.map +2 -2
- package/package.json +1 -1
- package/dist/cjs/_IframeSDK.07df88d3.min.js +0 -1
- package/dist/cjs/_IframeSDK.8ce25264.js.map +0 -7
- package/dist/cjs/_MyopHelpers.172384f4.min.js +0 -1
- package/dist/cjs/_MyopHelpers.95610381.js.map +0 -7
- package/dist/cjs/_WebComponentSDK.1aa213d9.js.map +0 -7
- package/dist/cjs/_WebComponentSDK.92468fac.min.js +0 -1
- package/dist/cjs/_hostSDK.c7ca0fae.js.map +0 -7
- package/dist/cjs/_hostSDK.dc198afa.min.js +0 -1
|
@@ -1023,6 +1023,19 @@ var MyopExtractedWebComponent = class extends BaseMyopComponent {
|
|
|
1023
1023
|
__publicField(this, "ctaCleanup");
|
|
1024
1024
|
__publicField(this, "_ctaHandler");
|
|
1025
1025
|
__publicField(this, "_ctaQueue", []);
|
|
1026
|
+
// A single 'myop-cta' listener, attached at construction so CTAs a component
|
|
1027
|
+
// dispatches during its first initWithData() render — before the host attaches
|
|
1028
|
+
// a handler — are buffered (and flushed on setCtaHandler), matching the iframe
|
|
1029
|
+
// path's pre-handler CTA queue.
|
|
1030
|
+
__publicField(this, "_ctaListener", (e) => {
|
|
1031
|
+
const detail = e.detail;
|
|
1032
|
+
if (!(detail == null ? void 0 : detail.action)) return;
|
|
1033
|
+
if (this._ctaHandler && !this.markedForDisposed) {
|
|
1034
|
+
this._ctaHandler(detail.action, detail.payload);
|
|
1035
|
+
} else if (!this._ctaHandler) {
|
|
1036
|
+
this._ctaQueue.push({ action: detail.action, payload: detail.payload });
|
|
1037
|
+
}
|
|
1038
|
+
});
|
|
1026
1039
|
__publicField(this, "cleanupInspect", () => {
|
|
1027
1040
|
});
|
|
1028
1041
|
/**
|
|
@@ -1043,6 +1056,8 @@ var MyopExtractedWebComponent = class extends BaseMyopComponent {
|
|
|
1043
1056
|
(_a = this.customElement.parentNode) == null ? void 0 : _a.removeChild(this.customElement);
|
|
1044
1057
|
});
|
|
1045
1058
|
this.element = customElement;
|
|
1059
|
+
this.customElement.addEventListener("myop-cta", this._ctaListener);
|
|
1060
|
+
this.ctaCleanup = () => this.customElement.removeEventListener("myop-cta", this._ctaListener);
|
|
1046
1061
|
this.setInitiated();
|
|
1047
1062
|
}
|
|
1048
1063
|
inspect() {
|
|
@@ -1087,9 +1102,6 @@ var MyopExtractedWebComponent = class extends BaseMyopComponent {
|
|
|
1087
1102
|
* Called via props.myop_cta_handler = handler
|
|
1088
1103
|
*/
|
|
1089
1104
|
setCtaHandler(handler) {
|
|
1090
|
-
if (this.ctaCleanup) {
|
|
1091
|
-
this.ctaCleanup();
|
|
1092
|
-
}
|
|
1093
1105
|
this._ctaHandler = handler;
|
|
1094
1106
|
if (this._ctaQueue.length > 0) {
|
|
1095
1107
|
const queue = [...this._ctaQueue];
|
|
@@ -1100,24 +1112,6 @@ var MyopExtractedWebComponent = class extends BaseMyopComponent {
|
|
|
1100
1112
|
}
|
|
1101
1113
|
});
|
|
1102
1114
|
}
|
|
1103
|
-
const listener = (e) => {
|
|
1104
|
-
var _a;
|
|
1105
|
-
const customEvent = e;
|
|
1106
|
-
if ((_a = customEvent.detail) == null ? void 0 : _a.action) {
|
|
1107
|
-
if (this._ctaHandler && !this.markedForDisposed) {
|
|
1108
|
-
this._ctaHandler(customEvent.detail.action, customEvent.detail.payload);
|
|
1109
|
-
} else if (!this._ctaHandler) {
|
|
1110
|
-
this._ctaQueue.push({
|
|
1111
|
-
action: customEvent.detail.action,
|
|
1112
|
-
payload: customEvent.detail.payload
|
|
1113
|
-
});
|
|
1114
|
-
}
|
|
1115
|
-
}
|
|
1116
|
-
};
|
|
1117
|
-
this.customElement.addEventListener("myop-cta", listener);
|
|
1118
|
-
this.ctaCleanup = () => {
|
|
1119
|
-
this.customElement.removeEventListener("myop-cta", listener);
|
|
1120
|
-
};
|
|
1121
1115
|
}
|
|
1122
1116
|
};
|
|
1123
1117
|
|
|
@@ -1186,6 +1180,17 @@ var connectProps = (component, propsConfig, selectedSkin) => {
|
|
|
1186
1180
|
}
|
|
1187
1181
|
return void 0;
|
|
1188
1182
|
}
|
|
1183
|
+
if (component instanceof MyopIframeComponent && component.isolated) {
|
|
1184
|
+
const typedPropBehavior = propConfig.behavior;
|
|
1185
|
+
const propName = typedPropBehavior.remap || prop;
|
|
1186
|
+
if (propName === "myop_init_interface") {
|
|
1187
|
+
return (data) => {
|
|
1188
|
+
if (data === void 0) return component.getData();
|
|
1189
|
+
component.initWithData(data);
|
|
1190
|
+
};
|
|
1191
|
+
}
|
|
1192
|
+
return void 0;
|
|
1193
|
+
}
|
|
1189
1194
|
if (selectedSkin.loader.type === SkinLoaders.HTMLLoader) {
|
|
1190
1195
|
const typedLoader = selectedSkin.loader;
|
|
1191
1196
|
if (typedLoader.shadowRootMode === ShadowRootModeType.localFrame) {
|
|
@@ -1232,6 +1237,18 @@ var connectProps = (component, propsConfig, selectedSkin) => {
|
|
|
1232
1237
|
return true;
|
|
1233
1238
|
}
|
|
1234
1239
|
}
|
|
1240
|
+
if (component instanceof MyopIframeComponent && component.isolated) {
|
|
1241
|
+
const typedPropBehavior = propConfig.behavior;
|
|
1242
|
+
const propName = typedPropBehavior.remap || prop;
|
|
1243
|
+
if (propName === "myop_cta_handler") {
|
|
1244
|
+
component.setCtaHandler(value);
|
|
1245
|
+
return true;
|
|
1246
|
+
}
|
|
1247
|
+
if (propName === "myop_init_interface") {
|
|
1248
|
+
component.initWithData(value);
|
|
1249
|
+
return true;
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1235
1252
|
if (selectedSkin.loader.type === SkinLoaders.HTMLLoader) {
|
|
1236
1253
|
const typedLoader = selectedSkin.loader;
|
|
1237
1254
|
if (typedLoader.shadowRootMode === ShadowRootModeType.localFrame) {
|
|
@@ -1437,6 +1454,7 @@ var connectRefs = async (component, componentConfig, components, withoutRefCompo
|
|
|
1437
1454
|
|
|
1438
1455
|
// src/host/components/myopIframeComponent.ts
|
|
1439
1456
|
var MyopIframeComponent = class extends BaseMyopComponent {
|
|
1457
|
+
// last reported size (for the enable race)
|
|
1440
1458
|
constructor(componentConfig, skin, container, IframeElement, options) {
|
|
1441
1459
|
super(componentConfig, container, options);
|
|
1442
1460
|
this.componentConfig = componentConfig;
|
|
@@ -1445,6 +1463,17 @@ var MyopIframeComponent = class extends BaseMyopComponent {
|
|
|
1445
1463
|
__publicField(this, "_autoSizeCleanup");
|
|
1446
1464
|
__publicField(this, "_autoSizeOptions");
|
|
1447
1465
|
__publicField(this, "_autoSizeUpdate");
|
|
1466
|
+
// ── Isolation (sandboxed cross-origin frame) — postMessage bridge, host side ──
|
|
1467
|
+
__publicField(this, "isolated", false);
|
|
1468
|
+
__publicField(this, "_lastData");
|
|
1469
|
+
// cached last-sent data (sync getData)
|
|
1470
|
+
__publicField(this, "_ctaHandler");
|
|
1471
|
+
__publicField(this, "_ctaQueue", []);
|
|
1472
|
+
__publicField(this, "_isoMsgHandler");
|
|
1473
|
+
__publicField(this, "_isoSizeOpts");
|
|
1474
|
+
__publicField(this, "_isoAutoSize", false);
|
|
1475
|
+
// bridge sizing only when auto-size is on
|
|
1476
|
+
__publicField(this, "_isoLastSize");
|
|
1448
1477
|
__publicField(this, "sizeMeta");
|
|
1449
1478
|
__publicField(this, "cleanupInspect");
|
|
1450
1479
|
__publicField(this, "setHeightBasedOnDocumentElement", () => {
|
|
@@ -1484,6 +1513,15 @@ var MyopIframeComponent = class extends BaseMyopComponent {
|
|
|
1484
1513
|
*/
|
|
1485
1514
|
__publicField(this, "observeAutoSize", (options) => {
|
|
1486
1515
|
this._autoSizeOptions = options;
|
|
1516
|
+
if (this.isolated) {
|
|
1517
|
+
this._isoSizeOpts = options;
|
|
1518
|
+
this._isoAutoSize = true;
|
|
1519
|
+
if (this._isoLastSize) this._applyIsoSize(this._isoLastSize.height, this._isoLastSize.width);
|
|
1520
|
+
return () => {
|
|
1521
|
+
this._isoAutoSize = false;
|
|
1522
|
+
this._isoSizeOpts = void 0;
|
|
1523
|
+
};
|
|
1524
|
+
}
|
|
1487
1525
|
if (this._autoSizeCleanup && this._autoSizeUpdate) {
|
|
1488
1526
|
this._autoSizeUpdate();
|
|
1489
1527
|
return this._autoSizeCleanup;
|
|
@@ -1686,12 +1724,73 @@ var MyopIframeComponent = class extends BaseMyopComponent {
|
|
|
1686
1724
|
this._autoSizeCleanup();
|
|
1687
1725
|
this._autoSizeCleanup = void 0;
|
|
1688
1726
|
}
|
|
1727
|
+
if (this._isoMsgHandler) {
|
|
1728
|
+
window.removeEventListener("message", this._isoMsgHandler);
|
|
1729
|
+
this._isoMsgHandler = void 0;
|
|
1730
|
+
}
|
|
1689
1731
|
if (this.cleanupInspect)
|
|
1690
1732
|
this.cleanupInspect();
|
|
1691
1733
|
super.dispose();
|
|
1692
1734
|
this.IframeElement.parentNode.removeChild(this.IframeElement);
|
|
1693
1735
|
});
|
|
1694
1736
|
this.element = this.IframeElement;
|
|
1737
|
+
this._lastData = options == null ? void 0 : options.data;
|
|
1738
|
+
}
|
|
1739
|
+
// ── Isolation bridge (host side) ─────────────────────────────────────────
|
|
1740
|
+
/** Attach the host-side postMessage listener for a sandboxed frame. */
|
|
1741
|
+
enableIsolation() {
|
|
1742
|
+
this.isolated = true;
|
|
1743
|
+
this.setInitiated();
|
|
1744
|
+
this._isoMsgHandler = (e) => {
|
|
1745
|
+
if (e.source !== this.IframeElement.contentWindow) return;
|
|
1746
|
+
const d = e.data;
|
|
1747
|
+
if (!d || d.__myop !== true) return;
|
|
1748
|
+
if (d.type === "myop:cta") {
|
|
1749
|
+
if (this._ctaHandler && !this.markedForDisposed) this._ctaHandler(d.action, d.payload);
|
|
1750
|
+
else if (!this._ctaHandler) this._ctaQueue.push({ action: d.action, payload: d.payload });
|
|
1751
|
+
} else if (d.type === "myop:size") {
|
|
1752
|
+
this._applyIsoSize(d.height, d.width);
|
|
1753
|
+
}
|
|
1754
|
+
};
|
|
1755
|
+
window.addEventListener("message", this._isoMsgHandler);
|
|
1756
|
+
}
|
|
1757
|
+
/** Data-in — unified with the extracted-WC API. Posts init over the bridge. */
|
|
1758
|
+
initWithData(data) {
|
|
1759
|
+
var _a, _b;
|
|
1760
|
+
this._lastData = data;
|
|
1761
|
+
(_b = (_a = this.IframeElement) == null ? void 0 : _a.contentWindow) == null ? void 0 : _b.postMessage({ __myop: true, type: "myop:init", data }, "*");
|
|
1762
|
+
}
|
|
1763
|
+
/** Data-in getter — returns the last data the host sent (cached, synchronous). */
|
|
1764
|
+
getData() {
|
|
1765
|
+
return this._lastData;
|
|
1766
|
+
}
|
|
1767
|
+
/** Data-out — unified with the extracted-WC API. Flushes CTAs queued pre-handler. */
|
|
1768
|
+
setCtaHandler(handler) {
|
|
1769
|
+
this._ctaHandler = handler;
|
|
1770
|
+
if (this._ctaQueue.length > 0) {
|
|
1771
|
+
const queue = [...this._ctaQueue];
|
|
1772
|
+
this._ctaQueue = [];
|
|
1773
|
+
queue.forEach((item) => {
|
|
1774
|
+
if (!this.markedForDisposed) handler(item.action, item.payload);
|
|
1775
|
+
});
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
_applyIsoSize(height, width) {
|
|
1779
|
+
var _a;
|
|
1780
|
+
if (!height || Number.isNaN(height)) return;
|
|
1781
|
+
this._isoLastSize = { height, width };
|
|
1782
|
+
if (!this._isoAutoSize) return;
|
|
1783
|
+
const opts = this._isoSizeOpts;
|
|
1784
|
+
const toNum = (v) => v === void 0 ? void 0 : typeof v === "number" ? v : isNaN(parseFloat(v)) ? void 0 : parseFloat(v);
|
|
1785
|
+
const min = toNum(opts == null ? void 0 : opts.minHeight), max = toNum(opts == null ? void 0 : opts.maxHeight);
|
|
1786
|
+
let h = height;
|
|
1787
|
+
if (min !== void 0 && h < min) h = min;
|
|
1788
|
+
if (max !== void 0 && h > max) h = max;
|
|
1789
|
+
this.IframeElement.style.position = "relative";
|
|
1790
|
+
this.IframeElement.style.inset = "auto";
|
|
1791
|
+
this.IframeElement.style.height = h + "px";
|
|
1792
|
+
this.IframeElement.style.width = "100%";
|
|
1793
|
+
(_a = opts == null ? void 0 : opts.onSizeChange) == null ? void 0 : _a.call(opts, { width: width != null ? width : this.IframeElement.clientWidth, height: h, autoSizingWidth: false, autoSizingHeight: true });
|
|
1695
1794
|
}
|
|
1696
1795
|
inspect() {
|
|
1697
1796
|
if (this.cleanupInspect) {
|
|
@@ -1900,7 +1999,7 @@ var WebcomponentLoader = class extends BaseMyopLoader {
|
|
|
1900
1999
|
};
|
|
1901
2000
|
|
|
1902
2001
|
// version:myop-sdk-version
|
|
1903
|
-
var myop_sdk_version_default = "0.3.
|
|
2002
|
+
var myop_sdk_version_default = "0.3.34";
|
|
1904
2003
|
|
|
1905
2004
|
// src/webcomponent/messageHandlers/BaseWebComponentMessageHandler.ts
|
|
1906
2005
|
var BaseWebComponentMessageHandler = class extends BaseContextMessageHandler {
|
|
@@ -2293,7 +2392,15 @@ var HTMLComponentLoader = class extends BaseMyopLoader {
|
|
|
2293
2392
|
__publicField(this, "type", SkinLoaders.HTMLLoader);
|
|
2294
2393
|
__publicField(this, "load", async (componentDefinition, skin, container, options) => {
|
|
2295
2394
|
const loaderConfig = skin.loader;
|
|
2296
|
-
|
|
2395
|
+
const isWC = this.isMyopWebComponent(loaderConfig.HTML);
|
|
2396
|
+
const { mode, isolate } = await this.resolveRenderMode(componentDefinition, skin, loaderConfig, isWC, options);
|
|
2397
|
+
if (mode === false) {
|
|
2398
|
+
throw new Error('[Myop] Rendering blocked by render policy for component "'.concat(componentDefinition.id, '"'));
|
|
2399
|
+
}
|
|
2400
|
+
if (isWC) {
|
|
2401
|
+
if (mode !== "webComponent") {
|
|
2402
|
+
throw new Error('[Myop] Web-component rendering denied by render policy for component "'.concat(componentDefinition.id, '"'));
|
|
2403
|
+
}
|
|
2297
2404
|
return this.loadExtractedWebComponent(componentDefinition, skin, container, loaderConfig.HTML, options);
|
|
2298
2405
|
}
|
|
2299
2406
|
let domId = "myop-comp-".concat(uuidv4());
|
|
@@ -2303,12 +2410,28 @@ var HTMLComponentLoader = class extends BaseMyopLoader {
|
|
|
2303
2410
|
const domId2 = "myop-comp-".concat(uniqId);
|
|
2304
2411
|
let IframeElement = document.createElement("iframe");
|
|
2305
2412
|
IframeElement.id = domId2;
|
|
2413
|
+
if (isolate) {
|
|
2414
|
+
IframeElement.setAttribute("sandbox", "allow-scripts allow-forms allow-popups");
|
|
2415
|
+
}
|
|
2306
2416
|
IframeElement.style.cssText = "\n display: block;\n padding: 0;\n margin: 0;\n position: absolute;\n inset: 0;\n overflow: hidden;\n border: none;\n opacity: ".concat((options == null ? void 0 : options.hidden) ? "0" : "1", ";\n width: 100%;\n height: 100%;\n pointer-events: ").concat((options == null ? void 0 : options.hidden) ? "none" : "all", ";\n ");
|
|
2307
2417
|
if (!container.querySelector('[id^="myop-comp-"]'))
|
|
2308
2418
|
container.innerHTML = "";
|
|
2309
2419
|
IframeElement = this.appendChild(container, IframeElement, options);
|
|
2310
|
-
const
|
|
2311
|
-
doc
|
|
2420
|
+
const __srcParts = [];
|
|
2421
|
+
const doc = isolate ? {
|
|
2422
|
+
open() {
|
|
2423
|
+
},
|
|
2424
|
+
writeln(s) {
|
|
2425
|
+
__srcParts.push(s);
|
|
2426
|
+
},
|
|
2427
|
+
close() {
|
|
2428
|
+
IframeElement.srcdoc = __srcParts.join("\n");
|
|
2429
|
+
}
|
|
2430
|
+
} : (() => {
|
|
2431
|
+
const d = IframeElement.contentDocument || IframeElement.contentWindow.document;
|
|
2432
|
+
d.open();
|
|
2433
|
+
return d;
|
|
2434
|
+
})();
|
|
2312
2435
|
let parsedSizeMeta = null;
|
|
2313
2436
|
{
|
|
2314
2437
|
const _preParser = new DOMParser();
|
|
@@ -2348,22 +2471,29 @@ var HTMLComponentLoader = class extends BaseMyopLoader {
|
|
|
2348
2471
|
const _doc = parser.parseFromString(HTML2Render, "text/html");
|
|
2349
2472
|
const styleTag = _doc.createElement("style");
|
|
2350
2473
|
styleTag.setAttribute("data-myop-injected", "true");
|
|
2351
|
-
styleTag.textContent = options.injectCss;
|
|
2474
|
+
styleTag.textContent = options.injectCss.replace(/<\s*\/\s*style/gi, "<\\/style");
|
|
2352
2475
|
(_doc.head || _doc.documentElement).appendChild(styleTag);
|
|
2353
2476
|
HTML2Render = "<!DOCTYPE html>" + _doc.documentElement.outerHTML;
|
|
2354
2477
|
}
|
|
2355
2478
|
doc.writeln(HTML2Render);
|
|
2356
2479
|
const sdkScript = HAS_EMBEDDED_SDK ? "<script>".concat(EMBEDDED_SDK_CONTENT, "<\/script>") : '<script src="'.concat(window.myop.__ROOT_SDK_PUBLIC_URL__, '"><\/script>');
|
|
2357
2480
|
const initScript = HAS_EMBEDDED_SDK ? "<script>\n const __myop_init = async () => {\n const iframeModule = await MyopSDK.getIframeModule();\n const IframeSDK = iframeModule.IframeSDK;\n const sdk = new IframeSDK();\n sdk.init();\n }\n __myop_init().then();\n <\/script>" : "<script>\n window.__federation__.__public_path__ = window.__federation__.__public_path__;\n const __myop_init = async () => {\n const {IframeSDK} = (await window.myop.rootSDK.getIframeModule());\n const sdk = new IframeSDK();\n sdk.init();\n }\n __myop_init().then();\n <\/script>";
|
|
2358
|
-
|
|
2359
|
-
|
|
2481
|
+
if (!isolate) {
|
|
2482
|
+
doc.writeln("".concat(sdkScript).concat(initScript));
|
|
2483
|
+
}
|
|
2484
|
+
if (!isolate && (options == null ? void 0 : options.data) !== void 0) {
|
|
2360
2485
|
const ctaQueueScript = "<script>\n window.__myop_cta_queue = [];\n window.myop_cta_handler = function(action, payload) {\n window.__myop_cta_queue.push({action: action, payload: payload});\n };\n <\/script>";
|
|
2361
2486
|
const escapedData = JSON.stringify(options.data).replace(/<\/script/gi, "\\u003c/script");
|
|
2362
2487
|
const dataScript = '<script id="__myop_init_data_script">\n (function() {\n var data = '.concat(escapedData, ";\n var scriptEl = document.getElementById('__myop_init_data_script');\n\n var callInitInterface = function(fn) {\n var startTime = performance.now();\n // Mark as pre-injected data call for extension tracking\n window.__myop_init_preinjected = true;\n try {\n fn(data);\n } finally {\n window.__myop_init_preinjected = false;\n }\n var duration = performance.now() - startTime;\n\n // Notify extension via postMessage (init* = pre-injected)\n try {\n window.parent.postMessage({\n type: 'MYOP_PREINJECTED_INIT',\n payload: {\n data: data,\n duration: duration,\n timestamp: Date.now()\n }\n }, '*');\n } catch (e) {}\n\n // Cleanup: remove script tag and stored data\n if (scriptEl && scriptEl.parentNode) {\n scriptEl.parentNode.removeChild(scriptEl);\n }\n delete window.__myop_init_data;\n };\n\n if (typeof window.myop_init_interface === 'function') {\n // Function already exists - call immediately\n callInitInterface(window.myop_init_interface);\n } else {\n // Function not yet defined - store data and watch for definition\n window.__myop_init_data = data;\n\n var _original;\n Object.defineProperty(window, 'myop_init_interface', {\n configurable: true,\n enumerable: true,\n set: function(fn) {\n _original = fn;\n if (window.__myop_init_data !== undefined) {\n var storedData = window.__myop_init_data;\n delete window.__myop_init_data;\n callInitInterface(fn);\n }\n },\n get: function() {\n return _original;\n }\n });\n }\n })();\n <\/script>");
|
|
2363
2488
|
doc.writeln(ctaQueueScript + dataScript);
|
|
2364
2489
|
}
|
|
2490
|
+
if (isolate) {
|
|
2491
|
+
const escapedData = (options == null ? void 0 : options.data) !== void 0 ? JSON.stringify(options.data).replace(/<\/script/gi, "\\u003c/script") : "undefined";
|
|
2492
|
+
doc.writeln(this.buildIsolationBridge(escapedData));
|
|
2493
|
+
}
|
|
2365
2494
|
doc.close();
|
|
2366
2495
|
const comp = new MyopIframeComponent(componentDefinition, skin, container, IframeElement, options);
|
|
2496
|
+
if (isolate) comp.enableIsolation();
|
|
2367
2497
|
comp.sizeMeta = parsedSizeMeta;
|
|
2368
2498
|
comp.initiated().then(() => {
|
|
2369
2499
|
if ((options == null ? void 0 : options.autoSize) === false) {
|
|
@@ -2418,6 +2548,42 @@ var HTMLComponentLoader = class extends BaseMyopLoader {
|
|
|
2418
2548
|
isMyopWebComponent(html) {
|
|
2419
2549
|
return html.trimStart().startsWith(MYOP_WEB_COMPONENT_MARKER);
|
|
2420
2550
|
}
|
|
2551
|
+
/**
|
|
2552
|
+
* Resolve how this component should render, applying the host render policy.
|
|
2553
|
+
* Precedence: options.renderPolicy (per-call) fully replaces the global
|
|
2554
|
+
* hostSDK.setRenderPolicy — so an app can restrict globally and allow specifics.
|
|
2555
|
+
* With no policy set, behavior is unchanged from before (marker ⇒ web component).
|
|
2556
|
+
*/
|
|
2557
|
+
async resolveRenderMode(componentDefinition, skin, loaderConfig, isWebComponent, options) {
|
|
2558
|
+
var _a, _b, _c, _d;
|
|
2559
|
+
const requestedMode = isWebComponent ? "webComponent" : loaderConfig.isolation || (options == null ? void 0 : options.isolation) ? "isolatedIframe" : "iframe";
|
|
2560
|
+
const policy = (_d = options == null ? void 0 : options.renderPolicy) != null ? _d : (_c = (_b = (_a = window == null ? void 0 : window.myop) == null ? void 0 : _a.hostSDK) == null ? void 0 : _b.getRenderPolicy) == null ? void 0 : _c.call(_b);
|
|
2561
|
+
const mode = policy ? await policy({ componentDefinition, skin, requestedMode, isWebComponent }) : requestedMode;
|
|
2562
|
+
return { mode, isolate: mode === "isolatedIframe" };
|
|
2563
|
+
}
|
|
2564
|
+
/**
|
|
2565
|
+
* The in-frame bridge for isolated components. Runs inside the sandboxed
|
|
2566
|
+
* (opaque-origin) iframe, translating the same author-facing contract to/from
|
|
2567
|
+
* postMessage since the host has no same-origin access:
|
|
2568
|
+
* • data-in : parent posts {type:'myop:init'} → calls window.myop_init_interface
|
|
2569
|
+
* (plus a baked initial value for the first render)
|
|
2570
|
+
* • data-out: window.myop_cta_handler → parent.postMessage({type:'myop:cta'})
|
|
2571
|
+
* • resize : ResizeObserver → parent.postMessage({type:'myop:size'})
|
|
2572
|
+
*
|
|
2573
|
+
* TODO(dev-extension): the isolated path deliberately skips the same-origin
|
|
2574
|
+
* dataScript, so it never posts the `MYOP_PREINJECTED_INIT` message the Myop dev
|
|
2575
|
+
* extension listens for to log the INITIAL render (`init*`). Later init updates and
|
|
2576
|
+
* all CTAs are still tracked (the extension wraps `comp.props`, which our isolated
|
|
2577
|
+
* connectProps branch routes through), so only the first-render payload is missing
|
|
2578
|
+
* from the extension's activity log for isolated components. Closing this would be a
|
|
2579
|
+
* ~1-line `parent.postMessage({type:'MYOP_PREINJECTED_INIT', payload:{data}})` inside
|
|
2580
|
+
* flushInitial() below — intentionally NOT done for now to avoid adding extension-only
|
|
2581
|
+
* traffic to the component runtime. Web components have the same initial-init gap
|
|
2582
|
+
* (initWithData is called on the element, not via comp.props) and it predates this.
|
|
2583
|
+
*/
|
|
2584
|
+
buildIsolationBridge(initialDataLiteral) {
|
|
2585
|
+
return "<script>\n (function () {\n var __initial = ".concat(initialDataLiteral, ";\n var __pending;\n // data-out (cta)\n window.myop_cta_handler = function (action, payload) {\n try { parent.postMessage({ __myop: true, type: 'myop:cta', action: action, payload: payload }, '*'); } catch (e) {}\n };\n function callInit(data) {\n if (typeof window.myop_init_interface === 'function') { window.myop_init_interface(data); return true; }\n return false;\n }\n // data-in (init updates)\n window.addEventListener('message', function (e) {\n var d = e.data;\n if (!d || d.__myop !== true) return;\n if (d.type === 'myop:init') { if (!callInit(d.data)) __pending = d.data; }\n });\n // first render: use a pending update if one arrived, else the baked initial data\n (function flushInitial() {\n var data = (__pending !== undefined) ? __pending : __initial;\n if (data === undefined) return;\n if (callInit(data)) { __pending = undefined; __initial = undefined; }\n else requestAnimationFrame(flushInitial);\n })();\n // resize (report content size)\n function contentHeight() {\n // Measure the BODY (content box). documentElement.scrollHeight includes\n // the iframe viewport \u2014 which we're driving \u2014 so it would report the\n // current frame height, not the content, and never shrink.\n var b = document.body;\n if (b) return Math.max(b.scrollHeight, b.offsetHeight);\n return document.documentElement.scrollHeight;\n }\n function postSize() {\n try {\n parent.postMessage({\n __myop: true, type: 'myop:size',\n height: contentHeight(),\n width: document.documentElement.scrollWidth\n }, '*');\n } catch (e) {}\n }\n // Observe the BODY (reflows with content) \u2014 not documentElement, whose box is\n // the iframe viewport and would feed back into a resize loop. A MutationObserver\n // catches content swaps (e.g. innerHTML re-render) that don't change body's box.\n if (window.ResizeObserver) {\n try { var __ro = new ResizeObserver(postSize); if (document.body) __ro.observe(document.body); } catch (e) {}\n }\n if (window.MutationObserver && document.body) {\n try { new MutationObserver(postSize).observe(document.body, { childList: true, subtree: true, attributes: true, characterData: true }); } catch (e) {}\n }\n window.addEventListener('load', postSize);\n postSize();\n })();\n <\/script>");
|
|
2586
|
+
}
|
|
2421
2587
|
/**
|
|
2422
2588
|
* Extract the web component script content from HTML
|
|
2423
2589
|
*/
|
|
@@ -2635,24 +2801,33 @@ var _CloudRepository = class _CloudRepository {
|
|
|
2635
2801
|
getPreloadedParams(componentId) {
|
|
2636
2802
|
return this.preloadedComponents[componentId];
|
|
2637
2803
|
}
|
|
2804
|
+
/**
|
|
2805
|
+
* Resolve a component config: fetch it once, then serve it from this
|
|
2806
|
+
* repository's cache.
|
|
2807
|
+
*
|
|
2808
|
+
* This is the name to use. `fetchComponentV2` is the same method under its
|
|
2809
|
+
* versioned name and stays for backward compatibility — note that the
|
|
2810
|
+
* unversioned `fetchComponent` is a *deprecated v1* API and is NOT this.
|
|
2811
|
+
*
|
|
2812
|
+
* Completes the trio with {@link getResolvedConfig} (synchronous read of an
|
|
2813
|
+
* already-resolved config) and {@link hydrateComponent} (seed one you
|
|
2814
|
+
* already hold).
|
|
2815
|
+
*
|
|
2816
|
+
* Prefer the module-level `preloadComponents([id])` in app code; reach for
|
|
2817
|
+
* this when you need an isolated repository instance whose cache lifetime
|
|
2818
|
+
* you control — a server with its own TTL, for example.
|
|
2819
|
+
*/
|
|
2820
|
+
async resolveComponent(componentId, env, preview) {
|
|
2821
|
+
return this.fetchComponentV2(componentId, env, preview);
|
|
2822
|
+
}
|
|
2638
2823
|
/**
|
|
2639
2824
|
* Fetch a v2 component config
|
|
2640
2825
|
* If env/preview not specified and component was preloaded, uses preloaded params
|
|
2826
|
+
*
|
|
2827
|
+
* @see resolveComponent — the unversioned name for this method
|
|
2641
2828
|
*/
|
|
2642
2829
|
async fetchComponentV2(componentId, environmentIdentifier, preview) {
|
|
2643
|
-
const
|
|
2644
|
-
const hasExplicitParams = environmentIdentifier !== void 0 || preview !== void 0;
|
|
2645
|
-
let env;
|
|
2646
|
-
let usePreview;
|
|
2647
|
-
if (!hasExplicitParams && preloaded) {
|
|
2648
|
-
env = preloaded.env;
|
|
2649
|
-
usePreview = preloaded.preview;
|
|
2650
|
-
} else {
|
|
2651
|
-
env = environmentIdentifier || this._defaultEnv;
|
|
2652
|
-
const hasEffectiveEnv = environmentIdentifier || this._envExplicitlySet;
|
|
2653
|
-
usePreview = preview === true ? true : preview === false ? false : !hasEffectiveEnv;
|
|
2654
|
-
}
|
|
2655
|
-
const cacheKey = "".concat(componentId, ":").concat(env, ":").concat(usePreview ? "preview" : "live");
|
|
2830
|
+
const { env, usePreview, cacheKey } = this.resolveParams(componentId, environmentIdentifier, preview);
|
|
2656
2831
|
console.log("[CloudRepository] fetchComponentV2", {
|
|
2657
2832
|
componentId: componentId.slice(0, 8) + "...",
|
|
2658
2833
|
env,
|
|
@@ -2721,20 +2896,52 @@ var _CloudRepository = class _CloudRepository {
|
|
|
2721
2896
|
*/
|
|
2722
2897
|
getResolvedConfig(componentId, env, preview) {
|
|
2723
2898
|
var _a;
|
|
2899
|
+
const { cacheKey } = this.resolveParams(componentId, env, preview);
|
|
2900
|
+
return ((_a = this.variants[cacheKey]) == null ? void 0 : _a.resolved) || null;
|
|
2901
|
+
}
|
|
2902
|
+
/**
|
|
2903
|
+
* Resolve which (env, preview) pair — and therefore which cache key — a call
|
|
2904
|
+
* for `componentId` refers to.
|
|
2905
|
+
*
|
|
2906
|
+
* Single source of truth for fetchComponentV2, getResolvedConfig and
|
|
2907
|
+
* hydrateComponent, so a hydrated config always lands on the key a later
|
|
2908
|
+
* fetch will look under.
|
|
2909
|
+
*/
|
|
2910
|
+
resolveParams(componentId, environmentIdentifier, preview) {
|
|
2724
2911
|
const preloaded = this.preloadedComponents[componentId];
|
|
2725
|
-
const hasExplicitParams =
|
|
2726
|
-
let
|
|
2912
|
+
const hasExplicitParams = environmentIdentifier !== void 0 || preview !== void 0;
|
|
2913
|
+
let env;
|
|
2727
2914
|
let usePreview;
|
|
2728
2915
|
if (!hasExplicitParams && preloaded) {
|
|
2729
|
-
|
|
2916
|
+
env = preloaded.env;
|
|
2730
2917
|
usePreview = preloaded.preview;
|
|
2731
2918
|
} else {
|
|
2732
|
-
|
|
2733
|
-
const hasEffectiveEnv =
|
|
2919
|
+
env = environmentIdentifier || this._defaultEnv;
|
|
2920
|
+
const hasEffectiveEnv = environmentIdentifier || this._envExplicitlySet;
|
|
2734
2921
|
usePreview = preview === true ? true : preview === false ? false : !hasEffectiveEnv;
|
|
2735
2922
|
}
|
|
2736
|
-
|
|
2737
|
-
|
|
2923
|
+
return { env, usePreview, cacheKey: "".concat(componentId, ":").concat(env, ":").concat(usePreview ? "preview" : "live") };
|
|
2924
|
+
}
|
|
2925
|
+
/**
|
|
2926
|
+
* Seed an already-resolved component config into the cache, without any
|
|
2927
|
+
* network request.
|
|
2928
|
+
*
|
|
2929
|
+
* The counterpart to {@link fetchComponentV2}: use it when the config was
|
|
2930
|
+
* resolved somewhere else — most often on a server, then embedded in the
|
|
2931
|
+
* page — so the browser can render the component with no round trip.
|
|
2932
|
+
*
|
|
2933
|
+
* After hydrating, `fetchComponentV2`, `getResolvedConfig` and `isPreloaded`
|
|
2934
|
+
* all answer for this component from memory.
|
|
2935
|
+
*
|
|
2936
|
+
* Pass the same `env` / `preview` the config was resolved with; the defaults
|
|
2937
|
+
* match what a plain `fetchComponentV2(componentId)` would have used.
|
|
2938
|
+
*/
|
|
2939
|
+
hydrateComponent(componentId, config, env, preview) {
|
|
2940
|
+
const { env: resolvedEnv, usePreview, cacheKey } = this.resolveParams(componentId, env, preview);
|
|
2941
|
+
const promise = Promise.resolve(config);
|
|
2942
|
+
promise.resolved = config;
|
|
2943
|
+
this.variants[cacheKey] = promise;
|
|
2944
|
+
this.preloadedComponents[componentId] = { env: resolvedEnv, preview: usePreview };
|
|
2738
2945
|
}
|
|
2739
2946
|
// ============ V1 Methods (Legacy) ============
|
|
2740
2947
|
/**
|
|
@@ -2867,6 +3074,13 @@ var HostSDK = class {
|
|
|
2867
3074
|
__publicField(this, "components2init", []);
|
|
2868
3075
|
__publicField(this, "components", []);
|
|
2869
3076
|
__publicField(this, "componentsLoaders", []);
|
|
3077
|
+
// Global render policy (allow/deny/mode gate). A per-call options.renderPolicy
|
|
3078
|
+
// takes precedence over this — see HTMLComponentLoader.resolveRenderMode.
|
|
3079
|
+
__publicField(this, "_renderPolicy");
|
|
3080
|
+
__publicField(this, "setRenderPolicy", (policy) => {
|
|
3081
|
+
this._renderPolicy = policy;
|
|
3082
|
+
});
|
|
3083
|
+
__publicField(this, "getRenderPolicy", () => this._renderPolicy);
|
|
2870
3084
|
__publicField(this, "initiated", false);
|
|
2871
3085
|
__publicField(this, "version", myop_sdk_version_default);
|
|
2872
3086
|
__publicField(this, "type2InstanceCount", {});
|