remote-components 0.1.0 → 0.1.2

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 (62) hide show
  1. package/dist/{component-loader-76eb1b8b.d.ts → component-loader-21865da3.d.ts} +140 -16
  2. package/dist/host-config-58cdccea.d.ts +87 -0
  3. package/dist/html/host.cjs +294 -162
  4. package/dist/html/host.cjs.map +1 -1
  5. package/dist/html/host.js +294 -162
  6. package/dist/html/host.js.map +1 -1
  7. package/dist/internal/next/host/app-router-client.cjs +9 -7
  8. package/dist/internal/next/host/app-router-client.cjs.map +1 -1
  9. package/dist/internal/next/host/app-router-client.d.ts +32 -19
  10. package/dist/internal/next/host/app-router-client.js +9 -7
  11. package/dist/internal/next/host/app-router-client.js.map +1 -1
  12. package/dist/internal/next/remote/render-server.cjs.map +1 -1
  13. package/dist/internal/next/remote/render-server.d.ts +13 -14
  14. package/dist/internal/next/remote/render-server.js.map +1 -1
  15. package/dist/internal/shared/client/proxy-through-host.cjs +15 -1
  16. package/dist/internal/shared/client/proxy-through-host.cjs.map +1 -1
  17. package/dist/internal/shared/client/proxy-through-host.d.ts +5 -0
  18. package/dist/internal/shared/client/proxy-through-host.js +15 -1
  19. package/dist/internal/shared/client/proxy-through-host.js.map +1 -1
  20. package/dist/internal/shared/client/remote-component.cjs.map +1 -1
  21. package/dist/internal/shared/client/remote-component.d.ts +2 -2
  22. package/dist/internal/shared/client/remote-component.js.map +1 -1
  23. package/dist/internal/shared/contract/host-state.cjs +38 -0
  24. package/dist/internal/shared/contract/host-state.cjs.map +1 -0
  25. package/dist/internal/shared/contract/host-state.d.ts +53 -0
  26. package/dist/internal/shared/contract/host-state.js +14 -0
  27. package/dist/internal/shared/contract/host-state.js.map +1 -0
  28. package/dist/internal/shared/contract/resolve-name-from-src.cjs +40 -0
  29. package/dist/internal/shared/contract/resolve-name-from-src.cjs.map +1 -0
  30. package/dist/internal/shared/contract/resolve-name-from-src.d.ts +13 -0
  31. package/dist/internal/shared/contract/resolve-name-from-src.js +16 -0
  32. package/dist/internal/shared/contract/resolve-name-from-src.js.map +1 -0
  33. package/dist/internal/shared/ssr/dom-flight.d.ts +1 -1
  34. package/dist/internal/shared/ssr/fetch-remote-component.cjs.map +1 -1
  35. package/dist/internal/shared/ssr/fetch-remote-component.d.ts +1 -1
  36. package/dist/internal/shared/ssr/fetch-remote-component.js.map +1 -1
  37. package/dist/internal/shared/ssr/fetch-with-hooks.d.ts +1 -1
  38. package/dist/next/host/app-router-server.cjs.map +1 -1
  39. package/dist/next/host/app-router-server.d.ts +11 -41
  40. package/dist/next/host/app-router-server.js.map +1 -1
  41. package/dist/next/host/client/index.cjs +203 -95
  42. package/dist/next/host/client/index.cjs.map +1 -1
  43. package/dist/next/host/client/index.d.ts +1 -1
  44. package/dist/next/host/client/index.js +203 -95
  45. package/dist/next/host/client/index.js.map +1 -1
  46. package/dist/next/host/pages-router-client.cjs.map +1 -1
  47. package/dist/next/host/pages-router-client.d.ts +13 -36
  48. package/dist/next/host/pages-router-client.js.map +1 -1
  49. package/dist/next/host/pages-router-server.cjs.map +1 -1
  50. package/dist/next/host/pages-router-server.d.ts +17 -42
  51. package/dist/next/host/pages-router-server.js.map +1 -1
  52. package/dist/next/index.cjs.map +1 -1
  53. package/dist/next/index.d.ts +13 -39
  54. package/dist/next/index.js.map +1 -1
  55. package/dist/next/remote/server.d.ts +4 -0
  56. package/dist/react/index.cjs +203 -95
  57. package/dist/react/index.cjs.map +1 -1
  58. package/dist/react/index.d.ts +12 -49
  59. package/dist/react/index.js +203 -95
  60. package/dist/react/index.js.map +1 -1
  61. package/dist/{types-cbe44b51.d.ts → types-2b26a246.d.ts} +23 -6
  62. package/package.json +1 -1
package/dist/html/host.js CHANGED
@@ -145,6 +145,33 @@ var init_error = __esm({
145
145
  }
146
146
  });
147
147
 
148
+ // src/shared/utils/index.ts
149
+ function escapeString(str) {
150
+ return str.replace(/[^a-z0-9]/g, "_");
151
+ }
152
+ var init_utils = __esm({
153
+ "src/shared/utils/index.ts"() {
154
+ "use strict";
155
+ }
156
+ });
157
+
158
+ // src/shared/client/const.ts
159
+ function getBundleKey(bundle) {
160
+ return escapeString(bundle);
161
+ }
162
+ var DEFAULT_ROUTE, RUNTIME_WEBPACK, RUNTIME_TURBOPACK, RUNTIME_SCRIPT, REMOTE_COMPONENT_REGEX;
163
+ var init_const = __esm({
164
+ "src/shared/client/const.ts"() {
165
+ "use strict";
166
+ init_utils();
167
+ DEFAULT_ROUTE = "/";
168
+ RUNTIME_WEBPACK = "webpack";
169
+ RUNTIME_TURBOPACK = "turbopack";
170
+ RUNTIME_SCRIPT = "script";
171
+ REMOTE_COMPONENT_REGEX = /(?<prefix>.*?)\[(?<bundle>[^\]]+)\](?:%20| )(?<id>.+)/;
172
+ }
173
+ });
174
+
148
175
  // src/shared/utils/logger.ts
149
176
  function logDebug(location2, message) {
150
177
  if (DEBUG) {
@@ -427,31 +454,6 @@ var init_script_loader = __esm({
427
454
  }
428
455
  });
429
456
 
430
- // src/shared/utils/index.ts
431
- function escapeString(str) {
432
- return str.replace(/[^a-z0-9]/g, "_");
433
- }
434
- var init_utils = __esm({
435
- "src/shared/utils/index.ts"() {
436
- "use strict";
437
- }
438
- });
439
-
440
- // src/shared/client/const.ts
441
- function getBundleKey(bundle) {
442
- return escapeString(bundle);
443
- }
444
- var RUNTIME_WEBPACK, RUNTIME_TURBOPACK, REMOTE_COMPONENT_REGEX;
445
- var init_const = __esm({
446
- "src/shared/client/const.ts"() {
447
- "use strict";
448
- init_utils();
449
- RUNTIME_WEBPACK = "webpack";
450
- RUNTIME_TURBOPACK = "turbopack";
451
- REMOTE_COMPONENT_REGEX = /(?<prefix>.*?)\[(?<bundle>[^\]]+)\](?:%20| )(?<id>.+)/;
452
- }
453
- });
454
-
455
457
  // src/shared/client/turbopack-patterns.ts
456
458
  var REMOTE_SHARED_MARKER_RE, REMOTE_SHARED_ASSIGNMENT_RE, ASYNC_MODULE_LOADER_RE, ASYNC_MODULE_RESOLVE_RE, ASYNC_MODULE_ALL_RE, TURBOPACK_GLOBAL_RE;
457
459
  var init_turbopack_patterns = __esm({
@@ -1769,7 +1771,21 @@ function applyOriginToNodes(doc, url, resolveClientUrl) {
1769
1771
  // src/shared/client/proxy-through-host.ts
1770
1772
  init_protected_rc_fallback();
1771
1773
  function withRemoteSrc(resolveClientUrl, remoteSrc) {
1772
- return (url) => resolveClientUrl(remoteSrc, url);
1774
+ const remoteOrigin = parseOrigin(remoteSrc);
1775
+ return (url) => {
1776
+ const urlOrigin = parseOrigin(url);
1777
+ if (remoteOrigin && urlOrigin && urlOrigin !== remoteOrigin) {
1778
+ return void 0;
1779
+ }
1780
+ return resolveClientUrl(remoteSrc, url);
1781
+ };
1782
+ }
1783
+ function parseOrigin(url) {
1784
+ try {
1785
+ return new URL(url).origin;
1786
+ } catch {
1787
+ return void 0;
1788
+ }
1773
1789
  }
1774
1790
  var proxyClientRequestsThroughHost = (remoteSrc, url) => {
1775
1791
  if (typeof location === "undefined") {
@@ -1794,6 +1810,102 @@ function bindResolveClientUrl(prop, remoteSrc) {
1794
1810
  return prop ? withRemoteSrc(prop, remoteSrc) : void 0;
1795
1811
  }
1796
1812
 
1813
+ // src/shared/client/parse-remote-html.ts
1814
+ init_error();
1815
+ init_const();
1816
+ function validateSingleComponent(doc, name, url) {
1817
+ if (doc.querySelectorAll("div[data-bundle][data-route]").length > 1 && !doc.querySelector(`div[data-bundle][data-route][id^="${name}"]`) || doc.querySelectorAll("remote-component:not([src])").length > 1 && !doc.querySelector(`remote-component[name="${name}"]`)) {
1818
+ throw multipleRemoteComponentsError(url);
1819
+ }
1820
+ }
1821
+ function findComponentElement(doc, name) {
1822
+ return doc.querySelector(`div[data-bundle][data-route][id^="${name}"]`) ?? doc.querySelector("div[data-bundle][data-route]") ?? doc.querySelector("div#__next") ?? doc.querySelector(`remote-component[name="${name}"]:not([src])`) ?? doc.querySelector("remote-component:not([src])");
1823
+ }
1824
+ function parseNextData(doc) {
1825
+ return JSON.parse(
1826
+ (doc.querySelector("#__NEXT_DATA__") ?? doc.querySelector("#__REMOTE_NEXT_DATA__"))?.textContent ?? "null"
1827
+ );
1828
+ }
1829
+ function resolveComponentName(component, nextData, fallbackName) {
1830
+ const isRemoteComponent = component?.tagName.toLowerCase() === "remote-component";
1831
+ const name = component?.getAttribute("id")?.replace(/_ssr$/, "") || isRemoteComponent && component?.getAttribute("name") || (nextData ? "__next" : fallbackName);
1832
+ return { name, isRemoteComponent };
1833
+ }
1834
+ function extractComponentMetadata(component, nextData, name, url) {
1835
+ return {
1836
+ name,
1837
+ bundle: component?.getAttribute("data-bundle") || nextData?.props.__REMOTE_COMPONENT__?.bundle || "default",
1838
+ route: component?.getAttribute("data-route") ?? nextData?.page ?? (url.pathname || DEFAULT_ROUTE),
1839
+ runtime: component?.getAttribute("data-runtime") ?? (nextData?.props.__REMOTE_COMPONENT__?.runtime || RUNTIME_SCRIPT)
1840
+ };
1841
+ }
1842
+ function extractRemoteShared(doc, name, nextData) {
1843
+ const remoteSharedEl = doc.querySelector(
1844
+ `#${name}_shared[data-remote-components-shared]`
1845
+ );
1846
+ const remoteShared = nextData?.props.__REMOTE_COMPONENT__?.shared ?? (JSON.parse(remoteSharedEl?.textContent ?? "{}") ?? {});
1847
+ remoteSharedEl?.remove();
1848
+ return remoteShared;
1849
+ }
1850
+ function validateComponentFound(component, rsc, nextData, isRemoteComponent, url, name) {
1851
+ if (!component || !(rsc || nextData || isRemoteComponent)) {
1852
+ throw new RemoteComponentsError(
1853
+ `Remote Component not found on ${url}.${name !== "__vercel_remote_component" ? ` The name for the <RemoteComponent> is "${name}". Check <RemoteComponent> usage.` : ""} Did you forget to wrap the content in <RemoteComponent>?`
1854
+ );
1855
+ }
1856
+ }
1857
+ function extractLinks(doc, component) {
1858
+ return Array.from(doc.querySelectorAll("link[href]")).filter(
1859
+ (link) => !component.contains(link)
1860
+ );
1861
+ }
1862
+ function extractScripts(doc, component, isRemoteComponent) {
1863
+ return Array.from(
1864
+ (isRemoteComponent ? component : doc).querySelectorAll(
1865
+ "script[src],script[data-src]"
1866
+ )
1867
+ );
1868
+ }
1869
+ function parseRemoteComponentDocument(doc, name, url) {
1870
+ validateSingleComponent(doc, name, url.href);
1871
+ const component = findComponentElement(doc, name);
1872
+ const nextData = parseNextData(doc);
1873
+ const { name: resolvedName, isRemoteComponent } = resolveComponentName(
1874
+ component,
1875
+ nextData,
1876
+ name
1877
+ );
1878
+ const rsc = doc.querySelector(`#${resolvedName}_rsc`);
1879
+ const metadata = extractComponentMetadata(
1880
+ component,
1881
+ nextData,
1882
+ resolvedName,
1883
+ url
1884
+ );
1885
+ const remoteShared = extractRemoteShared(doc, resolvedName, nextData);
1886
+ validateComponentFound(
1887
+ component,
1888
+ rsc,
1889
+ nextData,
1890
+ isRemoteComponent,
1891
+ url.href,
1892
+ resolvedName
1893
+ );
1894
+ const links = extractLinks(doc, component);
1895
+ const scripts = extractScripts(doc, component, isRemoteComponent);
1896
+ return {
1897
+ component,
1898
+ name: resolvedName,
1899
+ isRemoteComponent,
1900
+ metadata,
1901
+ nextData,
1902
+ rsc,
1903
+ remoteShared,
1904
+ links,
1905
+ scripts
1906
+ };
1907
+ }
1908
+
1797
1909
  // src/shared/client/remote-component.ts
1798
1910
  init_error();
1799
1911
 
@@ -1884,6 +1996,32 @@ init_script_loader();
1884
1996
  init_static_loader();
1885
1997
  init_webpack_adapter();
1886
1998
 
1999
+ // src/shared/contract/host-state.ts
2000
+ function createHostState() {
2001
+ return {
2002
+ stage: "idle",
2003
+ prevSrc: void 0,
2004
+ prevUrl: void 0,
2005
+ prevName: void 0,
2006
+ prevIsRemoteComponent: false,
2007
+ abortController: void 0
2008
+ };
2009
+ }
2010
+
2011
+ // src/shared/contract/resolve-name-from-src.ts
2012
+ function resolveNameFromSrc(src, defaultName) {
2013
+ if (!src) {
2014
+ return defaultName;
2015
+ }
2016
+ const hash = typeof src === "string" ? src : src.hash;
2017
+ const hashIndex = hash.indexOf("#");
2018
+ if (hashIndex < 0) {
2019
+ return defaultName;
2020
+ }
2021
+ const name = hash.slice(hashIndex + 1);
2022
+ return name || defaultName;
2023
+ }
2024
+
1887
2025
  // src/html/host/index.tsx
1888
2026
  init_error();
1889
2027
 
@@ -1940,6 +2078,15 @@ async function fetchWithHooks(url, additionalInit, options = {}) {
1940
2078
  return res;
1941
2079
  }
1942
2080
 
2081
+ // src/shared/ssr/get-client-or-server-url.ts
2082
+ function getClientOrServerUrl(src, serverFallback) {
2083
+ const fallback = typeof location !== "undefined" ? location.href : serverFallback;
2084
+ if (!src) {
2085
+ return new URL(fallback);
2086
+ }
2087
+ return typeof src === "string" ? new URL(src, fallback) : src;
2088
+ }
2089
+
1943
2090
  // src/html/host/index.tsx
1944
2091
  init_utils();
1945
2092
  init_abort();
@@ -2071,42 +2218,76 @@ if (typeof HTMLElement !== "undefined") {
2071
2218
  fallbackSlot;
2072
2219
  __next = null;
2073
2220
  fouc = null;
2074
- isLoading = false;
2075
- prevIsRemoteComponent = false;
2076
- prevUrl;
2077
- prevSrc = null;
2078
- prevName;
2221
+ hostState = createHostState();
2079
2222
  root = null;
2080
2223
  reactRoot;
2081
2224
  onRequest;
2082
2225
  onResponse;
2083
2226
  resolveClientUrl;
2084
- /** Current AbortController for the loading operation - can be used to cancel loading via controller.abort() */
2085
- abortController;
2227
+ // -- HostConfig property accessors (attribute-reflected) --
2228
+ get src() {
2229
+ return this.getAttribute("src") ?? void 0;
2230
+ }
2231
+ set src(value) {
2232
+ if (value == null) {
2233
+ this.removeAttribute("src");
2234
+ } else {
2235
+ this.setAttribute("src", String(value));
2236
+ }
2237
+ }
2238
+ /** Always `true` — the HTML host always isolates via Shadow DOM. */
2239
+ get isolate() {
2240
+ return true;
2241
+ }
2242
+ get mode() {
2243
+ const attr = this.getAttribute("mode");
2244
+ return attr === "closed" ? "closed" : "open";
2245
+ }
2246
+ set mode(value) {
2247
+ if (value) {
2248
+ this.setAttribute("mode", value);
2249
+ }
2250
+ }
2251
+ get reset() {
2252
+ return this.getAttribute("reset") !== null;
2253
+ }
2254
+ set reset(value) {
2255
+ if (value) {
2256
+ this.setAttribute("reset", "");
2257
+ } else {
2258
+ this.removeAttribute("reset");
2259
+ }
2260
+ }
2261
+ get credentials() {
2262
+ return this.getAttribute("credentials") || "same-origin";
2263
+ }
2264
+ set credentials(value) {
2265
+ if (value) {
2266
+ this.setAttribute("credentials", value);
2267
+ } else {
2268
+ this.removeAttribute("credentials");
2269
+ }
2270
+ }
2086
2271
  static get observedAttributes() {
2087
2272
  return ["src", "name", "mode"];
2088
2273
  }
2089
- // watch for src attribute changes
2090
- // this is required to reload the remote component when the src attribute is added later
2091
- // this is for rendering the custom element using React
2274
+ dispatchLifecycleEvent(type, detail) {
2275
+ const event = new Event(type, { bubbles: true, composed: true });
2276
+ if (detail) {
2277
+ Object.assign(event, detail);
2278
+ }
2279
+ this.dispatchEvent(event);
2280
+ }
2092
2281
  attributeChangedCallback(name, oldValue, newValue) {
2093
2282
  if ((name === "src" || name === "name") && oldValue !== newValue) {
2094
- if (this.getAttribute("src")) {
2283
+ if (this.src) {
2095
2284
  this.load().catch((e) => {
2096
2285
  if (isAbortError(e)) {
2097
2286
  return;
2098
2287
  }
2099
2288
  logError("HtmlHost", "Error loading remote component.", e);
2100
- const errorEvent = new Event("error", {
2101
- bubbles: true,
2102
- composed: true
2103
- });
2104
- Object.assign(errorEvent, {
2105
- error: e,
2106
- src: this.getAttribute("src")
2107
- });
2108
- this.dispatchEvent(errorEvent);
2109
- this.isLoading = false;
2289
+ this.dispatchLifecycleEvent("error", { error: e, src: this.src });
2290
+ this.hostState.stage = "error";
2110
2291
  });
2111
2292
  }
2112
2293
  } else if (name === "mode" && oldValue !== newValue && this.root) {
@@ -2122,15 +2303,7 @@ if (typeof HTMLElement !== "undefined") {
2122
2303
  return;
2123
2304
  }
2124
2305
  logError("HtmlHost", "Error reloading remote component.", e);
2125
- const errorEvent = new Event("error", {
2126
- bubbles: true,
2127
- composed: true
2128
- });
2129
- Object.assign(errorEvent, {
2130
- error: e,
2131
- src: this.getAttribute("src")
2132
- });
2133
- this.dispatchEvent(errorEvent);
2306
+ this.dispatchLifecycleEvent("error", { error: e, src: this.src });
2134
2307
  });
2135
2308
  }
2136
2309
  }
@@ -2140,9 +2313,9 @@ if (typeof HTMLElement !== "undefined") {
2140
2313
  resolve(void 0);
2141
2314
  });
2142
2315
  });
2143
- if (this.isLoading) {
2144
- this.abortController?.abort();
2145
- this.isLoading = false;
2316
+ if (this.hostState.stage === "loading") {
2317
+ this.hostState.abortController?.abort();
2318
+ this.hostState.stage = "idle";
2146
2319
  if (this.root && !this.reactRoot) {
2147
2320
  this.root.innerHTML = "";
2148
2321
  this.fouc = null;
@@ -2152,29 +2325,24 @@ if (typeof HTMLElement !== "undefined") {
2152
2325
  }
2153
2326
  if (!this.root) {
2154
2327
  this.root = this.attachShadow({
2155
- mode: this.getAttribute("mode") === "closed" ? "closed" : "open"
2328
+ mode: this.mode === "closed" ? "closed" : "open"
2156
2329
  });
2157
2330
  this.fallbackSlot = document.createElement("slot");
2158
2331
  this.root.appendChild(this.fallbackSlot);
2159
2332
  }
2160
2333
  this.name = this.getAttribute("name") || "__vercel_remote_component";
2161
2334
  this.bundle = "default";
2162
- this.isLoading = true;
2163
- const src = this.getAttribute("src");
2164
- this.abortController = new AbortController();
2165
- const signal = this.abortController.signal;
2166
- const isCurrentLoad = () => !signal.aborted && this.getAttribute("src") === src;
2335
+ this.hostState.stage = "loading";
2336
+ const src = this.src;
2337
+ this.hostState.abortController = new AbortController();
2338
+ const signal = this.hostState.abortController.signal;
2339
+ const isCurrentLoad = () => !signal.aborted && this.src === src;
2167
2340
  const abandonLoad = () => {
2168
- if (this.abortController?.signal === signal && this.isLoading) {
2169
- this.isLoading = false;
2341
+ if (this.hostState.abortController?.signal === signal && this.hostState.stage === "loading") {
2342
+ this.hostState.stage = "idle";
2170
2343
  }
2171
2344
  };
2172
- const beforeLoadEvent = new Event("beforeload", {
2173
- bubbles: true,
2174
- composed: true
2175
- });
2176
- Object.assign(beforeLoadEvent, { src });
2177
- this.dispatchEvent(beforeLoadEvent);
2345
+ this.dispatchLifecycleEvent("beforeload", { src });
2178
2346
  const remoteComponentChild = this.querySelector("div#__REMOTE_COMPONENT__") || this.querySelector("div[data-bundle][data-route]");
2179
2347
  if (!src && !remoteComponentChild) {
2180
2348
  throw new RemoteComponentsError('"src" attribute is required');
@@ -2182,15 +2350,16 @@ if (typeof HTMLElement !== "undefined") {
2182
2350
  let url = null;
2183
2351
  let html = this.innerHTML;
2184
2352
  if (src) {
2185
- url = new URL(src, window.location.href);
2186
- if (url.hash) {
2187
- this.name = url.hash.slice(1);
2188
- }
2353
+ url = getClientOrServerUrl(src, window.location.href);
2354
+ this.name = resolveNameFromSrc(
2355
+ src,
2356
+ this.name ?? "__vercel_remote_component"
2357
+ );
2189
2358
  }
2190
2359
  const resolveClientUrl = url ? bindResolveClientUrl(this.resolveClientUrl, url.href) : void 0;
2191
2360
  if (!remoteComponentChild && url) {
2192
2361
  const fetchInit = {
2193
- credentials: this.getAttribute("credentials") || "same-origin"
2362
+ credentials: this.credentials || "same-origin"
2194
2363
  };
2195
2364
  const resolvedUrl = new URL(
2196
2365
  resolveClientUrl?.(url.href) ?? url.href,
@@ -2201,7 +2370,7 @@ if (typeof HTMLElement !== "undefined") {
2201
2370
  res = await fetchWithHooks(resolvedUrl, fetchInit, {
2202
2371
  onRequest: this.onRequest,
2203
2372
  onResponse: this.onResponse,
2204
- abortController: this.abortController
2373
+ abortController: this.hostState.abortController
2205
2374
  });
2206
2375
  } catch (e) {
2207
2376
  if (isAbortError(e)) {
@@ -2226,29 +2395,27 @@ if (typeof HTMLElement !== "undefined") {
2226
2395
  }
2227
2396
  const parser = new DOMParser();
2228
2397
  const doc = parser.parseFromString(html, "text/html");
2229
- if (doc.querySelectorAll("div[data-bundle][data-route]").length > 1 && !doc.querySelector(
2230
- `div[data-bundle][data-route][id^="${this.name}"]`
2231
- ) || doc.querySelectorAll("remote-component").length > 1 && !doc.querySelector(`remote-component[name="${this.name}"]`)) {
2232
- throw multipleRemoteComponentsError(
2233
- url?.href ?? (this.getAttribute("src") || "unknown")
2234
- );
2235
- }
2236
- const component = doc.querySelector(`div[data-bundle][data-route][id^="${this.name}"]`) ?? // fallback to the first element with the data-bundle and data-route attributes when not using a named remote component
2237
- doc.querySelector("div[data-bundle][data-route]") ?? // fallback to Next.js Pages Router
2238
- doc.querySelector("div#__next") ?? // fallback to a <remote-component> element
2239
- doc.querySelector(`remote-component[name="${this.name}"]:not([src])`) ?? doc.querySelector("remote-component:not([src])");
2240
- const nextData = JSON.parse(
2241
- (doc.querySelector("#__NEXT_DATA__") ?? doc.querySelector("#__REMOTE_NEXT_DATA__"))?.textContent ?? "null"
2398
+ const parsed = parseRemoteComponentDocument(
2399
+ doc,
2400
+ this.name ?? "__vercel_remote_component",
2401
+ url ?? new URL(window.location.href)
2242
2402
  );
2243
- const isRemoteComponent = component?.tagName.toLowerCase() === "remote-component";
2403
+ const {
2404
+ component,
2405
+ name: resolvedName,
2406
+ isRemoteComponent,
2407
+ metadata: parsedMetadata,
2408
+ nextData,
2409
+ rsc,
2410
+ remoteShared
2411
+ } = parsed;
2244
2412
  if (nextData && nextData.buildId === "development" && !this.reactRoot) {
2245
2413
  this.fouc = document.createElement("style");
2246
2414
  this.fouc.textContent = `:host { display: none; }`;
2247
2415
  this.root.appendChild(this.fouc);
2248
2416
  }
2249
- this.name = component?.getAttribute("id")?.replace(/_ssr$/, "") || isRemoteComponent && component.getAttribute("name") || (nextData ? "__next" : this.name);
2250
- const rsc = doc.querySelector(`#${this.name}_rsc`);
2251
- this.bundle = component?.getAttribute("data-bundle") || nextData?.props.__REMOTE_COMPONENT__?.bundle || this.bundle;
2417
+ this.name = resolvedName;
2418
+ this.bundle = parsedMetadata.bundle;
2252
2419
  if (url) {
2253
2420
  const self2 = globalThis;
2254
2421
  if (!self2.__remote_bundle_url__) {
@@ -2256,38 +2423,28 @@ if (typeof HTMLElement !== "undefined") {
2256
2423
  }
2257
2424
  self2.__remote_bundle_url__[this.bundle ?? "default"] = url;
2258
2425
  }
2259
- const metadata = document.createElement("script");
2260
- metadata.type = "application/json";
2261
- metadata.setAttribute("data-remote-component", "");
2426
+ const metadataEl = document.createElement("script");
2427
+ metadataEl.type = "application/json";
2428
+ metadataEl.setAttribute("data-remote-component", "");
2262
2429
  const metadataObj = {
2263
2430
  name: this.name,
2264
2431
  bundle: this.bundle,
2265
- route: component?.getAttribute("data-route") ?? nextData?.page ?? url?.pathname ?? "/",
2266
- runtime: component?.getAttribute("data-runtime") ?? nextData?.props.__REMOTE_COMPONENT__?.runtime ?? "script"
2432
+ route: parsedMetadata.route,
2433
+ runtime: parsedMetadata.runtime
2267
2434
  };
2268
- metadata.textContent = JSON.stringify(metadataObj);
2435
+ metadataEl.textContent = JSON.stringify(metadataObj);
2269
2436
  if (this.previousElementSibling?.getAttribute("data-remote-component") !== null) {
2270
2437
  this.previousElementSibling?.remove();
2271
2438
  }
2272
- this.parentElement?.insertBefore(metadata, this);
2273
- const remoteSharedEl = doc.querySelector(
2274
- `#${this.name}_shared[data-remote-components-shared]`
2275
- );
2276
- const remoteShared = nextData?.props.__REMOTE_COMPONENT__?.shared ?? (JSON.parse(remoteSharedEl?.textContent ?? "{}") ?? {});
2277
- remoteSharedEl?.parentElement?.removeChild(remoteSharedEl);
2439
+ this.parentElement?.insertBefore(metadataEl, this);
2278
2440
  if ("__remote_components_missing_shared__" in remoteShared) {
2279
2441
  throw new RemoteComponentsError(
2280
2442
  remoteShared.__remote_components_missing_shared__
2281
2443
  );
2282
2444
  }
2283
- if (!component || !(rsc || nextData || isRemoteComponent)) {
2284
- throw new RemoteComponentsError(
2285
- `Remote Component not found on ${src}.${this.name !== "__vercel_remote_component" ? ` The name for the <RemoteComponent> is "${this.name}". Check <RemoteComponent> usage.` : ""} Did you forget to wrap the content in <RemoteComponent>?`
2286
- );
2287
- }
2288
- if (this.prevIsRemoteComponent) {
2289
- if (this.prevUrl) {
2290
- const prevUrl = this.prevUrl;
2445
+ if (this.hostState.prevIsRemoteComponent) {
2446
+ if (this.hostState.prevUrl) {
2447
+ const prevUrl = this.hostState.prevUrl;
2291
2448
  const self2 = globalThis;
2292
2449
  if (self2.__remote_script_entrypoint_unmount__?.[prevUrl.href]) {
2293
2450
  await Promise.all(
@@ -2312,26 +2469,21 @@ if (typeof HTMLElement !== "undefined") {
2312
2469
  }
2313
2470
  this.root.innerHTML = "";
2314
2471
  }
2315
- if (this.prevSrc !== null) {
2316
- const changeEvent = new Event("change", {
2317
- bubbles: true,
2318
- composed: true
2319
- });
2320
- Object.assign(changeEvent, {
2321
- previousSrc: this.prevSrc,
2472
+ if (this.hostState.prevSrc !== void 0) {
2473
+ this.dispatchLifecycleEvent("change", {
2474
+ previousSrc: this.hostState.prevSrc,
2322
2475
  nextSrc: src,
2323
- previousName: this.prevName,
2476
+ previousName: this.hostState.prevName,
2324
2477
  nextName: this.name
2325
2478
  });
2326
- this.dispatchEvent(changeEvent);
2327
2479
  }
2328
- this.prevUrl = url ?? new URL(window.location.href);
2329
- this.prevIsRemoteComponent = isRemoteComponent;
2330
- this.prevSrc = src;
2331
- this.prevName = this.name;
2480
+ this.hostState.prevUrl = url ?? new URL(window.location.href);
2481
+ this.hostState.prevIsRemoteComponent = isRemoteComponent;
2482
+ this.hostState.prevSrc = src;
2483
+ this.hostState.prevName = this.name;
2332
2484
  const removable = Array.from(this.childNodes);
2333
2485
  const links = doc.querySelectorAll("link[href]");
2334
- const remoteComponentSrc = this.getAttribute("src");
2486
+ const remoteComponentSrc = this.src ? String(this.src) : null;
2335
2487
  const doAttachStyles = () => attachStyles({
2336
2488
  doc,
2337
2489
  component,
@@ -2405,7 +2557,7 @@ if (typeof HTMLElement !== "undefined") {
2405
2557
  }
2406
2558
  this.fallbackSlot?.remove();
2407
2559
  const applyReset = () => {
2408
- if (this.getAttribute("reset") !== null && !this.root?.querySelector("link[data-remote-components-reset]")) {
2560
+ if (this.reset && !this.root?.querySelector("link[data-remote-components-reset]")) {
2409
2561
  const allInitial = document.createElement("link");
2410
2562
  allInitial.setAttribute("data-remote-components-reset", "");
2411
2563
  const css = `:host { all: initial; }`;
@@ -2423,7 +2575,7 @@ if (typeof HTMLElement !== "undefined") {
2423
2575
  allInitial.removeAttribute("onload");
2424
2576
  };
2425
2577
  this.root?.prepend(allInitial);
2426
- } else if (this.getAttribute("reset") === null && this.root?.querySelector("link[data-remote-components-reset]")) {
2578
+ } else if (!this.reset && this.root?.querySelector("link[data-remote-components-reset]")) {
2427
2579
  this.root.querySelector("link[data-remote-components-reset]")?.remove();
2428
2580
  }
2429
2581
  };
@@ -2531,14 +2683,9 @@ if (typeof HTMLElement !== "undefined") {
2531
2683
  });
2532
2684
  }
2533
2685
  if (isCurrentLoad()) {
2534
- this.isLoading = false;
2686
+ this.hostState.stage = "loaded";
2535
2687
  }
2536
- const loadEvent = new Event("load", {
2537
- bubbles: true,
2538
- composed: true
2539
- });
2540
- Object.assign(loadEvent, { src: this.getAttribute("src") });
2541
- this.dispatchEvent(loadEvent);
2688
+ this.dispatchLifecycleEvent("load", { src: this.src });
2542
2689
  }, [initial, name]);
2543
2690
  return Component;
2544
2691
  };
@@ -2572,7 +2719,7 @@ if (typeof HTMLElement !== "undefined") {
2572
2719
  } else if (nextData) {
2573
2720
  const { Component, App } = nextClientPagesLoader2(
2574
2721
  this.bundle ?? "default",
2575
- nextData.page,
2722
+ nextData.page ?? "/",
2576
2723
  this.root
2577
2724
  );
2578
2725
  if (Component) {
@@ -2586,16 +2733,11 @@ if (typeof HTMLElement !== "undefined") {
2586
2733
  });
2587
2734
  }
2588
2735
  if (isCurrentLoad()) {
2589
- remoteComponent.isLoading = false;
2736
+ remoteComponent.hostState.stage = "loaded";
2590
2737
  }
2591
- const loadEvent = new Event("load", {
2592
- bubbles: true,
2593
- composed: true
2594
- });
2595
- Object.assign(loadEvent, {
2596
- src: remoteComponent.getAttribute("src")
2738
+ remoteComponent.dispatchLifecycleEvent("load", {
2739
+ src: remoteComponent.src
2597
2740
  });
2598
- remoteComponent.dispatchEvent(loadEvent);
2599
2741
  }, [initial, remoteComponent]);
2600
2742
  return NextApp ? /* @__PURE__ */ jsx2(NextApp, { Component: NextComponent, ...nextData.props }) : /* @__PURE__ */ jsx2(NextComponent, { ...nextData.props });
2601
2743
  })(App, Component, this);
@@ -2605,7 +2747,7 @@ if (typeof HTMLElement !== "undefined") {
2605
2747
  root.render(/* @__PURE__ */ jsx2(RemoteComponentFromNext, { initial: false }));
2606
2748
  doCleanup();
2607
2749
  if (isCurrentLoad()) {
2608
- this.isLoading = false;
2750
+ this.hostState.stage = "loaded";
2609
2751
  }
2610
2752
  });
2611
2753
  return;
@@ -2636,22 +2778,12 @@ if (typeof HTMLElement !== "undefined") {
2636
2778
  }
2637
2779
  })
2638
2780
  );
2639
- const loadEvent = new Event("load", {
2640
- bubbles: true,
2641
- composed: true
2642
- });
2643
- Object.assign(loadEvent, { src: this.getAttribute("src") });
2644
- this.dispatchEvent(loadEvent);
2781
+ this.dispatchLifecycleEvent("load", { src: this.src });
2645
2782
  } else {
2646
- const loadEvent = new Event("load", {
2647
- bubbles: true,
2648
- composed: true
2649
- });
2650
- Object.assign(loadEvent, { src: this.getAttribute("src") });
2651
- this.dispatchEvent(loadEvent);
2783
+ this.dispatchLifecycleEvent("load", { src: this.src });
2652
2784
  }
2653
2785
  if (isCurrentLoad()) {
2654
- this.isLoading = false;
2786
+ this.hostState.stage = "loaded";
2655
2787
  }
2656
2788
  }
2657
2789
  }