@sanity/sdk-react 2.17.0 → 2.19.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.d.ts +143 -16
- package/dist/index.js +151 -27
- package/dist/index.js.map +1 -1
- package/package.json +11 -11
- package/src/_exports/sdk-react.ts +5 -0
- package/src/hooks/dashboard/useWindowTitle.test.ts +31 -0
- package/src/hooks/dashboard/useWindowTitle.ts +4 -2
- package/src/hooks/presence/usePresence.ts +14 -1
- package/src/hooks/presence/usePresenceForDocument.test.tsx +141 -0
- package/src/hooks/presence/usePresenceForDocument.ts +104 -0
- package/src/hooks/presence/useReportPresence.test.tsx +202 -0
- package/src/hooks/presence/useReportPresence.ts +170 -0
package/dist/index.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ import { DocumentEvent } from "@sanity/sdk";
|
|
|
18
18
|
import { DocumentHandle as DocumentHandle_2 } from "@sanity/sdk";
|
|
19
19
|
import { DocumentOptions } from "@sanity/sdk";
|
|
20
20
|
import { DocumentPermissionsResult } from "@sanity/sdk";
|
|
21
|
+
import { DocumentPresence } from "@sanity/sdk";
|
|
21
22
|
import { DocumentResource } from "@sanity/sdk";
|
|
22
23
|
import { DocumentTypeHandle as DocumentTypeHandle_2 } from "@sanity/sdk";
|
|
23
24
|
import { FallbackProps } from "react-error-boundary";
|
|
@@ -31,7 +32,9 @@ import { Organization } from "@sanity/sdk";
|
|
|
31
32
|
import { OrganizationOptions } from "@sanity/sdk";
|
|
32
33
|
import { Organizations } from "@sanity/sdk";
|
|
33
34
|
import { OrganizationsOptions } from "@sanity/sdk";
|
|
35
|
+
import { Path } from "@sanity/types";
|
|
34
36
|
import { PathChangeMessage } from "@sanity/message-protocol";
|
|
37
|
+
import { PresenceSelection } from "@sanity/sdk";
|
|
35
38
|
import { PreviewValue } from "@sanity/sdk";
|
|
36
39
|
import { Project } from "@sanity/sdk";
|
|
37
40
|
import { ProjectHandle } from "@sanity/sdk";
|
|
@@ -153,10 +156,7 @@ export declare interface AuthBoundaryProps {
|
|
|
153
156
|
* @public
|
|
154
157
|
*/
|
|
155
158
|
export declare type ComlinkStatus =
|
|
156
|
-
| "
|
|
157
|
-
| "handshaking"
|
|
158
|
-
| "connected"
|
|
159
|
-
| "disconnected";
|
|
159
|
+
"idle" | "handshaking" | "connected" | "disconnected";
|
|
160
160
|
|
|
161
161
|
/**
|
|
162
162
|
* This provider is used to provide the Comlink token refresh feature.
|
|
@@ -327,11 +327,7 @@ export declare interface FrameConnection<TFrameMessage extends FrameMessage> {
|
|
|
327
327
|
}
|
|
328
328
|
|
|
329
329
|
declare type IgnoredKey =
|
|
330
|
-
| "
|
|
331
|
-
| "_type"
|
|
332
|
-
| "_rev"
|
|
333
|
-
| "_createdAt"
|
|
334
|
-
| "_updatedAt";
|
|
330
|
+
"_id" | "_type" | "_rev" | "_createdAt" | "_updatedAt";
|
|
335
331
|
|
|
336
332
|
/**
|
|
337
333
|
* @alpha
|
|
@@ -3066,9 +3062,7 @@ export declare function useManageFavorite({
|
|
|
3066
3062
|
declare interface UseManageFavoriteProps extends DocumentHandle_2 {
|
|
3067
3063
|
resourceId?: string;
|
|
3068
3064
|
resourceType:
|
|
3069
|
-
|
|
|
3070
|
-
| MediaResource["type"]
|
|
3071
|
-
| CanvasResource["type"];
|
|
3065
|
+
StudioResource["type"] | MediaResource["type"] | CanvasResource["type"];
|
|
3072
3066
|
/**
|
|
3073
3067
|
* The name of the schema collection this document belongs to.
|
|
3074
3068
|
* Typically is the name of the workspace when used in the context of a studio.
|
|
@@ -3312,13 +3306,80 @@ export declare function usePerspective(
|
|
|
3312
3306
|
): string | string[];
|
|
3313
3307
|
|
|
3314
3308
|
/**
|
|
3315
|
-
*
|
|
3309
|
+
* Every participant in the current project and dataset, or Canvas.
|
|
3310
|
+
*
|
|
3311
|
+
* Reading presence never announces anything. Call `useReportPresence` to make the
|
|
3312
|
+
* current user visible to others, including to the Studio, which shares the same
|
|
3313
|
+
* presence room.
|
|
3314
|
+
*
|
|
3315
|
+
* This returns everyone in the whole resource and leaves the filtering to you.
|
|
3316
|
+
* Prefer `usePresenceForDocument` when you care about one document: it scopes and
|
|
3317
|
+
* flattens the result for rendering. Note that participants are counted by session,
|
|
3318
|
+
* so one person in two tabs appears twice.
|
|
3319
|
+
*
|
|
3320
|
+
* Presence is scoped to a single project and dataset. It is not a list of everyone
|
|
3321
|
+
* signed in to your organization.
|
|
3322
|
+
*
|
|
3316
3323
|
* @public
|
|
3317
3324
|
*/
|
|
3318
3325
|
export declare function usePresence(options?: ResourceHandle): {
|
|
3319
3326
|
locations: UserPresence[];
|
|
3320
3327
|
};
|
|
3321
3328
|
|
|
3329
|
+
/**
|
|
3330
|
+
* Who else is in a document, flattened to one entry per participant per location
|
|
3331
|
+
* so it can be rendered straight against a field.
|
|
3332
|
+
*
|
|
3333
|
+
* Reading presence never announces anything. Use `useReportPresence` to make the
|
|
3334
|
+
* current user visible to others.
|
|
3335
|
+
*
|
|
3336
|
+
* Prefer this over `usePresence` when you care about one document: `usePresence`
|
|
3337
|
+
* returns every participant in the whole project and dataset, leaving the filtering
|
|
3338
|
+
* to you.
|
|
3339
|
+
*
|
|
3340
|
+
* Resolves the document through its perspective exactly as `useReportPresence` does,
|
|
3341
|
+
* so reads match writes. Participants are counted by session, so one person in two
|
|
3342
|
+
* tabs appears twice.
|
|
3343
|
+
*
|
|
3344
|
+
* @example Avatars on a document
|
|
3345
|
+
* ```tsx
|
|
3346
|
+
* const {presence} = usePresenceForDocument({documentId, documentType})
|
|
3347
|
+
* return presence.map((p) => <Avatar key={p.sessionId} user={p.user} />)
|
|
3348
|
+
* ```
|
|
3349
|
+
*
|
|
3350
|
+
* @example Avatars on a single field
|
|
3351
|
+
* ```tsx
|
|
3352
|
+
* const {presence} = usePresenceForDocument({
|
|
3353
|
+
* documentId,
|
|
3354
|
+
* documentType,
|
|
3355
|
+
* path: ['title'],
|
|
3356
|
+
* excludeVersions: true,
|
|
3357
|
+
* })
|
|
3358
|
+
* ```
|
|
3359
|
+
*
|
|
3360
|
+
* @beta
|
|
3361
|
+
*/
|
|
3362
|
+
export declare function usePresenceForDocument(
|
|
3363
|
+
options: UsePresenceForDocumentOptions,
|
|
3364
|
+
): {
|
|
3365
|
+
presence: DocumentPresence[];
|
|
3366
|
+
};
|
|
3367
|
+
|
|
3368
|
+
/** @beta */
|
|
3369
|
+
export declare interface UsePresenceForDocumentOptions extends DocumentHandle {
|
|
3370
|
+
/**
|
|
3371
|
+
* Narrows to participants at or below this field path, which is what a field
|
|
3372
|
+
* indicator wants. Omit it for everyone in the document.
|
|
3373
|
+
*/
|
|
3374
|
+
path?: Path;
|
|
3375
|
+
/**
|
|
3376
|
+
* By default a draft, its published version, and any release versions count as
|
|
3377
|
+
* the same document, which is what document lists want. Set this to compare ids
|
|
3378
|
+
* exactly, so that a draft and a release version do not bleed into each other.
|
|
3379
|
+
*/
|
|
3380
|
+
excludeVersions?: boolean;
|
|
3381
|
+
}
|
|
3382
|
+
|
|
3322
3383
|
/**
|
|
3323
3384
|
* Returns metadata for a given project.
|
|
3324
3385
|
*
|
|
@@ -3567,9 +3628,7 @@ export declare function useRecordDocumentHistoryEvent({
|
|
|
3567
3628
|
*/
|
|
3568
3629
|
declare interface UseRecordDocumentHistoryEventProps extends DocumentHandle_2 {
|
|
3569
3630
|
resourceType:
|
|
3570
|
-
|
|
|
3571
|
-
| MediaResource["type"]
|
|
3572
|
-
| CanvasResource["type"];
|
|
3631
|
+
StudioResource["type"] | MediaResource["type"] | CanvasResource["type"];
|
|
3573
3632
|
resourceId?: string;
|
|
3574
3633
|
/**
|
|
3575
3634
|
* The name of the schema collection this document belongs to.
|
|
@@ -3578,6 +3637,74 @@ declare interface UseRecordDocumentHistoryEventProps extends DocumentHandle_2 {
|
|
|
3578
3637
|
schemaName?: string;
|
|
3579
3638
|
}
|
|
3580
3639
|
|
|
3640
|
+
/**
|
|
3641
|
+
* Announces that the current user is in a document, so that other clients in the
|
|
3642
|
+
* same project and dataset can show them.
|
|
3643
|
+
*
|
|
3644
|
+
* Writing presence is opt-in. Reading it with `usePresenceForDocument` or
|
|
3645
|
+
* `usePresence` never announces anything, and this hook is the only thing that
|
|
3646
|
+
* makes an app visible to others. That includes the Studio, which shares the same
|
|
3647
|
+
* presence room and will show these users in its navbar and field indicators.
|
|
3648
|
+
*
|
|
3649
|
+
* Announcements are throttled, collapsed over a short window, and then repeated
|
|
3650
|
+
* every 30 seconds while the user is idle. That repeat is what tells peers the
|
|
3651
|
+
* session is still alive, so the intended usage is to mount this hook for as long
|
|
3652
|
+
* as the user is in the document. On unmount the location is cleared, leaving the
|
|
3653
|
+
* user present in the app but not in any particular document.
|
|
3654
|
+
*
|
|
3655
|
+
* The perspective decides which specific document is reported: the draft under
|
|
3656
|
+
* `drafts`, the published document under `published`, a version under a release.
|
|
3657
|
+
* It is taken from `ResourceProvider` unless you pass one on the handle. That
|
|
3658
|
+
* matters for interoperability, because the Studio's field indicators compare the
|
|
3659
|
+
* exact id its form is on, so a mismatch shows your user at document level while
|
|
3660
|
+
* never lighting up a field.
|
|
3661
|
+
*
|
|
3662
|
+
* Presence is scoped to a single project and dataset. It is not a list of everyone
|
|
3663
|
+
* signed in to your organization.
|
|
3664
|
+
*
|
|
3665
|
+
* @example Document-level presence
|
|
3666
|
+
* ```tsx
|
|
3667
|
+
* function DocumentEditor({documentId, documentType}: DocumentHandle) {
|
|
3668
|
+
* useReportPresence({documentId, documentType})
|
|
3669
|
+
* return <Editor />
|
|
3670
|
+
* }
|
|
3671
|
+
* ```
|
|
3672
|
+
*
|
|
3673
|
+
* @example Presence in a release version
|
|
3674
|
+
* ```tsx
|
|
3675
|
+
* // The document id stays plain; the perspective selects the version.
|
|
3676
|
+
* useReportPresence({documentId, documentType, perspective: {releaseName: 'autumn'}})
|
|
3677
|
+
* ```
|
|
3678
|
+
*
|
|
3679
|
+
* @example Field-level presence
|
|
3680
|
+
* ```tsx
|
|
3681
|
+
* function TitleField({documentId, documentType}: DocumentHandle) {
|
|
3682
|
+
* const [focused, setFocused] = useState(false)
|
|
3683
|
+
* useReportPresence({documentId, documentType, path: focused ? ['title'] : undefined})
|
|
3684
|
+
* return <input onFocus={() => setFocused(true)} onBlur={() => setFocused(false)} />
|
|
3685
|
+
* }
|
|
3686
|
+
* ```
|
|
3687
|
+
*
|
|
3688
|
+
* @beta
|
|
3689
|
+
*/
|
|
3690
|
+
export declare function useReportPresence(
|
|
3691
|
+
options: UseReportPresenceOptions,
|
|
3692
|
+
): void;
|
|
3693
|
+
|
|
3694
|
+
/** @beta */
|
|
3695
|
+
export declare interface UseReportPresenceOptions extends DocumentHandle {
|
|
3696
|
+
/**
|
|
3697
|
+
* The focused field path. Omit it for document-level presence. Keyed and numeric
|
|
3698
|
+
* segments are supported, so array items and Portable Text spans can be
|
|
3699
|
+
* addressed.
|
|
3700
|
+
*/
|
|
3701
|
+
path?: Path;
|
|
3702
|
+
/** The Portable Text caret, when the focused field is a Portable Text field. */
|
|
3703
|
+
selection?: PresenceSelection;
|
|
3704
|
+
/** Overrides the throttle interval. Mainly useful in tests. */
|
|
3705
|
+
throttleMs?: number;
|
|
3706
|
+
}
|
|
3707
|
+
|
|
3581
3708
|
/**
|
|
3582
3709
|
* Returns the currently active `DocumentResource` for the nearest resource context.
|
|
3583
3710
|
*
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { c } from "react-compiler-runtime";
|
|
3
3
|
import { ClientError, CorsOriginError } from "@sanity/client";
|
|
4
|
-
import { getAuthState, getNodeState, getIsInDashboardState, isStudioConfig, setAuthToken, AuthStateType, getLoginUrlState, observeOrganizationVerificationState, handleAuthCallback, logout, isProjectUserNotFoundClientError, getClientErrorApiDescription, getClientErrorApiBody, isImportError, getCorsErrorProjectId, getDashboardOrganizationId, getClientState, isDatasetResource, createSanityInstance, agentGenerate, agentPatch, agentPrompt, agentTransform, agentTranslate, getTokenState, getCurrentUserState, getOrCreateController, getOrCreateChannel, releaseChannel, isMediaLibraryResource, isCanvasResource, getFavoritesState, resolveFavoritesState, resolveDatasets, getDatasetsState, applyDocumentActions, createDocument, resolveDocument, getDocumentState, subscribeDocumentEvents, getPermissionsState, getDocumentSyncStatus, editDocument, getQueryKey, parseQueryKey, getQueryState, resolveQuery, createGroqSearchFilter, resolveOrganization, getOrganizationState, resolveOrganizations, getOrganizationsState, getPresence, getProjectionState, resolveProjection,
|
|
4
|
+
import { getAuthState, getNodeState, getIsInDashboardState, isStudioConfig, setAuthToken, AuthStateType, getLoginUrlState, observeOrganizationVerificationState, handleAuthCallback, logout, isProjectUserNotFoundClientError, getClientErrorApiDescription, getClientErrorApiBody, isImportError, getCorsErrorProjectId, getDashboardOrganizationId, getClientState, isDatasetResource, createSanityInstance, agentGenerate, agentPatch, agentPrompt, agentTransform, agentTranslate, getTokenState, getCurrentUserState, getOrCreateController, getOrCreateChannel, releaseChannel, isMediaLibraryResource, isCanvasResource, getFavoritesState, resolveFavoritesState, resolveDatasets, getDatasetsState, applyDocumentActions, createDocument, resolveDocument, getDocumentState, subscribeDocumentEvents, getPermissionsState, getDocumentSyncStatus, editDocument, getQueryKey, parseQueryKey, getQueryState, resolveQuery, createGroqSearchFilter, resolveOrganization, getOrganizationState, resolveOrganizations, getOrganizationsState, getPresence, getDocumentPresence, reportPresence, getProjectionState, resolveProjection, PREVIEW_PROJECTION, transformProjectionToPreview, resolveProject, getProjectState, resolveProjects, getProjectsState, getActiveReleasesState, getAllReleasesState, getPerspectiveState, getUsersKey, parseUsersKey, getUsersState, resolveUsers, loadMoreUsers } from "@sanity/sdk";
|
|
5
5
|
export * from "@sanity/sdk";
|
|
6
6
|
import { createContext, useContext, useSyncExternalStore, useRef, useEffect, useState, Suspense, use, StrictMode, useCallback, useMemo, useInsertionEffect, useTransition } from "react";
|
|
7
7
|
import { getErrorMessage, ErrorBoundary } from "react-error-boundary";
|
|
@@ -1307,48 +1307,39 @@ function useRecordDocumentHistoryEvent(t0) {
|
|
|
1307
1307
|
}, $[8] = recordEvent, $[9] = t3) : t3 = $[9], t3;
|
|
1308
1308
|
}
|
|
1309
1309
|
function resolveAppTitle(resource) {
|
|
1310
|
-
return resource.manifest?.title
|
|
1310
|
+
return resource.manifest?.title || resource.activeDeployment?.manifest?.title || resource.title;
|
|
1311
1311
|
}
|
|
1312
1312
|
function useWindowTitle(viewTitle) {
|
|
1313
|
-
const
|
|
1314
|
-
|
|
1315
|
-
|
|
1313
|
+
const [appTitle, setAppTitle] = useState(null), {
|
|
1314
|
+
fetch
|
|
1315
|
+
} = useWindowConnection({
|
|
1316
1316
|
name: SDK_NODE_NAME,
|
|
1317
1317
|
connectTo: SDK_CHANNEL_NAME
|
|
1318
|
-
}
|
|
1319
|
-
|
|
1320
|
-
fetch
|
|
1321
|
-
} = useWindowConnection(t0);
|
|
1322
|
-
let t1, t2;
|
|
1323
|
-
$[1] !== fetch ? (t1 = () => {
|
|
1324
|
-
if (!fetch)
|
|
1325
|
-
return;
|
|
1318
|
+
});
|
|
1319
|
+
useEffect(() => {
|
|
1320
|
+
if (!fetch) return;
|
|
1326
1321
|
const controller = new AbortController();
|
|
1327
|
-
|
|
1322
|
+
async function fetchAppTitle(signal) {
|
|
1328
1323
|
try {
|
|
1329
1324
|
const data = await fetch("dashboard/v1/context", void 0, {
|
|
1330
1325
|
signal
|
|
1331
|
-
}), title = resolveAppTitle(data.context.resource);
|
|
1326
|
+
}), title = resolveAppTitle(data.context.resource) || document.title;
|
|
1332
1327
|
title && setAppTitle(title);
|
|
1333
|
-
} catch (
|
|
1334
|
-
|
|
1335
|
-
if (err instanceof Error && err.name === "AbortError")
|
|
1336
|
-
return;
|
|
1328
|
+
} catch (err) {
|
|
1329
|
+
if (err instanceof Error && err.name === "AbortError") return;
|
|
1337
1330
|
console.error("Failed to fetch app title from dashboard context:", err);
|
|
1338
1331
|
}
|
|
1339
|
-
}
|
|
1332
|
+
}
|
|
1333
|
+
return fetchAppTitle(controller.signal), () => {
|
|
1340
1334
|
controller.abort();
|
|
1341
1335
|
};
|
|
1342
|
-
},
|
|
1343
|
-
|
|
1344
|
-
$[4] !== appTitle || $[5] !== viewTitle ? (t3 = () => {
|
|
1345
|
-
if (!appTitle)
|
|
1346
|
-
return;
|
|
1336
|
+
}, [fetch]), useEffect(() => {
|
|
1337
|
+
if (!appTitle) return;
|
|
1347
1338
|
const previous = document.title;
|
|
1348
1339
|
return document.title = viewTitle ? `${viewTitle} | ${appTitle}` : appTitle, () => {
|
|
1349
1340
|
document.title = previous;
|
|
1350
1341
|
};
|
|
1351
|
-
},
|
|
1342
|
+
}, [viewTitle, appTitle]);
|
|
1352
1343
|
}
|
|
1353
1344
|
function useResolvedProjectId(options) {
|
|
1354
1345
|
const $ = c(6);
|
|
@@ -1807,6 +1798,137 @@ function usePresence(t0) {
|
|
|
1807
1798
|
locations: t6
|
|
1808
1799
|
}, $[12] = t6, $[13] = t7) : t7 = $[13], t7;
|
|
1809
1800
|
}
|
|
1801
|
+
function usePresenceForDocument(options) {
|
|
1802
|
+
const $ = c(23);
|
|
1803
|
+
let excludeVersions, handle, path;
|
|
1804
|
+
$[0] !== options ? ({
|
|
1805
|
+
path,
|
|
1806
|
+
excludeVersions,
|
|
1807
|
+
...handle
|
|
1808
|
+
} = options, $[0] = options, $[1] = excludeVersions, $[2] = handle, $[3] = path) : (excludeVersions = $[1], handle = $[2], path = $[3]);
|
|
1809
|
+
const normalizedOptions = useNormalizedResourceOptions(handle);
|
|
1810
|
+
if (normalizedOptions.resource && isMediaLibraryResource(normalizedOptions.resource))
|
|
1811
|
+
throw new Error("usePresenceForDocument() does not support media library resources. Presence tracking requires a canvas or dataset resource.");
|
|
1812
|
+
const sanityInstance = useSanityInstance();
|
|
1813
|
+
trackHookUsage(sanityInstance, "usePresenceForDocument");
|
|
1814
|
+
const {
|
|
1815
|
+
resource,
|
|
1816
|
+
perspective
|
|
1817
|
+
} = normalizedOptions, {
|
|
1818
|
+
documentId,
|
|
1819
|
+
liveEdit
|
|
1820
|
+
} = options;
|
|
1821
|
+
let t0;
|
|
1822
|
+
$[4] !== path ? (t0 = JSON.stringify(path ?? null), $[4] = path, $[5] = t0) : t0 = $[5];
|
|
1823
|
+
const pathKey = t0;
|
|
1824
|
+
let t1;
|
|
1825
|
+
$[6] !== documentId || $[7] !== excludeVersions || $[8] !== liveEdit || $[9] !== pathKey || $[10] !== perspective || $[11] !== resource || $[12] !== sanityInstance ? (t1 = getDocumentPresence(sanityInstance, {
|
|
1826
|
+
...resource ? {
|
|
1827
|
+
resource
|
|
1828
|
+
} : {},
|
|
1829
|
+
documentId,
|
|
1830
|
+
...perspective ? {
|
|
1831
|
+
perspective
|
|
1832
|
+
} : {},
|
|
1833
|
+
...liveEdit ? {
|
|
1834
|
+
liveEdit
|
|
1835
|
+
} : {},
|
|
1836
|
+
...pathKey === "null" ? {} : {
|
|
1837
|
+
path: JSON.parse(pathKey)
|
|
1838
|
+
},
|
|
1839
|
+
...excludeVersions === void 0 ? {} : {
|
|
1840
|
+
excludeVersions
|
|
1841
|
+
}
|
|
1842
|
+
}), $[6] = documentId, $[7] = excludeVersions, $[8] = liveEdit, $[9] = pathKey, $[10] = perspective, $[11] = resource, $[12] = sanityInstance, $[13] = t1) : t1 = $[13];
|
|
1843
|
+
const source = t1;
|
|
1844
|
+
let t2;
|
|
1845
|
+
$[14] !== source ? (t2 = (callback) => source.subscribe(callback), $[14] = source, $[15] = t2) : t2 = $[15];
|
|
1846
|
+
const subscribe = t2;
|
|
1847
|
+
let t3, t4;
|
|
1848
|
+
$[16] !== source ? (t3 = () => source.getCurrent(), t4 = () => source.getCurrent(), $[16] = source, $[17] = t3, $[18] = t4) : (t3 = $[17], t4 = $[18]);
|
|
1849
|
+
const presence = useSyncExternalStore(subscribe, t3, t4);
|
|
1850
|
+
let t5;
|
|
1851
|
+
$[19] !== presence ? (t5 = presence || [], $[19] = presence, $[20] = t5) : t5 = $[20];
|
|
1852
|
+
let t6;
|
|
1853
|
+
return $[21] !== t5 ? (t6 = {
|
|
1854
|
+
presence: t5
|
|
1855
|
+
}, $[21] = t5, $[22] = t6) : t6 = $[22], t6;
|
|
1856
|
+
}
|
|
1857
|
+
const FOCUS_THROTTLE_MS = 1e3, SELECTION_THROTTLE_MS = 250;
|
|
1858
|
+
function useReportPresence(options) {
|
|
1859
|
+
const $ = c(37);
|
|
1860
|
+
let handle, path, selection, throttleMs;
|
|
1861
|
+
$[0] !== options ? ({
|
|
1862
|
+
path,
|
|
1863
|
+
selection,
|
|
1864
|
+
throttleMs,
|
|
1865
|
+
...handle
|
|
1866
|
+
} = options, $[0] = options, $[1] = handle, $[2] = path, $[3] = selection, $[4] = throttleMs) : (handle = $[1], path = $[2], selection = $[3], throttleMs = $[4]);
|
|
1867
|
+
const normalizedOptions = useNormalizedResourceOptions(handle);
|
|
1868
|
+
if (normalizedOptions.resource && isMediaLibraryResource(normalizedOptions.resource))
|
|
1869
|
+
throw new Error("useReportPresence() does not support media library resources. Presence tracking requires a canvas or dataset resource.");
|
|
1870
|
+
const sanityInstance = useSanityInstance();
|
|
1871
|
+
trackHookUsage(sanityInstance, "useReportPresence");
|
|
1872
|
+
const {
|
|
1873
|
+
resource,
|
|
1874
|
+
perspective
|
|
1875
|
+
} = normalizedOptions, {
|
|
1876
|
+
documentId,
|
|
1877
|
+
liveEdit
|
|
1878
|
+
} = options, interval = throttleMs ?? (selection ? SELECTION_THROTTLE_MS : FOCUS_THROTTLE_MS);
|
|
1879
|
+
let t0;
|
|
1880
|
+
$[5] !== documentId || $[6] !== liveEdit || $[7] !== path || $[8] !== perspective || $[9] !== selection ? (t0 = JSON.stringify([documentId, path ?? [], selection ?? null, perspective ?? null, liveEdit]), $[5] = documentId, $[6] = liveEdit, $[7] = path, $[8] = perspective, $[9] = selection, $[10] = t0) : t0 = $[10];
|
|
1881
|
+
const locationKey = t0;
|
|
1882
|
+
let t1;
|
|
1883
|
+
$[11] !== locationKey ? (t1 = JSON.parse(locationKey), $[11] = locationKey, $[12] = t1) : t1 = $[12];
|
|
1884
|
+
const [id, parsedPath, parsedSelection, parsedPerspective, parsedLiveEdit] = t1;
|
|
1885
|
+
let t2;
|
|
1886
|
+
$[13] !== parsedPerspective ? (t2 = parsedPerspective ? {
|
|
1887
|
+
perspective: parsedPerspective
|
|
1888
|
+
} : {}, $[13] = parsedPerspective, $[14] = t2) : t2 = $[14];
|
|
1889
|
+
let t3;
|
|
1890
|
+
$[15] !== parsedLiveEdit ? (t3 = parsedLiveEdit ? {
|
|
1891
|
+
liveEdit: parsedLiveEdit
|
|
1892
|
+
} : {}, $[15] = parsedLiveEdit, $[16] = t3) : t3 = $[16];
|
|
1893
|
+
let t4;
|
|
1894
|
+
$[17] !== parsedPath ? (t4 = parsedPath.length > 0 ? {
|
|
1895
|
+
path: parsedPath
|
|
1896
|
+
} : {}, $[17] = parsedPath, $[18] = t4) : t4 = $[18];
|
|
1897
|
+
let t5;
|
|
1898
|
+
$[19] !== parsedSelection ? (t5 = parsedSelection ? {
|
|
1899
|
+
selection: parsedSelection
|
|
1900
|
+
} : {}, $[19] = parsedSelection, $[20] = t5) : t5 = $[20];
|
|
1901
|
+
let t6;
|
|
1902
|
+
$[21] !== id || $[22] !== t2 || $[23] !== t3 || $[24] !== t4 || $[25] !== t5 ? (t6 = {
|
|
1903
|
+
documentId: id,
|
|
1904
|
+
...t2,
|
|
1905
|
+
...t3,
|
|
1906
|
+
...t4,
|
|
1907
|
+
...t5
|
|
1908
|
+
}, $[21] = id, $[22] = t2, $[23] = t3, $[24] = t4, $[25] = t5, $[26] = t6) : t6 = $[26];
|
|
1909
|
+
const location2 = t6, lastSentAt = useRef(0), pending = useRef(void 0);
|
|
1910
|
+
let t7, t8;
|
|
1911
|
+
$[27] !== interval || $[28] !== location2 || $[29] !== resource || $[30] !== sanityInstance ? (t7 = () => {
|
|
1912
|
+
const send = () => {
|
|
1913
|
+
lastSentAt.current = Date.now(), reportPresence(sanityInstance, {
|
|
1914
|
+
...resource ? {
|
|
1915
|
+
resource
|
|
1916
|
+
} : {},
|
|
1917
|
+
locations: [location2]
|
|
1918
|
+
});
|
|
1919
|
+
}, elapsed = Date.now() - lastSentAt.current;
|
|
1920
|
+
return elapsed >= interval ? send() : (clearTimeout(pending.current), pending.current = setTimeout(send, interval - elapsed)), () => clearTimeout(pending.current);
|
|
1921
|
+
}, t8 = [location2, interval, sanityInstance, resource], $[27] = interval, $[28] = location2, $[29] = resource, $[30] = sanityInstance, $[31] = t7, $[32] = t8) : (t7 = $[31], t8 = $[32]), useEffect(t7, t8);
|
|
1922
|
+
let t10, t9;
|
|
1923
|
+
$[33] !== resource || $[34] !== sanityInstance ? (t9 = () => () => {
|
|
1924
|
+
reportPresence(sanityInstance, {
|
|
1925
|
+
...resource ? {
|
|
1926
|
+
resource
|
|
1927
|
+
} : {},
|
|
1928
|
+
locations: []
|
|
1929
|
+
});
|
|
1930
|
+
}, t10 = [sanityInstance, resource], $[33] = resource, $[34] = sanityInstance, $[35] = t10, $[36] = t9) : (t10 = $[35], t9 = $[36]), useEffect(t9, t10);
|
|
1931
|
+
}
|
|
1810
1932
|
function useDocumentProjection(t0) {
|
|
1811
1933
|
const $ = c(13);
|
|
1812
1934
|
let docHandle, projection, ref;
|
|
@@ -2024,7 +2146,7 @@ function useUsers(options) {
|
|
|
2024
2146
|
loadMore
|
|
2025
2147
|
}, $[20] = data, $[21] = hasMore, $[22] = isPending, $[23] = loadMore, $[24] = t8) : t8 = $[24], t8;
|
|
2026
2148
|
}
|
|
2027
|
-
var version = "2.
|
|
2149
|
+
var version = "2.19.0";
|
|
2028
2150
|
function getEnv(key) {
|
|
2029
2151
|
if (typeof import.meta < "u" && import.meta.env)
|
|
2030
2152
|
return import.meta.env[key];
|
|
@@ -2082,10 +2204,12 @@ export {
|
|
|
2082
2204
|
usePaginatedDocuments,
|
|
2083
2205
|
usePerspective,
|
|
2084
2206
|
usePresence,
|
|
2207
|
+
usePresenceForDocument,
|
|
2085
2208
|
useProject,
|
|
2086
2209
|
useProjects,
|
|
2087
2210
|
useQuery,
|
|
2088
2211
|
useRecordDocumentHistoryEvent,
|
|
2212
|
+
useReportPresence,
|
|
2089
2213
|
useResource,
|
|
2090
2214
|
useSanityInstance,
|
|
2091
2215
|
useStudioWorkspacesByProjectIdDataset,
|