@salesforce/experimental-mfe-bridge 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.
package/dist/index.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! @salesforce/experimental-mfe-bridge v2.2.0-rc.2 (2026-03-20) */
1
+ /*! @salesforce/experimental-mfe-bridge v2.2.1-rc.1 (2026-04-09) */
2
2
  /**
3
3
  * EmbeddingResizer - Handles dynamic iframe/container resizing
4
4
  * Uses ResizeObserver to monitor element size changes and notify the host
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/experimental-mfe-bridge",
3
- "version": "2.2.0",
3
+ "version": "2.2.1-rc.1",
4
4
  "private": false,
5
5
  "description": "EventTarget-Based Embed ↔ Host Communication for UI Embedding",
6
6
  "license": "SEE LICENSE IN LICENSE.txt",
@@ -24,8 +24,8 @@
24
24
  "test": "jest",
25
25
  "clean": "rimraf dist"
26
26
  },
27
- "dependencies": {
28
- "utils": "2.2.0"
27
+ "devDependencies": {
28
+ "utils": "2.2.1-rc.1"
29
29
  },
30
30
  "files": [
31
31
  "dist/",
@@ -1,282 +0,0 @@
1
- var LightningBridge = (function (exports) {
2
- 'use strict';
3
-
4
- /**
5
- * EmbeddingResizer - Handles dynamic iframe/container resizing
6
- * Uses ResizeObserver to monitor element size changes and notify the host
7
- */
8
- class EmbeddingResizer {
9
- #observer = null;
10
- #targetElement;
11
- #onResize;
12
- #onReady;
13
- #waitForDOMReady;
14
- #lastHeight = -1;
15
- #scheduled = false;
16
- #isObserving = false;
17
- constructor(options) {
18
- this.#targetElement = options.targetElement || document.body;
19
- this.#onResize = options.onResize;
20
- this.#onReady = options.onReady;
21
- this.#waitForDOMReady = options.waitForDOMReady ?? true;
22
- }
23
- /**
24
- * Start observing the target element for size changes
25
- */
26
- start() {
27
- if (this.#isObserving) {
28
- return;
29
- }
30
- if (this.#waitForDOMReady && document.readyState === "loading") {
31
- document.addEventListener("DOMContentLoaded", () => this.#startObserver(), { once: true });
32
- }
33
- else {
34
- this.#startObserver();
35
- }
36
- }
37
- /**
38
- * Stop observing and clean up resources
39
- */
40
- stop() {
41
- if (this.#observer) {
42
- this.#observer.disconnect();
43
- this.#observer = null;
44
- }
45
- this.#isObserving = false;
46
- this.#lastHeight = -1;
47
- this.#scheduled = false;
48
- }
49
- /**
50
- * Get the current observed height
51
- */
52
- getLastHeight() {
53
- return this.#lastHeight;
54
- }
55
- /**
56
- * Check if currently observing
57
- */
58
- isObserving() {
59
- return this.#isObserving;
60
- }
61
- #startObserver = () => {
62
- this.#observer = new ResizeObserver((entries) => {
63
- this.#handleResize(entries);
64
- });
65
- this.#observer.observe(this.#targetElement, { box: "border-box" });
66
- this.#isObserving = true;
67
- // Invoke ready callback if provided
68
- if (this.#onReady) {
69
- this.#onReady();
70
- }
71
- };
72
- #handleResize = (entries) => {
73
- if (!entries || entries.length === 0) {
74
- return;
75
- }
76
- const entry = entries[0];
77
- const measuredHeight = this.#extractHeight(entry);
78
- const heightPx = Math.max(0, Math.ceil(Number(measuredHeight)));
79
- if (!Number.isFinite(heightPx)) {
80
- return;
81
- }
82
- if (heightPx === this.#lastHeight) {
83
- return;
84
- }
85
- this.#lastHeight = heightPx;
86
- if (!this.#scheduled) {
87
- this.#scheduled = true;
88
- requestAnimationFrame(() => {
89
- this.#scheduled = false;
90
- this.#onResize(heightPx);
91
- });
92
- }
93
- };
94
- #extractHeight = (entry) => {
95
- // Try borderBoxSize first (more accurate)
96
- if (entry.borderBoxSize) {
97
- if (Array.isArray(entry.borderBoxSize)) {
98
- return entry.borderBoxSize[0]?.blockSize || 0;
99
- }
100
- // Some browsers return a single object instead of array
101
- return entry.borderBoxSize.blockSize || 0;
102
- }
103
- // Fallback to contentRect
104
- if (entry.contentRect && typeof entry.contentRect.height === "number") {
105
- return entry.contentRect.height;
106
- }
107
- // Last resort: getBoundingClientRect
108
- if (entry.target && typeof entry.target.getBoundingClientRect === "function") {
109
- return entry.target.getBoundingClientRect().height;
110
- }
111
- return 0;
112
- };
113
- }
114
-
115
- /**
116
- * ExternalEmbedBridge - EventTarget-based iframe ↔ host communication
117
- * Provides secure, structured interface for widget development
118
- * Auto-handles theme synchronization and error telemetry
119
- */
120
- class ExternalEmbedBridge extends EventTarget {
121
- #connected = false;
122
- #hostAppOrigin = null;
123
- #instanceId = null;
124
- #currentTheme = {};
125
- #currentData = {};
126
- #resizer = null;
127
- constructor() {
128
- super();
129
- window.addEventListener("message", (e) => this.#handleHostMessage(e));
130
- this.#setupErrorCapture();
131
- this.#sendToHost("bridge-ready");
132
- this.#setupResizeObserver();
133
- // eslint-disable-next-line no-console
134
- console.log("[Bridge] Initialized and ready for communication");
135
- }
136
- #handleHostMessage(event) {
137
- if (event.source !== window.parent)
138
- return;
139
- if (this.#hostAppOrigin && event.origin !== this.#hostAppOrigin)
140
- return;
141
- const payload = event.data || {};
142
- const { type, data, id } = payload;
143
- if (typeof type !== "string" || !type.startsWith("salesforce-"))
144
- return;
145
- if (this.#instanceId && id !== this.#instanceId)
146
- return;
147
- // eslint-disable-next-line no-console
148
- console.log("[Bridge] host->widget", type, data);
149
- switch (type) {
150
- case "salesforce-theme":
151
- this.#handleThemeUpdate(data);
152
- break;
153
- case "salesforce-data":
154
- this.#handleDataUpdate(data);
155
- break;
156
- case "salesforce-shell-ready":
157
- this.#handleConnectionReady(event.origin, id);
158
- break;
159
- }
160
- }
161
- #handleThemeUpdate(themeData) {
162
- this.#currentTheme = { ...themeData };
163
- this.#applyThemeToDocument(themeData);
164
- // use super to escape the override
165
- super.dispatchEvent(new CustomEvent("theme", { detail: themeData }));
166
- }
167
- #handleDataUpdate(payload) {
168
- this.#currentData = { ...payload };
169
- // use super to escape the override
170
- super.dispatchEvent(new CustomEvent("data", { detail: payload }));
171
- }
172
- #handleConnectionReady(origin, id) {
173
- this.#connected = true;
174
- this.#hostAppOrigin = origin;
175
- this.#instanceId = id;
176
- // use super to escape the override
177
- super.dispatchEvent(new CustomEvent("connected"));
178
- }
179
- #applyThemeToDocument(themeData) {
180
- const documentElement = document.documentElement;
181
- requestAnimationFrame(() => {
182
- Object.entries(themeData).forEach(([property, value]) => {
183
- if (property.startsWith("--")) {
184
- documentElement.style.setProperty(property, String(value));
185
- }
186
- });
187
- });
188
- }
189
- #setupErrorCapture() {
190
- // this allows salesforce to collect telemetry about errors in your app
191
- window.addEventListener("error", (event) => {
192
- this.#sendToHost("bridge-error", {
193
- type: "javascript-error",
194
- message: event.message,
195
- filename: event.filename,
196
- lineno: event.lineno,
197
- colno: event.colno,
198
- stack: event.error?.stack,
199
- timestamp: Date.now(),
200
- });
201
- });
202
- window.addEventListener("unhandledrejection", (event) => {
203
- this.#sendToHost("bridge-error", {
204
- type: "unhandled-rejection",
205
- reason: event.reason?.toString?.() || "Unknown rejection",
206
- stack: event.reason?.stack,
207
- timestamp: Date.now(),
208
- });
209
- });
210
- }
211
- #setupResizeObserver() {
212
- this.#resizer = new EmbeddingResizer({
213
- targetElement: document.body,
214
- onResize: (height) => {
215
- this.#sendToHost("bridge-event", { eventType: "resize", detail: { height } });
216
- },
217
- onReady: () => {
218
- this.#sendToHost("bridge-event", {
219
- eventType: "widget-ready",
220
- detail: { bridge: "ExternalEmbedBridge", version: "1.0.0", timestamp: Date.now() },
221
- });
222
- },
223
- waitForDOMReady: true,
224
- });
225
- this.#resizer.start();
226
- }
227
- #getHostAppOrigin(type) {
228
- return this.#hostAppOrigin || (type === "bridge-ready" ? "*" : null);
229
- }
230
- #sendToHost(type, data) {
231
- const origin = this.#getHostAppOrigin(type);
232
- if (!origin)
233
- return;
234
- try {
235
- const message = this.#instanceId ? { type, data, id: this.#instanceId } : { type, data };
236
- // eslint-disable-next-line no-console
237
- console.log("[Bridge] Sending message to host:", message);
238
- window.parent.postMessage(message, origin);
239
- }
240
- catch (error) {
241
- // eslint-disable-next-line no-console
242
- console.warn("[Bridge] Failed to send message to host:", error);
243
- }
244
- }
245
- // Override dispatchEvent to forward custom events to the host via post message
246
- dispatchEvent(event) {
247
- const result = super.dispatchEvent(event);
248
- this.#sendToHost("custom-event", {
249
- eventType: event.type,
250
- detail: event.detail,
251
- });
252
- return result;
253
- }
254
- getTheme() {
255
- return { ...this.#currentTheme };
256
- }
257
- getData() {
258
- return { ...this.#currentData };
259
- }
260
- get instanceId() {
261
- return this.#instanceId;
262
- }
263
- isConnected() {
264
- return this.#connected;
265
- }
266
- }
267
-
268
- /**
269
- * Bridge Package Entry Point
270
- * Exports the bridge singleton for iframe ↔ host communication
271
- */
272
- // Create and export a singleton instance for convenience
273
- const bridge = new ExternalEmbedBridge();
274
-
275
- exports.default = bridge;
276
-
277
- Object.defineProperty(exports, '__esModule', { value: true });
278
-
279
- return exports;
280
-
281
- })({});
282
- //# sourceMappingURL=index.iife.js.map
@@ -1,3 +0,0 @@
1
- /*! @lightning-out/bridge v2.2.0-rc.1 (2026-03-11) */
2
- var LightningBridge=function(e){"use strict";class t{#e=null;#t;#s;#n;#i;#r=-1;#a=!1;#o=!1;constructor(e){this.#t=e.targetElement||document.body,this.#s=e.onResize,this.#n=e.onReady,this.#i=e.waitForDOMReady??!0}start(){this.#o||(this.#i&&"loading"===document.readyState?document.addEventListener("DOMContentLoaded",()=>this.#d(),{once:!0}):this.#d())}stop(){this.#e&&(this.#e.disconnect(),this.#e=null),this.#o=!1,this.#r=-1,this.#a=!1}getLastHeight(){return this.#r}isObserving(){return this.#o}#d=()=>{this.#e=new ResizeObserver(e=>{this.#h(e)}),this.#e.observe(this.#t,{box:"border-box"}),this.#o=!0,this.#n&&this.#n()};#h=e=>{if(!e||0===e.length)return;const t=e[0],s=this.#c(t),n=Math.max(0,Math.ceil(Number(s)));Number.isFinite(n)&&n!==this.#r&&(this.#r=n,this.#a||(this.#a=!0,requestAnimationFrame(()=>{this.#a=!1,this.#s(n)})))};#c=e=>e.borderBoxSize?Array.isArray(e.borderBoxSize)?e.borderBoxSize[0]?.blockSize||0:e.borderBoxSize.blockSize||0:e.contentRect&&"number"==typeof e.contentRect.height?e.contentRect.height:e.target&&"function"==typeof e.target.getBoundingClientRect?e.target.getBoundingClientRect().height:0}class s extends EventTarget{#l=!1;#g=null;#u=null;#p={};#m={};#b=null;constructor(){super(),window.addEventListener("message",e=>this.#v(e)),this.#y(),this.#w("bridge-ready"),this.#R(),console.log("[Bridge] Initialized and ready for communication")}#v(e){if(e.source!==window.parent)return;if(this.#g&&e.origin!==this.#g)return;const t=e.data||{},{type:s,data:n,id:i}=t;if("string"==typeof s&&s.startsWith("salesforce-")&&(!this.#u||i===this.#u))switch(console.log("[Bridge] host->widget",s,n),s){case"salesforce-theme":this.#O(n);break;case"salesforce-data":this.#E(n);break;case"salesforce-shell-ready":this.#z(e.origin,i)}}#O(e){this.#p={...e},this.#T(e),super.dispatchEvent(new CustomEvent("theme",{detail:e}))}#E(e){this.#m={...e},super.dispatchEvent(new CustomEvent("data",{detail:e}))}#z(e,t){this.#l=!0,this.#g=e,this.#u=t,super.dispatchEvent(new CustomEvent("connected"))}#T(e){const t=document.documentElement;requestAnimationFrame(()=>{Object.entries(e).forEach(([e,s])=>{e.startsWith("--")&&t.style.setProperty(e,String(s))})})}#y(){window.addEventListener("error",e=>{this.#w("bridge-error",{type:"javascript-error",message:e.message,filename:e.filename,lineno:e.lineno,colno:e.colno,stack:e.error?.stack,timestamp:Date.now()})}),window.addEventListener("unhandledrejection",e=>{this.#w("bridge-error",{type:"unhandled-rejection",reason:e.reason?.toString?.()||"Unknown rejection",stack:e.reason?.stack,timestamp:Date.now()})})}#R(){this.#b=new t({targetElement:document.body,onResize:e=>{this.#w("bridge-event",{eventType:"resize",detail:{height:e}})},onReady:()=>{this.#w("bridge-event",{eventType:"widget-ready",detail:{bridge:"ExternalEmbedBridge",version:"1.0.0",timestamp:Date.now()}})},waitForDOMReady:!0}),this.#b.start()}#f(e){return this.#g||("bridge-ready"===e?"*":null)}#w(e,t){const s=this.#f(e);if(s)try{const n=this.#u?{type:e,data:t,id:this.#u}:{type:e,data:t};console.log("[Bridge] Sending message to host:",n),window.parent.postMessage(n,s)}catch(e){console.warn("[Bridge] Failed to send message to host:",e)}}dispatchEvent(e){const t=super.dispatchEvent(e);return this.#w("custom-event",{eventType:e.type,detail:e.detail}),t}getTheme(){return{...this.#p}}getData(){return{...this.#m}}get instanceId(){return this.#u}isConnected(){return this.#l}}const n=new s;return e.default=n,Object.defineProperty(e,"__esModule",{value:!0}),e}({});
3
- //# sourceMappingURL=index.iife.prod.js.map