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
@@ -3,7 +3,7 @@ import * as react from 'react';
3
3
  import { RemoteComponentProps } from '../../../react/index.js';
4
4
  export { RemoteComponentsProvider } from '../../../react/index.js';
5
5
  import '../../../proxy-through-host-a676a522.js';
6
- import '../../../component-loader-76eb1b8b.js';
6
+ import '../../../component-loader-21865da3.js';
7
7
 
8
8
  /**
9
9
  * RemoteComponent - Client-side component for rendering remote components
@@ -185,6 +185,122 @@ Docs: ${CORS_DOCS_URL}`
185
185
  );
186
186
  }
187
187
 
188
+ // src/shared/utils/index.ts
189
+ function escapeString(str) {
190
+ return str.replace(/[^a-z0-9]/g, "_");
191
+ }
192
+ var attrToProp = {
193
+ fetchpriority: "fetchPriority",
194
+ crossorigin: "crossOrigin",
195
+ imagesrcset: "imageSrcSet",
196
+ imagesizes: "imageSizes",
197
+ srcset: "srcSet"
198
+ };
199
+
200
+ // src/shared/client/const.ts
201
+ var DEFAULT_ROUTE = "/";
202
+ var RUNTIME_WEBPACK = "webpack";
203
+ var RUNTIME_TURBOPACK = "turbopack";
204
+ var RUNTIME_SCRIPT = "script";
205
+ var REMOTE_COMPONENT_REGEX = /(?<prefix>.*?)\[(?<bundle>[^\]]+)\](?:%20| )(?<id>.+)/;
206
+ function getBundleKey(bundle) {
207
+ return escapeString(bundle);
208
+ }
209
+
210
+ // src/shared/client/parse-remote-html.ts
211
+ function validateSingleComponent(doc, name, url) {
212
+ 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}"]`)) {
213
+ throw multipleRemoteComponentsError(url);
214
+ }
215
+ }
216
+ function findComponentElement(doc, name) {
217
+ 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])");
218
+ }
219
+ function parseNextData(doc) {
220
+ return JSON.parse(
221
+ (doc.querySelector("#__NEXT_DATA__") ?? doc.querySelector("#__REMOTE_NEXT_DATA__"))?.textContent ?? "null"
222
+ );
223
+ }
224
+ function resolveComponentName(component, nextData, fallbackName) {
225
+ const isRemoteComponent = component?.tagName.toLowerCase() === "remote-component";
226
+ const name = component?.getAttribute("id")?.replace(/_ssr$/, "") || isRemoteComponent && component?.getAttribute("name") || (nextData ? "__next" : fallbackName);
227
+ return { name, isRemoteComponent };
228
+ }
229
+ function extractComponentMetadata(component, nextData, name, url) {
230
+ return {
231
+ name,
232
+ bundle: component?.getAttribute("data-bundle") || nextData?.props.__REMOTE_COMPONENT__?.bundle || "default",
233
+ route: component?.getAttribute("data-route") ?? nextData?.page ?? (url.pathname || DEFAULT_ROUTE),
234
+ runtime: component?.getAttribute("data-runtime") ?? (nextData?.props.__REMOTE_COMPONENT__?.runtime || RUNTIME_SCRIPT)
235
+ };
236
+ }
237
+ function extractRemoteShared(doc, name, nextData) {
238
+ const remoteSharedEl = doc.querySelector(
239
+ `#${name}_shared[data-remote-components-shared]`
240
+ );
241
+ const remoteShared = nextData?.props.__REMOTE_COMPONENT__?.shared ?? (JSON.parse(remoteSharedEl?.textContent ?? "{}") ?? {});
242
+ remoteSharedEl?.remove();
243
+ return remoteShared;
244
+ }
245
+ function validateComponentFound(component, rsc, nextData, isRemoteComponent, url, name) {
246
+ if (!component || !(rsc || nextData || isRemoteComponent)) {
247
+ throw new RemoteComponentsError(
248
+ `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>?`
249
+ );
250
+ }
251
+ }
252
+ function extractLinks(doc, component) {
253
+ return Array.from(doc.querySelectorAll("link[href]")).filter(
254
+ (link) => !component.contains(link)
255
+ );
256
+ }
257
+ function extractScripts(doc, component, isRemoteComponent) {
258
+ return Array.from(
259
+ (isRemoteComponent ? component : doc).querySelectorAll(
260
+ "script[src],script[data-src]"
261
+ )
262
+ );
263
+ }
264
+ function parseRemoteComponentDocument(doc, name, url) {
265
+ validateSingleComponent(doc, name, url.href);
266
+ const component = findComponentElement(doc, name);
267
+ const nextData = parseNextData(doc);
268
+ const { name: resolvedName, isRemoteComponent } = resolveComponentName(
269
+ component,
270
+ nextData,
271
+ name
272
+ );
273
+ const rsc = doc.querySelector(`#${resolvedName}_rsc`);
274
+ const metadata = extractComponentMetadata(
275
+ component,
276
+ nextData,
277
+ resolvedName,
278
+ url
279
+ );
280
+ const remoteShared = extractRemoteShared(doc, resolvedName, nextData);
281
+ validateComponentFound(
282
+ component,
283
+ rsc,
284
+ nextData,
285
+ isRemoteComponent,
286
+ url.href,
287
+ resolvedName
288
+ );
289
+ const links = extractLinks(doc, component);
290
+ const scripts = extractScripts(doc, component, isRemoteComponent);
291
+ return {
292
+ component,
293
+ name: resolvedName,
294
+ isRemoteComponent,
295
+ metadata,
296
+ nextData,
297
+ rsc,
298
+ remoteShared,
299
+ links,
300
+ scripts
301
+ };
302
+ }
303
+
188
304
  // src/shared/utils/logger.ts
189
305
  var PREFIX = "remote-components";
190
306
  var DEBUG = typeof window !== "undefined" && localStorage.getItem("RC_DEBUG") === "true";
@@ -700,28 +816,6 @@ async function loadScripts(scripts, resolveClientUrl) {
700
816
  );
701
817
  }
702
818
 
703
- // src/shared/utils/index.ts
704
- function escapeString(str) {
705
- return str.replace(/[^a-z0-9]/g, "_");
706
- }
707
- var attrToProp = {
708
- fetchpriority: "fetchPriority",
709
- crossorigin: "crossOrigin",
710
- imagesrcset: "imageSrcSet",
711
- imagesizes: "imageSizes",
712
- srcset: "srcSet"
713
- };
714
-
715
- // src/shared/client/const.ts
716
- var DEFAULT_ROUTE = "/";
717
- var RUNTIME_WEBPACK = "webpack";
718
- var RUNTIME_TURBOPACK = "turbopack";
719
- var RUNTIME_SCRIPT = "script";
720
- var REMOTE_COMPONENT_REGEX = /(?<prefix>.*?)\[(?<bundle>[^\]]+)\](?:%20| )(?<id>.+)/;
721
- function getBundleKey(bundle) {
722
- return escapeString(bundle);
723
- }
724
-
725
819
  // src/shared/client/turbopack-patterns.ts
726
820
  var REMOTE_SHARED_MARKER_RE = /(?:self|[a-z])\.TURBOPACK_REMOTE_SHARED/;
727
821
  var REMOTE_SHARED_ASSIGNMENT_RE = /\.TURBOPACK_REMOTE_SHARED=await (?:__turbopack_context__|e)\.A\((?<sharedModuleId>[0-9]+)\)/;
@@ -1522,7 +1616,21 @@ function loadNextPagesComponent(bundle, route, nextData, name, container) {
1522
1616
 
1523
1617
  // src/shared/client/proxy-through-host.ts
1524
1618
  function withRemoteSrc(resolveClientUrl, remoteSrc) {
1525
- return (url) => resolveClientUrl(remoteSrc, url);
1619
+ const remoteOrigin = parseOrigin(remoteSrc);
1620
+ return (url) => {
1621
+ const urlOrigin = parseOrigin(url);
1622
+ if (remoteOrigin && urlOrigin && urlOrigin !== remoteOrigin) {
1623
+ return void 0;
1624
+ }
1625
+ return resolveClientUrl(remoteSrc, url);
1626
+ };
1627
+ }
1628
+ function parseOrigin(url) {
1629
+ try {
1630
+ return new URL(url).origin;
1631
+ } catch {
1632
+ return void 0;
1633
+ }
1526
1634
  }
1527
1635
 
1528
1636
  // src/shared/client/set-attributes-from-props.ts
@@ -1717,6 +1825,32 @@ async function loadStaticRemoteComponent(scripts, url, resolveClientUrl) {
1717
1825
  );
1718
1826
  }
1719
1827
 
1828
+ // src/shared/contract/host-state.ts
1829
+ function createHostState() {
1830
+ return {
1831
+ stage: "idle",
1832
+ prevSrc: void 0,
1833
+ prevUrl: void 0,
1834
+ prevName: void 0,
1835
+ prevIsRemoteComponent: false,
1836
+ abortController: void 0
1837
+ };
1838
+ }
1839
+
1840
+ // src/shared/contract/resolve-name-from-src.ts
1841
+ function resolveNameFromSrc(src, defaultName) {
1842
+ if (!src) {
1843
+ return defaultName;
1844
+ }
1845
+ const hash = typeof src === "string" ? src : src.hash;
1846
+ const hashIndex = hash.indexOf("#");
1847
+ if (hashIndex < 0) {
1848
+ return defaultName;
1849
+ }
1850
+ const name = hash.slice(hashIndex + 1);
1851
+ return name || defaultName;
1852
+ }
1853
+
1720
1854
  // src/shared/ssr/fetch-headers.ts
1721
1855
  function remoteFetchHeaders() {
1722
1856
  return {
@@ -1844,7 +1978,7 @@ function useShadowRoot({
1844
1978
  return { shadowRoot, shadowRootContainerRef };
1845
1979
  }
1846
1980
 
1847
- // src/react/utils/parse-remote-html.ts
1981
+ // src/react/utils/extract-remote-html.ts
1848
1982
  var DUMMY_FALLBACK = "http://remote-components-dummy-fallback";
1849
1983
  function getRemoteComponentHtml(html) {
1850
1984
  if (typeof document === "undefined")
@@ -1888,20 +2022,10 @@ function RemoteComponent({
1888
2022
  resolveClientUrl: _resolveClientUrl
1889
2023
  }) {
1890
2024
  const instanceId = useId();
1891
- const name = useMemo2(() => {
1892
- if (typeof src === "string") {
1893
- const url2 = new URL(
1894
- src,
1895
- typeof document !== "undefined" ? location.href : DUMMY_FALLBACK
1896
- );
1897
- if (url2.hash) {
1898
- return url2.hash.slice(1);
1899
- }
1900
- } else if (typeof src === "object" && "hash" in src && src.hash) {
1901
- return src.hash.slice(1) || nameProp;
1902
- }
1903
- return nameProp;
1904
- }, [src, nameProp]);
2025
+ const name = useMemo2(
2026
+ () => resolveNameFromSrc(src, nameProp),
2027
+ [src, nameProp]
2028
+ );
1905
2029
  const [data, setData] = useState2(null);
1906
2030
  const url = useMemo2(() => getClientOrServerUrl(src, DUMMY_FALLBACK), [src]);
1907
2031
  const resolveClientUrl = useResolveClientUrl(_resolveClientUrl, url.href);
@@ -1934,13 +2058,10 @@ function RemoteComponent({
1934
2058
  return elements;
1935
2059
  })() : []
1936
2060
  );
1937
- const prevSrcRef = useRef2(null);
2061
+ const hostStateRef = useRef2(createHostState());
1938
2062
  const componentHydrationHtml = useRef2(null);
1939
- const prevIsRemoteComponentRef = useRef2(false);
1940
- const prevUrlRef = useRef2(null);
1941
2063
  const prevRemoteComponentContainerRef = useRef2(null);
1942
2064
  const unmountRef = useRef2(null);
1943
- const prevNameRef = useRef2(void 0);
1944
2065
  useLayoutEffect2(() => {
1945
2066
  const shadowRootKey = `__remote_components_shadowroot_${keySuffix}`;
1946
2067
  return () => {
@@ -1979,14 +2100,18 @@ function RemoteComponent({
1979
2100
  }
1980
2101
  }, [shadowRoot, remoteComponent, name]);
1981
2102
  useEffect(() => {
1982
- if (src && src !== prevSrcRef.current) {
1983
- const previousSrc = prevSrcRef.current;
1984
- const previousName = prevNameRef.current;
1985
- prevSrcRef.current = src;
2103
+ if (src && src !== hostStateRef.current.prevSrc) {
2104
+ const previousSrc = hostStateRef.current.prevSrc;
2105
+ const previousName = hostStateRef.current.prevName;
2106
+ hostStateRef.current.prevSrc = src;
1986
2107
  if (previousSrc !== null) {
1987
2108
  htmlRef.current = null;
1988
2109
  }
2110
+ hostStateRef.current.abortController?.abort();
2111
+ hostStateRef.current.abortController = new AbortController();
2112
+ const { signal } = hostStateRef.current.abortController;
1989
2113
  onBeforeLoad?.(src);
2114
+ hostStateRef.current.stage = "loading";
1990
2115
  startTransition(async () => {
1991
2116
  try {
1992
2117
  let html = getRemoteComponentHtml(
@@ -2000,59 +2125,41 @@ function RemoteComponent({
2000
2125
  resolveClientUrl?.(url.href) ?? url.href,
2001
2126
  location.href
2002
2127
  );
2003
- const abortController = new AbortController();
2004
2128
  const res = await fetchWithHooks(resolvedUrl, fetchInit, {
2005
2129
  onRequest,
2006
2130
  onResponse,
2007
- abortController
2131
+ abortController: hostStateRef.current.abortController
2008
2132
  });
2009
2133
  if (!res || !res.ok) {
2010
2134
  throw await errorFromFailedFetch(url.href, resolvedUrl, res);
2011
2135
  }
2012
2136
  const remoteHtml = await res.text();
2137
+ if (signal.aborted)
2138
+ return;
2013
2139
  htmlRef.current = remoteHtml;
2014
2140
  html = getRemoteComponentHtml(remoteHtml);
2015
2141
  }
2142
+ if (signal.aborted)
2143
+ return;
2016
2144
  const parser = new DOMParser();
2017
2145
  const doc = parser.parseFromString(html, "text/html");
2018
- if (doc.querySelectorAll("div[data-bundle][data-route]").length > 1 && !doc.querySelector(
2019
- `div[data-bundle][data-route][id^="${name}"]`
2020
- ) || doc.querySelectorAll("remote-component:not([src])").length > 1 && !doc.querySelector(`remote-component[name="${name}"]`)) {
2021
- throw multipleRemoteComponentsError(url.href);
2022
- }
2023
- 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
2024
- doc.querySelector("div[data-bundle][data-route]") ?? // fallback to Next.js Pages Router
2025
- doc.querySelector("div#__next") ?? // fallback to the remote-component web component
2026
- doc.querySelector(`remote-component[name="${name}"]:not([src])`) ?? doc.querySelector("remote-component:not([src])");
2027
- const nextData = JSON.parse(
2028
- (doc.querySelector("#__NEXT_DATA__") ?? doc.querySelector("#__REMOTE_NEXT_DATA__"))?.textContent ?? "null"
2029
- );
2030
- const remoteName = component?.getAttribute("id")?.replace(/_ssr$/, "") || (nextData ? "__next" : name);
2031
- const rsc = doc.querySelector(`#${remoteName}_rsc`);
2032
- const bundle = component?.getAttribute("data-bundle") || nextData?.props.__REMOTE_COMPONENT__?.bundle || "default";
2033
- const isRemoteComponent = component?.tagName.toLowerCase() === "remote-component";
2034
- const metadata = {
2146
+ const {
2147
+ component,
2035
2148
  name: remoteName,
2036
- bundle,
2037
- route: component?.getAttribute("data-route") ?? nextData?.page ?? (url.pathname || DEFAULT_ROUTE),
2038
- runtime: component?.getAttribute("data-runtime") ?? (nextData?.props.__REMOTE_COMPONENT__?.runtime || RUNTIME_SCRIPT)
2039
- };
2040
- const remoteSharedEl = doc.querySelector(
2041
- `#${remoteName}_shared[data-remote-components-shared]`
2042
- );
2043
- const remoteShared = nextData?.props.__REMOTE_COMPONENT__?.shared ?? (JSON.parse(remoteSharedEl?.textContent ?? "{}") ?? {});
2044
- remoteSharedEl?.remove();
2045
- if (!component || !(rsc || nextData || isRemoteComponent)) {
2046
- throw new RemoteComponentsError(
2047
- `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>?`
2048
- );
2049
- }
2050
- if (prevIsRemoteComponentRef.current) {
2149
+ isRemoteComponent,
2150
+ metadata,
2151
+ nextData,
2152
+ rsc,
2153
+ remoteShared,
2154
+ links: linkElements,
2155
+ scripts: scriptElements
2156
+ } = parseRemoteComponentDocument(doc, name, url);
2157
+ if (hostStateRef.current.prevIsRemoteComponent) {
2051
2158
  if (shadowRoot) {
2052
2159
  shadowRoot.innerHTML = "";
2053
2160
  }
2054
2161
  const self = globalThis;
2055
- const prevUrl = prevUrlRef.current;
2162
+ const prevUrl = hostStateRef.current.prevUrl;
2056
2163
  if (prevUrl && self.__remote_script_entrypoint_unmount__?.[prevUrl.href]) {
2057
2164
  const unmountPromises = Promise.all(
2058
2165
  Array.from(unmountRef.current ?? []).map(
@@ -2065,15 +2172,11 @@ function RemoteComponent({
2065
2172
  await unmountPromises;
2066
2173
  }
2067
2174
  }
2068
- prevIsRemoteComponentRef.current = isRemoteComponent;
2069
- prevUrlRef.current = url;
2070
- prevNameRef.current = remoteName;
2175
+ hostStateRef.current.prevIsRemoteComponent = isRemoteComponent;
2176
+ hostStateRef.current.prevUrl = url;
2177
+ hostStateRef.current.prevName = remoteName;
2071
2178
  applyOriginToNodes(doc, url, resolveClientUrl);
2072
- const links = Array.from(
2073
- doc.querySelectorAll("link[href]")
2074
- ).filter((link) => {
2075
- return !component.contains(link);
2076
- }).map((link) => ({
2179
+ const links = linkElements.map((link) => ({
2077
2180
  href: new URL(link.getAttribute("href") ?? link.href, url).href,
2078
2181
  ...link.getAttributeNames().reduce((acc, key) => {
2079
2182
  if (key !== "href") {
@@ -2082,7 +2185,7 @@ function RemoteComponent({
2082
2185
  return acc;
2083
2186
  }, {})
2084
2187
  }));
2085
- const scripts = (isRemoteComponent ? component : doc).querySelectorAll("script[src],script[data-src]");
2188
+ const scripts = scriptElements;
2086
2189
  const inlineScripts = (isRemoteComponent ? component : doc).querySelectorAll(
2087
2190
  "script:not([src]):not([data-src]):not([id*='_rsc']):not([id='__NEXT_DATA__']):not([id='__REMOTE_NEXT_DATA__'])"
2088
2191
  );
@@ -2173,7 +2276,7 @@ function RemoteComponent({
2173
2276
  );
2174
2277
  }
2175
2278
  if (isRemoteComponent) {
2176
- if (previousSrc !== null) {
2279
+ if (previousSrc !== void 0) {
2177
2280
  onChange?.({
2178
2281
  previousSrc,
2179
2282
  nextSrc: src,
@@ -2225,12 +2328,13 @@ function RemoteComponent({
2225
2328
  );
2226
2329
  onLoad?.(src);
2227
2330
  }
2331
+ hostStateRef.current.stage = "loaded";
2228
2332
  } else {
2229
2333
  const result = await loadRemoteComponent({
2230
2334
  url,
2231
2335
  name: remoteName,
2232
2336
  rscName,
2233
- bundle,
2337
+ bundle: metadata.bundle,
2234
2338
  route: metadata.route,
2235
2339
  runtime: metadata.runtime,
2236
2340
  data: newData.data,
@@ -2265,7 +2369,7 @@ function RemoteComponent({
2265
2369
  rsc.remove();
2266
2370
  }
2267
2371
  setData(newData);
2268
- if (previousSrc !== null) {
2372
+ if (previousSrc !== void 0) {
2269
2373
  onChange?.({
2270
2374
  previousSrc,
2271
2375
  nextSrc: src,
@@ -2274,17 +2378,21 @@ function RemoteComponent({
2274
2378
  });
2275
2379
  }
2276
2380
  if (result.error) {
2381
+ hostStateRef.current.stage = "error";
2277
2382
  setRemoteComponent(result.error);
2278
2383
  onError?.(result.error);
2279
2384
  } else {
2385
+ hostStateRef.current.stage = "loaded";
2280
2386
  setRemoteComponent(result.component);
2281
2387
  onLoad?.(src);
2282
2388
  }
2283
2389
  }
2284
2390
  } catch (error) {
2285
2391
  if (isAbortError(error)) {
2392
+ hostStateRef.current.stage = "idle";
2286
2393
  return;
2287
2394
  }
2395
+ hostStateRef.current.stage = "error";
2288
2396
  setRemoteComponent(error);
2289
2397
  onError?.(error);
2290
2398
  }
@@ -2315,7 +2423,7 @@ function RemoteComponent({
2315
2423
  name: data?.name || name,
2316
2424
  bundle: data?.bundle || "default",
2317
2425
  route: data?.route || DEFAULT_ROUTE,
2318
- runtime: prevIsRemoteComponentRef.current ? RUNTIME_SCRIPT : data?.runtime || RUNTIME_WEBPACK
2426
+ runtime: hostStateRef.current.prevIsRemoteComponent ? RUNTIME_SCRIPT : data?.runtime || RUNTIME_WEBPACK
2319
2427
  }) });
2320
2428
  const resetStyle = reset ? /* @__PURE__ */ jsx2("style", { "data-remote-components-reset": "react", children: `:host { all: initial; }` }) : null;
2321
2429
  const linksToRender = data?.links?.map((link) => /* @__PURE__ */ createElement2(
@@ -2334,7 +2442,7 @@ function RemoteComponent({
2334
2442
  if (componentHydrationHtml.current && shadowRoot && !shadowRoot.innerHTML) {
2335
2443
  shadowRoot.innerHTML = componentHydrationHtml.current;
2336
2444
  componentHydrationHtml.current = null;
2337
- if (prevIsRemoteComponentRef.current) {
2445
+ if (hostStateRef.current.prevIsRemoteComponent) {
2338
2446
  loadStaticRemoteComponent(
2339
2447
  Array.from(shadowRoot.querySelectorAll("script")),
2340
2448
  url,