@sanity/sdk-react 2.7.0 → 3.0.0-rc.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.
Files changed (88) hide show
  1. package/README.md +125 -63
  2. package/dist/index.d.ts +381 -571
  3. package/dist/index.js +450 -366
  4. package/dist/index.js.map +1 -1
  5. package/package.json +6 -8
  6. package/src/_exports/index.ts +4 -0
  7. package/src/_exports/sdk-react.ts +16 -0
  8. package/src/components/SDKProvider.test.tsx +23 -58
  9. package/src/components/SDKProvider.tsx +38 -30
  10. package/src/components/SanityApp.test.tsx +12 -68
  11. package/src/components/SanityApp.tsx +88 -65
  12. package/src/components/auth/AuthBoundary.test.tsx +11 -26
  13. package/src/components/auth/LoginError.test.tsx +5 -0
  14. package/src/components/auth/LoginError.tsx +23 -2
  15. package/src/config/handles.ts +53 -0
  16. package/src/context/ComlinkTokenRefresh.test.tsx +27 -10
  17. package/src/context/DefaultResourceContext.ts +10 -0
  18. package/src/context/PerspectiveContext.ts +12 -0
  19. package/src/context/ResourceProvider.test.tsx +99 -19
  20. package/src/context/ResourceProvider.tsx +103 -37
  21. package/src/context/ResourcesContext.tsx +7 -0
  22. package/src/context/SDKStudioContext.test.tsx +33 -28
  23. package/src/context/SDKStudioContext.ts +6 -0
  24. package/src/context/renderSanityApp.test.tsx +49 -151
  25. package/src/context/renderSanityApp.tsx +8 -12
  26. package/src/hooks/agent/agentActions.test.tsx +1 -1
  27. package/src/hooks/agent/agentActions.ts +56 -19
  28. package/src/hooks/auth/useDashboardOrganizationId.test.tsx +8 -2
  29. package/src/hooks/auth/useVerifyOrgProjects.test.tsx +32 -8
  30. package/src/hooks/client/useClient.test.tsx +4 -1
  31. package/src/hooks/client/useClient.ts +0 -1
  32. package/src/hooks/context/useDefaultResource.test.tsx +25 -0
  33. package/src/hooks/context/useDefaultResource.ts +30 -0
  34. package/src/hooks/context/useSanityInstance.test.tsx +2 -140
  35. package/src/hooks/context/useSanityInstance.ts +9 -53
  36. package/src/hooks/dashboard/useDispatchIntent.test.ts +24 -15
  37. package/src/hooks/dashboard/useDispatchIntent.ts +7 -7
  38. package/src/hooks/dashboard/useManageFavorite.test.tsx +34 -94
  39. package/src/hooks/dashboard/useManageFavorite.ts +16 -10
  40. package/src/hooks/dashboard/useNavigateToStudioDocument.test.ts +7 -5
  41. package/src/hooks/dashboard/useNavigateToStudioDocument.ts +6 -2
  42. package/src/hooks/dashboard/useRecordDocumentHistoryEvent.test.ts +2 -0
  43. package/src/hooks/dashboard/useRecordDocumentHistoryEvent.ts +2 -1
  44. package/src/hooks/dashboard/utils/useResourceIdFromDocumentHandle.test.ts +17 -38
  45. package/src/hooks/dashboard/utils/useResourceIdFromDocumentHandle.ts +12 -19
  46. package/src/hooks/datasets/useDatasets.test.ts +8 -22
  47. package/src/hooks/datasets/useDatasets.ts +8 -16
  48. package/src/hooks/document/useApplyDocumentActions.test.ts +98 -52
  49. package/src/hooks/document/useApplyDocumentActions.ts +35 -37
  50. package/src/hooks/document/useDocument.test.tsx +8 -37
  51. package/src/hooks/document/useDocument.ts +78 -129
  52. package/src/hooks/document/useDocumentEvent.test.tsx +7 -19
  53. package/src/hooks/document/useDocumentEvent.ts +21 -19
  54. package/src/hooks/document/useDocumentPermissions.test.tsx +75 -84
  55. package/src/hooks/document/useDocumentPermissions.ts +41 -28
  56. package/src/hooks/document/useDocumentSyncStatus.test.ts +13 -3
  57. package/src/hooks/document/useDocumentSyncStatus.ts +19 -14
  58. package/src/hooks/document/useEditDocument.test.tsx +28 -70
  59. package/src/hooks/document/useEditDocument.ts +29 -149
  60. package/src/hooks/documents/useDocuments.test.tsx +44 -64
  61. package/src/hooks/documents/useDocuments.ts +19 -25
  62. package/src/hooks/helpers/createCallbackHook.test.tsx +19 -13
  63. package/src/hooks/helpers/createStateSourceHook.test.tsx +10 -10
  64. package/src/hooks/helpers/createStateSourceHook.tsx +2 -4
  65. package/src/hooks/helpers/useNormalizedResourceOptions.test.ts +65 -0
  66. package/src/hooks/helpers/useNormalizedResourceOptions.ts +127 -0
  67. package/src/hooks/paginatedDocuments/usePaginatedDocuments.test.tsx +27 -34
  68. package/src/hooks/paginatedDocuments/usePaginatedDocuments.ts +19 -20
  69. package/src/hooks/presence/usePresence.test.tsx +71 -9
  70. package/src/hooks/presence/usePresence.ts +28 -3
  71. package/src/hooks/preview/useDocumentPreview.test.tsx +85 -193
  72. package/src/hooks/preview/useDocumentPreview.tsx +42 -62
  73. package/src/hooks/projection/useDocumentProjection.test.tsx +9 -37
  74. package/src/hooks/projection/useDocumentProjection.ts +9 -82
  75. package/src/hooks/projects/useProject.test.ts +1 -2
  76. package/src/hooks/projects/useProject.ts +7 -8
  77. package/src/hooks/query/useQuery.test.tsx +5 -6
  78. package/src/hooks/query/useQuery.ts +12 -91
  79. package/src/hooks/releases/useActiveReleases.test.tsx +2 -2
  80. package/src/hooks/releases/useActiveReleases.ts +25 -13
  81. package/src/hooks/releases/usePerspective.test.tsx +9 -17
  82. package/src/hooks/releases/usePerspective.ts +29 -18
  83. package/src/hooks/users/useUser.test.tsx +9 -3
  84. package/src/hooks/users/useUser.ts +1 -1
  85. package/src/hooks/users/useUsers.test.tsx +5 -2
  86. package/src/hooks/users/useUsers.ts +1 -1
  87. package/src/context/SourcesContext.tsx +0 -7
  88. package/src/hooks/helpers/useNormalizedSourceOptions.ts +0 -85
@@ -1,8 +1,9 @@
1
- import {type DocumentOptions, getDocumentState, type JsonMatch, resolveDocument} from '@sanity/sdk'
2
- import {type SanityDocument} from 'groq'
3
- import {identity} from 'rxjs'
1
+ import {type DocumentOptions, getDocumentState, resolveDocument} from '@sanity/sdk'
2
+ import {type SanityDocument} from '@sanity/types'
4
3
 
4
+ import {type DocumentHandle} from '../../config/handles'
5
5
  import {createStateSourceHook} from '../helpers/createStateSourceHook'
6
+ import {useNormalizedResourceOptions} from '../helpers/useNormalizedResourceOptions'
6
7
  // used in an `{@link useDocumentProjection}` and `{@link useQuery}`
7
8
  // eslint-disable-next-line import/consistent-type-specifier-style, unused-imports/no-unused-imports
8
9
  import type {useDocumentProjection} from '../projection/useDocumentProjection'
@@ -19,9 +20,6 @@ const useDocumentValue = createStateSourceHook({
19
20
  // Extract handle part for resolveDocument
20
21
  suspender: (instance, options: DocumentOptions<string | undefined>) =>
21
22
  resolveDocument(instance, options),
22
- getConfig: identity as (
23
- options: DocumentOptions<string | undefined>,
24
- ) => DocumentOptions<string | undefined>,
25
23
  })
26
24
 
27
25
  const wrapHookWithData = <TParams extends unknown[], TReturn>(
@@ -33,184 +31,132 @@ const wrapHookWithData = <TParams extends unknown[], TReturn>(
33
31
  return useHook
34
32
  }
35
33
 
36
- interface UseDocument {
37
- /** @internal */
38
- <TDocumentType extends string, TDataset extends string, TProjectId extends string = string>(
39
- options: DocumentOptions<undefined, TDocumentType, TDataset, TProjectId>,
40
- ): {data: SanityDocument<TDocumentType, `${TProjectId}.${TDataset}`> | null}
41
-
42
- /** @internal */
43
- <
44
- TPath extends string,
45
- TDocumentType extends string,
46
- TDataset extends string = string,
47
- TProjectId extends string = string,
48
- >(
49
- options: DocumentOptions<TPath, TDocumentType, TDataset, TProjectId>,
50
- ): {
51
- data: JsonMatch<SanityDocument<TDocumentType, `${TProjectId}.${TDataset}`>, TPath> | undefined
52
- }
53
-
54
- /** @internal */
55
- <TData>(options: DocumentOptions<undefined>): {data: TData | null}
56
- /** @internal */
57
- <TData>(options: DocumentOptions<string>): {data: TData | undefined}
34
+ type UseDocumentOptions<
35
+ TPath extends string | undefined = undefined,
36
+ TDocumentType extends string = string,
37
+ TDataset extends string = string,
38
+ TProjectId extends string = string,
39
+ > = DocumentHandle<TDocumentType, TDataset, TProjectId> & {path?: TPath}
58
40
 
41
+ interface UseDocument {
59
42
  /**
60
- * ## useDocument via Type Inference (Recommended)
61
- *
62
43
  * @public
63
44
  *
64
- * The preferred way to use this hook when working with Sanity Typegen.
45
+ * ## useDocument with Explicit Types (no path)
65
46
  *
66
- * Features:
67
- * - Automatically infers document types from your schema
68
- * - Provides type-safe access to documents and nested fields
69
- * - Supports project/dataset-specific type inference
70
- * - Works seamlessly with Typegen-generated types
71
- *
72
- * This hook will suspend while the document data is being fetched and loaded.
73
- *
74
- * When fetching a full document:
75
- * - Returns the complete document object if it exists
76
- * - Returns `null` if the document doesn't exist
47
+ * Provide an explicit type parameter `TData` to type the returned document data.
48
+ * You can define your own interfaces or use types generated by your Sanity Studio.
77
49
  *
78
- * When fetching with a path:
79
- * - Returns the value at the specified path if both the document and path exist
80
- * - Returns `undefined` if either the document doesn't exist or the path doesn't exist in the document
50
+ * This hook will suspend while the document data is being fetched.
81
51
  *
82
- * @category Documents
52
+ * @typeParam TData - The explicit type for the document
83
53
  * @param options - Configuration including `documentId`, `documentType`, and optionally:
84
- * - `path`: To select a nested value (returns typed value at path)
85
54
  * - `projectId`/`dataset`: For multi-project/dataset setups
86
- * @returns The document state (or nested value if path provided).
55
+ * @returns The document state
87
56
  *
88
- * @example Basic document fetch
57
+ * @example Basic document fetch with explicit type
89
58
  * ```tsx
90
- * import {useDocument, type DocumentHandle} from '@sanity/sdk-react'
59
+ * import {useDocument, type DocumentHandle, type SanityDocument} from '@sanity/sdk-react'
91
60
  *
92
- * interface ProductViewProps {
93
- * doc: DocumentHandle<'product'> // Typegen infers product type
61
+ * interface Book extends SanityDocument {
62
+ * _type: 'book'
63
+ * title: string
64
+ * author: string
94
65
  * }
95
66
  *
96
- * function ProductView({doc}: ProductViewProps) {
97
- * const {data: product} = useDocument({...doc}) // Fully typed product
98
- * return <h1>{product.title ?? 'Untitled'}</h1>
67
+ * interface BookViewProps {
68
+ * doc: DocumentHandle
69
+ * }
70
+ *
71
+ * function BookView({doc}: BookViewProps) {
72
+ * const {data: book} = useDocument<Book>({...doc})
73
+ * return <h1>{book?.title ?? 'Untitled'} by {book?.author ?? 'Unknown'}</h1>
99
74
  * }
100
75
  * ```
101
76
  *
102
- * @example Fetching a specific field
77
+ * @inlineType DocumentOptions
78
+ */
79
+ <TData>(options: UseDocumentOptions<undefined>): {data: TData | null}
80
+
81
+ /**
82
+ * @public
83
+ *
84
+ * ## useDocument with Explicit Types (with path)
85
+ *
86
+ * Provide an explicit type parameter `TData` to type the returned field data
87
+ * when using a `path` to select a nested value.
88
+ *
89
+ * @typeParam TData - The explicit type for the field
90
+ * @param options - Configuration including `documentId`, `documentType`, `path`, and optionally:
91
+ * - `projectId`/`dataset`: For multi-project/dataset setups
92
+ * @returns The field value at the specified path
93
+ *
94
+ * @example Fetching a specific field with explicit type
103
95
  * ```tsx
104
96
  * import {useDocument, type DocumentHandle} from '@sanity/sdk-react'
105
97
  *
106
- * interface ProductTitleProps {
107
- * doc: DocumentHandle<'product'>
108
- * }
109
- *
110
- * function ProductTitle({doc}: ProductTitleProps) {
111
- * const {data: title} = useDocument({
112
- * ...doc,
113
- * path: 'title' // Returns just the title field
114
- * })
98
+ * function BookTitle({doc}: {doc: DocumentHandle}) {
99
+ * const {data: title} = useDocument<string>({...doc, path: 'title'})
115
100
  * return <h1>{title ?? 'Untitled'}</h1>
116
101
  * }
117
102
  * ```
118
103
  *
119
104
  * @inlineType DocumentOptions
120
105
  */
121
- <
122
- TPath extends string | undefined = undefined,
123
- TDocumentType extends string = string,
124
- TDataset extends string = string,
125
- TProjectId extends string = string,
126
- >(
127
- options: DocumentOptions<TPath, TDocumentType, TDataset, TProjectId>,
128
- ): TPath extends string
129
- ? {
130
- data:
131
- | JsonMatch<SanityDocument<TDocumentType, `${TProjectId}.${TDataset}`>, TPath>
132
- | undefined
133
- }
134
- : {data: SanityDocument<TDocumentType, `${TProjectId}.${TDataset}`> | null}
106
+ <TData>(options: UseDocumentOptions<string>): {data: TData | undefined}
135
107
 
136
108
  /**
137
109
  * @public
138
110
  *
139
- * ## useDocument via Explicit Types
111
+ * ## useDocument (default)
140
112
  *
141
- * Use this version when:
142
- * - You're not using Sanity Typegen
143
- * - You need to manually specify document types
144
- * - You're working with dynamic document types
113
+ * When no explicit type parameter is provided, the hook returns `SanityDocument`.
145
114
  *
146
- * Key differences from Typegen version:
147
- * - Requires manual type specification via `TData`
148
- * - Returns `TData | null` for full documents
149
- * - Returns `TData | undefined` for nested values
115
+ * This hook will suspend while the document data is being fetched and loaded.
150
116
  *
151
- * This hook will suspend while the document data is being fetched.
117
+ * When fetching a full document:
118
+ * - Returns the complete document object if it exists
119
+ * - Returns `null` if the document doesn't exist
120
+ *
121
+ * When fetching with a path:
122
+ * - Returns the value at the specified path if both the document and path exist
123
+ * - Returns `undefined` if either the document doesn't exist or the path doesn't exist in the document
152
124
  *
153
- * @typeParam TData - The explicit type for the document or field
154
- * @typeParam TPath - Optional path to a nested value
155
- * @param options - Configuration including `documentId` and optionally:
125
+ * @category Documents
126
+ * @param options - Configuration including `documentId`, `documentType`, and optionally:
156
127
  * - `path`: To select a nested value
157
128
  * - `projectId`/`dataset`: For multi-project/dataset setups
158
- * @returns The document state (or nested value if path provided)
159
- *
160
- * @example Basic document fetch with explicit type
161
- * ```tsx
162
- * import {useDocument, type DocumentHandle, type SanityDocument} from '@sanity/sdk-react'
163
- *
164
- * interface Book extends SanityDocument {
165
- * _type: 'book'
166
- * title: string
167
- * author: string
168
- * }
169
- *
170
- * interface BookViewProps {
171
- * doc: DocumentHandle
172
- * }
173
- *
174
- * function BookView({doc}: BookViewProps) {
175
- * const {data: book} = useDocument<Book>({...doc})
176
- * return <h1>{book?.title ?? 'Untitled'} by {book?.author ?? 'Unknown'}</h1>
177
- * }
178
- * ```
129
+ * @returns The document state (or nested value if path provided).
179
130
  *
180
- * @example Fetching a specific field with explicit type
131
+ * @example Basic document fetch
181
132
  * ```tsx
182
133
  * import {useDocument, type DocumentHandle} from '@sanity/sdk-react'
183
134
  *
184
- * interface BookTitleProps {
185
- * doc: DocumentHandle
186
- * }
187
- *
188
- * function BookTitle({doc}: BookTitleProps) {
189
- * const {data: title} = useDocument<string>({...doc, path: 'title'})
190
- * return <h1>{title ?? 'Untitled'}</h1>
135
+ * function ProductView({doc}: {doc: DocumentHandle}) {
136
+ * const {data: product} = useDocument({...doc})
137
+ * return <h1>{product?.title ?? 'Untitled'}</h1>
191
138
  * }
192
139
  * ```
193
140
  *
194
141
  * @inlineType DocumentOptions
195
142
  */
196
- <TData, TPath extends string>(
197
- options: DocumentOptions<TPath>,
198
- ): TPath extends string ? {data: TData | undefined} : {data: TData | null}
143
+ (options: UseDocumentOptions<undefined>): {data: SanityDocument | null}
199
144
 
200
145
  /**
201
146
  * @internal
202
147
  */
203
- (options: DocumentOptions): {data: unknown}
148
+ (options: UseDocumentOptions): {data: unknown}
204
149
  }
205
150
 
206
151
  /**
207
152
  * @public
208
153
  * Reads and subscribes to a document's realtime state, incorporating both local and remote changes.
209
154
  *
210
- * This hook comes in two main flavors to suit your needs:
155
+ * You can provide an explicit type parameter for full type safety:
156
+ * - `useDocument<MyType>({...})` returns `{data: MyType | null}`
157
+ * - `useDocument<string>({..., path: 'title'})` returns `{data: string | undefined}`
211
158
  *
212
- * 1. **[Type Inference](#usedocument-via-type-inference-recommended)** (Recommended) - Automatically gets types from your Sanity schema
213
- * 2. **[Explicit Types](#usedocument-via-explicit-types)** - Manually specify types when needed
159
+ * Without a type parameter, data is typed as `SanityDocument`.
214
160
  *
215
161
  * @remarks
216
162
  * `useDocument` is ideal for realtime editing interfaces where you need immediate feedback on changes.
@@ -226,4 +172,7 @@ interface UseDocument {
226
172
  *
227
173
  * @function
228
174
  */
229
- export const useDocument = wrapHookWithData(useDocumentValue) as UseDocument
175
+ export const useDocument = wrapHookWithData((options: UseDocumentOptions) => {
176
+ const normalizedOptions = useNormalizedResourceOptions(options)
177
+ return useDocumentValue(normalizedOptions)
178
+ }) as UseDocument
@@ -1,9 +1,8 @@
1
1
  // tests/useDocumentEvent.test.ts
2
2
  import {type DocumentEvent, type DocumentHandle, subscribeDocumentEvents} from '@sanity/sdk'
3
- import {renderHook} from '@testing-library/react'
4
3
  import {beforeEach, describe, expect, it, vi} from 'vitest'
5
4
 
6
- import {ResourceProvider} from '../../context/ResourceProvider'
5
+ import {renderHook} from '../../../test/test-utils'
7
6
  import {useDocumentEvent} from './useDocumentEvent'
8
7
 
9
8
  vi.mock('@sanity/sdk', async (importOriginal) => {
@@ -14,6 +13,7 @@ vi.mock('@sanity/sdk', async (importOriginal) => {
14
13
  const docHandle: DocumentHandle = {
15
14
  documentId: 'doc1',
16
15
  documentType: 'book',
16
+ resource: {projectId: 'p', dataset: 'd'},
17
17
  }
18
18
 
19
19
  describe('useDocumentEvent hook', () => {
@@ -26,22 +26,16 @@ describe('useDocumentEvent hook', () => {
26
26
  const unsubscribe = vi.fn()
27
27
  vi.mocked(subscribeDocumentEvents).mockReturnValue(unsubscribe)
28
28
 
29
- renderHook(() => useDocumentEvent({...docHandle, onEvent: handleEvent}), {
30
- wrapper: ({children}) => (
31
- <ResourceProvider projectId="test-project" dataset="test-dataset" fallback={null}>
32
- {children}
33
- </ResourceProvider>
34
- ),
35
- })
29
+ renderHook(() => useDocumentEvent({...docHandle, onEvent: handleEvent}))
36
30
 
37
31
  expect(vi.mocked(subscribeDocumentEvents)).toHaveBeenCalledTimes(1)
38
32
  expect(vi.mocked(subscribeDocumentEvents).mock.calls[0][0]).toEqual(expect.any(Object))
39
33
 
40
- const stableHandler = vi.mocked(subscribeDocumentEvents).mock.calls[0][1]
41
- expect(typeof stableHandler).toBe('function')
34
+ const options = vi.mocked(subscribeDocumentEvents).mock.calls[0][1]
35
+ expect(typeof options.eventHandler).toBe('function')
42
36
 
43
37
  const event = {type: 'edited', documentId: 'doc1', outgoing: {}} as DocumentEvent
44
- stableHandler(event)
38
+ options.eventHandler(event)
45
39
  expect(handleEvent).toHaveBeenCalledWith(event)
46
40
  })
47
41
 
@@ -50,13 +44,7 @@ describe('useDocumentEvent hook', () => {
50
44
  const unsubscribe = vi.fn()
51
45
  vi.mocked(subscribeDocumentEvents).mockReturnValue(unsubscribe)
52
46
 
53
- const {unmount} = renderHook(() => useDocumentEvent({...docHandle, onEvent: handleEvent}), {
54
- wrapper: ({children}) => (
55
- <ResourceProvider projectId="test-project" dataset="test-dataset" fallback={null}>
56
- {children}
57
- </ResourceProvider>
58
- ),
59
- })
47
+ const {unmount} = renderHook(() => useDocumentEvent({...docHandle, onEvent: handleEvent}))
60
48
  unmount()
61
49
  expect(unsubscribe).toHaveBeenCalledTimes(1)
62
50
  })
@@ -1,7 +1,9 @@
1
- import {type DatasetHandle, type DocumentEvent, subscribeDocumentEvents} from '@sanity/sdk'
1
+ import {type DocumentEvent, subscribeDocumentEvents} from '@sanity/sdk'
2
2
  import {useCallback, useEffect, useInsertionEffect, useRef} from 'react'
3
3
 
4
+ import {type ResourceHandle} from '../../config/handles'
4
5
  import {useSanityInstance} from '../context/useSanityInstance'
6
+ import {useNormalizedResourceOptions} from '../helpers/useNormalizedResourceOptions'
5
7
 
6
8
  /**
7
9
  * @public
@@ -9,7 +11,7 @@ import {useSanityInstance} from '../context/useSanityInstance'
9
11
  export interface UseDocumentEventOptions<
10
12
  TDataset extends string = string,
11
13
  TProjectId extends string = string,
12
- > extends DatasetHandle<TDataset, TProjectId> {
14
+ > extends ResourceHandle<TProjectId, TDataset> {
13
15
  onEvent: (documentEvent: DocumentEvent) => void
14
16
  }
15
17
 
@@ -20,19 +22,19 @@ export interface UseDocumentEventOptions<
20
22
  * Subscribes an event handler to events in your application's document store.
21
23
  *
22
24
  * @category Documents
23
- * @param options - An object containing the event handler (`onEvent`) and optionally a `DatasetHandle` (projectId and dataset). If the handle is not provided, the nearest Sanity instance from context will be used.
25
+ * @param options - An object containing the event handler (`onEvent`) and optionally a `resource`. If no resource is provided, the nearest resource from context will be used.
24
26
  * @example Creating a custom hook for document event toasts
25
27
  * ```tsx
26
- * import {createDatasetHandle, type DatasetHandle, type DocumentEvent, useDocumentEvent} from '@sanity/sdk-react'
28
+ * import {type DocumentResource, type DocumentEvent, useDocumentEvent} from '@sanity/sdk-react'
27
29
  * import {useToast} from './my-ui-library'
28
30
  *
29
- * // Define options for the custom hook, extending DatasetHandle
30
- * interface DocumentToastsOptions extends DatasetHandle {
31
- * // Could add more options, e.g., { includeEvents: DocumentEvent['type'][] }
31
+ * // Define options for the custom hook
32
+ * interface DocumentToastsOptions {
33
+ * resource?: DocumentResource
32
34
  * }
33
35
  *
34
36
  * // Define the custom hook
35
- * function useDocumentToasts({...datasetHandle}: DocumentToastsOptions = {}) {
37
+ * function useDocumentToasts({resource}: DocumentToastsOptions = {}) {
36
38
  * const showToast = useToast() // Get the toast function
37
39
  *
38
40
  * // Define the event handler logic to show toasts on specific events
@@ -44,24 +46,20 @@ export interface UseDocumentEventOptions<
44
46
  * } else if (event.type === 'deleted') {
45
47
  * showToast(`Document ${event.documentId} deleted.`)
46
48
  * } else {
47
- * // Optionally log other events for debugging
48
49
  * console.log('Document Event:', event.type, event.documentId)
49
50
  * }
50
51
  * }
51
52
  *
52
- * // Call the original hook, spreading the handle properties
53
53
  * useDocumentEvent({
54
- * ...datasetHandle, // Spread the dataset handle (projectId, dataset)
54
+ * resource,
55
55
  * onEvent: handleEvent,
56
56
  * })
57
57
  * }
58
58
  *
59
59
  * function MyComponentWithToasts() {
60
- * // Use the custom hook, passing specific handle info
61
- * const specificHandle = createDatasetHandle({ projectId: 'p1', dataset: 'ds1' })
62
- * useDocumentToasts(specificHandle)
60
+ * useDocumentToasts({resource: {projectId: 'p1', dataset: 'ds1'}})
63
61
  *
64
- * // // Or use it relying on context for the handle
62
+ * // Or rely on context for the resource:
65
63
  * // useDocumentToasts()
66
64
  *
67
65
  * return <div>...</div>
@@ -76,7 +74,8 @@ export function useDocumentEvent<
76
74
  options: UseDocumentEventOptions<TDataset, TProjectId>,
77
75
  ): void {
78
76
  // Destructure handler and datasetHandle from options
79
- const {onEvent, ...datasetHandle} = options
77
+ const normalizedOptions = useNormalizedResourceOptions(options)
78
+ const {onEvent, ...datasetHandle} = normalizedOptions
80
79
  const ref = useRef(onEvent)
81
80
 
82
81
  useInsertionEffect(() => {
@@ -87,8 +86,11 @@ export function useDocumentEvent<
87
86
  return ref.current(documentEvent)
88
87
  }, [])
89
88
 
90
- const instance = useSanityInstance(datasetHandle)
89
+ const instance = useSanityInstance()
91
90
  useEffect(() => {
92
- return subscribeDocumentEvents(instance, stableHandler)
93
- }, [instance, stableHandler])
91
+ return subscribeDocumentEvents(instance, {
92
+ eventHandler: stableHandler,
93
+ resource: datasetHandle.resource,
94
+ })
95
+ }, [instance, datasetHandle.resource, stableHandler])
94
96
  }