@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,75 +0,0 @@
|
|
|
1
|
-
import {useToast} from '@sanity/ui'
|
|
2
|
-
import {addSeconds, isAfter} from 'date-fns'
|
|
3
|
-
import {useEffect, useRef} from 'react'
|
|
4
|
-
import {ObjectSchemaType, useCurrentUser} from 'sanity'
|
|
5
|
-
|
|
6
|
-
import {getInstructionTitle} from '../../helpers/misc'
|
|
7
|
-
import {InstructionTask} from '../../types'
|
|
8
|
-
import {useStudioAssistDocument} from './useStudioAssistDocument'
|
|
9
|
-
|
|
10
|
-
const NO_TASKS: InstructionTask[] = []
|
|
11
|
-
|
|
12
|
-
export function useInstructionToaster(documentId: string, documentSchemaType: ObjectSchemaType) {
|
|
13
|
-
const assistDocument = useStudioAssistDocument({documentId, schemaType: documentSchemaType})
|
|
14
|
-
|
|
15
|
-
const assistDocLoaded = !!assistDocument
|
|
16
|
-
const currentUser = useCurrentUser()
|
|
17
|
-
const toast = useToast()
|
|
18
|
-
const tasks = assistDocument?.tasks
|
|
19
|
-
const previousTasks = useRef<InstructionTask[] | undefined | 'initial'>('initial')
|
|
20
|
-
|
|
21
|
-
useEffect(() => {
|
|
22
|
-
if (!assistDocLoaded) {
|
|
23
|
-
return
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (previousTasks.current !== 'initial') {
|
|
27
|
-
const prevTaskByKey = Object.fromEntries(
|
|
28
|
-
(previousTasks.current ?? NO_TASKS).map((run) => [run._key, run]),
|
|
29
|
-
)
|
|
30
|
-
const endedTasks = tasks
|
|
31
|
-
?.filter((task) => task.startedByUserId === currentUser?.id)
|
|
32
|
-
.filter((task) => {
|
|
33
|
-
const prevTask = prevTaskByKey[task._key]
|
|
34
|
-
return (!prevTask && task.ended) || (!prevTask?.ended && task.ended)
|
|
35
|
-
})
|
|
36
|
-
// filter out old stuff
|
|
37
|
-
.filter((task) => task.ended && isAfter(addSeconds(new Date(task.ended), 30), new Date()))
|
|
38
|
-
|
|
39
|
-
endedTasks?.forEach((task) => {
|
|
40
|
-
const title = task.title ?? getInstructionTitle(task.instruction)
|
|
41
|
-
if (task.reason === 'error') {
|
|
42
|
-
toast.push({
|
|
43
|
-
title: `Failed: ${title}`,
|
|
44
|
-
status: 'error',
|
|
45
|
-
description: `Instruction failed. ${task.message ?? ''}`,
|
|
46
|
-
closable: true,
|
|
47
|
-
duration: 10000,
|
|
48
|
-
})
|
|
49
|
-
} else if (task.reason === 'timeout') {
|
|
50
|
-
toast.push({
|
|
51
|
-
title: `Timeout: ${title}`,
|
|
52
|
-
status: 'error',
|
|
53
|
-
description: `Instruction timed out.`,
|
|
54
|
-
closable: true,
|
|
55
|
-
})
|
|
56
|
-
} else if (task.reason === 'success') {
|
|
57
|
-
toast.push({
|
|
58
|
-
title: `Success: ${title}`,
|
|
59
|
-
status: 'success',
|
|
60
|
-
description: `Instruction completed.`,
|
|
61
|
-
closable: true,
|
|
62
|
-
})
|
|
63
|
-
} else if (task.reason === 'aborted') {
|
|
64
|
-
toast.push({
|
|
65
|
-
title: `Canceled: ${title}`,
|
|
66
|
-
status: 'warning',
|
|
67
|
-
description: `Instruction canceled.`,
|
|
68
|
-
closable: true,
|
|
69
|
-
})
|
|
70
|
-
}
|
|
71
|
-
})
|
|
72
|
-
}
|
|
73
|
-
previousTasks.current = tasks
|
|
74
|
-
}, [tasks, previousTasks, toast, currentUser, assistDocLoaded])
|
|
75
|
-
}
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import {useEffect, useMemo} from 'react'
|
|
2
|
-
import {type ObjectSchemaType, typed, useClient, useCurrentUser} from 'sanity'
|
|
3
|
-
|
|
4
|
-
import {maxHistoryVisibilityMs} from '../../constants'
|
|
5
|
-
import {assistDocumentId, assistTasksStatusId} from '../../helpers/ids'
|
|
6
|
-
import {
|
|
7
|
-
assistDocumentTypeName,
|
|
8
|
-
type AssistTasksStatus,
|
|
9
|
-
assistTasksStatusTypeName,
|
|
10
|
-
type InstructionTask,
|
|
11
|
-
type StudioAssistDocument,
|
|
12
|
-
type StudioAssistField,
|
|
13
|
-
type StudioInstruction,
|
|
14
|
-
} from '../../types'
|
|
15
|
-
import {useDocumentState} from './useDocumentState'
|
|
16
|
-
|
|
17
|
-
interface UseAssistDocumentProps {
|
|
18
|
-
documentId: string
|
|
19
|
-
schemaType: ObjectSchemaType
|
|
20
|
-
initDoc?: boolean
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function useStudioAssistDocument({
|
|
24
|
-
documentId,
|
|
25
|
-
schemaType,
|
|
26
|
-
initDoc,
|
|
27
|
-
}: UseAssistDocumentProps): StudioAssistDocument | undefined {
|
|
28
|
-
const documentTypeName = schemaType.name
|
|
29
|
-
const currentUser = useCurrentUser()
|
|
30
|
-
|
|
31
|
-
const assistDocument = useDocumentState<StudioAssistDocument>(
|
|
32
|
-
assistDocumentId(documentTypeName),
|
|
33
|
-
assistDocumentTypeName,
|
|
34
|
-
)
|
|
35
|
-
const assistTasksStatus = useDocumentState<AssistTasksStatus>(
|
|
36
|
-
assistTasksStatusId(documentId ?? ''),
|
|
37
|
-
assistTasksStatusTypeName,
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
const client = useClient({apiVersion: '2023-01-01'})
|
|
41
|
-
|
|
42
|
-
useEffect(() => {
|
|
43
|
-
if (!assistDocument && initDoc) {
|
|
44
|
-
client
|
|
45
|
-
.createIfNotExists({
|
|
46
|
-
_id: assistDocumentId(documentTypeName),
|
|
47
|
-
_type: assistDocumentTypeName,
|
|
48
|
-
})
|
|
49
|
-
.catch(() => {
|
|
50
|
-
// best effort
|
|
51
|
-
})
|
|
52
|
-
}
|
|
53
|
-
}, [client, assistDocument, documentTypeName, initDoc])
|
|
54
|
-
|
|
55
|
-
return useMemo(() => {
|
|
56
|
-
if (!assistDocument) {
|
|
57
|
-
return undefined
|
|
58
|
-
}
|
|
59
|
-
const tasks = assistTasksStatus?.tasks ?? []
|
|
60
|
-
const fields = (assistDocument?.fields ?? []).map((assistField): StudioAssistField => {
|
|
61
|
-
return {
|
|
62
|
-
...assistField,
|
|
63
|
-
tasks: tasks.filter((task) => task.path === assistField.path),
|
|
64
|
-
instructions: assistField.instructions
|
|
65
|
-
?.filter((p) => !p.userId || p.userId === currentUser?.id)
|
|
66
|
-
.map((instruction) => asStudioInstruction(instruction, tasks)),
|
|
67
|
-
}
|
|
68
|
-
})
|
|
69
|
-
return typed<StudioAssistDocument>({
|
|
70
|
-
...assistDocument,
|
|
71
|
-
tasks: tasks?.map((task) => {
|
|
72
|
-
const instruction = fields
|
|
73
|
-
.find((f) => f.path === task.path)
|
|
74
|
-
?.instructions?.find((i) => i._key === task.instructionKey)
|
|
75
|
-
return {
|
|
76
|
-
...task,
|
|
77
|
-
instruction,
|
|
78
|
-
}
|
|
79
|
-
}),
|
|
80
|
-
fields: fields,
|
|
81
|
-
})
|
|
82
|
-
}, [assistDocument, assistTasksStatus, currentUser])
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function asStudioInstruction(
|
|
86
|
-
instruction: StudioInstruction,
|
|
87
|
-
run: InstructionTask[],
|
|
88
|
-
): StudioInstruction {
|
|
89
|
-
return {
|
|
90
|
-
...instruction,
|
|
91
|
-
tasks: run
|
|
92
|
-
.filter((task) => task.instructionKey === instruction._key)
|
|
93
|
-
.filter(
|
|
94
|
-
(task) =>
|
|
95
|
-
task.started &&
|
|
96
|
-
new Date().getTime() - new Date(task.started).getTime() < maxHistoryVisibilityMs,
|
|
97
|
-
),
|
|
98
|
-
}
|
|
99
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './AssistDocumentContextProvider'
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import {Box, Flex} from '@sanity/ui'
|
|
2
|
-
import {useMemo} from 'react'
|
|
3
|
-
import {FieldProps, isArraySchemaType} from 'sanity'
|
|
4
|
-
|
|
5
|
-
import {assistFormId} from '../_lib/form/constants'
|
|
6
|
-
import {isAssistSupported} from '../helpers/assistSupported'
|
|
7
|
-
import {isPortableTextArray, isType} from '../helpers/typeUtils'
|
|
8
|
-
import {AiFieldPresence} from '../presence/AiFieldPresence'
|
|
9
|
-
import {useAssistPresence} from '../presence/useAssistPresence'
|
|
10
|
-
import {contextDocumentTypeName} from '../types'
|
|
11
|
-
|
|
12
|
-
export function AssistFieldWrapper(props: FieldProps) {
|
|
13
|
-
const {schemaType} = props
|
|
14
|
-
|
|
15
|
-
const isSupported = useMemo(() => isAssistSupported(schemaType), [schemaType])
|
|
16
|
-
|
|
17
|
-
if (
|
|
18
|
-
!isSupported ||
|
|
19
|
-
schemaType.name.startsWith('sanity.') ||
|
|
20
|
-
schemaType.name === contextDocumentTypeName
|
|
21
|
-
) {
|
|
22
|
-
return props.renderDefault(props)
|
|
23
|
-
}
|
|
24
|
-
if (
|
|
25
|
-
!isType(props.schemaType, 'document') &&
|
|
26
|
-
props.inputId !== 'root' &&
|
|
27
|
-
props.inputId !== assistFormId
|
|
28
|
-
) {
|
|
29
|
-
return <AssistField {...props}>{props.children}</AssistField>
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return props.renderDefault(props)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function AssistField(props: FieldProps) {
|
|
36
|
-
const isPortableText = useMemo(
|
|
37
|
-
() => !!(isArraySchemaType(props.schemaType) && isPortableTextArray(props.schemaType)),
|
|
38
|
-
[props.schemaType],
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
const presence = useAssistPresence(props.path, isPortableText)
|
|
42
|
-
const singlePresence = presence[0]
|
|
43
|
-
|
|
44
|
-
const actions = (
|
|
45
|
-
<Flex gap={2} align="center" justify="space-between">
|
|
46
|
-
{singlePresence && (
|
|
47
|
-
<Box>
|
|
48
|
-
<AiFieldPresence presence={singlePresence} />
|
|
49
|
-
</Box>
|
|
50
|
-
)}
|
|
51
|
-
</Flex>
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
return props.renderDefault({
|
|
55
|
-
...props,
|
|
56
|
-
|
|
57
|
-
actions: props.actions,
|
|
58
|
-
|
|
59
|
-
// Render presence in the internal slot (between presence and the field actions)
|
|
60
|
-
// eslint-disable-next-line camelcase
|
|
61
|
-
__internal_slot: actions,
|
|
62
|
-
})
|
|
63
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import {Box, Flex} from '@sanity/ui'
|
|
2
|
-
import {useCallback} from 'react'
|
|
3
|
-
import {BlockProps, PatchEvent, useFormCallbacks} from 'sanity'
|
|
4
|
-
|
|
5
|
-
import {ErrorWrapper} from '../components/SafeValueInput'
|
|
6
|
-
import {AiFieldPresence} from '../presence/AiFieldPresence'
|
|
7
|
-
import {useAssistPresence} from '../presence/useAssistPresence'
|
|
8
|
-
|
|
9
|
-
export function AssistFormBlock(props: BlockProps) {
|
|
10
|
-
const presence = useAssistPresence(props.path, true)
|
|
11
|
-
const {onChange} = useFormCallbacks()
|
|
12
|
-
const key = props.value._key
|
|
13
|
-
const localOnChange = useCallback(
|
|
14
|
-
(patchEvent: PatchEvent) => {
|
|
15
|
-
if (!key) {
|
|
16
|
-
return
|
|
17
|
-
}
|
|
18
|
-
onChange(PatchEvent.from(patchEvent).prefixAll({_key: key}))
|
|
19
|
-
},
|
|
20
|
-
[onChange, key],
|
|
21
|
-
)
|
|
22
|
-
const singlePresence = presence[0]
|
|
23
|
-
return (
|
|
24
|
-
<ErrorWrapper onChange={localOnChange}>
|
|
25
|
-
<Flex align="center" justify="space-between">
|
|
26
|
-
<Box flex={1}>{props.renderDefault(props)}</Box>
|
|
27
|
-
{singlePresence && <AiFieldPresence presence={singlePresence} />}
|
|
28
|
-
</Flex>
|
|
29
|
-
</ErrorWrapper>
|
|
30
|
-
)
|
|
31
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import {createContext} from 'react'
|
|
2
|
-
import {BlockProps} from 'sanity'
|
|
3
|
-
|
|
4
|
-
// workaround for preview value sometimes lagging behind
|
|
5
|
-
export const InlineBlockValueContext = createContext<unknown>(undefined)
|
|
6
|
-
|
|
7
|
-
export function AssistInlineFormBlock(props: BlockProps) {
|
|
8
|
-
return (
|
|
9
|
-
<InlineBlockValueContext.Provider value={props.value}>
|
|
10
|
-
<>{props.renderDefault(props)}</>
|
|
11
|
-
</InlineBlockValueContext.Provider>
|
|
12
|
-
)
|
|
13
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import {Box, Flex} from '@sanity/ui'
|
|
2
|
-
import {ItemProps} from 'sanity'
|
|
3
|
-
|
|
4
|
-
import {AiFieldPresence} from '../presence/AiFieldPresence'
|
|
5
|
-
import {useAssistPresence} from '../presence/useAssistPresence'
|
|
6
|
-
|
|
7
|
-
export function AssistItem(props: ItemProps) {
|
|
8
|
-
const {path} = props
|
|
9
|
-
const presence = useAssistPresence(path, true)
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
<Flex align="center" width="fill" style={{position: 'relative'}}>
|
|
13
|
-
<Box flex={1}>{props.renderDefault({...props})}</Box>
|
|
14
|
-
{presence.map((pre) => (
|
|
15
|
-
<Box key={pre.user.id} style={{position: 'absolute', right: 35}}>
|
|
16
|
-
<AiFieldPresence presence={pre} />
|
|
17
|
-
</Box>
|
|
18
|
-
))}
|
|
19
|
-
</Flex>
|
|
20
|
-
)
|
|
21
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import {Box, type ButtonTone, Flex, MenuItem, Stack, Text} from '@sanity/ui'
|
|
2
|
-
import {useCallback} from 'react'
|
|
3
|
-
import type {Path, ValidationMarker} from 'sanity'
|
|
4
|
-
import {styled} from 'styled-components'
|
|
5
|
-
|
|
6
|
-
interface ValidationListItemProps {
|
|
7
|
-
marker: ValidationMarker
|
|
8
|
-
onClick?: (path?: Path) => void
|
|
9
|
-
path: string
|
|
10
|
-
truncate?: boolean
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const StyledText = styled(Text)`
|
|
14
|
-
white-space: initial;
|
|
15
|
-
`
|
|
16
|
-
|
|
17
|
-
const MENU_ITEM_TONES: Record<'error' | 'warning' | 'info', ButtonTone> = {
|
|
18
|
-
error: 'critical',
|
|
19
|
-
warning: 'caution',
|
|
20
|
-
info: 'primary',
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function ListItem(props: ValidationListItemProps) {
|
|
24
|
-
const {marker, onClick, path, truncate} = props
|
|
25
|
-
|
|
26
|
-
const handleClick = useCallback(() => {
|
|
27
|
-
if (onClick) {
|
|
28
|
-
onClick(marker.path)
|
|
29
|
-
}
|
|
30
|
-
}, [marker.path, onClick])
|
|
31
|
-
|
|
32
|
-
const menuItemTone = MENU_ITEM_TONES[marker?.level] || undefined
|
|
33
|
-
|
|
34
|
-
const children = (
|
|
35
|
-
<Flex>
|
|
36
|
-
{/* <Box>
|
|
37
|
-
<Text size={1}>
|
|
38
|
-
{marker.level === 'error' && <ErrorOutlineIcon />}
|
|
39
|
-
{marker.level === 'warning' && <WarningOutlineIcon />}
|
|
40
|
-
{marker.level === 'info' && <InfoOutlineIcon />}
|
|
41
|
-
</Text>
|
|
42
|
-
</Box>*/}
|
|
43
|
-
|
|
44
|
-
<Stack space={2} flex={1}>
|
|
45
|
-
{path && (
|
|
46
|
-
<StyledText size={1} weight="semibold">
|
|
47
|
-
{path}
|
|
48
|
-
</StyledText>
|
|
49
|
-
)}
|
|
50
|
-
{marker.item?.message && (
|
|
51
|
-
<StyledText muted size={1} textOverflow={truncate ? 'ellipsis' : undefined}>
|
|
52
|
-
{marker.item?.message}
|
|
53
|
-
</StyledText>
|
|
54
|
-
)}
|
|
55
|
-
</Stack>
|
|
56
|
-
</Flex>
|
|
57
|
-
)
|
|
58
|
-
return (
|
|
59
|
-
<MenuItem padding={1} onClick={handleClick} radius={2} tone={menuItemTone}>
|
|
60
|
-
<Box padding={2}>{children}</Box>
|
|
61
|
-
</MenuItem>
|
|
62
|
-
)
|
|
63
|
-
}
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import {Container} from '@sanity/ui'
|
|
2
|
-
import {useCallback} from 'react'
|
|
3
|
-
import {
|
|
4
|
-
isValidationErrorMarker,
|
|
5
|
-
isValidationInfoMarker,
|
|
6
|
-
isValidationWarningMarker,
|
|
7
|
-
ObjectSchemaType,
|
|
8
|
-
Path,
|
|
9
|
-
ValidationMarker,
|
|
10
|
-
} from 'sanity'
|
|
11
|
-
|
|
12
|
-
import {ListItem} from './listItem'
|
|
13
|
-
|
|
14
|
-
/** @internal */
|
|
15
|
-
export interface ValidationListProps {
|
|
16
|
-
documentType?: ObjectSchemaType
|
|
17
|
-
kind?: 'simple'
|
|
18
|
-
validation: ValidationMarker[]
|
|
19
|
-
onFocus?: (path: Path) => void
|
|
20
|
-
onClose?: () => void
|
|
21
|
-
truncate?: boolean
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function ValidationList(props: ValidationListProps) {
|
|
25
|
-
const {documentType, kind, validation, onFocus, onClose, truncate} = props
|
|
26
|
-
const errors = validation.filter(isValidationErrorMarker)
|
|
27
|
-
const warnings = validation.filter(isValidationWarningMarker)
|
|
28
|
-
const info = validation.filter(isValidationInfoMarker)
|
|
29
|
-
|
|
30
|
-
const handleClick = useCallback(
|
|
31
|
-
(path: Path = []) => {
|
|
32
|
-
if (onFocus) onFocus(path)
|
|
33
|
-
if (onClose) onClose()
|
|
34
|
-
},
|
|
35
|
-
[onFocus, onClose],
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
const resolvePathTitle = (path: Path) => {
|
|
39
|
-
const fields = documentType && documentType.fields
|
|
40
|
-
const field = fields && fields.find((curr) => curr.name === path[0])
|
|
41
|
-
|
|
42
|
-
return (field && field.type.title) || ''
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const hasErrors = errors.length > 0
|
|
46
|
-
const hasWarnings = warnings.length > 0
|
|
47
|
-
const hasInfo = info.length > 0
|
|
48
|
-
|
|
49
|
-
if (!hasErrors && !hasWarnings && !hasInfo) {
|
|
50
|
-
return null
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return (
|
|
54
|
-
<Container width={0} data-kind={kind} data-testid="validation-list">
|
|
55
|
-
{hasErrors &&
|
|
56
|
-
errors.map((_error, i) => (
|
|
57
|
-
<ListItem
|
|
58
|
-
// eslint-disable-next-line react/no-array-index-key
|
|
59
|
-
key={i}
|
|
60
|
-
truncate={truncate}
|
|
61
|
-
path={resolvePathTitle(_error.path)}
|
|
62
|
-
marker={_error}
|
|
63
|
-
onClick={handleClick}
|
|
64
|
-
/>
|
|
65
|
-
))}
|
|
66
|
-
{hasWarnings &&
|
|
67
|
-
warnings.map((_warning, i) => (
|
|
68
|
-
<ListItem
|
|
69
|
-
// eslint-disable-next-line react/no-array-index-key
|
|
70
|
-
key={i}
|
|
71
|
-
truncate={truncate}
|
|
72
|
-
path={resolvePathTitle(_warning.path)}
|
|
73
|
-
marker={_warning}
|
|
74
|
-
onClick={handleClick}
|
|
75
|
-
/>
|
|
76
|
-
))}
|
|
77
|
-
{hasInfo &&
|
|
78
|
-
info.map((_info, i) => (
|
|
79
|
-
<ListItem
|
|
80
|
-
// eslint-disable-next-line react/no-array-index-key
|
|
81
|
-
key={i}
|
|
82
|
-
truncate={truncate}
|
|
83
|
-
path={resolvePathTitle(_info.path)}
|
|
84
|
-
marker={_info}
|
|
85
|
-
onClick={handleClick}
|
|
86
|
-
/>
|
|
87
|
-
))}
|
|
88
|
-
</Container>
|
|
89
|
-
)
|
|
90
|
-
}
|