@sanity/assist 4.3.2 → 4.4.1
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 +3 -0
- package/dist/index.d.mts +12 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.esm.js +24 -6
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +24 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +24 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/assistDocument/AssistDocumentContext.tsx +4 -0
- package/src/assistDocument/hooks/useAssistDocumentContextValue.tsx +7 -1
- package/src/assistInspector/helpers.ts +8 -0
- package/src/assistLayout/RunInstructionProvider.tsx +1 -0
- package/src/fieldActions/assistFieldActions.tsx +15 -1
- package/src/fieldActions/customFieldActions.tsx +12 -0
- package/src/helpers/assistSupported.ts +5 -1
- package/src/schemas/serialize/serializeSchema.test.ts +18 -4
- package/src/types.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/assist",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.4.1",
|
|
4
4
|
"description": "You create the instructions; Sanity AI Assist does the rest.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"@rollup/plugin-image": "^3.0.3",
|
|
66
66
|
"@sanity/pkg-utils": "^6.13.4",
|
|
67
67
|
"@sanity/plugin-kit": "^3.1.10",
|
|
68
|
-
"@sanity/schema": "^3.
|
|
68
|
+
"@sanity/schema": "^3.93.0",
|
|
69
69
|
"@sanity/semantic-release-preset": "^4.1.7",
|
|
70
70
|
"@types/lodash": "^4.17.0",
|
|
71
71
|
"@types/lodash-es": "^4.17.12",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"react": "^18.2.0",
|
|
84
84
|
"react-dom": "^18.2.0",
|
|
85
85
|
"rimraf": "^5.0.5",
|
|
86
|
-
"sanity": "^3.
|
|
86
|
+
"sanity": "^3.93.0",
|
|
87
87
|
"semantic-release": "^23.0.8",
|
|
88
88
|
"styled-components": "^6.1.16",
|
|
89
89
|
"typescript": "^5.7.2",
|
|
@@ -2,6 +2,7 @@ import {createContext, useContext} from 'react'
|
|
|
2
2
|
import {DocumentInspector, ObjectSchemaType, PatchEvent} from 'sanity'
|
|
3
3
|
|
|
4
4
|
import {InstructionTask, StudioAssistDocument} from '../types'
|
|
5
|
+
import {FieldRef} from '../assistInspector/helpers'
|
|
5
6
|
|
|
6
7
|
export type AssistDocumentContextValue = (
|
|
7
8
|
| {assistDocument: StudioAssistDocument; loading: false}
|
|
@@ -32,6 +33,9 @@ export type AssistDocumentContextValue = (
|
|
|
32
33
|
syntheticTasks?: InstructionTask[]
|
|
33
34
|
addSyntheticTask: (syntheticTask: InstructionTask) => void
|
|
34
35
|
removeSyntheticTask: (syntheticTask: InstructionTask) => void
|
|
36
|
+
|
|
37
|
+
fieldRefs: FieldRef[]
|
|
38
|
+
fieldRefsByTypePath: Record<string, FieldRef | undefined>
|
|
35
39
|
}
|
|
36
40
|
|
|
37
41
|
export const AssistDocumentContext = createContext<AssistDocumentContextValue | undefined>(
|
|
@@ -2,7 +2,7 @@ import {useCallback, useEffect, useMemo, useState} from 'react'
|
|
|
2
2
|
import {getDraftId, getVersionId, type ObjectSchemaType, useSchema} from 'sanity'
|
|
3
3
|
import {useDocumentPane} from 'sanity/structure'
|
|
4
4
|
|
|
5
|
-
import {useAiPaneRouter} from '../../assistInspector/helpers'
|
|
5
|
+
import {asFieldRefsByTypePath, getFieldRefs, useAiPaneRouter} from '../../assistInspector/helpers'
|
|
6
6
|
import {fieldPathParam, InstructionTask} from '../../types'
|
|
7
7
|
import type {AssistDocumentContextValue} from '../AssistDocumentContext'
|
|
8
8
|
import {isDocAssistable} from '../RequestRunInstructionProvider'
|
|
@@ -53,6 +53,10 @@ export function useAssistDocumentContextValue(documentId: string, documentType:
|
|
|
53
53
|
})
|
|
54
54
|
const {syntheticTasks, addSyntheticTask, removeSyntheticTask} =
|
|
55
55
|
useSyntheticTasks(assistableDocumentId)
|
|
56
|
+
|
|
57
|
+
const fieldRefs = getFieldRefs(documentSchemaType)
|
|
58
|
+
const fieldRefsByTypePath = asFieldRefsByTypePath(fieldRefs)
|
|
59
|
+
|
|
56
60
|
const value: AssistDocumentContextValue = useMemo(() => {
|
|
57
61
|
const base = {
|
|
58
62
|
assistableDocumentId,
|
|
@@ -67,6 +71,8 @@ export function useAssistDocumentContextValue(documentId: string, documentType:
|
|
|
67
71
|
syntheticTasks,
|
|
68
72
|
addSyntheticTask,
|
|
69
73
|
removeSyntheticTask,
|
|
74
|
+
fieldRefs,
|
|
75
|
+
fieldRefsByTypePath,
|
|
70
76
|
}
|
|
71
77
|
if (!assistDocument) {
|
|
72
78
|
return {...base, loading: true, assistDocument: undefined}
|
|
@@ -57,6 +57,14 @@ export function getTypeIcon(schemaType: SchemaType) {
|
|
|
57
57
|
return DocumentIcon
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
export function asFieldRefsByTypePath(fieldRefs: FieldRef[]): Record<string, FieldRef | undefined> {
|
|
61
|
+
const lookup: Record<string, FieldRef | undefined> = fieldRefs.reduce(
|
|
62
|
+
(acc, ref) => ({...acc, [ref.key]: ref}),
|
|
63
|
+
{},
|
|
64
|
+
)
|
|
65
|
+
return lookup
|
|
66
|
+
}
|
|
67
|
+
|
|
60
68
|
export function getFieldRefsWithDocument(schemaType: ObjectSchemaType): FieldRef[] {
|
|
61
69
|
const fields = getFieldRefs(schemaType)
|
|
62
70
|
return [
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
type DocumentFieldAction,
|
|
5
5
|
type DocumentFieldActionGroup,
|
|
6
6
|
type DocumentFieldActionItem,
|
|
7
|
+
pathToString,
|
|
7
8
|
stringToPath,
|
|
8
9
|
typed,
|
|
9
10
|
useCurrentUser,
|
|
@@ -14,7 +15,7 @@ import {useAssistDocumentContext} from '../assistDocument/AssistDocumentContext'
|
|
|
14
15
|
import {getIcon} from '../assistDocument/components/instruction/appearance/IconInput'
|
|
15
16
|
import {useRequestRunInstruction} from '../assistDocument/RequestRunInstructionProvider'
|
|
16
17
|
import {aiInspectorId} from '../assistInspector/constants'
|
|
17
|
-
import {useSelectedField, useTypePath} from '../assistInspector/helpers'
|
|
18
|
+
import {getTypePath, useSelectedField, useTypePath} from '../assistInspector/helpers'
|
|
18
19
|
import {pluginTitleShort} from '../constants'
|
|
19
20
|
import {isSchemaAssistEnabled} from '../helpers/assistSupported'
|
|
20
21
|
import {getConditionalMembers} from '../helpers/conditionalMembers'
|
|
@@ -48,6 +49,7 @@ export const assistFieldActions: DocumentFieldAction = {
|
|
|
48
49
|
documentSchemaType,
|
|
49
50
|
selectedPath,
|
|
50
51
|
assistableDocumentId,
|
|
52
|
+
fieldRefsByTypePath,
|
|
51
53
|
} = useAssistDocumentContext()
|
|
52
54
|
|
|
53
55
|
const {value: docValue, formState} = useDocumentPane()
|
|
@@ -204,6 +206,17 @@ export const assistFieldActions: DocumentFieldAction = {
|
|
|
204
206
|
)
|
|
205
207
|
}, [])
|
|
206
208
|
|
|
209
|
+
const parentSchemaType = useMemo(() => {
|
|
210
|
+
if (!props.path.length) {
|
|
211
|
+
return undefined
|
|
212
|
+
} else if (props.path.length === 1) {
|
|
213
|
+
return documentSchemaType
|
|
214
|
+
}
|
|
215
|
+
const parentPath = props.path.slice(0, -1)
|
|
216
|
+
const typePath = getTypePath(docValueRef.current, pathToString(parentPath))
|
|
217
|
+
return typePath ? fieldRefsByTypePath[typePath]?.schemaType : undefined
|
|
218
|
+
}, [fieldRefsByTypePath, props.path, documentSchemaType])
|
|
219
|
+
|
|
207
220
|
const customActions = useCustomFieldActions({
|
|
208
221
|
actionType: props.path.length ? 'field' : 'document',
|
|
209
222
|
documentIdForAction: assistableDocumentId,
|
|
@@ -212,6 +225,7 @@ export const assistFieldActions: DocumentFieldAction = {
|
|
|
212
225
|
path: props.path,
|
|
213
226
|
getDocumentValue,
|
|
214
227
|
getConditionalPaths,
|
|
228
|
+
parentSchemaType,
|
|
215
229
|
})
|
|
216
230
|
|
|
217
231
|
const manageInstructionsItem = useMemo(
|
|
@@ -92,6 +92,8 @@ export interface AssistFieldActionProps {
|
|
|
92
92
|
* },
|
|
93
93
|
* //...
|
|
94
94
|
* })
|
|
95
|
+
*
|
|
96
|
+
* ```
|
|
95
97
|
*/
|
|
96
98
|
schemaId: string
|
|
97
99
|
|
|
@@ -142,6 +144,16 @@ export interface AssistFieldActionProps {
|
|
|
142
144
|
* ```
|
|
143
145
|
*/
|
|
144
146
|
schemaType: SchemaType
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Schema type of the parent field or array item holding this field.
|
|
150
|
+
*
|
|
151
|
+
* This can be undefined if the action was unable to resolve the parent type is excluded from AI Assist.
|
|
152
|
+
*
|
|
153
|
+
* @see schemaType
|
|
154
|
+
* @see documentSchemaType
|
|
155
|
+
*/
|
|
156
|
+
parentSchemaType?: SchemaType
|
|
145
157
|
}
|
|
146
158
|
|
|
147
159
|
export type AssistFieldActionNode =
|
|
@@ -23,7 +23,11 @@ export function isAssistSupported(type: SchemaType) {
|
|
|
23
23
|
|
|
24
24
|
if (type.jsonType === 'object') {
|
|
25
25
|
const unsupportedObject = type.fields.every((field) => isDisabled(field.type))
|
|
26
|
-
return
|
|
26
|
+
return (
|
|
27
|
+
!unsupportedObject ||
|
|
28
|
+
/* to allow attaching custom actions on fieldless images */
|
|
29
|
+
isType(type, 'image')
|
|
30
|
+
)
|
|
27
31
|
}
|
|
28
32
|
return true
|
|
29
33
|
}
|
|
@@ -123,7 +123,7 @@ describe('serializeSchema', () => {
|
|
|
123
123
|
expect(serializedTypes).toEqual([])
|
|
124
124
|
})
|
|
125
125
|
|
|
126
|
-
test('should not serialize excluded fields or types or types with every member excluded', () => {
|
|
126
|
+
test('should not serialize excluded fields or types or types with every member excluded (except images)', () => {
|
|
127
127
|
const options: AssistOptions = {aiAssist: {exclude: true}}
|
|
128
128
|
|
|
129
129
|
const schema = Schema.compile({
|
|
@@ -131,7 +131,7 @@ describe('serializeSchema', () => {
|
|
|
131
131
|
types: [
|
|
132
132
|
{
|
|
133
133
|
type: 'document',
|
|
134
|
-
name: '
|
|
134
|
+
name: 'mostFieldsExcluded',
|
|
135
135
|
fields: [
|
|
136
136
|
defineField({type: 'string', name: 'title', options}),
|
|
137
137
|
defineField({
|
|
@@ -148,7 +148,7 @@ describe('serializeSchema', () => {
|
|
|
148
148
|
of: [{type: 'object', name: 'remove', options}, {type: 'excluded'}],
|
|
149
149
|
options: {aiAssist: {exclude: true}},
|
|
150
150
|
}),
|
|
151
|
-
//image without extra fields should be excluded
|
|
151
|
+
//image without extra fields should NOT be excluded
|
|
152
152
|
defineField({type: 'image', name: 'image'}),
|
|
153
153
|
defineField({type: 'file', name: 'file'}),
|
|
154
154
|
defineField({type: 'reference', name: 'reference', to: [{type: 'excluded'}]}),
|
|
@@ -174,7 +174,21 @@ describe('serializeSchema', () => {
|
|
|
174
174
|
const serializedTypes = serializeSchema(schema, {leanFormat: true})
|
|
175
175
|
|
|
176
176
|
//everything excluded directly or indirectly
|
|
177
|
-
expect(serializedTypes).toEqual([
|
|
177
|
+
expect(serializedTypes).toEqual([
|
|
178
|
+
{
|
|
179
|
+
fields: [
|
|
180
|
+
{
|
|
181
|
+
fields: [],
|
|
182
|
+
name: 'image',
|
|
183
|
+
title: 'Image',
|
|
184
|
+
type: 'image',
|
|
185
|
+
},
|
|
186
|
+
],
|
|
187
|
+
name: 'mostFieldsExcluded',
|
|
188
|
+
title: 'Most Fields Excluded',
|
|
189
|
+
type: 'document',
|
|
190
|
+
},
|
|
191
|
+
])
|
|
178
192
|
})
|
|
179
193
|
|
|
180
194
|
test('should serialize opt-in inline object using custom typeName', () => {
|