@sanity/sdk-react 2.5.0 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/README.md +164 -19
  2. package/dist/index.d.ts +571 -26
  3. package/dist/index.js +149 -78
  4. package/dist/index.js.map +1 -1
  5. package/package.json +7 -7
  6. package/src/_exports/sdk-react.ts +2 -0
  7. package/src/components/SDKProvider.tsx +8 -3
  8. package/src/components/SanityApp.test.tsx +72 -2
  9. package/src/components/SanityApp.tsx +53 -10
  10. package/src/components/auth/AuthBoundary.tsx +5 -5
  11. package/src/context/ComlinkTokenRefresh.test.tsx +2 -2
  12. package/src/context/ComlinkTokenRefresh.tsx +3 -2
  13. package/src/context/SDKStudioContext.test.tsx +126 -0
  14. package/src/context/SDKStudioContext.ts +65 -0
  15. package/src/context/SourcesContext.tsx +7 -0
  16. package/src/context/renderSanityApp.test.tsx +355 -0
  17. package/src/context/renderSanityApp.tsx +48 -0
  18. package/src/hooks/agent/agentActions.ts +436 -21
  19. package/src/hooks/dashboard/useDispatchIntent.test.ts +26 -20
  20. package/src/hooks/dashboard/useDispatchIntent.ts +10 -11
  21. package/src/hooks/dashboard/utils/{getResourceIdFromDocumentHandle.test.ts → useResourceIdFromDocumentHandle.test.ts} +33 -60
  22. package/src/hooks/dashboard/utils/useResourceIdFromDocumentHandle.ts +46 -0
  23. package/src/hooks/document/useEditDocument.ts +3 -0
  24. package/src/hooks/documents/useDocuments.ts +3 -2
  25. package/src/hooks/helpers/useNormalizedSourceOptions.ts +85 -0
  26. package/src/hooks/paginatedDocuments/usePaginatedDocuments.ts +1 -0
  27. package/src/hooks/projection/useDocumentProjection.ts +15 -4
  28. package/src/hooks/query/useQuery.ts +30 -11
  29. package/src/hooks/dashboard/types.ts +0 -12
  30. package/src/hooks/dashboard/utils/getResourceIdFromDocumentHandle.ts +0 -53
package/dist/index.d.ts CHANGED
@@ -10,6 +10,7 @@ import {ApplyDocumentActionsOptions} from '@sanity/sdk'
10
10
  import {AuthState} from '@sanity/sdk'
11
11
  import {CanvasResource} from '@sanity/message-protocol'
12
12
  import {ClientOptions} from '@sanity/sdk'
13
+ import {Context} from 'react'
13
14
  import {CurrentUser} from '@sanity/sdk'
14
15
  import {DatasetHandle} from '@sanity/sdk'
15
16
  import {DatasetsResponse} from '@sanity/client'
@@ -49,6 +50,7 @@ import {SanityQueryResult} from 'groq'
49
50
  import {SanityUser} from '@sanity/sdk'
50
51
  import {SortOrderingItem} from '@sanity/types'
51
52
  import {StudioResource} from '@sanity/message-protocol'
53
+ import {TokenSource} from '@sanity/sdk'
52
54
  import {UserPresence} from '@sanity/sdk'
53
55
  import {WindowMessage} from '@sanity/sdk'
54
56
 
@@ -176,18 +178,6 @@ declare interface DispatchIntent {
176
178
  dispatchIntent: () => void
177
179
  }
178
180
 
179
- /**
180
- * Document handle that optionally includes a source (e.g., media library source)
181
- * or projectId and dataset for traditional dataset sources
182
- * (but now marked optional since it's valid to just use a source)
183
- * @beta
184
- */
185
- declare interface DocumentHandleWithSource extends Omit<DocumentHandle, 'projectId' | 'dataset'> {
186
- source?: DocumentSource
187
- projectId?: string
188
- dataset?: string
189
- }
190
-
191
181
  declare interface DocumentInteractionHistory {
192
182
  recordEvent: (eventType: 'viewed' | 'edited' | 'created' | 'deleted') => void
193
183
  }
@@ -218,6 +208,7 @@ export declare interface DocumentsOptions<
218
208
  batchSize?: number
219
209
  /**
220
210
  * Sorting configuration for the results
211
+ * @beta
221
212
  */
222
213
  orderings?: SortOrderingItem[]
223
214
  /**
@@ -307,6 +298,13 @@ export declare type MessageHandler<TWindowMessage extends WindowMessage> = (
307
298
  event: TWindowMessage['data'],
308
299
  ) => TWindowMessage['response'] | Promise<TWindowMessage['response']>
309
300
 
301
+ /** In-flight CLI PR is using named sources since it's aspirational.
302
+ * We can transform the shape in this function until it's finalized.
303
+ */
304
+ declare interface NamedSources {
305
+ [key: string]: SanityConfig
306
+ }
307
+
310
308
  /**
311
309
  * @public
312
310
  * @category Types
@@ -343,6 +341,7 @@ export declare interface PaginatedDocumentsOptions<
343
341
  pageSize?: number
344
342
  /**
345
343
  * Sorting configuration for the results
344
+ * @beta
346
345
  */
347
346
  orderings?: SortOrderingItem[]
348
347
  /**
@@ -446,6 +445,18 @@ export declare type ProjectWithoutMembers = Omit<SanityProject_2, 'members'>
446
445
  */
447
446
  export declare const REACT_SDK_VERSION: {}
448
447
 
448
+ /** @internal */
449
+ export declare function renderSanityApp(
450
+ rootElement: HTMLElement | null,
451
+ namedSources: NamedSources,
452
+ options: RenderSanitySDKAppOptions,
453
+ children: React.ReactNode,
454
+ ): () => void
455
+
456
+ declare interface RenderSanitySDKAppOptions {
457
+ reactStrictMode?: boolean
458
+ }
459
+
449
460
  /**
450
461
  * Provides a Sanity instance to child components through React Context
451
462
  *
@@ -518,12 +529,18 @@ export declare interface ResourceProviderProps extends SanityConfig {
518
529
  * must be wrapped with the SanityApp component to function properly.
519
530
  *
520
531
  * The `config` prop on the SanityApp component accepts either a single {@link SanityConfig} object, or an array of them.
521
- * This allows your app to work with one or more of your organizations datasets.
532
+ * This allows your app to work with one or more of your organization's datasets.
533
+ *
534
+ * When rendered inside a Sanity Studio that provides `SDKStudioContext`, the `config` prop is
535
+ * optional — `SanityApp` will automatically derive `projectId`, `dataset`, and auth from the
536
+ * Studio workspace.
522
537
  *
523
538
  * @remarks
524
539
  * When passing multiple SanityConfig objects to the `config` prop, the first configuration in the array becomes the default
525
540
  * configuration used by the App SDK Hooks.
526
541
  *
542
+ * When both `config` and `SDKStudioContext` are available, the explicit `config` takes precedence.
543
+ *
527
544
  * @category Components
528
545
  * @param props - Your Sanity configuration and the React children to render
529
546
  * @returns Your Sanity application, integrated with your Sanity configuration and application context
@@ -571,7 +588,7 @@ export declare interface ResourceProviderProps extends SanityConfig {
571
588
  export declare function SanityApp({
572
589
  children,
573
590
  fallback,
574
- config,
591
+ config: configProp,
575
592
  ...props
576
593
  }: SanityAppProps): ReactElement
577
594
 
@@ -580,9 +597,16 @@ export declare function SanityApp({
580
597
  * @category Types
581
598
  */
582
599
  export declare interface SanityAppProps {
583
- config: SanityConfig | SanityConfig[]
600
+ /**
601
+ * One or more SanityConfig objects providing a project ID and dataset name.
602
+ * Optional when `SanityApp` is rendered inside an `SDKStudioContext` provider
603
+ * (e.g. inside Sanity Studio) — the config is derived from the workspace
604
+ * automatically.
605
+ */
606
+ config?: SanityConfig | SanityConfig[]
584
607
  /** @deprecated use the `config` prop instead. */
585
608
  sanityConfigs?: SanityConfig[]
609
+ sources?: Record<string, DocumentSource>
586
610
  children: React.ReactNode
587
611
  fallback: React.ReactNode
588
612
  }
@@ -612,10 +636,73 @@ export declare interface SDKProviderProps extends AuthBoundaryProps {
612
636
  children: ReactNode
613
637
  config: SanityConfig | SanityConfig[]
614
638
  fallback: ReactNode
639
+ sources?: Record<string, DocumentSource>
615
640
  }
616
641
 
642
+ /**
643
+ * React context that allows the SDK to auto-detect when it is running
644
+ * inside a Sanity Studio. The Studio provides a workspace handle via this
645
+ * context, and `SanityApp` reads it to derive `projectId`, `dataset`, and
646
+ * a reactive auth token — eliminating the need for manual configuration.
647
+ *
648
+ * @remarks
649
+ * This context is defined in `@sanity/sdk-react` and provided by the Studio.
650
+ * The Studio imports it from this package and wraps its component tree:
651
+ *
652
+ * ```tsx
653
+ * import {SDKStudioContext} from '@sanity/sdk-react'
654
+ *
655
+ * function StudioRoot({children}) {
656
+ * const workspace = useWorkspace()
657
+ * return (
658
+ * <SDKStudioContext.Provider value={workspace}>
659
+ * {children}
660
+ * </SDKStudioContext.Provider>
661
+ * )
662
+ * }
663
+ * ```
664
+ *
665
+ * When `SanityApp` is rendered inside this provider, it auto-configures
666
+ * without any `config` prop:
667
+ *
668
+ * ```tsx
669
+ * <SanityApp fallback={<Loading />}>
670
+ * <MyComponent />
671
+ * </SanityApp>
672
+ * ```
673
+ *
674
+ * @public
675
+ */
676
+ export declare const SDKStudioContext: Context<StudioWorkspaceHandle | null>
677
+
617
678
  export {SortOrderingItem}
618
679
 
680
+ /**
681
+ * Minimal duck-typed interface representing a Sanity Studio workspace.
682
+ * The Studio's `Workspace` type satisfies this naturally — no import
683
+ * dependency on the `sanity` package is required.
684
+ *
685
+ * @public
686
+ */
687
+ export declare interface StudioWorkspaceHandle {
688
+ /** The Sanity project ID for this workspace. */
689
+ projectId: string
690
+ /** The dataset name for this workspace. */
691
+ dataset: string
692
+ /** Authentication state for this workspace. */
693
+ auth: {
694
+ /**
695
+ * Reactive token source from the Studio's auth store.
696
+ * When present, the SDK subscribes for ongoing token sync — the Studio
697
+ * is the single authority for auth and handles token refresh.
698
+ *
699
+ * Optional because Studios before Aug 2022 may not expose it. When
700
+ * absent, the SDK falls back to localStorage/cookie discovery.
701
+ */
702
+ token?: TokenSource
703
+ }
704
+ }
705
+
619
706
  declare interface StudioWorkspacesResult {
620
707
  workspacesByProjectIdAndDataset: WorkspacesByProjectIdDataset
621
708
  error: string | null
@@ -663,11 +750,69 @@ export declare const useActiveReleases: UseActiveReleases
663
750
  /**
664
751
  * @alpha
665
752
  * Generates content for a document (or specific fields) via Sanity Agent Actions.
753
+ *
754
+ * @remarks
755
+ * This hook provides a stable callback to trigger AI-powered content generation for documents.
756
+ *
757
+ * Features:
666
758
  * - Uses instruction templates with `$variables` and supports `instructionParams` (constants, fields, documents, GROQ queries).
667
759
  * - Can target specific paths/fields; supports image generation when targeting image fields.
668
760
  * - Supports optional `temperature`, `async`, `noWrite`, and `conditionalPaths`.
761
+ * - Returns a Subscribable stream for tracking generation progress.
762
+ *
763
+ * @returns A stable callback that triggers the action and yields a Subscribable stream.
669
764
  *
670
- * Returns a stable callback that triggers the action and yields a Subscribable stream.
765
+ * @example Basic content generation
766
+ * ```tsx
767
+ * import {useAgentGenerate} from '@sanity/sdk-react'
768
+ *
769
+ * function GenerateDescription({documentId}: {documentId: string}) {
770
+ * const generate = useAgentGenerate()
771
+ *
772
+ * const handleGenerate = () => {
773
+ * generate({
774
+ * documentId,
775
+ * instruction: 'Write a compelling product description based on the title: $title',
776
+ * instructionParams: {
777
+ * title: {type: 'field', path: 'title'},
778
+ * },
779
+ * targetPaths: ['description'],
780
+ * }).subscribe({
781
+ * next: (result) => console.log('Generation progress:', result),
782
+ * complete: () => console.log('Generation complete'),
783
+ * error: (err) => console.error('Generation failed:', err),
784
+ * })
785
+ * }
786
+ *
787
+ * return <button onClick={handleGenerate}>Generate Description</button>
788
+ * }
789
+ * ```
790
+ *
791
+ * @example Image generation
792
+ * ```tsx
793
+ * import {useAgentGenerate} from '@sanity/sdk-react'
794
+ *
795
+ * function GenerateProductImage({documentId}: {documentId: string}) {
796
+ * const generate = useAgentGenerate()
797
+ *
798
+ * const handleGenerateImage = () => {
799
+ * generate({
800
+ * documentId,
801
+ * instruction: 'Generate a product photo for: $productName',
802
+ * instructionParams: {
803
+ * productName: {type: 'field', path: 'name'},
804
+ * },
805
+ * targetPaths: ['mainImage'],
806
+ * }).subscribe({
807
+ * complete: () => console.log('Image generated'),
808
+ * })
809
+ * }
810
+ *
811
+ * return <button onClick={handleGenerateImage}>Generate Image</button>
812
+ * }
813
+ * ```
814
+ *
815
+ * @category Agent Actions
671
816
  */
672
817
  export declare const useAgentGenerate: () => (
673
818
  options: AgentGenerateOptions,
@@ -676,22 +821,247 @@ export declare const useAgentGenerate: () => (
676
821
  /**
677
822
  * @alpha
678
823
  * Schema-aware patching with Sanity Agent Actions.
824
+ *
825
+ * @remarks
826
+ * This hook provides a stable callback to apply schema-validated patches to documents.
827
+ * Unlike {@link useEditDocument}, this uses the Agent Actions API which provides
828
+ * additional schema validation and safe merging capabilities.
829
+ *
830
+ * Features:
679
831
  * - Validates provided paths/values against the document schema and merges object values safely.
680
832
  * - Prevents duplicate keys and supports array appends (including after a specific keyed item).
681
833
  * - Accepts `documentId` or `targetDocument` (mutually exclusive).
834
+ * - Requires `schemaId` (e.g., `'_.schemas.default'`) and `target` to specify patch operations.
682
835
  * - Optional `async`, `noWrite`, `conditionalPaths`.
683
836
  *
684
- * Returns a stable callback that triggers the action and resolves a Promise with the patch result.
837
+ * Each entry in `target` specifies a `path`, an `operation` (`'set'`, `'append'`, `'mixed'`, or `'unset'`),
838
+ * and a `value` (required for all operations except `'unset'`).
839
+ *
840
+ * @returns A stable callback that triggers the action and resolves a Promise with the patch result.
841
+ *
842
+ * @example Basic field update
843
+ * ```tsx
844
+ * import {useAgentPatch} from '@sanity/sdk-react'
845
+ *
846
+ * function UpdateTitle({documentId}: {documentId: string}) {
847
+ * const patch = useAgentPatch()
848
+ *
849
+ * const handleUpdate = async () => {
850
+ * const result = await patch({
851
+ * documentId,
852
+ * schemaId: '_.schemas.default',
853
+ * target: [
854
+ * {
855
+ * path: 'title',
856
+ * operation: 'set',
857
+ * value: 'Updated Title',
858
+ * },
859
+ * {
860
+ * path: 'lastModified',
861
+ * operation: 'set',
862
+ * value: new Date().toISOString(),
863
+ * },
864
+ * ],
865
+ * })
866
+ * console.log('Patch result:', result)
867
+ * }
868
+ *
869
+ * return <button onClick={handleUpdate}>Update Title</button>
870
+ * }
871
+ * ```
872
+ *
873
+ * @example Append items to an array
874
+ * ```tsx
875
+ * import {useAgentPatch} from '@sanity/sdk-react'
876
+ *
877
+ * function AddTag({documentId}: {documentId: string}) {
878
+ * const patch = useAgentPatch()
879
+ *
880
+ * const handleAddTag = async (newTag: string) => {
881
+ * await patch({
882
+ * documentId,
883
+ * schemaId: '_.schemas.default',
884
+ * target: {
885
+ * path: 'tags',
886
+ * operation: 'append',
887
+ * value: [newTag],
888
+ * },
889
+ * })
890
+ * }
891
+ *
892
+ * return (
893
+ * <button onClick={() => handleAddTag('featured')}>
894
+ * Add Featured Tag
895
+ * </button>
896
+ * )
897
+ * }
898
+ * ```
899
+ *
900
+ * @example Insert array item after a specific key
901
+ * ```tsx
902
+ * import {useAgentPatch} from '@sanity/sdk-react'
903
+ *
904
+ * function InsertContentBlock({
905
+ * documentId,
906
+ * afterKey,
907
+ * }: {
908
+ * documentId: string
909
+ * afterKey: string
910
+ * }) {
911
+ * const patch = useAgentPatch()
912
+ *
913
+ * const handleInsert = async () => {
914
+ * await patch({
915
+ * documentId,
916
+ * schemaId: '_.schemas.default',
917
+ * target: {
918
+ * path: ['content', {_key: afterKey}],
919
+ * operation: 'append',
920
+ * value: [{_type: 'block', text: 'New paragraph inserted here.'}],
921
+ * },
922
+ * })
923
+ * }
924
+ *
925
+ * return <button onClick={handleInsert}>Insert Block</button>
926
+ * }
927
+ * ```
928
+ *
929
+ * @example Create a new document with targetDocument
930
+ * ```tsx
931
+ * import {useAgentPatch} from '@sanity/sdk-react'
932
+ *
933
+ * function CreateProduct() {
934
+ * const patch = useAgentPatch()
935
+ *
936
+ * const handleCreate = async () => {
937
+ * const result = await patch({
938
+ * targetDocument: {
939
+ * operation: 'create',
940
+ * _type: 'product',
941
+ * },
942
+ * schemaId: '_.schemas.default',
943
+ * target: [
944
+ * {
945
+ * path: 'title',
946
+ * operation: 'set',
947
+ * value: 'New Product',
948
+ * },
949
+ * {
950
+ * path: 'price',
951
+ * operation: 'set',
952
+ * value: 29.99,
953
+ * },
954
+ * {
955
+ * path: 'inStock',
956
+ * operation: 'set',
957
+ * value: true,
958
+ * },
959
+ * ],
960
+ * })
961
+ * console.log('Created document:', result.documentId)
962
+ * }
963
+ *
964
+ * return <button onClick={handleCreate}>Create Product</button>
965
+ * }
966
+ * ```
967
+ *
968
+ * @category Agent Actions
685
969
  */
686
970
  export declare const useAgentPatch: () => (options: AgentPatchOptions) => Promise<AgentPatchResult>
687
971
 
688
972
  /**
689
973
  * @alpha
690
- * Prompts the LLM using the same instruction template format as other actions.
974
+ * Prompts the Content Agent using the same instruction template format as other agent actions.
975
+ *
976
+ * @remarks
977
+ * This hook provides a stable callback to send prompts to the Content Agent and receive responses.
978
+ * Unlike the other agent action hooks, this one does not modify documents—it simply
979
+ * returns the AI's response.
980
+ *
981
+ * Features:
982
+ * - Uses the same instruction template format with `$variables` as other actions.
691
983
  * - `format`: 'string' or 'json' (instruction must contain the word "json" for JSON responses).
692
- * - Optional `temperature`.
984
+ * - Supports `instructionParams` for dynamic content (constants, fields, documents, GROQ queries).
985
+ * - Optional `temperature` for controlling response creativity.
986
+ *
987
+ * @returns A stable callback that triggers the action and resolves a Promise with the prompt result.
693
988
  *
694
- * Returns a stable callback that triggers the action and resolves a Promise with the prompt result.
989
+ * @example Basic string prompt
990
+ * ```tsx
991
+ * import {useState} from 'react'
992
+ * import {useAgentPrompt} from '@sanity/sdk-react'
993
+ *
994
+ * function AskQuestion() {
995
+ * const prompt = useAgentPrompt()
996
+ * const [answer, setAnswer] = useState<string>('')
997
+ *
998
+ * const handleAsk = async () => {
999
+ * const result = await prompt({
1000
+ * instruction: 'What are the top 3 benefits of content modeling?',
1001
+ * format: 'string',
1002
+ * })
1003
+ * setAnswer(result.output)
1004
+ * }
1005
+ *
1006
+ * return (
1007
+ * <div>
1008
+ * <button onClick={handleAsk}>Ask AI</button>
1009
+ * {answer && <p>{answer}</p>}
1010
+ * </div>
1011
+ * )
1012
+ * }
1013
+ * ```
1014
+ *
1015
+ * @example JSON response with instruction params
1016
+ * ```tsx
1017
+ * import {useState} from 'react'
1018
+ * import {useAgentPrompt} from '@sanity/sdk-react'
1019
+ *
1020
+ * interface TagSuggestions {
1021
+ * tags: string[]
1022
+ * reasoning: string
1023
+ * }
1024
+ *
1025
+ * function SuggestTags({documentId}: {documentId: string}) {
1026
+ * const prompt = useAgentPrompt()
1027
+ * const [suggestions, setSuggestions] = useState<TagSuggestions | null>(null)
1028
+ *
1029
+ * const handleSuggest = async () => {
1030
+ * const result = await prompt({
1031
+ * instruction: `
1032
+ * Based on the following article title and content, suggest relevant tags.
1033
+ * Return as json with "tags" (array of strings) and "reasoning" (string).
1034
+ * Title: $title
1035
+ * Content: $body
1036
+ * `,
1037
+ * instructionParams: {
1038
+ * title: {type: 'field', path: 'title', documentId},
1039
+ * body: {type: 'field', path: 'body', documentId},
1040
+ * },
1041
+ * format: 'json',
1042
+ * })
1043
+ * setSuggestions(result.output as TagSuggestions)
1044
+ * }
1045
+ *
1046
+ * return (
1047
+ * <div>
1048
+ * <button onClick={handleSuggest}>Suggest Tags</button>
1049
+ * {suggestions && (
1050
+ * <div>
1051
+ * <p>Reasoning: {suggestions.reasoning}</p>
1052
+ * <ul>
1053
+ * {suggestions.tags.map((tag) => (
1054
+ * <li key={tag}>{tag}</li>
1055
+ * ))}
1056
+ * </ul>
1057
+ * </div>
1058
+ * )}
1059
+ * </div>
1060
+ * )
1061
+ * }
1062
+ * ```
1063
+ *
1064
+ * @category Agent Actions
695
1065
  */
696
1066
  export declare const useAgentPrompt: () => (
697
1067
  options: AgentPromptOptions,
@@ -732,12 +1102,73 @@ export declare function useAgentResourceContext(options: AgentResourceContextOpt
732
1102
  /**
733
1103
  * @alpha
734
1104
  * Transforms an existing document or selected fields using Sanity Agent Actions.
1105
+ *
1106
+ * @remarks
1107
+ * This hook provides a stable callback to apply AI-powered transformations to document content.
1108
+ *
1109
+ * Features:
735
1110
  * - Accepts `instruction` and `instructionParams` (constants, fields, documents, GROQ queries).
736
1111
  * - Can write to the same or a different `targetDocument` (create/edit), and target specific paths.
737
1112
  * - Supports per-path image transform instructions and image description operations.
738
1113
  * - Optional `temperature`, `async`, `noWrite`, `conditionalPaths`.
739
1114
  *
740
- * Returns a stable callback that triggers the action and yields a Subscribable stream.
1115
+ * @returns A stable callback that triggers the action and yields a Subscribable stream.
1116
+ *
1117
+ * @example Transform text content
1118
+ * ```tsx
1119
+ * import {useAgentTransform} from '@sanity/sdk-react'
1120
+ *
1121
+ * function SummarizeArticle({documentId}: {documentId: string}) {
1122
+ * const transform = useAgentTransform()
1123
+ *
1124
+ * const handleSummarize = () => {
1125
+ * transform({
1126
+ * documentId,
1127
+ * instruction: 'Summarize the following content into 2-3 sentences: $body',
1128
+ * instructionParams: {
1129
+ * body: {type: 'field', path: 'body'},
1130
+ * },
1131
+ * targetPaths: ['summary'],
1132
+ * }).subscribe({
1133
+ * complete: () => console.log('Summary generated'),
1134
+ * error: (err) => console.error('Transform failed:', err),
1135
+ * })
1136
+ * }
1137
+ *
1138
+ * return <button onClick={handleSummarize}>Generate Summary</button>
1139
+ * }
1140
+ * ```
1141
+ *
1142
+ * @example Transform and write to a different document
1143
+ * ```tsx
1144
+ * import {useAgentTransform} from '@sanity/sdk-react'
1145
+ *
1146
+ * function CreateVariant({sourceDocumentId}: {sourceDocumentId: string}) {
1147
+ * const transform = useAgentTransform()
1148
+ *
1149
+ * const handleCreateVariant = () => {
1150
+ * transform({
1151
+ * documentId: sourceDocumentId,
1152
+ * instruction: 'Rewrite this product description for a younger audience: $description',
1153
+ * instructionParams: {
1154
+ * description: {type: 'field', path: 'description'},
1155
+ * },
1156
+ * targetDocument: {
1157
+ * operation: 'create',
1158
+ * _type: 'product',
1159
+ * },
1160
+ * targetPaths: ['description'],
1161
+ * }).subscribe({
1162
+ * next: (result) => console.log('New document:', result),
1163
+ * complete: () => console.log('Variant created'),
1164
+ * })
1165
+ * }
1166
+ *
1167
+ * return <button onClick={handleCreateVariant}>Create Youth Variant</button>
1168
+ * }
1169
+ * ```
1170
+ *
1171
+ * @category Agent Actions
741
1172
  */
742
1173
  export declare const useAgentTransform: () => (
743
1174
  options: AgentTransformOptions,
@@ -746,11 +1177,92 @@ export declare const useAgentTransform: () => (
746
1177
  /**
747
1178
  * @alpha
748
1179
  * Translates documents or fields using Sanity Agent Actions.
1180
+ *
1181
+ * @remarks
1182
+ * This hook provides a stable callback to translate document content between languages using AI.
1183
+ *
1184
+ * Features:
749
1185
  * - Configure `fromLanguage`/`toLanguage`, optional `styleGuide`, and `protectedPhrases`.
750
1186
  * - Can write into a different `targetDocument`, and/or store language in a field.
751
1187
  * - Optional `temperature`, `async`, `noWrite`, `conditionalPaths`.
752
1188
  *
753
- * Returns a stable callback that triggers the action and yields a Subscribable stream.
1189
+ * @returns A stable callback that triggers the action and yields a Subscribable stream.
1190
+ *
1191
+ * @example Basic translation
1192
+ * ```tsx
1193
+ * import {useAgentTranslate} from '@sanity/sdk-react'
1194
+ *
1195
+ * function TranslateArticle({documentId}: {documentId: string}) {
1196
+ * const translate = useAgentTranslate()
1197
+ *
1198
+ * const handleTranslate = () => {
1199
+ * translate({
1200
+ * documentId,
1201
+ * fromLanguage: 'en',
1202
+ * toLanguage: 'es',
1203
+ * targetPaths: ['title', 'body'],
1204
+ * }).subscribe({
1205
+ * complete: () => console.log('Translation complete'),
1206
+ * error: (err) => console.error('Translation failed:', err),
1207
+ * })
1208
+ * }
1209
+ *
1210
+ * return <button onClick={handleTranslate}>Translate to Spanish</button>
1211
+ * }
1212
+ * ```
1213
+ *
1214
+ * @example Translation with style guide and protected phrases
1215
+ * ```tsx
1216
+ * import {useAgentTranslate} from '@sanity/sdk-react'
1217
+ *
1218
+ * function TranslateWithBrandTerms({documentId}: {documentId: string}) {
1219
+ * const translate = useAgentTranslate()
1220
+ *
1221
+ * const handleTranslate = () => {
1222
+ * translate({
1223
+ * documentId,
1224
+ * fromLanguage: 'en',
1225
+ * toLanguage: 'fr',
1226
+ * styleGuide: 'Use formal French appropriate for business communication.',
1227
+ * protectedPhrases: ['Acme Corp', 'PowerWidget Pro'],
1228
+ * targetPaths: ['title', 'description'],
1229
+ * }).subscribe({
1230
+ * complete: () => console.log('Translation complete'),
1231
+ * })
1232
+ * }
1233
+ *
1234
+ * return <button onClick={handleTranslate}>Translate to French</button>
1235
+ * }
1236
+ * ```
1237
+ *
1238
+ * @example Translate to a new document
1239
+ * ```tsx
1240
+ * import {useAgentTranslate} from '@sanity/sdk-react'
1241
+ *
1242
+ * function CreateTranslatedCopy({documentId}: {documentId: string}) {
1243
+ * const translate = useAgentTranslate()
1244
+ *
1245
+ * const handleCreateTranslation = () => {
1246
+ * translate({
1247
+ * documentId,
1248
+ * fromLanguage: 'en',
1249
+ * toLanguage: 'de',
1250
+ * targetDocument: {
1251
+ * operation: 'create',
1252
+ * _type: 'article',
1253
+ * },
1254
+ * languageFieldPath: 'language',
1255
+ * }).subscribe({
1256
+ * next: (result) => console.log('New translated document:', result),
1257
+ * complete: () => console.log('Translated copy created'),
1258
+ * })
1259
+ * }
1260
+ *
1261
+ * return <button onClick={handleCreateTranslation}>Create German Copy</button>
1262
+ * }
1263
+ * ```
1264
+ *
1265
+ * @category Agent Actions
754
1266
  */
755
1267
  export declare const useAgentTranslate: () => (
756
1268
  options: AgentTranslateOptions,
@@ -1146,7 +1658,7 @@ export declare function useDispatchIntent(params: UseDispatchIntentParams): Disp
1146
1658
  declare interface UseDispatchIntentParams {
1147
1659
  action?: 'edit'
1148
1660
  intentId?: string
1149
- documentHandle: DocumentHandleWithSource
1661
+ documentHandle: WithSourceNameSupport<DocumentHandle>
1150
1662
  parameters?: Record<string, unknown>
1151
1663
  }
1152
1664
 
@@ -1729,7 +2241,7 @@ export declare interface useDocumentProjectionOptions<
1729
2241
  TDocumentType extends string = string,
1730
2242
  TDataset extends string = string,
1731
2243
  TProjectId extends string = string,
1732
- > extends DocumentHandle<TDocumentType, TDataset, TProjectId> {
2244
+ > extends WithSourceNameSupport<DocumentHandle<TDocumentType, TDataset, TProjectId>> {
1733
2245
  /** The GROQ projection string */
1734
2246
  projection: TProjection
1735
2247
  /** Optional parameters for the projection query */
@@ -2459,7 +2971,7 @@ export declare function useQuery<
2459
2971
  TDataset extends string = string,
2460
2972
  TProjectId extends string = string,
2461
2973
  >(
2462
- options: QueryOptions<TQuery, TDataset, TProjectId>,
2974
+ options: UseQueryOptions<TQuery, TDataset, TProjectId>,
2463
2975
  ): {
2464
2976
  /** The query result, typed based on the GROQ query string */
2465
2977
  data: SanityQueryResult<TQuery, `${TProjectId}.${TDataset}`>
@@ -2495,13 +3007,23 @@ export declare function useQuery<
2495
3007
  * }
2496
3008
  * ```
2497
3009
  */
2498
- export declare function useQuery<TData>(options: QueryOptions): {
3010
+ export declare function useQuery<TData>(options: WithSourceNameSupport<QueryOptions>): {
2499
3011
  /** The query result, cast to the provided type TData */
2500
3012
  data: TData
2501
3013
  /** True if another query is resolving in the background (suspense handles the initial loading state) */
2502
3014
  isPending: boolean
2503
3015
  }
2504
3016
 
3017
+ /**
3018
+ * Hook options for useQuery, supporting both direct source and sourceName.
3019
+ * @beta
3020
+ */
3021
+ declare type UseQueryOptions<
3022
+ TQuery extends string = string,
3023
+ TDataset extends string = string,
3024
+ TProjectId extends string = string,
3025
+ > = WithSourceNameSupport<QueryOptions<TQuery, TDataset, TProjectId>>
3026
+
2505
3027
  /**
2506
3028
  * @internal
2507
3029
  * Hook for managing document interaction history in Sanity Studio.
@@ -2845,6 +3367,29 @@ export declare type WindowMessageHandler<TFrameMessage extends FrameMessage> = (
2845
3367
  event: TFrameMessage['data'],
2846
3368
  ) => TFrameMessage['response']
2847
3369
 
3370
+ /**
3371
+ * Adds React hook support (sourceName resolution) to core types.
3372
+ * This wrapper allows hooks to accept `sourceName` as a convenience,
3373
+ * which is then resolved to a `DocumentSource` at the React layer.
3374
+ * For now, we are trying to avoid source name resolution in core --
3375
+ * functions having sources explicitly passed will reduce complexity.
3376
+ *
3377
+ * @typeParam T - The core type to extend (must have optional `source` field)
3378
+ * @beta
3379
+ */
3380
+ declare type WithSourceNameSupport<
3381
+ T extends {
3382
+ source?: DocumentSource
3383
+ },
3384
+ > = T & {
3385
+ /**
3386
+ * Optional name of a source to resolve from context.
3387
+ * If provided, will be resolved to a `DocumentSource` via `SourcesContext`.
3388
+ * @beta
3389
+ */
3390
+ sourceName?: string
3391
+ }
3392
+
2848
3393
  declare interface WorkspacesByProjectIdDataset {
2849
3394
  [key: `${string}:${string}`]: DashboardResource[]
2850
3395
  }