@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.
Files changed (131) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +28 -254
  3. package/dist/index.d.ts +322 -410
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +3182 -2673
  6. package/dist/index.js.map +1 -1
  7. package/package.json +41 -77
  8. package/dist/index.cjs +0 -4264
  9. package/dist/index.cjs.map +0 -1
  10. package/dist/index.d.cts +0 -791
  11. package/sanity.json +0 -8
  12. package/src/_lib/connector/ConnectFromRegion.tsx +0 -25
  13. package/src/_lib/connector/ConnectToRegion.tsx +0 -23
  14. package/src/_lib/connector/ConnectorRegion.tsx +0 -24
  15. package/src/_lib/connector/ConnectorsProvider.tsx +0 -20
  16. package/src/_lib/connector/ConnectorsStore.ts +0 -122
  17. package/src/_lib/connector/ConnectorsStoreContext.ts +0 -5
  18. package/src/_lib/connector/helpers.ts +0 -5
  19. package/src/_lib/connector/index.ts +0 -9
  20. package/src/_lib/connector/mapConnectorToLine.ts +0 -83
  21. package/src/_lib/connector/types.ts +0 -56
  22. package/src/_lib/connector/useConnectorsStore.ts +0 -14
  23. package/src/_lib/connector/useRegionRects.ts +0 -142
  24. package/src/_lib/fixedListenQuery.ts +0 -101
  25. package/src/_lib/form/DocumentForm.tsx +0 -201
  26. package/src/_lib/form/constants.ts +0 -1
  27. package/src/_lib/form/helpers.ts +0 -32
  28. package/src/_lib/form/index.ts +0 -1
  29. package/src/_lib/randomKey.ts +0 -29
  30. package/src/_lib/useListeningQuery.ts +0 -62
  31. package/src/_lib/usePrevious.ts +0 -9
  32. package/src/assistConnectors/AssistConnectorsOverlay.tsx +0 -133
  33. package/src/assistConnectors/ConnectorPath.tsx +0 -63
  34. package/src/assistConnectors/draw/arrowPath.ts +0 -9
  35. package/src/assistConnectors/draw/connectorPath.ts +0 -142
  36. package/src/assistConnectors/index.ts +0 -1
  37. package/src/assistDocument/AssistDocumentContext.tsx +0 -51
  38. package/src/assistDocument/AssistDocumentContextProvider.tsx +0 -17
  39. package/src/assistDocument/AssistDocumentInput.tsx +0 -61
  40. package/src/assistDocument/AssistDocumentLayout.tsx +0 -12
  41. package/src/assistDocument/RequestRunInstructionProvider.tsx +0 -61
  42. package/src/assistDocument/components/AssistDocumentForm.tsx +0 -286
  43. package/src/assistDocument/components/AssistTypeContext.tsx +0 -7
  44. package/src/assistDocument/components/FieldRefPreview.tsx +0 -26
  45. package/src/assistDocument/components/InstructionsArrayField.tsx +0 -8
  46. package/src/assistDocument/components/InstructionsArrayInput.tsx +0 -27
  47. package/src/assistDocument/components/SelectedFieldContext.tsx +0 -10
  48. package/src/assistDocument/components/generic/HiddenFieldTitle.tsx +0 -5
  49. package/src/assistDocument/components/helpers.ts +0 -21
  50. package/src/assistDocument/components/instruction/BackToInstructionsLink.tsx +0 -32
  51. package/src/assistDocument/components/instruction/FieldRefInput.tsx +0 -54
  52. package/src/assistDocument/components/instruction/InstructionInput.tsx +0 -89
  53. package/src/assistDocument/components/instruction/InstructionOutputField.tsx +0 -46
  54. package/src/assistDocument/components/instruction/InstructionOutputInput.tsx +0 -206
  55. package/src/assistDocument/components/instruction/PromptInput.tsx +0 -59
  56. package/src/assistDocument/components/instruction/appearance/IconInput.tsx +0 -46
  57. package/src/assistDocument/components/instruction/appearance/InstructionVisibility.tsx +0 -37
  58. package/src/assistDocument/hooks/useAssistDocumentContextValue.tsx +0 -129
  59. package/src/assistDocument/hooks/useDocumentState.ts +0 -6
  60. package/src/assistDocument/hooks/useInstructionToaster.tsx +0 -75
  61. package/src/assistDocument/hooks/useStudioAssistDocument.ts +0 -99
  62. package/src/assistDocument/index.ts +0 -1
  63. package/src/assistFormComponents/AssistField.tsx +0 -63
  64. package/src/assistFormComponents/AssistFormBlock.tsx +0 -31
  65. package/src/assistFormComponents/AssistInlineFormBlock.tsx +0 -13
  66. package/src/assistFormComponents/AssistItem.tsx +0 -21
  67. package/src/assistFormComponents/validation/listItem.tsx +0 -63
  68. package/src/assistFormComponents/validation/validationList.tsx +0 -90
  69. package/src/assistInspector/AssistInspector.tsx +0 -423
  70. package/src/assistInspector/FieldAutocomplete.tsx +0 -146
  71. package/src/assistInspector/InstructionTaskHistoryButton.tsx +0 -262
  72. package/src/assistInspector/constants.ts +0 -1
  73. package/src/assistInspector/helpers.ts +0 -211
  74. package/src/assistInspector/index.ts +0 -27
  75. package/src/assistLayout/AiAssistanceConfigContext.tsx +0 -32
  76. package/src/assistLayout/AiAssistanceConfigProvider.tsx +0 -98
  77. package/src/assistLayout/AssistLayout.tsx +0 -39
  78. package/src/assistLayout/RunInstructionProvider.tsx +0 -278
  79. package/src/assistLayout/fieldRefCache.tsx +0 -34
  80. package/src/assistTypes.ts +0 -83
  81. package/src/components/AssistFeatureBadge.tsx +0 -9
  82. package/src/components/FadeInContent.tsx +0 -40
  83. package/src/components/HideReferenceChangedBannerInput.tsx +0 -25
  84. package/src/components/ImageContext.tsx +0 -85
  85. package/src/components/SafeValueInput.tsx +0 -74
  86. package/src/components/TimeAgo.tsx +0 -18
  87. package/src/constants.ts +0 -20
  88. package/src/fieldActions/PrivateIcon.tsx +0 -20
  89. package/src/fieldActions/assistFieldActions.tsx +0 -320
  90. package/src/fieldActions/customFieldActions.tsx +0 -333
  91. package/src/fieldActions/generateCaptionActions.tsx +0 -77
  92. package/src/fieldActions/generateImageActions.tsx +0 -58
  93. package/src/fieldActions/useUserInput.ts +0 -107
  94. package/src/globals.d.ts +0 -4
  95. package/src/helpers/assistSupported.ts +0 -49
  96. package/src/helpers/conditionalMembers.test.ts +0 -319
  97. package/src/helpers/conditionalMembers.ts +0 -134
  98. package/src/helpers/ids.test.ts +0 -28
  99. package/src/helpers/ids.ts +0 -23
  100. package/src/helpers/misc.ts +0 -25
  101. package/src/helpers/styleguide.ts +0 -24
  102. package/src/helpers/typeUtils.ts +0 -60
  103. package/src/helpers/useAssistSupported.ts +0 -8
  104. package/src/index.ts +0 -26
  105. package/src/onboarding/FirstAssistedPathProvider.tsx +0 -30
  106. package/src/onboarding/InspectorOnboarding.tsx +0 -47
  107. package/src/onboarding/onboardingStore.ts +0 -32
  108. package/src/plugin.tsx +0 -162
  109. package/src/presence/AiFieldPresence.tsx +0 -28
  110. package/src/presence/AssistAvatar.tsx +0 -96
  111. package/src/presence/AssistDocumentPresence.tsx +0 -50
  112. package/src/presence/useAssistPresence.ts +0 -64
  113. package/src/schemas/assistDocumentSchema.tsx +0 -497
  114. package/src/schemas/contextDocumentSchema.tsx +0 -57
  115. package/src/schemas/index.ts +0 -69
  116. package/src/schemas/serialize/SchemTypeTool.tsx +0 -103
  117. package/src/schemas/serialize/schemaUtils.ts +0 -38
  118. package/src/schemas/serialize/serializeSchema.test.ts +0 -819
  119. package/src/schemas/serialize/serializeSchema.ts +0 -224
  120. package/src/schemas/serializedSchemaTypeSchema.ts +0 -60
  121. package/src/schemas/typeDefExtensions.ts +0 -127
  122. package/src/translate/FieldTranslationProvider.tsx +0 -382
  123. package/src/translate/getLanguageParams.ts +0 -26
  124. package/src/translate/languageStore.ts +0 -18
  125. package/src/translate/paths.test.ts +0 -181
  126. package/src/translate/paths.ts +0 -183
  127. package/src/translate/translateActions.tsx +0 -205
  128. package/src/translate/types.ts +0 -197
  129. package/src/types.ts +0 -220
  130. package/src/useApiClient.ts +0 -338
  131. package/v2-incompatible.js +0 -11
@@ -1,262 +0,0 @@
1
- import {
2
- CheckmarkCircleIcon,
3
- ClockIcon,
4
- CloseCircleIcon,
5
- ErrorOutlineIcon,
6
- SyncIcon,
7
- } from '@sanity/icons'
8
- import {
9
- Box,
10
- Button,
11
- Card,
12
- Flex,
13
- Popover,
14
- Spinner,
15
- Stack,
16
- Text,
17
- useClickOutside,
18
- useGlobalKeyDown,
19
- useLayer,
20
- } from '@sanity/ui'
21
- import {createElement, type ForwardedRef, forwardRef, useCallback, useMemo, useState} from 'react'
22
- import {StatusButton, type StatusButtonProps, typed, useClient} from 'sanity'
23
- import {keyframes, styled} from 'styled-components'
24
-
25
- import {TimeAgo} from '../components/TimeAgo'
26
- import {maxHistoryVisibilityMs, pluginTitle} from '../constants'
27
- import {assistTasksStatusId} from '../helpers/ids'
28
- import {getInstructionTitle} from '../helpers/misc'
29
- import type {AssistTasksStatus, InstructionTask, StudioInstruction, TaskEndedReason} from '../types'
30
-
31
- export interface InstructionTaskHistoryButtonProps {
32
- documentId?: string
33
- tasks: InstructionTask[] | undefined
34
- instructions: StudioInstruction[] | undefined
35
- showTitles: boolean
36
- }
37
-
38
- interface CancelableInstructionTask extends InstructionTask {
39
- cancel: () => void
40
- title?: string
41
- }
42
-
43
- const rotate = keyframes`
44
- 0% {
45
- transform: rotate(0);
46
- }
47
- 100% {
48
- transform: rotate(360deg);
49
- }
50
- `
51
-
52
- const SyncSpinningIcon = styled(SyncIcon)`
53
- animation: ${rotate} 1s linear infinite;
54
- `
55
-
56
- const TASK_CONFIG = {
57
- aborted: {
58
- title: 'Canceled',
59
- icon: CloseCircleIcon,
60
- tone: 'transparent',
61
- },
62
- error: {
63
- title: 'Error',
64
- icon: ErrorOutlineIcon,
65
- tone: 'critical',
66
- },
67
- success: {
68
- title: 'Completed',
69
- icon: CheckmarkCircleIcon,
70
- tone: 'positive',
71
- },
72
- timeout: {
73
- title: 'Timeout',
74
- icon: ClockIcon,
75
- tone: 'caution',
76
- },
77
- } as const
78
-
79
- export function InstructionTaskHistoryButton(props: InstructionTaskHistoryButtonProps) {
80
- const {tasks, instructions, documentId, showTitles} = props
81
-
82
- const client = useClient({apiVersion: '2023-01-01'})
83
- const cancelRun = useCallback(
84
- (taskKey: string) => {
85
- if (!documentId) {
86
- return
87
- }
88
- const statusDocId = assistTasksStatusId(documentId)
89
- const basePath = `${typed<keyof AssistTasksStatus>('tasks')}[_key=="${taskKey}"]`
90
- client
91
- .patch(statusDocId)
92
- .set({
93
- [`${basePath}.${typed<keyof InstructionTask>('ended')}`]: new Date().toISOString(),
94
- [`${basePath}.${typed<keyof InstructionTask>('reason')}`]:
95
- typed<TaskEndedReason>('aborted'),
96
- })
97
- .commit()
98
- .catch(console.error)
99
- },
100
- [client, documentId],
101
- )
102
-
103
- const titledTasks = useMemo(() => {
104
- const t =
105
- tasks
106
- ?.filter(
107
- (task) =>
108
- task.started &&
109
- new Date().getTime() - new Date(task.started).getTime() < maxHistoryVisibilityMs,
110
- )
111
- .map((task): CancelableInstructionTask => {
112
- const instruction = instructions?.find((i) => i._key === task.instructionKey)
113
- return {
114
- ...task,
115
- title: showTitles ? (task.title ?? getInstructionTitle(instruction)) : undefined,
116
- cancel: () => cancelRun(task._key),
117
- }
118
- }) ?? []
119
- t.sort((a, b) => new Date(b.started ?? '').getTime() - new Date(a.started ?? '').getTime())
120
- return t
121
- }, [tasks, instructions, cancelRun, showTitles])
122
-
123
- // const id = useId()
124
-
125
- const isRunning = useMemo(() => titledTasks.some((r) => !r.ended), [titledTasks])
126
- const hasErrors = useMemo(
127
- () => titledTasks.some((r) => r.reason === 'error' || r.reason === 'timeout'),
128
- [titledTasks],
129
- )
130
-
131
- const [open, setOpen] = useState(false)
132
-
133
- const toggleOpen = useCallback(() => setOpen((v) => !v), [])
134
-
135
- const [button, setButton] = useState<HTMLButtonElement | null>(null)
136
- const [popover, setPopover] = useState<HTMLDivElement | null>(null)
137
-
138
- const handleClickOutside = useCallback(() => {
139
- setOpen(false)
140
- }, [])
141
-
142
- useClickOutside(handleClickOutside, [button, popover])
143
-
144
- const handleEscape = useCallback(() => {
145
- setOpen(false)
146
- button?.focus()
147
- }, [button])
148
-
149
- return (
150
- <Popover
151
- constrainSize
152
- content={<TaskList onEscape={handleEscape} tasks={titledTasks} />}
153
- open={open && !!titledTasks?.length}
154
- placement="top"
155
- portal
156
- ref={setPopover}
157
- width={0}
158
- >
159
- <TaskStatusButton
160
- disabled={!titledTasks?.length}
161
- hasErrors={hasErrors}
162
- isRunning={isRunning}
163
- onClick={toggleOpen}
164
- ref={setButton}
165
- selected={open}
166
- />
167
- </Popover>
168
- )
169
- }
170
-
171
- const TASK_STATUS_BUTTON_TOOLTIP_PROPS: StatusButtonProps['tooltipProps'] = {
172
- placement: 'top',
173
- }
174
-
175
- const TaskStatusButton = forwardRef(function TaskStatusButton(
176
- props: {
177
- disabled: boolean
178
- hasErrors: boolean
179
- isRunning: boolean
180
- onClick: () => void
181
- selected: boolean
182
- },
183
- ref: ForwardedRef<HTMLButtonElement>,
184
- ) {
185
- const {disabled, hasErrors, isRunning, onClick, selected} = props
186
-
187
- return (
188
- <StatusButton
189
- label={`${pluginTitle} status`}
190
- aria-label={`${pluginTitle} status`}
191
- icon={isRunning ? SyncSpinningIcon : hasErrors ? ErrorOutlineIcon : CheckmarkCircleIcon}
192
- mode="bleed"
193
- onClick={onClick}
194
- tone={hasErrors ? 'critical' : undefined}
195
- disabled={disabled}
196
- ref={ref}
197
- selected={selected}
198
- tooltipProps={TASK_STATUS_BUTTON_TOOLTIP_PROPS}
199
- />
200
- )
201
- })
202
-
203
- function TaskList(props: {onEscape: () => void; tasks: CancelableInstructionTask[]}) {
204
- const {onEscape, tasks} = props
205
-
206
- const {isTopLayer} = useLayer()
207
-
208
- useGlobalKeyDown(
209
- useCallback(
210
- (event) => {
211
- if (isTopLayer && event.key === 'Escape') {
212
- onEscape()
213
- }
214
- },
215
- [isTopLayer, onEscape],
216
- ),
217
- )
218
-
219
- return (
220
- <Stack padding={1} space={1}>
221
- {tasks.map((task) => (
222
- <TaskItem key={task._key} task={task} />
223
- ))}
224
- </Stack>
225
- )
226
- }
227
-
228
- function TaskItem(props: {task: CancelableInstructionTask}) {
229
- const {task} = props
230
-
231
- const taskType = task.reason && TASK_CONFIG[task.reason]
232
- return (
233
- <Card radius={2} tone={taskType && taskType?.tone}>
234
- <Flex align="center" gap={1}>
235
- <Flex align="flex-start" flex={1} gap={3} padding={3}>
236
- <Box flex="none">
237
- <Text size={1}>
238
- {taskType && createElement(taskType.icon)}
239
- {!task.reason && <Spinner />}
240
- </Text>
241
- </Box>
242
- <Stack flex={1} space={2}>
243
- <Text size={1} weight="medium">
244
- {taskType ? taskType.title : 'Running'}
245
- {task.title && <>: {task.title}</>}
246
- </Text>
247
- {task.message ? <Text size={1}>{task.message}</Text> : null}
248
- <Text muted size={1}>
249
- <TimeAgo date={task.ended ?? task.started} />
250
- </Text>
251
- </Stack>
252
- </Flex>
253
-
254
- {!task.ended && (
255
- <Box flex="none" padding={1}>
256
- <Button fontSize={1} mode="bleed" onClick={task.cancel} text="Cancel" />
257
- </Box>
258
- )}
259
- </Flex>
260
- </Card>
261
- )
262
- }
@@ -1 +0,0 @@
1
- export const aiInspectorId = 'ai-assistance'
@@ -1,211 +0,0 @@
1
- import {
2
- BlockContentIcon,
3
- BlockquoteIcon,
4
- DocumentIcon,
5
- ImageIcon,
6
- LinkIcon,
7
- OlistIcon,
8
- StringIcon,
9
- } from '@sanity/icons'
10
- import {extractWithPath} from '@sanity/mutator'
11
- import {type ComponentType, useMemo} from 'react'
12
- import {
13
- type ArraySchemaType,
14
- isKeySegment,
15
- isObjectSchemaType,
16
- type ObjectSchemaType,
17
- type Path,
18
- pathToString,
19
- type SanityDocumentLike,
20
- type SchemaType,
21
- stringToPath,
22
- } from 'sanity'
23
- import {type PaneRouterContextValue, usePaneRouter} from 'sanity/structure'
24
- import {isAssistSupported} from '../helpers/assistSupported'
25
- import {isPortableTextArray, isType} from '../helpers/typeUtils'
26
- import {type AssistInspectorRouteParams, documentRootKey} from '../types'
27
- import {useAiAssistanceConfig} from '../assistLayout/AiAssistanceConfigContext'
28
-
29
- export interface FieldRef {
30
- key: string
31
- path: Path
32
- title: string
33
- schemaType: SchemaType
34
- icon: ComponentType
35
- synthetic?: boolean
36
- }
37
-
38
- const maxDepth = 6
39
-
40
- export function getTypeIcon(schemaType: SchemaType) {
41
- let t: SchemaType | undefined = schemaType
42
-
43
- while (t) {
44
- if (t.icon) return t.icon
45
- t = t.type
46
- }
47
-
48
- if (isType(schemaType, 'slug')) return LinkIcon
49
- if (isType(schemaType, 'image')) return ImageIcon
50
- if (schemaType.jsonType === 'array' && isPortableTextArray(schemaType)) return BlockContentIcon
51
-
52
- if (schemaType.jsonType === 'array') return OlistIcon
53
- if (schemaType.jsonType === 'object') return BlockquoteIcon
54
- if (schemaType.jsonType === 'string') return StringIcon
55
-
56
- return DocumentIcon
57
- }
58
-
59
- export function asFieldRefsByTypePath(fieldRefs: FieldRef[]): Record<string, FieldRef | undefined> {
60
- const lookup: Record<string, FieldRef | undefined> = fieldRefs.reduce(
61
- (acc, ref) => ({...acc, [ref.key]: ref}),
62
- {},
63
- )
64
- return lookup
65
- }
66
-
67
- export function getDocumentFieldRef(schemaType: ObjectSchemaType) {
68
- return {
69
- key: documentRootKey,
70
- icon: schemaType.icon ?? DocumentIcon,
71
- title: `The entire document`,
72
- path: [],
73
- schemaType: schemaType,
74
- }
75
- }
76
-
77
- export function getFieldRefs(
78
- schemaType: ObjectSchemaType,
79
- parent?: FieldRef,
80
- depth = 0,
81
- ): FieldRef[] {
82
- if (depth >= maxDepth) {
83
- return []
84
- }
85
- return schemaType.fields
86
- .filter((f) => !f.name.startsWith('_'))
87
- .flatMap((field) => {
88
- const path: Path = parent ? [...parent.path, field.name] : [field.name]
89
- const title = field.type.title ?? field.name
90
- const fieldRef: FieldRef = {
91
- key: patchableKey(pathToString(path)),
92
- path,
93
- title: parent ? [parent.title, title].join(' / ') : title,
94
- schemaType: field.type,
95
- icon: getTypeIcon(field.type),
96
- }
97
- const fields =
98
- field.type.jsonType === 'object' ? getFieldRefs(field.type, fieldRef, depth + 1) : []
99
-
100
- const syntheticFields =
101
- field.type.jsonType === 'array' ? getSyntheticFields(field.type, fieldRef, depth + 1) : []
102
- if (!isAssistSupported(field.type)) {
103
- return [...fields, ...syntheticFields]
104
- }
105
- return [fieldRef, ...fields, ...syntheticFields]
106
- })
107
- }
108
-
109
- function getSyntheticFields(schemaType: ArraySchemaType, parent?: FieldRef, depth = 0) {
110
- if (depth >= maxDepth) {
111
- return []
112
- }
113
-
114
- return schemaType.of
115
- .filter((itemType) => !isType(itemType, 'block'))
116
- .flatMap((itemType) => {
117
- const segment = {_key: itemType.name}
118
- const title = itemType.title ?? itemType.name
119
- const path: Path = parent ? [...parent.path, segment] : [segment]
120
- const fieldRef: FieldRef = {
121
- key: patchableKey(pathToString(path)),
122
- path,
123
- title: parent ? [parent.title, title].join(' / ') : title,
124
- schemaType: itemType,
125
- icon: getTypeIcon(itemType),
126
- synthetic: true,
127
- }
128
- const fields =
129
- itemType.jsonType === 'object' ? getFieldRefs(itemType, fieldRef, depth + 1) : []
130
-
131
- if (!isAssistSupported(itemType)) {
132
- return fields
133
- }
134
- return [fieldRef, ...fields]
135
- })
136
- }
137
-
138
- export function getTypePath(doc: SanityDocumentLike, pathString: string) {
139
- if (!pathString) {
140
- return undefined
141
- }
142
-
143
- const path = stringToPath(pathString)
144
- const currentPath: Path = []
145
- let valid = true
146
- const syntheticPath = path.map((segment) => {
147
- currentPath.push(segment)
148
-
149
- if (isKeySegment(segment)) {
150
- const match = extractWithPath(pathToString(currentPath), doc)[0]
151
- const value = match?.value
152
- if (match && value && typeof value === 'object' && '_type' in value) {
153
- return {_key: value._type as string}
154
- }
155
- valid = false
156
- }
157
- return segment
158
- })
159
-
160
- return valid ? patchableKey(pathToString(syntheticPath)) : undefined
161
- }
162
-
163
- /**
164
- * mutator crashes if path contains certain letters
165
- * @param pathKey
166
- */
167
- function patchableKey(pathKey: string) {
168
- return pathKey.replace(/[=]=/g, ':').replace(/[[\]]/g, '|').replace(/"/g, '')
169
- }
170
-
171
- export function useTypePath(doc: SanityDocumentLike, pathString: string) {
172
- return useMemo(() => getTypePath(doc, pathString), [doc, pathString])
173
- }
174
-
175
- export function useSelectedField(
176
- documentSchemaType?: SchemaType,
177
- path?: string,
178
- ): FieldRef | undefined {
179
- const {getFieldRefs} = useAiAssistanceConfig()
180
-
181
- const selectableFields = useMemo(
182
- () =>
183
- documentSchemaType && isObjectSchemaType(documentSchemaType)
184
- ? [getDocumentFieldRef(documentSchemaType), ...getFieldRefs(documentSchemaType.name)]
185
- : [],
186
- [documentSchemaType, getFieldRefs],
187
- )
188
-
189
- return useMemo(() => {
190
- return path ? selectableFields?.find((f) => f.key === path) : undefined
191
- }, [selectableFields, path])
192
- }
193
-
194
- export function getFieldTitle(field?: FieldRef) {
195
- const schemaType = field?.schemaType
196
- return field?.title ?? schemaType?.title ?? schemaType?.name ?? 'Untitled'
197
- }
198
-
199
- export type AiPaneRouter = Omit<PaneRouterContextValue, 'setParams' | 'params'> & {
200
- params: AssistInspectorRouteParams
201
- setParams: (p: Record<keyof AssistInspectorRouteParams, string | undefined>) => void
202
- }
203
-
204
- export function useAiPaneRouter() {
205
- const paneRouter = usePaneRouter()
206
-
207
- return useMemo(
208
- () => ({...paneRouter, params: paneRouter.params ?? {}}) as AiPaneRouter,
209
- [paneRouter],
210
- )
211
- }
@@ -1,27 +0,0 @@
1
- import {SparklesIcon} from '@sanity/icons'
2
- import {DocumentInspector, typed} from 'sanity'
3
-
4
- import {pluginTitle} from '../constants'
5
- import {AssistInspectorRouteParams, fieldPathParam, instructionParam} from '../types'
6
- import {AssistInspectorWrapper} from './AssistInspector'
7
- import {aiInspectorId} from './constants'
8
-
9
- export const assistInspector: DocumentInspector = {
10
- name: aiInspectorId,
11
- useMenuItem: () => ({
12
- icon: SparklesIcon,
13
- title: pluginTitle,
14
- hidden: true,
15
- showAsAction: false,
16
- }),
17
- component: AssistInspectorWrapper,
18
- onClose({params}) {
19
- return {
20
- params: typed<AssistInspectorRouteParams>({
21
- ...params,
22
- [fieldPathParam]: undefined,
23
- [instructionParam]: undefined,
24
- }) as typeof params,
25
- }
26
- },
27
- }
@@ -1,32 +0,0 @@
1
- import {createContext, useContext} from 'react'
2
-
3
- import {AssistPluginConfig} from '../plugin'
4
- import {InstructStatus} from '../useApiClient'
5
- import {SerializedSchemaType} from '../types'
6
- import {FieldRef} from '../assistInspector/helpers'
7
-
8
- export interface AiAssistanceConfigContextValue {
9
- config: AssistPluginConfig
10
- status?: InstructStatus
11
- statusLoading: boolean
12
- initLoading: boolean
13
- init: () => void
14
- error?: Error
15
- serializedTypes: SerializedSchemaType[]
16
- getFieldRefs: (documentType: string) => FieldRef[]
17
- getFieldRefsByTypePath: (documentType: string) => Record<string, FieldRef | undefined>
18
- }
19
-
20
- export const AiAssistanceConfigContext = createContext<AiAssistanceConfigContextValue>({} as any)
21
-
22
- export function useAiAssistanceConfig() {
23
- const context = useContext(AiAssistanceConfigContext)
24
- if (!context) {
25
- throw new Error('Missing AiAssistanceConfigContext')
26
- }
27
- return context
28
- }
29
-
30
- export function useSerializedTypes() {
31
- return useAiAssistanceConfig().serializedTypes
32
- }
@@ -1,98 +0,0 @@
1
- import {ReactNode, useCallback, useEffect, useMemo, useState} from 'react'
2
- import {AssistPluginConfig} from '../plugin'
3
- import {InstructStatus, useApiClient, useGetInstructStatus, useInitInstruct} from '../useApiClient'
4
- import {type ObjectSchemaType, Schema, useSchema} from 'sanity'
5
- import {serializeSchema} from '../schemas/serialize/serializeSchema'
6
- import {
7
- AiAssistanceConfigContext,
8
- AiAssistanceConfigContextValue,
9
- } from './AiAssistanceConfigContext'
10
- import {createFieldRefCache} from './fieldRefCache'
11
-
12
- export function AiAssistanceConfigProvider(props: {
13
- children?: ReactNode
14
- config: AssistPluginConfig
15
- }) {
16
- const [status, setStatus] = useState<InstructStatus | undefined>()
17
- const [error, setError] = useState<Error | undefined>()
18
-
19
- const apiClient = useApiClient(props.config?.__customApiClient)
20
- const {getInstructStatus, loading: statusLoading} = useGetInstructStatus(apiClient)
21
- const {initInstruct, loading: initLoading} = useInitInstruct(apiClient)
22
-
23
- const schema = useSchema()
24
- const serializedTypes = useMemo(() => serializeSchema(schema, {leanFormat: true}), [schema])
25
- const {getFieldRefs, getFieldRefsByTypePath} = useFieldRefGetters(schema)
26
-
27
- useEffect(() => {
28
- getInstructStatus()
29
- .then((s) => setStatus(s))
30
- .catch((e) => {
31
- console.error(e)
32
- setError(e as Error)
33
- })
34
- }, [getInstructStatus])
35
-
36
- const init = useCallback(async () => {
37
- setError(undefined)
38
- try {
39
- await initInstruct()
40
- const status = await getInstructStatus()
41
- setStatus(status)
42
- } catch (e) {
43
- console.error('Failed to init ai assistance', e)
44
- setError(e as Error)
45
- }
46
- }, [initInstruct, getInstructStatus, setStatus])
47
-
48
- const {config, children} = props
49
- const context = useMemo<AiAssistanceConfigContextValue>(() => {
50
- return {
51
- config,
52
- status,
53
- statusLoading,
54
- init,
55
- initLoading,
56
- error,
57
- serializedTypes,
58
- getFieldRefs,
59
- getFieldRefsByTypePath,
60
- }
61
- }, [
62
- config,
63
- status,
64
- init,
65
- statusLoading,
66
- initLoading,
67
- error,
68
- serializedTypes,
69
- getFieldRefs,
70
- getFieldRefsByTypePath,
71
- ])
72
-
73
- return (
74
- <AiAssistanceConfigContext.Provider value={context}>
75
- {children}
76
- </AiAssistanceConfigContext.Provider>
77
- )
78
- }
79
-
80
- function useFieldRefGetters(schema: Schema) {
81
- return useMemo(() => {
82
- const getForSchemaType = createFieldRefCache()
83
-
84
- function getRefsForType(documentType: string) {
85
- const schemaType = schema.get(documentType) as ObjectSchemaType | undefined
86
- if (!schemaType) {
87
- throw new Error(`Schema type "${documentType}" not found`)
88
- }
89
- return getForSchemaType(schemaType)
90
- }
91
-
92
- return {
93
- getFieldRefs: (documentType: string) => getRefsForType(documentType).fieldRefs,
94
- getFieldRefsByTypePath: (documentType: string) =>
95
- getRefsForType(documentType).fieldRefsByTypePath,
96
- }
97
- }, [schema])
98
- }
@@ -1,39 +0,0 @@
1
- import {ThemeProvider} from '@sanity/ui'
2
- import {useState} from 'react'
3
- import {LayoutProps} from 'sanity'
4
-
5
- import {Connector, ConnectorsProvider} from '../_lib/connector'
6
- import {AssistConnectorsOverlay} from '../assistConnectors'
7
- import {AssistPluginConfig} from '../plugin'
8
- import {FieldTranslationProvider} from '../translate/FieldTranslationProvider'
9
- import {StudioInstruction} from '../types'
10
- import {RunInstructionRequest} from '../useApiClient'
11
- import {RunInstructionProvider} from './RunInstructionProvider'
12
- import {AiAssistanceConfigProvider} from './AiAssistanceConfigProvider'
13
-
14
- export interface AIStudioLayoutProps extends LayoutProps {
15
- config: AssistPluginConfig
16
- }
17
-
18
- export type RunInstructionArgs = Omit<RunInstructionRequest, 'instructionKey' | 'userText'> & {
19
- instruction: StudioInstruction
20
- }
21
-
22
- export function AssistLayout(props: AIStudioLayoutProps) {
23
- const [connectors, setConnectors] = useState<Connector[]>([])
24
-
25
- return (
26
- <AiAssistanceConfigProvider config={props.config}>
27
- <RunInstructionProvider>
28
- <FieldTranslationProvider>
29
- <ConnectorsProvider onConnectorsChange={setConnectors}>
30
- {props.renderDefault(props)}
31
- <ThemeProvider tone="default">
32
- <AssistConnectorsOverlay connectors={connectors} />
33
- </ThemeProvider>
34
- </ConnectorsProvider>
35
- </FieldTranslationProvider>
36
- </RunInstructionProvider>
37
- </AiAssistanceConfigProvider>
38
- )
39
- }