@salesforce/internal-lightning-out-containers 2.2.0 → 2.2.1-rc.1

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.
@@ -7,7 +7,8 @@
7
7
  import { api, LightningElement, track } from "lwc";
8
8
  import { pdpEventSchema } from "o11y_schema/sf_pdp";
9
9
 
10
- import { MSG } from "./utils/contants";
10
+ import { MSG } from "./utils/constants";
11
+ import { EmbeddingResizer } from "./utils/EmbeddingResizer";
11
12
 
12
13
  import { createEnvContext } from "./utils/env";
13
14
  import { createGlobalError } from "./utils/errorHandling";
@@ -15,12 +16,16 @@ import { createGlobalError } from "./utils/errorHandling";
15
16
  import { createInstrumentation } from "./utils/instrumentation";
16
17
  import { applyCustomStyleProperties } from "./utils/style";
17
18
 
19
+ const ENABLE_RESIZING = false;
20
+
18
21
  // These settings are important for layout and sizing.
19
- document.documentElement.style.height = "100%";
20
22
  document.documentElement.style.display = "block";
21
23
  document.body.style.margin = "0px";
22
- document.body.style.height = "100%";
23
24
  document.body.style.display = "block";
25
+ if (!ENABLE_RESIZING) {
26
+ document.documentElement.style.height = "100%";
27
+ document.body.style.height = "100%";
28
+ }
24
29
 
25
30
  // Apply global style overrides from URL parameter during bootstrap
26
31
  const urlSearchParams = new URLSearchParams(window.location.search);
@@ -52,6 +57,9 @@ export default class LightningOutBaseContainer extends LightningElement {
52
57
  isError = false;
53
58
  #instrumentation;
54
59
 
60
+ // Resize observer
61
+ #resizer = null;
62
+
55
63
  constructor() {
56
64
  super();
57
65
  this.#env = createEnvContext();
@@ -215,6 +223,28 @@ export default class LightningOutBaseContainer extends LightningElement {
215
223
  }
216
224
  }
217
225
 
226
+ disconnectedCallback() {
227
+ if (ENABLE_RESIZING) {
228
+ this.#resizer?.stop();
229
+ this.#resizer = null;
230
+ }
231
+ }
232
+
233
+ #setupResizeObserver = () => {
234
+ this.#resizer = new EmbeddingResizer({
235
+ targetElement: document.body,
236
+ onResize: (height) => {
237
+ this.#env.parentPostMessage({
238
+ type: MSG.RESIZE,
239
+ height,
240
+ });
241
+ },
242
+ waitForDOMReady: false, // Already connected, no need to wait
243
+ });
244
+
245
+ this.#resizer.start();
246
+ };
247
+
218
248
  renderedCallback() {
219
249
  if (!this.#embeddedCmp && this.refs?.embeddedCmp) {
220
250
  this.#embeddedCmp = this.refs.embeddedCmp;
@@ -226,6 +256,9 @@ export default class LightningOutBaseContainer extends LightningElement {
226
256
  });
227
257
  });
228
258
  this.#env.parentPostMessage({ type: MSG.READY });
259
+ if (ENABLE_RESIZING) {
260
+ this.#setupResizeObserver();
261
+ }
229
262
 
230
263
  // PDP_ProductUsage telemetry
231
264
  if (this.#instrumentation?.log) {
@@ -0,0 +1,112 @@
1
+ /**
2
+ * EmbeddingResizer - Handles dynamic iframe/container resizing
3
+ * Uses ResizeObserver to monitor element size changes and notify the host
4
+ */
5
+ class EmbeddingResizer {
6
+ #observer = null;
7
+ #targetElement;
8
+ #onResize;
9
+ #onReady;
10
+ #waitForDOMReady;
11
+ #lastHeight = -1;
12
+ #scheduled = false;
13
+ #isObserving = false;
14
+ constructor(options) {
15
+ this.#targetElement = options.targetElement || document.body;
16
+ this.#onResize = options.onResize;
17
+ this.#onReady = options.onReady;
18
+ this.#waitForDOMReady = options.waitForDOMReady ?? true;
19
+ }
20
+ /**
21
+ * Start observing the target element for size changes
22
+ */
23
+ start() {
24
+ if (this.#isObserving) {
25
+ return;
26
+ }
27
+ if (this.#waitForDOMReady && document.readyState === "loading") {
28
+ document.addEventListener("DOMContentLoaded", () => this.#startObserver(), { once: true });
29
+ } else {
30
+ this.#startObserver();
31
+ }
32
+ }
33
+ /**
34
+ * Stop observing and clean up resources
35
+ */
36
+ stop() {
37
+ if (this.#observer) {
38
+ this.#observer.disconnect();
39
+ this.#observer = null;
40
+ }
41
+ this.#isObserving = false;
42
+ this.#lastHeight = -1;
43
+ this.#scheduled = false;
44
+ }
45
+ /**
46
+ * Get the current observed height
47
+ */
48
+ getLastHeight() {
49
+ return this.#lastHeight;
50
+ }
51
+ /**
52
+ * Check if currently observing
53
+ */
54
+ isObserving() {
55
+ return this.#isObserving;
56
+ }
57
+ #startObserver = () => {
58
+ this.#observer = new ResizeObserver((entries) => {
59
+ this.#handleResize(entries);
60
+ });
61
+ this.#observer.observe(this.#targetElement, { box: "border-box" });
62
+ this.#isObserving = true;
63
+ // Invoke ready callback if provided
64
+ if (this.#onReady) {
65
+ this.#onReady();
66
+ }
67
+ };
68
+ #handleResize = (entries) => {
69
+ if (!entries || entries.length === 0) {
70
+ return;
71
+ }
72
+ const entry = entries[0];
73
+ const measuredHeight = this.#extractHeight(entry);
74
+ const heightPx = Math.max(0, Math.ceil(Number(measuredHeight)));
75
+ if (!Number.isFinite(heightPx)) {
76
+ return;
77
+ }
78
+ if (heightPx === this.#lastHeight) {
79
+ return;
80
+ }
81
+ this.#lastHeight = heightPx;
82
+ if (!this.#scheduled) {
83
+ this.#scheduled = true;
84
+ requestAnimationFrame(() => {
85
+ this.#scheduled = false;
86
+ if (!this.#isObserving) return;
87
+ this.#onResize(this.#lastHeight);
88
+ });
89
+ }
90
+ };
91
+ #extractHeight = (entry) => {
92
+ // Try borderBoxSize first (more accurate)
93
+ if (entry.borderBoxSize) {
94
+ if (Array.isArray(entry.borderBoxSize)) {
95
+ return entry.borderBoxSize[0]?.blockSize || 0;
96
+ }
97
+ // Some browsers return a single object instead of array
98
+ return entry.borderBoxSize.blockSize || 0;
99
+ }
100
+ // Fallback to contentRect
101
+ if (entry.contentRect && typeof entry.contentRect.height === "number") {
102
+ return entry.contentRect.height;
103
+ }
104
+ // Last resort: getBoundingClientRect
105
+ if (entry.target && typeof entry.target.getBoundingClientRect === "function") {
106
+ return entry.target.getBoundingClientRect().height;
107
+ }
108
+ return 0;
109
+ };
110
+ }
111
+
112
+ export { EmbeddingResizer };
@@ -14,4 +14,5 @@ export const MSG = {
14
14
  SET_COMPONENT_PROPS: "lo.setComponentProps",
15
15
  RELOAD: "lo.reload",
16
16
  GET_COMPONENT_DATA: "lo.getComponentData",
17
+ RESIZE: "lo.resize",
17
18
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/internal-lightning-out-containers",
3
- "version": "2.2.0",
3
+ "version": "2.2.1-rc.1",
4
4
  "private": false,
5
5
  "description": "Lightning Out 2.0 Container Components",
6
6
  "type": "module",