@sanity/assist 5.0.4 → 6.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/LICENSE +1 -1
- package/README.md +28 -254
- package/dist/index.d.ts +322 -410
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3181 -2649
- package/dist/index.js.map +1 -1
- package/package.json +38 -78
- package/dist/index.cjs +0 -4239
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -791
- package/sanity.json +0 -8
- package/src/_lib/connector/ConnectFromRegion.tsx +0 -25
- package/src/_lib/connector/ConnectToRegion.tsx +0 -23
- package/src/_lib/connector/ConnectorRegion.tsx +0 -24
- package/src/_lib/connector/ConnectorsProvider.tsx +0 -20
- package/src/_lib/connector/ConnectorsStore.ts +0 -122
- package/src/_lib/connector/ConnectorsStoreContext.ts +0 -5
- package/src/_lib/connector/helpers.ts +0 -5
- package/src/_lib/connector/index.ts +0 -9
- package/src/_lib/connector/mapConnectorToLine.ts +0 -83
- package/src/_lib/connector/types.ts +0 -56
- package/src/_lib/connector/useConnectorsStore.ts +0 -14
- package/src/_lib/connector/useRegionRects.ts +0 -142
- package/src/_lib/fixedListenQuery.ts +0 -101
- package/src/_lib/form/DocumentForm.tsx +0 -201
- package/src/_lib/form/constants.ts +0 -1
- package/src/_lib/form/helpers.ts +0 -32
- package/src/_lib/form/index.ts +0 -1
- package/src/_lib/randomKey.ts +0 -29
- package/src/_lib/useListeningQuery.ts +0 -62
- package/src/_lib/usePrevious.ts +0 -9
- package/src/assistConnectors/AssistConnectorsOverlay.tsx +0 -133
- package/src/assistConnectors/ConnectorPath.tsx +0 -63
- package/src/assistConnectors/draw/arrowPath.ts +0 -9
- package/src/assistConnectors/draw/connectorPath.ts +0 -142
- package/src/assistConnectors/index.ts +0 -1
- package/src/assistDocument/AssistDocumentContext.tsx +0 -51
- package/src/assistDocument/AssistDocumentContextProvider.tsx +0 -17
- package/src/assistDocument/AssistDocumentInput.tsx +0 -61
- package/src/assistDocument/AssistDocumentLayout.tsx +0 -12
- package/src/assistDocument/RequestRunInstructionProvider.tsx +0 -61
- package/src/assistDocument/components/AssistDocumentForm.tsx +0 -287
- package/src/assistDocument/components/AssistTypeContext.tsx +0 -7
- package/src/assistDocument/components/FieldRefPreview.tsx +0 -26
- package/src/assistDocument/components/InstructionsArrayField.tsx +0 -8
- package/src/assistDocument/components/InstructionsArrayInput.tsx +0 -27
- package/src/assistDocument/components/SelectedFieldContext.tsx +0 -10
- package/src/assistDocument/components/generic/HiddenFieldTitle.tsx +0 -5
- package/src/assistDocument/components/helpers.ts +0 -21
- package/src/assistDocument/components/instruction/BackToInstructionsLink.tsx +0 -32
- package/src/assistDocument/components/instruction/FieldRefInput.tsx +0 -54
- package/src/assistDocument/components/instruction/InstructionInput.tsx +0 -89
- package/src/assistDocument/components/instruction/InstructionOutputField.tsx +0 -46
- package/src/assistDocument/components/instruction/InstructionOutputInput.tsx +0 -206
- package/src/assistDocument/components/instruction/PromptInput.tsx +0 -59
- package/src/assistDocument/components/instruction/appearance/IconInput.tsx +0 -46
- package/src/assistDocument/components/instruction/appearance/InstructionVisibility.tsx +0 -37
- package/src/assistDocument/hooks/useAssistDocumentContextValue.tsx +0 -127
- package/src/assistDocument/hooks/useDocumentState.ts +0 -6
- package/src/assistDocument/hooks/useInstructionToaster.tsx +0 -75
- package/src/assistDocument/hooks/useStudioAssistDocument.ts +0 -99
- package/src/assistDocument/index.ts +0 -1
- package/src/assistFormComponents/AssistField.tsx +0 -63
- package/src/assistFormComponents/AssistFormBlock.tsx +0 -31
- package/src/assistFormComponents/AssistInlineFormBlock.tsx +0 -13
- package/src/assistFormComponents/AssistItem.tsx +0 -21
- package/src/assistFormComponents/validation/listItem.tsx +0 -63
- package/src/assistFormComponents/validation/validationList.tsx +0 -90
- package/src/assistInspector/AssistInspector.tsx +0 -419
- package/src/assistInspector/FieldAutocomplete.tsx +0 -146
- package/src/assistInspector/InstructionTaskHistoryButton.tsx +0 -262
- package/src/assistInspector/constants.ts +0 -1
- package/src/assistInspector/helpers.ts +0 -211
- package/src/assistInspector/index.ts +0 -27
- package/src/assistLayout/AiAssistanceConfigContext.tsx +0 -32
- package/src/assistLayout/AiAssistanceConfigProvider.tsx +0 -98
- package/src/assistLayout/AssistLayout.tsx +0 -39
- package/src/assistLayout/RunInstructionProvider.tsx +0 -278
- package/src/assistLayout/fieldRefCache.tsx +0 -34
- package/src/assistTypes.ts +0 -83
- package/src/components/AssistFeatureBadge.tsx +0 -9
- package/src/components/FadeInContent.tsx +0 -40
- package/src/components/HideReferenceChangedBannerInput.tsx +0 -25
- package/src/components/ImageContext.tsx +0 -85
- package/src/components/SafeValueInput.tsx +0 -74
- package/src/components/TimeAgo.tsx +0 -18
- package/src/constants.ts +0 -20
- package/src/fieldActions/PrivateIcon.tsx +0 -20
- package/src/fieldActions/assistFieldActions.tsx +0 -320
- package/src/fieldActions/customFieldActions.tsx +0 -333
- package/src/fieldActions/generateCaptionActions.tsx +0 -77
- package/src/fieldActions/generateImageActions.tsx +0 -58
- package/src/fieldActions/useUserInput.ts +0 -107
- package/src/globals.d.ts +0 -4
- package/src/helpers/assistSupported.ts +0 -49
- package/src/helpers/conditionalMembers.test.ts +0 -319
- package/src/helpers/conditionalMembers.ts +0 -134
- package/src/helpers/ids.test.ts +0 -28
- package/src/helpers/ids.ts +0 -23
- package/src/helpers/misc.ts +0 -25
- package/src/helpers/styleguide.ts +0 -24
- package/src/helpers/typeUtils.ts +0 -60
- package/src/helpers/useAssistSupported.ts +0 -8
- package/src/index.ts +0 -26
- package/src/onboarding/FirstAssistedPathProvider.tsx +0 -30
- package/src/onboarding/InspectorOnboarding.tsx +0 -47
- package/src/onboarding/onboardingStore.ts +0 -32
- package/src/plugin.tsx +0 -162
- package/src/presence/AiFieldPresence.tsx +0 -28
- package/src/presence/AssistAvatar.tsx +0 -96
- package/src/presence/AssistDocumentPresence.tsx +0 -50
- package/src/presence/useAssistPresence.ts +0 -64
- package/src/schemas/assistDocumentSchema.tsx +0 -497
- package/src/schemas/contextDocumentSchema.tsx +0 -57
- package/src/schemas/index.ts +0 -69
- package/src/schemas/serialize/SchemTypeTool.tsx +0 -103
- package/src/schemas/serialize/schemaUtils.ts +0 -38
- package/src/schemas/serialize/serializeSchema.test.ts +0 -819
- package/src/schemas/serialize/serializeSchema.ts +0 -224
- package/src/schemas/serializedSchemaTypeSchema.ts +0 -60
- package/src/schemas/typeDefExtensions.ts +0 -127
- package/src/translate/FieldTranslationProvider.tsx +0 -382
- package/src/translate/getLanguageParams.ts +0 -26
- package/src/translate/languageStore.ts +0 -18
- package/src/translate/paths.test.ts +0 -181
- package/src/translate/paths.ts +0 -183
- package/src/translate/translateActions.tsx +0 -205
- package/src/translate/types.ts +0 -197
- package/src/types.ts +0 -220
- package/src/useApiClient.ts +0 -338
- package/v2-incompatible.js +0 -11
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import {createContext, useContext} from 'react'
|
|
2
|
-
import {DocumentInspector, ObjectSchemaType, PatchEvent} from 'sanity'
|
|
3
|
-
|
|
4
|
-
import {InstructionTask, StudioAssistDocument} from '../types'
|
|
5
|
-
import {FieldRef} from '../assistInspector/helpers'
|
|
6
|
-
|
|
7
|
-
export type AssistDocumentContextValue = (
|
|
8
|
-
| {assistDocument: StudioAssistDocument; loading: false}
|
|
9
|
-
| {assistDocument: undefined; loading: true}
|
|
10
|
-
) & {
|
|
11
|
-
documentIsNew: boolean
|
|
12
|
-
/**
|
|
13
|
-
* This is the _actual_ id of the current document (ie the document loaded in the pane); it contains draft. versions. prefix ect depending on context
|
|
14
|
-
*/
|
|
15
|
-
assistableDocumentId: string
|
|
16
|
-
documentIsAssistable: boolean
|
|
17
|
-
documentSchemaType: ObjectSchemaType
|
|
18
|
-
openInspector: (inspectorName: string, paneParams?: Record<string, string>) => void
|
|
19
|
-
closeInspector: (inspectorName?: string) => void
|
|
20
|
-
inspector: DocumentInspector | null
|
|
21
|
-
selectedPath?: string
|
|
22
|
-
documentOnChange: (event: PatchEvent) => void
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Synthetic task is used to display AI presence at the document level for the user who started the action.
|
|
26
|
-
* These are not persisted, so other users will not see them.
|
|
27
|
-
* It is mostly a helper to give _some_ visual feedback to the user while a custom action is running.
|
|
28
|
-
* This also means that reloading the page will remove the icon.
|
|
29
|
-
*
|
|
30
|
-
* Agent Actions add their own "real" tasks, so if a custom action calls an Agent action, _those_ tasks
|
|
31
|
-
* are visible across sessions.
|
|
32
|
-
*/
|
|
33
|
-
syntheticTasks?: InstructionTask[]
|
|
34
|
-
addSyntheticTask: (syntheticTask: InstructionTask) => void
|
|
35
|
-
removeSyntheticTask: (syntheticTask: InstructionTask) => void
|
|
36
|
-
|
|
37
|
-
fieldRefs: FieldRef[]
|
|
38
|
-
fieldRefsByTypePath: Record<string, FieldRef | undefined>
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export const AssistDocumentContext = createContext<AssistDocumentContextValue | undefined>(
|
|
42
|
-
undefined,
|
|
43
|
-
)
|
|
44
|
-
|
|
45
|
-
export function useAssistDocumentContext(): AssistDocumentContextValue {
|
|
46
|
-
const context = useContext(AssistDocumentContext)
|
|
47
|
-
if (!context) {
|
|
48
|
-
throw new Error('AssistDocumentContext value is missing')
|
|
49
|
-
}
|
|
50
|
-
return context
|
|
51
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import {PropsWithChildren} from 'react'
|
|
2
|
-
|
|
3
|
-
import {AssistDocumentContext} from './AssistDocumentContext'
|
|
4
|
-
import {useAssistDocumentContextValue} from './hooks/useAssistDocumentContextValue'
|
|
5
|
-
|
|
6
|
-
export interface AIDocumentInputProps {
|
|
7
|
-
documentId: string
|
|
8
|
-
documentType: string
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function AssistDocumentContextProvider(props: PropsWithChildren<AIDocumentInputProps>) {
|
|
12
|
-
const {documentId, documentType} = props
|
|
13
|
-
const value = useAssistDocumentContextValue(documentId, documentType)
|
|
14
|
-
return (
|
|
15
|
-
<AssistDocumentContext.Provider value={value}>{props.children}</AssistDocumentContext.Provider>
|
|
16
|
-
)
|
|
17
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import {useLayer} from '@sanity/ui'
|
|
2
|
-
import {useMemo} from 'react'
|
|
3
|
-
import type {InputProps, ObjectInputProps, ObjectSchemaType} from 'sanity'
|
|
4
|
-
import {useDocumentPane} from 'sanity/structure'
|
|
5
|
-
|
|
6
|
-
import {ConnectFromRegion} from '../_lib/connector'
|
|
7
|
-
import {assistFormId} from '../_lib/form/constants'
|
|
8
|
-
import {usePathKey} from '../helpers/misc'
|
|
9
|
-
import {isType} from '../helpers/typeUtils'
|
|
10
|
-
import {FirstAssistedPathProvider} from '../onboarding/FirstAssistedPathProvider'
|
|
11
|
-
import {assistDocumentTypeName} from '../types'
|
|
12
|
-
import {useInstructionToaster} from './hooks/useInstructionToaster'
|
|
13
|
-
|
|
14
|
-
export function AssistDocumentInputWrapper(props: InputProps) {
|
|
15
|
-
if (!isType(props.schemaType, 'document') && props.id !== 'root' && props.id !== assistFormId) {
|
|
16
|
-
return <AssistInput {...props} />
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const documentId = (props.value as any)?._id as string | undefined
|
|
20
|
-
if (!documentId) {
|
|
21
|
-
return props.renderDefault(props)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return <AssistDocumentInput {...(props as ObjectInputProps)} documentId={documentId} />
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function AssistDocumentInput({documentId, ...props}: ObjectInputProps & {documentId: string}) {
|
|
28
|
-
useInstructionToaster(documentId, props.schemaType)
|
|
29
|
-
|
|
30
|
-
const schemaType = useMemo(() => {
|
|
31
|
-
if (props.schemaType.name !== assistDocumentTypeName) {
|
|
32
|
-
return props.schemaType
|
|
33
|
-
}
|
|
34
|
-
return {
|
|
35
|
-
...props.schemaType,
|
|
36
|
-
type: {
|
|
37
|
-
...props.schemaType.type,
|
|
38
|
-
// compatability with i18nArrays plugin that requires this to be document
|
|
39
|
-
name: 'document',
|
|
40
|
-
},
|
|
41
|
-
} as ObjectSchemaType
|
|
42
|
-
}, [props.schemaType])
|
|
43
|
-
|
|
44
|
-
return (
|
|
45
|
-
<FirstAssistedPathProvider members={props.members}>
|
|
46
|
-
{props.renderDefault({...props, schemaType})}
|
|
47
|
-
</FirstAssistedPathProvider>
|
|
48
|
-
)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function AssistInput(props: InputProps) {
|
|
52
|
-
const {zIndex} = useLayer()
|
|
53
|
-
const {paneKey} = useDocumentPane()
|
|
54
|
-
const pathKey = usePathKey(props.path)
|
|
55
|
-
|
|
56
|
-
return (
|
|
57
|
-
<ConnectFromRegion _key={`${paneKey}_${pathKey}`} zIndex={zIndex} style={{minWidth: 0}}>
|
|
58
|
-
{props.renderDefault(props)}
|
|
59
|
-
</ConnectFromRegion>
|
|
60
|
-
)
|
|
61
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import {DocumentLayoutProps} from 'sanity'
|
|
2
|
-
|
|
3
|
-
import {AssistDocumentContextProvider} from './AssistDocumentContextProvider'
|
|
4
|
-
|
|
5
|
-
export function AssistDocumentLayout(props: DocumentLayoutProps) {
|
|
6
|
-
const {documentId, documentType} = props
|
|
7
|
-
return (
|
|
8
|
-
<AssistDocumentContextProvider documentType={documentType} documentId={documentId}>
|
|
9
|
-
{props.renderDefault(props)}
|
|
10
|
-
</AssistDocumentContextProvider>
|
|
11
|
-
)
|
|
12
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import {useCallback, useEffect, useState} from 'react'
|
|
2
|
-
import {ObjectSchemaType, PatchEvent, SanityDocument, unset} from 'sanity'
|
|
3
|
-
|
|
4
|
-
import {useRunInstruction} from '../assistLayout/RunInstructionProvider'
|
|
5
|
-
|
|
6
|
-
export interface DraftDelayedTaskArgs<T> {
|
|
7
|
-
documentOnChange: (event: PatchEvent) => void
|
|
8
|
-
// indicates if the document is a draft or liveEditable currently
|
|
9
|
-
isDocAssistable: boolean
|
|
10
|
-
task: (args: T) => void
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function isDocAssistable(
|
|
14
|
-
documentSchemaType: ObjectSchemaType,
|
|
15
|
-
published?: SanityDocument | null,
|
|
16
|
-
draft?: SanityDocument | null,
|
|
17
|
-
) {
|
|
18
|
-
return !!(documentSchemaType.liveEdit ? published : draft)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function useRequestRunInstruction(args: {
|
|
22
|
-
documentOnChange: (event: PatchEvent) => void
|
|
23
|
-
// indicates if the document is a draft or liveEditable currently
|
|
24
|
-
isDocAssistable: boolean
|
|
25
|
-
}) {
|
|
26
|
-
const {runInstruction, instructionLoading} = useRunInstruction()
|
|
27
|
-
const requestRunInstruction = useDraftDelayedTask({
|
|
28
|
-
...args,
|
|
29
|
-
task: runInstruction,
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
return {
|
|
33
|
-
instructionLoading,
|
|
34
|
-
requestRunInstruction,
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Ensures that the current document is a draft before running task
|
|
40
|
-
*/
|
|
41
|
-
export function useDraftDelayedTask<T>(args: DraftDelayedTaskArgs<T>) {
|
|
42
|
-
const {documentOnChange, isDocAssistable, task} = args
|
|
43
|
-
|
|
44
|
-
const [queuedArgs, setQueuedArgs] = useState<T | undefined>(undefined)
|
|
45
|
-
|
|
46
|
-
useEffect(() => {
|
|
47
|
-
if (queuedArgs && isDocAssistable) {
|
|
48
|
-
task(queuedArgs)
|
|
49
|
-
setQueuedArgs(undefined)
|
|
50
|
-
}
|
|
51
|
-
}, [queuedArgs, isDocAssistable, task])
|
|
52
|
-
|
|
53
|
-
return useCallback(
|
|
54
|
-
(taskArgs: T) => {
|
|
55
|
-
// make a dummy edit: this will trigger the document/draft to be created
|
|
56
|
-
documentOnChange(PatchEvent.from([unset(['_force_document_creation'])]))
|
|
57
|
-
setQueuedArgs(taskArgs)
|
|
58
|
-
},
|
|
59
|
-
[setQueuedArgs, documentOnChange],
|
|
60
|
-
)
|
|
61
|
-
}
|
|
@@ -1,287 +0,0 @@
|
|
|
1
|
-
import {Card, Stack, Text} from '@sanity/ui'
|
|
2
|
-
import {useContext, useEffect, useMemo, useRef} from 'react'
|
|
3
|
-
import {
|
|
4
|
-
FieldError,
|
|
5
|
-
FormCallbacksProvider,
|
|
6
|
-
FormCallbacksValue,
|
|
7
|
-
FormInput,
|
|
8
|
-
insert,
|
|
9
|
-
KeyedSegment,
|
|
10
|
-
MemberFieldError,
|
|
11
|
-
ObjectInputProps,
|
|
12
|
-
ObjectSchemaType,
|
|
13
|
-
PatchEvent,
|
|
14
|
-
Path,
|
|
15
|
-
SchemaType,
|
|
16
|
-
set,
|
|
17
|
-
setIfMissing,
|
|
18
|
-
stringToPath,
|
|
19
|
-
typed,
|
|
20
|
-
useFormCallbacks,
|
|
21
|
-
useSchema,
|
|
22
|
-
} from 'sanity'
|
|
23
|
-
|
|
24
|
-
import {useAiPaneRouter} from '../../assistInspector/helpers'
|
|
25
|
-
import {useAiAssistanceConfig} from '../../assistLayout/AiAssistanceConfigContext'
|
|
26
|
-
import {
|
|
27
|
-
AssistDocument,
|
|
28
|
-
AssistField,
|
|
29
|
-
assistFieldTypeName,
|
|
30
|
-
AssistInspectorRouteParams,
|
|
31
|
-
documentRootKey,
|
|
32
|
-
fieldPathParam,
|
|
33
|
-
instructionParam,
|
|
34
|
-
StudioInstruction,
|
|
35
|
-
} from '../../types'
|
|
36
|
-
import {AssistTypeContext} from './AssistTypeContext'
|
|
37
|
-
import {BackToInstructionListLink} from './instruction/BackToInstructionsLink'
|
|
38
|
-
import {SelectedFieldContextProvider, SelectedFieldContextValue} from './SelectedFieldContext'
|
|
39
|
-
|
|
40
|
-
const EMPTY_FIELDS: AssistField[] = []
|
|
41
|
-
|
|
42
|
-
export function AssistDocumentForm(props: ObjectInputProps) {
|
|
43
|
-
if (props.readOnly) {
|
|
44
|
-
return (
|
|
45
|
-
<Card border tone="caution" padding={2}>
|
|
46
|
-
<Text size={1}> You do not have sufficient permissions to manage instructions.</Text>
|
|
47
|
-
</Card>
|
|
48
|
-
)
|
|
49
|
-
}
|
|
50
|
-
return <AssistDocumentFormEditable {...props} />
|
|
51
|
-
}
|
|
52
|
-
function AssistDocumentFormEditable(props: ObjectInputProps) {
|
|
53
|
-
const {onChange} = props
|
|
54
|
-
const value = props.value as AssistDocument | undefined
|
|
55
|
-
const id = value?._id
|
|
56
|
-
const fields = value?.fields
|
|
57
|
-
|
|
58
|
-
const {params, setParams} = useAiPaneRouter()
|
|
59
|
-
const pathKey = params[fieldPathParam]
|
|
60
|
-
const {typePath, documentType: targetDocumentType} = useContext(AssistTypeContext)
|
|
61
|
-
const instruction = params[instructionParam]
|
|
62
|
-
|
|
63
|
-
const activeKey = useMemo(() => {
|
|
64
|
-
if (!typePath) {
|
|
65
|
-
return undefined
|
|
66
|
-
}
|
|
67
|
-
return (fields ?? EMPTY_FIELDS).find((f) => f.path === typePath)?._key
|
|
68
|
-
}, [fields, typePath])
|
|
69
|
-
|
|
70
|
-
const activePath: Path | undefined = useMemo(() => {
|
|
71
|
-
if (!activeKey) {
|
|
72
|
-
return undefined
|
|
73
|
-
}
|
|
74
|
-
const base = ['fields', {_key: activeKey}]
|
|
75
|
-
return instruction ? [...base, 'instructions', {_key: instruction}] : base
|
|
76
|
-
}, [activeKey, instruction])
|
|
77
|
-
|
|
78
|
-
const schema = useSchema()
|
|
79
|
-
const documentSchema: ObjectSchemaType | undefined = useMemo(() => {
|
|
80
|
-
if (!targetDocumentType) {
|
|
81
|
-
return undefined
|
|
82
|
-
}
|
|
83
|
-
return schema.get(targetDocumentType) as ObjectSchemaType
|
|
84
|
-
}, [schema, targetDocumentType])
|
|
85
|
-
|
|
86
|
-
const fieldSchema = useSelectedSchema(pathKey, documentSchema)
|
|
87
|
-
|
|
88
|
-
const context: SelectedFieldContextValue = useMemo(
|
|
89
|
-
() => ({
|
|
90
|
-
documentSchema,
|
|
91
|
-
fieldSchema: fieldSchema ?? documentSchema,
|
|
92
|
-
}),
|
|
93
|
-
[fieldSchema, documentSchema],
|
|
94
|
-
)
|
|
95
|
-
|
|
96
|
-
const title = value?.title
|
|
97
|
-
|
|
98
|
-
useEffect(() => {
|
|
99
|
-
if (!title && documentSchema && !id?.startsWith('drafts.')) {
|
|
100
|
-
onChange(set(documentSchema.title ?? documentSchema.name, ['title']))
|
|
101
|
-
}
|
|
102
|
-
}, [title, documentSchema, onChange, id])
|
|
103
|
-
|
|
104
|
-
const {onPathOpen, ...formCallbacks} = useFormCallbacks()
|
|
105
|
-
|
|
106
|
-
const newCallbacks: FormCallbacksValue = useMemo(
|
|
107
|
-
() => ({
|
|
108
|
-
...formCallbacks,
|
|
109
|
-
onPathOpen: (path) => {
|
|
110
|
-
if (!instruction && path.length === 4 && path[2] === 'instructions') {
|
|
111
|
-
setParams(
|
|
112
|
-
typed<AssistInspectorRouteParams>({
|
|
113
|
-
...params,
|
|
114
|
-
[instructionParam]: (path[3] as KeyedSegment)?._key,
|
|
115
|
-
}) as Record<keyof AssistInspectorRouteParams, string | undefined>,
|
|
116
|
-
)
|
|
117
|
-
} else {
|
|
118
|
-
setTimeout(() => onPathOpen(path), 0)
|
|
119
|
-
}
|
|
120
|
-
},
|
|
121
|
-
}),
|
|
122
|
-
[formCallbacks, onPathOpen, params, setParams, instruction],
|
|
123
|
-
)
|
|
124
|
-
|
|
125
|
-
// When showing the instruction list (no specific instruction selected),
|
|
126
|
-
// tell the form to focus on the field path to close any open modals
|
|
127
|
-
useEffect(() => {
|
|
128
|
-
if (activePath && !instruction) {
|
|
129
|
-
onPathOpen(activePath)
|
|
130
|
-
}
|
|
131
|
-
}, [activePath, instruction, onPathOpen])
|
|
132
|
-
|
|
133
|
-
const fieldError = useMemo(() => {
|
|
134
|
-
const fieldError = props.members.find(
|
|
135
|
-
(m): m is FieldError => m.kind === 'error' && m.fieldName === 'fields',
|
|
136
|
-
)
|
|
137
|
-
if (fieldError) {
|
|
138
|
-
return <MemberFieldError member={fieldError} />
|
|
139
|
-
}
|
|
140
|
-
return undefined
|
|
141
|
-
}, [props.members])
|
|
142
|
-
|
|
143
|
-
return (
|
|
144
|
-
<SelectedFieldContextProvider value={context}>
|
|
145
|
-
<Stack space={5}>
|
|
146
|
-
<FieldsInitializer
|
|
147
|
-
key={typePath}
|
|
148
|
-
pathKey={typePath}
|
|
149
|
-
activePath={activePath}
|
|
150
|
-
fields={fields}
|
|
151
|
-
documentSchema={documentSchema}
|
|
152
|
-
onChange={onChange}
|
|
153
|
-
/>
|
|
154
|
-
{instruction && <BackToInstructionListLink />}
|
|
155
|
-
|
|
156
|
-
{activePath && !fieldError && (
|
|
157
|
-
<FormCallbacksProvider {...newCallbacks}>
|
|
158
|
-
<div style={{lineHeight: '1.25em'}}>
|
|
159
|
-
<FormInput {...props} absolutePath={activePath} />
|
|
160
|
-
</div>
|
|
161
|
-
</FormCallbacksProvider>
|
|
162
|
-
)}
|
|
163
|
-
|
|
164
|
-
{fieldError}
|
|
165
|
-
|
|
166
|
-
{!activePath && props.renderDefault(props)}
|
|
167
|
-
</Stack>
|
|
168
|
-
</SelectedFieldContextProvider>
|
|
169
|
-
)
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
function useSelectedSchema(
|
|
173
|
-
fieldPath: string | undefined,
|
|
174
|
-
documentSchema: ObjectSchemaType | undefined,
|
|
175
|
-
): SchemaType | undefined {
|
|
176
|
-
return useMemo(() => {
|
|
177
|
-
if (!fieldPath) {
|
|
178
|
-
return undefined
|
|
179
|
-
}
|
|
180
|
-
if (fieldPath === documentRootKey) {
|
|
181
|
-
return documentSchema
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const path = stringToPath(fieldPath)
|
|
185
|
-
let currentSchema: ObjectSchemaType | undefined = documentSchema
|
|
186
|
-
for (let i = 0; i < path.length; i++) {
|
|
187
|
-
const segment = path[i]
|
|
188
|
-
const field = currentSchema?.fields.find((f) => f.name === segment)
|
|
189
|
-
if (!field) {
|
|
190
|
-
return undefined
|
|
191
|
-
}
|
|
192
|
-
if (i === path.length - 1) {
|
|
193
|
-
return field.type
|
|
194
|
-
}
|
|
195
|
-
if (field.type.jsonType !== 'object') {
|
|
196
|
-
return undefined
|
|
197
|
-
}
|
|
198
|
-
currentSchema = field.type
|
|
199
|
-
}
|
|
200
|
-
return currentSchema
|
|
201
|
-
}, [documentSchema, fieldPath])
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
function FieldsInitializer({
|
|
205
|
-
pathKey,
|
|
206
|
-
activePath,
|
|
207
|
-
fields,
|
|
208
|
-
documentSchema,
|
|
209
|
-
onChange,
|
|
210
|
-
}: {
|
|
211
|
-
pathKey?: string
|
|
212
|
-
activePath?: Path
|
|
213
|
-
fields: AssistField[] | undefined
|
|
214
|
-
documentSchema: ObjectSchemaType | undefined
|
|
215
|
-
onChange: ObjectInputProps['onChange']
|
|
216
|
-
}) {
|
|
217
|
-
const {
|
|
218
|
-
config: {__presets: presets},
|
|
219
|
-
} = useAiAssistanceConfig()
|
|
220
|
-
|
|
221
|
-
const existingField = fields?.find((f) => f._key === pathKey)
|
|
222
|
-
const documentPresets = !!documentSchema?.name && presets?.[documentSchema?.name]
|
|
223
|
-
|
|
224
|
-
const missingPresetInstructions = useMemo(() => {
|
|
225
|
-
if (!documentPresets || !pathKey) {
|
|
226
|
-
return undefined
|
|
227
|
-
}
|
|
228
|
-
const existingInstructions = existingField?.instructions
|
|
229
|
-
const presetField = documentPresets.fields?.find((f) => f.path === pathKey)
|
|
230
|
-
return presetField?.instructions?.filter(
|
|
231
|
-
(i) => !existingInstructions?.some((ei) => ei._key === i._key),
|
|
232
|
-
)
|
|
233
|
-
}, [documentPresets, pathKey, existingField])
|
|
234
|
-
|
|
235
|
-
// need this to not fire onChange twice in React strict mode
|
|
236
|
-
const initialized = useRef(false)
|
|
237
|
-
useEffect(() => {
|
|
238
|
-
if (initialized.current || !pathKey) {
|
|
239
|
-
return
|
|
240
|
-
}
|
|
241
|
-
if (existingField && !missingPresetInstructions?.length) {
|
|
242
|
-
return
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
let event = PatchEvent.from([setIfMissing([], ['fields'])])
|
|
246
|
-
if (!existingField) {
|
|
247
|
-
event = event.append(
|
|
248
|
-
insert(
|
|
249
|
-
[
|
|
250
|
-
typed<AssistField>({
|
|
251
|
-
_key: pathKey,
|
|
252
|
-
_type: assistFieldTypeName,
|
|
253
|
-
path: pathKey,
|
|
254
|
-
instructions: [],
|
|
255
|
-
}),
|
|
256
|
-
],
|
|
257
|
-
'after',
|
|
258
|
-
['fields', -1],
|
|
259
|
-
),
|
|
260
|
-
)
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
if (!existingField?.instructions?.length) {
|
|
264
|
-
event = event.append([setIfMissing([], ['fields', {_key: pathKey}, 'instructions'])])
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
if (missingPresetInstructions?.length) {
|
|
268
|
-
event = event.append(
|
|
269
|
-
insert(
|
|
270
|
-
missingPresetInstructions.map(
|
|
271
|
-
(preset): StudioInstruction => ({
|
|
272
|
-
...preset,
|
|
273
|
-
_type: 'sanity.assist.instruction',
|
|
274
|
-
prompt: preset.prompt?.map((p) => ({markDefs: [], ...p})),
|
|
275
|
-
}),
|
|
276
|
-
),
|
|
277
|
-
'after',
|
|
278
|
-
['fields', {_key: pathKey}, 'instructions', -1],
|
|
279
|
-
),
|
|
280
|
-
)
|
|
281
|
-
}
|
|
282
|
-
onChange(event)
|
|
283
|
-
initialized.current = true
|
|
284
|
-
}, [activePath, onChange, pathKey, existingField, missingPresetInstructions])
|
|
285
|
-
|
|
286
|
-
return null
|
|
287
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import {Box, Flex, Text} from '@sanity/ui'
|
|
2
|
-
import {useContext} from 'react'
|
|
3
|
-
import {PreviewProps} from 'sanity'
|
|
4
|
-
|
|
5
|
-
import {InlineBlockValueContext} from '../../assistFormComponents/AssistInlineFormBlock'
|
|
6
|
-
import {useSelectedField} from '../../assistInspector/helpers'
|
|
7
|
-
import {SelectedFieldContext} from './SelectedFieldContext'
|
|
8
|
-
|
|
9
|
-
export function FieldRefPreview(props: PreviewProps & {path?: string}) {
|
|
10
|
-
const {actions} = props
|
|
11
|
-
const documentSchema = useContext(SelectedFieldContext)?.documentSchema
|
|
12
|
-
const path = (useContext(InlineBlockValueContext) as {path?: string})?.path ?? props.path
|
|
13
|
-
const selectedField = useSelectedField(documentSchema, path)
|
|
14
|
-
return (
|
|
15
|
-
<Flex gap={2} align="center" style={{width: '100%'}}>
|
|
16
|
-
<Flex flex={1} gap={2} align="center" paddingY={3} paddingX={1}>
|
|
17
|
-
<Box>
|
|
18
|
-
<Text size={1} textOverflow="ellipsis">
|
|
19
|
-
{selectedField?.title ?? 'Select field'}
|
|
20
|
-
</Text>
|
|
21
|
-
</Box>
|
|
22
|
-
</Flex>
|
|
23
|
-
{actions as any}
|
|
24
|
-
</Flex>
|
|
25
|
-
)
|
|
26
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import {useMemo} from 'react'
|
|
2
|
-
import {ArrayOfObjectsInputProps, useCurrentUser} from 'sanity'
|
|
3
|
-
|
|
4
|
-
import {StudioInstruction} from '../../types'
|
|
5
|
-
|
|
6
|
-
export function InstructionsArrayInput(props: ArrayOfObjectsInputProps) {
|
|
7
|
-
const user = useCurrentUser()
|
|
8
|
-
|
|
9
|
-
const originalValue = props.value as StudioInstruction[] | undefined
|
|
10
|
-
const originalMembers = props.members
|
|
11
|
-
const value = useMemo(
|
|
12
|
-
() => (originalValue ?? []).filter((v) => !v.userId || v.userId === user?.id),
|
|
13
|
-
[originalValue, user],
|
|
14
|
-
)
|
|
15
|
-
const members = useMemo(
|
|
16
|
-
() =>
|
|
17
|
-
(originalMembers ?? []).filter((v) => {
|
|
18
|
-
if (v.kind === 'error') {
|
|
19
|
-
return true
|
|
20
|
-
}
|
|
21
|
-
const value = v?.item?.value as any
|
|
22
|
-
return !value.userId || value.userId === user?.id
|
|
23
|
-
}),
|
|
24
|
-
[originalMembers, user],
|
|
25
|
-
)
|
|
26
|
-
return props.renderDefault({...props, value, members})
|
|
27
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import {createContext} from 'react'
|
|
2
|
-
import {ObjectSchemaType, SchemaType} from 'sanity'
|
|
3
|
-
|
|
4
|
-
export interface SelectedFieldContextValue {
|
|
5
|
-
documentSchema?: ObjectSchemaType
|
|
6
|
-
fieldSchema?: SchemaType
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export const SelectedFieldContext = createContext<SelectedFieldContextValue | undefined>(undefined)
|
|
10
|
-
export const SelectedFieldContextProvider = SelectedFieldContext.Provider
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import {FieldError, FieldMember, FieldSetMember, ObjectMember} from 'sanity'
|
|
2
|
-
|
|
3
|
-
export function findFieldMember(
|
|
4
|
-
members: ObjectMember[],
|
|
5
|
-
fieldName: string,
|
|
6
|
-
): FieldMember | FieldError | undefined {
|
|
7
|
-
return members.find(
|
|
8
|
-
(m): m is FieldMember | FieldError =>
|
|
9
|
-
(m.kind === 'field' && m.name === fieldName) ||
|
|
10
|
-
(m.kind === 'error' && m.fieldName === fieldName),
|
|
11
|
-
)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export function findFieldsetMember(
|
|
15
|
-
members: ObjectMember[],
|
|
16
|
-
fieldsetName: string,
|
|
17
|
-
): FieldSetMember | undefined {
|
|
18
|
-
return members.find(
|
|
19
|
-
(m): m is FieldSetMember => m.kind === 'fieldSet' && m.fieldSet.name === fieldsetName,
|
|
20
|
-
)
|
|
21
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import {ArrowLeftIcon} from '@sanity/icons'
|
|
2
|
-
import {Button} from '@sanity/ui'
|
|
3
|
-
import {useCallback} from 'react'
|
|
4
|
-
import {useDocumentPane} from 'sanity/structure'
|
|
5
|
-
|
|
6
|
-
import {aiInspectorId} from '../../../assistInspector/constants'
|
|
7
|
-
import {instructionParam} from '../../../types'
|
|
8
|
-
|
|
9
|
-
export function BackToInstructionListLink() {
|
|
10
|
-
const {openInspector} = useDocumentPane()
|
|
11
|
-
|
|
12
|
-
const goBack = useCallback(
|
|
13
|
-
() => openInspector(aiInspectorId, {[instructionParam]: undefined as any}),
|
|
14
|
-
[openInspector],
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
return (
|
|
18
|
-
<div>
|
|
19
|
-
<Button
|
|
20
|
-
as="a"
|
|
21
|
-
fontSize={1}
|
|
22
|
-
icon={ArrowLeftIcon}
|
|
23
|
-
mode="bleed"
|
|
24
|
-
padding={1}
|
|
25
|
-
space={2}
|
|
26
|
-
onClick={goBack}
|
|
27
|
-
text=" Instructions"
|
|
28
|
-
textAlign="left"
|
|
29
|
-
/>
|
|
30
|
-
</div>
|
|
31
|
-
)
|
|
32
|
-
}
|