@sanity/sdk-react 3.4.0-next.20260921073349 → 3.4.0-next.20260921115438
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/_exports/dashboard.d.ts +50 -28
- package/dist/_exports/dashboard.d.ts.map +1 -1
- package/dist/_exports/dashboard.js +142 -56
- package/dist/_exports/dashboard.js.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +2 -2
- package/src/_exports/dashboard.ts +5 -1
- package/src/hooks/dashboard/useNavigate.test.ts +392 -5
- package/src/hooks/dashboard/useNavigate.ts +169 -26
- package/src/hooks/dashboard/useNavigateToStudioDocument.test.ts +116 -9
- package/src/hooks/dashboard/useNavigateToStudioDocument.ts +110 -39
|
@@ -586,50 +586,69 @@ type TopicEmitter<K extends EventTopic$1> = (...args: PayloadOf$1<K> extends voi
|
|
|
586
586
|
* @public
|
|
587
587
|
*/
|
|
588
588
|
export declare function useEmit<K extends EventTopic$1>(topic: K): TopicEmitter<K>;
|
|
589
|
+
/**
|
|
590
|
+
* A navigation the Dashboard asks the app to perform, or that the app reports to the Dashboard.
|
|
591
|
+
* `path` is relative to the app's own route, with no leading slash (`'documents/abc'`), and may
|
|
592
|
+
* carry a query string and hash.
|
|
593
|
+
* @public
|
|
594
|
+
*/
|
|
595
|
+
type DashboardNavigation = PathChangeMessage['data'];
|
|
596
|
+
/**
|
|
597
|
+
* Reports an in-app navigation to the Dashboard so the browser URL and the Dashboard's own
|
|
598
|
+
* router follow the app. `type` defaults to `'push'` and only applies in the federated runtime;
|
|
599
|
+
* see {@link useNavigate}.
|
|
600
|
+
* @public
|
|
601
|
+
*/
|
|
602
|
+
type NavigateToDashboardPath = (options: {
|
|
603
|
+
path: string;
|
|
604
|
+
type?: 'push' | 'replace';
|
|
605
|
+
}) => void;
|
|
589
606
|
/**
|
|
590
607
|
* @public
|
|
591
608
|
*
|
|
592
609
|
* A helper hook designed to be injected into routing components for apps within the Dashboard.
|
|
593
|
-
*
|
|
594
|
-
*
|
|
595
|
-
*
|
|
596
|
-
*
|
|
597
|
-
*
|
|
598
|
-
*
|
|
599
|
-
*
|
|
600
|
-
*
|
|
610
|
+
* It keeps the app's router and the Dashboard in two-way sync: `navigateFn` receives the
|
|
611
|
+
* navigations the Dashboard asks the app to perform, and the returned function reports the app's
|
|
612
|
+
* own in-app navigations back to the Dashboard so the browser URL and the Dashboard's router
|
|
613
|
+
* follow along.
|
|
614
|
+
*
|
|
615
|
+
* A navigation the app reports is not echoed back through `navigateFn`. The returned function is
|
|
616
|
+
* referentially stable.
|
|
617
|
+
*
|
|
618
|
+
* The two Dashboard runtimes differ:
|
|
619
|
+
* - In an iframe (Comlink), inbound `type` may be `'push'`, `'replace'` or `'pop'`. Reporting is
|
|
620
|
+
* optional because the bridge already forwards the iframe's own `pushState`; a reported `type`
|
|
621
|
+
* is ignored and the host applies the URL as a `replace`.
|
|
622
|
+
* - In a federated app (message bus), inbound `type` is `'push'` or `'replace'`; `'pop'` is never
|
|
623
|
+
* sent. Reporting is required because the app's router does not reach the host, and `type` is
|
|
624
|
+
* honoured. Until the Dashboard publishes the app's base path, reports are dropped with a
|
|
625
|
+
* console warning.
|
|
601
626
|
*
|
|
602
627
|
* @param navigateFn - Function to handle navigation; should accept:
|
|
603
628
|
* - `path`: a string, which will be a relative path (for example, 'my-route')
|
|
604
629
|
* - `type`: 'push', 'replace', or 'pop', which will be the type of navigation to perform
|
|
630
|
+
* @returns A function the app calls to report its own in-app navigations to the Dashboard.
|
|
605
631
|
*
|
|
606
632
|
* @example
|
|
607
633
|
* ```tsx
|
|
608
634
|
* import {useNavigate} from '@sanity/sdk-react/dashboard'
|
|
609
|
-
* import {
|
|
610
|
-
* import {
|
|
611
|
-
*
|
|
612
|
-
* function
|
|
613
|
-
* const
|
|
614
|
-
*
|
|
615
|
-
*
|
|
635
|
+
* import {useEffect} from 'react'
|
|
636
|
+
* import {useLocation, useNavigate as useRouterNavigate} from 'react-router'
|
|
637
|
+
*
|
|
638
|
+
* function DashboardNavigationSync() {
|
|
639
|
+
* const routerNavigate = useRouterNavigate()
|
|
640
|
+
* const {pathname, search, hash} = useLocation()
|
|
641
|
+
* const navigate = useNavigate(({path, type}) => {
|
|
642
|
+
* routerNavigate(path, {replace: type === 'replace'})
|
|
616
643
|
* })
|
|
644
|
+
* useEffect(() => {
|
|
645
|
+
* navigate({path: `${pathname.slice(1)}${search}${hash}`})
|
|
646
|
+
* }, [navigate, pathname, search, hash])
|
|
617
647
|
* return null
|
|
618
648
|
* }
|
|
619
|
-
*
|
|
620
|
-
* // Wrap the component with Suspense since the hook may suspend
|
|
621
|
-
* function MyApp() {
|
|
622
|
-
* return (
|
|
623
|
-
* <BrowserRouter>
|
|
624
|
-
* <Suspense>
|
|
625
|
-
* <DashboardNavigationHandler />
|
|
626
|
-
* </Suspense>
|
|
627
|
-
* </BrowserRouter>
|
|
628
|
-
* )
|
|
629
|
-
* }
|
|
630
649
|
* ```
|
|
631
650
|
*/
|
|
632
|
-
export declare function useNavigate(navigateFn: (options:
|
|
651
|
+
export declare function useNavigate(navigateFn: (options: DashboardNavigation) => void): NavigateToDashboardPath;
|
|
633
652
|
/**
|
|
634
653
|
* @public
|
|
635
654
|
* @category Types
|
|
@@ -645,6 +664,9 @@ interface NavigateToStudioResult {
|
|
|
645
664
|
* Uses the `projectId` and `dataset` properties of the {@link DocumentHandle} you provide to resolve the correct Studio.
|
|
646
665
|
* This will only work if you have deployed a studio with a workspace with this `projectId` / `dataset` combination.
|
|
647
666
|
*
|
|
667
|
+
* Works in both Dashboard runtimes: it sends the navigation over the Comlink connection in the
|
|
668
|
+
* iframe runtime and over the message bus in the federated runtime.
|
|
669
|
+
*
|
|
648
670
|
* @remarks If you write your own Document Handle to pass to this hook (as opposed to a Document Handle generated by another hook),
|
|
649
671
|
* it must include values for `documentId`, `documentType`, `projectId`, and `dataset`.
|
|
650
672
|
*
|
|
@@ -773,5 +795,5 @@ export declare const useTopic: <K extends StateTopic$1>(topic: K) => TopicData$1
|
|
|
773
795
|
* @public
|
|
774
796
|
*/
|
|
775
797
|
export declare function useWindowTitle(viewTitle?: string): void;
|
|
776
|
-
export { type AgentResourceContextOptions, type ApplicationConfig, type ApplicationConfigAppType, type ApplicationConfigSelector, type CanvasUrl, type Capability, type CapabilityRecord, type ConnectMessageBusOptions, type CoreApplicationUrl, type CreateIntentParameters, type CreateRemoteInstanceOptions, type DashboardApplication, type DashboardTopics, type DashboardUrl, type DashboardView, type DashboardWebWorker, type EditIntentParameters, type EventTopic, type EventTopicDef, type FederationRemote, type MediaLibraryUrl, type MessageBus, type MessageBusAbortOptions, type MessageBusClient, type MessageBusConnection, type MessageBusEmitOptions, type MessageBusEmitResult, MessageBusError, type MessageBusErrorCode, type MessageBusHost, type MessageBusMessage, type MessageBusMeta, type MessageBusQueryOptions, type MessageBusStateSource, type NavigateToStudioResult, type NavigationLocation, type NavigationTarget, type PayloadOf, type ReleaseIntentParameters, type RemoteInstance, type RemoteModuleRef, type ReplyOf, type StateTopic, type StateTopicDef, type StudioIntentUrl, type StudioUrl, type StudioWorkspaceUrl, DashboardTokenRefreshProvider as TokenRefreshProvider, type TopicData, type TopicEmitter, TopicError, type TopicName, type TopicResult, type Topics, type Urls, type ValueOf, capabilities, connectMessageBus };
|
|
798
|
+
export { type AgentResourceContextOptions, type ApplicationConfig, type ApplicationConfigAppType, type ApplicationConfigSelector, type CanvasUrl, type Capability, type CapabilityRecord, type ConnectMessageBusOptions, type CoreApplicationUrl, type CreateIntentParameters, type CreateRemoteInstanceOptions, type DashboardApplication, type DashboardNavigation, type DashboardTopics, type DashboardUrl, type DashboardView, type DashboardWebWorker, type EditIntentParameters, type EventTopic, type EventTopicDef, type FederationRemote, type MediaLibraryUrl, type MessageBus, type MessageBusAbortOptions, type MessageBusClient, type MessageBusConnection, type MessageBusEmitOptions, type MessageBusEmitResult, MessageBusError, type MessageBusErrorCode, type MessageBusHost, type MessageBusMessage, type MessageBusMeta, type MessageBusQueryOptions, type MessageBusStateSource, type NavigateToDashboardPath, type NavigateToStudioResult, type NavigationLocation, type NavigationTarget, type PayloadOf, type ReleaseIntentParameters, type RemoteInstance, type RemoteModuleRef, type ReplyOf, type StateTopic, type StateTopicDef, type StudioIntentUrl, type StudioUrl, type StudioWorkspaceUrl, DashboardTokenRefreshProvider as TokenRefreshProvider, type TopicData, type TopicEmitter, TopicError, type TopicName, type TopicResult, type Topics, type Urls, type ValueOf, capabilities, connectMessageBus };
|
|
777
799
|
//# sourceMappingURL=dashboard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard.d.ts","names":[],"sources":["../../src/context/DashboardTokenRefresh.tsx","../../src/dashboard/createRemoteInstance.ts","../../src/dashboard/urlFor.ts","../../src/hooks/dashboard/useAgentResourceContext.ts","../../src/hooks/dashboard/useApplications.ts","../../src/hooks/dashboard/useApplication.ts","../../src/hooks/dashboard/useApplicationBasePath.ts","../../src/hooks/dashboard/useApplicationConfig.ts","../../src/hooks/dashboard/useApplicationConfigs.ts","../../src/hooks/dashboard/useApplicationForegroundId.ts","../../src/hooks/dashboard/useAuthToken.ts","../../src/hooks/dashboard/useCapabilities.ts","../../src/hooks/dashboard/useCurrentUser.ts","../../src/hooks/dashboard/useEmit.ts","../../src/hooks/dashboard/useNavigate.ts","../../src/hooks/dashboard/useNavigateToStudioDocument.ts","../../src/hooks/dashboard/useOrganizationId.tsx","../../src/hooks/dashboard/useRemoteClient.ts","../../src/hooks/dashboard/useTopic.ts","../../src/hooks/dashboard/useWindowTitle.ts"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"dashboard.d.ts","names":[],"sources":["../../src/context/DashboardTokenRefresh.tsx","../../src/dashboard/createRemoteInstance.ts","../../src/dashboard/urlFor.ts","../../src/hooks/dashboard/useAgentResourceContext.ts","../../src/hooks/dashboard/useApplications.ts","../../src/hooks/dashboard/useApplication.ts","../../src/hooks/dashboard/useApplicationBasePath.ts","../../src/hooks/dashboard/useApplicationConfig.ts","../../src/hooks/dashboard/useApplicationConfigs.ts","../../src/hooks/dashboard/useApplicationForegroundId.ts","../../src/hooks/dashboard/useAuthToken.ts","../../src/hooks/dashboard/useCapabilities.ts","../../src/hooks/dashboard/useCurrentUser.ts","../../src/hooks/dashboard/useEmit.ts","../../src/hooks/dashboard/useNavigate.ts","../../src/hooks/dashboard/useNavigateToStudioDocument.ts","../../src/hooks/dashboard/useOrganizationId.tsx","../../src/hooks/dashboard/useRemoteClient.ts","../../src/hooks/dashboard/useTopic.ts","../../src/hooks/dashboard/useWindowTitle.ts"],"mappings":"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"}
|
|
@@ -2,11 +2,11 @@ import { a as useWindowConnection, c as useSanityInstance, i as DashboardTokenRe
|
|
|
2
2
|
import { c } from "react-compiler-runtime";
|
|
3
3
|
import "@sanity/sdk";
|
|
4
4
|
import { createLogger, getApplicationOrigin, isDashboardEnvironment, requireDashboardMessageBus } from "@sanity/sdk/_internal";
|
|
5
|
-
import { useEffect, useRef, useState } from "react";
|
|
5
|
+
import { useCallback, useEffect, useEffectEvent, useRef, useState } from "react";
|
|
6
6
|
import { SDK_CHANNEL_NAME, SDK_NODE_NAME } from "@sanity/message-protocol";
|
|
7
7
|
import "@sanity/sdk/comlink";
|
|
8
|
-
import { of } from "rxjs";
|
|
9
|
-
import { MessageBusError, TopicError, capabilities, connectMessageBus } from "@sanity/sdk/dashboard";
|
|
8
|
+
import { filter, map, of, pairwise } from "rxjs";
|
|
9
|
+
import { MessageBusError, TopicError, TopicError as TopicError$1, capabilities, connectMessageBus } from "@sanity/sdk/dashboard";
|
|
10
10
|
import "@sanity/types";
|
|
11
11
|
import { createInstance } from "@module-federation/runtime";
|
|
12
12
|
import "@module-federation/runtime/types";
|
|
@@ -723,54 +723,140 @@ function useEmit(topic) {
|
|
|
723
723
|
* @public
|
|
724
724
|
*
|
|
725
725
|
* A helper hook designed to be injected into routing components for apps within the Dashboard.
|
|
726
|
-
*
|
|
727
|
-
*
|
|
728
|
-
*
|
|
729
|
-
*
|
|
730
|
-
*
|
|
731
|
-
*
|
|
732
|
-
*
|
|
733
|
-
*
|
|
726
|
+
* It keeps the app's router and the Dashboard in two-way sync: `navigateFn` receives the
|
|
727
|
+
* navigations the Dashboard asks the app to perform, and the returned function reports the app's
|
|
728
|
+
* own in-app navigations back to the Dashboard so the browser URL and the Dashboard's router
|
|
729
|
+
* follow along.
|
|
730
|
+
*
|
|
731
|
+
* A navigation the app reports is not echoed back through `navigateFn`. The returned function is
|
|
732
|
+
* referentially stable.
|
|
733
|
+
*
|
|
734
|
+
* The two Dashboard runtimes differ:
|
|
735
|
+
* - In an iframe (Comlink), inbound `type` may be `'push'`, `'replace'` or `'pop'`. Reporting is
|
|
736
|
+
* optional because the bridge already forwards the iframe's own `pushState`; a reported `type`
|
|
737
|
+
* is ignored and the host applies the URL as a `replace`.
|
|
738
|
+
* - In a federated app (message bus), inbound `type` is `'push'` or `'replace'`; `'pop'` is never
|
|
739
|
+
* sent. Reporting is required because the app's router does not reach the host, and `type` is
|
|
740
|
+
* honoured. Until the Dashboard publishes the app's base path, reports are dropped with a
|
|
741
|
+
* console warning.
|
|
734
742
|
*
|
|
735
743
|
* @param navigateFn - Function to handle navigation; should accept:
|
|
736
744
|
* - `path`: a string, which will be a relative path (for example, 'my-route')
|
|
737
745
|
* - `type`: 'push', 'replace', or 'pop', which will be the type of navigation to perform
|
|
746
|
+
* @returns A function the app calls to report its own in-app navigations to the Dashboard.
|
|
738
747
|
*
|
|
739
748
|
* @example
|
|
740
749
|
* ```tsx
|
|
741
750
|
* import {useNavigate} from '@sanity/sdk-react/dashboard'
|
|
742
|
-
* import {
|
|
743
|
-
* import {
|
|
744
|
-
*
|
|
745
|
-
* function
|
|
746
|
-
* const
|
|
747
|
-
*
|
|
748
|
-
*
|
|
751
|
+
* import {useEffect} from 'react'
|
|
752
|
+
* import {useLocation, useNavigate as useRouterNavigate} from 'react-router'
|
|
753
|
+
*
|
|
754
|
+
* function DashboardNavigationSync() {
|
|
755
|
+
* const routerNavigate = useRouterNavigate()
|
|
756
|
+
* const {pathname, search, hash} = useLocation()
|
|
757
|
+
* const navigate = useNavigate(({path, type}) => {
|
|
758
|
+
* routerNavigate(path, {replace: type === 'replace'})
|
|
749
759
|
* })
|
|
760
|
+
* useEffect(() => {
|
|
761
|
+
* navigate({path: `${pathname.slice(1)}${search}${hash}`})
|
|
762
|
+
* }, [navigate, pathname, search, hash])
|
|
750
763
|
* return null
|
|
751
764
|
* }
|
|
752
|
-
*
|
|
753
|
-
* // Wrap the component with Suspense since the hook may suspend
|
|
754
|
-
* function MyApp() {
|
|
755
|
-
* return (
|
|
756
|
-
* <BrowserRouter>
|
|
757
|
-
* <Suspense>
|
|
758
|
-
* <DashboardNavigationHandler />
|
|
759
|
-
* </Suspense>
|
|
760
|
-
* </BrowserRouter>
|
|
761
|
-
* )
|
|
762
|
-
* }
|
|
763
765
|
* ```
|
|
764
766
|
*/
|
|
765
767
|
function useNavigate(navigateFn) {
|
|
766
|
-
|
|
768
|
+
return isDashboardEnvironment() ? useBusNavigate(navigateFn) : useComlinkNavigate(navigateFn);
|
|
769
|
+
}
|
|
770
|
+
function useComlinkNavigate(navigateFn) {
|
|
771
|
+
let $ = c(4), t0;
|
|
767
772
|
$[0] === navigateFn ? t0 = $[1] : (t0 = {
|
|
768
773
|
name: SDK_NODE_NAME,
|
|
769
774
|
connectTo: SDK_CHANNEL_NAME,
|
|
770
775
|
onMessage: { "dashboard/v1/history/change-path": (data) => {
|
|
771
776
|
navigateFn(data);
|
|
772
777
|
} }
|
|
773
|
-
}, $[0] = navigateFn, $[1] = t0)
|
|
778
|
+
}, $[0] = navigateFn, $[1] = t0);
|
|
779
|
+
let { sendMessage } = useWindowConnection(t0), t1;
|
|
780
|
+
return $[2] === sendMessage ? t1 = $[3] : (t1 = (t2) => {
|
|
781
|
+
let { path } = t2;
|
|
782
|
+
return sendMessage("dashboard/v1/bridge/listeners/history/update-url", { url: new URL(path, window.location.origin).href });
|
|
783
|
+
}, $[2] = sendMessage, $[3] = t1), t1;
|
|
784
|
+
}
|
|
785
|
+
function joinPath(base, path) {
|
|
786
|
+
let root = base.replace(/\/$/, "");
|
|
787
|
+
return path ? `${root}/${path}` : root;
|
|
788
|
+
}
|
|
789
|
+
function useBusNavigate(navigateFn) {
|
|
790
|
+
let $ = c(9), instance = useSanityInstance(), t0;
|
|
791
|
+
$[0] === instance ? t0 = $[1] : (t0 = requireDashboardMessageBus(instance, "navigate"), $[0] = instance, $[1] = t0);
|
|
792
|
+
let bus = t0, navigate = useEffectEvent(navigateFn), ownRequest = useRef(null), t1;
|
|
793
|
+
$[2] !== bus || $[3] !== navigate ? (t1 = () => {
|
|
794
|
+
let sub = bus.subscribe("navigation.location").pipe(pairwise(), filter((pair) => {
|
|
795
|
+
let [prev, curr] = pair;
|
|
796
|
+
return curr?.transition === null && curr.appId === bus.appId && prev?.transition?.to.appId === bus.appId && prev.transition.to.path === curr.path;
|
|
797
|
+
}), filter((t2) => {
|
|
798
|
+
let [, curr_0] = t2, suppress = curr_0.path === ownRequest.current;
|
|
799
|
+
return ownRequest.current = null, !suppress;
|
|
800
|
+
}), map(_temp$1)).subscribe((change) => navigate(change));
|
|
801
|
+
return () => sub.unsubscribe();
|
|
802
|
+
}, $[2] = bus, $[3] = navigate, $[4] = t1) : t1 = $[4];
|
|
803
|
+
let t2;
|
|
804
|
+
$[5] === bus ? t2 = $[6] : (t2 = [bus], $[5] = bus, $[6] = t2), useEffect(t1, t2);
|
|
805
|
+
let t3;
|
|
806
|
+
return $[7] === bus ? t3 = $[8] : (t3 = (t4) => {
|
|
807
|
+
let { path, type: t5 } = t4, type = t5 === void 0 ? "push" : t5, own = path.replace(/^\//, "");
|
|
808
|
+
ownRequest.current = own;
|
|
809
|
+
let clearIfStale = () => {
|
|
810
|
+
ownRequest.current === own && (ownRequest.current = null);
|
|
811
|
+
};
|
|
812
|
+
bus.query("applications.base-path").then((base) => {
|
|
813
|
+
if (!base.ok) throw new TopicError$1("applications.base-path");
|
|
814
|
+
return bus.emit("navigation.location.update", {
|
|
815
|
+
url: joinPath(base.value, own),
|
|
816
|
+
history: type
|
|
817
|
+
});
|
|
818
|
+
}).then((reply) => {
|
|
819
|
+
reply.ok || clearIfStale();
|
|
820
|
+
}, (error) => {
|
|
821
|
+
console.warn("Failed to report navigation to the Dashboard", error), clearIfStale();
|
|
822
|
+
});
|
|
823
|
+
}, $[7] = bus, $[8] = t3), t3;
|
|
824
|
+
}
|
|
825
|
+
function _temp$1(t0) {
|
|
826
|
+
let [prev_0, curr_1] = t0;
|
|
827
|
+
return {
|
|
828
|
+
path: curr_1.path,
|
|
829
|
+
type: prev_0.transition.navigationType
|
|
830
|
+
};
|
|
831
|
+
}
|
|
832
|
+
function useComlinkStudioNavigator(documentHandle) {
|
|
833
|
+
let $ = c(5), t0;
|
|
834
|
+
$[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = {
|
|
835
|
+
name: SDK_NODE_NAME,
|
|
836
|
+
connectTo: SDK_CHANNEL_NAME
|
|
837
|
+
}, $[0] = t0) : t0 = $[0];
|
|
838
|
+
let { sendMessage } = useWindowConnection(t0), t1;
|
|
839
|
+
return $[1] !== documentHandle.documentId || $[2] !== documentHandle.documentType || $[3] !== sendMessage ? (t1 = (workspace) => {
|
|
840
|
+
let message = {
|
|
841
|
+
type: "dashboard/v1/bridge/navigate-to-resource",
|
|
842
|
+
data: {
|
|
843
|
+
resourceId: workspace.id,
|
|
844
|
+
resourceType: "studio",
|
|
845
|
+
path: `/intent/edit/id=${documentHandle.documentId};type=${documentHandle.documentType}`
|
|
846
|
+
}
|
|
847
|
+
};
|
|
848
|
+
sendMessage(message.type, message.data);
|
|
849
|
+
}, $[1] = documentHandle.documentId, $[2] = documentHandle.documentType, $[3] = sendMessage, $[4] = t1) : t1 = $[4], t1;
|
|
850
|
+
}
|
|
851
|
+
function useBusStudioNavigator(documentHandle) {
|
|
852
|
+
let $ = c(4), navigate = useEmit("navigation.location.update"), t0;
|
|
853
|
+
return $[0] !== documentHandle.documentId || $[1] !== documentHandle.documentType || $[2] !== navigate ? (t0 = (workspace) => {
|
|
854
|
+
let url = urlFor.studios(workspace.userApplicationId).workspace(workspace.name).intent("edit", {
|
|
855
|
+
id: documentHandle.documentId,
|
|
856
|
+
type: documentHandle.documentType
|
|
857
|
+
}).url();
|
|
858
|
+
navigate({ url }).then(_temp, _temp2);
|
|
859
|
+
}, $[0] = documentHandle.documentId, $[1] = documentHandle.documentType, $[2] = navigate, $[3] = t0) : t0 = $[3], t0;
|
|
774
860
|
}
|
|
775
861
|
/**
|
|
776
862
|
* @public
|
|
@@ -780,6 +866,9 @@ function useNavigate(navigateFn) {
|
|
|
780
866
|
* Uses the `projectId` and `dataset` properties of the {@link DocumentHandle} you provide to resolve the correct Studio.
|
|
781
867
|
* This will only work if you have deployed a studio with a workspace with this `projectId` / `dataset` combination.
|
|
782
868
|
*
|
|
869
|
+
* Works in both Dashboard runtimes: it sends the navigation over the Comlink connection in the
|
|
870
|
+
* iframe runtime and over the message bus in the federated runtime.
|
|
871
|
+
*
|
|
783
872
|
* @remarks If you write your own Document Handle to pass to this hook (as opposed to a Document Handle generated by another hook),
|
|
784
873
|
* it must include values for `documentId`, `documentType`, `projectId`, and `dataset`.
|
|
785
874
|
*
|
|
@@ -817,41 +906,38 @@ function useNavigate(navigateFn) {
|
|
|
817
906
|
* }
|
|
818
907
|
* ```
|
|
819
908
|
*/
|
|
909
|
+
function _temp2(error) {
|
|
910
|
+
console.warn("Failed to navigate to studio document", error);
|
|
911
|
+
}
|
|
912
|
+
function _temp(reply) {
|
|
913
|
+
reply.ok === !1 && console.warn("Failed to navigate to studio document", reply);
|
|
914
|
+
}
|
|
820
915
|
function useNavigateToStudioDocument(documentHandle, preferredStudioUrl) {
|
|
821
|
-
let
|
|
822
|
-
|
|
823
|
-
name: SDK_NODE_NAME,
|
|
824
|
-
connectTo: SDK_CHANNEL_NAME
|
|
825
|
-
}, $[0] = t0) : t0 = $[0];
|
|
826
|
-
let { sendMessage } = useWindowConnection(t0), t1;
|
|
827
|
-
$[1] !== documentHandle || $[2] !== preferredStudioUrl || $[3] !== sendMessage || $[4] !== workspacesByProjectIdAndDataset ? (t1 = () => {
|
|
916
|
+
let { workspacesByProjectIdAndDataset } = useStudioWorkspacesByProjectIdDataset(), sendToWorkspace = isDashboardEnvironment() ? useBusStudioNavigator(documentHandle) : useComlinkStudioNavigator(documentHandle);
|
|
917
|
+
return { navigateToStudioDocument: useCallback(() => {
|
|
828
918
|
let { projectId, dataset } = documentHandle;
|
|
829
919
|
if (!projectId || !dataset) {
|
|
830
920
|
console.warn("Project ID and dataset are required to navigate to a studio document");
|
|
831
921
|
return;
|
|
832
922
|
}
|
|
833
|
-
let workspace;
|
|
834
|
-
if (preferredStudioUrl) workspace = [...workspacesByProjectIdAndDataset[`${projectId}:${dataset}`] || [], ...workspacesByProjectIdAndDataset["NO_PROJECT_ID:NO_DATASET"] || []].find((w) => w.url === preferredStudioUrl);
|
|
835
|
-
else {
|
|
836
|
-
let workspaces = workspacesByProjectIdAndDataset[`${projectId}:${dataset}`];
|
|
837
|
-
workspaces?.length > 1 && (console.warn("Multiple workspaces found for document and no preferred studio url", documentHandle), console.warn("Using the first one", workspaces[0])), workspace = workspaces?.[0];
|
|
838
|
-
}
|
|
923
|
+
let workspace = resolveWorkspace(documentHandle, workspacesByProjectIdAndDataset, preferredStudioUrl);
|
|
839
924
|
if (!workspace) {
|
|
840
925
|
console.warn(`No workspace found for document with projectId: ${projectId} and dataset: ${dataset}${preferredStudioUrl ? ` or with preferred studio url: ${preferredStudioUrl}` : ""}`);
|
|
841
926
|
return;
|
|
842
927
|
}
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
928
|
+
sendToWorkspace(workspace);
|
|
929
|
+
}, [
|
|
930
|
+
documentHandle,
|
|
931
|
+
workspacesByProjectIdAndDataset,
|
|
932
|
+
preferredStudioUrl,
|
|
933
|
+
sendToWorkspace
|
|
934
|
+
]) };
|
|
935
|
+
}
|
|
936
|
+
function resolveWorkspace(documentHandle, workspacesByProjectIdAndDataset, preferredStudioUrl) {
|
|
937
|
+
let { projectId, dataset } = documentHandle, key = `${projectId}:${dataset}`;
|
|
938
|
+
if (preferredStudioUrl) return [...workspacesByProjectIdAndDataset[key] || [], ...workspacesByProjectIdAndDataset["NO_PROJECT_ID:NO_DATASET"] || []].find((w) => w.url === preferredStudioUrl);
|
|
939
|
+
let workspaces = workspacesByProjectIdAndDataset[key];
|
|
940
|
+
return workspaces && workspaces.length > 1 && (console.warn("Multiple workspaces found for document and no preferred studio url", documentHandle), console.warn("Using the first one", workspaces[0])), workspaces?.[0];
|
|
855
941
|
}
|
|
856
942
|
const remoteClientStates = /* @__PURE__ */ new WeakMap();
|
|
857
943
|
/** Returns the instance's remote client state, creating it on first use. @internal */
|