@myop/sdk 0.3.32 → 0.3.33
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 +135 -48
- package/dist/cjs/_IframeSDK.c7a53057.min.js +1 -0
- package/dist/cjs/{_IframeSDK.8ce25264.js → _IframeSDK.e5b2bc49.js} +201 -28
- package/dist/cjs/_IframeSDK.e5b2bc49.js.map +7 -0
- package/dist/cjs/_MyopHelpers.95610381.js.map +2 -2
- package/dist/cjs/{_MyopHelpers.172384f4.min.js → _MyopHelpers.ca1b3a3c.min.js} +1 -1
- package/dist/cjs/_WebComponentSDK.3a72ed95.min.js +1 -0
- package/dist/cjs/{_WebComponentSDK.1aa213d9.js → _WebComponentSDK.a7e660ab.js} +201 -28
- package/dist/cjs/_WebComponentSDK.a7e660ab.js.map +7 -0
- package/dist/cjs/_hostSDK.0529d5ed.min.js +1 -0
- package/dist/cjs/{_hostSDK.c7ca0fae.js → _hostSDK.1905850e.js} +201 -28
- package/dist/cjs/_hostSDK.1905850e.js.map +7 -0
- package/dist/cjs/myop_sdk.js +11 -11
- 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 +203 -29
- 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 +259 -29
- package/dist/module/Iframe/index.js.map +2 -2
- package/dist/module/SDK.js +260 -29
- 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/index.js +1 -1
- 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 +259 -29
- 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 +259 -29
- 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/_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
|
@@ -1168,6 +1168,19 @@ var MyopExtractedWebComponent = class extends BaseMyopComponent {
|
|
|
1168
1168
|
__publicField(this, "ctaCleanup");
|
|
1169
1169
|
__publicField(this, "_ctaHandler");
|
|
1170
1170
|
__publicField(this, "_ctaQueue", []);
|
|
1171
|
+
// A single 'myop-cta' listener, attached at construction so CTAs a component
|
|
1172
|
+
// dispatches during its first initWithData() render — before the host attaches
|
|
1173
|
+
// a handler — are buffered (and flushed on setCtaHandler), matching the iframe
|
|
1174
|
+
// path's pre-handler CTA queue.
|
|
1175
|
+
__publicField(this, "_ctaListener", (e) => {
|
|
1176
|
+
const detail = e.detail;
|
|
1177
|
+
if (!(detail == null ? void 0 : detail.action)) return;
|
|
1178
|
+
if (this._ctaHandler && !this.markedForDisposed) {
|
|
1179
|
+
this._ctaHandler(detail.action, detail.payload);
|
|
1180
|
+
} else if (!this._ctaHandler) {
|
|
1181
|
+
this._ctaQueue.push({ action: detail.action, payload: detail.payload });
|
|
1182
|
+
}
|
|
1183
|
+
});
|
|
1171
1184
|
__publicField(this, "cleanupInspect", () => {
|
|
1172
1185
|
});
|
|
1173
1186
|
/**
|
|
@@ -1188,6 +1201,8 @@ var MyopExtractedWebComponent = class extends BaseMyopComponent {
|
|
|
1188
1201
|
(_a = this.customElement.parentNode) == null ? void 0 : _a.removeChild(this.customElement);
|
|
1189
1202
|
});
|
|
1190
1203
|
this.element = customElement;
|
|
1204
|
+
this.customElement.addEventListener("myop-cta", this._ctaListener);
|
|
1205
|
+
this.ctaCleanup = () => this.customElement.removeEventListener("myop-cta", this._ctaListener);
|
|
1191
1206
|
this.setInitiated();
|
|
1192
1207
|
}
|
|
1193
1208
|
inspect() {
|
|
@@ -1232,9 +1247,6 @@ var MyopExtractedWebComponent = class extends BaseMyopComponent {
|
|
|
1232
1247
|
* Called via props.myop_cta_handler = handler
|
|
1233
1248
|
*/
|
|
1234
1249
|
setCtaHandler(handler) {
|
|
1235
|
-
if (this.ctaCleanup) {
|
|
1236
|
-
this.ctaCleanup();
|
|
1237
|
-
}
|
|
1238
1250
|
this._ctaHandler = handler;
|
|
1239
1251
|
if (this._ctaQueue.length > 0) {
|
|
1240
1252
|
const queue = [...this._ctaQueue];
|
|
@@ -1245,24 +1257,6 @@ var MyopExtractedWebComponent = class extends BaseMyopComponent {
|
|
|
1245
1257
|
}
|
|
1246
1258
|
});
|
|
1247
1259
|
}
|
|
1248
|
-
const listener = (e) => {
|
|
1249
|
-
var _a;
|
|
1250
|
-
const customEvent = e;
|
|
1251
|
-
if ((_a = customEvent.detail) == null ? void 0 : _a.action) {
|
|
1252
|
-
if (this._ctaHandler && !this.markedForDisposed) {
|
|
1253
|
-
this._ctaHandler(customEvent.detail.action, customEvent.detail.payload);
|
|
1254
|
-
} else if (!this._ctaHandler) {
|
|
1255
|
-
this._ctaQueue.push({
|
|
1256
|
-
action: customEvent.detail.action,
|
|
1257
|
-
payload: customEvent.detail.payload
|
|
1258
|
-
});
|
|
1259
|
-
}
|
|
1260
|
-
}
|
|
1261
|
-
};
|
|
1262
|
-
this.customElement.addEventListener("myop-cta", listener);
|
|
1263
|
-
this.ctaCleanup = () => {
|
|
1264
|
-
this.customElement.removeEventListener("myop-cta", listener);
|
|
1265
|
-
};
|
|
1266
1260
|
}
|
|
1267
1261
|
};
|
|
1268
1262
|
|
|
@@ -1331,6 +1325,17 @@ var connectProps = (component, propsConfig, selectedSkin) => {
|
|
|
1331
1325
|
}
|
|
1332
1326
|
return void 0;
|
|
1333
1327
|
}
|
|
1328
|
+
if (component instanceof MyopIframeComponent && component.isolated) {
|
|
1329
|
+
const typedPropBehavior = propConfig.behavior;
|
|
1330
|
+
const propName = typedPropBehavior.remap || prop;
|
|
1331
|
+
if (propName === "myop_init_interface") {
|
|
1332
|
+
return (data) => {
|
|
1333
|
+
if (data === void 0) return component.getData();
|
|
1334
|
+
component.initWithData(data);
|
|
1335
|
+
};
|
|
1336
|
+
}
|
|
1337
|
+
return void 0;
|
|
1338
|
+
}
|
|
1334
1339
|
if (selectedSkin.loader.type === SkinLoaders.HTMLLoader) {
|
|
1335
1340
|
const typedLoader = selectedSkin.loader;
|
|
1336
1341
|
if (typedLoader.shadowRootMode === ShadowRootModeType.localFrame) {
|
|
@@ -1377,6 +1382,18 @@ var connectProps = (component, propsConfig, selectedSkin) => {
|
|
|
1377
1382
|
return true;
|
|
1378
1383
|
}
|
|
1379
1384
|
}
|
|
1385
|
+
if (component instanceof MyopIframeComponent && component.isolated) {
|
|
1386
|
+
const typedPropBehavior = propConfig.behavior;
|
|
1387
|
+
const propName = typedPropBehavior.remap || prop;
|
|
1388
|
+
if (propName === "myop_cta_handler") {
|
|
1389
|
+
component.setCtaHandler(value);
|
|
1390
|
+
return true;
|
|
1391
|
+
}
|
|
1392
|
+
if (propName === "myop_init_interface") {
|
|
1393
|
+
component.initWithData(value);
|
|
1394
|
+
return true;
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1380
1397
|
if (selectedSkin.loader.type === SkinLoaders.HTMLLoader) {
|
|
1381
1398
|
const typedLoader = selectedSkin.loader;
|
|
1382
1399
|
if (typedLoader.shadowRootMode === ShadowRootModeType.localFrame) {
|
|
@@ -1582,6 +1599,7 @@ var connectRefs = async (component, componentConfig, components, withoutRefCompo
|
|
|
1582
1599
|
|
|
1583
1600
|
// src/host/components/myopIframeComponent.ts
|
|
1584
1601
|
var MyopIframeComponent = class extends BaseMyopComponent {
|
|
1602
|
+
// last reported size (for the enable race)
|
|
1585
1603
|
constructor(componentConfig, skin, container, IframeElement, options) {
|
|
1586
1604
|
super(componentConfig, container, options);
|
|
1587
1605
|
this.componentConfig = componentConfig;
|
|
@@ -1590,6 +1608,17 @@ var MyopIframeComponent = class extends BaseMyopComponent {
|
|
|
1590
1608
|
__publicField(this, "_autoSizeCleanup");
|
|
1591
1609
|
__publicField(this, "_autoSizeOptions");
|
|
1592
1610
|
__publicField(this, "_autoSizeUpdate");
|
|
1611
|
+
// ── Isolation (sandboxed cross-origin frame) — postMessage bridge, host side ──
|
|
1612
|
+
__publicField(this, "isolated", false);
|
|
1613
|
+
__publicField(this, "_lastData");
|
|
1614
|
+
// cached last-sent data (sync getData)
|
|
1615
|
+
__publicField(this, "_ctaHandler");
|
|
1616
|
+
__publicField(this, "_ctaQueue", []);
|
|
1617
|
+
__publicField(this, "_isoMsgHandler");
|
|
1618
|
+
__publicField(this, "_isoSizeOpts");
|
|
1619
|
+
__publicField(this, "_isoAutoSize", false);
|
|
1620
|
+
// bridge sizing only when auto-size is on
|
|
1621
|
+
__publicField(this, "_isoLastSize");
|
|
1593
1622
|
__publicField(this, "sizeMeta");
|
|
1594
1623
|
__publicField(this, "cleanupInspect");
|
|
1595
1624
|
__publicField(this, "setHeightBasedOnDocumentElement", () => {
|
|
@@ -1629,6 +1658,15 @@ var MyopIframeComponent = class extends BaseMyopComponent {
|
|
|
1629
1658
|
*/
|
|
1630
1659
|
__publicField(this, "observeAutoSize", (options) => {
|
|
1631
1660
|
this._autoSizeOptions = options;
|
|
1661
|
+
if (this.isolated) {
|
|
1662
|
+
this._isoSizeOpts = options;
|
|
1663
|
+
this._isoAutoSize = true;
|
|
1664
|
+
if (this._isoLastSize) this._applyIsoSize(this._isoLastSize.height, this._isoLastSize.width);
|
|
1665
|
+
return () => {
|
|
1666
|
+
this._isoAutoSize = false;
|
|
1667
|
+
this._isoSizeOpts = void 0;
|
|
1668
|
+
};
|
|
1669
|
+
}
|
|
1632
1670
|
if (this._autoSizeCleanup && this._autoSizeUpdate) {
|
|
1633
1671
|
this._autoSizeUpdate();
|
|
1634
1672
|
return this._autoSizeCleanup;
|
|
@@ -1831,12 +1869,73 @@ var MyopIframeComponent = class extends BaseMyopComponent {
|
|
|
1831
1869
|
this._autoSizeCleanup();
|
|
1832
1870
|
this._autoSizeCleanup = void 0;
|
|
1833
1871
|
}
|
|
1872
|
+
if (this._isoMsgHandler) {
|
|
1873
|
+
window.removeEventListener("message", this._isoMsgHandler);
|
|
1874
|
+
this._isoMsgHandler = void 0;
|
|
1875
|
+
}
|
|
1834
1876
|
if (this.cleanupInspect)
|
|
1835
1877
|
this.cleanupInspect();
|
|
1836
1878
|
super.dispose();
|
|
1837
1879
|
this.IframeElement.parentNode.removeChild(this.IframeElement);
|
|
1838
1880
|
});
|
|
1839
1881
|
this.element = this.IframeElement;
|
|
1882
|
+
this._lastData = options == null ? void 0 : options.data;
|
|
1883
|
+
}
|
|
1884
|
+
// ── Isolation bridge (host side) ─────────────────────────────────────────
|
|
1885
|
+
/** Attach the host-side postMessage listener for a sandboxed frame. */
|
|
1886
|
+
enableIsolation() {
|
|
1887
|
+
this.isolated = true;
|
|
1888
|
+
this.setInitiated();
|
|
1889
|
+
this._isoMsgHandler = (e) => {
|
|
1890
|
+
if (e.source !== this.IframeElement.contentWindow) return;
|
|
1891
|
+
const d = e.data;
|
|
1892
|
+
if (!d || d.__myop !== true) return;
|
|
1893
|
+
if (d.type === "myop:cta") {
|
|
1894
|
+
if (this._ctaHandler && !this.markedForDisposed) this._ctaHandler(d.action, d.payload);
|
|
1895
|
+
else if (!this._ctaHandler) this._ctaQueue.push({ action: d.action, payload: d.payload });
|
|
1896
|
+
} else if (d.type === "myop:size") {
|
|
1897
|
+
this._applyIsoSize(d.height, d.width);
|
|
1898
|
+
}
|
|
1899
|
+
};
|
|
1900
|
+
window.addEventListener("message", this._isoMsgHandler);
|
|
1901
|
+
}
|
|
1902
|
+
/** Data-in — unified with the extracted-WC API. Posts init over the bridge. */
|
|
1903
|
+
initWithData(data) {
|
|
1904
|
+
var _a, _b;
|
|
1905
|
+
this._lastData = data;
|
|
1906
|
+
(_b = (_a = this.IframeElement) == null ? void 0 : _a.contentWindow) == null ? void 0 : _b.postMessage({ __myop: true, type: "myop:init", data }, "*");
|
|
1907
|
+
}
|
|
1908
|
+
/** Data-in getter — returns the last data the host sent (cached, synchronous). */
|
|
1909
|
+
getData() {
|
|
1910
|
+
return this._lastData;
|
|
1911
|
+
}
|
|
1912
|
+
/** Data-out — unified with the extracted-WC API. Flushes CTAs queued pre-handler. */
|
|
1913
|
+
setCtaHandler(handler) {
|
|
1914
|
+
this._ctaHandler = handler;
|
|
1915
|
+
if (this._ctaQueue.length > 0) {
|
|
1916
|
+
const queue = [...this._ctaQueue];
|
|
1917
|
+
this._ctaQueue = [];
|
|
1918
|
+
queue.forEach((item) => {
|
|
1919
|
+
if (!this.markedForDisposed) handler(item.action, item.payload);
|
|
1920
|
+
});
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
_applyIsoSize(height, width) {
|
|
1924
|
+
var _a;
|
|
1925
|
+
if (!height || Number.isNaN(height)) return;
|
|
1926
|
+
this._isoLastSize = { height, width };
|
|
1927
|
+
if (!this._isoAutoSize) return;
|
|
1928
|
+
const opts = this._isoSizeOpts;
|
|
1929
|
+
const toNum = (v) => v === void 0 ? void 0 : typeof v === "number" ? v : isNaN(parseFloat(v)) ? void 0 : parseFloat(v);
|
|
1930
|
+
const min = toNum(opts == null ? void 0 : opts.minHeight), max = toNum(opts == null ? void 0 : opts.maxHeight);
|
|
1931
|
+
let h = height;
|
|
1932
|
+
if (min !== void 0 && h < min) h = min;
|
|
1933
|
+
if (max !== void 0 && h > max) h = max;
|
|
1934
|
+
this.IframeElement.style.position = "relative";
|
|
1935
|
+
this.IframeElement.style.inset = "auto";
|
|
1936
|
+
this.IframeElement.style.height = h + "px";
|
|
1937
|
+
this.IframeElement.style.width = "100%";
|
|
1938
|
+
(_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 });
|
|
1840
1939
|
}
|
|
1841
1940
|
inspect() {
|
|
1842
1941
|
if (this.cleanupInspect) {
|
|
@@ -2040,7 +2139,7 @@ var WebcomponentLoader = class extends BaseMyopLoader {
|
|
|
2040
2139
|
};
|
|
2041
2140
|
|
|
2042
2141
|
// version:myop-sdk-version
|
|
2043
|
-
var myop_sdk_version_default = "0.3.
|
|
2142
|
+
var myop_sdk_version_default = "0.3.33";
|
|
2044
2143
|
|
|
2045
2144
|
// src/host/embeddedSDK.ts
|
|
2046
2145
|
var EMBEDDED_SDK_CONTENT = "";
|
|
@@ -2088,7 +2187,15 @@ var HTMLComponentLoader = class extends BaseMyopLoader {
|
|
|
2088
2187
|
__publicField(this, "type", SkinLoaders.HTMLLoader);
|
|
2089
2188
|
__publicField(this, "load", async (componentDefinition, skin, container, options) => {
|
|
2090
2189
|
const loaderConfig = skin.loader;
|
|
2091
|
-
|
|
2190
|
+
const isWC = this.isMyopWebComponent(loaderConfig.HTML);
|
|
2191
|
+
const { mode, isolate } = await this.resolveRenderMode(componentDefinition, skin, loaderConfig, isWC, options);
|
|
2192
|
+
if (mode === false) {
|
|
2193
|
+
throw new Error('[Myop] Rendering blocked by render policy for component "'.concat(componentDefinition.id, '"'));
|
|
2194
|
+
}
|
|
2195
|
+
if (isWC) {
|
|
2196
|
+
if (mode !== "webComponent") {
|
|
2197
|
+
throw new Error('[Myop] Web-component rendering denied by render policy for component "'.concat(componentDefinition.id, '"'));
|
|
2198
|
+
}
|
|
2092
2199
|
return this.loadExtractedWebComponent(componentDefinition, skin, container, loaderConfig.HTML, options);
|
|
2093
2200
|
}
|
|
2094
2201
|
let domId = "myop-comp-".concat(uuidv4());
|
|
@@ -2098,12 +2205,28 @@ var HTMLComponentLoader = class extends BaseMyopLoader {
|
|
|
2098
2205
|
const domId2 = "myop-comp-".concat(uniqId);
|
|
2099
2206
|
let IframeElement = document.createElement("iframe");
|
|
2100
2207
|
IframeElement.id = domId2;
|
|
2208
|
+
if (isolate) {
|
|
2209
|
+
IframeElement.setAttribute("sandbox", "allow-scripts allow-forms allow-popups");
|
|
2210
|
+
}
|
|
2101
2211
|
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 ");
|
|
2102
2212
|
if (!container.querySelector('[id^="myop-comp-"]'))
|
|
2103
2213
|
container.innerHTML = "";
|
|
2104
2214
|
IframeElement = this.appendChild(container, IframeElement, options);
|
|
2105
|
-
const
|
|
2106
|
-
doc
|
|
2215
|
+
const __srcParts = [];
|
|
2216
|
+
const doc = isolate ? {
|
|
2217
|
+
open() {
|
|
2218
|
+
},
|
|
2219
|
+
writeln(s) {
|
|
2220
|
+
__srcParts.push(s);
|
|
2221
|
+
},
|
|
2222
|
+
close() {
|
|
2223
|
+
IframeElement.srcdoc = __srcParts.join("\n");
|
|
2224
|
+
}
|
|
2225
|
+
} : (() => {
|
|
2226
|
+
const d = IframeElement.contentDocument || IframeElement.contentWindow.document;
|
|
2227
|
+
d.open();
|
|
2228
|
+
return d;
|
|
2229
|
+
})();
|
|
2107
2230
|
let parsedSizeMeta = null;
|
|
2108
2231
|
{
|
|
2109
2232
|
const _preParser = new DOMParser();
|
|
@@ -2143,22 +2266,29 @@ var HTMLComponentLoader = class extends BaseMyopLoader {
|
|
|
2143
2266
|
const _doc = parser.parseFromString(HTML2Render, "text/html");
|
|
2144
2267
|
const styleTag = _doc.createElement("style");
|
|
2145
2268
|
styleTag.setAttribute("data-myop-injected", "true");
|
|
2146
|
-
styleTag.textContent = options.injectCss;
|
|
2269
|
+
styleTag.textContent = options.injectCss.replace(/<\s*\/\s*style/gi, "<\\/style");
|
|
2147
2270
|
(_doc.head || _doc.documentElement).appendChild(styleTag);
|
|
2148
2271
|
HTML2Render = "<!DOCTYPE html>" + _doc.documentElement.outerHTML;
|
|
2149
2272
|
}
|
|
2150
2273
|
doc.writeln(HTML2Render);
|
|
2151
2274
|
const sdkScript = HAS_EMBEDDED_SDK ? "<script>".concat(EMBEDDED_SDK_CONTENT, "<\/script>") : '<script src="'.concat(window.myop.__ROOT_SDK_PUBLIC_URL__, '"><\/script>');
|
|
2152
2275
|
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>";
|
|
2153
|
-
|
|
2154
|
-
|
|
2276
|
+
if (!isolate) {
|
|
2277
|
+
doc.writeln("".concat(sdkScript).concat(initScript));
|
|
2278
|
+
}
|
|
2279
|
+
if (!isolate && (options == null ? void 0 : options.data) !== void 0) {
|
|
2155
2280
|
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>";
|
|
2156
2281
|
const escapedData = JSON.stringify(options.data).replace(/<\/script/gi, "\\u003c/script");
|
|
2157
2282
|
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>");
|
|
2158
2283
|
doc.writeln(ctaQueueScript + dataScript);
|
|
2159
2284
|
}
|
|
2285
|
+
if (isolate) {
|
|
2286
|
+
const escapedData = (options == null ? void 0 : options.data) !== void 0 ? JSON.stringify(options.data).replace(/<\/script/gi, "\\u003c/script") : "undefined";
|
|
2287
|
+
doc.writeln(this.buildIsolationBridge(escapedData));
|
|
2288
|
+
}
|
|
2160
2289
|
doc.close();
|
|
2161
2290
|
const comp = new MyopIframeComponent(componentDefinition, skin, container, IframeElement, options);
|
|
2291
|
+
if (isolate) comp.enableIsolation();
|
|
2162
2292
|
comp.sizeMeta = parsedSizeMeta;
|
|
2163
2293
|
comp.initiated().then(() => {
|
|
2164
2294
|
if ((options == null ? void 0 : options.autoSize) === false) {
|
|
@@ -2213,6 +2343,42 @@ var HTMLComponentLoader = class extends BaseMyopLoader {
|
|
|
2213
2343
|
isMyopWebComponent(html) {
|
|
2214
2344
|
return html.trimStart().startsWith(MYOP_WEB_COMPONENT_MARKER);
|
|
2215
2345
|
}
|
|
2346
|
+
/**
|
|
2347
|
+
* Resolve how this component should render, applying the host render policy.
|
|
2348
|
+
* Precedence: options.renderPolicy (per-call) fully replaces the global
|
|
2349
|
+
* hostSDK.setRenderPolicy — so an app can restrict globally and allow specifics.
|
|
2350
|
+
* With no policy set, behavior is unchanged from before (marker ⇒ web component).
|
|
2351
|
+
*/
|
|
2352
|
+
async resolveRenderMode(componentDefinition, skin, loaderConfig, isWebComponent, options) {
|
|
2353
|
+
var _a, _b, _c, _d;
|
|
2354
|
+
const requestedMode = isWebComponent ? "webComponent" : loaderConfig.isolation || (options == null ? void 0 : options.isolation) ? "isolatedIframe" : "iframe";
|
|
2355
|
+
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);
|
|
2356
|
+
const mode = policy ? await policy({ componentDefinition, skin, requestedMode, isWebComponent }) : requestedMode;
|
|
2357
|
+
return { mode, isolate: mode === "isolatedIframe" };
|
|
2358
|
+
}
|
|
2359
|
+
/**
|
|
2360
|
+
* The in-frame bridge for isolated components. Runs inside the sandboxed
|
|
2361
|
+
* (opaque-origin) iframe, translating the same author-facing contract to/from
|
|
2362
|
+
* postMessage since the host has no same-origin access:
|
|
2363
|
+
* • data-in : parent posts {type:'myop:init'} → calls window.myop_init_interface
|
|
2364
|
+
* (plus a baked initial value for the first render)
|
|
2365
|
+
* • data-out: window.myop_cta_handler → parent.postMessage({type:'myop:cta'})
|
|
2366
|
+
* • resize : ResizeObserver → parent.postMessage({type:'myop:size'})
|
|
2367
|
+
*
|
|
2368
|
+
* TODO(dev-extension): the isolated path deliberately skips the same-origin
|
|
2369
|
+
* dataScript, so it never posts the `MYOP_PREINJECTED_INIT` message the Myop dev
|
|
2370
|
+
* extension listens for to log the INITIAL render (`init*`). Later init updates and
|
|
2371
|
+
* all CTAs are still tracked (the extension wraps `comp.props`, which our isolated
|
|
2372
|
+
* connectProps branch routes through), so only the first-render payload is missing
|
|
2373
|
+
* from the extension's activity log for isolated components. Closing this would be a
|
|
2374
|
+
* ~1-line `parent.postMessage({type:'MYOP_PREINJECTED_INIT', payload:{data}})` inside
|
|
2375
|
+
* flushInitial() below — intentionally NOT done for now to avoid adding extension-only
|
|
2376
|
+
* traffic to the component runtime. Web components have the same initial-init gap
|
|
2377
|
+
* (initWithData is called on the element, not via comp.props) and it predates this.
|
|
2378
|
+
*/
|
|
2379
|
+
buildIsolationBridge(initialDataLiteral) {
|
|
2380
|
+
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>");
|
|
2381
|
+
}
|
|
2216
2382
|
/**
|
|
2217
2383
|
* Extract the web component script content from HTML
|
|
2218
2384
|
*/
|
|
@@ -2662,6 +2828,13 @@ var HostSDK = class {
|
|
|
2662
2828
|
__publicField(this, "components2init", []);
|
|
2663
2829
|
__publicField(this, "components", []);
|
|
2664
2830
|
__publicField(this, "componentsLoaders", []);
|
|
2831
|
+
// Global render policy (allow/deny/mode gate). A per-call options.renderPolicy
|
|
2832
|
+
// takes precedence over this — see HTMLComponentLoader.resolveRenderMode.
|
|
2833
|
+
__publicField(this, "_renderPolicy");
|
|
2834
|
+
__publicField(this, "setRenderPolicy", (policy) => {
|
|
2835
|
+
this._renderPolicy = policy;
|
|
2836
|
+
});
|
|
2837
|
+
__publicField(this, "getRenderPolicy", () => this._renderPolicy);
|
|
2665
2838
|
__publicField(this, "initiated", false);
|
|
2666
2839
|
__publicField(this, "version", myop_sdk_version_default);
|
|
2667
2840
|
__publicField(this, "type2InstanceCount", {});
|