@sanity/sdk-react 0.0.0-rc.6 → 0.0.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/README.md +5 -57
- package/dist/index.d.ts +1000 -438
- package/dist/index.js +324 -258
- package/dist/index.js.map +1 -1
- package/package.json +17 -16
- package/src/_exports/sdk-react.ts +4 -1
- package/src/components/SDKProvider.tsx +6 -1
- package/src/components/SanityApp.test.tsx +29 -47
- package/src/components/SanityApp.tsx +12 -11
- package/src/components/auth/AuthBoundary.test.tsx +177 -7
- package/src/components/auth/AuthBoundary.tsx +32 -2
- package/src/components/auth/ConfigurationError.ts +22 -0
- package/src/components/auth/LoginError.tsx +9 -3
- package/src/hooks/auth/useVerifyOrgProjects.test.tsx +136 -0
- package/src/hooks/auth/useVerifyOrgProjects.tsx +48 -0
- package/src/hooks/client/useClient.ts +3 -3
- package/src/hooks/comlink/useManageFavorite.test.ts +276 -27
- package/src/hooks/comlink/useManageFavorite.ts +102 -51
- package/src/hooks/comlink/useWindowConnection.ts +3 -2
- package/src/hooks/document/useApplyDocumentActions.ts +105 -31
- package/src/hooks/document/useDocument.test.ts +41 -4
- package/src/hooks/document/useDocument.ts +198 -114
- package/src/hooks/document/useDocumentEvent.test.ts +5 -5
- package/src/hooks/document/useDocumentEvent.ts +67 -23
- package/src/hooks/document/useDocumentPermissions.ts +47 -8
- package/src/hooks/document/useDocumentSyncStatus.test.ts +12 -5
- package/src/hooks/document/useDocumentSyncStatus.ts +41 -14
- package/src/hooks/document/useEditDocument.test.ts +24 -6
- package/src/hooks/document/useEditDocument.ts +238 -133
- package/src/hooks/documents/useDocuments.test.tsx +1 -1
- package/src/hooks/documents/useDocuments.ts +153 -44
- package/src/hooks/paginatedDocuments/usePaginatedDocuments.test.tsx +1 -1
- package/src/hooks/paginatedDocuments/usePaginatedDocuments.ts +120 -47
- package/src/hooks/projection/useProjection.ts +134 -46
- package/src/hooks/query/useQuery.test.tsx +4 -4
- package/src/hooks/query/useQuery.ts +115 -43
- package/src/hooks/releases/useActiveReleases.test.tsx +84 -0
- package/src/hooks/releases/useActiveReleases.ts +39 -0
- package/src/hooks/releases/usePerspective.test.tsx +120 -0
- package/src/hooks/releases/usePerspective.ts +50 -0
package/dist/index.d.ts
CHANGED
|
@@ -9,25 +9,31 @@ import {DatasetsResponse} from '@sanity/client'
|
|
|
9
9
|
import {DocumentAction} from '@sanity/sdk'
|
|
10
10
|
import {DocumentEvent} from '@sanity/sdk'
|
|
11
11
|
import {DocumentHandle} from '@sanity/sdk'
|
|
12
|
+
import {DocumentOptions} from '@sanity/sdk'
|
|
12
13
|
import {DocumentPermissionsResult} from '@sanity/sdk'
|
|
13
14
|
import {FallbackProps} from 'react-error-boundary'
|
|
15
|
+
import {FavoriteStatusResponse} from '@sanity/sdk'
|
|
14
16
|
import {FrameMessage} from '@sanity/sdk'
|
|
15
17
|
import {GetUsersOptions} from '@sanity/sdk'
|
|
16
18
|
import {JsonMatch} from '@sanity/sdk'
|
|
17
|
-
import {JsonMatchPath} from '@sanity/sdk'
|
|
18
19
|
import {MediaResource} from '@sanity/message-protocol'
|
|
20
|
+
import {PerspectiveHandle} from '@sanity/sdk'
|
|
19
21
|
import {PreviewValue} from '@sanity/sdk'
|
|
20
22
|
import {ProjectHandle} from '@sanity/sdk'
|
|
21
23
|
import {QueryOptions} from '@sanity/sdk'
|
|
22
24
|
import {ReactElement} from 'react'
|
|
23
25
|
import {ReactNode} from 'react'
|
|
26
|
+
import {ReleaseDocument} from '@sanity/sdk'
|
|
24
27
|
import {SanityClient} from '@sanity/client'
|
|
25
28
|
import {SanityConfig} from '@sanity/sdk'
|
|
26
29
|
import {SanityDocument} from '@sanity/types'
|
|
30
|
+
import {SanityDocumentResult} from 'groq'
|
|
27
31
|
import {SanityInstance} from '@sanity/sdk'
|
|
28
32
|
import {SanityProject} from '@sanity/sdk'
|
|
29
33
|
import {SanityProject as SanityProject_2} from '@sanity/client'
|
|
34
|
+
import {SanityProjectionResult} from 'groq'
|
|
30
35
|
import {SanityProjectMember} from '@sanity/client'
|
|
36
|
+
import {SanityQueryResult} from 'groq'
|
|
31
37
|
import {SanityUser} from '@sanity/sdk'
|
|
32
38
|
import {SortOrderingItem} from '@sanity/types'
|
|
33
39
|
import {StudioResource} from '@sanity/message-protocol'
|
|
@@ -61,9 +67,9 @@ export declare function AuthBoundary({
|
|
|
61
67
|
}: AuthBoundaryProps): React.ReactNode
|
|
62
68
|
|
|
63
69
|
/**
|
|
64
|
-
* @
|
|
70
|
+
* @internal
|
|
65
71
|
*/
|
|
66
|
-
declare interface AuthBoundaryProps {
|
|
72
|
+
export declare interface AuthBoundaryProps {
|
|
67
73
|
/**
|
|
68
74
|
* Custom component to render the login screen.
|
|
69
75
|
* Receives all props. Defaults to {@link Login}.
|
|
@@ -88,10 +94,22 @@ declare interface AuthBoundaryProps {
|
|
|
88
94
|
LoginErrorComponent?: React.ComponentType<LoginErrorProps>
|
|
89
95
|
/** Header content to display */
|
|
90
96
|
header?: React.ReactNode
|
|
97
|
+
/**
|
|
98
|
+
* The project IDs to use for organization verification.
|
|
99
|
+
*/
|
|
100
|
+
projectIds?: string[]
|
|
91
101
|
/** Footer content to display */
|
|
92
102
|
footer?: React.ReactNode
|
|
93
103
|
/** Protected content to render when authenticated */
|
|
94
104
|
children?: React.ReactNode
|
|
105
|
+
/**
|
|
106
|
+
* Whether to verify that the project belongs to the organization specified in the dashboard context.
|
|
107
|
+
* By default, organization verification is enabled when running in a dashboard context.
|
|
108
|
+
*
|
|
109
|
+
* WARNING: Disabling organization verification is NOT RECOMMENDED and may cause your application
|
|
110
|
+
* to break in the future. This should never be disabled in production environments.
|
|
111
|
+
*/
|
|
112
|
+
verifyOrganization?: boolean
|
|
95
113
|
}
|
|
96
114
|
|
|
97
115
|
/**
|
|
@@ -124,7 +142,16 @@ declare interface DocumentInteractionHistory {
|
|
|
124
142
|
* @beta
|
|
125
143
|
* @category Types
|
|
126
144
|
*/
|
|
127
|
-
export declare interface DocumentsOptions
|
|
145
|
+
export declare interface DocumentsOptions<
|
|
146
|
+
TDocumentType extends string = string,
|
|
147
|
+
TDataset extends string = string,
|
|
148
|
+
TProjectId extends string = string,
|
|
149
|
+
> extends DatasetHandle<TDataset, TProjectId>,
|
|
150
|
+
Pick<QueryOptions, 'perspective' | 'params'> {
|
|
151
|
+
/**
|
|
152
|
+
* Filter documents by their `_type`. Can be a single type or an array of types.
|
|
153
|
+
*/
|
|
154
|
+
documentType?: TDocumentType | TDocumentType[]
|
|
128
155
|
/**
|
|
129
156
|
* GROQ filter expression to apply to the query
|
|
130
157
|
*/
|
|
@@ -149,11 +176,15 @@ export declare interface DocumentsOptions extends QueryOptions {
|
|
|
149
176
|
* @beta
|
|
150
177
|
* @category Types
|
|
151
178
|
*/
|
|
152
|
-
export declare interface DocumentsResponse
|
|
179
|
+
export declare interface DocumentsResponse<
|
|
180
|
+
TDocumentType extends string = string,
|
|
181
|
+
TDataset extends string = string,
|
|
182
|
+
TProjectId extends string = string,
|
|
183
|
+
> {
|
|
153
184
|
/**
|
|
154
185
|
* Array of document handles for the current batch
|
|
155
186
|
*/
|
|
156
|
-
data: DocumentHandle[]
|
|
187
|
+
data: DocumentHandle<TDocumentType, TDataset, TProjectId>[]
|
|
157
188
|
/**
|
|
158
189
|
* Whether there are more items available to load
|
|
159
190
|
*/
|
|
@@ -202,9 +233,9 @@ export declare interface FrameConnection<TFrameMessage extends FrameMessage> {
|
|
|
202
233
|
*/
|
|
203
234
|
declare type LoginErrorProps = FallbackProps
|
|
204
235
|
|
|
205
|
-
declare interface ManageFavorite {
|
|
206
|
-
favorite: () => void
|
|
207
|
-
unfavorite: () => void
|
|
236
|
+
declare interface ManageFavorite extends FavoriteStatusResponse {
|
|
237
|
+
favorite: () => Promise<void>
|
|
238
|
+
unfavorite: () => Promise<void>
|
|
208
239
|
isFavorited: boolean
|
|
209
240
|
isConnected: boolean
|
|
210
241
|
}
|
|
@@ -236,7 +267,12 @@ export declare interface NavigateToStudioResult {
|
|
|
236
267
|
* @beta
|
|
237
268
|
* @category Types
|
|
238
269
|
*/
|
|
239
|
-
export declare interface PaginatedDocumentsOptions
|
|
270
|
+
export declare interface PaginatedDocumentsOptions<
|
|
271
|
+
TDocumentType extends string = string,
|
|
272
|
+
TDataset extends string = string,
|
|
273
|
+
TProjectId extends string = string,
|
|
274
|
+
> extends Omit<QueryOptions<TDocumentType, TDataset, TProjectId>, 'query'> {
|
|
275
|
+
documentType?: TDocumentType | TDocumentType[]
|
|
240
276
|
/**
|
|
241
277
|
* GROQ filter expression to apply to the query
|
|
242
278
|
*/
|
|
@@ -261,11 +297,15 @@ export declare interface PaginatedDocumentsOptions extends QueryOptions {
|
|
|
261
297
|
* @beta
|
|
262
298
|
* @category Types
|
|
263
299
|
*/
|
|
264
|
-
export declare interface PaginatedDocumentsResponse
|
|
300
|
+
export declare interface PaginatedDocumentsResponse<
|
|
301
|
+
TDocumentType extends string = string,
|
|
302
|
+
TDataset extends string = string,
|
|
303
|
+
TProjectId extends string = string,
|
|
304
|
+
> {
|
|
265
305
|
/**
|
|
266
306
|
* Array of document handles for the current page
|
|
267
307
|
*/
|
|
268
|
-
data: DocumentHandle[]
|
|
308
|
+
data: DocumentHandle<TDocumentType, TDataset, TProjectId>[]
|
|
269
309
|
/**
|
|
270
310
|
* Whether a query is currently in progress
|
|
271
311
|
*/
|
|
@@ -417,8 +457,12 @@ export declare interface ResourceProviderProps extends SanityConfig {
|
|
|
417
457
|
* as well as application context and state which is used by the Sanity React hooks. Your application
|
|
418
458
|
* must be wrapped with the SanityApp component to function properly.
|
|
419
459
|
*
|
|
420
|
-
* SanityApp
|
|
421
|
-
*
|
|
460
|
+
* The `config` prop on the SanityApp component accepts either a single {@link SanityConfig} object, or an array of them.
|
|
461
|
+
* This allows your app to work with one or more of your organization’s datasets.
|
|
462
|
+
*
|
|
463
|
+
* @remarks
|
|
464
|
+
* When passing multiple SanityConfig objects to the `config` prop, the first configuration in the array becomes the default
|
|
465
|
+
* configuration used by the App SDK Hooks.
|
|
422
466
|
*
|
|
423
467
|
* @category Components
|
|
424
468
|
* @param props - Your Sanity configuration and the React children to render
|
|
@@ -426,18 +470,18 @@ export declare interface ResourceProviderProps extends SanityConfig {
|
|
|
426
470
|
*
|
|
427
471
|
* @example
|
|
428
472
|
* ```tsx
|
|
429
|
-
* import { SanityApp } from '@sanity/sdk-react'
|
|
473
|
+
* import { SanityApp, type SanityConfig } from '@sanity/sdk-react'
|
|
430
474
|
*
|
|
431
475
|
* import MyAppRoot from './Root'
|
|
432
476
|
*
|
|
433
477
|
* // Single project configuration
|
|
434
|
-
* const mySanityConfig = {
|
|
478
|
+
* const mySanityConfig: SanityConfig = {
|
|
435
479
|
* projectId: 'my-project-id',
|
|
436
480
|
* dataset: 'production',
|
|
437
481
|
* }
|
|
438
482
|
*
|
|
439
483
|
* // Or multiple project configurations
|
|
440
|
-
* const multipleConfigs = [
|
|
484
|
+
* const multipleConfigs: SanityConfig[] = [
|
|
441
485
|
* // Configuration for your main project. This will be used as the default project for hooks.
|
|
442
486
|
* {
|
|
443
487
|
* projectId: 'marketing-website-project',
|
|
@@ -457,7 +501,7 @@ export declare interface ResourceProviderProps extends SanityConfig {
|
|
|
457
501
|
*
|
|
458
502
|
* export default function MyApp() {
|
|
459
503
|
* return (
|
|
460
|
-
* <SanityApp config={mySanityConfig} fallback={<
|
|
504
|
+
* <SanityApp config={mySanityConfig} fallback={<div>Loading…</div>}>
|
|
461
505
|
* <MyAppRoot />
|
|
462
506
|
* </SanityApp>
|
|
463
507
|
* )
|
|
@@ -468,7 +512,6 @@ export declare function SanityApp({
|
|
|
468
512
|
children,
|
|
469
513
|
fallback,
|
|
470
514
|
config,
|
|
471
|
-
sanityConfigs,
|
|
472
515
|
...props
|
|
473
516
|
}: SanityAppProps): ReactElement
|
|
474
517
|
|
|
@@ -519,57 +562,141 @@ declare interface StudioWorkspacesResult {
|
|
|
519
562
|
isConnected: boolean
|
|
520
563
|
}
|
|
521
564
|
|
|
522
|
-
declare type Updater<TValue> = TValue | ((
|
|
565
|
+
declare type Updater<TValue> = TValue | ((currentValue: TValue) => TValue)
|
|
566
|
+
|
|
567
|
+
/**
|
|
568
|
+
* @public
|
|
569
|
+
*/
|
|
570
|
+
declare type UseActiveReleases = {
|
|
571
|
+
(): ReleaseDocument[]
|
|
572
|
+
}
|
|
523
573
|
|
|
524
574
|
/**
|
|
575
|
+
* @public
|
|
576
|
+
|
|
577
|
+
* Returns the active releases for the current project,
|
|
578
|
+
* represented as a list of release documents.
|
|
525
579
|
*
|
|
580
|
+
* @returns The active releases for the current project.
|
|
581
|
+
* @category Projects
|
|
582
|
+
* @example
|
|
583
|
+
* ```tsx
|
|
584
|
+
* import {useActiveReleases} from '@sanity/sdk-react'
|
|
585
|
+
*
|
|
586
|
+
* const activeReleases = useActiveReleases()
|
|
587
|
+
* ```
|
|
588
|
+
*/
|
|
589
|
+
export declare const useActiveReleases: UseActiveReleases
|
|
590
|
+
|
|
591
|
+
/**
|
|
526
592
|
* @beta
|
|
593
|
+
*/
|
|
594
|
+
declare interface UseApplyDocumentActions {
|
|
595
|
+
(): <
|
|
596
|
+
TDocumentType extends string = string,
|
|
597
|
+
TDataset extends string = string,
|
|
598
|
+
TProjectId extends string = string,
|
|
599
|
+
>(
|
|
600
|
+
action:
|
|
601
|
+
| DocumentAction<TDocumentType, TDataset, TProjectId>
|
|
602
|
+
| DocumentAction<TDocumentType, TDataset, TProjectId>[],
|
|
603
|
+
options?: ApplyDocumentActionsOptions,
|
|
604
|
+
) => Promise<ActionsResult<SanityDocumentResult<TDocumentType, TDataset, TProjectId>>>
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* @beta
|
|
609
|
+
*
|
|
610
|
+
* Provides a stable callback function for applying one or more document actions.
|
|
527
611
|
*
|
|
528
|
-
*
|
|
612
|
+
* This hook wraps the core `applyDocumentActions` functionality from `@sanity/sdk`,
|
|
613
|
+
* integrating it with the React component lifecycle and {@link SanityInstance}.
|
|
614
|
+
* It allows you to apply actions generated by functions like `createDocument`,
|
|
615
|
+
* `editDocument`, `deleteDocument`, `publishDocument`, `unpublishDocument`,
|
|
616
|
+
* and `discardDocument` to documents.
|
|
617
|
+
*
|
|
618
|
+
* Features:
|
|
619
|
+
* - Applies one or multiple `DocumentAction` objects.
|
|
620
|
+
* - Supports optimistic updates: Local state reflects changes immediately.
|
|
621
|
+
* - Handles batching: Multiple actions passed together are sent as a single atomic transaction.
|
|
622
|
+
* - Integrates with the collaborative editing engine for conflict resolution and state synchronization.
|
|
529
623
|
*
|
|
530
624
|
* @category Documents
|
|
531
|
-
* @
|
|
532
|
-
*
|
|
625
|
+
* @returns A stable callback function. When called with a single `DocumentAction` or an array of `DocumentAction`s,
|
|
626
|
+
* it returns a promise that resolves to an {@link ActionsResult}. The `ActionsResult` contains information about the
|
|
627
|
+
* outcome, including optimistic results if applicable.
|
|
628
|
+
*
|
|
629
|
+
* @remarks
|
|
630
|
+
* This hook is a fundamental part of interacting with document state programmatically.
|
|
631
|
+
* It operates within the same unified pipeline as other document hooks like `useDocument` (for reading state)
|
|
632
|
+
* and {@link useEditDocument} (a higher-level hook specifically for edits).
|
|
633
|
+
*
|
|
634
|
+
* When multiple actions are provided in a single call, they are guaranteed to be submitted
|
|
635
|
+
* as a single transaction to Content Lake. This ensures atomicity for related operations (e.g., creating and publishing a document).
|
|
636
|
+
*
|
|
637
|
+
* @function
|
|
638
|
+
*
|
|
533
639
|
* @example Publish or unpublish a document
|
|
534
|
-
* ```
|
|
535
|
-
* import {
|
|
536
|
-
*
|
|
640
|
+
* ```tsx
|
|
641
|
+
* import {
|
|
642
|
+
* publishDocument,
|
|
643
|
+
* unpublishDocument,
|
|
644
|
+
* useApplyDocumentActions,
|
|
645
|
+
* type DocumentHandle
|
|
646
|
+
* } from '@sanity/sdk-react'
|
|
647
|
+
*
|
|
648
|
+
* // Define props using the DocumentHandle type
|
|
649
|
+
* interface PublishControlsProps {
|
|
650
|
+
* doc: DocumentHandle
|
|
651
|
+
* }
|
|
537
652
|
*
|
|
538
|
-
*
|
|
539
|
-
*
|
|
653
|
+
* function PublishControls({doc}: PublishControlsProps) {
|
|
654
|
+
* const apply = useApplyDocumentActions()
|
|
540
655
|
*
|
|
541
|
-
*
|
|
542
|
-
*
|
|
543
|
-
* <button onClick={() => apply(unpublishDocument(myDocument))}>Unpublish</button>
|
|
544
|
-
* )
|
|
545
|
-
* ```
|
|
656
|
+
* const handlePublish = () => apply(publishDocument(doc))
|
|
657
|
+
* const handleUnpublish = () => apply(unpublishDocument(doc))
|
|
546
658
|
*
|
|
547
|
-
*
|
|
659
|
+
* return (
|
|
660
|
+
* <>
|
|
661
|
+
* <button onClick={handlePublish}>Publish</button>
|
|
662
|
+
* <button onClick={handleUnpublish}>Unpublish</button>
|
|
663
|
+
* </>
|
|
664
|
+
* )
|
|
665
|
+
* }
|
|
548
666
|
* ```
|
|
549
|
-
* import { createDocument, publishDocument } from '@sanity/sdk'
|
|
550
|
-
* import { useApplyDocumentActions } from '@sanity/sdk-react'
|
|
551
667
|
*
|
|
552
|
-
*
|
|
668
|
+
* @example Create and publish a new document
|
|
669
|
+
* ```tsx
|
|
670
|
+
* import {
|
|
671
|
+
* createDocument,
|
|
672
|
+
* publishDocument,
|
|
673
|
+
* createDocumentHandle,
|
|
674
|
+
* useApplyDocumentActions
|
|
675
|
+
* } from '@sanity/sdk-react'
|
|
676
|
+
*
|
|
677
|
+
* function CreateAndPublishButton({documentType}: {documentType: string}) {
|
|
678
|
+
* const apply = useApplyDocumentActions()
|
|
679
|
+
*
|
|
680
|
+
* const handleCreateAndPublish = () => {
|
|
681
|
+
* // Create a new handle inside the handler
|
|
682
|
+
* const newDocHandle = createDocumentHandle({ documentId: crypto.randomUUID(), documentType })
|
|
683
|
+
*
|
|
684
|
+
* // Apply multiple actions for the new handle as a single transaction
|
|
685
|
+
* apply([
|
|
686
|
+
* createDocument(newDocHandle),
|
|
687
|
+
* publishDocument(newDocHandle),
|
|
688
|
+
* ])
|
|
689
|
+
* }
|
|
553
690
|
*
|
|
554
|
-
*
|
|
555
|
-
*
|
|
556
|
-
*
|
|
557
|
-
*
|
|
558
|
-
*
|
|
559
|
-
* ])
|
|
691
|
+
* return (
|
|
692
|
+
* <button onClick={handleCreateAndPublish}>
|
|
693
|
+
* I'm feeling lucky
|
|
694
|
+
* </button>
|
|
695
|
+
* )
|
|
560
696
|
* }
|
|
561
|
-
*
|
|
562
|
-
* return (
|
|
563
|
-
* <button onClick={handleCreateAndPublish}>
|
|
564
|
-
* I'm feeling lucky
|
|
565
|
-
* </button>
|
|
566
|
-
* )
|
|
567
697
|
* ```
|
|
568
698
|
*/
|
|
569
|
-
export declare const useApplyDocumentActions:
|
|
570
|
-
action: DocumentAction | DocumentAction[],
|
|
571
|
-
options?: ApplyDocumentActionsOptions | undefined,
|
|
572
|
-
) => Promise<ActionsResult<SanityDocument>>
|
|
699
|
+
export declare const useApplyDocumentActions: UseApplyDocumentActions
|
|
573
700
|
|
|
574
701
|
/**
|
|
575
702
|
* @internal
|
|
@@ -603,11 +730,11 @@ export declare const useAuthToken: () => string | null
|
|
|
603
730
|
|
|
604
731
|
/**
|
|
605
732
|
* A React hook that provides a client that subscribes to changes in your application,
|
|
606
|
-
* such as user authentication changes.
|
|
607
733
|
*
|
|
608
734
|
* @remarks
|
|
609
|
-
*
|
|
610
|
-
*
|
|
735
|
+
* This hook is intended for advanced use cases and special API calls that the React SDK
|
|
736
|
+
* does not yet provide hooks for. We welcome you to get in touch with us to let us know
|
|
737
|
+
* your use cases for this!
|
|
611
738
|
*
|
|
612
739
|
* @category Platform
|
|
613
740
|
* @returns A Sanity client
|
|
@@ -713,122 +840,259 @@ declare type UseDatasets = {
|
|
|
713
840
|
*/
|
|
714
841
|
export declare const useDatasets: UseDatasets
|
|
715
842
|
|
|
843
|
+
declare interface UseDocument {
|
|
844
|
+
/** @internal */
|
|
845
|
+
<TDocumentType extends string, TDataset extends string, TProjectId extends string = string>(
|
|
846
|
+
options: DocumentOptions<undefined, TDocumentType, TDataset, TProjectId>,
|
|
847
|
+
): SanityDocumentResult<TDocumentType, TDataset, TProjectId> | null
|
|
848
|
+
/** @internal */
|
|
849
|
+
<
|
|
850
|
+
TPath extends string,
|
|
851
|
+
TDocumentType extends string,
|
|
852
|
+
TDataset extends string = string,
|
|
853
|
+
TProjectId extends string = string,
|
|
854
|
+
>(
|
|
855
|
+
options: DocumentOptions<TPath, TDocumentType, TDataset, TProjectId>,
|
|
856
|
+
): JsonMatch<SanityDocumentResult<TDocumentType, TDataset, TProjectId>, TPath> | undefined
|
|
857
|
+
/** @internal */
|
|
858
|
+
<TData>(options: DocumentOptions<undefined>): TData | null
|
|
859
|
+
/** @internal */
|
|
860
|
+
<TData>(options: DocumentOptions<string>): TData | undefined
|
|
861
|
+
/**
|
|
862
|
+
* ## useDocument via Type Inference (Recommended)
|
|
863
|
+
*
|
|
864
|
+
* @beta
|
|
865
|
+
*
|
|
866
|
+
* The preferred way to use this hook when working with Sanity Typegen.
|
|
867
|
+
*
|
|
868
|
+
* Features:
|
|
869
|
+
* - Automatically infers document types from your schema
|
|
870
|
+
* - Provides type-safe access to documents and nested fields
|
|
871
|
+
* - Supports project/dataset-specific type inference
|
|
872
|
+
* - Works seamlessly with Typegen-generated types
|
|
873
|
+
*
|
|
874
|
+
* This hook will suspend while the document data is being fetched and loaded.
|
|
875
|
+
*
|
|
876
|
+
* When fetching a full document:
|
|
877
|
+
* - Returns the complete document object if it exists
|
|
878
|
+
* - Returns `null` if the document doesn't exist
|
|
879
|
+
*
|
|
880
|
+
* When fetching with a path:
|
|
881
|
+
* - Returns the value at the specified path if both the document and path exist
|
|
882
|
+
* - Returns `undefined` if either the document doesn't exist or the path doesn't exist in the document
|
|
883
|
+
*
|
|
884
|
+
* @category Documents
|
|
885
|
+
* @param options - Configuration including `documentId`, `documentType`, and optionally:
|
|
886
|
+
* - `path`: To select a nested value (returns typed value at path)
|
|
887
|
+
* - `projectId`/`dataset`: For multi-project/dataset setups
|
|
888
|
+
* @returns The document state (or nested value if path provided).
|
|
889
|
+
*
|
|
890
|
+
* @example Basic document fetch
|
|
891
|
+
* ```tsx
|
|
892
|
+
* import {useDocument, type DocumentHandle} from '@sanity/sdk-react'
|
|
893
|
+
*
|
|
894
|
+
* interface ProductViewProps {
|
|
895
|
+
* doc: DocumentHandle<'product'> // Typegen infers product type
|
|
896
|
+
* }
|
|
897
|
+
*
|
|
898
|
+
* function ProductView({doc}: ProductViewProps) {
|
|
899
|
+
* const product = useDocument({...doc}) // Fully typed product
|
|
900
|
+
* return <h1>{product.title ?? 'Untitled'}</h1>
|
|
901
|
+
* }
|
|
902
|
+
* ```
|
|
903
|
+
*
|
|
904
|
+
* @example Fetching a specific field
|
|
905
|
+
* ```tsx
|
|
906
|
+
* import {useDocument, type DocumentHandle} from '@sanity/sdk-react'
|
|
907
|
+
*
|
|
908
|
+
* interface ProductTitleProps {
|
|
909
|
+
* doc: DocumentHandle<'product'>
|
|
910
|
+
* }
|
|
911
|
+
*
|
|
912
|
+
* function ProductTitle({doc}: ProductTitleProps) {
|
|
913
|
+
* const title = useDocument({
|
|
914
|
+
* ...doc,
|
|
915
|
+
* path: 'title' // Returns just the title field
|
|
916
|
+
* })
|
|
917
|
+
* return <h1>{title ?? 'Untitled'}</h1>
|
|
918
|
+
* }
|
|
919
|
+
* ```
|
|
920
|
+
*
|
|
921
|
+
* @inlineType DocumentOptions
|
|
922
|
+
*/
|
|
923
|
+
<
|
|
924
|
+
TPath extends string | undefined = undefined,
|
|
925
|
+
TDocumentType extends string = string,
|
|
926
|
+
TDataset extends string = string,
|
|
927
|
+
TProjectId extends string = string,
|
|
928
|
+
>(
|
|
929
|
+
options: DocumentOptions<TPath, TDocumentType, TDataset, TProjectId>,
|
|
930
|
+
): TPath extends string
|
|
931
|
+
? JsonMatch<SanityDocumentResult<TDocumentType, TDataset, TProjectId>, TPath> | undefined
|
|
932
|
+
: SanityDocumentResult<TDocumentType, TDataset, TProjectId> | null
|
|
933
|
+
/**
|
|
934
|
+
* @beta
|
|
935
|
+
*
|
|
936
|
+
* ## useDocument via Explicit Types
|
|
937
|
+
*
|
|
938
|
+
* Use this version when:
|
|
939
|
+
* - You're not using Sanity Typegen
|
|
940
|
+
* - You need to manually specify document types
|
|
941
|
+
* - You're working with dynamic document types
|
|
942
|
+
*
|
|
943
|
+
* Key differences from Typegen version:
|
|
944
|
+
* - Requires manual type specification via `TData`
|
|
945
|
+
* - Returns `TData | null` for full documents
|
|
946
|
+
* - Returns `TData | undefined` for nested values
|
|
947
|
+
*
|
|
948
|
+
* This hook will suspend while the document data is being fetched.
|
|
949
|
+
*
|
|
950
|
+
* @typeParam TData - The explicit type for the document or field
|
|
951
|
+
* @typeParam TPath - Optional path to a nested value
|
|
952
|
+
* @param options - Configuration including `documentId` and optionally:
|
|
953
|
+
* - `path`: To select a nested value
|
|
954
|
+
* - `projectId`/`dataset`: For multi-project/dataset setups
|
|
955
|
+
* @returns The document state (or nested value if path provided)
|
|
956
|
+
*
|
|
957
|
+
* @example Basic document fetch with explicit type
|
|
958
|
+
* ```tsx
|
|
959
|
+
* import {useDocument, type DocumentHandle, type SanityDocument} from '@sanity/sdk-react'
|
|
960
|
+
*
|
|
961
|
+
* interface Book extends SanityDocument {
|
|
962
|
+
* _type: 'book'
|
|
963
|
+
* title: string
|
|
964
|
+
* author: string
|
|
965
|
+
* }
|
|
966
|
+
*
|
|
967
|
+
* interface BookViewProps {
|
|
968
|
+
* doc: DocumentHandle
|
|
969
|
+
* }
|
|
970
|
+
*
|
|
971
|
+
* function BookView({doc}: BookViewProps) {
|
|
972
|
+
* const book = useDocument<Book>({...doc})
|
|
973
|
+
* return <h1>{book?.title ?? 'Untitled'} by {book?.author ?? 'Unknown'}</h1>
|
|
974
|
+
* }
|
|
975
|
+
* ```
|
|
976
|
+
*
|
|
977
|
+
* @example Fetching a specific field with explicit type
|
|
978
|
+
* ```tsx
|
|
979
|
+
* import {useDocument, type DocumentHandle} from '@sanity/sdk-react'
|
|
980
|
+
*
|
|
981
|
+
* interface BookTitleProps {
|
|
982
|
+
* doc: DocumentHandle
|
|
983
|
+
* }
|
|
984
|
+
*
|
|
985
|
+
* function BookTitle({doc}: BookTitleProps) {
|
|
986
|
+
* const title = useDocument<string>({...doc, path: 'title'})
|
|
987
|
+
* return <h1>{title ?? 'Untitled'}</h1>
|
|
988
|
+
* }
|
|
989
|
+
* ```
|
|
990
|
+
*
|
|
991
|
+
* @inlineType DocumentOptions
|
|
992
|
+
*/
|
|
993
|
+
<TData, TPath extends string>(
|
|
994
|
+
options: DocumentOptions<TPath>,
|
|
995
|
+
): TPath extends string ? TData | undefined : TData | null
|
|
996
|
+
/**
|
|
997
|
+
* @internal
|
|
998
|
+
*/
|
|
999
|
+
(options: DocumentOptions): unknown
|
|
1000
|
+
}
|
|
1001
|
+
|
|
716
1002
|
/**
|
|
717
1003
|
* @beta
|
|
1004
|
+
* Reads and subscribes to a document's realtime state, incorporating both local and remote changes.
|
|
718
1005
|
*
|
|
719
|
-
*
|
|
720
|
-
* Read and subscribe to nested values in a document
|
|
721
|
-
* @category Documents
|
|
722
|
-
* @param doc - The document to read state from, specified as a DocumentHandle
|
|
723
|
-
* @param path - The path to the nested value to read from
|
|
724
|
-
* @returns The value at the specified path
|
|
725
|
-
* @example
|
|
726
|
-
* ```tsx
|
|
727
|
-
* import {useDocument} from '@sanity/sdk-react'
|
|
1006
|
+
* This hook comes in two main flavors to suit your needs:
|
|
728
1007
|
*
|
|
729
|
-
*
|
|
730
|
-
*
|
|
731
|
-
* documentType: 'order',
|
|
732
|
-
* projectId: 'abc123',
|
|
733
|
-
* dataset: 'production'
|
|
734
|
-
* }
|
|
1008
|
+
* 1. **[Type Inference](#usedocument-via-type-inference-recommended)** (Recommended) - Automatically gets types from your Sanity schema
|
|
1009
|
+
* 2. **[Explicit Types](#usedocument-via-explicit-types)** - Manually specify types when needed
|
|
735
1010
|
*
|
|
736
|
-
*
|
|
737
|
-
*
|
|
738
|
-
*
|
|
1011
|
+
* @remarks
|
|
1012
|
+
* `useDocument` is ideal for realtime editing interfaces where you need immediate feedback on changes.
|
|
1013
|
+
* However, it can be resource-intensive since it maintains a realtime connection.
|
|
739
1014
|
*
|
|
740
|
-
*
|
|
741
|
-
*
|
|
742
|
-
*
|
|
743
|
-
*
|
|
744
|
-
*
|
|
1015
|
+
* For simpler cases where:
|
|
1016
|
+
* - You only need to display content
|
|
1017
|
+
* - Realtime updates aren't critical
|
|
1018
|
+
* - You want better performance
|
|
1019
|
+
*
|
|
1020
|
+
* …consider using {@link useProjection} or {@link useQuery} instead. These hooks are more efficient
|
|
1021
|
+
* for read-heavy applications.
|
|
745
1022
|
*
|
|
1023
|
+
* @function
|
|
746
1024
|
*/
|
|
747
|
-
export declare
|
|
748
|
-
TDocument extends SanityDocument,
|
|
749
|
-
TPath extends JsonMatchPath<TDocument>,
|
|
750
|
-
>(doc: DocumentHandle<TDocument>, path: TPath): JsonMatch<TDocument, TPath> | undefined
|
|
1025
|
+
export declare const useDocument: UseDocument
|
|
751
1026
|
|
|
752
1027
|
/**
|
|
1028
|
+
*
|
|
753
1029
|
* @beta
|
|
754
|
-
* ## useDocument(doc)
|
|
755
|
-
* Read and subscribe to an entire document
|
|
756
|
-
* @param doc - The document to read state from, specified as a DocumentHandle
|
|
757
|
-
* @returns The document state as an object
|
|
758
|
-
* @example
|
|
759
|
-
* ```tsx
|
|
760
|
-
* import {type SanityDocument, useDocument} from '@sanity/sdk-react'
|
|
761
1030
|
*
|
|
762
|
-
*
|
|
763
|
-
* title: string
|
|
764
|
-
* author: string
|
|
765
|
-
* summary: string
|
|
766
|
-
* }
|
|
1031
|
+
* Subscribes an event handler to events in your application's document store.
|
|
767
1032
|
*
|
|
768
|
-
*
|
|
769
|
-
*
|
|
770
|
-
*
|
|
771
|
-
*
|
|
772
|
-
*
|
|
773
|
-
* }
|
|
1033
|
+
* @category Documents
|
|
1034
|
+
* @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.
|
|
1035
|
+
* @example Creating a custom hook for document event toasts
|
|
1036
|
+
* ```tsx
|
|
1037
|
+
* import {createDatasetHandle, type DatasetHandle, type DocumentEvent, useDocumentEvent} from '@sanity/sdk-react'
|
|
1038
|
+
* import {useToast} from './my-ui-library'
|
|
774
1039
|
*
|
|
775
|
-
*
|
|
776
|
-
*
|
|
1040
|
+
* // Define options for the custom hook, extending DatasetHandle
|
|
1041
|
+
* interface DocumentToastsOptions extends DatasetHandle {
|
|
1042
|
+
* // Could add more options, e.g., { includeEvents: DocumentEvent['type'][] }
|
|
1043
|
+
* }
|
|
777
1044
|
*
|
|
778
|
-
*
|
|
779
|
-
*
|
|
1045
|
+
* // Define the custom hook
|
|
1046
|
+
* function useDocumentToasts({...datasetHandle}: DocumentToastsOptions = {}) {
|
|
1047
|
+
* const showToast = useToast() // Get the toast function
|
|
1048
|
+
*
|
|
1049
|
+
* // Define the event handler logic to show toasts on specific events
|
|
1050
|
+
* const handleEvent = (event: DocumentEvent) => {
|
|
1051
|
+
* if (event.type === 'published') {
|
|
1052
|
+
* showToast(`Document ${event.documentId} published.`)
|
|
1053
|
+
* } else if (event.type === 'unpublished') {
|
|
1054
|
+
* showToast(`Document ${event.documentId} unpublished.`)
|
|
1055
|
+
* } else if (event.type === 'deleted') {
|
|
1056
|
+
* showToast(`Document ${event.documentId} deleted.`)
|
|
1057
|
+
* } else {
|
|
1058
|
+
* // Optionally log other events for debugging
|
|
1059
|
+
* console.log('Document Event:', event.type, event.documentId)
|
|
1060
|
+
* }
|
|
780
1061
|
* }
|
|
781
1062
|
*
|
|
782
|
-
*
|
|
783
|
-
*
|
|
784
|
-
*
|
|
785
|
-
*
|
|
1063
|
+
* // Call the original hook, spreading the handle properties
|
|
1064
|
+
* useDocumentEvent({
|
|
1065
|
+
* ...datasetHandle, // Spread the dataset handle (projectId, dataset)
|
|
1066
|
+
* onEvent: handleEvent,
|
|
1067
|
+
* })
|
|
1068
|
+
* }
|
|
786
1069
|
*
|
|
787
|
-
*
|
|
788
|
-
*
|
|
1070
|
+
* function MyComponentWithToasts() {
|
|
1071
|
+
* // Use the custom hook, passing specific handle info
|
|
1072
|
+
* const specificHandle = createDatasetHandle({ projectId: 'p1', dataset: 'ds1' })
|
|
1073
|
+
* useDocumentToasts(specificHandle)
|
|
789
1074
|
*
|
|
790
|
-
*
|
|
791
|
-
*
|
|
792
|
-
*
|
|
793
|
-
*
|
|
1075
|
+
* // // Or use it relying on context for the handle
|
|
1076
|
+
* // useDocumentToasts()
|
|
1077
|
+
*
|
|
1078
|
+
* return <div>...</div>
|
|
794
1079
|
* }
|
|
795
1080
|
* ```
|
|
796
|
-
*
|
|
797
1081
|
*/
|
|
798
|
-
export declare function
|
|
799
|
-
|
|
800
|
-
|
|
1082
|
+
export declare function useDocumentEvent<
|
|
1083
|
+
TDataset extends string = string,
|
|
1084
|
+
TProjectId extends string = string,
|
|
1085
|
+
>(options: UseDocumentEventOptions<TDataset, TProjectId>): void
|
|
801
1086
|
|
|
802
1087
|
/**
|
|
803
|
-
*
|
|
804
1088
|
* @beta
|
|
805
|
-
*
|
|
806
|
-
* Subscribes an event handler to events in your application's document store, such as document
|
|
807
|
-
* creation, deletion, and updates.
|
|
808
|
-
*
|
|
809
|
-
* @category Documents
|
|
810
|
-
* @param handler - The event handler to register.
|
|
811
|
-
* @param doc - The document to subscribe to events for. If you pass a `DocumentHandle` with specified `projectId` and `dataset`,
|
|
812
|
-
* the document will be read from the specified Sanity project and dataset that is included in the handle. If no `projectId` or `dataset` is provided,
|
|
813
|
-
* the document will use the nearest instance from context.
|
|
814
|
-
* @example
|
|
815
|
-
* ```
|
|
816
|
-
* import {useDocumentEvent} from '@sanity/sdk-react'
|
|
817
|
-
* import {type DocumentEvent} from '@sanity/sdk'
|
|
818
|
-
*
|
|
819
|
-
* useDocumentEvent((event) => {
|
|
820
|
-
* if (event.type === DocumentEvent.DocumentDeletedEvent) {
|
|
821
|
-
* alert(`Document with ID ${event.documentId} deleted!`)
|
|
822
|
-
* } else {
|
|
823
|
-
* console.log(event)
|
|
824
|
-
* }
|
|
825
|
-
* })
|
|
826
|
-
* ```
|
|
827
1089
|
*/
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
1090
|
+
declare interface UseDocumentEventOptions<
|
|
1091
|
+
TDataset extends string = string,
|
|
1092
|
+
TProjectId extends string = string,
|
|
1093
|
+
> extends DatasetHandle<TDataset, TProjectId> {
|
|
1094
|
+
onEvent: (documentEvent: DocumentEvent) => void
|
|
1095
|
+
}
|
|
832
1096
|
|
|
833
1097
|
/**
|
|
834
1098
|
*
|
|
@@ -837,23 +1101,41 @@ export declare function useDocumentEvent(
|
|
|
837
1101
|
* Check if the current user has the specified permissions for the given document actions.
|
|
838
1102
|
*
|
|
839
1103
|
* @category Permissions
|
|
840
|
-
* @param actionOrActions - One
|
|
1104
|
+
* @param actionOrActions - One or more document action functions (e.g., `publishDocument(handle)`).
|
|
841
1105
|
* @returns An object that specifies whether the action is allowed; if the action is not allowed, an explanatory message and list of reasons is also provided.
|
|
842
1106
|
*
|
|
1107
|
+
* @remarks
|
|
1108
|
+
* When passing multiple actions, all actions must belong to the same project and dataset.
|
|
1109
|
+
* Note, however, that you can check permissions on multiple documents from the same project and dataset (as in the second example below).
|
|
1110
|
+
*
|
|
843
1111
|
* @example Checking for permission to publish a document
|
|
844
|
-
* ```
|
|
845
|
-
* import {
|
|
846
|
-
*
|
|
1112
|
+
* ```tsx
|
|
1113
|
+
* import {
|
|
1114
|
+
* useDocumentPermissions,
|
|
1115
|
+
* useApplyDocumentActions,
|
|
1116
|
+
* publishDocument,
|
|
1117
|
+
* createDocumentHandle,
|
|
1118
|
+
* type DocumentHandle
|
|
1119
|
+
* } from '@sanity/sdk-react'
|
|
1120
|
+
*
|
|
1121
|
+
* // Define props using the DocumentHandle type
|
|
1122
|
+
* interface PublishButtonProps {
|
|
1123
|
+
* doc: DocumentHandle
|
|
1124
|
+
* }
|
|
1125
|
+
*
|
|
1126
|
+
* function PublishButton({doc}: PublishButtonProps) {
|
|
1127
|
+
* const publishAction = publishDocument(doc)
|
|
847
1128
|
*
|
|
848
|
-
*
|
|
849
|
-
* const publishPermissions = useDocumentPermissions(
|
|
850
|
-
* const
|
|
1129
|
+
* // Pass the same action call to check permissions
|
|
1130
|
+
* const publishPermissions = useDocumentPermissions(publishAction)
|
|
1131
|
+
* const apply = useApplyDocumentActions()
|
|
851
1132
|
*
|
|
852
1133
|
* return (
|
|
853
1134
|
* <>
|
|
854
1135
|
* <button
|
|
855
1136
|
* disabled={!publishPermissions.allowed}
|
|
856
|
-
*
|
|
1137
|
+
* // Pass the same action call to apply the action
|
|
1138
|
+
* onClick={() => apply(publishAction)}
|
|
857
1139
|
* popoverTarget={`${publishPermissions.allowed ? undefined : 'publishButtonPopover'}`}
|
|
858
1140
|
* >
|
|
859
1141
|
* Publish
|
|
@@ -866,6 +1148,27 @@ export declare function useDocumentEvent(
|
|
|
866
1148
|
* </>
|
|
867
1149
|
* )
|
|
868
1150
|
* }
|
|
1151
|
+
*
|
|
1152
|
+
* // Usage:
|
|
1153
|
+
* // const doc = createDocumentHandle({ documentId: 'doc1', documentType: 'myType' })
|
|
1154
|
+
* // <PublishButton doc={doc} />
|
|
1155
|
+
* ```
|
|
1156
|
+
*
|
|
1157
|
+
* @example Checking for permissions to edit multiple documents
|
|
1158
|
+
* ```tsx
|
|
1159
|
+
* import {
|
|
1160
|
+
* useDocumentPermissions,
|
|
1161
|
+
* editDocument,
|
|
1162
|
+
* type DocumentHandle
|
|
1163
|
+
* } from '@sanity/sdk-react'
|
|
1164
|
+
*
|
|
1165
|
+
* export default function canEditMultiple(docHandles: DocumentHandle[]) {
|
|
1166
|
+
* // Create an array containing an editDocument action for each of the document handles
|
|
1167
|
+
* const editActions = docHandles.map(doc => editDocument(doc))
|
|
1168
|
+
*
|
|
1169
|
+
* // Return the result of checking for edit permissions on all of the document handles
|
|
1170
|
+
* return useDocumentPermissions(editActions)
|
|
1171
|
+
* }
|
|
869
1172
|
* ```
|
|
870
1173
|
*/
|
|
871
1174
|
export declare function useDocumentPermissions(
|
|
@@ -889,38 +1192,115 @@ export declare function useDocumentPermissions(
|
|
|
889
1192
|
*
|
|
890
1193
|
* @example Basic infinite list with loading more
|
|
891
1194
|
* ```tsx
|
|
892
|
-
*
|
|
893
|
-
*
|
|
894
|
-
*
|
|
895
|
-
*
|
|
896
|
-
*
|
|
897
|
-
*
|
|
1195
|
+
* import {
|
|
1196
|
+
* useDocuments,
|
|
1197
|
+
* createDatasetHandle,
|
|
1198
|
+
* type DatasetHandle,
|
|
1199
|
+
* type DocumentHandle,
|
|
1200
|
+
* type SortOrderingItem
|
|
1201
|
+
* } from '@sanity/sdk-react'
|
|
1202
|
+
* import {Suspense} from 'react'
|
|
1203
|
+
*
|
|
1204
|
+
* // Define a component to display a single document (using useProjection for efficiency)
|
|
1205
|
+
* function MyDocumentComponent({doc}: {doc: DocumentHandle}) {
|
|
1206
|
+
* const {data} = useProjection<{title?: string}>({
|
|
1207
|
+
* ...doc, // Pass the full handle
|
|
1208
|
+
* projection: '{title}'
|
|
1209
|
+
* })
|
|
898
1210
|
*
|
|
899
|
-
*
|
|
900
|
-
*
|
|
901
|
-
*
|
|
902
|
-
*
|
|
903
|
-
*
|
|
904
|
-
*
|
|
905
|
-
*
|
|
906
|
-
*
|
|
1211
|
+
* return <>{data?.title || 'Untitled'}</>
|
|
1212
|
+
* }
|
|
1213
|
+
*
|
|
1214
|
+
* // Define props for the list component
|
|
1215
|
+
* interface DocumentListProps {
|
|
1216
|
+
* dataset: DatasetHandle
|
|
1217
|
+
* documentType: string
|
|
1218
|
+
* search?: string
|
|
1219
|
+
* }
|
|
1220
|
+
*
|
|
1221
|
+
* function DocumentList({dataset, documentType, search}: DocumentListProps) {
|
|
1222
|
+
* const { data, hasMore, isPending, loadMore, count } = useDocuments({
|
|
1223
|
+
* ...dataset,
|
|
1224
|
+
* documentType,
|
|
1225
|
+
* search,
|
|
1226
|
+
* batchSize: 10,
|
|
1227
|
+
* orderings: [{field: '_createdAt', direction: 'desc'}],
|
|
1228
|
+
* })
|
|
1229
|
+
*
|
|
1230
|
+
* return (
|
|
1231
|
+
* <div>
|
|
1232
|
+
* <p>Total documents: {count}</p>
|
|
1233
|
+
* <ol>
|
|
1234
|
+
* {data.map((docHandle) => (
|
|
1235
|
+
* <li key={docHandle.documentId}>
|
|
1236
|
+
* <Suspense fallback="Loading…">
|
|
1237
|
+
* <MyDocumentComponent docHandle={docHandle} />
|
|
1238
|
+
* </Suspense>
|
|
1239
|
+
* </li>
|
|
1240
|
+
* ))}
|
|
1241
|
+
* </ol>
|
|
1242
|
+
* {hasMore && (
|
|
1243
|
+
* <button onClick={loadMore}>
|
|
1244
|
+
* {isPending ? 'Loading...' : 'Load More'}
|
|
1245
|
+
* </button>
|
|
1246
|
+
* )}
|
|
1247
|
+
* </div>
|
|
1248
|
+
* )
|
|
1249
|
+
* }
|
|
1250
|
+
*
|
|
1251
|
+
* // Usage:
|
|
1252
|
+
* // const myDatasetHandle = createDatasetHandle({ projectId: 'p1', dataset: 'production' })
|
|
1253
|
+
* // <DocumentList dataset={myDatasetHandle} documentType="post" search="Sanity" />
|
|
1254
|
+
* ```
|
|
1255
|
+
*
|
|
1256
|
+
* @example Using `filter` and `params` options for narrowing a collection
|
|
1257
|
+
* ```tsx
|
|
1258
|
+
* import {useState} from 'react'
|
|
1259
|
+
* import {useDocuments} from '@sanity/sdk-react'
|
|
1260
|
+
*
|
|
1261
|
+
* export default function FilteredAuthors() {
|
|
1262
|
+
* const [max, setMax] = useState(2)
|
|
1263
|
+
* const {data} = useDocuments({
|
|
1264
|
+
* documentType: 'author',
|
|
1265
|
+
* filter: 'length(books) <= $max',
|
|
1266
|
+
* params: {max},
|
|
1267
|
+
* })
|
|
1268
|
+
*
|
|
1269
|
+
* return (
|
|
1270
|
+
* <>
|
|
1271
|
+
* <input
|
|
1272
|
+
* id="maxBooks"
|
|
1273
|
+
* type="number"
|
|
1274
|
+
* value={max}
|
|
1275
|
+
* onChange={e => setMax(e.currentTarget.value)}
|
|
1276
|
+
* />
|
|
1277
|
+
* {data.map(author => (
|
|
1278
|
+
* <Suspense key={author.documentId}>
|
|
1279
|
+
* <MyAuthorComponent documentHandle={author} />
|
|
1280
|
+
* </Suspense>
|
|
907
1281
|
* ))}
|
|
908
|
-
*
|
|
909
|
-
*
|
|
910
|
-
*
|
|
911
|
-
* </button>}
|
|
912
|
-
* </div>
|
|
913
|
-
* )
|
|
1282
|
+
* </>
|
|
1283
|
+
* )
|
|
1284
|
+
* }
|
|
914
1285
|
* ```
|
|
915
1286
|
*/
|
|
916
|
-
export declare function useDocuments
|
|
1287
|
+
export declare function useDocuments<
|
|
1288
|
+
TDocumentType extends string = string,
|
|
1289
|
+
TDataset extends string = string,
|
|
1290
|
+
TProjectId extends string = string,
|
|
1291
|
+
>({
|
|
917
1292
|
batchSize,
|
|
918
1293
|
params,
|
|
919
1294
|
search,
|
|
920
1295
|
filter,
|
|
921
1296
|
orderings,
|
|
1297
|
+
documentType,
|
|
922
1298
|
...options
|
|
923
|
-
}: DocumentsOptions): DocumentsResponse
|
|
1299
|
+
}: DocumentsOptions<TDocumentType, TDataset, TProjectId>): DocumentsResponse<
|
|
1300
|
+
TDocumentType,
|
|
1301
|
+
TDataset,
|
|
1302
|
+
TProjectId
|
|
1303
|
+
>
|
|
924
1304
|
|
|
925
1305
|
declare type UseDocumentSyncStatus = {
|
|
926
1306
|
/**
|
|
@@ -930,20 +1310,32 @@ declare type UseDocumentSyncStatus = {
|
|
|
930
1310
|
* @param doc - The document handle to get sync status for. If you pass a `DocumentHandle` with specified `projectId` and `dataset`,
|
|
931
1311
|
* the document will be read from the specified Sanity project and dataset that is included in the handle. If no `projectId` or `dataset` is provided,
|
|
932
1312
|
* the document will use the nearest instance from context.
|
|
933
|
-
* @returns `true` if local changes are synced with remote, `false` if
|
|
934
|
-
* @example
|
|
935
|
-
* ```
|
|
936
|
-
*
|
|
937
|
-
* const documentSynced = useDocumentSyncStatus(myDocumentHandle)
|
|
1313
|
+
* @returns `true` if local changes are synced with remote, `false` if changes are pending. Note: Suspense handles loading states.
|
|
1314
|
+
* @example Show sync status indicator
|
|
1315
|
+
* ```tsx
|
|
1316
|
+
* import {useDocumentSyncStatus, createDocumentHandle, type DocumentHandle} from '@sanity/sdk-react'
|
|
938
1317
|
*
|
|
939
|
-
*
|
|
940
|
-
*
|
|
941
|
-
*
|
|
942
|
-
*
|
|
943
|
-
*
|
|
1318
|
+
* // Define props including the DocumentHandle type
|
|
1319
|
+
* interface SyncIndicatorProps {
|
|
1320
|
+
* doc: DocumentHandle
|
|
1321
|
+
* }
|
|
1322
|
+
*
|
|
1323
|
+
* function SyncIndicator({doc}: SyncIndicatorProps) {
|
|
1324
|
+
* const isSynced = useDocumentSyncStatus(doc)
|
|
1325
|
+
*
|
|
1326
|
+
* return (
|
|
1327
|
+
* <div className={`sync-status ${isSynced ? 'synced' : 'pending'}`}>
|
|
1328
|
+
* {isSynced ? '✓ Synced' : 'Saving changes...'}
|
|
1329
|
+
* </div>
|
|
1330
|
+
* )
|
|
1331
|
+
* }
|
|
1332
|
+
*
|
|
1333
|
+
* // Usage:
|
|
1334
|
+
* // const doc = createDocumentHandle({ documentId: 'doc1', documentType: 'myType' })
|
|
1335
|
+
* // <SyncIndicator doc={doc} />
|
|
944
1336
|
* ```
|
|
945
1337
|
*/
|
|
946
|
-
(doc: DocumentHandle): boolean
|
|
1338
|
+
(doc: DocumentHandle): boolean
|
|
947
1339
|
}
|
|
948
1340
|
|
|
949
1341
|
/**
|
|
@@ -953,142 +1345,65 @@ declare type UseDocumentSyncStatus = {
|
|
|
953
1345
|
export declare const useDocumentSyncStatus: UseDocumentSyncStatus
|
|
954
1346
|
|
|
955
1347
|
/**
|
|
956
|
-
*
|
|
957
1348
|
* @beta
|
|
1349
|
+
* Edit an entire document, relying on Typegen for the type.
|
|
958
1350
|
*
|
|
959
|
-
*
|
|
960
|
-
*
|
|
961
|
-
*
|
|
962
|
-
* @category Documents
|
|
963
|
-
* @param docHandle - The document to be edited, specified as a DocumentHandle
|
|
964
|
-
* @param path - The path to the nested value to be edited
|
|
965
|
-
* @returns A function to update the nested value. Accepts either a new value, or an updater function that exposes the previous value and returns a new value.
|
|
966
|
-
* @example Update a document's name by providing the new value directly
|
|
967
|
-
* ```tsx
|
|
968
|
-
* const handle = {
|
|
969
|
-
* documentId: 'movie-123',
|
|
970
|
-
* documentType: 'movie',
|
|
971
|
-
* projectId: 'abc123',
|
|
972
|
-
* dataset: 'production'
|
|
973
|
-
* }
|
|
974
|
-
*
|
|
975
|
-
* const name = useDocument(handle, 'name')
|
|
976
|
-
* const editName = useEditDocument(handle, 'name')
|
|
977
|
-
*
|
|
978
|
-
* function handleNameChange(event: React.ChangeEvent<HTMLInputElement>) {
|
|
979
|
-
* editName(event.target.value)
|
|
980
|
-
* }
|
|
981
|
-
*
|
|
982
|
-
* return (
|
|
983
|
-
* <input type='text' value={name} onChange={handleNameChange} />
|
|
984
|
-
* )
|
|
985
|
-
* ```
|
|
986
|
-
*
|
|
987
|
-
* @example Update a count on a document by providing an updater function
|
|
988
|
-
* ```tsx
|
|
989
|
-
* const handle = {
|
|
990
|
-
* documentId: 'counter-123',
|
|
991
|
-
* documentType: 'counter',
|
|
992
|
-
* projectId: 'abc123',
|
|
993
|
-
* dataset: 'production'
|
|
994
|
-
* }
|
|
995
|
-
*
|
|
996
|
-
* const count = useDocument(handle, 'count')
|
|
997
|
-
* const editCount = useEditDocument(handle, 'count')
|
|
998
|
-
*
|
|
999
|
-
* function incrementCount() {
|
|
1000
|
-
* editCount(previousCount => previousCount + 1)
|
|
1001
|
-
* }
|
|
1002
|
-
*
|
|
1003
|
-
* return (
|
|
1004
|
-
* <>
|
|
1005
|
-
* <button onClick={incrementCount}>
|
|
1006
|
-
* Increment
|
|
1007
|
-
* </button>
|
|
1008
|
-
* Current count: {count}
|
|
1009
|
-
* </>
|
|
1010
|
-
* )
|
|
1011
|
-
* ```
|
|
1351
|
+
* @param options - Document options including `documentId`, `documentType`, and optionally `projectId`/`dataset`.
|
|
1352
|
+
* @returns A stable function to update the document state. Accepts either the new document state or an updater function `(currentValue) => nextValue`.
|
|
1353
|
+
* Returns a promise resolving to the {@link ActionsResult}.
|
|
1012
1354
|
*/
|
|
1013
1355
|
export declare function useEditDocument<
|
|
1014
|
-
|
|
1015
|
-
|
|
1356
|
+
TDocumentType extends string = string,
|
|
1357
|
+
TDataset extends string = string,
|
|
1358
|
+
TProjectId extends string = string,
|
|
1016
1359
|
>(
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1360
|
+
options: DocumentOptions<undefined, TDocumentType, TDataset, TProjectId>,
|
|
1361
|
+
): (
|
|
1362
|
+
nextValue: Updater<SanityDocumentResult<TDocumentType, TDataset, TProjectId>>,
|
|
1363
|
+
) => Promise<ActionsResult<SanityDocumentResult<TDocumentType, TDataset, TProjectId>>>
|
|
1020
1364
|
|
|
1021
1365
|
/**
|
|
1022
|
-
*
|
|
1023
1366
|
* @beta
|
|
1367
|
+
* Edit a specific path within a document, relying on Typegen for the type.
|
|
1024
1368
|
*
|
|
1025
|
-
*
|
|
1026
|
-
*
|
|
1027
|
-
*
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
*
|
|
1042
|
-
*
|
|
1043
|
-
*
|
|
1044
|
-
* function handleFieldChange(e: React.ChangeEvent<HTMLInputElement>) {
|
|
1045
|
-
* const {name, value} = e.currentTarget
|
|
1046
|
-
* // Use an updater function to update the document state based on the previous state
|
|
1047
|
-
* editMyDocument(previousDocument => ({
|
|
1048
|
-
* ...previousDocument,
|
|
1049
|
-
* [name]: value
|
|
1050
|
-
* }))
|
|
1051
|
-
* }
|
|
1369
|
+
* @param options - Document options including `documentId`, `documentType`, `path`, and optionally `projectId`/`dataset`.
|
|
1370
|
+
* @returns A stable function to update the value at the specified path. Accepts either the new value or an updater function `(currentValue) => nextValue`.
|
|
1371
|
+
* Returns a promise resolving to the {@link ActionsResult}.
|
|
1372
|
+
*/
|
|
1373
|
+
export declare function useEditDocument<
|
|
1374
|
+
TPath extends string = string,
|
|
1375
|
+
TDocumentType extends string = string,
|
|
1376
|
+
TDataset extends string = string,
|
|
1377
|
+
TProjectId extends string = string,
|
|
1378
|
+
>(
|
|
1379
|
+
options: DocumentOptions<TPath, TDocumentType, TDataset, TProjectId>,
|
|
1380
|
+
): (
|
|
1381
|
+
nextValue: Updater<JsonMatch<SanityDocumentResult<TDocumentType, TDataset, TProjectId>, TPath>>,
|
|
1382
|
+
) => Promise<ActionsResult<SanityDocumentResult<TDocumentType, TDataset, TProjectId>>>
|
|
1383
|
+
|
|
1384
|
+
/**
|
|
1385
|
+
* @beta
|
|
1386
|
+
* Edit an entire document with an explicit type `TData`.
|
|
1052
1387
|
*
|
|
1053
|
-
*
|
|
1054
|
-
*
|
|
1055
|
-
*
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
*
|
|
1063
|
-
*
|
|
1064
|
-
* const { salePrice, ...rest } = myDocument
|
|
1065
|
-
* // Update the document state to remove the salePrice field
|
|
1066
|
-
* editMyDocument(rest)
|
|
1067
|
-
* }
|
|
1068
|
-
* }
|
|
1388
|
+
* @param options - Document options including `documentId` and optionally `projectId`/`dataset`.
|
|
1389
|
+
* @returns A stable function to update the document state. Accepts either the new document state (`TData`) or an updater function `(currentValue: TData) => nextValue: TData`.
|
|
1390
|
+
* Returns a promise resolving to the {@link ActionsResult}.
|
|
1391
|
+
*/
|
|
1392
|
+
export declare function useEditDocument<TData>(
|
|
1393
|
+
options: DocumentOptions<undefined>,
|
|
1394
|
+
): (nextValue: Updater<TData>) => Promise<ActionsResult>
|
|
1395
|
+
|
|
1396
|
+
/**
|
|
1397
|
+
* @beta
|
|
1398
|
+
* Edit a specific path within a document with an explicit type `TData`.
|
|
1069
1399
|
*
|
|
1070
|
-
*
|
|
1071
|
-
*
|
|
1072
|
-
*
|
|
1073
|
-
* <input name='title' type='text' value={title} onChange={handleFieldChange} />
|
|
1074
|
-
* <input name='price' type='number' value={price} onChange={handleFieldChange} />
|
|
1075
|
-
* <input
|
|
1076
|
-
* name='salePrice'
|
|
1077
|
-
* type='checkbox'
|
|
1078
|
-
* checked={myDocument && 'salePrice' in myDocument}
|
|
1079
|
-
* onChange={handleSaleChange}
|
|
1080
|
-
* />
|
|
1081
|
-
* </form>
|
|
1082
|
-
* <pre><code>
|
|
1083
|
-
* {JSON.stringify(myDocument, null, 2)}
|
|
1084
|
-
* </code></pre>
|
|
1085
|
-
* </>
|
|
1086
|
-
* )
|
|
1087
|
-
* ```
|
|
1400
|
+
* @param options - Document options including `documentId`, `path`, and optionally `projectId`/`dataset`.
|
|
1401
|
+
* @returns A stable function to update the value at the specified path. Accepts either the new value (`TData`) or an updater function `(currentValue: TData) => nextValue: TData`.
|
|
1402
|
+
* Returns a promise resolving to the {@link ActionsResult}.
|
|
1088
1403
|
*/
|
|
1089
|
-
export declare function useEditDocument<
|
|
1090
|
-
|
|
1091
|
-
): (nextValue: Updater<
|
|
1404
|
+
export declare function useEditDocument<TData>(
|
|
1405
|
+
options: DocumentOptions<string>,
|
|
1406
|
+
): (nextValue: Updater<TData>) => Promise<ActionsResult>
|
|
1092
1407
|
|
|
1093
1408
|
/**
|
|
1094
1409
|
* @internal
|
|
@@ -1189,7 +1504,7 @@ export declare const useLogOut: () => () => Promise<void>
|
|
|
1189
1504
|
*
|
|
1190
1505
|
* @example
|
|
1191
1506
|
* ```tsx
|
|
1192
|
-
* function
|
|
1507
|
+
* function FavoriteButton(props: DocumentActionProps) {
|
|
1193
1508
|
* const {documentId, documentType} = props
|
|
1194
1509
|
* const {favorite, unfavorite, isFavorited, isConnected} = useManageFavorite({
|
|
1195
1510
|
* documentId,
|
|
@@ -1204,6 +1519,22 @@ export declare const useLogOut: () => () => Promise<void>
|
|
|
1204
1519
|
* />
|
|
1205
1520
|
* )
|
|
1206
1521
|
* }
|
|
1522
|
+
*
|
|
1523
|
+
* // Wrap the component with Suspense since the hook may suspend
|
|
1524
|
+
* function MyDocumentAction(props: DocumentActionProps) {
|
|
1525
|
+
* return (
|
|
1526
|
+
* <Suspense
|
|
1527
|
+
* fallback={
|
|
1528
|
+
* <Button
|
|
1529
|
+
* text="Loading..."
|
|
1530
|
+
* disabled
|
|
1531
|
+
* />
|
|
1532
|
+
* }
|
|
1533
|
+
* >
|
|
1534
|
+
* <FavoriteButton {...props} />
|
|
1535
|
+
* </Suspense>
|
|
1536
|
+
* )
|
|
1537
|
+
* }
|
|
1207
1538
|
* ```
|
|
1208
1539
|
*/
|
|
1209
1540
|
export declare function useManageFavorite({
|
|
@@ -1273,54 +1604,141 @@ export declare function useNavigateToStudioDocument(
|
|
|
1273
1604
|
* @beta
|
|
1274
1605
|
* @category Documents
|
|
1275
1606
|
* @param options - Configuration options for the paginated list
|
|
1276
|
-
* @returns An object containing the
|
|
1607
|
+
* @returns An object containing the list of document handles, pagination details, and functions to navigate between pages
|
|
1277
1608
|
*
|
|
1278
1609
|
* @remarks
|
|
1279
1610
|
* - The returned document handles include projectId and dataset information from the current Sanity instance
|
|
1280
1611
|
* - This makes them ready to use with document operations and other document hooks
|
|
1281
1612
|
* - The hook automatically uses the correct Sanity instance based on the projectId and dataset in the options
|
|
1282
1613
|
*
|
|
1283
|
-
* @example
|
|
1614
|
+
* @example Paginated list of documents with navigation
|
|
1284
1615
|
* ```tsx
|
|
1285
|
-
*
|
|
1286
|
-
*
|
|
1287
|
-
*
|
|
1288
|
-
*
|
|
1289
|
-
*
|
|
1290
|
-
*
|
|
1291
|
-
*
|
|
1292
|
-
*
|
|
1293
|
-
*
|
|
1294
|
-
* }
|
|
1295
|
-
*
|
|
1296
|
-
*
|
|
1297
|
-
*
|
|
1298
|
-
*
|
|
1299
|
-
*
|
|
1616
|
+
* import {
|
|
1617
|
+
* usePaginatedDocuments,
|
|
1618
|
+
* createDatasetHandle,
|
|
1619
|
+
* type DatasetHandle,
|
|
1620
|
+
* type DocumentHandle,
|
|
1621
|
+
* type SortOrderingItem,
|
|
1622
|
+
* useProjection
|
|
1623
|
+
* } from '@sanity/sdk-react'
|
|
1624
|
+
* import {Suspense} from 'react'
|
|
1625
|
+
* import {ErrorBoundary} from 'react-error-boundary'
|
|
1626
|
+
*
|
|
1627
|
+
* // Define a component to display a single document row
|
|
1628
|
+
* function MyTableRowComponent({doc}: {doc: DocumentHandle}) {
|
|
1629
|
+
* const {data} = useProjection<{title?: string}>({
|
|
1630
|
+
* ...doc,
|
|
1631
|
+
* projection: '{title}',
|
|
1632
|
+
* })
|
|
1300
1633
|
*
|
|
1301
|
-
*
|
|
1302
|
-
*
|
|
1303
|
-
*
|
|
1304
|
-
*
|
|
1305
|
-
*
|
|
1306
|
-
*
|
|
1307
|
-
* </table>
|
|
1308
|
-
* {hasPreviousPage && <button onClick={previousPage}>Previous</button>}
|
|
1309
|
-
* {currentPage} / {totalPages}
|
|
1310
|
-
* {hasNextPage && <button onClick={nextPage}>Next</button>}
|
|
1311
|
-
* </>
|
|
1312
|
-
* )
|
|
1313
|
-
* ```
|
|
1634
|
+
* return (
|
|
1635
|
+
* <tr>
|
|
1636
|
+
* <td>{data?.title ?? 'Untitled'}</td>
|
|
1637
|
+
* </tr>
|
|
1638
|
+
* )
|
|
1639
|
+
* }
|
|
1314
1640
|
*
|
|
1641
|
+
* // Define props for the list component
|
|
1642
|
+
* interface PaginatedDocumentListProps {
|
|
1643
|
+
* documentType: string
|
|
1644
|
+
* dataset?: DatasetHandle
|
|
1645
|
+
* }
|
|
1646
|
+
*
|
|
1647
|
+
* function PaginatedDocumentList({documentType, dataset}: PaginatedDocumentListProps) {
|
|
1648
|
+
* const {
|
|
1649
|
+
* data,
|
|
1650
|
+
* isPending,
|
|
1651
|
+
* currentPage,
|
|
1652
|
+
* totalPages,
|
|
1653
|
+
* nextPage,
|
|
1654
|
+
* previousPage,
|
|
1655
|
+
* hasNextPage,
|
|
1656
|
+
* hasPreviousPage
|
|
1657
|
+
* } = usePaginatedDocuments({
|
|
1658
|
+
* ...dataset,
|
|
1659
|
+
* documentType,
|
|
1660
|
+
* pageSize: 10,
|
|
1661
|
+
* orderings: [{field: '_createdAt', direction: 'desc'}],
|
|
1662
|
+
* })
|
|
1663
|
+
*
|
|
1664
|
+
* return (
|
|
1665
|
+
* <div>
|
|
1666
|
+
* <table>
|
|
1667
|
+
* <thead>
|
|
1668
|
+
* <tr><th>Title</th></tr>
|
|
1669
|
+
* </thead>
|
|
1670
|
+
* <tbody>
|
|
1671
|
+
* {data.map(doc => (
|
|
1672
|
+
* <ErrorBoundary key={doc.documentId} fallback={<tr><td>Error loading document</td></tr>}>
|
|
1673
|
+
* <Suspense fallback={<tr><td>Loading...</td></tr>}>
|
|
1674
|
+
* <MyTableRowComponent doc={doc} />
|
|
1675
|
+
* </Suspense>
|
|
1676
|
+
* </ErrorBoundary>
|
|
1677
|
+
* ))}
|
|
1678
|
+
* </tbody>
|
|
1679
|
+
* </table>
|
|
1680
|
+
* <div style={{opacity: isPending ? 0.5 : 1}}>
|
|
1681
|
+
* <button onClick={previousPage} disabled={!hasPreviousPage || isPending}>Previous</button>
|
|
1682
|
+
* <span>Page {currentPage} / {totalPages}</span>
|
|
1683
|
+
* <button onClick={nextPage} disabled={!hasNextPage || isPending}>Next</button>
|
|
1684
|
+
* </div>
|
|
1685
|
+
* </div>
|
|
1686
|
+
* )
|
|
1687
|
+
* }
|
|
1688
|
+
*
|
|
1689
|
+
* // Usage:
|
|
1690
|
+
* // const myDatasetHandle = createDatasetHandle({ projectId: 'p1', dataset: 'production' })
|
|
1691
|
+
* // <PaginatedDocumentList dataset={myDatasetHandle} documentType="post" />
|
|
1692
|
+
* ```
|
|
1315
1693
|
*/
|
|
1316
|
-
export declare function usePaginatedDocuments
|
|
1694
|
+
export declare function usePaginatedDocuments<
|
|
1695
|
+
TDocumentType extends string = string,
|
|
1696
|
+
TDataset extends string = string,
|
|
1697
|
+
TProjectId extends string = string,
|
|
1698
|
+
>({
|
|
1699
|
+
documentType,
|
|
1317
1700
|
filter,
|
|
1318
1701
|
pageSize,
|
|
1319
1702
|
params,
|
|
1320
1703
|
orderings,
|
|
1321
1704
|
search,
|
|
1322
1705
|
...options
|
|
1323
|
-
}: PaginatedDocumentsOptions): PaginatedDocumentsResponse
|
|
1706
|
+
}: PaginatedDocumentsOptions<TDocumentType, TDataset, TProjectId>): PaginatedDocumentsResponse<
|
|
1707
|
+
TDocumentType,
|
|
1708
|
+
TDataset,
|
|
1709
|
+
TProjectId
|
|
1710
|
+
>
|
|
1711
|
+
|
|
1712
|
+
/**
|
|
1713
|
+
* @public
|
|
1714
|
+
*/
|
|
1715
|
+
declare type UsePerspective = {
|
|
1716
|
+
(perspectiveHandle: PerspectiveHandle): string | string[]
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
/**
|
|
1720
|
+
* @public
|
|
1721
|
+
* @function
|
|
1722
|
+
*
|
|
1723
|
+
* Returns a single or stack of perspectives for the given perspective handle,
|
|
1724
|
+
* which can then be used to correctly query the documents
|
|
1725
|
+
* via the `perspective` parameter in the client.
|
|
1726
|
+
*
|
|
1727
|
+
* @param perspectiveHandle - The perspective handle to get the perspective for.
|
|
1728
|
+
* @category Documents
|
|
1729
|
+
* @example
|
|
1730
|
+
* ```tsx
|
|
1731
|
+
* import {usePerspective, useQuery} from '@sanity/sdk-react'
|
|
1732
|
+
|
|
1733
|
+
* const perspective = usePerspective({perspective: 'rxg1346', projectId: 'abc123', dataset: 'production'})
|
|
1734
|
+
* const {data} = useQuery<Movie[]>('*[_type == "movie"]', {
|
|
1735
|
+
* perspective: perspective,
|
|
1736
|
+
* })
|
|
1737
|
+
* ```
|
|
1738
|
+
*
|
|
1739
|
+
* @returns The perspective for the given perspective handle.
|
|
1740
|
+
*/
|
|
1741
|
+
export declare const usePerspective: UsePerspective
|
|
1324
1742
|
|
|
1325
1743
|
/**
|
|
1326
1744
|
* @beta
|
|
@@ -1424,83 +1842,160 @@ export declare const useProject: UseProject
|
|
|
1424
1842
|
/**
|
|
1425
1843
|
* @public
|
|
1426
1844
|
*
|
|
1427
|
-
* Returns the
|
|
1428
|
-
*
|
|
1429
|
-
* To
|
|
1430
|
-
*
|
|
1845
|
+
* Returns the projected values of a document based on the provided projection string.
|
|
1846
|
+
* These values are live and will update in realtime.
|
|
1847
|
+
* To optimize network requests, an optional `ref` can be passed to only resolve the projection
|
|
1848
|
+
* when the referenced element is intersecting the viewport.
|
|
1431
1849
|
*
|
|
1432
1850
|
* @category Documents
|
|
1433
|
-
* @
|
|
1434
|
-
*
|
|
1851
|
+
* @remarks
|
|
1852
|
+
* This hook has multiple signatures allowing for fine-grained control over type inference:
|
|
1853
|
+
* - Using Typegen: Infers the return type based on the `documentType`, `dataset`, `projectId`, and `projection`.
|
|
1854
|
+
* - Using explicit type parameter: Allows specifying a custom return type `TData`.
|
|
1435
1855
|
*
|
|
1436
|
-
* @
|
|
1437
|
-
*
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
*
|
|
1441
|
-
*
|
|
1442
|
-
*
|
|
1856
|
+
* @param options - An object containing the `DocumentHandle` properties (`documentId`, `documentType`, etc.), the `projection` string, optional `params`, and an optional `ref`.
|
|
1857
|
+
* @returns An object containing the projection results (`data`) and a boolean indicating whether the resolution is pending (`isPending`). Note: Suspense handles initial loading states; `data` being `undefined` after initial loading means the document doesn't exist or the projection yielded no result.
|
|
1858
|
+
*/
|
|
1859
|
+
/**
|
|
1860
|
+
* @beta
|
|
1861
|
+
* Fetch a projection, relying on Typegen for the return type based on the handle and projection.
|
|
1862
|
+
*
|
|
1863
|
+
* @category Documents
|
|
1864
|
+
* @param options - Options including the document handle properties (`documentId`, `documentType`, etc.) and the `projection`.
|
|
1865
|
+
* @returns The projected data, typed based on Typegen.
|
|
1866
|
+
*
|
|
1867
|
+
* @example Using Typegen for a book preview
|
|
1868
|
+
* ```tsx
|
|
1869
|
+
* // ProjectionComponent.tsx
|
|
1870
|
+
* import {useProjection, type DocumentHandle} from '@sanity/sdk-react'
|
|
1871
|
+
* import {useRef} from 'react'
|
|
1872
|
+
* import {defineProjection} from 'groq'
|
|
1873
|
+
*
|
|
1874
|
+
* // Define props using DocumentHandle with the specific document type
|
|
1875
|
+
* type ProjectionComponentProps = {
|
|
1876
|
+
* doc: DocumentHandle<'book'> // Typegen knows 'book'
|
|
1877
|
+
* }
|
|
1878
|
+
*
|
|
1879
|
+
* // This is required for typegen to generate the correct return type
|
|
1880
|
+
* const myProjection = defineProjection(`{
|
|
1881
|
+
* title,
|
|
1882
|
+
* 'coverImage': cover.asset->url,
|
|
1883
|
+
* 'authors': array::join(authors[]->{'name': firstName + ' ' + lastName}.name, ', ')
|
|
1884
|
+
* }`)
|
|
1885
|
+
*
|
|
1886
|
+
* export default function ProjectionComponent({ doc }: ProjectionComponentProps) {
|
|
1887
|
+
* const ref = useRef(null) // Optional ref to track viewport intersection for lazy loading
|
|
1888
|
+
*
|
|
1889
|
+
* // Spread the doc handle into the options
|
|
1890
|
+
* // Typegen infers the return type based on 'book' and the projection
|
|
1891
|
+
* const { data } = useProjection({
|
|
1892
|
+
* ...doc, // Pass the handle properties
|
|
1443
1893
|
* ref,
|
|
1444
|
-
* projection:
|
|
1445
|
-
* title,
|
|
1446
|
-
* 'coverImage': cover.asset->url,
|
|
1447
|
-
* 'authors': array::join(authors[]->{'name': firstName + ' ' + lastName + ' '}.name, ', ')
|
|
1448
|
-
* }`,
|
|
1894
|
+
* projection: myProjection,
|
|
1449
1895
|
* })
|
|
1450
1896
|
*
|
|
1897
|
+
* // Suspense handles initial load, check for data existence after
|
|
1451
1898
|
* return (
|
|
1452
|
-
* <article ref={ref}
|
|
1453
|
-
* <h2>{title}</h2>
|
|
1454
|
-
* <img src={coverImage} alt={title} />
|
|
1455
|
-
* <p>{authors}</p>
|
|
1899
|
+
* <article ref={ref}>
|
|
1900
|
+
* <h2>{data.title ?? 'Untitled'}</h2>
|
|
1901
|
+
* {data.coverImage && <img src={data.coverImage} alt={data.title} />}
|
|
1902
|
+
* <p>{data.authors ?? 'Unknown authors'}</p>
|
|
1456
1903
|
* </article>
|
|
1457
1904
|
* )
|
|
1458
1905
|
* }
|
|
1459
|
-
* ```
|
|
1460
1906
|
*
|
|
1461
|
-
*
|
|
1907
|
+
* // Usage:
|
|
1908
|
+
* // import {createDocumentHandle} from '@sanity/sdk-react'
|
|
1909
|
+
* // const myDocHandle = createDocumentHandle({ documentId: 'book123', documentType: 'book' })
|
|
1910
|
+
* // <Suspense fallback='Loading preview...'>
|
|
1911
|
+
* // <ProjectionComponent doc={myDocHandle} />
|
|
1912
|
+
* // </Suspense>
|
|
1462
1913
|
* ```
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
*
|
|
1475
|
-
*
|
|
1476
|
-
*
|
|
1477
|
-
*
|
|
1478
|
-
*
|
|
1479
|
-
*
|
|
1480
|
-
*
|
|
1914
|
+
*/
|
|
1915
|
+
export declare function useProjection<
|
|
1916
|
+
TProjection extends ValidProjection = ValidProjection,
|
|
1917
|
+
TDocumentType extends string = string,
|
|
1918
|
+
TDataset extends string = string,
|
|
1919
|
+
TProjectId extends string = string,
|
|
1920
|
+
>(
|
|
1921
|
+
options: UseProjectionOptions<TProjection, TDocumentType, TDataset, TProjectId>,
|
|
1922
|
+
): UseProjectionResults<SanityProjectionResult<TProjection, TDocumentType, TDataset, TProjectId>>
|
|
1923
|
+
|
|
1924
|
+
/**
|
|
1925
|
+
* @beta
|
|
1926
|
+
* Fetch a projection with an explicitly defined return type `TData`.
|
|
1927
|
+
*
|
|
1928
|
+
* @param options - Options including the document handle properties (`documentId`, etc.) and the `projection`.
|
|
1929
|
+
* @returns The projected data, cast to the explicit type `TData`.
|
|
1930
|
+
*
|
|
1931
|
+
* @example Explicitly typing the projection result
|
|
1932
|
+
* ```tsx
|
|
1933
|
+
* import {useProjection, type DocumentHandle} from '@sanity/sdk-react'
|
|
1934
|
+
* import {useRef} from 'react'
|
|
1935
|
+
*
|
|
1936
|
+
* interface SimpleBookPreview {
|
|
1937
|
+
* title?: string;
|
|
1938
|
+
* authorName?: string;
|
|
1939
|
+
* }
|
|
1940
|
+
*
|
|
1941
|
+
* type BookPreviewProps = {
|
|
1942
|
+
* doc: DocumentHandle
|
|
1943
|
+
* }
|
|
1944
|
+
*
|
|
1945
|
+
* function BookPreview({ doc }: BookPreviewProps) {
|
|
1946
|
+
* const ref = useRef(null)
|
|
1947
|
+
* const { data } = useProjection<SimpleBookPreview>({
|
|
1948
|
+
* ...doc,
|
|
1949
|
+
* ref,
|
|
1950
|
+
* projection: `{ title, 'authorName': author->name }`
|
|
1951
|
+
* })
|
|
1952
|
+
*
|
|
1953
|
+
* return (
|
|
1954
|
+
* <div ref={ref}>
|
|
1955
|
+
* <h3>{data.title ?? 'No Title'}</h3>
|
|
1956
|
+
* <p>By: {data.authorName ?? 'Unknown'}</p>
|
|
1957
|
+
* </div>
|
|
1958
|
+
* )
|
|
1959
|
+
* }
|
|
1960
|
+
*
|
|
1961
|
+
* // Usage:
|
|
1962
|
+
* // import {createDocumentHandle} from '@sanity/sdk-react'
|
|
1963
|
+
* // const doc = createDocumentHandle({ documentId: 'abc', documentType: 'book' })
|
|
1964
|
+
* // <Suspense fallback='Loading...'>
|
|
1965
|
+
* // <BookPreview doc={doc} />
|
|
1966
|
+
* // </Suspense>
|
|
1481
1967
|
* ```
|
|
1482
1968
|
*/
|
|
1483
|
-
export declare function useProjection<TData extends object>(
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
...docHandle
|
|
1487
|
-
}: UseProjectionOptions): UseProjectionResults<TData>
|
|
1969
|
+
export declare function useProjection<TData extends object>(
|
|
1970
|
+
options: UseProjectionOptions,
|
|
1971
|
+
): UseProjectionResults<TData>
|
|
1488
1972
|
|
|
1489
1973
|
/**
|
|
1490
1974
|
* @public
|
|
1491
1975
|
* @category Types
|
|
1492
1976
|
*/
|
|
1493
|
-
export declare interface UseProjectionOptions
|
|
1977
|
+
export declare interface UseProjectionOptions<
|
|
1978
|
+
TProjection extends ValidProjection = ValidProjection,
|
|
1979
|
+
TDocumentType extends string = string,
|
|
1980
|
+
TDataset extends string = string,
|
|
1981
|
+
TProjectId extends string = string,
|
|
1982
|
+
> extends DocumentHandle<TDocumentType, TDataset, TProjectId> {
|
|
1983
|
+
/** The GROQ projection string */
|
|
1984
|
+
projection: TProjection
|
|
1985
|
+
/** Optional parameters for the projection query */
|
|
1986
|
+
params?: Record<string, unknown>
|
|
1987
|
+
/** Optional ref to track viewport intersection for lazy loading */
|
|
1494
1988
|
ref?: React.RefObject<unknown>
|
|
1495
|
-
projection: ValidProjection
|
|
1496
1989
|
}
|
|
1497
1990
|
|
|
1498
1991
|
/**
|
|
1499
1992
|
* @public
|
|
1500
1993
|
* @category Types
|
|
1501
1994
|
*/
|
|
1502
|
-
export declare interface UseProjectionResults<TData
|
|
1995
|
+
export declare interface UseProjectionResults<TData> {
|
|
1996
|
+
/** The projected data */
|
|
1503
1997
|
data: TData
|
|
1998
|
+
/** True if the projection is currently being resolved */
|
|
1504
1999
|
isPending: boolean
|
|
1505
2000
|
}
|
|
1506
2001
|
|
|
@@ -1534,63 +2029,105 @@ declare type UseProjects = {
|
|
|
1534
2029
|
export declare const useProjects: UseProjects
|
|
1535
2030
|
|
|
1536
2031
|
/**
|
|
1537
|
-
*
|
|
2032
|
+
* @beta
|
|
2033
|
+
* Executes a GROQ query, inferring the result type from the query string and options.
|
|
2034
|
+
* Leverages Sanity Typegen if configured for enhanced type safety.
|
|
1538
2035
|
*
|
|
1539
|
-
*
|
|
1540
|
-
*
|
|
1541
|
-
* automatic updates.
|
|
2036
|
+
* @param options - Configuration for the query, including `query`, optional `params`, `projectId`, `dataset`, etc.
|
|
2037
|
+
* @returns An object containing `data` (typed based on the query) and `isPending` (for transitions).
|
|
1542
2038
|
*
|
|
1543
|
-
* @
|
|
1544
|
-
*
|
|
1545
|
-
*
|
|
2039
|
+
* @example Basic usage (Inferred Type)
|
|
2040
|
+
* ```tsx
|
|
2041
|
+
* import {useQuery} from '@sanity/sdk-react'
|
|
2042
|
+
* import {defineQuery} from 'groq'
|
|
1546
2043
|
*
|
|
1547
|
-
*
|
|
1548
|
-
* @category GROQ
|
|
1549
|
-
* @param query - GROQ query string to execute
|
|
1550
|
-
* @param options - Optional configuration for the query, including projectId and dataset
|
|
1551
|
-
* @returns Object containing the query result and a pending state flag
|
|
2044
|
+
* const myQuery = defineQuery(`*[_type == "movie"]{_id, title}`)
|
|
1552
2045
|
*
|
|
1553
|
-
*
|
|
1554
|
-
*
|
|
1555
|
-
*
|
|
1556
|
-
* ```
|
|
2046
|
+
* function MovieList() {
|
|
2047
|
+
* // Typegen infers the return type for data
|
|
2048
|
+
* const {data} = useQuery({ query: myQuery })
|
|
1557
2049
|
*
|
|
1558
|
-
*
|
|
1559
|
-
*
|
|
1560
|
-
*
|
|
1561
|
-
*
|
|
1562
|
-
*
|
|
1563
|
-
*
|
|
2050
|
+
* return (
|
|
2051
|
+
* <div>
|
|
2052
|
+
* <h2>Movies</h2>
|
|
2053
|
+
* <ul>
|
|
2054
|
+
* {data.map(movie => <li key={movie._id}>{movie.title}</li>)}
|
|
2055
|
+
* </ul>
|
|
2056
|
+
* </div>
|
|
2057
|
+
* )
|
|
2058
|
+
* }
|
|
2059
|
+
* // Suspense boundary should wrap <MovieList /> for initial load
|
|
1564
2060
|
* ```
|
|
1565
2061
|
*
|
|
1566
|
-
* @example
|
|
2062
|
+
* @example Using parameters (Inferred Type)
|
|
1567
2063
|
* ```tsx
|
|
1568
|
-
*
|
|
1569
|
-
*
|
|
1570
|
-
*
|
|
1571
|
-
*
|
|
1572
|
-
*
|
|
2064
|
+
* import {useQuery} from '@sanity/sdk-react'
|
|
2065
|
+
* import {defineQuery} from 'groq'
|
|
2066
|
+
*
|
|
2067
|
+
* const myQuery = defineQuery(`*[_type == "movie" && _id == $id][0]`)
|
|
2068
|
+
*
|
|
2069
|
+
* function MovieDetails({movieId}: {movieId: string}) {
|
|
2070
|
+
* // Typegen infers the return type based on query and params
|
|
2071
|
+
* const {data, isPending} = useQuery({
|
|
2072
|
+
* query: myQuery,
|
|
2073
|
+
* params: { id: movieId }
|
|
2074
|
+
* })
|
|
2075
|
+
*
|
|
2076
|
+
* return (
|
|
2077
|
+
* // utilize `isPending` to signal to users that new data is coming in
|
|
2078
|
+
* // (e.g. the `movieId` changed and we're loading in the new one)
|
|
2079
|
+
* <div style={{ opacity: isPending ? 0.5 : 1 }}>
|
|
2080
|
+
* {data ? <h1>{data.title}</h1> : <p>Movie not found</p>}
|
|
2081
|
+
* </div>
|
|
2082
|
+
* )
|
|
2083
|
+
* }
|
|
1573
2084
|
* ```
|
|
2085
|
+
*/
|
|
2086
|
+
export declare function useQuery<
|
|
2087
|
+
TQuery extends string = string,
|
|
2088
|
+
TDataset extends string = string,
|
|
2089
|
+
TProjectId extends string = string,
|
|
2090
|
+
>(
|
|
2091
|
+
options: QueryOptions<TQuery, TDataset, TProjectId>,
|
|
2092
|
+
): {
|
|
2093
|
+
/** The query result, typed based on the GROQ query string */
|
|
2094
|
+
data: SanityQueryResult<TQuery, TDataset, TProjectId>
|
|
2095
|
+
/** True if a query transition is in progress */
|
|
2096
|
+
isPending: boolean
|
|
2097
|
+
}
|
|
2098
|
+
|
|
2099
|
+
/**
|
|
2100
|
+
* @beta
|
|
2101
|
+
* Executes a GROQ query with an explicitly provided result type `TData`.
|
|
1574
2102
|
*
|
|
1575
|
-
* @
|
|
2103
|
+
* @param options - Configuration for the query, including `query`, optional `params`, `projectId`, `dataset`, etc.
|
|
2104
|
+
* @returns An object containing `data` (cast to `TData`) and `isPending` (indicates whether a query resolution is pending; note that Suspense handles initial loading states). *
|
|
2105
|
+
* @example Manually typed query result
|
|
1576
2106
|
* ```tsx
|
|
1577
|
-
*
|
|
1578
|
-
*
|
|
1579
|
-
*
|
|
1580
|
-
*
|
|
1581
|
-
*
|
|
1582
|
-
*
|
|
1583
|
-
*
|
|
1584
|
-
*
|
|
1585
|
-
*
|
|
1586
|
-
*
|
|
2107
|
+
* import {useQuery} from '@sanity/sdk-react'
|
|
2108
|
+
*
|
|
2109
|
+
* interface CustomMovieTitle {
|
|
2110
|
+
* movieTitle?: string
|
|
2111
|
+
* }
|
|
2112
|
+
*
|
|
2113
|
+
* function FirstMovieTitle() {
|
|
2114
|
+
* // Provide the explicit type TData
|
|
2115
|
+
* const {data, isPending} = useQuery<CustomMovieTitle>({
|
|
2116
|
+
* query: '*[_type == "movie"][0]{ "movieTitle": title }'
|
|
2117
|
+
* })
|
|
1587
2118
|
*
|
|
2119
|
+
* return (
|
|
2120
|
+
* <h1 style={{ opacity: isPending ? 0.5 : 1 }}>
|
|
2121
|
+
* {data?.movieTitle ?? 'No title found'}
|
|
2122
|
+
* </h1>
|
|
2123
|
+
* )
|
|
2124
|
+
* }
|
|
2125
|
+
* ```
|
|
1588
2126
|
*/
|
|
1589
|
-
export declare function useQuery<
|
|
1590
|
-
query
|
|
1591
|
-
|
|
1592
|
-
)
|
|
1593
|
-
data: T
|
|
2127
|
+
export declare function useQuery<TData>(options: QueryOptions): {
|
|
2128
|
+
/** The query result, cast to the provided type TData */
|
|
2129
|
+
data: TData
|
|
2130
|
+
/** True if another query is resolving in the background (suspense handles the initial loading state) */
|
|
1594
2131
|
isPending: boolean
|
|
1595
2132
|
}
|
|
1596
2133
|
|
|
@@ -1765,6 +2302,31 @@ export declare function useStudioWorkspacesByProjectIdDataset(): StudioWorkspace
|
|
|
1765
2302
|
*/
|
|
1766
2303
|
export declare function useUsers(options?: GetUsersOptions): UsersResult
|
|
1767
2304
|
|
|
2305
|
+
/**
|
|
2306
|
+
* Hook that verifies the current projects belongs to the organization ID specified in the dashboard context.
|
|
2307
|
+
*
|
|
2308
|
+
* @public
|
|
2309
|
+
* @param disabled - When true, disables verification and skips project verification API calls
|
|
2310
|
+
* @returns Error message if the project doesn't match the organization ID, or null if all match or verification isn't needed
|
|
2311
|
+
* @category Projects
|
|
2312
|
+
* @example
|
|
2313
|
+
* ```tsx
|
|
2314
|
+
* function OrgVerifier() {
|
|
2315
|
+
* const error = useVerifyOrgProjects()
|
|
2316
|
+
*
|
|
2317
|
+
* if (error) {
|
|
2318
|
+
* return <div className="error">{error}</div>
|
|
2319
|
+
* }
|
|
2320
|
+
*
|
|
2321
|
+
* return <div>Organization projects verified!</div>
|
|
2322
|
+
* }
|
|
2323
|
+
* ```
|
|
2324
|
+
*/
|
|
2325
|
+
export declare function useVerifyOrgProjects(
|
|
2326
|
+
disabled?: boolean,
|
|
2327
|
+
projectIds?: string[],
|
|
2328
|
+
): string | null
|
|
2329
|
+
|
|
1768
2330
|
/**
|
|
1769
2331
|
* @internal
|
|
1770
2332
|
* Hook to wrap a Comlink node in a React hook.
|