@thor-commerce/app-bridge-react 0.7.3 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -23,8 +23,12 @@ __export(index_exports, {
23
23
  AppBridge: () => AppBridge,
24
24
  AppBridgeProvider: () => AppBridgeProvider,
25
25
  EMBEDDED_LAUNCH_PARAMS: () => EMBEDDED_LAUNCH_PARAMS,
26
+ EmbeddedAppRuntime: () => EmbeddedAppRuntime,
27
+ THOR_NAVIGATE_EVENT: () => THOR_NAVIGATE_EVENT,
26
28
  buildNavigationUpdatePayload: () => buildNavigationUpdatePayload,
27
29
  createAppBridge: () => createAppBridge,
30
+ getEmbeddedAppRuntime: () => getEmbeddedAppRuntime,
31
+ getOrCreateEmbeddedAppRuntime: () => getOrCreateEmbeddedAppRuntime,
28
32
  isBridgeMessage: () => isBridgeMessage,
29
33
  normalizeBridgeNavigationItem: () => normalizeBridgeNavigationItem,
30
34
  normalizeBridgeNavigationItems: () => normalizeBridgeNavigationItems,
@@ -539,242 +543,155 @@ function createAppBridge(options = {}) {
539
543
 
540
544
  // src/react.tsx
541
545
  var import_react = require("react");
542
- var import_jsx_runtime = require("react/jsx-runtime");
543
- var AppBridgeContext = (0, import_react.createContext)(null);
544
- function AppBridgeProvider({
545
- children,
546
- clientId,
547
- currentPath,
548
- navigationItems,
549
- navigationEventType = "navigation:go",
550
- navigationUpdateEventType = "navigation:update",
551
- namespace,
552
- onNavigate,
553
- readyEventType = "app:ready",
554
- readyPayload,
555
- requestTimeoutMs,
556
- selfWindow,
557
- targetOrigin,
558
- targetWindow
559
- }) {
560
- const [bridge, setBridge] = (0, import_react.useState)(null);
561
- const onNavigateRef = (0, import_react.useRef)(onNavigate);
562
- const normalizedNavigationItems = (0, import_react.useMemo)(
563
- () => normalizeBridgeNavigationItems(navigationItems),
564
- [navigationItems]
565
- );
566
- const sessionTokenCacheRef = (0, import_react.useRef)(null);
567
- const projectRef = (0, import_react.useRef)(readInitialProject(selfWindow));
568
- const pendingSessionTokenRef = (0, import_react.useRef)(null);
569
- (0, import_react.useEffect)(() => {
570
- onNavigateRef.current = onNavigate;
571
- }, [onNavigate]);
572
- (0, import_react.useEffect)(() => {
573
- if (typeof window === "undefined" && !selfWindow) {
574
- return;
546
+
547
+ // src/runtime.ts
548
+ var GLOBAL_RUNTIME_KEY = "__thorEmbeddedAppRuntime__";
549
+ var THOR_NAVIGATE_EVENT = "thor:navigate";
550
+ var EmbeddedAppRuntime = class {
551
+ constructor(config) {
552
+ this.currentPath = null;
553
+ this.navigationItems = [];
554
+ this.navigationEventType = "navigation:go";
555
+ this.navigationUpdateEventType = "navigation:update";
556
+ this.readyEventType = "app:ready";
557
+ this.sessionTokenCache = null;
558
+ this.pendingSessionToken = null;
559
+ const resolvedWindow = config.selfWindow ?? (typeof window !== "undefined" ? window : void 0);
560
+ if (!resolvedWindow) {
561
+ throw new Error("EmbeddedAppRuntime requires a browser window.");
575
562
  }
576
- const resolvedTargetOrigin = targetOrigin ?? getReferrerOrigin(selfWindow);
577
- const resolvedAllowedOrigins = resolvedTargetOrigin ? [resolvedTargetOrigin] : void 0;
578
- const nextBridge = createAppBridge({
579
- allowedOrigins: resolvedAllowedOrigins,
580
- clientId,
581
- namespace,
582
- requestTimeoutMs,
583
- selfWindow,
563
+ this.selfWindow = resolvedWindow;
564
+ this.targetOrigin = config.targetOrigin ?? getReferrerOrigin(resolvedWindow);
565
+ this.clientId = config.clientId;
566
+ this.project = readInitialProject(resolvedWindow);
567
+ this.readyPayload = config.readyPayload ?? { clientId: config.clientId };
568
+ this.bridge = createAppBridge({
569
+ allowedOrigins: this.targetOrigin ? [this.targetOrigin] : void 0,
570
+ namespace: config.namespace,
571
+ requestTimeoutMs: config.requestTimeoutMs,
572
+ selfWindow: resolvedWindow,
584
573
  source: "embedded-app",
585
574
  target: "dashboard",
586
- targetOrigin: resolvedTargetOrigin,
587
- targetWindow
575
+ targetOrigin: this.targetOrigin,
576
+ targetWindow: config.targetWindow
588
577
  });
589
- setBridge(nextBridge);
590
- return () => {
591
- setBridge((currentBridge) => currentBridge === nextBridge ? null : currentBridge);
592
- nextBridge.destroy();
593
- };
594
- }, [
595
- clientId,
596
- namespace,
597
- requestTimeoutMs,
598
- selfWindow,
599
- targetOrigin,
600
- targetWindow
601
- ]);
602
- (0, import_react.useEffect)(() => {
603
- if (!bridge || !bridge.hasTargetWindow()) {
604
- return;
605
- }
606
- bridge.send(
607
- readyEventType,
608
- readyPayload ?? {
609
- clientId
610
- }
611
- );
612
- }, [bridge, clientId, readyEventType, readyPayload]);
613
- (0, import_react.useEffect)(() => {
614
- if (!bridge || !bridge.hasTargetWindow()) {
615
- return;
616
- }
617
- bridge.send("navigation:items:update", {
618
- items: normalizedNavigationItems
619
- });
620
- }, [bridge, normalizedNavigationItems]);
621
- (0, import_react.useEffect)(() => {
622
- if (!bridge || !bridge.hasTargetWindow() || !currentPath) {
623
- return;
624
- }
625
- bridge.send(navigationUpdateEventType, buildNavigationUpdatePayload(currentPath));
626
- }, [bridge, currentPath, navigationUpdateEventType]);
627
- (0, import_react.useEffect)(() => {
628
- if (!bridge || !onNavigate) {
629
- return;
630
- }
631
- return bridge.on(navigationEventType, (message) => {
578
+ this.removeNavigationRequestHandler = this.bridge.on(this.navigationEventType, (message) => {
632
579
  const destination = resolveNavigationDestination(message.payload);
633
580
  if (!destination) {
634
581
  return;
635
582
  }
636
583
  const nextPath = preserveEmbeddedAppLaunchParams(
637
584
  destination,
638
- typeof window !== "undefined" ? window.location.href : void 0
585
+ this.selfWindow.location.href
639
586
  );
640
- onNavigateRef.current?.(nextPath ?? destination, message);
587
+ this.navigate(nextPath ?? destination, message);
641
588
  });
642
- }, [bridge, navigationEventType, onNavigate]);
643
- (0, import_react.useEffect)(() => {
644
- if (!bridge || !onNavigate || typeof document === "undefined" || typeof window === "undefined") {
645
- return;
646
- }
647
- const handleLocalNavigation = (path) => {
648
- const sanitizedPath = sanitizeEmbeddedAppPath(path);
649
- if (!sanitizedPath) {
650
- return;
651
- }
652
- const nextPath = preserveEmbeddedAppLaunchParams(
653
- sanitizedPath,
654
- window.location.href
655
- );
656
- onNavigateRef.current?.(nextPath ?? sanitizedPath);
657
- };
658
- const handleDocumentClick = (event) => {
659
- if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.altKey || event.ctrlKey || event.shiftKey) {
660
- return;
661
- }
662
- const target = event.target;
663
- if (!(target instanceof Element)) {
664
- return;
665
- }
666
- const anchor = target.closest("a[href]");
667
- if (!(anchor instanceof HTMLAnchorElement)) {
668
- return;
669
- }
670
- if (anchor.hasAttribute("download")) {
671
- return;
672
- }
673
- const targetWindow2 = anchor.target.toLowerCase();
674
- const href = anchor.getAttribute("href");
675
- if (!href) {
676
- return;
677
- }
678
- if (targetWindow2 === "_top" || targetWindow2 === "_parent") {
679
- event.preventDefault();
680
- bridge.redirectToRemote(anchor.href);
681
- return;
682
- }
683
- if (targetWindow2 && targetWindow2 !== "_self") {
684
- return;
685
- }
686
- const nextPath = resolveLocalNavigationPath(href, window.location.origin);
687
- if (!nextPath) {
688
- return;
689
- }
690
- event.preventDefault();
691
- handleLocalNavigation(nextPath);
692
- };
693
- const originalOpen = window.open.bind(window);
694
- window.open = (url, target, features) => {
695
- if (url == null) {
696
- return originalOpen(url, target, features);
697
- }
698
- const href = typeof url === "string" ? url : url.toString();
699
- const targetName = (target ?? "").toLowerCase();
700
- if (targetName === "_top" || targetName === "_parent") {
701
- bridge.redirectToRemote(new URL(href, window.location.href).toString());
702
- return null;
589
+ this.removeNavigationInterceptors = installNavigationInterceptors({
590
+ bridge: this.bridge,
591
+ selfWindow: this.selfWindow,
592
+ navigate: (path) => this.navigate(path)
593
+ });
594
+ this.restoreFetch = installFetchInterceptor({
595
+ bridge: this.bridge,
596
+ getClientId: () => this.clientId,
597
+ getProject: () => this.project,
598
+ setProject: (project) => {
599
+ this.project = project;
600
+ },
601
+ readCachedToken: () => this.sessionTokenCache,
602
+ writeCachedToken: (token) => {
603
+ this.sessionTokenCache = token;
604
+ },
605
+ readPendingToken: () => this.pendingSessionToken,
606
+ writePendingToken: (token) => {
607
+ this.pendingSessionToken = token;
703
608
  }
704
- if (!targetName || targetName === "_self") {
705
- const nextPath = resolveLocalNavigationPath(href, window.location.origin);
706
- if (nextPath) {
707
- handleLocalNavigation(nextPath);
708
- return window;
709
- }
609
+ });
610
+ this.update(config);
611
+ }
612
+ update(config) {
613
+ if (config.clientId) {
614
+ this.clientId = config.clientId;
615
+ if (!this.readyPayload || typeof this.readyPayload === "object" && this.readyPayload !== null && "clientId" in this.readyPayload) {
616
+ this.readyPayload = config.readyPayload ?? { clientId: config.clientId };
710
617
  }
711
- return originalOpen(url, target, features);
712
- };
713
- document.addEventListener("click", handleDocumentClick, true);
714
- return () => {
715
- document.removeEventListener("click", handleDocumentClick, true);
716
- window.open = originalOpen;
717
- };
718
- }, [bridge, onNavigate]);
719
- (0, import_react.useEffect)(() => {
720
- if (!bridge || typeof window === "undefined") {
618
+ }
619
+ if (config.currentPath !== void 0) {
620
+ this.currentPath = config.currentPath;
621
+ }
622
+ if (config.navigationItems !== void 0) {
623
+ this.navigationItems = normalizeBridgeNavigationItems(config.navigationItems);
624
+ }
625
+ if (config.onNavigate !== void 0) {
626
+ this.onNavigate = config.onNavigate;
627
+ }
628
+ if (config.readyEventType) {
629
+ this.readyEventType = config.readyEventType;
630
+ }
631
+ if (config.readyPayload !== void 0) {
632
+ this.readyPayload = config.readyPayload;
633
+ }
634
+ if (config.targetWindow !== void 0) {
635
+ this.bridge.setTargetWindow(config.targetWindow ?? null);
636
+ }
637
+ this.syncBridgeState();
638
+ }
639
+ clearNavigationHandler() {
640
+ this.onNavigate = void 0;
641
+ }
642
+ destroy() {
643
+ this.removeNavigationRequestHandler?.();
644
+ this.removeNavigationInterceptors();
645
+ this.restoreFetch();
646
+ this.bridge.destroy();
647
+ }
648
+ syncBridgeState() {
649
+ if (!this.bridge.hasTargetWindow()) {
721
650
  return;
722
651
  }
723
- const originalFetch = globalThis.fetch.bind(globalThis);
724
- const interceptedFetch = async (input, init) => {
725
- if (!shouldAttachSessionToken(input)) {
726
- return originalFetch(input, init);
727
- }
728
- const existingAuthorization = getExistingAuthorization(input, init);
729
- if (existingAuthorization) {
730
- return originalFetch(input, init);
731
- }
732
- const nextHeaders = new Headers(
733
- input instanceof Request ? input.headers : init?.headers
652
+ this.bridge.send(this.readyEventType, this.readyPayload);
653
+ this.bridge.send("navigation:items:update", {
654
+ items: this.navigationItems
655
+ });
656
+ if (this.currentPath) {
657
+ this.bridge.send(
658
+ this.navigationUpdateEventType,
659
+ buildNavigationUpdatePayload(this.currentPath)
734
660
  );
735
- if (projectRef.current && !nextHeaders.has("X-Thor-Project")) {
736
- nextHeaders.set("X-Thor-Project", projectRef.current);
737
- }
738
- try {
739
- const sessionToken = await getSessionToken({
740
- bridge,
741
- clientId,
742
- pendingSessionTokenRef,
743
- projectRef,
744
- sessionTokenCacheRef
745
- });
746
- nextHeaders.set("Authorization", `Bearer ${sessionToken}`);
747
- } catch {
748
- if (!projectRef.current) {
749
- throw new Error("Missing Thor embedded session token");
750
- }
751
- }
752
- if (!nextHeaders.has("X-Requested-With")) {
753
- nextHeaders.set("X-Requested-With", "XMLHttpRequest");
754
- }
755
- if (input instanceof Request) {
756
- return originalFetch(
757
- new Request(input, {
758
- headers: nextHeaders
759
- })
760
- );
761
- }
762
- return originalFetch(input, {
763
- ...init,
764
- headers: nextHeaders
765
- });
766
- };
767
- globalThis.fetch = interceptedFetch;
768
- window.fetch = interceptedFetch;
769
- return () => {
770
- globalThis.fetch = originalFetch;
771
- window.fetch = originalFetch;
772
- };
773
- }, [bridge, clientId]);
774
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AppBridgeContext.Provider, { value: bridge, children });
661
+ }
662
+ }
663
+ navigate(path, message) {
664
+ if (this.onNavigate) {
665
+ this.onNavigate(path, message);
666
+ return;
667
+ }
668
+ if (dispatchNavigateEvent(this.selfWindow.document, path)) {
669
+ return;
670
+ }
671
+ this.selfWindow.location.assign(path);
672
+ }
673
+ };
674
+ function getOrCreateEmbeddedAppRuntime(config) {
675
+ const globalScope = globalThis;
676
+ const existingRuntime = globalScope[GLOBAL_RUNTIME_KEY];
677
+ if (existingRuntime) {
678
+ existingRuntime.update(config);
679
+ return existingRuntime;
680
+ }
681
+ const runtime = new EmbeddedAppRuntime(config);
682
+ globalScope[GLOBAL_RUNTIME_KEY] = runtime;
683
+ return runtime;
775
684
  }
776
- function useAppBridge() {
777
- return (0, import_react.useContext)(AppBridgeContext);
685
+ function getEmbeddedAppRuntime() {
686
+ return globalThis[GLOBAL_RUNTIME_KEY] ?? null;
687
+ }
688
+ function dispatchNavigateEvent(document, path) {
689
+ const event = new CustomEvent(THOR_NAVIGATE_EVENT, {
690
+ cancelable: true,
691
+ detail: { path }
692
+ });
693
+ document.dispatchEvent(event);
694
+ return event.defaultPrevented;
778
695
  }
779
696
  function getReferrerOrigin(explicitWindow) {
780
697
  const resolvedWindow = explicitWindow ?? (typeof window !== "undefined" ? window : void 0);
@@ -788,40 +705,190 @@ function getReferrerOrigin(explicitWindow) {
788
705
  return void 0;
789
706
  }
790
707
  }
708
+ function installNavigationInterceptors({
709
+ bridge,
710
+ selfWindow,
711
+ navigate
712
+ }) {
713
+ const document = selfWindow.document;
714
+ const handleLocalNavigation = (path) => {
715
+ const sanitizedPath = sanitizeEmbeddedAppPath(path);
716
+ if (!sanitizedPath) {
717
+ return;
718
+ }
719
+ const nextPath = preserveEmbeddedAppLaunchParams(
720
+ sanitizedPath,
721
+ selfWindow.location.href
722
+ );
723
+ navigate(nextPath ?? sanitizedPath);
724
+ };
725
+ const handleDocumentClick = (event) => {
726
+ if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.altKey || event.ctrlKey || event.shiftKey) {
727
+ return;
728
+ }
729
+ const target = event.target;
730
+ if (!(target instanceof Element)) {
731
+ return;
732
+ }
733
+ const anchor = target.closest("a[href]");
734
+ if (!(anchor instanceof HTMLAnchorElement)) {
735
+ return;
736
+ }
737
+ if (anchor.hasAttribute("download")) {
738
+ return;
739
+ }
740
+ const targetWindow = anchor.target.toLowerCase();
741
+ const href = anchor.getAttribute("href");
742
+ if (!href) {
743
+ return;
744
+ }
745
+ if (targetWindow === "_top" || targetWindow === "_parent") {
746
+ event.preventDefault();
747
+ bridge.redirectToRemote(anchor.href);
748
+ return;
749
+ }
750
+ if (targetWindow && targetWindow !== "_self") {
751
+ return;
752
+ }
753
+ const nextPath = resolveLocalNavigationPath(href, selfWindow.location.origin);
754
+ if (!nextPath) {
755
+ return;
756
+ }
757
+ event.preventDefault();
758
+ handleLocalNavigation(nextPath);
759
+ };
760
+ const originalOpen = selfWindow.open.bind(selfWindow);
761
+ selfWindow.open = (url, target, features) => {
762
+ if (url == null) {
763
+ return originalOpen(url, target, features);
764
+ }
765
+ const href = typeof url === "string" ? url : url.toString();
766
+ const targetName = (target ?? "").toLowerCase();
767
+ if (targetName === "_top" || targetName === "_parent") {
768
+ bridge.redirectToRemote(new URL(href, selfWindow.location.href).toString());
769
+ return null;
770
+ }
771
+ if (!targetName || targetName === "_self") {
772
+ const nextPath = resolveLocalNavigationPath(
773
+ href,
774
+ selfWindow.location.origin
775
+ );
776
+ if (nextPath) {
777
+ handleLocalNavigation(nextPath);
778
+ return selfWindow;
779
+ }
780
+ }
781
+ return originalOpen(url, target, features);
782
+ };
783
+ document.addEventListener("click", handleDocumentClick, true);
784
+ return () => {
785
+ document.removeEventListener("click", handleDocumentClick, true);
786
+ selfWindow.open = originalOpen;
787
+ };
788
+ }
789
+ function installFetchInterceptor({
790
+ bridge,
791
+ getClientId,
792
+ getProject,
793
+ setProject,
794
+ readCachedToken,
795
+ writeCachedToken,
796
+ readPendingToken,
797
+ writePendingToken
798
+ }) {
799
+ if (typeof window === "undefined") {
800
+ return () => {
801
+ };
802
+ }
803
+ const originalFetch = globalThis.fetch.bind(globalThis);
804
+ const interceptedFetch = async (input, init) => {
805
+ if (!shouldAttachSessionToken(input)) {
806
+ return originalFetch(input, init);
807
+ }
808
+ const existingAuthorization = getExistingAuthorization(input, init);
809
+ if (existingAuthorization) {
810
+ return originalFetch(input, init);
811
+ }
812
+ const nextHeaders = new Headers(
813
+ input instanceof Request ? input.headers : init?.headers
814
+ );
815
+ try {
816
+ const sessionToken = await getSessionToken({
817
+ bridge,
818
+ clientId: getClientId(),
819
+ project: getProject,
820
+ setProject,
821
+ readCachedToken,
822
+ writeCachedToken,
823
+ readPendingToken,
824
+ writePendingToken
825
+ });
826
+ nextHeaders.set("Authorization", `Bearer ${sessionToken}`);
827
+ } catch {
828
+ if (!getProject()) {
829
+ throw new Error("Missing Thor embedded session token");
830
+ }
831
+ }
832
+ if (!nextHeaders.has("X-Requested-With")) {
833
+ nextHeaders.set("X-Requested-With", "XMLHttpRequest");
834
+ }
835
+ if (input instanceof Request) {
836
+ return originalFetch(
837
+ new Request(input, {
838
+ headers: nextHeaders
839
+ })
840
+ );
841
+ }
842
+ return originalFetch(input, {
843
+ ...init,
844
+ headers: nextHeaders
845
+ });
846
+ };
847
+ globalThis.fetch = interceptedFetch;
848
+ window.fetch = interceptedFetch;
849
+ return () => {
850
+ globalThis.fetch = originalFetch;
851
+ window.fetch = originalFetch;
852
+ };
853
+ }
791
854
  async function getSessionToken({
792
855
  bridge,
793
856
  clientId,
794
- pendingSessionTokenRef,
795
- projectRef,
796
- sessionTokenCacheRef
857
+ project,
858
+ setProject,
859
+ readCachedToken,
860
+ writeCachedToken,
861
+ readPendingToken,
862
+ writePendingToken
797
863
  }) {
798
- const cachedToken = sessionTokenCacheRef.current;
864
+ const cachedToken = readCachedToken();
799
865
  if (cachedToken && !isExpired(cachedToken.expiresAt)) {
800
866
  return cachedToken.token;
801
867
  }
802
- if (pendingSessionTokenRef.current) {
803
- return pendingSessionTokenRef.current;
868
+ const pendingToken = readPendingToken();
869
+ if (pendingToken) {
870
+ return pendingToken;
804
871
  }
805
- const pendingToken = bridge.getSessionToken({ clientId }).then((response) => {
872
+ const nextPendingToken = bridge.getSessionToken({ clientId }).then((response) => {
806
873
  const token = response.sessionToken ?? response.idToken;
807
874
  if (!token) {
808
875
  throw new Error("Missing Thor embedded session token");
809
876
  }
810
877
  if (response.project) {
811
- projectRef.current = response.project;
878
+ setProject(response.project);
812
879
  }
813
- sessionTokenCacheRef.current = {
880
+ writeCachedToken({
814
881
  token,
815
882
  expiresAt: normalizeTokenExpiry(token, response.exp)
816
- };
817
- pendingSessionTokenRef.current = null;
883
+ });
884
+ writePendingToken(null);
818
885
  return token;
819
886
  }).catch((error) => {
820
- pendingSessionTokenRef.current = null;
887
+ writePendingToken(null);
821
888
  throw error;
822
889
  });
823
- pendingSessionTokenRef.current = pendingToken;
824
- return pendingToken;
890
+ writePendingToken(nextPendingToken);
891
+ return nextPendingToken;
825
892
  }
826
893
  function shouldAttachSessionToken(input) {
827
894
  if (typeof window === "undefined") {
@@ -887,13 +954,84 @@ function readInitialProject(explicitWindow) {
887
954
  return null;
888
955
  }
889
956
  }
957
+
958
+ // src/react.tsx
959
+ var import_jsx_runtime = require("react/jsx-runtime");
960
+ var AppBridgeContext = (0, import_react.createContext)(null);
961
+ function AppBridgeProvider({
962
+ children,
963
+ clientId,
964
+ currentPath,
965
+ navigationItems,
966
+ navigationEventType = "navigation:go",
967
+ navigationUpdateEventType = "navigation:update",
968
+ namespace,
969
+ onNavigate,
970
+ readyEventType = "app:ready",
971
+ readyPayload,
972
+ requestTimeoutMs,
973
+ selfWindow,
974
+ targetOrigin,
975
+ targetWindow
976
+ }) {
977
+ const [bridge, setBridge] = (0, import_react.useState)(null);
978
+ (0, import_react.useEffect)(() => {
979
+ if (typeof window === "undefined" && !selfWindow) {
980
+ return;
981
+ }
982
+ const runtime = getOrCreateEmbeddedAppRuntime({
983
+ clientId,
984
+ currentPath,
985
+ navigationEventType,
986
+ navigationItems,
987
+ navigationUpdateEventType,
988
+ namespace,
989
+ onNavigate,
990
+ readyEventType,
991
+ readyPayload,
992
+ requestTimeoutMs,
993
+ selfWindow,
994
+ targetOrigin,
995
+ targetWindow
996
+ });
997
+ setBridge(runtime.bridge);
998
+ return () => {
999
+ runtime.clearNavigationHandler();
1000
+ setBridge(
1001
+ (currentBridge) => currentBridge === runtime.bridge ? null : currentBridge
1002
+ );
1003
+ };
1004
+ }, [
1005
+ clientId,
1006
+ currentPath,
1007
+ navigationEventType,
1008
+ navigationItems,
1009
+ navigationUpdateEventType,
1010
+ namespace,
1011
+ onNavigate,
1012
+ readyEventType,
1013
+ readyPayload,
1014
+ requestTimeoutMs,
1015
+ selfWindow,
1016
+ targetOrigin,
1017
+ targetWindow
1018
+ ]);
1019
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AppBridgeContext.Provider, { value: bridge, children });
1020
+ }
1021
+ function useAppBridge() {
1022
+ return (0, import_react.useContext)(AppBridgeContext);
1023
+ }
890
1024
  // Annotate the CommonJS export names for ESM import in node:
891
1025
  0 && (module.exports = {
892
1026
  AppBridge,
893
1027
  AppBridgeProvider,
894
1028
  EMBEDDED_LAUNCH_PARAMS,
1029
+ EmbeddedAppRuntime,
1030
+ THOR_NAVIGATE_EVENT,
895
1031
  buildNavigationUpdatePayload,
896
1032
  createAppBridge,
1033
+ getEmbeddedAppRuntime,
1034
+ getOrCreateEmbeddedAppRuntime,
897
1035
  isBridgeMessage,
898
1036
  normalizeBridgeNavigationItem,
899
1037
  normalizeBridgeNavigationItems,