@sanity/sdk-react 2.7.0 → 2.9.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 +144 -25
- package/dist/index.js +248 -139
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/src/_exports/sdk-react.ts +1 -0
- package/src/components/SanityApp.tsx +1 -0
- package/src/components/auth/AuthBoundary.test.tsx +3 -0
- package/src/components/auth/LoginError.test.tsx +5 -0
- package/src/components/auth/LoginError.tsx +22 -1
- package/src/context/ResourceProvider.test.tsx +7 -1
- package/src/context/ResourceProvider.tsx +6 -0
- package/src/context/SDKStudioContext.ts +6 -0
- package/src/hooks/dashboard/useDispatchIntent.test.ts +2 -0
- package/src/hooks/dashboard/useWindowTitle.test.ts +213 -0
- package/src/hooks/dashboard/useWindowTitle.ts +112 -0
- package/src/hooks/document/useApplyDocumentActions.test.ts +113 -10
- package/src/hooks/document/useApplyDocumentActions.ts +99 -3
- package/src/hooks/document/useDocument.ts +22 -6
- package/src/hooks/document/useDocumentEvent.test.tsx +3 -3
- package/src/hooks/document/useDocumentEvent.ts +10 -3
- package/src/hooks/document/useDocumentPermissions.test.tsx +86 -2
- package/src/hooks/document/useDocumentPermissions.ts +22 -0
- package/src/hooks/document/useDocumentSyncStatus.test.ts +13 -2
- package/src/hooks/document/useDocumentSyncStatus.ts +14 -5
- package/src/hooks/document/useEditDocument.ts +34 -8
- package/src/hooks/documents/useDocuments.ts +2 -0
- package/src/hooks/helpers/useNormalizedSourceOptions.ts +50 -28
- package/src/hooks/helpers/useTrackHookUsage.ts +37 -0
- package/src/hooks/paginatedDocuments/usePaginatedDocuments.ts +2 -0
- package/src/hooks/presence/usePresence.ts +2 -0
- package/src/hooks/preview/useDocumentPreview.test.tsx +84 -193
- package/src/hooks/preview/useDocumentPreview.tsx +39 -55
- package/src/hooks/projection/useDocumentProjection.ts +2 -0
- package/src/hooks/query/useQuery.ts +2 -0
- package/src/hooks/releases/useActiveReleases.ts +32 -13
- package/src/hooks/releases/usePerspective.ts +26 -14
- package/src/hooks/users/useUser.ts +2 -0
- package/src/hooks/users/useUsers.ts +2 -0
|
@@ -1,14 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {
|
|
2
|
+
type DocumentHandle,
|
|
3
|
+
PREVIEW_PROJECTION,
|
|
4
|
+
type PreviewQueryResult,
|
|
5
|
+
type PreviewValue,
|
|
6
|
+
transformProjectionToPreview,
|
|
7
|
+
} from '@sanity/sdk'
|
|
8
|
+
import {useMemo} from 'react'
|
|
4
9
|
|
|
5
10
|
import {useSanityInstance} from '../context/useSanityInstance'
|
|
11
|
+
import {
|
|
12
|
+
useNormalizedSourceOptions,
|
|
13
|
+
type WithSourceNameSupport,
|
|
14
|
+
} from '../helpers/useNormalizedSourceOptions'
|
|
15
|
+
import {trackHookUsage} from '../helpers/useTrackHookUsage'
|
|
16
|
+
import {useDocumentProjection} from '../projection/useDocumentProjection'
|
|
6
17
|
|
|
7
18
|
/**
|
|
8
19
|
* @public
|
|
9
20
|
* @category Types
|
|
10
21
|
*/
|
|
11
|
-
export interface useDocumentPreviewOptions extends DocumentHandle {
|
|
22
|
+
export interface useDocumentPreviewOptions extends WithSourceNameSupport<DocumentHandle> {
|
|
12
23
|
/**
|
|
13
24
|
* Optional ref object to track visibility. When provided, preview resolution
|
|
14
25
|
* only occurs when the referenced element is visible in the viewport.
|
|
@@ -21,7 +32,7 @@ export interface useDocumentPreviewOptions extends DocumentHandle {
|
|
|
21
32
|
* @category Types
|
|
22
33
|
*/
|
|
23
34
|
export interface useDocumentPreviewResults {
|
|
24
|
-
/** The results of inferring the document
|
|
35
|
+
/** The results of inferring the document's preview values */
|
|
25
36
|
data: PreviewValue
|
|
26
37
|
/** True when inferred preview values are being refreshed */
|
|
27
38
|
isPending: boolean
|
|
@@ -31,7 +42,7 @@ export interface useDocumentPreviewResults {
|
|
|
31
42
|
* @public
|
|
32
43
|
*
|
|
33
44
|
* Attempts to infer preview values of a document (specified via a `DocumentHandle`),
|
|
34
|
-
* including the document
|
|
45
|
+
* including the document's `title`, `subtitle`, `media`, and `status`. These values are live and will update in realtime.
|
|
35
46
|
* To reduce unnecessary network requests for resolving the preview values, an optional `ref` can be passed to the hook so that preview
|
|
36
47
|
* resolution will only occur if the `ref` is intersecting the current viewport.
|
|
37
48
|
*
|
|
@@ -40,9 +51,13 @@ export interface useDocumentPreviewResults {
|
|
|
40
51
|
* @remarks
|
|
41
52
|
* Values returned by this hook may not be as expected. It is currently unable to read preview values as defined in your schema;
|
|
42
53
|
* instead, it attempts to infer these preview values by checking against a basic set of potential fields on your document.
|
|
43
|
-
* We are anticipating being able to significantly improve this hook
|
|
54
|
+
* We are anticipating being able to significantly improve this hook's functionality and output in a future release.
|
|
44
55
|
* For now, we recommend using {@link useDocumentProjection} for rendering individual document fields (or projections of those fields).
|
|
45
56
|
*
|
|
57
|
+
* Internally, this hook is implemented as a specialized projection with post-processing logic.
|
|
58
|
+
* It uses a fixed GROQ projection to fetch common preview fields (title, subtitle, media) and
|
|
59
|
+
* transforms the results into the PreviewValue format.
|
|
60
|
+
*
|
|
46
61
|
* @category Documents
|
|
47
62
|
* @param options - The document handle for the document you want to infer preview values for, and an optional ref
|
|
48
63
|
* @returns The inferred values for the given document and a boolean to indicate whether the resolution is pending
|
|
@@ -84,56 +99,25 @@ export function useDocumentPreview({
|
|
|
84
99
|
...docHandle
|
|
85
100
|
}: useDocumentPreviewOptions): useDocumentPreviewResults {
|
|
86
101
|
const instance = useSanityInstance(docHandle)
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
// Create subscribe function for useSyncExternalStore
|
|
90
|
-
const subscribe = useCallback(
|
|
91
|
-
(onStoreChanged: () => void) => {
|
|
92
|
-
const subscription = new Observable<boolean>((observer) => {
|
|
93
|
-
// For environments that don't have an intersection observer (e.g. server-side),
|
|
94
|
-
// we pass true to always subscribe since we can't detect visibility
|
|
95
|
-
if (typeof IntersectionObserver === 'undefined' || typeof HTMLElement === 'undefined') {
|
|
96
|
-
observer.next(true)
|
|
97
|
-
return
|
|
98
|
-
}
|
|
102
|
+
trackHookUsage(instance, 'useDocumentPreview')
|
|
103
|
+
const normalizedDocHandle = useNormalizedSourceOptions(docHandle)
|
|
99
104
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
} else {
|
|
107
|
-
// If no ref is provided or ref.current isn't an HTML element,
|
|
108
|
-
// pass true to always subscribe since we can't track visibility
|
|
109
|
-
observer.next(true)
|
|
110
|
-
}
|
|
111
|
-
return () => intersectionObserver.disconnect()
|
|
112
|
-
})
|
|
113
|
-
.pipe(
|
|
114
|
-
startWith(false),
|
|
115
|
-
distinctUntilChanged(),
|
|
116
|
-
switchMap((isVisible) =>
|
|
117
|
-
isVisible
|
|
118
|
-
? new Observable<void>((obs) => {
|
|
119
|
-
return stateSource.subscribe(() => obs.next())
|
|
120
|
-
})
|
|
121
|
-
: EMPTY,
|
|
122
|
-
),
|
|
123
|
-
)
|
|
124
|
-
.subscribe({next: onStoreChanged})
|
|
105
|
+
// Use the projection hook with the fixed preview projection
|
|
106
|
+
const projectionResult = useDocumentProjection<PreviewQueryResult>({
|
|
107
|
+
...normalizedDocHandle,
|
|
108
|
+
projection: PREVIEW_PROJECTION,
|
|
109
|
+
ref,
|
|
110
|
+
})
|
|
125
111
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
112
|
+
// Contract: useDocumentProjection suspends while data is null, so data is always available here.
|
|
113
|
+
// Keep this non-null assumption aligned with useDocumentPreviewResults.data.
|
|
114
|
+
const previewValue = useMemo(
|
|
115
|
+
() => transformProjectionToPreview(instance, projectionResult.data, normalizedDocHandle.source),
|
|
116
|
+
[projectionResult.data, instance, normalizedDocHandle.source],
|
|
129
117
|
)
|
|
130
118
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
return currentState as useDocumentPreviewResults
|
|
136
|
-
}, [docHandle, instance, stateSource])
|
|
137
|
-
|
|
138
|
-
return useSyncExternalStore(subscribe, getSnapshot)
|
|
119
|
+
return {
|
|
120
|
+
data: previewValue,
|
|
121
|
+
isPending: projectionResult.isPending,
|
|
122
|
+
}
|
|
139
123
|
}
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
useNormalizedSourceOptions,
|
|
9
9
|
type WithSourceNameSupport,
|
|
10
10
|
} from '../helpers/useNormalizedSourceOptions'
|
|
11
|
+
import {trackHookUsage} from '../helpers/useTrackHookUsage'
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* @public
|
|
@@ -181,6 +182,7 @@ export function useDocumentProjection<TData extends object>({
|
|
|
181
182
|
...docHandle
|
|
182
183
|
}: useDocumentProjectionOptions): useDocumentProjectionResults<TData> {
|
|
183
184
|
const instance = useSanityInstance(docHandle)
|
|
185
|
+
trackHookUsage(instance, 'useDocumentProjection')
|
|
184
186
|
|
|
185
187
|
// Normalize projection string to handle template literals with whitespace
|
|
186
188
|
// This ensures that the same projection content produces the same state source
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
useNormalizedSourceOptions,
|
|
14
14
|
type WithSourceNameSupport,
|
|
15
15
|
} from '../helpers/useNormalizedSourceOptions'
|
|
16
|
+
import {trackHookUsage} from '../helpers/useTrackHookUsage'
|
|
16
17
|
/**
|
|
17
18
|
* Hook options for useQuery, supporting both direct source and sourceName.
|
|
18
19
|
* @beta
|
|
@@ -152,6 +153,7 @@ export function useQuery(options: WithSourceNameSupport<QueryOptions>): {
|
|
|
152
153
|
} {
|
|
153
154
|
// Implementation returns unknown, overloads define specifics
|
|
154
155
|
const instance = useSanityInstance(options)
|
|
156
|
+
trackHookUsage(instance, 'useQuery')
|
|
155
157
|
|
|
156
158
|
// Normalize options: resolve sourceName to source and strip sourceName
|
|
157
159
|
const normalized = useNormalizedSourceOptions(options)
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
|
+
type DocumentSource,
|
|
2
3
|
getActiveReleasesState,
|
|
3
4
|
type ReleaseDocument,
|
|
5
|
+
type SanityConfig,
|
|
4
6
|
type SanityInstance,
|
|
5
7
|
type StateSource,
|
|
6
8
|
} from '@sanity/sdk'
|
|
7
9
|
import {filter, firstValueFrom} from 'rxjs'
|
|
8
10
|
|
|
9
11
|
import {createStateSourceHook} from '../helpers/createStateSourceHook'
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
type UseActiveReleases = {
|
|
15
|
-
(): ReleaseDocument[]
|
|
16
|
-
}
|
|
12
|
+
import {
|
|
13
|
+
useNormalizedSourceOptions,
|
|
14
|
+
type WithSourceNameSupport,
|
|
15
|
+
} from '../helpers/useNormalizedSourceOptions'
|
|
17
16
|
|
|
18
17
|
/**
|
|
19
18
|
* @public
|
|
@@ -30,10 +29,30 @@ type UseActiveReleases = {
|
|
|
30
29
|
* const activeReleases = useActiveReleases()
|
|
31
30
|
* ```
|
|
32
31
|
*/
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
type UseActiveReleases = {
|
|
33
|
+
(options?: WithSourceNameSupport<SanityConfig> | undefined): ReleaseDocument[]
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const useActiveReleasesValue: UseActiveReleases = createStateSourceHook({
|
|
37
|
+
getState: getActiveReleasesState as (
|
|
38
|
+
instance: SanityInstance,
|
|
39
|
+
options?: {source?: DocumentSource},
|
|
40
|
+
) => StateSource<ReleaseDocument[]>,
|
|
41
|
+
shouldSuspend: (instance: SanityInstance, options?: {source?: DocumentSource}) =>
|
|
42
|
+
getActiveReleasesState(instance, options ?? {}).getCurrent() === undefined,
|
|
43
|
+
suspender: (instance: SanityInstance, options?: {source?: DocumentSource}) =>
|
|
44
|
+
firstValueFrom(
|
|
45
|
+
getActiveReleasesState(instance, options ?? {}).observable.pipe(filter(Boolean)),
|
|
46
|
+
),
|
|
39
47
|
})
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @public
|
|
51
|
+
* @function
|
|
52
|
+
*/
|
|
53
|
+
export const useActiveReleases: UseActiveReleases = (
|
|
54
|
+
options: WithSourceNameSupport<{source?: DocumentSource}> | undefined,
|
|
55
|
+
) => {
|
|
56
|
+
const normalizedOptions = useNormalizedSourceOptions(options ?? {})
|
|
57
|
+
return useActiveReleasesValue(normalizedOptions)
|
|
58
|
+
}
|
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
type DatasetHandle,
|
|
3
|
+
type DocumentSource,
|
|
3
4
|
getPerspectiveState,
|
|
4
|
-
type PerspectiveHandle,
|
|
5
5
|
type SanityInstance,
|
|
6
6
|
type StateSource,
|
|
7
7
|
} from '@sanity/sdk'
|
|
8
8
|
import {filter, firstValueFrom} from 'rxjs'
|
|
9
9
|
|
|
10
10
|
import {createStateSourceHook} from '../helpers/createStateSourceHook'
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
type UsePerspective = {
|
|
16
|
-
(perspectiveHandle: PerspectiveHandle): string | string[]
|
|
17
|
-
}
|
|
11
|
+
import {
|
|
12
|
+
useNormalizedSourceOptions,
|
|
13
|
+
type WithSourceNameSupport,
|
|
14
|
+
} from '../helpers/useNormalizedSourceOptions'
|
|
18
15
|
|
|
19
16
|
/**
|
|
20
17
|
* @public
|
|
@@ -38,13 +35,28 @@ type UsePerspective = {
|
|
|
38
35
|
*
|
|
39
36
|
* @returns The perspective for the given perspective handle.
|
|
40
37
|
*/
|
|
41
|
-
|
|
38
|
+
type UsePerspective = {
|
|
39
|
+
(perspectiveHandle: DatasetHandle): string | string[]
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const usePerspectiveValue: UsePerspective = createStateSourceHook({
|
|
42
43
|
getState: getPerspectiveState as (
|
|
43
44
|
instance: SanityInstance,
|
|
44
|
-
perspectiveHandle?:
|
|
45
|
+
perspectiveHandle?: {source?: DocumentSource},
|
|
45
46
|
) => StateSource<string | string[]>,
|
|
46
|
-
shouldSuspend: (instance: SanityInstance, options:
|
|
47
|
+
shouldSuspend: (instance: SanityInstance, options: {source?: DocumentSource}): boolean =>
|
|
47
48
|
getPerspectiveState(instance, options).getCurrent() === undefined,
|
|
48
|
-
suspender: (instance: SanityInstance, _options?:
|
|
49
|
-
firstValueFrom(
|
|
49
|
+
suspender: (instance: SanityInstance, _options?: {source?: DocumentSource}) =>
|
|
50
|
+
firstValueFrom(getPerspectiveState(instance, _options ?? {}).observable.pipe(filter(Boolean))),
|
|
50
51
|
})
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @public
|
|
55
|
+
* @function
|
|
56
|
+
*/
|
|
57
|
+
export const usePerspective: UsePerspective = (
|
|
58
|
+
options: WithSourceNameSupport<DatasetHandle> | undefined,
|
|
59
|
+
) => {
|
|
60
|
+
const normalizedOptions = useNormalizedSourceOptions(options ?? {})
|
|
61
|
+
return usePerspectiveValue(normalizedOptions)
|
|
62
|
+
}
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
import {useEffect, useMemo, useState, useSyncExternalStore, useTransition} from 'react'
|
|
10
10
|
|
|
11
11
|
import {useSanityInstance} from '../context/useSanityInstance'
|
|
12
|
+
import {trackHookUsage} from '../helpers/useTrackHookUsage'
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* @public
|
|
@@ -59,6 +60,7 @@ export interface UserResult {
|
|
|
59
60
|
*/
|
|
60
61
|
export function useUser(options: GetUserOptions): UserResult {
|
|
61
62
|
const instance = useSanityInstance(options)
|
|
63
|
+
trackHookUsage(instance, 'useUser')
|
|
62
64
|
// Use React's useTransition to avoid UI jank when user options change
|
|
63
65
|
const [isPending, startTransition] = useTransition()
|
|
64
66
|
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
import {useCallback, useEffect, useMemo, useState, useSyncExternalStore, useTransition} from 'react'
|
|
11
11
|
|
|
12
12
|
import {useSanityInstance} from '../context/useSanityInstance'
|
|
13
|
+
import {trackHookUsage} from '../helpers/useTrackHookUsage'
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* @public
|
|
@@ -69,6 +70,7 @@ export interface UsersResult {
|
|
|
69
70
|
*/
|
|
70
71
|
export function useUsers(options?: GetUsersOptions): UsersResult {
|
|
71
72
|
const instance = useSanityInstance(options)
|
|
73
|
+
trackHookUsage(instance, 'useUsers')
|
|
72
74
|
// Use React's useTransition to avoid UI jank when user options change
|
|
73
75
|
const [isPending, startTransition] = useTransition()
|
|
74
76
|
|