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
@@ -211,6 +211,122 @@ Docs: ${CORS_DOCS_URL}`
211
211
  );
212
212
  }
213
213
 
214
+ // src/shared/utils/index.ts
215
+ function escapeString(str) {
216
+ return str.replace(/[^a-z0-9]/g, "_");
217
+ }
218
+ var attrToProp = {
219
+ fetchpriority: "fetchPriority",
220
+ crossorigin: "crossOrigin",
221
+ imagesrcset: "imageSrcSet",
222
+ imagesizes: "imageSizes",
223
+ srcset: "srcSet"
224
+ };
225
+
226
+ // src/shared/client/const.ts
227
+ var DEFAULT_ROUTE = "/";
228
+ var RUNTIME_WEBPACK = "webpack";
229
+ var RUNTIME_TURBOPACK = "turbopack";
230
+ var RUNTIME_SCRIPT = "script";
231
+ var REMOTE_COMPONENT_REGEX = /(?<prefix>.*?)\[(?<bundle>[^\]]+)\](?:%20| )(?<id>.+)/;
232
+ function getBundleKey(bundle) {
233
+ return escapeString(bundle);
234
+ }
235
+
236
+ // src/shared/client/parse-remote-html.ts
237
+ function validateSingleComponent(doc, name, url) {
238
+ 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}"]`)) {
239
+ throw multipleRemoteComponentsError(url);
240
+ }
241
+ }
242
+ function findComponentElement(doc, name) {
243
+ 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])");
244
+ }
245
+ function parseNextData(doc) {
246
+ return JSON.parse(
247
+ (doc.querySelector("#__NEXT_DATA__") ?? doc.querySelector("#__REMOTE_NEXT_DATA__"))?.textContent ?? "null"
248
+ );
249
+ }
250
+ function resolveComponentName(component, nextData, fallbackName) {
251
+ const isRemoteComponent = component?.tagName.toLowerCase() === "remote-component";
252
+ const name = component?.getAttribute("id")?.replace(/_ssr$/, "") || isRemoteComponent && component?.getAttribute("name") || (nextData ? "__next" : fallbackName);
253
+ return { name, isRemoteComponent };
254
+ }
255
+ function extractComponentMetadata(component, nextData, name, url) {
256
+ return {
257
+ name,
258
+ bundle: component?.getAttribute("data-bundle") || nextData?.props.__REMOTE_COMPONENT__?.bundle || "default",
259
+ route: component?.getAttribute("data-route") ?? nextData?.page ?? (url.pathname || DEFAULT_ROUTE),
260
+ runtime: component?.getAttribute("data-runtime") ?? (nextData?.props.__REMOTE_COMPONENT__?.runtime || RUNTIME_SCRIPT)
261
+ };
262
+ }
263
+ function extractRemoteShared(doc, name, nextData) {
264
+ const remoteSharedEl = doc.querySelector(
265
+ `#${name}_shared[data-remote-components-shared]`
266
+ );
267
+ const remoteShared = nextData?.props.__REMOTE_COMPONENT__?.shared ?? (JSON.parse(remoteSharedEl?.textContent ?? "{}") ?? {});
268
+ remoteSharedEl?.remove();
269
+ return remoteShared;
270
+ }
271
+ function validateComponentFound(component, rsc, nextData, isRemoteComponent, url, name) {
272
+ if (!component || !(rsc || nextData || isRemoteComponent)) {
273
+ throw new RemoteComponentsError(
274
+ `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>?`
275
+ );
276
+ }
277
+ }
278
+ function extractLinks(doc, component) {
279
+ return Array.from(doc.querySelectorAll("link[href]")).filter(
280
+ (link) => !component.contains(link)
281
+ );
282
+ }
283
+ function extractScripts(doc, component, isRemoteComponent) {
284
+ return Array.from(
285
+ (isRemoteComponent ? component : doc).querySelectorAll(
286
+ "script[src],script[data-src]"
287
+ )
288
+ );
289
+ }
290
+ function parseRemoteComponentDocument(doc, name, url) {
291
+ validateSingleComponent(doc, name, url.href);
292
+ const component = findComponentElement(doc, name);
293
+ const nextData = parseNextData(doc);
294
+ const { name: resolvedName, isRemoteComponent } = resolveComponentName(
295
+ component,
296
+ nextData,
297
+ name
298
+ );
299
+ const rsc = doc.querySelector(`#${resolvedName}_rsc`);
300
+ const metadata = extractComponentMetadata(
301
+ component,
302
+ nextData,
303
+ resolvedName,
304
+ url
305
+ );
306
+ const remoteShared = extractRemoteShared(doc, resolvedName, nextData);
307
+ validateComponentFound(
308
+ component,
309
+ rsc,
310
+ nextData,
311
+ isRemoteComponent,
312
+ url.href,
313
+ resolvedName
314
+ );
315
+ const links = extractLinks(doc, component);
316
+ const scripts = extractScripts(doc, component, isRemoteComponent);
317
+ return {
318
+ component,
319
+ name: resolvedName,
320
+ isRemoteComponent,
321
+ metadata,
322
+ nextData,
323
+ rsc,
324
+ remoteShared,
325
+ links,
326
+ scripts
327
+ };
328
+ }
329
+
214
330
  // src/shared/utils/logger.ts
215
331
  var PREFIX = "remote-components";
216
332
  var DEBUG = typeof window !== "undefined" && localStorage.getItem("RC_DEBUG") === "true";
@@ -726,28 +842,6 @@ async function loadScripts(scripts, resolveClientUrl) {
726
842
  );
727
843
  }
728
844
 
729
- // src/shared/utils/index.ts
730
- function escapeString(str) {
731
- return str.replace(/[^a-z0-9]/g, "_");
732
- }
733
- var attrToProp = {
734
- fetchpriority: "fetchPriority",
735
- crossorigin: "crossOrigin",
736
- imagesrcset: "imageSrcSet",
737
- imagesizes: "imageSizes",
738
- srcset: "srcSet"
739
- };
740
-
741
- // src/shared/client/const.ts
742
- var DEFAULT_ROUTE = "/";
743
- var RUNTIME_WEBPACK = "webpack";
744
- var RUNTIME_TURBOPACK = "turbopack";
745
- var RUNTIME_SCRIPT = "script";
746
- var REMOTE_COMPONENT_REGEX = /(?<prefix>.*?)\[(?<bundle>[^\]]+)\](?:%20| )(?<id>.+)/;
747
- function getBundleKey(bundle) {
748
- return escapeString(bundle);
749
- }
750
-
751
845
  // src/shared/client/turbopack-patterns.ts
752
846
  var REMOTE_SHARED_MARKER_RE = /(?:self|[a-z])\.TURBOPACK_REMOTE_SHARED/;
753
847
  var REMOTE_SHARED_ASSIGNMENT_RE = /\.TURBOPACK_REMOTE_SHARED=await (?:__turbopack_context__|e)\.A\((?<sharedModuleId>[0-9]+)\)/;
@@ -1548,7 +1642,21 @@ function loadNextPagesComponent(bundle, route, nextData, name, container) {
1548
1642
 
1549
1643
  // src/shared/client/proxy-through-host.ts
1550
1644
  function withRemoteSrc(resolveClientUrl, remoteSrc) {
1551
- return (url) => resolveClientUrl(remoteSrc, url);
1645
+ const remoteOrigin = parseOrigin(remoteSrc);
1646
+ return (url) => {
1647
+ const urlOrigin = parseOrigin(url);
1648
+ if (remoteOrigin && urlOrigin && urlOrigin !== remoteOrigin) {
1649
+ return void 0;
1650
+ }
1651
+ return resolveClientUrl(remoteSrc, url);
1652
+ };
1653
+ }
1654
+ function parseOrigin(url) {
1655
+ try {
1656
+ return new URL(url).origin;
1657
+ } catch {
1658
+ return void 0;
1659
+ }
1552
1660
  }
1553
1661
  var proxyClientRequestsThroughHost = (remoteSrc, url) => {
1554
1662
  if (typeof location === "undefined") {
@@ -1760,6 +1868,32 @@ async function loadStaticRemoteComponent(scripts, url, resolveClientUrl) {
1760
1868
  );
1761
1869
  }
1762
1870
 
1871
+ // src/shared/contract/host-state.ts
1872
+ function createHostState() {
1873
+ return {
1874
+ stage: "idle",
1875
+ prevSrc: void 0,
1876
+ prevUrl: void 0,
1877
+ prevName: void 0,
1878
+ prevIsRemoteComponent: false,
1879
+ abortController: void 0
1880
+ };
1881
+ }
1882
+
1883
+ // src/shared/contract/resolve-name-from-src.ts
1884
+ function resolveNameFromSrc(src, defaultName) {
1885
+ if (!src) {
1886
+ return defaultName;
1887
+ }
1888
+ const hash = typeof src === "string" ? src : src.hash;
1889
+ const hashIndex = hash.indexOf("#");
1890
+ if (hashIndex < 0) {
1891
+ return defaultName;
1892
+ }
1893
+ const name = hash.slice(hashIndex + 1);
1894
+ return name || defaultName;
1895
+ }
1896
+
1763
1897
  // src/shared/ssr/fetch-headers.ts
1764
1898
  function remoteFetchHeaders() {
1765
1899
  return {
@@ -1887,7 +2021,7 @@ function useShadowRoot({
1887
2021
  return { shadowRoot, shadowRootContainerRef };
1888
2022
  }
1889
2023
 
1890
- // src/react/utils/parse-remote-html.ts
2024
+ // src/react/utils/extract-remote-html.ts
1891
2025
  var DUMMY_FALLBACK = "http://remote-components-dummy-fallback";
1892
2026
  function getRemoteComponentHtml(html) {
1893
2027
  if (typeof document === "undefined")
@@ -1934,20 +2068,10 @@ function RemoteComponent({
1934
2068
  resolveClientUrl: _resolveClientUrl
1935
2069
  }) {
1936
2070
  const instanceId = (0, import_react3.useId)();
1937
- const name = (0, import_react3.useMemo)(() => {
1938
- if (typeof src === "string") {
1939
- const url2 = new URL(
1940
- src,
1941
- typeof document !== "undefined" ? location.href : DUMMY_FALLBACK
1942
- );
1943
- if (url2.hash) {
1944
- return url2.hash.slice(1);
1945
- }
1946
- } else if (typeof src === "object" && "hash" in src && src.hash) {
1947
- return src.hash.slice(1) || nameProp;
1948
- }
1949
- return nameProp;
1950
- }, [src, nameProp]);
2071
+ const name = (0, import_react3.useMemo)(
2072
+ () => resolveNameFromSrc(src, nameProp),
2073
+ [src, nameProp]
2074
+ );
1951
2075
  const [data, setData] = (0, import_react3.useState)(null);
1952
2076
  const url = (0, import_react3.useMemo)(() => getClientOrServerUrl(src, DUMMY_FALLBACK), [src]);
1953
2077
  const resolveClientUrl = useResolveClientUrl(_resolveClientUrl, url.href);
@@ -1980,13 +2104,10 @@ function RemoteComponent({
1980
2104
  return elements;
1981
2105
  })() : []
1982
2106
  );
1983
- const prevSrcRef = (0, import_react3.useRef)(null);
2107
+ const hostStateRef = (0, import_react3.useRef)(createHostState());
1984
2108
  const componentHydrationHtml = (0, import_react3.useRef)(null);
1985
- const prevIsRemoteComponentRef = (0, import_react3.useRef)(false);
1986
- const prevUrlRef = (0, import_react3.useRef)(null);
1987
2109
  const prevRemoteComponentContainerRef = (0, import_react3.useRef)(null);
1988
2110
  const unmountRef = (0, import_react3.useRef)(null);
1989
- const prevNameRef = (0, import_react3.useRef)(void 0);
1990
2111
  (0, import_react3.useLayoutEffect)(() => {
1991
2112
  const shadowRootKey = `__remote_components_shadowroot_${keySuffix}`;
1992
2113
  return () => {
@@ -2025,14 +2146,18 @@ function RemoteComponent({
2025
2146
  }
2026
2147
  }, [shadowRoot, remoteComponent, name]);
2027
2148
  (0, import_react3.useEffect)(() => {
2028
- if (src && src !== prevSrcRef.current) {
2029
- const previousSrc = prevSrcRef.current;
2030
- const previousName = prevNameRef.current;
2031
- prevSrcRef.current = src;
2149
+ if (src && src !== hostStateRef.current.prevSrc) {
2150
+ const previousSrc = hostStateRef.current.prevSrc;
2151
+ const previousName = hostStateRef.current.prevName;
2152
+ hostStateRef.current.prevSrc = src;
2032
2153
  if (previousSrc !== null) {
2033
2154
  htmlRef.current = null;
2034
2155
  }
2156
+ hostStateRef.current.abortController?.abort();
2157
+ hostStateRef.current.abortController = new AbortController();
2158
+ const { signal } = hostStateRef.current.abortController;
2035
2159
  onBeforeLoad?.(src);
2160
+ hostStateRef.current.stage = "loading";
2036
2161
  (0, import_react3.startTransition)(async () => {
2037
2162
  try {
2038
2163
  let html = getRemoteComponentHtml(
@@ -2046,59 +2171,41 @@ function RemoteComponent({
2046
2171
  resolveClientUrl?.(url.href) ?? url.href,
2047
2172
  location.href
2048
2173
  );
2049
- const abortController = new AbortController();
2050
2174
  const res = await fetchWithHooks(resolvedUrl, fetchInit, {
2051
2175
  onRequest,
2052
2176
  onResponse,
2053
- abortController
2177
+ abortController: hostStateRef.current.abortController
2054
2178
  });
2055
2179
  if (!res || !res.ok) {
2056
2180
  throw await errorFromFailedFetch(url.href, resolvedUrl, res);
2057
2181
  }
2058
2182
  const remoteHtml = await res.text();
2183
+ if (signal.aborted)
2184
+ return;
2059
2185
  htmlRef.current = remoteHtml;
2060
2186
  html = getRemoteComponentHtml(remoteHtml);
2061
2187
  }
2188
+ if (signal.aborted)
2189
+ return;
2062
2190
  const parser = new DOMParser();
2063
2191
  const doc = parser.parseFromString(html, "text/html");
2064
- if (doc.querySelectorAll("div[data-bundle][data-route]").length > 1 && !doc.querySelector(
2065
- `div[data-bundle][data-route][id^="${name}"]`
2066
- ) || doc.querySelectorAll("remote-component:not([src])").length > 1 && !doc.querySelector(`remote-component[name="${name}"]`)) {
2067
- throw multipleRemoteComponentsError(url.href);
2068
- }
2069
- const component = doc.querySelector(`div[data-bundle][data-route][id^="${name}"]`) ?? // fallback to the first element with the data-bundle and data-route attributes when not using a named remote component
2070
- doc.querySelector("div[data-bundle][data-route]") ?? // fallback to Next.js Pages Router
2071
- doc.querySelector("div#__next") ?? // fallback to the remote-component web component
2072
- doc.querySelector(`remote-component[name="${name}"]:not([src])`) ?? doc.querySelector("remote-component:not([src])");
2073
- const nextData = JSON.parse(
2074
- (doc.querySelector("#__NEXT_DATA__") ?? doc.querySelector("#__REMOTE_NEXT_DATA__"))?.textContent ?? "null"
2075
- );
2076
- const remoteName = component?.getAttribute("id")?.replace(/_ssr$/, "") || (nextData ? "__next" : name);
2077
- const rsc = doc.querySelector(`#${remoteName}_rsc`);
2078
- const bundle = component?.getAttribute("data-bundle") || nextData?.props.__REMOTE_COMPONENT__?.bundle || "default";
2079
- const isRemoteComponent = component?.tagName.toLowerCase() === "remote-component";
2080
- const metadata = {
2192
+ const {
2193
+ component,
2081
2194
  name: remoteName,
2082
- bundle,
2083
- route: component?.getAttribute("data-route") ?? nextData?.page ?? (url.pathname || DEFAULT_ROUTE),
2084
- runtime: component?.getAttribute("data-runtime") ?? (nextData?.props.__REMOTE_COMPONENT__?.runtime || RUNTIME_SCRIPT)
2085
- };
2086
- const remoteSharedEl = doc.querySelector(
2087
- `#${remoteName}_shared[data-remote-components-shared]`
2088
- );
2089
- const remoteShared = nextData?.props.__REMOTE_COMPONENT__?.shared ?? (JSON.parse(remoteSharedEl?.textContent ?? "{}") ?? {});
2090
- remoteSharedEl?.remove();
2091
- if (!component || !(rsc || nextData || isRemoteComponent)) {
2092
- throw new RemoteComponentsError(
2093
- `Remote Component not found on ${url.href}.${remoteName !== "__vercel_remote_component" ? `The name for the <RemoteComponent> is "${remoteName}". Check <RemoteComponent> usage.` : ""} Did you forget to wrap the content in <RemoteComponent>?`
2094
- );
2095
- }
2096
- if (prevIsRemoteComponentRef.current) {
2195
+ isRemoteComponent,
2196
+ metadata,
2197
+ nextData,
2198
+ rsc,
2199
+ remoteShared,
2200
+ links: linkElements,
2201
+ scripts: scriptElements
2202
+ } = parseRemoteComponentDocument(doc, name, url);
2203
+ if (hostStateRef.current.prevIsRemoteComponent) {
2097
2204
  if (shadowRoot) {
2098
2205
  shadowRoot.innerHTML = "";
2099
2206
  }
2100
2207
  const self = globalThis;
2101
- const prevUrl = prevUrlRef.current;
2208
+ const prevUrl = hostStateRef.current.prevUrl;
2102
2209
  if (prevUrl && self.__remote_script_entrypoint_unmount__?.[prevUrl.href]) {
2103
2210
  const unmountPromises = Promise.all(
2104
2211
  Array.from(unmountRef.current ?? []).map(
@@ -2111,15 +2218,11 @@ function RemoteComponent({
2111
2218
  await unmountPromises;
2112
2219
  }
2113
2220
  }
2114
- prevIsRemoteComponentRef.current = isRemoteComponent;
2115
- prevUrlRef.current = url;
2116
- prevNameRef.current = remoteName;
2221
+ hostStateRef.current.prevIsRemoteComponent = isRemoteComponent;
2222
+ hostStateRef.current.prevUrl = url;
2223
+ hostStateRef.current.prevName = remoteName;
2117
2224
  applyOriginToNodes(doc, url, resolveClientUrl);
2118
- const links = Array.from(
2119
- doc.querySelectorAll("link[href]")
2120
- ).filter((link) => {
2121
- return !component.contains(link);
2122
- }).map((link) => ({
2225
+ const links = linkElements.map((link) => ({
2123
2226
  href: new URL(link.getAttribute("href") ?? link.href, url).href,
2124
2227
  ...link.getAttributeNames().reduce((acc, key) => {
2125
2228
  if (key !== "href") {
@@ -2128,7 +2231,7 @@ function RemoteComponent({
2128
2231
  return acc;
2129
2232
  }, {})
2130
2233
  }));
2131
- const scripts = (isRemoteComponent ? component : doc).querySelectorAll("script[src],script[data-src]");
2234
+ const scripts = scriptElements;
2132
2235
  const inlineScripts = (isRemoteComponent ? component : doc).querySelectorAll(
2133
2236
  "script:not([src]):not([data-src]):not([id*='_rsc']):not([id='__NEXT_DATA__']):not([id='__REMOTE_NEXT_DATA__'])"
2134
2237
  );
@@ -2219,7 +2322,7 @@ function RemoteComponent({
2219
2322
  );
2220
2323
  }
2221
2324
  if (isRemoteComponent) {
2222
- if (previousSrc !== null) {
2325
+ if (previousSrc !== void 0) {
2223
2326
  onChange?.({
2224
2327
  previousSrc,
2225
2328
  nextSrc: src,
@@ -2270,12 +2373,13 @@ function RemoteComponent({
2270
2373
  );
2271
2374
  onLoad?.(src);
2272
2375
  }
2376
+ hostStateRef.current.stage = "loaded";
2273
2377
  } else {
2274
2378
  const result = await loadRemoteComponent({
2275
2379
  url,
2276
2380
  name: remoteName,
2277
2381
  rscName,
2278
- bundle,
2382
+ bundle: metadata.bundle,
2279
2383
  route: metadata.route,
2280
2384
  runtime: metadata.runtime,
2281
2385
  data: newData.data,
@@ -2310,7 +2414,7 @@ function RemoteComponent({
2310
2414
  rsc.remove();
2311
2415
  }
2312
2416
  setData(newData);
2313
- if (previousSrc !== null) {
2417
+ if (previousSrc !== void 0) {
2314
2418
  onChange?.({
2315
2419
  previousSrc,
2316
2420
  nextSrc: src,
@@ -2319,17 +2423,21 @@ function RemoteComponent({
2319
2423
  });
2320
2424
  }
2321
2425
  if (result.error) {
2426
+ hostStateRef.current.stage = "error";
2322
2427
  setRemoteComponent(result.error);
2323
2428
  onError?.(result.error);
2324
2429
  } else {
2430
+ hostStateRef.current.stage = "loaded";
2325
2431
  setRemoteComponent(result.component);
2326
2432
  onLoad?.(src);
2327
2433
  }
2328
2434
  }
2329
2435
  } catch (error) {
2330
2436
  if (isAbortError(error)) {
2437
+ hostStateRef.current.stage = "idle";
2331
2438
  return;
2332
2439
  }
2440
+ hostStateRef.current.stage = "error";
2333
2441
  setRemoteComponent(error);
2334
2442
  onError?.(error);
2335
2443
  }
@@ -2360,7 +2468,7 @@ function RemoteComponent({
2360
2468
  name: data?.name || name,
2361
2469
  bundle: data?.bundle || "default",
2362
2470
  route: data?.route || DEFAULT_ROUTE,
2363
- runtime: prevIsRemoteComponentRef.current ? RUNTIME_SCRIPT : data?.runtime || RUNTIME_WEBPACK
2471
+ runtime: hostStateRef.current.prevIsRemoteComponent ? RUNTIME_SCRIPT : data?.runtime || RUNTIME_WEBPACK
2364
2472
  }) });
2365
2473
  const resetStyle = reset ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { "data-remote-components-reset": "react", children: `:host { all: initial; }` }) : null;
2366
2474
  const linksToRender = data?.links?.map((link) => /* @__PURE__ */ (0, import_react4.createElement)(
@@ -2379,7 +2487,7 @@ function RemoteComponent({
2379
2487
  if (componentHydrationHtml.current && shadowRoot && !shadowRoot.innerHTML) {
2380
2488
  shadowRoot.innerHTML = componentHydrationHtml.current;
2381
2489
  componentHydrationHtml.current = null;
2382
- if (prevIsRemoteComponentRef.current) {
2490
+ if (hostStateRef.current.prevIsRemoteComponent) {
2383
2491
  loadStaticRemoteComponent(
2384
2492
  Array.from(shadowRoot.querySelectorAll("script")),
2385
2493
  url,