@sanity/assist 5.0.3 → 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 +3182 -2673
- package/dist/index.js.map +1 -1
- package/package.json +41 -77
- package/dist/index.cjs +0 -4264
- 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 -286
- 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 -129
- 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 -423
- 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,54 +0,0 @@
|
|
|
1
|
-
import {Box} from '@sanity/ui'
|
|
2
|
-
import {useCallback, useContext, useEffect, useId, useRef} from 'react'
|
|
3
|
-
import {set, StringInputProps} from 'sanity'
|
|
4
|
-
|
|
5
|
-
import {FieldAutocomplete} from '../../../assistInspector/FieldAutocomplete'
|
|
6
|
-
import {FieldRef} from '../../../assistInspector/helpers'
|
|
7
|
-
import {AssistTypeContext} from '../AssistTypeContext'
|
|
8
|
-
import {SelectedFieldContext} from '../SelectedFieldContext'
|
|
9
|
-
|
|
10
|
-
export function FieldRefPathInput(props: StringInputProps) {
|
|
11
|
-
const documentSchema = useContext(SelectedFieldContext)?.documentSchema
|
|
12
|
-
const {typePath} = useContext(AssistTypeContext)
|
|
13
|
-
const ref = useRef<HTMLDivElement>(null)
|
|
14
|
-
const id = useId()
|
|
15
|
-
const {onChange} = props
|
|
16
|
-
|
|
17
|
-
useEffect(() => {
|
|
18
|
-
ref.current?.querySelector('input')?.focus()
|
|
19
|
-
}, [])
|
|
20
|
-
|
|
21
|
-
const onSelect = useCallback((path: string) => onChange(set(path)), [onChange])
|
|
22
|
-
|
|
23
|
-
const filter = useCallback(
|
|
24
|
-
(field: FieldRef) => {
|
|
25
|
-
if (!field.key.includes('|') || !typePath) {
|
|
26
|
-
return true
|
|
27
|
-
}
|
|
28
|
-
if (field.key.includes('|') && !typePath.includes('|')) {
|
|
29
|
-
return false
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const fieldSegments = field.key.split('.')
|
|
33
|
-
const lastArrayItemIndex = fieldSegments.findLastIndex((s) => s.includes('|'))
|
|
34
|
-
const mustStartWith = fieldSegments.slice(0, lastArrayItemIndex + 1).join('.')
|
|
35
|
-
return typePath.startsWith(mustStartWith)
|
|
36
|
-
},
|
|
37
|
-
[typePath],
|
|
38
|
-
)
|
|
39
|
-
if (!documentSchema) {
|
|
40
|
-
return props.renderDefault(props)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return (
|
|
44
|
-
<Box flex={1} style={{minWidth: 300}} ref={ref}>
|
|
45
|
-
<FieldAutocomplete
|
|
46
|
-
id={id}
|
|
47
|
-
schemaType={documentSchema}
|
|
48
|
-
onSelect={onSelect}
|
|
49
|
-
fieldPath={props.value}
|
|
50
|
-
filter={filter}
|
|
51
|
-
/>
|
|
52
|
-
</Box>
|
|
53
|
-
)
|
|
54
|
-
}
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import {Box, Flex, Stack, Text} from '@sanity/ui'
|
|
2
|
-
import {useId, useMemo} from 'react'
|
|
3
|
-
import {FieldError, FieldMember, ObjectInputMember, ObjectInputProps} from 'sanity'
|
|
4
|
-
|
|
5
|
-
import {findFieldMember, findFieldsetMember} from '../helpers'
|
|
6
|
-
|
|
7
|
-
export function InstructionInput(props: ObjectInputProps) {
|
|
8
|
-
return (
|
|
9
|
-
<Stack space={[4, 4, 4, 5]}>
|
|
10
|
-
<NameField {...props} />
|
|
11
|
-
<ShareField {...props} />
|
|
12
|
-
<ObjectMember fieldName={'prompt'} {...props} />
|
|
13
|
-
<ObjectMember fieldName={'output'} {...props} />
|
|
14
|
-
</Stack>
|
|
15
|
-
)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function ObjectMember({fieldName, ...props}: ObjectInputProps & {fieldName: string}) {
|
|
19
|
-
const member = findFieldMember(props.members, fieldName)
|
|
20
|
-
return member ? <ObjectInputMember {...props} member={member} /> : null
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const NONE: (FieldMember | FieldError)[] = []
|
|
24
|
-
|
|
25
|
-
function NameField(props: ObjectInputProps) {
|
|
26
|
-
const fieldsetMember = findFieldsetMember(props.members, 'appearance')
|
|
27
|
-
const titleId = useId()
|
|
28
|
-
|
|
29
|
-
const members = fieldsetMember?.fieldSet.members ?? NONE
|
|
30
|
-
const iconMember = findFieldMember(members, 'icon')
|
|
31
|
-
const titleMember = findFieldMember(members, 'title')
|
|
32
|
-
|
|
33
|
-
const titlePlaceholder = 'Untitled'
|
|
34
|
-
const moddedTitleMember = useMemo(() => {
|
|
35
|
-
if (!titleMember) {
|
|
36
|
-
return undefined
|
|
37
|
-
}
|
|
38
|
-
if (titleMember.kind === 'error') {
|
|
39
|
-
return titleMember
|
|
40
|
-
}
|
|
41
|
-
return {
|
|
42
|
-
...titleMember,
|
|
43
|
-
field: {
|
|
44
|
-
...titleMember?.field,
|
|
45
|
-
schemaType: {
|
|
46
|
-
...titleMember?.field.schemaType,
|
|
47
|
-
placeholder: titlePlaceholder,
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
}
|
|
51
|
-
}, [titleMember, titlePlaceholder])
|
|
52
|
-
|
|
53
|
-
return (
|
|
54
|
-
<Stack space={5}>
|
|
55
|
-
<Stack space={2}>
|
|
56
|
-
<Flex gap={1}>
|
|
57
|
-
<Text as="label" weight="semibold" size={1} htmlFor={titleId}>
|
|
58
|
-
Name
|
|
59
|
-
</Text>
|
|
60
|
-
</Flex>
|
|
61
|
-
|
|
62
|
-
<Text muted size={1}>
|
|
63
|
-
How this instruction appears in menus
|
|
64
|
-
</Text>
|
|
65
|
-
|
|
66
|
-
<Flex align="center">
|
|
67
|
-
{iconMember && (
|
|
68
|
-
<Box flex="none">
|
|
69
|
-
<ObjectInputMember {...props} member={iconMember} />
|
|
70
|
-
</Box>
|
|
71
|
-
)}
|
|
72
|
-
{moddedTitleMember && (
|
|
73
|
-
<Box flex={1} style={{marginLeft: -1}}>
|
|
74
|
-
<ObjectInputMember {...props} member={moddedTitleMember} />
|
|
75
|
-
</Box>
|
|
76
|
-
)}
|
|
77
|
-
</Flex>
|
|
78
|
-
</Stack>
|
|
79
|
-
</Stack>
|
|
80
|
-
)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function ShareField(props: ObjectInputProps) {
|
|
84
|
-
const fieldsetMember = findFieldsetMember(props.members, 'appearance')
|
|
85
|
-
const members = fieldsetMember?.fieldSet.members ?? NONE
|
|
86
|
-
const visibilityMember = findFieldMember(members, 'userId')
|
|
87
|
-
|
|
88
|
-
return <>{visibilityMember && <ObjectInputMember {...props} member={visibilityMember} />}</>
|
|
89
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import {useCallback, useContext, useState} from 'react'
|
|
2
|
-
import {
|
|
3
|
-
ArrayFieldProps,
|
|
4
|
-
ArraySchemaType,
|
|
5
|
-
isArrayOfObjectsSchemaType,
|
|
6
|
-
isObjectSchemaType,
|
|
7
|
-
ObjectSchemaType,
|
|
8
|
-
} from 'sanity'
|
|
9
|
-
|
|
10
|
-
import {SelectedFieldContext} from '../SelectedFieldContext'
|
|
11
|
-
|
|
12
|
-
export function InstructionOutputField(props: ArrayFieldProps) {
|
|
13
|
-
const {fieldSchema} = useContext(SelectedFieldContext) ?? {}
|
|
14
|
-
|
|
15
|
-
if (
|
|
16
|
-
!fieldSchema ||
|
|
17
|
-
!(isObjectSchemaType(fieldSchema) || isArrayOfObjectsSchemaType(fieldSchema))
|
|
18
|
-
) {
|
|
19
|
-
return null
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return (
|
|
23
|
-
<EnabledOutputField {...props} fieldSchema={fieldSchema}>
|
|
24
|
-
{props.children}
|
|
25
|
-
</EnabledOutputField>
|
|
26
|
-
)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function EnabledOutputField({
|
|
30
|
-
fieldSchema,
|
|
31
|
-
...props
|
|
32
|
-
}: ArrayFieldProps & {fieldSchema: ObjectSchemaType | ArraySchemaType<ObjectSchemaType>}) {
|
|
33
|
-
const [open, setOpen] = useState(!!props.value?.length)
|
|
34
|
-
const onExpand = useCallback(() => setOpen(true), [])
|
|
35
|
-
const onCollapse = useCallback(() => setOpen(false), [])
|
|
36
|
-
|
|
37
|
-
return props.renderDefault({
|
|
38
|
-
...props,
|
|
39
|
-
collapsible: true,
|
|
40
|
-
onExpand,
|
|
41
|
-
onCollapse,
|
|
42
|
-
collapsed: !open,
|
|
43
|
-
level: 1,
|
|
44
|
-
title: isObjectSchemaType(fieldSchema) ? 'Allowed fields' : 'Allowed types',
|
|
45
|
-
})
|
|
46
|
-
}
|
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
import {Card, Checkbox, Flex, Stack, Text} from '@sanity/ui'
|
|
2
|
-
import {useCallback, useContext, useEffect, useMemo} from 'react'
|
|
3
|
-
import {
|
|
4
|
-
ArrayOfObjectsInputProps,
|
|
5
|
-
ArraySchemaType,
|
|
6
|
-
FormPatch,
|
|
7
|
-
insert,
|
|
8
|
-
isArrayOfObjectsSchemaType,
|
|
9
|
-
isObjectSchemaType,
|
|
10
|
-
ObjectSchemaType,
|
|
11
|
-
PatchEvent,
|
|
12
|
-
setIfMissing,
|
|
13
|
-
typed,
|
|
14
|
-
unset,
|
|
15
|
-
} from 'sanity'
|
|
16
|
-
|
|
17
|
-
import {isAssistSupported} from '../../../helpers/assistSupported'
|
|
18
|
-
import {isType} from '../../../helpers/typeUtils'
|
|
19
|
-
import {OutputFieldItem, outputFieldTypeName, OutputTypeItem} from '../../../types'
|
|
20
|
-
import {SelectedFieldContext} from '../SelectedFieldContext'
|
|
21
|
-
|
|
22
|
-
export function InstructionOutputInput(props: ArrayOfObjectsInputProps) {
|
|
23
|
-
const {fieldSchema} = useContext(SelectedFieldContext) ?? {}
|
|
24
|
-
|
|
25
|
-
if (!fieldSchema) {
|
|
26
|
-
return null
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (isObjectSchemaType(fieldSchema)) {
|
|
30
|
-
return <ObjectOutputInput {...props} fieldSchema={fieldSchema} />
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (isArrayOfObjectsSchemaType(fieldSchema)) {
|
|
34
|
-
return <ArrayOutputInput {...props} fieldSchema={fieldSchema} />
|
|
35
|
-
}
|
|
36
|
-
return null
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function useEmptySelectAllValue(
|
|
40
|
-
value: (OutputTypeItem | OutputFieldItem)[],
|
|
41
|
-
allowedValues: {name: string}[],
|
|
42
|
-
onChange: (patch: FormPatch | FormPatch[] | PatchEvent) => void,
|
|
43
|
-
) {
|
|
44
|
-
useEffect(() => {
|
|
45
|
-
const validValues = value?.filter((v) =>
|
|
46
|
-
allowedValues.find(
|
|
47
|
-
(f) => f.name === (v._type === outputFieldTypeName ? v.relativePath : v.type),
|
|
48
|
-
),
|
|
49
|
-
)
|
|
50
|
-
const valueLength = value?.length ?? 0
|
|
51
|
-
const validLength = validValues?.length ?? 0
|
|
52
|
-
if ((!validLength && valueLength) || validLength >= allowedValues.length) {
|
|
53
|
-
// if we end up here, we consider this a "no selected fields/types" selections. This should render and behave as all values selected.
|
|
54
|
-
// we need this behaviour to accommodate new fields/types being added to the model, so they get visited by instructions without having to update the filter
|
|
55
|
-
// when things have been explicitly selected, we let the selection remain as is
|
|
56
|
-
onChange(PatchEvent.from([unset()]))
|
|
57
|
-
}
|
|
58
|
-
}, [allowedValues, value, onChange])
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function ObjectOutputInput({
|
|
62
|
-
fieldSchema,
|
|
63
|
-
...props
|
|
64
|
-
}: ArrayOfObjectsInputProps & {fieldSchema: ObjectSchemaType}) {
|
|
65
|
-
const {value, onChange} = props
|
|
66
|
-
|
|
67
|
-
const fields = useMemo(
|
|
68
|
-
() => fieldSchema.fields.filter((field) => isAssistSupported(field.type)),
|
|
69
|
-
[fieldSchema.fields],
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
useEmptySelectAllValue(value as OutputTypeItem[], fields, onChange)
|
|
73
|
-
|
|
74
|
-
const onSelectChange = useCallback(
|
|
75
|
-
(checked: boolean, selectedValue: string) => {
|
|
76
|
-
if (checked) {
|
|
77
|
-
if (value?.length) {
|
|
78
|
-
onChange(PatchEvent.from(unset([{_key: selectedValue}])))
|
|
79
|
-
} else {
|
|
80
|
-
// we went from empty array to everything selected but one
|
|
81
|
-
const items = fields
|
|
82
|
-
.filter((f) => f.name !== selectedValue)
|
|
83
|
-
.map((field) =>
|
|
84
|
-
typed<OutputFieldItem>({
|
|
85
|
-
_key: field.name,
|
|
86
|
-
_type: 'sanity.assist.output.field',
|
|
87
|
-
relativePath: field.name,
|
|
88
|
-
}),
|
|
89
|
-
)
|
|
90
|
-
onChange(PatchEvent.from([setIfMissing([]), insert(items, 'after', [-1])]))
|
|
91
|
-
}
|
|
92
|
-
} else {
|
|
93
|
-
const patchValue: OutputFieldItem = {
|
|
94
|
-
_key: selectedValue,
|
|
95
|
-
_type: 'sanity.assist.output.field',
|
|
96
|
-
relativePath: selectedValue,
|
|
97
|
-
}
|
|
98
|
-
onChange(PatchEvent.from([setIfMissing([]), insert([patchValue], 'after', [-1])]))
|
|
99
|
-
}
|
|
100
|
-
},
|
|
101
|
-
[onChange, value, fields],
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
return (
|
|
105
|
-
<Stack space={2}>
|
|
106
|
-
{fields.map((field) => {
|
|
107
|
-
return (
|
|
108
|
-
<Flex key={field.name} align="center" gap={2}>
|
|
109
|
-
<Selectable
|
|
110
|
-
value={field.name}
|
|
111
|
-
title={field.type.title ?? field.name}
|
|
112
|
-
arrayValue={value as OutputFieldItem[]}
|
|
113
|
-
onChange={onSelectChange}
|
|
114
|
-
/>
|
|
115
|
-
</Flex>
|
|
116
|
-
)
|
|
117
|
-
})}
|
|
118
|
-
</Stack>
|
|
119
|
-
)
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
function ArrayOutputInput({
|
|
123
|
-
fieldSchema,
|
|
124
|
-
...props
|
|
125
|
-
}: ArrayOfObjectsInputProps & {fieldSchema: ArraySchemaType}) {
|
|
126
|
-
const {value, onChange} = props
|
|
127
|
-
|
|
128
|
-
const ofItems = useMemo(
|
|
129
|
-
() => fieldSchema.of.filter((itemType) => isAssistSupported(itemType)),
|
|
130
|
-
[fieldSchema.of],
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
useEmptySelectAllValue(value as OutputTypeItem[], ofItems, onChange)
|
|
134
|
-
|
|
135
|
-
const onSelectChange = useCallback(
|
|
136
|
-
(checked: boolean, selectedValue: string) => {
|
|
137
|
-
if (checked) {
|
|
138
|
-
if (value?.length) {
|
|
139
|
-
onChange(PatchEvent.from(unset([{_key: selectedValue}])))
|
|
140
|
-
} else {
|
|
141
|
-
// we went from empty array to everything selected but one
|
|
142
|
-
const items = ofItems
|
|
143
|
-
.filter((f) => f.name !== selectedValue)
|
|
144
|
-
.map((field) =>
|
|
145
|
-
typed<OutputTypeItem>({
|
|
146
|
-
_key: field.name,
|
|
147
|
-
_type: 'sanity.assist.output.type',
|
|
148
|
-
type: field.name,
|
|
149
|
-
}),
|
|
150
|
-
)
|
|
151
|
-
onChange(PatchEvent.from([setIfMissing([]), insert(items, 'after', [-1])]))
|
|
152
|
-
}
|
|
153
|
-
} else {
|
|
154
|
-
const patchValue: OutputTypeItem = {
|
|
155
|
-
_key: selectedValue,
|
|
156
|
-
_type: 'sanity.assist.output.type',
|
|
157
|
-
type: selectedValue,
|
|
158
|
-
}
|
|
159
|
-
onChange(PatchEvent.from([setIfMissing([]), insert([patchValue], 'after', [-1])]))
|
|
160
|
-
}
|
|
161
|
-
},
|
|
162
|
-
[onChange, value, ofItems],
|
|
163
|
-
)
|
|
164
|
-
return (
|
|
165
|
-
<Stack space={2}>
|
|
166
|
-
{ofItems.map((itemType) => {
|
|
167
|
-
return (
|
|
168
|
-
<Flex key={itemType.name}>
|
|
169
|
-
<Selectable
|
|
170
|
-
value={itemType.name}
|
|
171
|
-
title={isType(itemType, 'block') ? 'Text' : (itemType.title ?? itemType.name)}
|
|
172
|
-
arrayValue={value as OutputTypeItem[] | undefined}
|
|
173
|
-
onChange={onSelectChange}
|
|
174
|
-
/>
|
|
175
|
-
</Flex>
|
|
176
|
-
)
|
|
177
|
-
})}
|
|
178
|
-
</Stack>
|
|
179
|
-
)
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
function Selectable({
|
|
183
|
-
title,
|
|
184
|
-
arrayValue,
|
|
185
|
-
value,
|
|
186
|
-
onChange,
|
|
187
|
-
}: {
|
|
188
|
-
title: string
|
|
189
|
-
value: string
|
|
190
|
-
arrayValue?: {_key: string}[]
|
|
191
|
-
onChange: (checked: boolean, value: string) => void
|
|
192
|
-
}) {
|
|
193
|
-
const checked = !arrayValue?.length || !!arrayValue?.find((v) => v._key === value)
|
|
194
|
-
const handleChange = useCallback(() => onChange(checked, value), [onChange, checked, value])
|
|
195
|
-
|
|
196
|
-
return (
|
|
197
|
-
<Flex gap={2} align="flex-start">
|
|
198
|
-
<Checkbox checked={checked} onChange={handleChange} />
|
|
199
|
-
<Card marginTop={1} onClick={handleChange}>
|
|
200
|
-
<Text style={{cursor: 'default'}} size={1}>
|
|
201
|
-
{title}
|
|
202
|
-
</Text>
|
|
203
|
-
</Card>
|
|
204
|
-
</Flex>
|
|
205
|
-
)
|
|
206
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import {Box} from '@sanity/ui'
|
|
2
|
-
import {useEffect} from 'react'
|
|
3
|
-
import {type ArrayOfObjectsInputProps, set, typed} from 'sanity'
|
|
4
|
-
import {styled} from 'styled-components'
|
|
5
|
-
|
|
6
|
-
import {randomKey} from '../../../_lib/randomKey'
|
|
7
|
-
import type {
|
|
8
|
-
ContextBlock,
|
|
9
|
-
FieldRef,
|
|
10
|
-
PromptBlock,
|
|
11
|
-
PromptTextBlock,
|
|
12
|
-
UserInputBlock,
|
|
13
|
-
} from '../../../types'
|
|
14
|
-
|
|
15
|
-
const PteMods = styled(Box)`
|
|
16
|
-
& [data-testid='pt-editor__toolbar-card'] > div > div:last-child {
|
|
17
|
-
display: none;
|
|
18
|
-
}
|
|
19
|
-
& [data-testid='pt-editor'] {
|
|
20
|
-
min-height: 300px;
|
|
21
|
-
}
|
|
22
|
-
& [data-testid='pt-editor'] .pt-inline-object * {
|
|
23
|
-
max-width: 400px;
|
|
24
|
-
}
|
|
25
|
-
`
|
|
26
|
-
|
|
27
|
-
export function PromptInput(props: ArrayOfObjectsInputProps) {
|
|
28
|
-
// quickfixes the model (converts blocks to inline blocks for alpha customers)
|
|
29
|
-
// backend supports both types, but this prevents "missing block" schema errors
|
|
30
|
-
useOnlyInlineBlocks(props)
|
|
31
|
-
return <PteMods>{props.renderDefault(props)}</PteMods>
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function useOnlyInlineBlocks(props: ArrayOfObjectsInputProps) {
|
|
35
|
-
useEffect(() => {
|
|
36
|
-
let needsFix = false
|
|
37
|
-
const val = ((props.value as PromptBlock[]) ?? []).map((block) => {
|
|
38
|
-
if (block._type === 'block') {
|
|
39
|
-
return block
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
needsFix = true
|
|
43
|
-
return typed<PromptTextBlock>({
|
|
44
|
-
_key: randomKey(12),
|
|
45
|
-
_type: 'block',
|
|
46
|
-
level: 0,
|
|
47
|
-
markDefs: [],
|
|
48
|
-
style: 'normal',
|
|
49
|
-
children: [block as FieldRef | ContextBlock | UserInputBlock],
|
|
50
|
-
})
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
if (needsFix) {
|
|
54
|
-
props.onChange(set(val))
|
|
55
|
-
}
|
|
56
|
-
// only run this once when loading the field
|
|
57
|
-
// eslint-disable-next-line
|
|
58
|
-
}, [])
|
|
59
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import {icons} from '@sanity/icons'
|
|
2
|
-
import {Button, Menu, MenuButton, MenuItem} from '@sanity/ui'
|
|
3
|
-
import {ElementType, ReactNode, useCallback, useId, useMemo} from 'react'
|
|
4
|
-
import {set, StringInputProps} from 'sanity'
|
|
5
|
-
|
|
6
|
-
export function IconInput(props: StringInputProps) {
|
|
7
|
-
const {value, onChange} = props
|
|
8
|
-
const id = useId()
|
|
9
|
-
const items = useMemo(
|
|
10
|
-
() =>
|
|
11
|
-
Object.entries(icons).map(([key, icon]) => (
|
|
12
|
-
<IconItem key={key} iconKey={key} icon={icon} onChange={onChange} />
|
|
13
|
-
)),
|
|
14
|
-
[onChange],
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
const selectedIcon = useMemo(() => getIcon(value), [value])
|
|
18
|
-
|
|
19
|
-
return (
|
|
20
|
-
<MenuButton
|
|
21
|
-
button={
|
|
22
|
-
<Button icon={selectedIcon} title="Select icon" padding={3} mode="ghost" radius={1} />
|
|
23
|
-
}
|
|
24
|
-
id={id}
|
|
25
|
-
menu={<Menu style={{maxHeight: 300}}>{items}</Menu>}
|
|
26
|
-
popover={{portal: true}}
|
|
27
|
-
/>
|
|
28
|
-
)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function IconItem({
|
|
32
|
-
icon,
|
|
33
|
-
iconKey: key,
|
|
34
|
-
onChange,
|
|
35
|
-
}: {
|
|
36
|
-
iconKey: string
|
|
37
|
-
icon: ElementType | ReactNode
|
|
38
|
-
onChange: StringInputProps['onChange']
|
|
39
|
-
}) {
|
|
40
|
-
const onClick = useCallback(() => onChange(set(key)), [onChange, key])
|
|
41
|
-
return <MenuItem icon={icon} title={key} text={key} onClick={onClick} />
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export function getIcon(iconName?: string) {
|
|
45
|
-
return Object.entries(icons).find(([key]) => key === iconName)?.[1] ?? icons.sparkles
|
|
46
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import {Card, Flex, Switch, Text} from '@sanity/ui'
|
|
2
|
-
import {useCallback, useId} from 'react'
|
|
3
|
-
import {set, StringInputProps, unset, useCurrentUser} from 'sanity'
|
|
4
|
-
|
|
5
|
-
export function InstructionVisibility(props: StringInputProps) {
|
|
6
|
-
const {value, onChange} = props
|
|
7
|
-
|
|
8
|
-
const user = useCurrentUser()
|
|
9
|
-
|
|
10
|
-
const handleChange = useCallback(() => {
|
|
11
|
-
const newValue = value ? '' : (user?.id ?? '')
|
|
12
|
-
onChange(newValue ? set(newValue) : unset())
|
|
13
|
-
}, [onChange, user, value])
|
|
14
|
-
|
|
15
|
-
const id = useId()
|
|
16
|
-
|
|
17
|
-
return (
|
|
18
|
-
<Card>
|
|
19
|
-
<Flex gap={2} align="flex-start">
|
|
20
|
-
<div style={{margin: '-3px 0'}}>
|
|
21
|
-
<Switch
|
|
22
|
-
{...props.elementProps}
|
|
23
|
-
id={id}
|
|
24
|
-
value={`${!value}`}
|
|
25
|
-
checked={!value}
|
|
26
|
-
onChange={handleChange}
|
|
27
|
-
disabled={props.elementProps.readOnly}
|
|
28
|
-
/>
|
|
29
|
-
</div>
|
|
30
|
-
|
|
31
|
-
<Text muted size={1} weight="medium">
|
|
32
|
-
<label htmlFor={id}>Make visible to all Studio members</label>
|
|
33
|
-
</Text>
|
|
34
|
-
</Flex>
|
|
35
|
-
</Card>
|
|
36
|
-
)
|
|
37
|
-
}
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import {useCallback, useEffect, useMemo, useState} from 'react'
|
|
2
|
-
import {getDraftId, getVersionId, type ObjectSchemaType, useSchema} from 'sanity'
|
|
3
|
-
import {useDocumentPane} from 'sanity/structure'
|
|
4
|
-
import {fieldPathParam, InstructionTask} from '../../types'
|
|
5
|
-
import {AssistDocumentContextValue} from '../AssistDocumentContext'
|
|
6
|
-
import {isDocAssistable} from '../RequestRunInstructionProvider'
|
|
7
|
-
import {useStudioAssistDocument} from './useStudioAssistDocument'
|
|
8
|
-
import {useAiAssistanceConfig} from '../../assistLayout/AiAssistanceConfigContext'
|
|
9
|
-
import {useAiPaneRouter} from '../../assistInspector/helpers'
|
|
10
|
-
|
|
11
|
-
export function useAssistDocumentContextValue(documentId: string, documentType: string) {
|
|
12
|
-
const schema = useSchema()
|
|
13
|
-
|
|
14
|
-
const {getFieldRefs, getFieldRefsByTypePath} = useAiAssistanceConfig()
|
|
15
|
-
const documentSchemaType = useMemo(() => {
|
|
16
|
-
const schemaType = schema.get(documentType) as ObjectSchemaType | undefined
|
|
17
|
-
if (!schemaType) {
|
|
18
|
-
throw new Error(`Schema type "${documentType}" not found`)
|
|
19
|
-
}
|
|
20
|
-
return schemaType
|
|
21
|
-
}, [documentType, schema])
|
|
22
|
-
|
|
23
|
-
const {fieldRefs, fieldRefsByTypePath} = useMemo(() => {
|
|
24
|
-
return {
|
|
25
|
-
fieldRefs: getFieldRefs(documentType),
|
|
26
|
-
fieldRefsByTypePath: getFieldRefsByTypePath(documentType),
|
|
27
|
-
}
|
|
28
|
-
}, [getFieldRefs, getFieldRefsByTypePath, documentType])
|
|
29
|
-
|
|
30
|
-
const {
|
|
31
|
-
openInspector,
|
|
32
|
-
closeInspector,
|
|
33
|
-
inspector,
|
|
34
|
-
onChange: documentOnChange,
|
|
35
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
36
|
-
// @ts-ignore this is a valid option available in `corel` - Remove after corel is merged to next
|
|
37
|
-
selectedReleaseId,
|
|
38
|
-
editState,
|
|
39
|
-
} = useDocumentPane()
|
|
40
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
41
|
-
// @ts-ignore this is a valid option available in `corel` - Remove after corel is merged to next
|
|
42
|
-
const {draft, published, version} = editState || {}
|
|
43
|
-
|
|
44
|
-
const assistableDocumentId = selectedReleaseId
|
|
45
|
-
? getVersionId(documentId, selectedReleaseId)
|
|
46
|
-
: documentSchemaType.liveEdit
|
|
47
|
-
? documentId
|
|
48
|
-
: getDraftId(documentId)
|
|
49
|
-
|
|
50
|
-
const documentIsNew = selectedReleaseId ? !version?._id : !draft?._id && !published?._id
|
|
51
|
-
const documentIsAssistable = selectedReleaseId
|
|
52
|
-
? !!version
|
|
53
|
-
: isDocAssistable(documentSchemaType, published, draft)
|
|
54
|
-
|
|
55
|
-
const {params} = useAiPaneRouter()
|
|
56
|
-
const selectedPath = params[fieldPathParam]
|
|
57
|
-
|
|
58
|
-
const assistDocument = useStudioAssistDocument({
|
|
59
|
-
documentId: assistableDocumentId,
|
|
60
|
-
schemaType: documentSchemaType,
|
|
61
|
-
})
|
|
62
|
-
const {syntheticTasks, addSyntheticTask, removeSyntheticTask} =
|
|
63
|
-
useSyntheticTasks(assistableDocumentId)
|
|
64
|
-
|
|
65
|
-
const value: AssistDocumentContextValue = useMemo(() => {
|
|
66
|
-
const base = {
|
|
67
|
-
assistableDocumentId,
|
|
68
|
-
documentSchemaType,
|
|
69
|
-
documentIsNew,
|
|
70
|
-
documentIsAssistable,
|
|
71
|
-
openInspector,
|
|
72
|
-
closeInspector,
|
|
73
|
-
inspector,
|
|
74
|
-
documentOnChange,
|
|
75
|
-
selectedPath,
|
|
76
|
-
syntheticTasks,
|
|
77
|
-
addSyntheticTask,
|
|
78
|
-
removeSyntheticTask,
|
|
79
|
-
fieldRefs,
|
|
80
|
-
fieldRefsByTypePath,
|
|
81
|
-
}
|
|
82
|
-
if (!assistDocument) {
|
|
83
|
-
return {...base, loading: true, assistDocument: undefined}
|
|
84
|
-
}
|
|
85
|
-
return {
|
|
86
|
-
...base,
|
|
87
|
-
loading: false,
|
|
88
|
-
assistDocument: assistDocument,
|
|
89
|
-
}
|
|
90
|
-
}, [
|
|
91
|
-
assistDocument,
|
|
92
|
-
documentIsAssistable,
|
|
93
|
-
assistableDocumentId,
|
|
94
|
-
documentSchemaType,
|
|
95
|
-
documentIsNew,
|
|
96
|
-
openInspector,
|
|
97
|
-
closeInspector,
|
|
98
|
-
inspector,
|
|
99
|
-
documentOnChange,
|
|
100
|
-
selectedPath,
|
|
101
|
-
syntheticTasks,
|
|
102
|
-
addSyntheticTask,
|
|
103
|
-
removeSyntheticTask,
|
|
104
|
-
fieldRefs,
|
|
105
|
-
fieldRefsByTypePath,
|
|
106
|
-
])
|
|
107
|
-
|
|
108
|
-
return value
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function useSyntheticTasks(assistableDocumentId: string) {
|
|
112
|
-
const [syntheticTasks, setSyntheticTasks] = useState<InstructionTask[]>(() => [])
|
|
113
|
-
const addSyntheticTask = useCallback((task: InstructionTask) => {
|
|
114
|
-
setSyntheticTasks((current) => [...current, task])
|
|
115
|
-
}, [])
|
|
116
|
-
const removeSyntheticTask = useCallback((task: InstructionTask) => {
|
|
117
|
-
setSyntheticTasks((current) => current.filter((t) => task._key !== t._key))
|
|
118
|
-
}, [])
|
|
119
|
-
|
|
120
|
-
useEffect(() => {
|
|
121
|
-
setSyntheticTasks([])
|
|
122
|
-
}, [assistableDocumentId])
|
|
123
|
-
|
|
124
|
-
return {
|
|
125
|
-
syntheticTasks,
|
|
126
|
-
addSyntheticTask,
|
|
127
|
-
removeSyntheticTask,
|
|
128
|
-
}
|
|
129
|
-
}
|