@sanity/sdk-react 0.0.0-alpha.20 → 0.0.0-alpha.21

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 (40) hide show
  1. package/dist/index.d.ts +276 -207
  2. package/dist/index.js +90 -75
  3. package/dist/index.js.map +1 -1
  4. package/package.json +3 -3
  5. package/src/_exports/index.ts +11 -11
  6. package/src/components/Login/LoginLinks.test.tsx +2 -2
  7. package/src/components/Login/LoginLinks.tsx +2 -2
  8. package/src/components/auth/AuthBoundary.test.tsx +2 -2
  9. package/src/components/auth/LoginCallback.test.tsx +3 -3
  10. package/src/components/auth/LoginCallback.tsx +4 -4
  11. package/src/hooks/auth/useCurrentUser.tsx +1 -0
  12. package/src/hooks/auth/useHandleAuthCallback.test.tsx +16 -0
  13. package/src/hooks/auth/{useHandleCallback.tsx → useHandleAuthCallback.tsx} +6 -6
  14. package/src/hooks/auth/useLogOut.test.tsx +2 -2
  15. package/src/hooks/client/useClient.ts +1 -0
  16. package/src/hooks/comlink/useManageFavorite.test.ts +9 -4
  17. package/src/hooks/comlink/useManageFavorite.ts +42 -13
  18. package/src/hooks/comlink/useRecordDocumentHistoryEvent.test.ts +7 -3
  19. package/src/hooks/comlink/useRecordDocumentHistoryEvent.ts +39 -12
  20. package/src/hooks/dashboard/useNavigateToStudioDocument.test.ts +178 -0
  21. package/src/hooks/dashboard/useNavigateToStudioDocument.ts +31 -5
  22. package/src/hooks/dashboard/useStudioWorkspacesByResourceId.test.tsx +5 -1
  23. package/src/hooks/dashboard/useStudioWorkspacesByResourceId.ts +4 -3
  24. package/src/hooks/datasets/useDatasets.ts +6 -3
  25. package/src/hooks/document/useApplyDocumentActions.test.ts +25 -0
  26. package/src/hooks/document/{useApplyActions.ts → useApplyDocumentActions.ts} +13 -12
  27. package/src/hooks/document/{usePermissions.ts → useDocumentPermissions.ts} +8 -6
  28. package/src/hooks/document/useDocumentSyncStatus.ts +4 -1
  29. package/src/hooks/document/useEditDocument.test.ts +8 -8
  30. package/src/hooks/document/useEditDocument.ts +2 -2
  31. package/src/hooks/{infiniteList/useInfiniteList.test.tsx → documents/useDocuments.test.tsx} +9 -9
  32. package/src/hooks/{infiniteList/useInfiniteList.ts → documents/useDocuments.ts} +10 -10
  33. package/src/hooks/{paginatedList/usePaginatedList.test.tsx → paginatedDocuments/usePaginatedDocuments.test.tsx} +14 -14
  34. package/src/hooks/{paginatedList/usePaginatedList.ts → paginatedDocuments/usePaginatedDocuments.ts} +7 -7
  35. package/src/hooks/preview/usePreview.tsx +2 -2
  36. package/src/hooks/projection/useProjection.ts +2 -2
  37. package/src/hooks/projects/useProject.ts +4 -1
  38. package/src/hooks/projects/useProjects.ts +7 -3
  39. package/src/hooks/auth/useHandleCallback.test.tsx +0 -16
  40. package/src/hooks/document/useApplyActions.test.ts +0 -25
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/sdk-react",
3
- "version": "0.0.0-alpha.20",
3
+ "version": "0.0.0-alpha.21",
4
4
  "private": false,
5
5
  "description": "Sanity SDK React toolkit for Content OS",
6
6
  "keywords": [
@@ -43,11 +43,11 @@
43
43
  "prettier": "@sanity/prettier-config",
44
44
  "dependencies": {
45
45
  "@sanity/logos": "^2.1.13",
46
- "@sanity/message-protocol": "^0.1.0",
46
+ "@sanity/message-protocol": "^0.6.0",
47
47
  "@sanity/types": "^3.78.1",
48
48
  "react-error-boundary": "^5.0.0",
49
49
  "rxjs": "^7.8.1",
50
- "@sanity/sdk": "0.0.0-alpha.19"
50
+ "@sanity/sdk": "0.0.0-alpha.20"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@sanity/browserslist-config": "^1.0.5",
@@ -7,7 +7,7 @@ export {useAuthState} from '../hooks/auth/useAuthState'
7
7
  export {useAuthToken} from '../hooks/auth/useAuthToken'
8
8
  export {useCurrentUser} from '../hooks/auth/useCurrentUser'
9
9
  export {useDashboardOrganizationId} from '../hooks/auth/useDashboardOrganizationId'
10
- export {useHandleCallback} from '../hooks/auth/useHandleCallback'
10
+ export {useHandleAuthCallback} from '../hooks/auth/useHandleAuthCallback'
11
11
  export {useLoginUrls} from '../hooks/auth/useLoginUrls'
12
12
  export {useLogOut} from '../hooks/auth/useLogOut'
13
13
  export {useClient} from '../hooks/client/useClient'
@@ -29,22 +29,22 @@ export {useSanityInstance} from '../hooks/context/useSanityInstance'
29
29
  export {useNavigateToStudioDocument} from '../hooks/dashboard/useNavigateToStudioDocument'
30
30
  export {useStudioWorkspacesByResourceId} from '../hooks/dashboard/useStudioWorkspacesByResourceId'
31
31
  export {useDatasets} from '../hooks/datasets/useDatasets'
32
- export {useApplyActions} from '../hooks/document/useApplyActions'
32
+ export {useApplyDocumentActions} from '../hooks/document/useApplyDocumentActions'
33
33
  export {useDocument} from '../hooks/document/useDocument'
34
34
  export {useDocumentEvent} from '../hooks/document/useDocumentEvent'
35
+ export {useDocumentPermissions} from '../hooks/document/useDocumentPermissions'
35
36
  export {useDocumentSyncStatus} from '../hooks/document/useDocumentSyncStatus'
36
37
  export {useEditDocument} from '../hooks/document/useEditDocument'
37
- export {usePermissions} from '../hooks/document/usePermissions'
38
38
  export {
39
- type InfiniteList,
40
- type InfiniteListOptions,
41
- useInfiniteList,
42
- } from '../hooks/infiniteList/useInfiniteList'
39
+ type DocumentsOptions,
40
+ type DocumentsResponse,
41
+ useDocuments,
42
+ } from '../hooks/documents/useDocuments'
43
43
  export {
44
- type PaginatedList,
45
- type PaginatedListOptions,
46
- usePaginatedList,
47
- } from '../hooks/paginatedList/usePaginatedList'
44
+ type PaginatedDocumentsOptions,
45
+ type PaginatedDocumentsResponse,
46
+ usePaginatedDocuments,
47
+ } from '../hooks/paginatedDocuments/usePaginatedDocuments'
48
48
  export {
49
49
  usePreview,
50
50
  type UsePreviewOptions,
@@ -36,8 +36,8 @@ vi.mock('../../hooks/auth/useAuthState', () => ({
36
36
  useAuthState: vi.fn(() => 'logged-out'),
37
37
  }))
38
38
 
39
- vi.mock('../../hooks/auth/useHandleCallback', () => ({
40
- useHandleCallback: vi.fn(),
39
+ vi.mock('../../hooks/auth/useHandleAuthCallback', () => ({
40
+ useHandleAuthCallback: vi.fn(),
41
41
  }))
42
42
 
43
43
  describe('LoginLinks', () => {
@@ -1,7 +1,7 @@
1
1
  import {type ReactElement} from 'react'
2
2
 
3
3
  import {useAuthState} from '../../hooks/auth/useAuthState'
4
- import {useHandleCallback} from '../../hooks/auth/useHandleCallback'
4
+ import {useHandleAuthCallback} from '../../hooks/auth/useHandleAuthCallback'
5
5
  import {useLoginUrls} from '../../hooks/auth/useLoginUrls'
6
6
 
7
7
  /**
@@ -26,7 +26,7 @@ import {useLoginUrls} from '../../hooks/auth/useLoginUrls'
26
26
  export const LoginLinks = (): ReactElement => {
27
27
  const loginUrls = useLoginUrls()
28
28
  const authState = useAuthState()
29
- useHandleCallback()
29
+ useHandleAuthCallback()
30
30
 
31
31
  if (authState.type === 'logging-in') {
32
32
  return <div className="sc-login-links__logging-in">Logging in...</div>
@@ -13,8 +13,8 @@ vi.mock('../../hooks/auth/useAuthState', () => ({
13
13
  vi.mock('../../hooks/auth/useLoginUrls', () => ({
14
14
  useLoginUrls: vi.fn(() => [{title: 'Provider A', url: 'https://provider-a.com/auth'}]),
15
15
  }))
16
- vi.mock('../../hooks/auth/useHandleCallback', () => ({
17
- useHandleCallback: vi.fn(() => async () => {}),
16
+ vi.mock('../../hooks/auth/useHandleAuthCallback', () => ({
17
+ useHandleAuthCallback: vi.fn(() => async () => {}),
18
18
  }))
19
19
  vi.mock('../../hooks/auth/useLogOut', () => ({
20
20
  useLogOut: vi.fn(() => async () => {}),
@@ -3,9 +3,9 @@ import {afterAll, beforeAll, beforeEach, describe, expect, it, vi} from 'vitest'
3
3
 
4
4
  import {renderWithWrappers} from './authTestHelpers'
5
5
 
6
- // Mock `useHandleCallback`
7
- vi.mock('../../hooks/auth/useHandleCallback', () => ({
8
- useHandleCallback: vi.fn(() => async (url: string) => {
6
+ // Mock `useHandleAuthCallback`
7
+ vi.mock('../../hooks/auth/useHandleAuthCallback', () => ({
8
+ useHandleAuthCallback: vi.fn(() => async (url: string) => {
9
9
  const parsedUrl = new URL(url)
10
10
  const sid = new URLSearchParams(parsedUrl.hash.slice(1)).get('sid')
11
11
  if (sid === 'valid') {
@@ -1,6 +1,6 @@
1
1
  import {useEffect} from 'react'
2
2
 
3
- import {useHandleCallback} from '../../hooks/auth/useHandleCallback'
3
+ import {useHandleAuthCallback} from '../../hooks/auth/useHandleAuthCallback'
4
4
  import {LoginLayout, type LoginLayoutProps} from './LoginLayout'
5
5
 
6
6
  /**
@@ -12,18 +12,18 @@ import {LoginLayout, type LoginLayoutProps} from './LoginLayout'
12
12
  * @alpha
13
13
  */
14
14
  export function LoginCallback({header, footer}: LoginLayoutProps): React.ReactNode {
15
- const handleCallback = useHandleCallback()
15
+ const handleAuthCallback = useHandleAuthCallback()
16
16
 
17
17
  useEffect(() => {
18
18
  const url = new URL(location.href)
19
- handleCallback(url.toString()).then((replacementLocation) => {
19
+ handleAuthCallback(url.toString()).then((replacementLocation) => {
20
20
  if (replacementLocation) {
21
21
  // history API with `replaceState` is used to prevent a reload but still
22
22
  // remove the short-lived token from the URL
23
23
  history.replaceState(null, '', replacementLocation)
24
24
  }
25
25
  })
26
- }, [handleCallback])
26
+ }, [handleAuthCallback])
27
27
 
28
28
  return (
29
29
  <LoginLayout header={header} footer={footer}>
@@ -28,6 +28,7 @@ type UseCurrentUser = {
28
28
 
29
29
  /**
30
30
  * @public
31
+ * @function
31
32
  * @TODO This should not return null — users of a custom app will always be authenticated via Core
32
33
  */
33
34
  export const useCurrentUser: UseCurrentUser = createStateSourceHook(getCurrentUserState)
@@ -0,0 +1,16 @@
1
+ import {handleAuthCallback} from '@sanity/sdk'
2
+ import {identity} from 'rxjs'
3
+ import {describe, it} from 'vitest'
4
+
5
+ import {createCallbackHook} from '../helpers/createCallbackHook'
6
+
7
+ vi.mock('../helpers/createCallbackHook', () => ({createCallbackHook: vi.fn(identity)}))
8
+ vi.mock('@sanity/sdk', () => ({handleAuthCallback: vi.fn()}))
9
+
10
+ describe('useHandleAuthCallback', () => {
11
+ it('calls `createCallbackHook` with `handleAuthCallback`', async () => {
12
+ const {useHandleAuthCallback} = await import('./useHandleAuthCallback')
13
+ expect(createCallbackHook).toHaveBeenCalledWith(handleAuthCallback)
14
+ expect(useHandleAuthCallback).toBe(handleAuthCallback)
15
+ })
16
+ })
@@ -1,4 +1,4 @@
1
- import {handleCallback} from '@sanity/sdk'
1
+ import {handleAuthCallback} from '@sanity/sdk'
2
2
 
3
3
  import {createCallbackHook} from '../helpers/createCallbackHook'
4
4
 
@@ -10,7 +10,7 @@ import {createCallbackHook} from '../helpers/createCallbackHook'
10
10
  * This hook provides access to the authentication store's callback handler,
11
11
  * which processes auth redirects by extracting the session ID and fetching the
12
12
  * authentication token. If fetching the long-lived token is successful,
13
- * `handleCallback` will return a Promise that resolves a new location that
13
+ * `handleAuthCallback` will return a Promise that resolves a new location that
14
14
  * removes the short-lived token from the URL. Use this in combination with
15
15
  * `history.replaceState` or your own router's `replace` function to update the
16
16
  * current location without triggering a reload.
@@ -18,13 +18,13 @@ import {createCallbackHook} from '../helpers/createCallbackHook'
18
18
  * @example
19
19
  * ```tsx
20
20
  * function AuthCallback() {
21
- * const handleCallback = useHandleCallback()
21
+ * const handleAuthCallback = useHandleAuthCallback()
22
22
  * const router = useRouter() // Example router
23
23
  *
24
24
  * useEffect(() => {
25
25
  * async function processCallback() {
26
26
  * // Handle the callback and get the cleaned URL
27
- * const newUrl = await handleCallback(window.location.href)
27
+ * const newUrl = await handleAuthCallback(window.location.href)
28
28
  *
29
29
  * if (newUrl) {
30
30
  * // Replace URL without triggering navigation
@@ -33,7 +33,7 @@ import {createCallbackHook} from '../helpers/createCallbackHook'
33
33
  * }
34
34
  *
35
35
  * processCallback().catch(console.error)
36
- * }, [handleCallback, router])
36
+ * }, [handleAuthCallback, router])
37
37
  *
38
38
  * return <div>Completing login...</div>
39
39
  * }
@@ -42,4 +42,4 @@ import {createCallbackHook} from '../helpers/createCallbackHook'
42
42
  * @returns A callback handler function that processes OAuth redirects
43
43
  * @public
44
44
  */
45
- export const useHandleCallback = createCallbackHook(handleCallback)
45
+ export const useHandleAuthCallback = createCallbackHook(handleAuthCallback)
@@ -7,8 +7,8 @@ import {createCallbackHook} from '../helpers/createCallbackHook'
7
7
  vi.mock('../helpers/createCallbackHook', () => ({createCallbackHook: vi.fn(identity)}))
8
8
  vi.mock('@sanity/sdk', () => ({logout: vi.fn()}))
9
9
 
10
- describe('useHandleCallback', () => {
11
- it('calls `createCallbackHook` with `handleCallback`', async () => {
10
+ describe('useLogOut', () => {
11
+ it('calls `createCallbackHook` with `logout`', async () => {
12
12
  const {useLogOut} = await import('./useLogOut')
13
13
  expect(createCallbackHook).toHaveBeenCalledWith(logout)
14
14
  expect(useLogOut).toBe(logout)
@@ -27,6 +27,7 @@ import {createStateSourceHook} from '../helpers/createStateSourceHook'
27
27
  * ```
28
28
  *
29
29
  * @public
30
+ * @function
30
31
  */
31
32
  export const useClient = createStateSourceHook({
32
33
  getState: getClientState,
@@ -19,8 +19,9 @@ describe('useManageFavorite', () => {
19
19
  let statusCallback: ((status: Status) => void) | null = null
20
20
 
21
21
  const mockDocumentHandle = {
22
- _id: 'mock-id',
23
- _type: 'mock-type',
22
+ documentId: 'mock-id',
23
+ documentType: 'mock-type',
24
+ resourceType: 'studio' as const,
24
25
  }
25
26
 
26
27
  function createMockNode() {
@@ -55,10 +56,12 @@ describe('useManageFavorite', () => {
55
56
  result.current.favorite()
56
57
  })
57
58
 
58
- expect(node.post).toHaveBeenCalledWith('core/v1/events/favorite', {
59
+ expect(node.post).toHaveBeenCalledWith('dashboard/v1/events/favorite/mutate', {
59
60
  documentId: 'mock-id',
60
61
  documentType: 'mock-type',
61
62
  eventType: 'added',
63
+ resourceType: 'studio',
64
+ resourceId: undefined,
62
65
  })
63
66
  expect(result.current.isFavorited).toBe(true)
64
67
  })
@@ -70,10 +73,12 @@ describe('useManageFavorite', () => {
70
73
  result.current.unfavorite()
71
74
  })
72
75
 
73
- expect(node.post).toHaveBeenCalledWith('core/v1/events/favorite', {
76
+ expect(node.post).toHaveBeenCalledWith('dashboard/v1/events/favorite/mutate', {
74
77
  documentId: 'mock-id',
75
78
  documentType: 'mock-type',
76
79
  eventType: 'removed',
80
+ resourceType: 'studio',
81
+ resourceId: undefined,
77
82
  })
78
83
  expect(result.current.isFavorited).toBe(false)
79
84
  })
@@ -1,6 +1,13 @@
1
1
  import {type Status} from '@sanity/comlink'
2
- import {type Events, SDK_CHANNEL_NAME, SDK_NODE_NAME} from '@sanity/message-protocol'
3
- import {type DocumentHandle, type FrameMessage} from '@sanity/sdk'
2
+ import {
3
+ type CanvasResource,
4
+ type Events,
5
+ type MediaResource,
6
+ SDK_CHANNEL_NAME,
7
+ SDK_NODE_NAME,
8
+ type StudioResource,
9
+ } from '@sanity/message-protocol'
10
+ import {type FrameMessage} from '@sanity/sdk'
4
11
  import {useCallback, useState} from 'react'
5
12
 
6
13
  import {useWindowConnection} from './useWindowConnection'
@@ -14,27 +21,34 @@ interface ManageFavorite {
14
21
  isConnected: boolean
15
22
  }
16
23
 
24
+ interface UseManageFavoriteProps {
25
+ documentId: string
26
+ documentType: string
27
+ resourceId?: string
28
+ resourceType: StudioResource['type'] | MediaResource['type'] | CanvasResource['type']
29
+ }
30
+
17
31
  /**
18
32
  * @beta
19
33
  *
20
34
  * ## useManageFavorite
21
35
  * This hook provides functionality to add and remove documents from favorites,
22
36
  * and tracks the current favorite status of the document.
23
- * @category Core UI Communication
37
+ * @category Dashboard Communication
24
38
  * @param documentHandle - The document handle containing document ID and type, like `{_id: '123', _type: 'book'}`
25
39
  * @returns An object containing:
26
40
  * - `favorite` - Function to add document to favorites
27
41
  * - `unfavorite` - Function to remove document from favorites
28
42
  * - `isFavorited` - Boolean indicating if document is currently favorited
29
- * - `isConnected` - Boolean indicating if connection to Core UI is established
43
+ * - `isConnected` - Boolean indicating if connection to Dashboard UI is established
30
44
  *
31
45
  * @example
32
46
  * ```tsx
33
47
  * function MyDocumentAction(props: DocumentActionProps) {
34
- * const {_id, _type} = props
48
+ * const {documentId, documentType} = props
35
49
  * const {favorite, unfavorite, isFavorited, isConnected} = useManageFavorite({
36
- * _id,
37
- * _type
50
+ * documentId,
51
+ * documentType
38
52
  * })
39
53
  *
40
54
  * return (
@@ -47,7 +61,12 @@ interface ManageFavorite {
47
61
  * }
48
62
  * ```
49
63
  */
50
- export function useManageFavorite({_id, _type}: DocumentHandle): ManageFavorite {
64
+ export function useManageFavorite({
65
+ documentId,
66
+ documentType,
67
+ resourceId,
68
+ resourceType,
69
+ }: UseManageFavoriteProps): ManageFavorite {
51
70
  const [isFavorited, setIsFavorited] = useState(false) // should load this from a comlink fetch
52
71
  const [status, setStatus] = useState<Status>('idle')
53
72
  const {sendMessage} = useWindowConnection<Events.FavoriteMessage, FrameMessage>({
@@ -56,17 +75,27 @@ export function useManageFavorite({_id, _type}: DocumentHandle): ManageFavorite
56
75
  onStatus: setStatus,
57
76
  })
58
77
 
78
+ if (resourceType !== 'studio' && !resourceId) {
79
+ throw new Error('resourceId is required for media-library and canvas resources')
80
+ }
81
+
59
82
  const handleFavoriteAction = useCallback(
60
83
  (action: 'added' | 'removed', setFavoriteState: boolean) => {
61
- if (!_id || !_type) return
84
+ if (!documentId || !documentType || !resourceType) return
62
85
 
63
86
  try {
64
87
  const message: Events.FavoriteMessage = {
65
- type: 'core/v1/events/favorite',
88
+ type: 'dashboard/v1/events/favorite/mutate',
66
89
  data: {
67
90
  eventType: action,
68
- documentId: _id,
69
- documentType: _type,
91
+ documentId,
92
+ documentType,
93
+ resourceType,
94
+ // Resource Id should exist for media-library and canvas resources
95
+ resourceId: resourceId!,
96
+ },
97
+ response: {
98
+ success: true,
70
99
  },
71
100
  }
72
101
 
@@ -82,7 +111,7 @@ export function useManageFavorite({_id, _type}: DocumentHandle): ManageFavorite
82
111
  throw error
83
112
  }
84
113
  },
85
- [_id, _type, sendMessage],
114
+ [documentId, documentType, resourceId, resourceType, sendMessage],
86
115
  )
87
116
 
88
117
  const favorite = useCallback(() => handleFavoriteAction('added', true), [handleFavoriteAction])
@@ -19,8 +19,10 @@ describe('useRecordDocumentHistoryEvent', () => {
19
19
  let statusCallback: ((status: Status) => void) | null = null
20
20
 
21
21
  const mockDocumentHandle = {
22
- _id: 'mock-id',
23
- _type: 'mock-type',
22
+ documentId: 'mock-id',
23
+ documentType: 'mock-type',
24
+ resourceType: 'studio' as const,
25
+ resourceId: 'mock-resource-id',
24
26
  }
25
27
 
26
28
  function createMockNode() {
@@ -58,10 +60,12 @@ describe('useRecordDocumentHistoryEvent', () => {
58
60
 
59
61
  result.current.recordEvent('viewed')
60
62
 
61
- expect(node.post).toHaveBeenCalledWith('core/v1/events/history', {
63
+ expect(node.post).toHaveBeenCalledWith('dashboard/v1/events/history', {
62
64
  eventType: 'viewed',
63
65
  documentId: 'mock-id',
64
66
  documentType: 'mock-type',
67
+ resourceType: 'studio',
68
+ resourceId: 'mock-resource-id',
65
69
  })
66
70
  })
67
71
 
@@ -1,6 +1,13 @@
1
1
  import {type Status} from '@sanity/comlink'
2
- import {type Events, SDK_CHANNEL_NAME, SDK_NODE_NAME} from '@sanity/message-protocol'
3
- import {type DocumentHandle, type FrameMessage} from '@sanity/sdk'
2
+ import {
3
+ type CanvasResource,
4
+ type Events,
5
+ type MediaResource,
6
+ SDK_CHANNEL_NAME,
7
+ SDK_NODE_NAME,
8
+ type StudioResource,
9
+ } from '@sanity/message-protocol'
10
+ import {type FrameMessage} from '@sanity/sdk'
4
11
  import {useCallback, useState} from 'react'
5
12
 
6
13
  import {useWindowConnection} from './useWindowConnection'
@@ -10,6 +17,16 @@ interface DocumentInteractionHistory {
10
17
  isConnected: boolean
11
18
  }
12
19
 
20
+ /**
21
+ * @public
22
+ */
23
+ interface UseRecordDocumentHistoryEventProps {
24
+ documentId: string
25
+ documentType: string
26
+ resourceType: StudioResource['type'] | MediaResource['type'] | CanvasResource['type']
27
+ resourceId?: string
28
+ }
29
+
13
30
  /**
14
31
  * @public
15
32
  * Hook for managing document interaction history in Sanity Studio.
@@ -23,10 +40,12 @@ interface DocumentInteractionHistory {
23
40
  * @example
24
41
  * ```tsx
25
42
  * function MyDocumentAction(props: DocumentActionProps) {
26
- * const {_id, _type} = props
43
+ * const {documentId, documentType, resourceType, resourceId} = props
27
44
  * const {recordEvent, isConnected} = useRecordDocumentHistoryEvent({
28
- * _id,
29
- * _type
45
+ * documentId,
46
+ * documentType,
47
+ * resourceType,
48
+ * resourceId,
30
49
  * })
31
50
  *
32
51
  * return (
@@ -40,9 +59,11 @@ interface DocumentInteractionHistory {
40
59
  * ```
41
60
  */
42
61
  export function useRecordDocumentHistoryEvent({
43
- _id,
44
- _type,
45
- }: DocumentHandle): DocumentInteractionHistory {
62
+ documentId,
63
+ documentType,
64
+ resourceType,
65
+ resourceId,
66
+ }: UseRecordDocumentHistoryEventProps): DocumentInteractionHistory {
46
67
  const [status, setStatus] = useState<Status>('idle')
47
68
  const {sendMessage} = useWindowConnection<Events.HistoryMessage, FrameMessage>({
48
69
  name: SDK_NODE_NAME,
@@ -50,15 +71,21 @@ export function useRecordDocumentHistoryEvent({
50
71
  onStatus: setStatus,
51
72
  })
52
73
 
74
+ if (resourceType !== 'studio' && !resourceId) {
75
+ throw new Error('resourceId is required for media-library and canvas resources')
76
+ }
77
+
53
78
  const recordEvent = useCallback(
54
79
  (eventType: 'viewed' | 'edited' | 'created' | 'deleted') => {
55
80
  try {
56
81
  const message: Events.HistoryMessage = {
57
- type: 'core/v1/events/history',
82
+ type: 'dashboard/v1/events/history',
58
83
  data: {
59
84
  eventType,
60
- documentId: _id,
61
- documentType: _type,
85
+ documentId,
86
+ documentType,
87
+ resourceType,
88
+ resourceId: resourceId!,
62
89
  },
63
90
  }
64
91
 
@@ -69,7 +96,7 @@ export function useRecordDocumentHistoryEvent({
69
96
  throw error
70
97
  }
71
98
  },
72
- [_id, _type, sendMessage],
99
+ [documentId, documentType, resourceId, resourceType, sendMessage],
73
100
  )
74
101
 
75
102
  return {