diff --git a/.gitignore b/.gitignore index 6bc6e4b82..ca4026021 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ + +.DS_Store + # Logs logs *.log @@ -7,6 +10,8 @@ yarn-error.log* lerna-debug.log* .pnpm-debug.log* + + # Diagnostic reports (https://nodejs.org/api/report.html) report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json diff --git a/apps/common/src/queries.ts b/apps/common/src/queries.ts index acac1322e..49a20993c 100644 --- a/apps/common/src/queries.ts +++ b/apps/common/src/queries.ts @@ -2,6 +2,7 @@ import type {ImageAsset, ImageCrop, ImageHotspot, PortableTextTextBlock} from 's export const shoesList = /* groq */ `*[_type == "shoe" && defined(slug.current)]{ title, + subtitle, slug, "price": string(price), "media": media[0]{ alt, asset, crop, hotspot }, @@ -9,6 +10,7 @@ export const shoesList = /* groq */ `*[_type == "shoe" && defined(slug.current)] } | order(_updatedAt desc) ` export type ShoesListResult = { title?: string | null + subtitle?: string | null slug: {current: string} price?: string | null media?: { @@ -32,6 +34,7 @@ export type ShoesListResult = { export const shoe = /* groq */ `*[_type == "shoe" && slug.current == $slug]{ title, + subtitle, slug, "price": string(price), "media": media[]{ alt, asset, crop, hotspot }, diff --git a/apps/common/src/schema/shoe/shoe.ts b/apps/common/src/schema/shoe/shoe.ts index 641df4dde..7ffba365b 100644 --- a/apps/common/src/schema/shoe/shoe.ts +++ b/apps/common/src/schema/shoe/shoe.ts @@ -3,6 +3,13 @@ import {defineArrayMember, defineField, defineType} from 'sanity' export const shoeType = defineType({ type: 'document', name: 'shoe', + groups: [ + { + default: true, + name: 'details', + title: 'Details', + }, + ], fields: [ defineField({ type: 'string', @@ -11,6 +18,13 @@ export const shoeType = defineType({ validation: (rule) => rule.required(), }), defineField({ + group: 'details', + type: 'string', + name: 'subtitle', + title: 'Subtitle', + }), + defineField({ + group: 'details', type: 'slug', name: 'slug', title: 'Slug', diff --git a/packages/presentation/src/plugin.tsx b/packages/presentation/src/plugin.tsx index 91a8f5430..829f02990 100644 --- a/packages/presentation/src/plugin.tsx +++ b/packages/presentation/src/plugin.tsx @@ -1,6 +1,14 @@ import type {SanityDocument} from '@sanity/client' -import {lazy, Suspense} from 'react' -import {definePlugin, type InputProps, isDocumentSchemaType} from 'sanity' +import {lazy, Suspense, useEffect, useMemo} from 'react' +import { + definePlugin, + type InputProps, + isDocumentSchemaType, + type BaseFormNode, + type ObjectSchemaType, + type ObjectInputProps, + pathToString, +} from 'sanity' import {DEFAULT_TOOL_ICON, DEFAULT_TOOL_NAME, EDIT_INTENT_MODE} from './constants' import {PresentationDocumentHeader} from './document/PresentationDocumentHeader' @@ -8,7 +16,7 @@ import {PresentationDocumentProvider} from './document/PresentationDocumentProvi import {openInStructure} from './fieldActions/openInStructure' import {getIntentState} from './getIntentState' import {presentationUsEnglishLocaleBundle} from './i18n' -import {getPublishedId} from './internals' +import {getPublishedId, useDocumentPane} from './internals' import {router} from './router' import type { DocumentLocationResolverObject, @@ -52,21 +60,43 @@ export const presentationTool = definePlugin((options const hasLocationsResolver = !!(options.resolve?.locations || options.locate) - function PresentationDocumentInput(props: InputProps) { - const value = props.value as SanityDocument + function PresentationDocumentInput(input: InputProps) { + const value = input.value as SanityDocument const documentId = value?._id ? getPublishedId(value?._id) : undefined + const {focusPath} = useDocumentPane() + + if (isDocumentSchemaType(input.schemaType)) { + const props = input as ObjectInputProps + + // Create a fast index of the groups for all fields in the schema + const fieldGroupIndex = useMemo(() => { + const index = new Map() + props.schemaType.fields.forEach((field) => { + index.set(field.name, field?.group?.[0] ?? 'all-fields') + }) + return index + }, [props.schemaType.fields]) + + // Watch value of props.focusPath + useEffect(() => { + if (!focusPath || focusPath.length === 0) return + const focusFieldPath = focusPath[0] + const group = fieldGroupIndex.get(focusFieldPath?.toString()) ?? 'all-fields' + if (group) { + props.onFieldGroupSelect(group) + } + }, [focusPath]) - if (isDocumentSchemaType(props.schemaType)) { return ( {hasLocationsResolver && documentId && ( )} - {props.renderDefault(props)} + {input.renderDefault(props)} @@ -74,7 +104,7 @@ export const presentationTool = definePlugin((options ) } - return props.renderDefault(props) + return input.renderDefault(input) } function canHandleCreateIntent(params: Record) {