@sanity/sdk-react 2.5.0 → 2.6.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 CHANGED
@@ -322,6 +322,29 @@ The SDK handles updating the document state automatically:
322
322
  - `publishDocument()` copies draft → published, deletes draft
323
323
  - `discardDraft()` deletes draft, reverts to published
324
324
 
325
+ #### LiveEdit Documents
326
+
327
+ For documents that don't need the draft/published workflow (such as settings, configuration, or real-time collaborative documents), you can use **liveEdit mode** by setting `liveEdit: true` in the document handle:
328
+
329
+ ```tsx
330
+ const settingsHandle: DocumentHandle = {
331
+ documentId: 'site-settings',
332
+ documentType: 'settings',
333
+ liveEdit: true, // Edits apply directly without creating a draft
334
+ }
335
+
336
+ // Edits are applied immediately to the published document
337
+ const editSettings = useEditDocument(settingsHandle)
338
+ ```
339
+
340
+ **When using liveEdit documents:**
341
+
342
+ - Drafts will not be created when the document is edited
343
+ - Edits will be applied directly to the published document
344
+ - `publishDocument()`, `unpublishDocument()`, and `discardDraft()` actions cannot be used (since liveEdit documents are always published and do not have drafts)
345
+
346
+ For more details, see the [Sanity documentation on liveEdit documents](https://www.sanity.io/docs/content-lake/drafts).
347
+
325
348
  ---
326
349
 
327
350
  ### Real-Time Behavior
@@ -340,43 +363,97 @@ Any mutation to a subscribed document (even fields you don't display) will trigg
340
363
 
341
364
  ### Multi-Project Access
342
365
 
343
- #### Specify Source in Handle
366
+ The SDK supports accessing documents from multiple projects and datasets simultaneously. There are two main approaches:
367
+
368
+ #### Approach 1: Specify Project/Dataset Directly in the Handle
369
+
370
+ Pass `projectId` and `dataset` directly in document handles to fetch data from specific projects (note that any `projectId` and `dataset` pair you pass must be defined in your application’s array of [SanityConfig objects](https://www.sanity.io/docs/app-sdk/sdk-configuration#d95b8773097c)):
344
371
 
345
372
  ```tsx
346
- const handle: DocumentHandle = {
347
- documentId: 'xyz',
348
- documentType: 'product',
349
- projectId: 'project-a',
350
- dataset: 'production',
373
+ import {useDocument} from '@sanity/sdk-react'
374
+
375
+ function MultiProjectComponent() {
376
+ // Fetch from Project A
377
+ const {data: productA} = useDocument({
378
+ documentId: 'product-123',
379
+ documentType: 'product',
380
+ projectId: 'project-a',
381
+ dataset: 'production',
382
+ })
383
+
384
+ // Fetch from Project B
385
+ const {data: productB} = useDocument({
386
+ documentId: 'product-456',
387
+ documentType: 'product',
388
+ projectId: 'project-b',
389
+ dataset: 'staging',
390
+ })
391
+
392
+ return (
393
+ <div>
394
+ <h2>{productA?.title} (Project A)</h2>
395
+ <h2>{productB?.title} (Project B)</h2>
396
+ </div>
397
+ )
351
398
  }
352
399
  ```
353
400
 
354
- #### Use Resource Provider Context
401
+ #### Approach 2: Use ResourceProvider to Set Context
402
+
403
+ Wrap components in `ResourceProvider` to set default project/dataset values for all child components:
355
404
 
356
405
  ```tsx
357
406
  // App.tsx
358
- import {ResourceProvider} from '@sanity/sdk-react'
407
+ import {ResourceProvider, useDocument, useSanityInstance} from '@sanity/sdk-react'
408
+
409
+ function ProductCard({productId}: {productId: string}) {
410
+ // Get the current project/dataset from context
411
+ const {config} = useSanityInstance()
359
412
 
360
- import {ProductCard} from './ProductCard'
413
+ // No need to specify projectId/dataset - inherited from ResourceProvider
414
+ const {data: product} = useDocument({
415
+ documentId: productId,
416
+ documentType: 'product',
417
+ })
361
418
 
362
- export function WrappedProductCard() {
363
419
  return (
364
- <ResourceProvider projectId="project-a" dataset="production">
365
- <ProductCard productId="xyz" />
366
- </ResourceProvider>
420
+ <div>
421
+ <h3>{product?.title}</h3>
422
+ <p>
423
+ From: {config.projectId}.{config.dataset}
424
+ </p>
425
+ </div>
367
426
  )
368
427
  }
369
428
 
370
- // ProductCard.tsx
371
- import {useProjectId, useDataset} from '@sanity/sdk-react'
372
-
373
- function ProductCard({productId}: {productId: string}) {
374
- const projectId = useProjectId() // "project-a" from nearest configured ResourceProvider
375
- const dataset = useDataset() // "production" from nearest configured ResourceProvider
376
- // ...
429
+ export function MultiProjectApp() {
430
+ return (
431
+ <div>
432
+ {/* Products from Project A */}
433
+ <ResourceProvider projectId="project-a" dataset="production" fallback={<div>Loading...</div>}>
434
+ <h2>Project A Products</h2>
435
+ <ProductCard productId="product-123" />
436
+ <ProductCard productId="product-456" />
437
+ </ResourceProvider>
438
+
439
+ {/* Products from Project B */}
440
+ <ResourceProvider projectId="project-b" dataset="staging" fallback={<div>Loading...</div>}>
441
+ <h2>Project B Products</h2>
442
+ <ProductCard productId="product-789" />
443
+ </ResourceProvider>
444
+ </div>
445
+ )
377
446
  }
378
447
  ```
379
448
 
449
+ **Key Points:**
450
+
451
+ - When using hooks that take document handles as arguments (such useDocument, useEditDocument, useQuery, etc.), the document handles’ `projectId` and `dataset` values can be explicitly set to fetch documents from arbitrary projects and datasets
452
+ - The ResourceProvider component is used to create a project ID and dataset context that child components will inherit from; this can negate the need to specify the project ID and dataset values for document handles in hooks called by child components
453
+ - Use `useSanityInstance()` to access the context configuration for the current component: `const {config} = useSanityInstance()`
454
+ - You can nest ResourceProvider components to create component trees with different project/dataset configurations — but be aware that, when the project ID and dataset values for document handles are _not_ specified, the project ID and dataset from the closest ResourceProvider context will be used
455
+ - Regardless of the approach you use, the project IDs and dataset names you reference (whether in document handles or ResourceProviders) must be enumerated in your application’s [SanityConfig objects](https://www.sanity.io/docs/app-sdk/sdk-configuration#d95b8773097c)
456
+
380
457
  ---
381
458
 
382
459
  ### TypeScript & TypeGen
package/dist/index.d.ts CHANGED
@@ -176,18 +176,6 @@ declare interface DispatchIntent {
176
176
  dispatchIntent: () => void
177
177
  }
178
178
 
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
179
  declare interface DocumentInteractionHistory {
192
180
  recordEvent: (eventType: 'viewed' | 'edited' | 'created' | 'deleted') => void
193
181
  }
@@ -218,6 +206,7 @@ export declare interface DocumentsOptions<
218
206
  batchSize?: number
219
207
  /**
220
208
  * Sorting configuration for the results
209
+ * @beta
221
210
  */
222
211
  orderings?: SortOrderingItem[]
223
212
  /**
@@ -307,6 +296,13 @@ export declare type MessageHandler<TWindowMessage extends WindowMessage> = (
307
296
  event: TWindowMessage['data'],
308
297
  ) => TWindowMessage['response'] | Promise<TWindowMessage['response']>
309
298
 
299
+ /** In-flight CLI PR is using named sources since it's aspirational.
300
+ * We can transform the shape in this function until it's finalized.
301
+ */
302
+ declare interface NamedSources {
303
+ [key: string]: SanityConfig
304
+ }
305
+
310
306
  /**
311
307
  * @public
312
308
  * @category Types
@@ -343,6 +339,7 @@ export declare interface PaginatedDocumentsOptions<
343
339
  pageSize?: number
344
340
  /**
345
341
  * Sorting configuration for the results
342
+ * @beta
346
343
  */
347
344
  orderings?: SortOrderingItem[]
348
345
  /**
@@ -446,6 +443,18 @@ export declare type ProjectWithoutMembers = Omit<SanityProject_2, 'members'>
446
443
  */
447
444
  export declare const REACT_SDK_VERSION: {}
448
445
 
446
+ /** @internal */
447
+ export declare function renderSanityApp(
448
+ rootElement: HTMLElement | null,
449
+ namedSources: NamedSources,
450
+ options: RenderSanitySDKAppOptions,
451
+ children: React.ReactNode,
452
+ ): () => void
453
+
454
+ declare interface RenderSanitySDKAppOptions {
455
+ reactStrictMode?: boolean
456
+ }
457
+
449
458
  /**
450
459
  * Provides a Sanity instance to child components through React Context
451
460
  *
@@ -583,6 +592,7 @@ export declare interface SanityAppProps {
583
592
  config: SanityConfig | SanityConfig[]
584
593
  /** @deprecated use the `config` prop instead. */
585
594
  sanityConfigs?: SanityConfig[]
595
+ sources?: Record<string, DocumentSource>
586
596
  children: React.ReactNode
587
597
  fallback: React.ReactNode
588
598
  }
@@ -612,6 +622,7 @@ export declare interface SDKProviderProps extends AuthBoundaryProps {
612
622
  children: ReactNode
613
623
  config: SanityConfig | SanityConfig[]
614
624
  fallback: ReactNode
625
+ sources?: Record<string, DocumentSource>
615
626
  }
616
627
 
617
628
  export {SortOrderingItem}
@@ -1146,7 +1157,7 @@ export declare function useDispatchIntent(params: UseDispatchIntentParams): Disp
1146
1157
  declare interface UseDispatchIntentParams {
1147
1158
  action?: 'edit'
1148
1159
  intentId?: string
1149
- documentHandle: DocumentHandleWithSource
1160
+ documentHandle: DocumentHandle
1150
1161
  parameters?: Record<string, unknown>
1151
1162
  }
1152
1163
 
@@ -2458,8 +2469,9 @@ export declare function useQuery<
2458
2469
  TQuery extends string = string,
2459
2470
  TDataset extends string = string,
2460
2471
  TProjectId extends string = string,
2472
+ TSourceName extends string = string,
2461
2473
  >(
2462
- options: QueryOptions<TQuery, TDataset, TProjectId>,
2474
+ options: UseQueryOptions<TQuery, TDataset, TProjectId, TSourceName>,
2463
2475
  ): {
2464
2476
  /** The query result, typed based on the GROQ query string */
2465
2477
  data: SanityQueryResult<TQuery, `${TProjectId}.${TDataset}`>
@@ -2502,6 +2514,15 @@ export declare function useQuery<TData>(options: QueryOptions): {
2502
2514
  isPending: boolean
2503
2515
  }
2504
2516
 
2517
+ declare interface UseQueryOptions<
2518
+ TQuery extends string = string,
2519
+ TDataset extends string = string,
2520
+ TProjectId extends string = string,
2521
+ TSourceName extends string = string,
2522
+ > extends QueryOptions<TQuery, TDataset, TProjectId> {
2523
+ sourceName?: TSourceName
2524
+ }
2525
+
2505
2526
  /**
2506
2527
  * @internal
2507
2528
  * Hook for managing document interaction history in Sanity Studio.
package/dist/index.js CHANGED
@@ -1,12 +1,13 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
2
  import { c } from "react-compiler-runtime";
3
3
  import { ClientError, CorsOriginError } from "@sanity/client";
4
- import { getAuthState, getNodeState, getIsInDashboardState, setAuthToken, AuthStateType, getLoginUrlState, observeOrganizationVerificationState, handleAuthCallback, logout, isProjectUserNotFoundClientError, getClientErrorApiDescription, getClientErrorApiBody, getCorsErrorProjectId, createSanityInstance, agentGenerate, agentTransform, agentTranslate, agentPrompt, agentPatch, getTokenState, getCurrentUserState, getDashboardOrganizationId, getClientState, getOrCreateController, getOrCreateChannel, releaseChannel, getFavoritesState, resolveFavoritesState, resolveDatasets, getDatasetsState, applyDocumentActions, resolveDocument, getDocumentState, subscribeDocumentEvents, getPermissionsState, getDocumentSyncStatus, editDocument, getQueryKey, parseQueryKey, getQueryState, resolveQuery, createGroqSearchFilter, getPresence, getPreviewState, resolvePreview, getProjectionState, resolveProjection, resolveProject, getProjectState, resolveProjects, getProjectsState, getActiveReleasesState, getPerspectiveState, getUsersKey, parseUsersKey, getUsersState, resolveUsers, loadMoreUsers } from "@sanity/sdk";
4
+ import { getAuthState, getNodeState, getIsInDashboardState, setAuthToken, AuthStateType, getLoginUrlState, observeOrganizationVerificationState, handleAuthCallback, logout, isProjectUserNotFoundClientError, getClientErrorApiDescription, getClientErrorApiBody, getCorsErrorProjectId, createSanityInstance, agentGenerate, agentTransform, agentTranslate, agentPrompt, agentPatch, getTokenState, getCurrentUserState, getDashboardOrganizationId, getClientState, getOrCreateController, getOrCreateChannel, releaseChannel, isDatasetSource, isMediaLibrarySource, isCanvasSource, getFavoritesState, resolveFavoritesState, resolveDatasets, getDatasetsState, applyDocumentActions, resolveDocument, getDocumentState, subscribeDocumentEvents, getPermissionsState, getDocumentSyncStatus, editDocument, getQueryKey, parseQueryKey, getQueryState, resolveQuery, createGroqSearchFilter, getPresence, getPreviewState, resolvePreview, getProjectionState, resolveProjection, resolveProject, getProjectState, resolveProjects, getProjectsState, getActiveReleasesState, getPerspectiveState, getUsersKey, parseUsersKey, getUsersState, resolveUsers, loadMoreUsers } from "@sanity/sdk";
5
5
  export * from "@sanity/sdk";
6
- import { createContext, useContext, useSyncExternalStore, useRef, useEffect, useState, Suspense, useCallback, useMemo, useInsertionEffect, useTransition } from "react";
6
+ import { createContext, useContext, useSyncExternalStore, useRef, useEffect, useState, Suspense, StrictMode, useCallback, useMemo, useInsertionEffect, useTransition } from "react";
7
7
  import { ErrorBoundary } from "react-error-boundary";
8
8
  import { SDK_CHANNEL_NAME, SDK_NODE_NAME } from "@sanity/message-protocol";
9
9
  import { firstValueFrom, filter, identity, Observable, startWith, distinctUntilChanged, switchMap, EMPTY } from "rxjs";
10
+ import { createRoot } from "react-dom/client";
10
11
  import { pick } from "lodash-es";
11
12
  const SanityInstanceContext = createContext(null), useSanityInstance = (config) => {
12
13
  const $ = c(3), instance = useContext(SanityInstanceContext);
@@ -65,7 +66,7 @@ function useWindowConnection(t0) {
65
66
  const [type, handler] = t42, messageUnsubscribe = node.on(type, handler);
66
67
  messageUnsubscribe && messageUnsubscribers.current.push(messageUnsubscribe);
67
68
  }), () => {
68
- messageUnsubscribers.current.forEach(_temp$7), messageUnsubscribers.current = [];
69
+ messageUnsubscribers.current.forEach(_temp$8), messageUnsubscribers.current = [];
69
70
  }), $[4] = node, $[5] = onMessage, $[6] = t3) : t3 = $[6];
70
71
  let t4;
71
72
  $[7] !== instance || $[8] !== name || $[9] !== node || $[10] !== onMessage ? (t4 = [instance, name, onMessage, node], $[7] = instance, $[8] = name, $[9] = node, $[10] = onMessage, $[11] = t4) : t4 = $[11], useEffect(t3, t4);
@@ -83,7 +84,7 @@ function useWindowConnection(t0) {
83
84
  fetch
84
85
  }, $[16] = fetch, $[17] = sendMessage, $[18] = t7) : t7 = $[18], t7;
85
86
  }
86
- function _temp$7(unsubscribe) {
87
+ function _temp$8(unsubscribe) {
87
88
  return unsubscribe();
88
89
  }
89
90
  const DEFAULT_RESPONSE_TIMEOUT = 1e4;
@@ -113,7 +114,7 @@ function DashboardTokenRefresh(t0) {
113
114
  if (clearRefreshTimeout(), res.token) {
114
115
  setAuthToken(instance, res.token);
115
116
  const errorContainer = document.getElementById("__sanityError");
116
- errorContainer && Array.from(errorContainer.getElementsByTagName("div")).some(_temp$6) && errorContainer.remove();
117
+ errorContainer && Array.from(errorContainer.getElementsByTagName("div")).some(_temp$7) && errorContainer.remove();
117
118
  }
118
119
  isTokenRefreshInProgress.current = !1;
119
120
  } catch {
@@ -134,7 +135,7 @@ function DashboardTokenRefresh(t0) {
134
135
  let t7;
135
136
  return $[11] !== authState || $[12] !== requestNewToken ? (t7 = [authState, requestNewToken], $[11] = authState, $[12] = requestNewToken, $[13] = t7) : t7 = $[13], useEffect(t6, t7), children;
136
137
  }
137
- function _temp$6(div) {
138
+ function _temp$7(div) {
138
139
  return div.textContent?.includes("Uncaught error: Unauthorized - A valid session is required for this endpoint");
139
140
  }
140
141
  const ComlinkTokenRefreshProvider = (t0) => {
@@ -289,10 +290,10 @@ function LoginCallback() {
289
290
  let t0, t1;
290
291
  return $[0] !== handleAuthCallback2 ? (t0 = () => {
291
292
  const url = new URL(location.href);
292
- handleAuthCallback2(url.toString()).then(_temp$5);
293
+ handleAuthCallback2(url.toString()).then(_temp$6);
293
294
  }, t1 = [handleAuthCallback2], $[0] = handleAuthCallback2, $[1] = t0, $[2] = t1) : (t0 = $[1], t1 = $[2]), useEffect(t0, t1), null;
294
295
  }
295
- function _temp$5(replacementLocation) {
296
+ function _temp$6(replacementLocation) {
296
297
  replacementLocation && history.replaceState(null, "", replacementLocation);
297
298
  }
298
299
  const useLogOut = createCallbackHook(logout);
@@ -419,14 +420,37 @@ function ResourceProvider(t0) {
419
420
  let t7;
420
421
  return $[13] !== instance || $[14] !== t6 ? (t7 = /* @__PURE__ */ jsx(SanityInstanceContext.Provider, { value: instance, children: t6 }), $[13] = instance, $[14] = t6, $[15] = t7) : t7 = $[15], t7;
421
422
  }
422
- function SDKProvider({
423
- children,
424
- config,
425
- fallback,
426
- ...props
427
- }) {
428
- const configs = (Array.isArray(config) ? config : [config]).slice().reverse(), projectIds = configs.map((c2) => c2.projectId).filter((id) => !!id), createNestedProviders = (index) => index >= configs.length ? /* @__PURE__ */ jsx(AuthBoundary, { ...props, projectIds, children }) : /* @__PURE__ */ jsx(ResourceProvider, { ...configs[index], fallback, children: createNestedProviders(index + 1) });
429
- return createNestedProviders(0);
423
+ const SourcesContext = createContext({});
424
+ function SDKProvider(t0) {
425
+ const $ = c(19);
426
+ let children, config, fallback, props;
427
+ $[0] !== t0 ? ({
428
+ children,
429
+ config,
430
+ fallback,
431
+ ...props
432
+ } = t0, $[0] = t0, $[1] = children, $[2] = config, $[3] = fallback, $[4] = props) : (children = $[1], config = $[2], fallback = $[3], props = $[4]);
433
+ let t1;
434
+ $[5] !== config ? (t1 = Array.isArray(config) ? config : [config], $[5] = config, $[6] = t1) : t1 = $[6];
435
+ let configs, t2;
436
+ $[7] !== t1 ? (configs = t1.slice().reverse(), t2 = configs.map(_temp$5).filter(_temp2$1), $[7] = t1, $[8] = configs, $[9] = t2) : (configs = $[8], t2 = $[9]);
437
+ const projectIds = t2;
438
+ let t3, t4;
439
+ $[10] !== props.sources ? (t4 = props.sources ?? {}, $[10] = props.sources, $[11] = t4) : t4 = $[11], t3 = t4;
440
+ const sourcesValue = t3;
441
+ let t5;
442
+ if ($[12] !== children || $[13] !== configs || $[14] !== fallback || $[15] !== projectIds || $[16] !== props || $[17] !== sourcesValue) {
443
+ const createNestedProviders = (index) => index >= configs.length ? /* @__PURE__ */ jsx(AuthBoundary, { ...props, projectIds, children: /* @__PURE__ */ jsx(SourcesContext.Provider, { value: sourcesValue, children }) }) : /* @__PURE__ */ jsx(ResourceProvider, { ...configs[index], fallback, children: createNestedProviders(index + 1) });
444
+ t5 = createNestedProviders(0), $[12] = children, $[13] = configs, $[14] = fallback, $[15] = projectIds, $[16] = props, $[17] = sourcesValue, $[18] = t5;
445
+ } else
446
+ t5 = $[18];
447
+ return t5;
448
+ }
449
+ function _temp2$1(id) {
450
+ return !!id;
451
+ }
452
+ function _temp$5(c2) {
453
+ return c2.projectId;
430
454
  }
431
455
  const REDIRECT_URL = "https://sanity.io/welcome";
432
456
  function SanityApp(t0) {
@@ -453,6 +477,14 @@ function SanityApp(t0) {
453
477
  function _temp$4() {
454
478
  console.warn("Redirecting to core", REDIRECT_URL), window.location.replace(REDIRECT_URL);
455
479
  }
480
+ function renderSanityApp(rootElement, namedSources, options, children) {
481
+ if (!rootElement)
482
+ throw new Error("Missing root element to mount application into");
483
+ const {
484
+ reactStrictMode = !1
485
+ } = options, root = createRoot(rootElement), config = Object.values(namedSources);
486
+ return root.render(reactStrictMode ? /* @__PURE__ */ jsx(StrictMode, { children: /* @__PURE__ */ jsx(SanityApp, { config, fallback: /* @__PURE__ */ jsx("div", { children: "Loading..." }), children }) }) : /* @__PURE__ */ jsx(SanityApp, { config, fallback: /* @__PURE__ */ jsx("div", { children: "Loading..." }), children })), () => root.unmount();
487
+ }
456
488
  const useAgentGenerate = createCallbackHook(agentGenerate), useAgentTransform = createCallbackHook(agentTransform), useAgentTranslate = createCallbackHook(agentTranslate);
457
489
  function promptAdapter(instance, options) {
458
490
  return firstValueFrom(agentPrompt(instance, options));
@@ -588,28 +620,28 @@ function useDashboardNavigate(navigateFn) {
588
620
  }
589
621
  }, $[0] = navigateFn, $[1] = t0) : t0 = $[1], useWindowConnection(t0);
590
622
  }
591
- const SOURCE_ID = "__sanity_internal_sourceId", isDocumentHandleWithSource = (documentHandle) => "source" in documentHandle;
592
- function getResourceIdFromDocumentHandle(documentHandle) {
593
- let source;
594
- const {
623
+ function useSource(options) {
624
+ const sources = useContext(SourcesContext);
625
+ if (!(!options.sourceName && !options.source)) {
626
+ if (options.source)
627
+ return options.source;
628
+ if (options.sourceName && !Object.hasOwn(sources, options.sourceName))
629
+ throw new Error(`There's no source named ${JSON.stringify(options.sourceName)} in context. Please use <SourceProvider>.`);
630
+ return options.sourceName ? sources[options.sourceName] : void 0;
631
+ }
632
+ }
633
+ function useResourceIdFromDocumentHandle(documentHandle) {
634
+ const $ = c(3), source = useSource(documentHandle), {
595
635
  projectId,
596
636
  dataset
597
637
  } = documentHandle;
598
- isDocumentHandleWithSource(documentHandle) && (source = documentHandle.source);
599
- let resourceId = projectId + "." + dataset, resourceType;
600
- if (source) {
601
- const sourceId = source[SOURCE_ID];
602
- if (Array.isArray(sourceId))
603
- (sourceId[0] === "media-library" || sourceId[0] === "canvas") && (resourceType = sourceId[0], resourceId = sourceId[1]);
604
- else if (sourceId && typeof sourceId == "object" && "projectId" in sourceId) {
605
- const datasetSource = sourceId;
606
- resourceId = `${datasetSource.projectId}.${datasetSource.dataset}`;
607
- }
608
- }
609
- return {
638
+ let resourceId = "", resourceType;
639
+ projectId && dataset && (resourceId = `${projectId}.${dataset}`), source && (isDatasetSource(source) ? (resourceId = `${source.projectId}.${source.dataset}`, resourceType = void 0) : isMediaLibrarySource(source) ? (resourceId = source.mediaLibraryId, resourceType = "media-library") : isCanvasSource(source) && (resourceId = source.canvasId, resourceType = "canvas"));
640
+ let t0;
641
+ return $[0] !== resourceId || $[1] !== resourceType ? (t0 = {
610
642
  id: resourceId,
611
643
  type: resourceType
612
- };
644
+ }, $[0] = resourceId, $[1] = resourceType, $[2] = t0) : t0 = $[2], t0;
613
645
  }
614
646
  function useDispatchIntent(params) {
615
647
  const {
@@ -622,7 +654,7 @@ function useDispatchIntent(params) {
622
654
  } = useWindowConnection({
623
655
  name: SDK_NODE_NAME,
624
656
  connectTo: SDK_CHANNEL_NAME
625
- });
657
+ }), resource = useResourceIdFromDocumentHandle(documentHandle);
626
658
  return {
627
659
  dispatchIntent: useCallback(() => {
628
660
  try {
@@ -631,11 +663,11 @@ function useDispatchIntent(params) {
631
663
  const {
632
664
  projectId,
633
665
  dataset,
634
- source
666
+ sourceName
635
667
  } = documentHandle;
636
- if (action && intentId && console.warn("useDispatchIntent: Both `action` and `intentId` were provided. Using `intentId` and ignoring `action`."), !source && (!projectId || !dataset))
637
- throw new Error("useDispatchIntent: Either `source` or both `projectId` and `dataset` must be provided in documentHandle.");
638
- const resource = getResourceIdFromDocumentHandle(documentHandle), message = {
668
+ if (action && intentId && console.warn("useDispatchIntent: Both `action` and `intentId` were provided. Using `intentId` and ignoring `action`."), !sourceName && (!projectId || !dataset))
669
+ throw new Error("useDispatchIntent: Either `sourceName` or both `projectId` and `dataset` must be provided in documentHandle.");
670
+ const message = {
639
671
  type: "dashboard/v1/events/intents/dispatch-intent",
640
672
  data: {
641
673
  ...action && !intentId ? {
@@ -663,7 +695,7 @@ function useDispatchIntent(params) {
663
695
  } catch (error) {
664
696
  throw console.error("Failed to dispatch intent:", error), error;
665
697
  }
666
- }, [action, intentId, documentHandle, parameters, sendMessage])
698
+ }, [action, intentId, documentHandle, parameters, sendMessage, resource.id, resource.type])
667
699
  };
668
700
  }
669
701
  function useManageFavorite({
@@ -1044,7 +1076,7 @@ function _temp$1(key) {
1044
1076
  return !ignoredKeys.includes(key);
1045
1077
  }
1046
1078
  function useQuery(options) {
1047
- const instance = useSanityInstance(options), [isPending, startTransition] = useTransition(), queryKey = getQueryKey(options), [deferredQueryKey, setDeferredQueryKey] = useState(queryKey), deferred = useMemo(() => parseQueryKey(deferredQueryKey), [deferredQueryKey]), ref = useRef(new AbortController());
1079
+ const instance = useSanityInstance(options), source = useSource(options), [isPending, startTransition] = useTransition(), queryKey = getQueryKey(options), [deferredQueryKey, setDeferredQueryKey] = useState(queryKey), ref = useRef(new AbortController());
1048
1080
  useEffect(() => {
1049
1081
  queryKey !== deferredQueryKey && startTransition(() => {
1050
1082
  ref && !ref.current.signal.aborted && (ref.current.abort(), ref.current = new AbortController()), setDeferredQueryKey(queryKey);
@@ -1053,11 +1085,18 @@ function useQuery(options) {
1053
1085
  const {
1054
1086
  getCurrent,
1055
1087
  subscribe
1056
- } = useMemo(() => getQueryState(instance, deferred), [instance, deferred]);
1088
+ } = useMemo(() => {
1089
+ const deferred = parseQueryKey(deferredQueryKey);
1090
+ return getQueryState(instance, {
1091
+ ...deferred,
1092
+ source
1093
+ });
1094
+ }, [instance, deferredQueryKey, source]);
1057
1095
  if (getCurrent() === void 0) {
1058
- const currentSignal = ref.current.signal;
1096
+ const currentSignal = ref.current.signal, deferred_0 = parseQueryKey(deferredQueryKey);
1059
1097
  throw resolveQuery(instance, {
1060
- ...deferred,
1098
+ ...deferred_0,
1099
+ source,
1061
1100
  signal: currentSignal
1062
1101
  });
1063
1102
  }
@@ -1406,7 +1445,7 @@ function useUsers(options) {
1406
1445
  loadMore
1407
1446
  };
1408
1447
  }
1409
- var version = "2.5.0";
1448
+ var version = "2.6.0";
1410
1449
  function getEnv(key) {
1411
1450
  if (typeof import.meta < "u" && import.meta.env)
1412
1451
  return import.meta.env[key];
@@ -1423,6 +1462,7 @@ export {
1423
1462
  ResourceProvider,
1424
1463
  SDKProvider,
1425
1464
  SanityApp,
1465
+ renderSanityApp,
1426
1466
  useActiveReleases,
1427
1467
  useAgentGenerate,
1428
1468
  useAgentPatch,