@sanity/assist 4.3.1 → 4.4.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 +181 -175
- package/dist/index.d.mts +21 -3
- package/dist/index.d.ts +21 -3
- package/dist/index.esm.js +31 -10
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +31 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +31 -10
- 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 +38 -10
- package/src/helpers/misc.ts +4 -0
- package/src/plugin.tsx +4 -1
- package/src/types.ts +1 -1
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
- [Adding translation actions to fields](#adding-translation-actions-to-fields)
|
|
36
36
|
- [Translation style guide](#translation-style-guide)
|
|
37
37
|
- [Custom field actions](#custom-field-actions)
|
|
38
|
-
- [
|
|
38
|
+
- [useExampleFieldActions](#usefieldaction)
|
|
39
39
|
- [Define helpers](#define-helpers)
|
|
40
40
|
- [useUserInput](#useuserinput)
|
|
41
41
|
- [License](#license)
|
|
@@ -949,40 +949,59 @@ assist({
|
|
|
949
949
|
<img width="513" alt="Field action menu with custom actions" src="https://github.com/user-attachments/assets/c613f692-4983-4acc-a8c2-8fb60294682a" />
|
|
950
950
|
|
|
951
951
|
To incorporate [Agent Actions](https://www.sanity.io/docs/agent-actions?utm_source=github.com&utm_medium=organic_social&utm_campaign=ai-assist&utm_content=)
|
|
952
|
-
or other custom actions into the AI Assist document and field action menus, use `fieldActions` plugin config
|
|
952
|
+
or other custom actions into the AI Assist document and field action menus, use `fieldActions` plugin config.
|
|
953
|
+
|
|
954
|
+
Because of react hook linting, we recommend defining the `useExampleFieldActions` outside the plugin config:
|
|
953
955
|
|
|
954
956
|
```ts
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
}
|
|
970
|
-
|
|
957
|
+
//sanity.config.ts
|
|
958
|
+
import {defineConfig} from 'sanity'
|
|
959
|
+
import {assist, type AssistFieldActionProps, defineAssistFieldAction} from '@sanity/assist'
|
|
960
|
+
|
|
961
|
+
function useExampleFieldActions(props: AssistFieldActionProps) {
|
|
962
|
+
return useMemo(() => [
|
|
963
|
+
defineAssistFieldAction({
|
|
964
|
+
title: 'Do something',
|
|
965
|
+
icon: ActionIcon,
|
|
966
|
+
onAction: async () => {
|
|
967
|
+
// perform an (async) action
|
|
968
|
+
// errors will be caught and displayed in a toast
|
|
969
|
+
// until the action completes or fails, AI Assist "presence" will show up on the top of the document
|
|
970
|
+
},
|
|
971
|
+
})], [])
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
export default defineConfig({
|
|
975
|
+
//...
|
|
976
|
+
plugins: [
|
|
977
|
+
//...other plugins
|
|
978
|
+
assist({
|
|
979
|
+
fieldActions: {
|
|
980
|
+
title: 'Custom actions',
|
|
981
|
+
useExampleFieldActions
|
|
982
|
+
}
|
|
983
|
+
})
|
|
984
|
+
]
|
|
971
985
|
})
|
|
972
986
|
```
|
|
973
987
|
|
|
974
|
-
### `
|
|
988
|
+
### `useExampleFieldActions`
|
|
975
989
|
|
|
976
|
-
`
|
|
990
|
+
`useExampleFieldActions` is called for the document itself and for all fields within it. It can call React hooks.
|
|
977
991
|
Actions returned by the hook will be added to the corresponding document or field menu.
|
|
978
992
|
|
|
979
|
-
It is recommended to wrap the returned actions in `useMemo`.
|
|
993
|
+
It is recommended to wrap the returned actions in `useMemo`. The returned array can contain `undefined` values.
|
|
994
|
+
These will be filtered out.
|
|
995
|
+
|
|
980
996
|
|
|
981
997
|
See TSDocs for [AssistFieldActionProps](./src/fieldActions/customFieldActions.tsx) for details on how each
|
|
982
998
|
prop can be used to parameterize Agent Actions on sanity client.
|
|
983
999
|
|
|
984
1000
|
#### Agent Action examples
|
|
985
1001
|
|
|
1002
|
+
Below are some examples of agent action integration.
|
|
1003
|
+
For more, see [HOW-TO_USE](../studio/examples/agentActions/HOW-TO-USE.md)
|
|
1004
|
+
|
|
986
1005
|
##### Fix spelling
|
|
987
1006
|
|
|
988
1007
|
The following example adds a "Fix spelling" action to all fields and the document itself.
|
|
@@ -991,49 +1010,44 @@ It will fix spelling mistakes for the field it is invoked for (and all child fie
|
|
|
991
1010
|
by calling `client.agent.action.transform`.
|
|
992
1011
|
|
|
993
1012
|
```ts
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
path,
|
|
1033
|
-
])
|
|
1034
|
-
},
|
|
1035
|
-
},
|
|
1036
|
-
})
|
|
1013
|
+
function useExampleFieldActions(props: AssistFieldActionProps) {
|
|
1014
|
+
const {
|
|
1015
|
+
documentSchemaType,
|
|
1016
|
+
schemaId,
|
|
1017
|
+
getDocumentValue,
|
|
1018
|
+
getConditionalPaths,
|
|
1019
|
+
documentIdForAction,
|
|
1020
|
+
path,
|
|
1021
|
+
} = props
|
|
1022
|
+
const client = useClient({apiVersion: 'vX'})
|
|
1023
|
+
return useMemo(() => {
|
|
1024
|
+
return [
|
|
1025
|
+
defineAssistFieldAction({
|
|
1026
|
+
title: 'Fix spelling',
|
|
1027
|
+
icon: TranslateIcon,
|
|
1028
|
+
onAction: async () => {
|
|
1029
|
+
await client.agent.action.transform({
|
|
1030
|
+
schemaId,
|
|
1031
|
+
documentId: documentIdForAction,
|
|
1032
|
+
instruction: 'Fix any spelling mistakes',
|
|
1033
|
+
instructionParams: {field: {type: 'field', path}},
|
|
1034
|
+
// no need to send path for document actions
|
|
1035
|
+
target: path.length ? {path} : undefined,
|
|
1036
|
+
conditionalPaths: {paths: getConditionalPaths()},
|
|
1037
|
+
})
|
|
1038
|
+
},
|
|
1039
|
+
}),
|
|
1040
|
+
]
|
|
1041
|
+
}, [
|
|
1042
|
+
client,
|
|
1043
|
+
documentSchemaType,
|
|
1044
|
+
schemaId,
|
|
1045
|
+
getDocumentValue,
|
|
1046
|
+
getConditionalPaths,
|
|
1047
|
+
documentIdForAction,
|
|
1048
|
+
path,
|
|
1049
|
+
])
|
|
1050
|
+
}
|
|
1037
1051
|
```
|
|
1038
1052
|
|
|
1039
1053
|
##### Fill field (contextually aware)
|
|
@@ -1047,44 +1061,41 @@ The action will:
|
|
|
1047
1061
|
- output to the field the action started from (`target.path`)
|
|
1048
1062
|
|
|
1049
1063
|
```ts
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
return
|
|
1069
|
-
|
|
1070
|
-
// in this case we dont want a document action
|
|
1071
|
-
return []
|
|
1072
|
-
}
|
|
1064
|
+
function useExampleFieldActions(props: AssistFieldActionProps) {
|
|
1065
|
+
const {
|
|
1066
|
+
documentSchemaType,
|
|
1067
|
+
actionType,
|
|
1068
|
+
schemaId,
|
|
1069
|
+
getDocumentValue,
|
|
1070
|
+
getConditionalPaths,
|
|
1071
|
+
documentIdForAction,
|
|
1072
|
+
path,
|
|
1073
|
+
schemaType,
|
|
1074
|
+
} = props
|
|
1075
|
+
|
|
1076
|
+
// hook usage has to happen outside onAction, so preassemble state in useExampleFieldActions and pass to useMemo
|
|
1077
|
+
const client = useClient({apiVersion: 'vX'})
|
|
1078
|
+
|
|
1079
|
+
return useMemo(() => {
|
|
1080
|
+
if (actionType === 'document') {
|
|
1081
|
+
// in this case we dont want a document action
|
|
1082
|
+
return []
|
|
1083
|
+
}
|
|
1073
1084
|
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1085
|
+
return [
|
|
1086
|
+
defineAssistFieldAction({
|
|
1087
|
+
title: 'Fill field',
|
|
1088
|
+
icon: EditIcon,
|
|
1089
|
+
onAction: async () => {
|
|
1090
|
+
await client.agent.action.generate({
|
|
1091
|
+
schemaId,
|
|
1092
|
+
targetDocument: {
|
|
1093
|
+
operation: 'createIfNotExists',
|
|
1094
|
+
_id: documentIdForAction,
|
|
1095
|
+
_type: documentSchemaType.name,
|
|
1096
|
+
initialValues: getDocumentValue(),
|
|
1097
|
+
},
|
|
1098
|
+
instruction: `
|
|
1088
1099
|
We are generating a new value for a document field.
|
|
1089
1100
|
The document type is ${documentSchemaType.name}, and the document type title is ${documentSchemaType.title}
|
|
1090
1101
|
The document language is: "$lang" (use en-US if unspecified)
|
|
@@ -1099,35 +1110,33 @@ The action will:
|
|
|
1099
1110
|
Generate a new field value. The new value should be relevant to the document type and context.
|
|
1100
1111
|
Keep it interesting. Generate using the document language.
|
|
1101
1112
|
`,
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
},
|
|
1107
|
-
target: {
|
|
1108
|
-
path,
|
|
1109
|
-
},
|
|
1110
|
-
conditionalPaths: {
|
|
1111
|
-
paths: getConditionalPaths(),
|
|
1112
|
-
},
|
|
1113
|
-
})
|
|
1113
|
+
instructionParams: {
|
|
1114
|
+
doc: {type: 'document'},
|
|
1115
|
+
field: {type: 'field', path},
|
|
1116
|
+
lang: {type: 'field', path: ['language']},
|
|
1114
1117
|
},
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1118
|
+
target: {
|
|
1119
|
+
path,
|
|
1120
|
+
},
|
|
1121
|
+
conditionalPaths: {
|
|
1122
|
+
paths: getConditionalPaths(),
|
|
1123
|
+
},
|
|
1124
|
+
})
|
|
1125
|
+
},
|
|
1126
|
+
}),
|
|
1127
|
+
]
|
|
1128
|
+
}, [
|
|
1129
|
+
client,
|
|
1130
|
+
documentSchemaType,
|
|
1131
|
+
schemaId,
|
|
1132
|
+
getDocumentValue,
|
|
1133
|
+
getConditionalPaths,
|
|
1134
|
+
documentIdForAction,
|
|
1135
|
+
actionType,
|
|
1136
|
+
path,
|
|
1137
|
+
schemaType,
|
|
1138
|
+
])
|
|
1139
|
+
}
|
|
1131
1140
|
```
|
|
1132
1141
|
|
|
1133
1142
|
### Define helpers
|
|
@@ -1136,7 +1145,7 @@ The action will:
|
|
|
1136
1145
|
|
|
1137
1146
|
Adds a single action that will appear in the document/field action menu.
|
|
1138
1147
|
|
|
1139
|
-
`onAction` _cannot_ call hooks. If state from hook is needed, it should be pre-assembled by `
|
|
1148
|
+
`onAction` _cannot_ call hooks. If state from hook is needed, it should be pre-assembled by `useExampleFieldActions`
|
|
1140
1149
|
|
|
1141
1150
|
```ts
|
|
1142
1151
|
defineAssistFieldAction({
|
|
@@ -1151,10 +1160,12 @@ defineAssistFieldAction({
|
|
|
1151
1160
|
#### `defineAssistFieldActionGroup`
|
|
1152
1161
|
|
|
1153
1162
|
Adds a group to hold one or more actions (or nested groups).
|
|
1163
|
+
`children` can contain `undefined` values. These will be filtered out.
|
|
1164
|
+
A group that has an empty `children` array (or only undefined values) will be filtered out.
|
|
1154
1165
|
|
|
1155
|
-
By default, any actions returned by `
|
|
1166
|
+
By default, any actions returned by `useExampleFieldActions` will be grouped under `title`.
|
|
1156
1167
|
```ts
|
|
1157
|
-
|
|
1168
|
+
function useExampleFieldActions(props: AssistFieldActionProps) {
|
|
1158
1169
|
return [
|
|
1159
1170
|
defineAssistFieldAction({/* ... */}),
|
|
1160
1171
|
defineAssistFieldActionGroup({
|
|
@@ -1167,15 +1178,14 @@ useFieldActions: (props) => {
|
|
|
1167
1178
|
}
|
|
1168
1179
|
```
|
|
1169
1180
|
|
|
1170
|
-
#### Only groups in `
|
|
1171
|
-
If `
|
|
1181
|
+
#### Only groups in `useExampleFieldActions`
|
|
1182
|
+
If `useExampleFieldActions` _only_ returns groups, the default wrapper group will be omitted. This allows full control over each group title.
|
|
1172
1183
|
|
|
1173
1184
|
#### `defineFieldActionDivider`
|
|
1174
1185
|
Adds a divider between actions or groups. Takes no arguments:
|
|
1175
1186
|
|
|
1176
1187
|
```ts
|
|
1177
|
-
|
|
1178
|
-
useFieldActions: (props) => {
|
|
1188
|
+
function useExampleFieldActions(props: AssistFieldActionProps) {
|
|
1179
1189
|
return useMemo(() => [
|
|
1180
1190
|
defineAssistFieldAction({/* ... */}),
|
|
1181
1191
|
defineFieldActionDivider(),
|
|
@@ -1198,45 +1208,41 @@ When the user completes the dialog, the user inputted text will be available (or
|
|
|
1198
1208
|
|
|
1199
1209
|
|
|
1200
1210
|
```ts
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
)
|
|
1237
|
-
},
|
|
1238
|
-
},
|
|
1239
|
-
})
|
|
1211
|
+
|
|
1212
|
+
function useExampleFieldActions(props: AssistFieldActionProps) {
|
|
1213
|
+
const getUserInput = useUserInput()
|
|
1214
|
+
|
|
1215
|
+
return useMemo(
|
|
1216
|
+
() => [
|
|
1217
|
+
defineAssistFieldAction({
|
|
1218
|
+
title: 'Do something with user input',
|
|
1219
|
+
onAction: async () => {
|
|
1220
|
+
const inputResult = await getUserInput({
|
|
1221
|
+
title: 'What do you want to do?', // dialog title
|
|
1222
|
+
inputs: [
|
|
1223
|
+
{
|
|
1224
|
+
id: 'topic',
|
|
1225
|
+
title: 'Topic',
|
|
1226
|
+
},
|
|
1227
|
+
{
|
|
1228
|
+
id: 'facts',
|
|
1229
|
+
title: 'Facts',
|
|
1230
|
+
description: 'Provide additional facts that will be used by the action',
|
|
1231
|
+
},
|
|
1232
|
+
],
|
|
1233
|
+
})
|
|
1234
|
+
if (!inputResult) {
|
|
1235
|
+
return // user closed the dialog
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
//use the result from each input
|
|
1239
|
+
//const [{result: topic}, {result: facts}] = inputResult
|
|
1240
|
+
},
|
|
1241
|
+
}),
|
|
1242
|
+
],
|
|
1243
|
+
[getUserInput],
|
|
1244
|
+
)
|
|
1245
|
+
}
|
|
1240
1246
|
```
|
|
1241
1247
|
|
|
1242
1248
|
## Caveats
|
package/dist/index.d.mts
CHANGED
|
@@ -78,7 +78,11 @@ export declare type AssistFieldActionGroup = Omit<
|
|
|
78
78
|
DocumentFieldActionGroup,
|
|
79
79
|
'renderAsButton' | 'expanded' | 'children'
|
|
80
80
|
> & {
|
|
81
|
-
|
|
81
|
+
/**
|
|
82
|
+
* `children` can include undefined entries in the action array. These will be filtered out.
|
|
83
|
+
* If the group has no defined children, the group will also be filtered out.
|
|
84
|
+
*/
|
|
85
|
+
children: (AssistFieldActionNode | undefined)[]
|
|
82
86
|
}
|
|
83
87
|
|
|
84
88
|
export declare type AssistFieldActionItem = Omit<
|
|
@@ -153,6 +157,8 @@ export declare interface AssistFieldActionProps {
|
|
|
153
157
|
* },
|
|
154
158
|
* //...
|
|
155
159
|
* })
|
|
160
|
+
*
|
|
161
|
+
* ```
|
|
156
162
|
*/
|
|
157
163
|
schemaId: string
|
|
158
164
|
/**
|
|
@@ -201,6 +207,15 @@ export declare interface AssistFieldActionProps {
|
|
|
201
207
|
* ```
|
|
202
208
|
*/
|
|
203
209
|
schemaType: SchemaType_2
|
|
210
|
+
/**
|
|
211
|
+
* Schema type of the parent field or array item holding this field.
|
|
212
|
+
*
|
|
213
|
+
* This can be undefined if the action was unable to resolve the parent type is excluded from AI Assist.
|
|
214
|
+
*
|
|
215
|
+
* @see schemaType
|
|
216
|
+
* @see documentSchemaType
|
|
217
|
+
*/
|
|
218
|
+
parentSchemaType?: SchemaType_2
|
|
204
219
|
}
|
|
205
220
|
|
|
206
221
|
export declare interface AssistOptions {
|
|
@@ -223,7 +238,10 @@ declare interface AssistPluginConfig {
|
|
|
223
238
|
assist?: AssistConfig
|
|
224
239
|
fieldActions?: {
|
|
225
240
|
title?: string
|
|
226
|
-
|
|
241
|
+
/**
|
|
242
|
+
* The returned array can include `undefined` entries in the action array. These will be filtered out.
|
|
243
|
+
*/
|
|
244
|
+
useFieldActions?: (props: AssistFieldActionProps) => (AssistFieldActionNode | undefined)[]
|
|
227
245
|
}
|
|
228
246
|
/**
|
|
229
247
|
* @internal
|
|
@@ -525,7 +543,7 @@ declare interface PresetInstruction {
|
|
|
525
543
|
prompt?: PromptTextBlock[]
|
|
526
544
|
title?: string
|
|
527
545
|
/**
|
|
528
|
-
* String key from
|
|
546
|
+
* String key from `@sanity/icons` IconMap
|
|
529
547
|
*/
|
|
530
548
|
icon?: string
|
|
531
549
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -78,7 +78,11 @@ export declare type AssistFieldActionGroup = Omit<
|
|
|
78
78
|
DocumentFieldActionGroup,
|
|
79
79
|
'renderAsButton' | 'expanded' | 'children'
|
|
80
80
|
> & {
|
|
81
|
-
|
|
81
|
+
/**
|
|
82
|
+
* `children` can include undefined entries in the action array. These will be filtered out.
|
|
83
|
+
* If the group has no defined children, the group will also be filtered out.
|
|
84
|
+
*/
|
|
85
|
+
children: (AssistFieldActionNode | undefined)[]
|
|
82
86
|
}
|
|
83
87
|
|
|
84
88
|
export declare type AssistFieldActionItem = Omit<
|
|
@@ -153,6 +157,8 @@ export declare interface AssistFieldActionProps {
|
|
|
153
157
|
* },
|
|
154
158
|
* //...
|
|
155
159
|
* })
|
|
160
|
+
*
|
|
161
|
+
* ```
|
|
156
162
|
*/
|
|
157
163
|
schemaId: string
|
|
158
164
|
/**
|
|
@@ -201,6 +207,15 @@ export declare interface AssistFieldActionProps {
|
|
|
201
207
|
* ```
|
|
202
208
|
*/
|
|
203
209
|
schemaType: SchemaType_2
|
|
210
|
+
/**
|
|
211
|
+
* Schema type of the parent field or array item holding this field.
|
|
212
|
+
*
|
|
213
|
+
* This can be undefined if the action was unable to resolve the parent type is excluded from AI Assist.
|
|
214
|
+
*
|
|
215
|
+
* @see schemaType
|
|
216
|
+
* @see documentSchemaType
|
|
217
|
+
*/
|
|
218
|
+
parentSchemaType?: SchemaType_2
|
|
204
219
|
}
|
|
205
220
|
|
|
206
221
|
export declare interface AssistOptions {
|
|
@@ -223,7 +238,10 @@ declare interface AssistPluginConfig {
|
|
|
223
238
|
assist?: AssistConfig
|
|
224
239
|
fieldActions?: {
|
|
225
240
|
title?: string
|
|
226
|
-
|
|
241
|
+
/**
|
|
242
|
+
* The returned array can include `undefined` entries in the action array. These will be filtered out.
|
|
243
|
+
*/
|
|
244
|
+
useFieldActions?: (props: AssistFieldActionProps) => (AssistFieldActionNode | undefined)[]
|
|
227
245
|
}
|
|
228
246
|
/**
|
|
229
247
|
* @internal
|
|
@@ -525,7 +543,7 @@ declare interface PresetInstruction {
|
|
|
525
543
|
prompt?: PromptTextBlock[]
|
|
526
544
|
title?: string
|
|
527
545
|
/**
|
|
528
|
-
* String key from
|
|
546
|
+
* String key from `@sanity/icons` IconMap
|
|
529
547
|
*/
|
|
530
548
|
icon?: string
|
|
531
549
|
/**
|
package/dist/index.esm.js
CHANGED
|
@@ -211,6 +211,9 @@ function getPathKey(path) {
|
|
|
211
211
|
function getInstructionTitle(instruction2) {
|
|
212
212
|
return instruction2?.title ?? "Untitled";
|
|
213
213
|
}
|
|
214
|
+
function isDefined(t) {
|
|
215
|
+
return t != null;
|
|
216
|
+
}
|
|
214
217
|
function isPortableTextArray(type) {
|
|
215
218
|
return type.of.find((t) => isType(t, "block"));
|
|
216
219
|
}
|
|
@@ -397,6 +400,12 @@ function getTypeIcon(schemaType) {
|
|
|
397
400
|
}
|
|
398
401
|
return isType(schemaType, "slug") ? LinkIcon : isType(schemaType, "image") ? ImageIcon : schemaType.jsonType === "array" && isPortableTextArray(schemaType) ? BlockContentIcon : schemaType.jsonType === "array" ? OlistIcon : schemaType.jsonType === "object" ? BlockquoteIcon : schemaType.jsonType === "string" ? StringIcon : DocumentIcon;
|
|
399
402
|
}
|
|
403
|
+
function asFieldRefsByTypePath(fieldRefs) {
|
|
404
|
+
return fieldRefs.reduce(
|
|
405
|
+
(acc, ref) => ({ ...acc, [ref.key]: ref }),
|
|
406
|
+
{}
|
|
407
|
+
);
|
|
408
|
+
}
|
|
400
409
|
function getFieldRefsWithDocument(schemaType) {
|
|
401
410
|
const fields = getFieldRefs(schemaType);
|
|
402
411
|
return [
|
|
@@ -1026,7 +1035,7 @@ function useAssistDocumentContextValue(documentId, documentType) {
|
|
|
1026
1035
|
} = useDocumentPane(), { draft, published, version } = editState || {}, assistableDocumentId = selectedReleaseId ? getVersionId(documentId, selectedReleaseId) : documentSchemaType.liveEdit ? documentId : getDraftId(documentId), documentIsNew = selectedReleaseId ? !version?._id : !draft?._id && !published?._id, documentIsAssistable = selectedReleaseId ? !!version : isDocAssistable(documentSchemaType, published, draft), { params } = useAiPaneRouter(), selectedPath = params[fieldPathParam], assistDocument = useStudioAssistDocument({
|
|
1027
1036
|
documentId: assistableDocumentId,
|
|
1028
1037
|
schemaType: documentSchemaType
|
|
1029
|
-
}), { syntheticTasks, addSyntheticTask, removeSyntheticTask } = useSyntheticTasks(assistableDocumentId);
|
|
1038
|
+
}), { syntheticTasks, addSyntheticTask, removeSyntheticTask } = useSyntheticTasks(assistableDocumentId), fieldRefs = getFieldRefs(documentSchemaType), fieldRefsByTypePath = asFieldRefsByTypePath(fieldRefs);
|
|
1030
1039
|
return useMemo(() => {
|
|
1031
1040
|
const base = {
|
|
1032
1041
|
assistableDocumentId,
|
|
@@ -1040,7 +1049,9 @@ function useAssistDocumentContextValue(documentId, documentType) {
|
|
|
1040
1049
|
selectedPath,
|
|
1041
1050
|
syntheticTasks,
|
|
1042
1051
|
addSyntheticTask,
|
|
1043
|
-
removeSyntheticTask
|
|
1052
|
+
removeSyntheticTask,
|
|
1053
|
+
fieldRefs,
|
|
1054
|
+
fieldRefsByTypePath
|
|
1044
1055
|
};
|
|
1045
1056
|
return assistDocument ? {
|
|
1046
1057
|
...base,
|
|
@@ -2870,12 +2881,12 @@ function useCustomFieldActions(props) {
|
|
|
2870
2881
|
path: props.path
|
|
2871
2882
|
});
|
|
2872
2883
|
return useMemo(() => {
|
|
2873
|
-
const title = fieldActions?.title, customActions = configActions?.map((node) => createSafeNode({
|
|
2884
|
+
const title = fieldActions?.title, customActions = configActions?.filter(isDefined).map((node) => createSafeNode({
|
|
2874
2885
|
node,
|
|
2875
2886
|
pushToast,
|
|
2876
2887
|
addSyntheticTask,
|
|
2877
2888
|
removeSyntheticTask
|
|
2878
|
-
})), onlyGroups = customActions?.length && customActions?.every((node) => node.type === "group");
|
|
2889
|
+
})).filter(isDefined), onlyGroups = customActions?.length && customActions?.every((node) => node.type === "group");
|
|
2879
2890
|
return (customActions?.length ? onlyGroups ? customActions : [
|
|
2880
2891
|
{
|
|
2881
2892
|
type: "group",
|
|
@@ -2892,12 +2903,13 @@ function createSafeNode(args) {
|
|
|
2892
2903
|
case "action":
|
|
2893
2904
|
return createSafeAction({ ...args, action: node });
|
|
2894
2905
|
case "group":
|
|
2895
|
-
|
|
2906
|
+
const children = node.children?.filter(isDefined).map((child) => createSafeNode({ ...args, node: child })).filter(isDefined);
|
|
2907
|
+
return children?.length ? {
|
|
2896
2908
|
...node,
|
|
2897
2909
|
renderAsButton: !1,
|
|
2898
2910
|
expanded: !0,
|
|
2899
|
-
children
|
|
2900
|
-
};
|
|
2911
|
+
children
|
|
2912
|
+
} : void 0;
|
|
2901
2913
|
case "divider":
|
|
2902
2914
|
default:
|
|
2903
2915
|
return node;
|
|
@@ -2955,7 +2967,8 @@ const assistFieldActions = {
|
|
|
2955
2967
|
documentOnChange,
|
|
2956
2968
|
documentSchemaType,
|
|
2957
2969
|
selectedPath,
|
|
2958
|
-
assistableDocumentId
|
|
2970
|
+
assistableDocumentId,
|
|
2971
|
+
fieldRefsByTypePath
|
|
2959
2972
|
} = useAssistDocumentContext(), { value: docValue, formState } = useDocumentPane(), docValueRef = useRef(docValue), formStateRef = useRef(formState);
|
|
2960
2973
|
formStateRef.current = formState;
|
|
2961
2974
|
const currentUser = useCurrentUser(), isHidden = !assistDocument, pathKey = usePathKey(props.path), typePath = useTypePath(docValue, pathKey), assistDocumentId2 = assistDocument?._id, { requestRunInstruction } = useRequestRunInstruction({
|
|
@@ -3043,14 +3056,22 @@ const assistFieldActions = {
|
|
|
3043
3056
|
path
|
|
3044
3057
|
};
|
|
3045
3058
|
}
|
|
3046
|
-
), []),
|
|
3059
|
+
), []), parentSchemaType = useMemo(() => {
|
|
3060
|
+
if (props.path.length) {
|
|
3061
|
+
if (props.path.length === 1)
|
|
3062
|
+
return documentSchemaType;
|
|
3063
|
+
} else return;
|
|
3064
|
+
const parentPath = props.path.slice(0, -1), typePath2 = getTypePath(docValueRef.current, pathToString(parentPath));
|
|
3065
|
+
return typePath2 ? fieldRefsByTypePath[typePath2]?.schemaType : void 0;
|
|
3066
|
+
}, [fieldRefsByTypePath, props.path, documentSchemaType]), customActions = useCustomFieldActions({
|
|
3047
3067
|
actionType: props.path.length ? "field" : "document",
|
|
3048
3068
|
documentIdForAction: assistableDocumentId,
|
|
3049
3069
|
schemaType,
|
|
3050
3070
|
documentSchemaType,
|
|
3051
3071
|
path: props.path,
|
|
3052
3072
|
getDocumentValue,
|
|
3053
|
-
getConditionalPaths
|
|
3073
|
+
getConditionalPaths,
|
|
3074
|
+
parentSchemaType
|
|
3054
3075
|
}), manageInstructionsItem = useMemo(
|
|
3055
3076
|
() => ({
|
|
3056
3077
|
type: "action",
|