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
 
1554
1662
  // src/shared/client/set-attributes-from-props.ts
@@ -1743,6 +1851,32 @@ async function loadStaticRemoteComponent(scripts, url, resolveClientUrl) {
1743
1851
  );
1744
1852
  }
1745
1853
 
1854
+ // src/shared/contract/host-state.ts
1855
+ function createHostState() {
1856
+ return {
1857
+ stage: "idle",
1858
+ prevSrc: void 0,
1859
+ prevUrl: void 0,
1860
+ prevName: void 0,
1861
+ prevIsRemoteComponent: false,
1862
+ abortController: void 0
1863
+ };
1864
+ }
1865
+
1866
+ // src/shared/contract/resolve-name-from-src.ts
1867
+ function resolveNameFromSrc(src, defaultName) {
1868
+ if (!src) {
1869
+ return defaultName;
1870
+ }
1871
+ const hash = typeof src === "string" ? src : src.hash;
1872
+ const hashIndex = hash.indexOf("#");
1873
+ if (hashIndex < 0) {
1874
+ return defaultName;
1875
+ }
1876
+ const name = hash.slice(hashIndex + 1);
1877
+ return name || defaultName;
1878
+ }
1879
+
1746
1880
  // src/shared/ssr/fetch-headers.ts
1747
1881
  function remoteFetchHeaders() {
1748
1882
  return {
@@ -1870,7 +2004,7 @@ function useShadowRoot({
1870
2004
  return { shadowRoot, shadowRootContainerRef };
1871
2005
  }
1872
2006
 
1873
- // src/react/utils/parse-remote-html.ts
2007
+ // src/react/utils/extract-remote-html.ts
1874
2008
  var DUMMY_FALLBACK = "http://remote-components-dummy-fallback";
1875
2009
  function getRemoteComponentHtml(html) {
1876
2010
  if (typeof document === "undefined")
@@ -1917,20 +2051,10 @@ function RemoteComponent({
1917
2051
  resolveClientUrl: _resolveClientUrl
1918
2052
  }) {
1919
2053
  const instanceId = (0, import_react3.useId)();
1920
- const name = (0, import_react3.useMemo)(() => {
1921
- if (typeof src === "string") {
1922
- const url2 = new URL(
1923
- src,
1924
- typeof document !== "undefined" ? location.href : DUMMY_FALLBACK
1925
- );
1926
- if (url2.hash) {
1927
- return url2.hash.slice(1);
1928
- }
1929
- } else if (typeof src === "object" && "hash" in src && src.hash) {
1930
- return src.hash.slice(1) || nameProp;
1931
- }
1932
- return nameProp;
1933
- }, [src, nameProp]);
2054
+ const name = (0, import_react3.useMemo)(
2055
+ () => resolveNameFromSrc(src, nameProp),
2056
+ [src, nameProp]
2057
+ );
1934
2058
  const [data, setData] = (0, import_react3.useState)(null);
1935
2059
  const url = (0, import_react3.useMemo)(() => getClientOrServerUrl(src, DUMMY_FALLBACK), [src]);
1936
2060
  const resolveClientUrl = useResolveClientUrl(_resolveClientUrl, url.href);
@@ -1963,13 +2087,10 @@ function RemoteComponent({
1963
2087
  return elements;
1964
2088
  })() : []
1965
2089
  );
1966
- const prevSrcRef = (0, import_react3.useRef)(null);
2090
+ const hostStateRef = (0, import_react3.useRef)(createHostState());
1967
2091
  const componentHydrationHtml = (0, import_react3.useRef)(null);
1968
- const prevIsRemoteComponentRef = (0, import_react3.useRef)(false);
1969
- const prevUrlRef = (0, import_react3.useRef)(null);
1970
2092
  const prevRemoteComponentContainerRef = (0, import_react3.useRef)(null);
1971
2093
  const unmountRef = (0, import_react3.useRef)(null);
1972
- const prevNameRef = (0, import_react3.useRef)(void 0);
1973
2094
  (0, import_react3.useLayoutEffect)(() => {
1974
2095
  const shadowRootKey = `__remote_components_shadowroot_${keySuffix}`;
1975
2096
  return () => {
@@ -2008,14 +2129,18 @@ function RemoteComponent({
2008
2129
  }
2009
2130
  }, [shadowRoot, remoteComponent, name]);
2010
2131
  (0, import_react3.useEffect)(() => {
2011
- if (src && src !== prevSrcRef.current) {
2012
- const previousSrc = prevSrcRef.current;
2013
- const previousName = prevNameRef.current;
2014
- prevSrcRef.current = src;
2132
+ if (src && src !== hostStateRef.current.prevSrc) {
2133
+ const previousSrc = hostStateRef.current.prevSrc;
2134
+ const previousName = hostStateRef.current.prevName;
2135
+ hostStateRef.current.prevSrc = src;
2015
2136
  if (previousSrc !== null) {
2016
2137
  htmlRef.current = null;
2017
2138
  }
2139
+ hostStateRef.current.abortController?.abort();
2140
+ hostStateRef.current.abortController = new AbortController();
2141
+ const { signal } = hostStateRef.current.abortController;
2018
2142
  onBeforeLoad?.(src);
2143
+ hostStateRef.current.stage = "loading";
2019
2144
  (0, import_react3.startTransition)(async () => {
2020
2145
  try {
2021
2146
  let html = getRemoteComponentHtml(
@@ -2029,59 +2154,41 @@ function RemoteComponent({
2029
2154
  resolveClientUrl?.(url.href) ?? url.href,
2030
2155
  location.href
2031
2156
  );
2032
- const abortController = new AbortController();
2033
2157
  const res = await fetchWithHooks(resolvedUrl, fetchInit, {
2034
2158
  onRequest,
2035
2159
  onResponse,
2036
- abortController
2160
+ abortController: hostStateRef.current.abortController
2037
2161
  });
2038
2162
  if (!res || !res.ok) {
2039
2163
  throw await errorFromFailedFetch(url.href, resolvedUrl, res);
2040
2164
  }
2041
2165
  const remoteHtml = await res.text();
2166
+ if (signal.aborted)
2167
+ return;
2042
2168
  htmlRef.current = remoteHtml;
2043
2169
  html = getRemoteComponentHtml(remoteHtml);
2044
2170
  }
2171
+ if (signal.aborted)
2172
+ return;
2045
2173
  const parser = new DOMParser();
2046
2174
  const doc = parser.parseFromString(html, "text/html");
2047
- if (doc.querySelectorAll("div[data-bundle][data-route]").length > 1 && !doc.querySelector(
2048
- `div[data-bundle][data-route][id^="${name}"]`
2049
- ) || doc.querySelectorAll("remote-component:not([src])").length > 1 && !doc.querySelector(`remote-component[name="${name}"]`)) {
2050
- throw multipleRemoteComponentsError(url.href);
2051
- }
2052
- 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
2053
- doc.querySelector("div[data-bundle][data-route]") ?? // fallback to Next.js Pages Router
2054
- doc.querySelector("div#__next") ?? // fallback to the remote-component web component
2055
- doc.querySelector(`remote-component[name="${name}"]:not([src])`) ?? doc.querySelector("remote-component:not([src])");
2056
- const nextData = JSON.parse(
2057
- (doc.querySelector("#__NEXT_DATA__") ?? doc.querySelector("#__REMOTE_NEXT_DATA__"))?.textContent ?? "null"
2058
- );
2059
- const remoteName = component?.getAttribute("id")?.replace(/_ssr$/, "") || (nextData ? "__next" : name);
2060
- const rsc = doc.querySelector(`#${remoteName}_rsc`);
2061
- const bundle = component?.getAttribute("data-bundle") || nextData?.props.__REMOTE_COMPONENT__?.bundle || "default";
2062
- const isRemoteComponent = component?.tagName.toLowerCase() === "remote-component";
2063
- const metadata = {
2175
+ const {
2176
+ component,
2064
2177
  name: remoteName,
2065
- bundle,
2066
- route: component?.getAttribute("data-route") ?? nextData?.page ?? (url.pathname || DEFAULT_ROUTE),
2067
- runtime: component?.getAttribute("data-runtime") ?? (nextData?.props.__REMOTE_COMPONENT__?.runtime || RUNTIME_SCRIPT)
2068
- };
2069
- const remoteSharedEl = doc.querySelector(
2070
- `#${remoteName}_shared[data-remote-components-shared]`
2071
- );
2072
- const remoteShared = nextData?.props.__REMOTE_COMPONENT__?.shared ?? (JSON.parse(remoteSharedEl?.textContent ?? "{}") ?? {});
2073
- remoteSharedEl?.remove();
2074
- if (!component || !(rsc || nextData || isRemoteComponent)) {
2075
- throw new RemoteComponentsError(
2076
- `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>?`
2077
- );
2078
- }
2079
- if (prevIsRemoteComponentRef.current) {
2178
+ isRemoteComponent,
2179
+ metadata,
2180
+ nextData,
2181
+ rsc,
2182
+ remoteShared,
2183
+ links: linkElements,
2184
+ scripts: scriptElements
2185
+ } = parseRemoteComponentDocument(doc, name, url);
2186
+ if (hostStateRef.current.prevIsRemoteComponent) {
2080
2187
  if (shadowRoot) {
2081
2188
  shadowRoot.innerHTML = "";
2082
2189
  }
2083
2190
  const self = globalThis;
2084
- const prevUrl = prevUrlRef.current;
2191
+ const prevUrl = hostStateRef.current.prevUrl;
2085
2192
  if (prevUrl && self.__remote_script_entrypoint_unmount__?.[prevUrl.href]) {
2086
2193
  const unmountPromises = Promise.all(
2087
2194
  Array.from(unmountRef.current ?? []).map(
@@ -2094,15 +2201,11 @@ function RemoteComponent({
2094
2201
  await unmountPromises;
2095
2202
  }
2096
2203
  }
2097
- prevIsRemoteComponentRef.current = isRemoteComponent;
2098
- prevUrlRef.current = url;
2099
- prevNameRef.current = remoteName;
2204
+ hostStateRef.current.prevIsRemoteComponent = isRemoteComponent;
2205
+ hostStateRef.current.prevUrl = url;
2206
+ hostStateRef.current.prevName = remoteName;
2100
2207
  applyOriginToNodes(doc, url, resolveClientUrl);
2101
- const links = Array.from(
2102
- doc.querySelectorAll("link[href]")
2103
- ).filter((link) => {
2104
- return !component.contains(link);
2105
- }).map((link) => ({
2208
+ const links = linkElements.map((link) => ({
2106
2209
  href: new URL(link.getAttribute("href") ?? link.href, url).href,
2107
2210
  ...link.getAttributeNames().reduce((acc, key) => {
2108
2211
  if (key !== "href") {
@@ -2111,7 +2214,7 @@ function RemoteComponent({
2111
2214
  return acc;
2112
2215
  }, {})
2113
2216
  }));
2114
- const scripts = (isRemoteComponent ? component : doc).querySelectorAll("script[src],script[data-src]");
2217
+ const scripts = scriptElements;
2115
2218
  const inlineScripts = (isRemoteComponent ? component : doc).querySelectorAll(
2116
2219
  "script:not([src]):not([data-src]):not([id*='_rsc']):not([id='__NEXT_DATA__']):not([id='__REMOTE_NEXT_DATA__'])"
2117
2220
  );
@@ -2202,7 +2305,7 @@ function RemoteComponent({
2202
2305
  );
2203
2306
  }
2204
2307
  if (isRemoteComponent) {
2205
- if (previousSrc !== null) {
2308
+ if (previousSrc !== void 0) {
2206
2309
  onChange?.({
2207
2310
  previousSrc,
2208
2311
  nextSrc: src,
@@ -2253,12 +2356,13 @@ function RemoteComponent({
2253
2356
  );
2254
2357
  onLoad?.(src);
2255
2358
  }
2359
+ hostStateRef.current.stage = "loaded";
2256
2360
  } else {
2257
2361
  const result = await loadRemoteComponent({
2258
2362
  url,
2259
2363
  name: remoteName,
2260
2364
  rscName,
2261
- bundle,
2365
+ bundle: metadata.bundle,
2262
2366
  route: metadata.route,
2263
2367
  runtime: metadata.runtime,
2264
2368
  data: newData.data,
@@ -2293,7 +2397,7 @@ function RemoteComponent({
2293
2397
  rsc.remove();
2294
2398
  }
2295
2399
  setData(newData);
2296
- if (previousSrc !== null) {
2400
+ if (previousSrc !== void 0) {
2297
2401
  onChange?.({
2298
2402
  previousSrc,
2299
2403
  nextSrc: src,
@@ -2302,17 +2406,21 @@ function RemoteComponent({
2302
2406
  });
2303
2407
  }
2304
2408
  if (result.error) {
2409
+ hostStateRef.current.stage = "error";
2305
2410
  setRemoteComponent(result.error);
2306
2411
  onError?.(result.error);
2307
2412
  } else {
2413
+ hostStateRef.current.stage = "loaded";
2308
2414
  setRemoteComponent(result.component);
2309
2415
  onLoad?.(src);
2310
2416
  }
2311
2417
  }
2312
2418
  } catch (error) {
2313
2419
  if (isAbortError(error)) {
2420
+ hostStateRef.current.stage = "idle";
2314
2421
  return;
2315
2422
  }
2423
+ hostStateRef.current.stage = "error";
2316
2424
  setRemoteComponent(error);
2317
2425
  onError?.(error);
2318
2426
  }
@@ -2343,7 +2451,7 @@ function RemoteComponent({
2343
2451
  name: data?.name || name,
2344
2452
  bundle: data?.bundle || "default",
2345
2453
  route: data?.route || DEFAULT_ROUTE,
2346
- runtime: prevIsRemoteComponentRef.current ? RUNTIME_SCRIPT : data?.runtime || RUNTIME_WEBPACK
2454
+ runtime: hostStateRef.current.prevIsRemoteComponent ? RUNTIME_SCRIPT : data?.runtime || RUNTIME_WEBPACK
2347
2455
  }) });
2348
2456
  const resetStyle = reset ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { "data-remote-components-reset": "react", children: `:host { all: initial; }` }) : null;
2349
2457
  const linksToRender = data?.links?.map((link) => /* @__PURE__ */ (0, import_react4.createElement)(
@@ -2362,7 +2470,7 @@ function RemoteComponent({
2362
2470
  if (componentHydrationHtml.current && shadowRoot && !shadowRoot.innerHTML) {
2363
2471
  shadowRoot.innerHTML = componentHydrationHtml.current;
2364
2472
  componentHydrationHtml.current = null;
2365
- if (prevIsRemoteComponentRef.current) {
2473
+ if (hostStateRef.current.prevIsRemoteComponent) {
2366
2474
  loadStaticRemoteComponent(
2367
2475
  Array.from(shadowRoot.querySelectorAll("script")),
2368
2476
  url,