@sanity/sdk-react 3.4.0-rc.0 → 3.5.0-next.20260922182803
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 +151 -45
- package/dist/_exports/dashboard.d.ts.map +1 -1
- package/dist/_exports/dashboard.js +267 -125
- package/dist/_exports/dashboard.js.map +1 -1
- package/dist/index.d.ts +21 -141
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +66 -147
- package/dist/index.js.map +1 -1
- package/dist/{useStudioWorkspacesByProjectIdDataset-B5A5kBH9.js → useStudioWorkspacesByProjectIdDataset-DL6_9jgU.js} +61 -4
- package/dist/useStudioWorkspacesByProjectIdDataset-DL6_9jgU.js.map +1 -0
- package/package.json +9 -9
- package/src/_exports/dashboard.test-d.ts +3 -0
- package/src/_exports/dashboard.ts +13 -2
- package/src/_exports/sdk-react.ts +0 -3
- package/src/components/auth/AuthBoundary.test.tsx +2 -81
- package/src/components/auth/AuthBoundary.tsx +3 -17
- package/src/components/auth/LoginCallback.test.tsx +7 -46
- package/src/components/auth/LoginCallback.tsx +4 -22
- package/src/hooks/dashboard/useAgentResourceContext.test.tsx +67 -2
- package/src/hooks/dashboard/useAgentResourceContext.ts +35 -6
- package/src/hooks/dashboard/useApplicationContext.test.tsx +95 -0
- package/src/hooks/dashboard/useApplicationContext.ts +47 -0
- package/src/hooks/dashboard/useApplications.test.tsx +165 -7
- package/src/hooks/dashboard/useApplications.ts +112 -28
- package/src/hooks/dashboard/useCapabilities.test.tsx +84 -0
- package/src/hooks/dashboard/useCapabilities.ts +27 -0
- 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
- package/src/hooks/dashboard/useRecordDocumentHistoryEvent.test.ts +99 -1
- package/src/hooks/dashboard/useRecordDocumentHistoryEvent.ts +73 -2
- package/src/hooks/dashboard/useStudioWorkspacesByProjectIdDataset.test.tsx +23 -1
- package/src/hooks/dashboard/useStudioWorkspacesByProjectIdDataset.ts +2 -1
- package/dist/useStudioWorkspacesByProjectIdDataset-B5A5kBH9.js.map +0 -1
- package/src/hooks/auth/useHandleOAuthCallback.test.tsx +0 -16
- package/src/hooks/auth/useHandleOAuthCallback.tsx +0 -49
- package/src/hooks/auth/useOAuthAuthorize.test.tsx +0 -16
- package/src/hooks/auth/useOAuthAuthorize.tsx +0 -28
- package/src/hooks/auth/useOAuthTokens.test.tsx +0 -240
- package/src/hooks/auth/useOAuthTokens.tsx +0 -95
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as DashboardTokenRefreshProvider, c as createStateSourceHook, i as useOrganizationId, l as useSanityInstance, n as useTopic, o as useWindowConnection, r as useEmit, t as useStudioWorkspacesByProjectIdDataset } from "../useStudioWorkspacesByProjectIdDataset-DL6_9jgU.js";
|
|
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, 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";
|
|
@@ -382,13 +382,53 @@ const createRootBuilder = (Builder, ...segments) => new Builder(appendSegments(n
|
|
|
382
382
|
return Object.assign(urls, methods);
|
|
383
383
|
}, urlFor = createUrls({});
|
|
384
384
|
/**
|
|
385
|
+
* Publishes what this application is currently showing to the Dashboard message bus, so the host
|
|
386
|
+
* can hold the foreground application's context. Pass `null` when nothing is open.
|
|
387
|
+
*
|
|
388
|
+
* The context is published on mount and whenever it changes, and cleared with `null` on unmount.
|
|
389
|
+
* A change publishes `null` before the new context, as the component has stopped showing the old
|
|
390
|
+
* one. Pass a memoised value: the hook compares by reference, so a new object on every render
|
|
391
|
+
* republishes on every render.
|
|
392
|
+
*
|
|
393
|
+
* The host reads the sending application from `message.meta.appId`, so the payload carries no
|
|
394
|
+
* application ID.
|
|
395
|
+
*
|
|
396
|
+
* @param context - The application context to publish, or `null` to clear it
|
|
397
|
+
*
|
|
398
|
+
* @example
|
|
399
|
+
* ```tsx
|
|
400
|
+
* import {useApplicationContext} from '@sanity/sdk-react/dashboard'
|
|
401
|
+
* import {useMemo} from 'react'
|
|
402
|
+
*
|
|
403
|
+
* function DocumentView({documentId}: {documentId: string}) {
|
|
404
|
+
* const context = useMemo(
|
|
405
|
+
* () => ({resource: {id: 'my-project.production', type: 'dataset' as const}, document: {id: documentId}}),
|
|
406
|
+
* [documentId],
|
|
407
|
+
* )
|
|
408
|
+
* useApplicationContext(context)
|
|
409
|
+
* return <div>Editing {documentId}</div>
|
|
410
|
+
* }
|
|
411
|
+
* ```
|
|
412
|
+
*
|
|
385
413
|
* @public
|
|
386
|
-
*
|
|
387
|
-
|
|
388
|
-
|
|
414
|
+
* @category Dashboard
|
|
415
|
+
*/
|
|
416
|
+
function useApplicationContext(context) {
|
|
417
|
+
let $ = c(4), emit = useEmit("applications.context.update"), t0, t1;
|
|
418
|
+
$[0] !== context || $[1] !== emit ? (t0 = () => (emit(context), () => {
|
|
419
|
+
emit(null);
|
|
420
|
+
}), t1 = [emit, context], $[0] = context, $[1] = emit, $[2] = t0, $[3] = t1) : (t0 = $[2], t1 = $[3]), useEffect(t0, t1);
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* @public
|
|
424
|
+
* Hook for reporting the resource the user is currently interacting with (for example, which
|
|
425
|
+
* document they're editing) so the Agent can understand their context. The hook reports on mount
|
|
426
|
+
* and again whenever the context changes.
|
|
389
427
|
*
|
|
390
|
-
* The
|
|
391
|
-
*
|
|
428
|
+
* The two Dashboard runtimes differ in transport, but the signature is the same:
|
|
429
|
+
* - In an iframe (Comlink), it emits the `dashboard/v1/events/agent/resource/update` event.
|
|
430
|
+
* - In a federated app (message bus), it publishes {@link useApplicationContext}'s
|
|
431
|
+
* `applications.context.update` topic. Reach for `useApplicationContext` directly in new code.
|
|
392
432
|
*
|
|
393
433
|
* @category Agent
|
|
394
434
|
* @param options - The resource context options containing projectId, dataset, and optional documentId
|
|
@@ -412,6 +452,19 @@ const createRootBuilder = (Builder, ...segments) => new Builder(appendSegments(n
|
|
|
412
452
|
* ```
|
|
413
453
|
*/
|
|
414
454
|
function useAgentResourceContext(options) {
|
|
455
|
+
return isDashboardEnvironment() ? useBusAgentResourceContext(options) : useComlinkAgentResourceContext(options);
|
|
456
|
+
}
|
|
457
|
+
function useBusAgentResourceContext(t0) {
|
|
458
|
+
let $ = c(4), { projectId, dataset, documentId } = t0, t1;
|
|
459
|
+
$[0] !== dataset || $[1] !== documentId || $[2] !== projectId ? (t1 = projectId && dataset ? {
|
|
460
|
+
resource: {
|
|
461
|
+
id: `${projectId}.${dataset}`,
|
|
462
|
+
type: "dataset"
|
|
463
|
+
},
|
|
464
|
+
document: documentId ? { id: documentId } : null
|
|
465
|
+
} : null, $[0] = dataset, $[1] = documentId, $[2] = projectId, $[3] = t1) : t1 = $[3], useApplicationContext(t1);
|
|
466
|
+
}
|
|
467
|
+
function useComlinkAgentResourceContext(options) {
|
|
415
468
|
let $ = c(9), { projectId, dataset, documentId } = options, t0;
|
|
416
469
|
$[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = {
|
|
417
470
|
name: SDK_NODE_NAME,
|
|
@@ -446,10 +499,9 @@ function useAgentResourceContext(options) {
|
|
|
446
499
|
updateContext();
|
|
447
500
|
}, t3 = [updateContext], $[6] = updateContext, $[7] = t2, $[8] = t3), useEffect(t2, t3);
|
|
448
501
|
}
|
|
449
|
-
const loadableInterfaces = ({ activeDeployment, config }) => config?.mfManifest
|
|
450
|
-
let
|
|
502
|
+
const loadableInterfaces = ({ activeDeployment, config }, isLocal) => isLocal || config?.mfManifest !== void 0 ? activeDeployment?.interfaces ?? [] : [], loadModules = (base, interfaces) => {
|
|
503
|
+
let entry = interfaces.length === 0 ? null : getApplicationOrigin(base);
|
|
451
504
|
if (entry === null) return {
|
|
452
|
-
...application,
|
|
453
505
|
views: [],
|
|
454
506
|
webWorkers: []
|
|
455
507
|
};
|
|
@@ -457,13 +509,13 @@ const loadableInterfaces = ({ activeDeployment, config }) => config?.mfManifest
|
|
|
457
509
|
for (let extension of interfaces) {
|
|
458
510
|
let module = {
|
|
459
511
|
entry,
|
|
460
|
-
moduleId: `${
|
|
512
|
+
moduleId: `${base.id}/${extension.moduleId}`,
|
|
461
513
|
version: extension.version
|
|
462
514
|
};
|
|
463
515
|
if (extension.type === "worker") {
|
|
464
516
|
webWorkers.push({
|
|
465
517
|
...extension,
|
|
466
|
-
application:
|
|
518
|
+
application: base,
|
|
467
519
|
module
|
|
468
520
|
});
|
|
469
521
|
continue;
|
|
@@ -471,22 +523,57 @@ const loadableInterfaces = ({ activeDeployment, config }) => config?.mfManifest
|
|
|
471
523
|
let { type, ...view } = extension;
|
|
472
524
|
views.push({
|
|
473
525
|
...view,
|
|
474
|
-
application:
|
|
526
|
+
application: base,
|
|
475
527
|
module,
|
|
476
528
|
surface: type === "app" ? "window" : type
|
|
477
529
|
});
|
|
478
530
|
}
|
|
479
531
|
return {
|
|
480
|
-
...application,
|
|
481
532
|
views,
|
|
482
533
|
webWorkers
|
|
483
534
|
};
|
|
535
|
+
}, toApplication = (application) => {
|
|
536
|
+
let { activeDeployment: _activeDeployment, config: _config, ...applicationBase } = application, isLocal = "local" in application;
|
|
537
|
+
return {
|
|
538
|
+
...application,
|
|
539
|
+
isLocal,
|
|
540
|
+
...loadModules({
|
|
541
|
+
...applicationBase,
|
|
542
|
+
isLocal
|
|
543
|
+
}, loadableInterfaces(application, isLocal))
|
|
544
|
+
};
|
|
545
|
+
}, toInstallation = (installation) => {
|
|
546
|
+
let { application } = installation, base = {
|
|
547
|
+
id: installation.id,
|
|
548
|
+
type: "installation",
|
|
549
|
+
isLocal: !1,
|
|
550
|
+
title: application.title,
|
|
551
|
+
name: application.name,
|
|
552
|
+
reference: application.reference,
|
|
553
|
+
icon: application.icon,
|
|
554
|
+
isSingleton: !0,
|
|
555
|
+
visibility: "default",
|
|
556
|
+
slug: application.slug,
|
|
557
|
+
externalUrl: null,
|
|
558
|
+
organizationId: application.organizationId,
|
|
559
|
+
createdAt: installation.createdAt,
|
|
560
|
+
updatedAt: installation.updatedAt
|
|
561
|
+
};
|
|
562
|
+
return {
|
|
563
|
+
...base,
|
|
564
|
+
type: "installation",
|
|
565
|
+
installation,
|
|
566
|
+
...loadModules(base, installation.interfaces ?? [])
|
|
567
|
+
};
|
|
484
568
|
};
|
|
485
569
|
/**
|
|
486
|
-
* Returns the applications available in the dashboard.
|
|
570
|
+
* Returns the applications and installations available in the dashboard, in one consistent shape.
|
|
487
571
|
*
|
|
488
|
-
* Suspends until the dashboard publishes its
|
|
489
|
-
*
|
|
572
|
+
* Suspends until the dashboard publishes its list; a cleared list is empty. Throws a `TopicError`
|
|
573
|
+
* to the nearest error boundary when the dashboard fails to load. Every entry exposes the same base
|
|
574
|
+
* fields plus `views` and `webWorkers`; `type` distinguishes applications (`'studio' | 'coreApp'`)
|
|
575
|
+
* from installations (`'installation'`), which also carry the raw record under `installation`.
|
|
576
|
+
* `isLocal` marks applications served by a CLI dev server.
|
|
490
577
|
*
|
|
491
578
|
* @example
|
|
492
579
|
* ```tsx
|
|
@@ -500,7 +587,10 @@ const loadableInterfaces = ({ activeDeployment, config }) => config?.mfManifest
|
|
|
500
587
|
*/
|
|
501
588
|
function useApplications() {
|
|
502
589
|
let $ = c(2), applications = useTopic("applications.list"), t0;
|
|
503
|
-
return $[0] === applications ? t0 = $[1] : (t0 = applications?.map(
|
|
590
|
+
return $[0] === applications ? t0 = $[1] : (t0 = applications?.map(_temp$2) ?? [], $[0] = applications, $[1] = t0), t0;
|
|
591
|
+
}
|
|
592
|
+
function _temp$2(entry) {
|
|
593
|
+
return "type" in entry ? toApplication(entry) : toInstallation(entry);
|
|
504
594
|
}
|
|
505
595
|
/**
|
|
506
596
|
* Returns a dashboard application by id, or `null` when it is unavailable.
|
|
@@ -622,132 +712,184 @@ function useAuthToken() {
|
|
|
622
712
|
return useTopic("auth.token");
|
|
623
713
|
}
|
|
624
714
|
/**
|
|
625
|
-
* Returns the
|
|
715
|
+
* Returns the capabilities the host provides.
|
|
626
716
|
*
|
|
627
|
-
*
|
|
717
|
+
* A capability is something the host provides; an application reads this record to hide its own
|
|
718
|
+
* implementation of anything the host provides, or to skip publishing to a capability the host
|
|
719
|
+
* does not have. A missing key means the host does not provide that capability.
|
|
720
|
+
*
|
|
721
|
+
* Suspends until the host publishes the record.
|
|
628
722
|
*
|
|
629
723
|
* @example
|
|
630
724
|
* ```tsx
|
|
631
|
-
* function
|
|
632
|
-
* const
|
|
633
|
-
*
|
|
725
|
+
* function UserMenu() {
|
|
726
|
+
* const {globalUserMenu} = useCapabilities()
|
|
727
|
+
* if (globalUserMenu) return null
|
|
728
|
+
* return <LocalUserMenu />
|
|
634
729
|
* }
|
|
635
730
|
* ```
|
|
636
731
|
*
|
|
637
732
|
* @public
|
|
638
733
|
*/
|
|
639
|
-
function
|
|
640
|
-
return useTopic("
|
|
734
|
+
function useCapabilities() {
|
|
735
|
+
return useTopic("applications.capabilities");
|
|
641
736
|
}
|
|
642
737
|
/**
|
|
643
|
-
* Returns
|
|
644
|
-
*
|
|
645
|
-
* The event is sent immediately. Ignore the lazy result for fire-and-forget delivery, await it
|
|
646
|
-
* inside `useTransition` to track a reply, or read it with React `use` to suspend. A reply
|
|
647
|
-
* that fails (`NO_RESPONDER`, `TIMEOUT`, `ABORTED`) rejects the result; when read with `use`
|
|
648
|
-
* that reaches the nearest error boundary, so pair the `Suspense` with one.
|
|
738
|
+
* Returns the signed-in user, or `null` while signed out.
|
|
649
739
|
*
|
|
650
|
-
*
|
|
651
|
-
* ```tsx
|
|
652
|
-
* function ExpandPanel() {
|
|
653
|
-
* const setPanelMode = useEmit('panels.mode.set')
|
|
654
|
-
* return (
|
|
655
|
-
* <button onClick={() => setPanelMode({name: 'favorites', mode: 'full'})}>
|
|
656
|
-
* Expand
|
|
657
|
-
* </button>
|
|
658
|
-
* )
|
|
659
|
-
* }
|
|
660
|
-
* ```
|
|
740
|
+
* Suspends until Dashboard publishes the current user.
|
|
661
741
|
*
|
|
662
|
-
* @example
|
|
742
|
+
* @example
|
|
663
743
|
* ```tsx
|
|
664
|
-
* function
|
|
665
|
-
*
|
|
666
|
-
* return <
|
|
667
|
-
* }
|
|
668
|
-
*
|
|
669
|
-
* function SessionAccordion() {
|
|
670
|
-
* const refreshToken = useEmit('auth.token.refresh')
|
|
671
|
-
* const [request, setRequest] = useState<MessageBusEmitResult<string> | null>(null)
|
|
672
|
-
*
|
|
673
|
-
* return (
|
|
674
|
-
* <details
|
|
675
|
-
* onToggle={(event) => setRequest(event.currentTarget.open ? refreshToken() : null)}
|
|
676
|
-
* >
|
|
677
|
-
* <summary>Session</summary>
|
|
678
|
-
* <ErrorBoundary fallback={<p>Could not refresh</p>}>
|
|
679
|
-
* <Suspense fallback={<p>Refreshing...</p>}>
|
|
680
|
-
* {request && <Session request={request} />}
|
|
681
|
-
* </Suspense>
|
|
682
|
-
* </ErrorBoundary>
|
|
683
|
-
* </details>
|
|
684
|
-
* )
|
|
744
|
+
* function CurrentUser() {
|
|
745
|
+
* const user = useCurrentUser()
|
|
746
|
+
* return <span>{user?.name ?? 'Signed out'}</span>
|
|
685
747
|
* }
|
|
686
748
|
* ```
|
|
687
749
|
*
|
|
688
750
|
* @public
|
|
689
751
|
*/
|
|
690
|
-
function
|
|
691
|
-
|
|
692
|
-
$[0] !== instance || $[1] !== t0 ? (t1 = requireDashboardMessageBus(instance, t0), $[0] = instance, $[1] = t0, $[2] = t1) : t1 = $[2];
|
|
693
|
-
let messageBus = t1, t2;
|
|
694
|
-
return $[3] !== messageBus || $[4] !== topic ? (t2 = (...t3) => {
|
|
695
|
-
let args = t3;
|
|
696
|
-
return messageBus.emit(topic, ...args);
|
|
697
|
-
}, $[3] = messageBus, $[4] = topic, $[5] = t2) : t2 = $[5], t2;
|
|
752
|
+
function useCurrentUser() {
|
|
753
|
+
return useTopic("users.current");
|
|
698
754
|
}
|
|
699
755
|
/**
|
|
700
756
|
* @public
|
|
701
757
|
*
|
|
702
758
|
* A helper hook designed to be injected into routing components for apps within the Dashboard.
|
|
703
|
-
*
|
|
704
|
-
*
|
|
759
|
+
* It keeps the app's router and the Dashboard in two-way sync: `navigateFn` receives the
|
|
760
|
+
* navigations the Dashboard asks the app to perform, and the returned function reports the app's
|
|
761
|
+
* own in-app navigations back to the Dashboard so the browser URL and the Dashboard's router
|
|
762
|
+
* follow along.
|
|
705
763
|
*
|
|
706
|
-
*
|
|
707
|
-
*
|
|
708
|
-
* there needs to be some way for the dashboard to signal to your application to reroute to where that document was favorited.
|
|
764
|
+
* A navigation the app reports is not echoed back through `navigateFn`. The returned function is
|
|
765
|
+
* referentially stable.
|
|
709
766
|
*
|
|
710
|
-
*
|
|
767
|
+
* The two Dashboard runtimes differ:
|
|
768
|
+
* - In an iframe (Comlink), inbound `type` may be `'push'`, `'replace'` or `'pop'`. Reporting is
|
|
769
|
+
* optional because the bridge already forwards the iframe's own `pushState`; a reported `type`
|
|
770
|
+
* is ignored and the host applies the URL as a `replace`.
|
|
771
|
+
* - In a federated app (message bus), inbound `type` is `'push'` or `'replace'`; `'pop'` is never
|
|
772
|
+
* sent. Reporting is required because the app's router does not reach the host, and `type` is
|
|
773
|
+
* honoured. Until the Dashboard publishes the app's base path, reports are dropped with a
|
|
774
|
+
* console warning.
|
|
711
775
|
*
|
|
712
776
|
* @param navigateFn - Function to handle navigation; should accept:
|
|
713
777
|
* - `path`: a string, which will be a relative path (for example, 'my-route')
|
|
714
778
|
* - `type`: 'push', 'replace', or 'pop', which will be the type of navigation to perform
|
|
779
|
+
* @returns A function the app calls to report its own in-app navigations to the Dashboard.
|
|
715
780
|
*
|
|
716
781
|
* @example
|
|
717
782
|
* ```tsx
|
|
718
783
|
* import {useNavigate} from '@sanity/sdk-react/dashboard'
|
|
719
|
-
* import {
|
|
720
|
-
* import {
|
|
784
|
+
* import {useEffect} from 'react'
|
|
785
|
+
* import {useLocation, useNavigate as useRouterNavigate} from 'react-router'
|
|
721
786
|
*
|
|
722
|
-
* function
|
|
723
|
-
* const
|
|
724
|
-
*
|
|
725
|
-
*
|
|
787
|
+
* function DashboardNavigationSync() {
|
|
788
|
+
* const routerNavigate = useRouterNavigate()
|
|
789
|
+
* const {pathname, search, hash} = useLocation()
|
|
790
|
+
* const navigate = useNavigate(({path, type}) => {
|
|
791
|
+
* routerNavigate(path, {replace: type === 'replace'})
|
|
726
792
|
* })
|
|
793
|
+
* useEffect(() => {
|
|
794
|
+
* navigate({path: `${pathname.slice(1)}${search}${hash}`})
|
|
795
|
+
* }, [navigate, pathname, search, hash])
|
|
727
796
|
* return null
|
|
728
797
|
* }
|
|
729
|
-
*
|
|
730
|
-
* // Wrap the component with Suspense since the hook may suspend
|
|
731
|
-
* function MyApp() {
|
|
732
|
-
* return (
|
|
733
|
-
* <BrowserRouter>
|
|
734
|
-
* <Suspense>
|
|
735
|
-
* <DashboardNavigationHandler />
|
|
736
|
-
* </Suspense>
|
|
737
|
-
* </BrowserRouter>
|
|
738
|
-
* )
|
|
739
|
-
* }
|
|
740
798
|
* ```
|
|
741
799
|
*/
|
|
742
800
|
function useNavigate(navigateFn) {
|
|
743
|
-
|
|
801
|
+
return isDashboardEnvironment() ? useBusNavigate(navigateFn) : useComlinkNavigate(navigateFn);
|
|
802
|
+
}
|
|
803
|
+
function useComlinkNavigate(navigateFn) {
|
|
804
|
+
let $ = c(4), t0;
|
|
744
805
|
$[0] === navigateFn ? t0 = $[1] : (t0 = {
|
|
745
806
|
name: SDK_NODE_NAME,
|
|
746
807
|
connectTo: SDK_CHANNEL_NAME,
|
|
747
808
|
onMessage: { "dashboard/v1/history/change-path": (data) => {
|
|
748
809
|
navigateFn(data);
|
|
749
810
|
} }
|
|
750
|
-
}, $[0] = navigateFn, $[1] = t0)
|
|
811
|
+
}, $[0] = navigateFn, $[1] = t0);
|
|
812
|
+
let { sendMessage } = useWindowConnection(t0), t1;
|
|
813
|
+
return $[2] === sendMessage ? t1 = $[3] : (t1 = (t2) => {
|
|
814
|
+
let { path } = t2;
|
|
815
|
+
return sendMessage("dashboard/v1/bridge/listeners/history/update-url", { url: new URL(path, window.location.origin).href });
|
|
816
|
+
}, $[2] = sendMessage, $[3] = t1), t1;
|
|
817
|
+
}
|
|
818
|
+
function joinPath(base, path) {
|
|
819
|
+
let root = base.replace(/\/$/, "");
|
|
820
|
+
return path ? `${root}/${path}` : root;
|
|
821
|
+
}
|
|
822
|
+
function useBusNavigate(navigateFn) {
|
|
823
|
+
let $ = c(9), instance = useSanityInstance(), t0;
|
|
824
|
+
$[0] === instance ? t0 = $[1] : (t0 = requireDashboardMessageBus(instance, "navigate"), $[0] = instance, $[1] = t0);
|
|
825
|
+
let bus = t0, navigate = useEffectEvent(navigateFn), ownRequest = useRef(null), t1;
|
|
826
|
+
$[2] !== bus || $[3] !== navigate ? (t1 = () => {
|
|
827
|
+
let sub = bus.subscribe("navigation.location").pipe(pairwise(), filter((pair) => {
|
|
828
|
+
let [prev, curr] = pair;
|
|
829
|
+
return curr?.transition === null && curr.appId === bus.appId && prev?.transition?.to.appId === bus.appId && prev.transition.to.path === curr.path;
|
|
830
|
+
}), filter((t2) => {
|
|
831
|
+
let [, curr_0] = t2, suppress = curr_0.path === ownRequest.current;
|
|
832
|
+
return ownRequest.current = null, !suppress;
|
|
833
|
+
}), map(_temp$1)).subscribe((change) => navigate(change));
|
|
834
|
+
return () => sub.unsubscribe();
|
|
835
|
+
}, $[2] = bus, $[3] = navigate, $[4] = t1) : t1 = $[4];
|
|
836
|
+
let t2;
|
|
837
|
+
$[5] === bus ? t2 = $[6] : (t2 = [bus], $[5] = bus, $[6] = t2), useEffect(t1, t2);
|
|
838
|
+
let t3;
|
|
839
|
+
return $[7] === bus ? t3 = $[8] : (t3 = (t4) => {
|
|
840
|
+
let { path, type: t5 } = t4, type = t5 === void 0 ? "push" : t5, own = path.replace(/^\//, "");
|
|
841
|
+
ownRequest.current = own;
|
|
842
|
+
let clearIfStale = () => {
|
|
843
|
+
ownRequest.current === own && (ownRequest.current = null);
|
|
844
|
+
};
|
|
845
|
+
bus.query("applications.base-path").then((base) => {
|
|
846
|
+
if (!base.ok) throw new TopicError$1("applications.base-path");
|
|
847
|
+
return bus.emit("navigation.location.update", {
|
|
848
|
+
url: joinPath(base.value, own),
|
|
849
|
+
history: type
|
|
850
|
+
});
|
|
851
|
+
}).then((reply) => {
|
|
852
|
+
reply.ok || clearIfStale();
|
|
853
|
+
}, (error) => {
|
|
854
|
+
console.warn("Failed to report navigation to the Dashboard", error), clearIfStale();
|
|
855
|
+
});
|
|
856
|
+
}, $[7] = bus, $[8] = t3), t3;
|
|
857
|
+
}
|
|
858
|
+
function _temp$1(t0) {
|
|
859
|
+
let [prev_0, curr_1] = t0;
|
|
860
|
+
return {
|
|
861
|
+
path: curr_1.path,
|
|
862
|
+
type: prev_0.transition.navigationType
|
|
863
|
+
};
|
|
864
|
+
}
|
|
865
|
+
function useComlinkStudioNavigator(documentHandle) {
|
|
866
|
+
let $ = c(5), t0;
|
|
867
|
+
$[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = {
|
|
868
|
+
name: SDK_NODE_NAME,
|
|
869
|
+
connectTo: SDK_CHANNEL_NAME
|
|
870
|
+
}, $[0] = t0) : t0 = $[0];
|
|
871
|
+
let { sendMessage } = useWindowConnection(t0), t1;
|
|
872
|
+
return $[1] !== documentHandle.documentId || $[2] !== documentHandle.documentType || $[3] !== sendMessage ? (t1 = (workspace) => {
|
|
873
|
+
let message = {
|
|
874
|
+
type: "dashboard/v1/bridge/navigate-to-resource",
|
|
875
|
+
data: {
|
|
876
|
+
resourceId: workspace.id,
|
|
877
|
+
resourceType: "studio",
|
|
878
|
+
path: `/intent/edit/id=${documentHandle.documentId};type=${documentHandle.documentType}`
|
|
879
|
+
}
|
|
880
|
+
};
|
|
881
|
+
sendMessage(message.type, message.data);
|
|
882
|
+
}, $[1] = documentHandle.documentId, $[2] = documentHandle.documentType, $[3] = sendMessage, $[4] = t1) : t1 = $[4], t1;
|
|
883
|
+
}
|
|
884
|
+
function useBusStudioNavigator(documentHandle) {
|
|
885
|
+
let $ = c(4), navigate = useEmit("navigation.location.update"), t0;
|
|
886
|
+
return $[0] !== documentHandle.documentId || $[1] !== documentHandle.documentType || $[2] !== navigate ? (t0 = (workspace) => {
|
|
887
|
+
let url = urlFor.studios(workspace.userApplicationId).workspace(workspace.name).intent("edit", {
|
|
888
|
+
id: documentHandle.documentId,
|
|
889
|
+
type: documentHandle.documentType
|
|
890
|
+
}).url();
|
|
891
|
+
navigate({ url }).then(_temp, _temp2);
|
|
892
|
+
}, $[0] = documentHandle.documentId, $[1] = documentHandle.documentType, $[2] = navigate, $[3] = t0) : t0 = $[3], t0;
|
|
751
893
|
}
|
|
752
894
|
/**
|
|
753
895
|
* @public
|
|
@@ -757,6 +899,9 @@ function useNavigate(navigateFn) {
|
|
|
757
899
|
* Uses the `projectId` and `dataset` properties of the {@link DocumentHandle} you provide to resolve the correct Studio.
|
|
758
900
|
* This will only work if you have deployed a studio with a workspace with this `projectId` / `dataset` combination.
|
|
759
901
|
*
|
|
902
|
+
* Works in both Dashboard runtimes: it sends the navigation over the Comlink connection in the
|
|
903
|
+
* iframe runtime and over the message bus in the federated runtime.
|
|
904
|
+
*
|
|
760
905
|
* @remarks If you write your own Document Handle to pass to this hook (as opposed to a Document Handle generated by another hook),
|
|
761
906
|
* it must include values for `documentId`, `documentType`, `projectId`, and `dataset`.
|
|
762
907
|
*
|
|
@@ -794,41 +939,38 @@ function useNavigate(navigateFn) {
|
|
|
794
939
|
* }
|
|
795
940
|
* ```
|
|
796
941
|
*/
|
|
942
|
+
function _temp2(error) {
|
|
943
|
+
console.warn("Failed to navigate to studio document", error);
|
|
944
|
+
}
|
|
945
|
+
function _temp(reply) {
|
|
946
|
+
reply.ok === !1 && console.warn("Failed to navigate to studio document", reply);
|
|
947
|
+
}
|
|
797
948
|
function useNavigateToStudioDocument(documentHandle, preferredStudioUrl) {
|
|
798
|
-
let
|
|
799
|
-
|
|
800
|
-
name: SDK_NODE_NAME,
|
|
801
|
-
connectTo: SDK_CHANNEL_NAME
|
|
802
|
-
}, $[0] = t0) : t0 = $[0];
|
|
803
|
-
let { sendMessage } = useWindowConnection(t0), t1;
|
|
804
|
-
$[1] !== documentHandle || $[2] !== preferredStudioUrl || $[3] !== sendMessage || $[4] !== workspacesByProjectIdAndDataset ? (t1 = () => {
|
|
949
|
+
let { workspacesByProjectIdAndDataset } = useStudioWorkspacesByProjectIdDataset(), sendToWorkspace = isDashboardEnvironment() ? useBusStudioNavigator(documentHandle) : useComlinkStudioNavigator(documentHandle);
|
|
950
|
+
return { navigateToStudioDocument: useCallback(() => {
|
|
805
951
|
let { projectId, dataset } = documentHandle;
|
|
806
952
|
if (!projectId || !dataset) {
|
|
807
953
|
console.warn("Project ID and dataset are required to navigate to a studio document");
|
|
808
954
|
return;
|
|
809
955
|
}
|
|
810
|
-
let workspace;
|
|
811
|
-
if (preferredStudioUrl) workspace = [...workspacesByProjectIdAndDataset[`${projectId}:${dataset}`] || [], ...workspacesByProjectIdAndDataset["NO_PROJECT_ID:NO_DATASET"] || []].find((w) => w.url === preferredStudioUrl);
|
|
812
|
-
else {
|
|
813
|
-
let workspaces = workspacesByProjectIdAndDataset[`${projectId}:${dataset}`];
|
|
814
|
-
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];
|
|
815
|
-
}
|
|
956
|
+
let workspace = resolveWorkspace(documentHandle, workspacesByProjectIdAndDataset, preferredStudioUrl);
|
|
816
957
|
if (!workspace) {
|
|
817
958
|
console.warn(`No workspace found for document with projectId: ${projectId} and dataset: ${dataset}${preferredStudioUrl ? ` or with preferred studio url: ${preferredStudioUrl}` : ""}`);
|
|
818
959
|
return;
|
|
819
960
|
}
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
961
|
+
sendToWorkspace(workspace);
|
|
962
|
+
}, [
|
|
963
|
+
documentHandle,
|
|
964
|
+
workspacesByProjectIdAndDataset,
|
|
965
|
+
preferredStudioUrl,
|
|
966
|
+
sendToWorkspace
|
|
967
|
+
]) };
|
|
968
|
+
}
|
|
969
|
+
function resolveWorkspace(documentHandle, workspacesByProjectIdAndDataset, preferredStudioUrl) {
|
|
970
|
+
let { projectId, dataset } = documentHandle, key = `${projectId}:${dataset}`;
|
|
971
|
+
if (preferredStudioUrl) return [...workspacesByProjectIdAndDataset[key] || [], ...workspacesByProjectIdAndDataset["NO_PROJECT_ID:NO_DATASET"] || []].find((w) => w.url === preferredStudioUrl);
|
|
972
|
+
let workspaces = workspacesByProjectIdAndDataset[key];
|
|
973
|
+
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];
|
|
832
974
|
}
|
|
833
975
|
const remoteClientStates = /* @__PURE__ */ new WeakMap();
|
|
834
976
|
/** Returns the instance's remote client state, creating it on first use. @internal */
|
|
@@ -925,6 +1067,6 @@ function useComlinkWindowTitle(viewTitle) {
|
|
|
925
1067
|
};
|
|
926
1068
|
}, [viewTitle, appTitle]);
|
|
927
1069
|
}
|
|
928
|
-
export { MessageBusError, DashboardTokenRefreshProvider as TokenRefreshProvider, TopicError, UrlBuilder, connectMessageBus, createRemoteInstance, urlFor, useAgentResourceContext, useApplication, useApplicationBasePath, useApplicationConfig, useApplicationConfigs, useApplicationForegroundId, useApplications, useAuthToken, useCurrentUser, useEmit, useNavigate, useNavigateToStudioDocument, useOrganizationId, useRemoteClient, useTopic, useWindowTitle };
|
|
1070
|
+
export { MessageBusError, DashboardTokenRefreshProvider as TokenRefreshProvider, TopicError, UrlBuilder, capabilities, connectMessageBus, createRemoteInstance, urlFor, useAgentResourceContext, useApplication, useApplicationBasePath, useApplicationConfig, useApplicationConfigs, useApplicationContext, useApplicationForegroundId, useApplications, useAuthToken, useCapabilities, useCurrentUser, useEmit, useNavigate, useNavigateToStudioDocument, useOrganizationId, useRemoteClient, useTopic, useWindowTitle };
|
|
929
1071
|
|
|
930
1072
|
//# sourceMappingURL=dashboard.js.map
|