@myop/sdk 0.4.0-beta.2 → 0.4.0-beta.4

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 (37) hide show
  1. package/dist/bundled-declarations.d.ts +72 -32
  2. package/dist/cjs/{_IframeSDK.a43cfa7d.js → _IframeSDK.3a412cd4.js} +165 -63
  3. package/dist/cjs/_IframeSDK.3a412cd4.js.map +7 -0
  4. package/dist/cjs/_IframeSDK.9338575d.min.js +1 -0
  5. package/dist/cjs/{_WebComponentSDK.0f6ef369.js → _WebComponentSDK.4b6ac803.js} +121 -18
  6. package/dist/cjs/_WebComponentSDK.4b6ac803.js.map +7 -0
  7. package/dist/cjs/_WebComponentSDK.4e78d94a.min.js +1 -0
  8. package/dist/cjs/_hostSDK.34f770f6.min.js +1 -0
  9. package/dist/cjs/{_hostSDK.38fcc5b4.js → _hostSDK.e9b70e44.js} +121 -18
  10. package/dist/cjs/_hostSDK.e9b70e44.js.map +7 -0
  11. package/dist/cjs/myop_sdk.js +11 -11
  12. package/dist/cjs/myop_sdk.js.map +1 -1
  13. package/dist/cjs/myop_sdk.min.js +1 -1
  14. package/dist/cjs-bundled/myop_sdk.bundled.js +167 -64
  15. package/dist/cjs-bundled/myop_sdk.bundled.js.map +3 -3
  16. package/dist/cjs-bundled/myop_sdk.bundled.min.js +1 -1
  17. package/dist/module/Iframe/IframeSDK.d.ts +26 -30
  18. package/dist/module/Iframe/index.js +166 -64
  19. package/dist/module/Iframe/index.js.map +3 -3
  20. package/dist/module/SDK.js +167 -64
  21. package/dist/module/SDK.js.map +3 -3
  22. package/dist/module/embeddedSDK.js +1 -1
  23. package/dist/module/host/components/IMyopComponent.d.ts +3 -0
  24. package/dist/module/host/components/myopExtractedWebComponent.d.ts +24 -1
  25. package/dist/module/host/embeddedSDK.js +1 -1
  26. package/dist/module/host/index.js +122 -19
  27. package/dist/module/host/index.js.map +2 -2
  28. package/dist/module/host/loaders/HTMLComponentLoader.d.ts +19 -1
  29. package/dist/module/webcomponent/index.js +122 -19
  30. package/dist/module/webcomponent/index.js.map +2 -2
  31. package/package.json +1 -1
  32. package/dist/cjs/_IframeSDK.8f08de4b.min.js +0 -1
  33. package/dist/cjs/_IframeSDK.a43cfa7d.js.map +0 -7
  34. package/dist/cjs/_WebComponentSDK.0f6ef369.js.map +0 -7
  35. package/dist/cjs/_WebComponentSDK.649e5e47.min.js +0 -1
  36. package/dist/cjs/_hostSDK.131fedc9.min.js +0 -1
  37. package/dist/cjs/_hostSDK.38fcc5b4.js.map +0 -7
@@ -607,6 +607,7 @@ var BaseMyopComponent = class {
607
607
  setTimeout(() => {
608
608
  if (!this.isInitiated && this._whenInitiatedReject && !this._markedForDisposed) {
609
609
  this._whenInitiatedReject("timeout_".concat(timeout, " ").concat(this.id));
610
+ this.dispose();
610
611
  }
611
612
  }, timeout);
612
613
  this.initiated().then(() => {
@@ -690,19 +691,27 @@ var BaseMyopComponent = class {
690
691
  };
691
692
  }
692
693
  }
694
+ /** Runs the 'onDispose' handlers once. hostSDK registers the one that unregisters
695
+ * this component, so it has to run on EVERY dispose path, initiated or not. */
696
+ runDisposeHandlers() {
697
+ const onDisposeHandlers = this.messageHandlers["onDispose"];
698
+ if (onDisposeHandlers) {
699
+ onDisposeHandlers.forEach((disposeHandler) => {
700
+ disposeHandler(null);
701
+ });
702
+ }
703
+ }
693
704
  dispose() {
694
705
  this.markedForDisposed = true;
695
706
  if (!this.isInitiated) {
707
+ this.runDisposeHandlers();
708
+ this.messageHandlers = {};
709
+ this.id += "_disposed";
696
710
  return;
697
711
  }
698
712
  console.log("disposing component", this.id);
699
713
  this.send(new DisposeMessage());
700
- const onDisposeHandlers = this.messageHandlers["onDispose"];
701
- if (onDisposeHandlers) {
702
- onDisposeHandlers.forEach((disposeHandler) => {
703
- disposeHandler(null);
704
- });
705
- }
714
+ this.runDisposeHandlers();
706
715
  this.messageHandlers = {};
707
716
  this.id += "_disposed";
708
717
  this.isInitiated = false;
@@ -1036,6 +1045,67 @@ var MyopExtractedWebComponent = class extends BaseMyopComponent {
1036
1045
  this._ctaQueue.push({ action: detail.action, payload: detail.payload });
1037
1046
  }
1038
1047
  });
1048
+ __publicField(this, "_autoSizeOptions");
1049
+ /**
1050
+ * Data-out for size — the extracted counterpart of the iframe implementation.
1051
+ *
1052
+ * THIS EXISTED ONLY ON MyopIframeComponent, and that was invisible for as long as
1053
+ * minification was sending every v2 component down the iframe path. Restoring v2
1054
+ * detection moves them to this class, and `@myop/react` drives both through one
1055
+ * wrapper: in content mode it hides its loader from the FIRST onSizeChange, so a
1056
+ * component whose class has no observeAutoSize leaves a React host on a loader
1057
+ * forever. Pic-Time's sizeMeta is width:100% with no height, which is exactly content
1058
+ * mode. Caught by v2-data-contract D8 (API parity).
1059
+ *
1060
+ * It REPORTS rather than imposes. An iframe has no intrinsic size and must be
1061
+ * measured inside and then set from outside; a custom element sizes itself from its
1062
+ * own content, so the honest thing is to measure it and tell the host, and let the
1063
+ * host decide. React then uses width:100% and the measured height.
1064
+ *
1065
+ * The one thing it does impose is `display: block` when the element computes to
1066
+ * `inline`, which is the default for a custom element and measures as zero height no
1067
+ * matter what it contains. The iframe path forces width:100% for the same reason —
1068
+ * without it the first measurement is 0 and the host sizes the component to nothing.
1069
+ */
1070
+ __publicField(this, "observeAutoSize", (options) => {
1071
+ this._autoSizeOptions = options;
1072
+ const el = this.customElement;
1073
+ try {
1074
+ if (getComputedStyle(el).display === "inline") el.style.display = "block";
1075
+ } catch (e) {
1076
+ }
1077
+ const parse = (v) => {
1078
+ if (v === void 0) return void 0;
1079
+ if (typeof v === "number") return v;
1080
+ const n = parseFloat(v);
1081
+ return isNaN(n) ? void 0 : n;
1082
+ };
1083
+ const clamp = (v, min, max) => min !== void 0 && v < min ? min : max !== void 0 && v > max ? max : v;
1084
+ const report = () => {
1085
+ var _a;
1086
+ const opts = this._autoSizeOptions;
1087
+ const rect = el.getBoundingClientRect();
1088
+ const autoHeight = (opts == null ? void 0 : opts.explicitHeight) === void 0;
1089
+ (_a = opts == null ? void 0 : opts.onSizeChange) == null ? void 0 : _a.call(opts, {
1090
+ width: rect.width,
1091
+ height: autoHeight ? clamp(rect.height, parse(opts == null ? void 0 : opts.minHeight), parse(opts == null ? void 0 : opts.maxHeight)) : rect.height,
1092
+ autoSizingWidth: false,
1093
+ // a web component fills its container's width
1094
+ autoSizingHeight: autoHeight
1095
+ });
1096
+ };
1097
+ let ro;
1098
+ try {
1099
+ ro = new ResizeObserver(() => report());
1100
+ ro.observe(el);
1101
+ } catch (e) {
1102
+ }
1103
+ report();
1104
+ return () => {
1105
+ ro == null ? void 0 : ro.disconnect();
1106
+ this._autoSizeOptions = void 0;
1107
+ };
1108
+ });
1039
1109
  __publicField(this, "cleanupInspect", () => {
1040
1110
  });
1041
1111
  /**
@@ -1363,8 +1433,13 @@ var createRefComponent = async (ref, componentConfig, components, options) => {
1363
1433
  return new Promise(async (resolve, reject) => {
1364
1434
  const refComponent = new MyopRefComponent(componentConfig.type, component, options);
1365
1435
  components.push(refComponent);
1436
+ const unregister = () => {
1437
+ const at = components.indexOf(refComponent);
1438
+ if (at !== -1) components.splice(at, 1);
1439
+ };
1366
1440
  await component.initiated();
1367
1441
  const timeout = setTimeout(() => {
1442
+ unregister();
1368
1443
  reject("timeout");
1369
1444
  }, 5e3);
1370
1445
  component.send(new CreateRefComponentMessage(
@@ -1377,11 +1452,13 @@ var createRefComponent = async (ref, componentConfig, components, options) => {
1377
1452
  async (message) => {
1378
1453
  clearTimeout(timeout);
1379
1454
  if (message.failed) {
1455
+ unregister();
1380
1456
  reject("CreateRefComponentMessage failed");
1381
1457
  return;
1382
1458
  }
1383
1459
  const implementationComponent = components.find((c) => c.id == refComponent.id);
1384
- if (implementationComponent !== refComponent) {
1460
+ if (implementationComponent && implementationComponent !== refComponent) {
1461
+ unregister();
1385
1462
  component.refs[ref.refConfig.name] = implementationComponent;
1386
1463
  resolve(implementationComponent);
1387
1464
  return;
@@ -1745,7 +1822,7 @@ var MyopIframeComponent = class extends BaseMyopComponent {
1745
1822
  return cleanupHandler;
1746
1823
  });
1747
1824
  __publicField(this, "dispose", () => {
1748
- var _a;
1825
+ var _a, _b;
1749
1826
  (_a = this._bridgeSizeCleanup) == null ? void 0 : _a.call(this);
1750
1827
  if (this._autoSizeCleanup) {
1751
1828
  this._autoSizeCleanup();
@@ -1758,7 +1835,7 @@ var MyopIframeComponent = class extends BaseMyopComponent {
1758
1835
  if (this.cleanupInspect)
1759
1836
  this.cleanupInspect();
1760
1837
  super.dispose();
1761
- this.IframeElement.parentNode.removeChild(this.IframeElement);
1838
+ (_b = this.IframeElement.parentNode) == null ? void 0 : _b.removeChild(this.IframeElement);
1762
1839
  });
1763
1840
  this.element = this.IframeElement;
1764
1841
  this._lastData = options == null ? void 0 : options.data;
@@ -2030,7 +2107,7 @@ var WebcomponentLoader = class extends BaseMyopLoader {
2030
2107
  };
2031
2108
 
2032
2109
  // version:myop-sdk-version
2033
- var myop_sdk_version_default = "0.4.0-beta.2";
2110
+ var myop_sdk_version_default = "0.4.0-beta.4";
2034
2111
 
2035
2112
  // src/helpers/deliveryStore.ts
2036
2113
  var DB_NAME = "myop-delivery";
@@ -3214,14 +3291,14 @@ var HTMLComponentLoader = class extends BaseMyopLoader {
3214
3291
  if (!isolate) {
3215
3292
  doc.writeln("".concat(sdkScript).concat(initScript));
3216
3293
  }
3217
- if (!isolate && (options == null ? void 0 : options.data) !== void 0) {
3294
+ if (!isolate && (options == null ? void 0 : options.data) !== void 0 && (options == null ? void 0 : options.data) !== null) {
3218
3295
  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>";
3219
3296
  const escapedData = JSON.stringify(options.data).replace(/<\/script/gi, "\\u003c/script");
3220
3297
  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>");
3221
3298
  doc.writeln(ctaQueueScript + dataScript);
3222
3299
  }
3223
3300
  if (isolate) {
3224
- const escapedData = (options == null ? void 0 : options.data) !== void 0 ? JSON.stringify(options.data).replace(/<\/script/gi, "\\u003c/script") : "undefined";
3301
+ const escapedData = (options == null ? void 0 : options.data) !== void 0 && (options == null ? void 0 : options.data) !== null ? JSON.stringify(options.data).replace(/<\/script/gi, "\\u003c/script") : "undefined";
3225
3302
  doc.writeln(this.buildIsolationBridge(escapedData));
3226
3303
  }
3227
3304
  doc.close();
@@ -3276,10 +3353,29 @@ var HTMLComponentLoader = class extends BaseMyopLoader {
3276
3353
  });
3277
3354
  }
3278
3355
  /**
3279
- * Detect if HTML is a Myop Web Component (starts with marker comment)
3356
+ * Detect if HTML is a Myop Web Component.
3357
+ *
3358
+ * THE MARKER COMMENT ALONE IS NOT A SAFE SIGNAL, BECAUSE MINIFIERS DELETE COMMENTS.
3359
+ *
3360
+ * This used to be `startsWith(MYOP_WEB_COMPONENT_MARKER)` and nothing else. The
3361
+ * delivery lane minifies with `removeComments: true` (myop-server derive.ts MIN_CFG),
3362
+ * so the stored `min` artifact of every v2 web component loses its leading
3363
+ * `<!-- myop-web-component -->`. Detection then returned false, the component fell
3364
+ * back to plain iframe rendering, and the whole authored document was shown --
3365
+ * including the v2 authoring wrapper, so Pic-Time's production dashboard displayed the
3366
+ * preview chrome ("Web Component v2", a tag-name badge reading `loading...`, SIZE /
3367
+ * OVERFLOW / BG controls) instead of their component. Reported 2026-10-18; the served
3368
+ * HTML measured 328,071 bytes against 951,130 at origin, with zero `<!--` left in it.
3369
+ *
3370
+ * The script id is the signal that survives, and it is the one `extractWebComponentScript`
3371
+ * already depends on: if that element is present, extraction works, so detection
3372
+ * should agree. Checked with a regex rather than DOMParser -- this runs for every
3373
+ * HTML component, and parsing a 300 KB document to answer a yes/no question is not
3374
+ * worth it.
3280
3375
  */
3281
3376
  isMyopWebComponent(html) {
3282
- return html.trimStart().startsWith(MYOP_WEB_COMPONENT_MARKER);
3377
+ if (html.trimStart().startsWith(MYOP_WEB_COMPONENT_MARKER)) return true;
3378
+ return new RegExp("<script[^>]*\\sid=[\"']?".concat(MYOP_WEB_COMPONENT_SCRIPT_ID, "[\"'\\s>]"), "i").test(html);
3283
3379
  }
3284
3380
  /**
3285
3381
  * Resolve how this component should render, applying the host render policy.
@@ -3374,7 +3470,6 @@ var HTMLComponentLoader = class extends BaseMyopLoader {
3374
3470
  if (!container.querySelector('[id^="myop-comp-"]')) {
3375
3471
  container.innerHTML = "";
3376
3472
  }
3377
- this.appendChild(container, element, options);
3378
3473
  const component = new MyopExtractedWebComponent(
3379
3474
  componentDefinition,
3380
3475
  skin,
@@ -3383,7 +3478,8 @@ var HTMLComponentLoader = class extends BaseMyopLoader {
3383
3478
  tagName,
3384
3479
  options
3385
3480
  );
3386
- if ((options == null ? void 0 : options.data) !== void 0) {
3481
+ this.appendChild(container, element, options);
3482
+ if ((options == null ? void 0 : options.data) !== void 0 && (options == null ? void 0 : options.data) !== null) {
3387
3483
  component.initWithData(options.data);
3388
3484
  }
3389
3485
  console.log("[MyopWebComponent] Loaded <".concat(tagName, "> into container"));
@@ -3508,7 +3604,12 @@ var HostSDK = class {
3508
3604
  }
3509
3605
  const myopMessage = event.data;
3510
3606
  if (myopMessage.messageType === MyopMessages.InitRequest) {
3511
- this.components2init.forEach((component2) => {
3607
+ const fromAskingFrame = this.components2init.filter((component2) => {
3608
+ const element = component2.element;
3609
+ return (element == null ? void 0 : element.nodeName) === "IFRAME" && element.contentWindow === event.source;
3610
+ });
3611
+ const targets = fromAskingFrame.length ? fromAskingFrame : this.components2init;
3612
+ targets.forEach((component2) => {
3512
3613
  component2.send(new InitMessage(component2.id));
3513
3614
  });
3514
3615
  return;
@@ -3725,7 +3826,6 @@ var HostSDK = class {
3725
3826
  let component = await componentLoader.load(componentConfig.type, selectedSkin, container, options);
3726
3827
  if (!component.isInitiated) {
3727
3828
  this.components2init.push(component);
3728
- component.send(new InitMessage(component.id));
3729
3829
  }
3730
3830
  component.bind("onDispose", () => {
3731
3831
  this.components = this.components.filter((c) => c !== component);
@@ -3733,6 +3833,9 @@ var HostSDK = class {
3733
3833
  return true;
3734
3834
  });
3735
3835
  this.components.push(component);
3836
+ if (!component.isInitiated) {
3837
+ component.send(new InitMessage(component.id));
3838
+ }
3736
3839
  if (!options || options.connectProps !== false) {
3737
3840
  component = connectProps(component, componentConfig.type.props, selectedSkin);
3738
3841
  }