@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.
Files changed (45) hide show
  1. package/dist/bundled-declarations.d.ts +135 -48
  2. package/dist/cjs/_IframeSDK.c7a53057.min.js +1 -0
  3. package/dist/cjs/{_IframeSDK.8ce25264.js → _IframeSDK.e5b2bc49.js} +201 -28
  4. package/dist/cjs/_IframeSDK.e5b2bc49.js.map +7 -0
  5. package/dist/cjs/_MyopHelpers.95610381.js.map +2 -2
  6. package/dist/cjs/{_MyopHelpers.172384f4.min.js → _MyopHelpers.ca1b3a3c.min.js} +1 -1
  7. package/dist/cjs/_WebComponentSDK.3a72ed95.min.js +1 -0
  8. package/dist/cjs/{_WebComponentSDK.1aa213d9.js → _WebComponentSDK.a7e660ab.js} +201 -28
  9. package/dist/cjs/_WebComponentSDK.a7e660ab.js.map +7 -0
  10. package/dist/cjs/_hostSDK.0529d5ed.min.js +1 -0
  11. package/dist/cjs/{_hostSDK.c7ca0fae.js → _hostSDK.1905850e.js} +201 -28
  12. package/dist/cjs/_hostSDK.1905850e.js.map +7 -0
  13. package/dist/cjs/myop_sdk.js +11 -11
  14. package/dist/cjs/myop_sdk.js.map +1 -1
  15. package/dist/cjs/myop_sdk.min.js +1 -1
  16. package/dist/cjs-bundled/myop_sdk.bundled.js +203 -29
  17. package/dist/cjs-bundled/myop_sdk.bundled.js.map +3 -3
  18. package/dist/cjs-bundled/myop_sdk.bundled.min.js +1 -1
  19. package/dist/module/Iframe/index.js +259 -29
  20. package/dist/module/Iframe/index.js.map +2 -2
  21. package/dist/module/SDK.js +260 -29
  22. package/dist/module/SDK.js.map +3 -3
  23. package/dist/module/common/index.d.ts +26 -0
  24. package/dist/module/common/index.js +1 -1
  25. package/dist/module/common/index.js.map +2 -2
  26. package/dist/module/embeddedSDK.js +1 -1
  27. package/dist/module/helpers/index.js +1 -1
  28. package/dist/module/helpers/index.js.map +2 -2
  29. package/dist/module/host/components/myopExtractedWebComponent.d.ts +1 -0
  30. package/dist/module/host/components/myopIframeComponent.d.ts +17 -0
  31. package/dist/module/host/embeddedSDK.js +1 -1
  32. package/dist/module/host/hostSDK.d.ts +15 -0
  33. package/dist/module/host/index.d.ts +1 -1
  34. package/dist/module/host/index.js +259 -29
  35. package/dist/module/host/index.js.map +2 -2
  36. package/dist/module/host/loaders/HTMLComponentLoader.d.ts +29 -1
  37. package/dist/module/webcomponent/index.js +259 -29
  38. package/dist/module/webcomponent/index.js.map +2 -2
  39. package/package.json +1 -1
  40. package/dist/cjs/_IframeSDK.07df88d3.min.js +0 -1
  41. package/dist/cjs/_IframeSDK.8ce25264.js.map +0 -7
  42. package/dist/cjs/_WebComponentSDK.1aa213d9.js.map +0 -7
  43. package/dist/cjs/_WebComponentSDK.92468fac.min.js +0 -1
  44. package/dist/cjs/_hostSDK.c7ca0fae.js.map +0 -7
  45. package/dist/cjs/_hostSDK.dc198afa.min.js +0 -1
@@ -1166,6 +1166,19 @@ var MyopExtractedWebComponent = class extends BaseMyopComponent {
1166
1166
  __publicField(this, "ctaCleanup");
1167
1167
  __publicField(this, "_ctaHandler");
1168
1168
  __publicField(this, "_ctaQueue", []);
1169
+ // A single 'myop-cta' listener, attached at construction so CTAs a component
1170
+ // dispatches during its first initWithData() render — before the host attaches
1171
+ // a handler — are buffered (and flushed on setCtaHandler), matching the iframe
1172
+ // path's pre-handler CTA queue.
1173
+ __publicField(this, "_ctaListener", (e) => {
1174
+ const detail = e.detail;
1175
+ if (!(detail == null ? void 0 : detail.action)) return;
1176
+ if (this._ctaHandler && !this.markedForDisposed) {
1177
+ this._ctaHandler(detail.action, detail.payload);
1178
+ } else if (!this._ctaHandler) {
1179
+ this._ctaQueue.push({ action: detail.action, payload: detail.payload });
1180
+ }
1181
+ });
1169
1182
  __publicField(this, "cleanupInspect", () => {
1170
1183
  });
1171
1184
  /**
@@ -1186,6 +1199,8 @@ var MyopExtractedWebComponent = class extends BaseMyopComponent {
1186
1199
  (_a = this.customElement.parentNode) == null ? void 0 : _a.removeChild(this.customElement);
1187
1200
  });
1188
1201
  this.element = customElement;
1202
+ this.customElement.addEventListener("myop-cta", this._ctaListener);
1203
+ this.ctaCleanup = () => this.customElement.removeEventListener("myop-cta", this._ctaListener);
1189
1204
  this.setInitiated();
1190
1205
  }
1191
1206
  inspect() {
@@ -1230,9 +1245,6 @@ var MyopExtractedWebComponent = class extends BaseMyopComponent {
1230
1245
  * Called via props.myop_cta_handler = handler
1231
1246
  */
1232
1247
  setCtaHandler(handler) {
1233
- if (this.ctaCleanup) {
1234
- this.ctaCleanup();
1235
- }
1236
1248
  this._ctaHandler = handler;
1237
1249
  if (this._ctaQueue.length > 0) {
1238
1250
  const queue = [...this._ctaQueue];
@@ -1243,24 +1255,6 @@ var MyopExtractedWebComponent = class extends BaseMyopComponent {
1243
1255
  }
1244
1256
  });
1245
1257
  }
1246
- const listener = (e) => {
1247
- var _a;
1248
- const customEvent = e;
1249
- if ((_a = customEvent.detail) == null ? void 0 : _a.action) {
1250
- if (this._ctaHandler && !this.markedForDisposed) {
1251
- this._ctaHandler(customEvent.detail.action, customEvent.detail.payload);
1252
- } else if (!this._ctaHandler) {
1253
- this._ctaQueue.push({
1254
- action: customEvent.detail.action,
1255
- payload: customEvent.detail.payload
1256
- });
1257
- }
1258
- }
1259
- };
1260
- this.customElement.addEventListener("myop-cta", listener);
1261
- this.ctaCleanup = () => {
1262
- this.customElement.removeEventListener("myop-cta", listener);
1263
- };
1264
1258
  }
1265
1259
  };
1266
1260
 
@@ -1329,6 +1323,17 @@ var connectProps = (component, propsConfig, selectedSkin) => {
1329
1323
  }
1330
1324
  return void 0;
1331
1325
  }
1326
+ if (component instanceof MyopIframeComponent && component.isolated) {
1327
+ const typedPropBehavior = propConfig.behavior;
1328
+ const propName = typedPropBehavior.remap || prop;
1329
+ if (propName === "myop_init_interface") {
1330
+ return (data) => {
1331
+ if (data === void 0) return component.getData();
1332
+ component.initWithData(data);
1333
+ };
1334
+ }
1335
+ return void 0;
1336
+ }
1332
1337
  if (selectedSkin.loader.type === SkinLoaders.HTMLLoader) {
1333
1338
  const typedLoader = selectedSkin.loader;
1334
1339
  if (typedLoader.shadowRootMode === ShadowRootModeType.localFrame) {
@@ -1375,6 +1380,18 @@ var connectProps = (component, propsConfig, selectedSkin) => {
1375
1380
  return true;
1376
1381
  }
1377
1382
  }
1383
+ if (component instanceof MyopIframeComponent && component.isolated) {
1384
+ const typedPropBehavior = propConfig.behavior;
1385
+ const propName = typedPropBehavior.remap || prop;
1386
+ if (propName === "myop_cta_handler") {
1387
+ component.setCtaHandler(value);
1388
+ return true;
1389
+ }
1390
+ if (propName === "myop_init_interface") {
1391
+ component.initWithData(value);
1392
+ return true;
1393
+ }
1394
+ }
1378
1395
  if (selectedSkin.loader.type === SkinLoaders.HTMLLoader) {
1379
1396
  const typedLoader = selectedSkin.loader;
1380
1397
  if (typedLoader.shadowRootMode === ShadowRootModeType.localFrame) {
@@ -1580,6 +1597,7 @@ var connectRefs = async (component, componentConfig, components, withoutRefCompo
1580
1597
 
1581
1598
  // src/host/components/myopIframeComponent.ts
1582
1599
  var MyopIframeComponent = class extends BaseMyopComponent {
1600
+ // last reported size (for the enable race)
1583
1601
  constructor(componentConfig, skin, container, IframeElement, options) {
1584
1602
  super(componentConfig, container, options);
1585
1603
  this.componentConfig = componentConfig;
@@ -1588,6 +1606,17 @@ var MyopIframeComponent = class extends BaseMyopComponent {
1588
1606
  __publicField(this, "_autoSizeCleanup");
1589
1607
  __publicField(this, "_autoSizeOptions");
1590
1608
  __publicField(this, "_autoSizeUpdate");
1609
+ // ── Isolation (sandboxed cross-origin frame) — postMessage bridge, host side ──
1610
+ __publicField(this, "isolated", false);
1611
+ __publicField(this, "_lastData");
1612
+ // cached last-sent data (sync getData)
1613
+ __publicField(this, "_ctaHandler");
1614
+ __publicField(this, "_ctaQueue", []);
1615
+ __publicField(this, "_isoMsgHandler");
1616
+ __publicField(this, "_isoSizeOpts");
1617
+ __publicField(this, "_isoAutoSize", false);
1618
+ // bridge sizing only when auto-size is on
1619
+ __publicField(this, "_isoLastSize");
1591
1620
  __publicField(this, "sizeMeta");
1592
1621
  __publicField(this, "cleanupInspect");
1593
1622
  __publicField(this, "setHeightBasedOnDocumentElement", () => {
@@ -1627,6 +1656,15 @@ var MyopIframeComponent = class extends BaseMyopComponent {
1627
1656
  */
1628
1657
  __publicField(this, "observeAutoSize", (options) => {
1629
1658
  this._autoSizeOptions = options;
1659
+ if (this.isolated) {
1660
+ this._isoSizeOpts = options;
1661
+ this._isoAutoSize = true;
1662
+ if (this._isoLastSize) this._applyIsoSize(this._isoLastSize.height, this._isoLastSize.width);
1663
+ return () => {
1664
+ this._isoAutoSize = false;
1665
+ this._isoSizeOpts = void 0;
1666
+ };
1667
+ }
1630
1668
  if (this._autoSizeCleanup && this._autoSizeUpdate) {
1631
1669
  this._autoSizeUpdate();
1632
1670
  return this._autoSizeCleanup;
@@ -1829,12 +1867,73 @@ var MyopIframeComponent = class extends BaseMyopComponent {
1829
1867
  this._autoSizeCleanup();
1830
1868
  this._autoSizeCleanup = void 0;
1831
1869
  }
1870
+ if (this._isoMsgHandler) {
1871
+ window.removeEventListener("message", this._isoMsgHandler);
1872
+ this._isoMsgHandler = void 0;
1873
+ }
1832
1874
  if (this.cleanupInspect)
1833
1875
  this.cleanupInspect();
1834
1876
  super.dispose();
1835
1877
  this.IframeElement.parentNode.removeChild(this.IframeElement);
1836
1878
  });
1837
1879
  this.element = this.IframeElement;
1880
+ this._lastData = options == null ? void 0 : options.data;
1881
+ }
1882
+ // ── Isolation bridge (host side) ─────────────────────────────────────────
1883
+ /** Attach the host-side postMessage listener for a sandboxed frame. */
1884
+ enableIsolation() {
1885
+ this.isolated = true;
1886
+ this.setInitiated();
1887
+ this._isoMsgHandler = (e) => {
1888
+ if (e.source !== this.IframeElement.contentWindow) return;
1889
+ const d = e.data;
1890
+ if (!d || d.__myop !== true) return;
1891
+ if (d.type === "myop:cta") {
1892
+ if (this._ctaHandler && !this.markedForDisposed) this._ctaHandler(d.action, d.payload);
1893
+ else if (!this._ctaHandler) this._ctaQueue.push({ action: d.action, payload: d.payload });
1894
+ } else if (d.type === "myop:size") {
1895
+ this._applyIsoSize(d.height, d.width);
1896
+ }
1897
+ };
1898
+ window.addEventListener("message", this._isoMsgHandler);
1899
+ }
1900
+ /** Data-in — unified with the extracted-WC API. Posts init over the bridge. */
1901
+ initWithData(data) {
1902
+ var _a, _b;
1903
+ this._lastData = data;
1904
+ (_b = (_a = this.IframeElement) == null ? void 0 : _a.contentWindow) == null ? void 0 : _b.postMessage({ __myop: true, type: "myop:init", data }, "*");
1905
+ }
1906
+ /** Data-in getter — returns the last data the host sent (cached, synchronous). */
1907
+ getData() {
1908
+ return this._lastData;
1909
+ }
1910
+ /** Data-out — unified with the extracted-WC API. Flushes CTAs queued pre-handler. */
1911
+ setCtaHandler(handler) {
1912
+ this._ctaHandler = handler;
1913
+ if (this._ctaQueue.length > 0) {
1914
+ const queue = [...this._ctaQueue];
1915
+ this._ctaQueue = [];
1916
+ queue.forEach((item) => {
1917
+ if (!this.markedForDisposed) handler(item.action, item.payload);
1918
+ });
1919
+ }
1920
+ }
1921
+ _applyIsoSize(height, width) {
1922
+ var _a;
1923
+ if (!height || Number.isNaN(height)) return;
1924
+ this._isoLastSize = { height, width };
1925
+ if (!this._isoAutoSize) return;
1926
+ const opts = this._isoSizeOpts;
1927
+ const toNum = (v) => v === void 0 ? void 0 : typeof v === "number" ? v : isNaN(parseFloat(v)) ? void 0 : parseFloat(v);
1928
+ const min = toNum(opts == null ? void 0 : opts.minHeight), max = toNum(opts == null ? void 0 : opts.maxHeight);
1929
+ let h = height;
1930
+ if (min !== void 0 && h < min) h = min;
1931
+ if (max !== void 0 && h > max) h = max;
1932
+ this.IframeElement.style.position = "relative";
1933
+ this.IframeElement.style.inset = "auto";
1934
+ this.IframeElement.style.height = h + "px";
1935
+ this.IframeElement.style.width = "100%";
1936
+ (_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 });
1838
1937
  }
1839
1938
  inspect() {
1840
1939
  if (this.cleanupInspect) {
@@ -2043,7 +2142,7 @@ var WebcomponentLoader = class extends BaseMyopLoader {
2043
2142
  };
2044
2143
 
2045
2144
  // version:myop-sdk-version
2046
- var myop_sdk_version_default = "0.3.32";
2145
+ var myop_sdk_version_default = "0.3.33";
2047
2146
 
2048
2147
  // src/webcomponent/messageHandlers/BaseWebComponentMessageHandler.ts
2049
2148
  var BaseWebComponentMessageHandler = class extends BaseContextMessageHandler {
@@ -2414,7 +2513,15 @@ var HTMLComponentLoader = class extends BaseMyopLoader {
2414
2513
  __publicField(this, "type", SkinLoaders.HTMLLoader);
2415
2514
  __publicField(this, "load", async (componentDefinition, skin, container, options) => {
2416
2515
  const loaderConfig = skin.loader;
2417
- if (this.isMyopWebComponent(loaderConfig.HTML)) {
2516
+ const isWC = this.isMyopWebComponent(loaderConfig.HTML);
2517
+ const { mode, isolate } = await this.resolveRenderMode(componentDefinition, skin, loaderConfig, isWC, options);
2518
+ if (mode === false) {
2519
+ throw new Error('[Myop] Rendering blocked by render policy for component "'.concat(componentDefinition.id, '"'));
2520
+ }
2521
+ if (isWC) {
2522
+ if (mode !== "webComponent") {
2523
+ throw new Error('[Myop] Web-component rendering denied by render policy for component "'.concat(componentDefinition.id, '"'));
2524
+ }
2418
2525
  return this.loadExtractedWebComponent(componentDefinition, skin, container, loaderConfig.HTML, options);
2419
2526
  }
2420
2527
  let domId = "myop-comp-".concat(uuidv4());
@@ -2424,12 +2531,28 @@ var HTMLComponentLoader = class extends BaseMyopLoader {
2424
2531
  const domId2 = "myop-comp-".concat(uniqId);
2425
2532
  let IframeElement = document.createElement("iframe");
2426
2533
  IframeElement.id = domId2;
2534
+ if (isolate) {
2535
+ IframeElement.setAttribute("sandbox", "allow-scripts allow-forms allow-popups");
2536
+ }
2427
2537
  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 ");
2428
2538
  if (!container.querySelector('[id^="myop-comp-"]'))
2429
2539
  container.innerHTML = "";
2430
2540
  IframeElement = this.appendChild(container, IframeElement, options);
2431
- const doc = IframeElement.contentDocument || IframeElement.contentWindow.document;
2432
- doc.open();
2541
+ const __srcParts = [];
2542
+ const doc = isolate ? {
2543
+ open() {
2544
+ },
2545
+ writeln(s) {
2546
+ __srcParts.push(s);
2547
+ },
2548
+ close() {
2549
+ IframeElement.srcdoc = __srcParts.join("\n");
2550
+ }
2551
+ } : (() => {
2552
+ const d = IframeElement.contentDocument || IframeElement.contentWindow.document;
2553
+ d.open();
2554
+ return d;
2555
+ })();
2433
2556
  let parsedSizeMeta = null;
2434
2557
  {
2435
2558
  const _preParser = new DOMParser();
@@ -2469,22 +2592,29 @@ var HTMLComponentLoader = class extends BaseMyopLoader {
2469
2592
  const _doc = parser.parseFromString(HTML2Render, "text/html");
2470
2593
  const styleTag = _doc.createElement("style");
2471
2594
  styleTag.setAttribute("data-myop-injected", "true");
2472
- styleTag.textContent = options.injectCss;
2595
+ styleTag.textContent = options.injectCss.replace(/<\s*\/\s*style/gi, "<\\/style");
2473
2596
  (_doc.head || _doc.documentElement).appendChild(styleTag);
2474
2597
  HTML2Render = "<!DOCTYPE html>" + _doc.documentElement.outerHTML;
2475
2598
  }
2476
2599
  doc.writeln(HTML2Render);
2477
2600
  const sdkScript = HAS_EMBEDDED_SDK ? "<script>".concat(EMBEDDED_SDK_CONTENT, "<\/script>") : '<script src="'.concat(window.myop.__ROOT_SDK_PUBLIC_URL__, '"><\/script>');
2478
2601
  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>";
2479
- doc.writeln("".concat(sdkScript).concat(initScript));
2480
- if ((options == null ? void 0 : options.data) !== void 0) {
2602
+ if (!isolate) {
2603
+ doc.writeln("".concat(sdkScript).concat(initScript));
2604
+ }
2605
+ if (!isolate && (options == null ? void 0 : options.data) !== void 0) {
2481
2606
  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>";
2482
2607
  const escapedData = JSON.stringify(options.data).replace(/<\/script/gi, "\\u003c/script");
2483
2608
  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>");
2484
2609
  doc.writeln(ctaQueueScript + dataScript);
2485
2610
  }
2611
+ if (isolate) {
2612
+ const escapedData = (options == null ? void 0 : options.data) !== void 0 ? JSON.stringify(options.data).replace(/<\/script/gi, "\\u003c/script") : "undefined";
2613
+ doc.writeln(this.buildIsolationBridge(escapedData));
2614
+ }
2486
2615
  doc.close();
2487
2616
  const comp = new MyopIframeComponent(componentDefinition, skin, container, IframeElement, options);
2617
+ if (isolate) comp.enableIsolation();
2488
2618
  comp.sizeMeta = parsedSizeMeta;
2489
2619
  comp.initiated().then(() => {
2490
2620
  if ((options == null ? void 0 : options.autoSize) === false) {
@@ -2539,6 +2669,42 @@ var HTMLComponentLoader = class extends BaseMyopLoader {
2539
2669
  isMyopWebComponent(html) {
2540
2670
  return html.trimStart().startsWith(MYOP_WEB_COMPONENT_MARKER);
2541
2671
  }
2672
+ /**
2673
+ * Resolve how this component should render, applying the host render policy.
2674
+ * Precedence: options.renderPolicy (per-call) fully replaces the global
2675
+ * hostSDK.setRenderPolicy — so an app can restrict globally and allow specifics.
2676
+ * With no policy set, behavior is unchanged from before (marker ⇒ web component).
2677
+ */
2678
+ async resolveRenderMode(componentDefinition, skin, loaderConfig, isWebComponent, options) {
2679
+ var _a, _b, _c, _d;
2680
+ const requestedMode = isWebComponent ? "webComponent" : loaderConfig.isolation || (options == null ? void 0 : options.isolation) ? "isolatedIframe" : "iframe";
2681
+ 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);
2682
+ const mode = policy ? await policy({ componentDefinition, skin, requestedMode, isWebComponent }) : requestedMode;
2683
+ return { mode, isolate: mode === "isolatedIframe" };
2684
+ }
2685
+ /**
2686
+ * The in-frame bridge for isolated components. Runs inside the sandboxed
2687
+ * (opaque-origin) iframe, translating the same author-facing contract to/from
2688
+ * postMessage since the host has no same-origin access:
2689
+ * • data-in : parent posts {type:'myop:init'} → calls window.myop_init_interface
2690
+ * (plus a baked initial value for the first render)
2691
+ * • data-out: window.myop_cta_handler → parent.postMessage({type:'myop:cta'})
2692
+ * • resize : ResizeObserver → parent.postMessage({type:'myop:size'})
2693
+ *
2694
+ * TODO(dev-extension): the isolated path deliberately skips the same-origin
2695
+ * dataScript, so it never posts the `MYOP_PREINJECTED_INIT` message the Myop dev
2696
+ * extension listens for to log the INITIAL render (`init*`). Later init updates and
2697
+ * all CTAs are still tracked (the extension wraps `comp.props`, which our isolated
2698
+ * connectProps branch routes through), so only the first-render payload is missing
2699
+ * from the extension's activity log for isolated components. Closing this would be a
2700
+ * ~1-line `parent.postMessage({type:'MYOP_PREINJECTED_INIT', payload:{data}})` inside
2701
+ * flushInitial() below — intentionally NOT done for now to avoid adding extension-only
2702
+ * traffic to the component runtime. Web components have the same initial-init gap
2703
+ * (initWithData is called on the element, not via comp.props) and it predates this.
2704
+ */
2705
+ buildIsolationBridge(initialDataLiteral) {
2706
+ 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>");
2707
+ }
2542
2708
  /**
2543
2709
  * Extract the web component script content from HTML
2544
2710
  */
@@ -2988,6 +3154,13 @@ var HostSDK = class {
2988
3154
  __publicField(this, "components2init", []);
2989
3155
  __publicField(this, "components", []);
2990
3156
  __publicField(this, "componentsLoaders", []);
3157
+ // Global render policy (allow/deny/mode gate). A per-call options.renderPolicy
3158
+ // takes precedence over this — see HTMLComponentLoader.resolveRenderMode.
3159
+ __publicField(this, "_renderPolicy");
3160
+ __publicField(this, "setRenderPolicy", (policy) => {
3161
+ this._renderPolicy = policy;
3162
+ });
3163
+ __publicField(this, "getRenderPolicy", () => this._renderPolicy);
2991
3164
  __publicField(this, "initiated", false);
2992
3165
  __publicField(this, "version", myop_sdk_version_default);
2993
3166
  __publicField(this, "type2InstanceCount", {});