@sanity/assist 1.0.8 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/index.esm.js +4449 -2334
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +4463 -2333
- package/dist/index.js.map +1 -1
- package/package.json +6 -2
- package/src/assistInspector/helpers.ts +1 -1
- package/src/components/FadeInContent.tsx +33 -0
- package/src/fieldActions/assistFieldActions.tsx +4 -2
- package/src/helpers/assistSupported.ts +15 -5
- package/src/presence/AiFieldPresence.tsx +4 -6
- package/src/schemas/serialize/serializeSchema.test.ts +26 -0
- package/src/schemas/serialize/serializeSchema.ts +2 -0
- package/src/components/Delay.tsx +0 -25
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/assist",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.10",
|
|
4
4
|
"description": "",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"@sanity/icons": "^2.4.0",
|
|
54
54
|
"@sanity/incompatible-plugin": "^1.0.4",
|
|
55
55
|
"@sanity/ui": "^1.6.0",
|
|
56
|
+
"date-fns": "^2.30.0",
|
|
56
57
|
"react-fast-compare": "^3.2.1",
|
|
57
58
|
"rxjs": "^7.8.0",
|
|
58
59
|
"rxjs-exhaustmap-with-trailing": "^2.1.1"
|
|
@@ -68,6 +69,7 @@
|
|
|
68
69
|
"@types/styled-components": "^5.1.26",
|
|
69
70
|
"@typescript-eslint/eslint-plugin": "^5.56.0",
|
|
70
71
|
"@typescript-eslint/parser": "^5.56.0",
|
|
72
|
+
"date-fns": "^2.30.0",
|
|
71
73
|
"eslint": "^8.36.0",
|
|
72
74
|
"eslint-config-prettier": "^8.8.0",
|
|
73
75
|
"eslint-config-sanity": "^6.0.0",
|
|
@@ -87,7 +89,9 @@
|
|
|
87
89
|
},
|
|
88
90
|
"peerDependencies": {
|
|
89
91
|
"react": "^18",
|
|
90
|
-
"
|
|
92
|
+
"react-is": "^18.2.0",
|
|
93
|
+
"sanity": "^3.13.0",
|
|
94
|
+
"styled-components": "^5.2"
|
|
91
95
|
},
|
|
92
96
|
"engines": {
|
|
93
97
|
"node": ">=14"
|
|
@@ -82,7 +82,7 @@ export function getFieldRefs(
|
|
|
82
82
|
const fields =
|
|
83
83
|
field.type.jsonType === 'object' ? getFieldRefs(field.type, fieldRef, depth + 1) : []
|
|
84
84
|
|
|
85
|
-
if (!isAssistSupported(field.type)) {
|
|
85
|
+
if (!isAssistSupported(field.type, true)) {
|
|
86
86
|
return fields
|
|
87
87
|
}
|
|
88
88
|
return [fieldRef, ...fields]
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import {ReactElement, ReactNode} from 'react'
|
|
2
|
+
import styled, {keyframes} from 'styled-components'
|
|
3
|
+
|
|
4
|
+
const fadeIn = keyframes`
|
|
5
|
+
0% {
|
|
6
|
+
opacity: 0;
|
|
7
|
+
transform: scale(0.75);
|
|
8
|
+
}
|
|
9
|
+
40% {
|
|
10
|
+
opacity: 0;
|
|
11
|
+
transform: scale(0.75);
|
|
12
|
+
}
|
|
13
|
+
100% {
|
|
14
|
+
opacity: 1;
|
|
15
|
+
transform: scale(1);
|
|
16
|
+
}
|
|
17
|
+
`
|
|
18
|
+
|
|
19
|
+
const FadeInDiv = styled.div`
|
|
20
|
+
animation-name: ${fadeIn};
|
|
21
|
+
animation-timing-function: ease-in-out;
|
|
22
|
+
`
|
|
23
|
+
|
|
24
|
+
export function FadeInContent({
|
|
25
|
+
children,
|
|
26
|
+
durationMs = 250,
|
|
27
|
+
}: {
|
|
28
|
+
children?: ReactNode
|
|
29
|
+
ms?: number
|
|
30
|
+
durationMs?: number
|
|
31
|
+
}): ReactElement {
|
|
32
|
+
return <FadeInDiv style={{animationDuration: `${durationMs}ms`}}>{children}</FadeInDiv>
|
|
33
|
+
}
|
|
@@ -28,7 +28,9 @@ function node(node: DocumentFieldActionItem | DocumentFieldActionGroup) {
|
|
|
28
28
|
export const assistFieldActions: DocumentFieldAction = {
|
|
29
29
|
name: 'sanity-assist-actions',
|
|
30
30
|
useAction(props) {
|
|
31
|
-
const
|
|
31
|
+
const {schemaType} = props
|
|
32
|
+
const assistSupported = useAssistSupported(props.path, schemaType)
|
|
33
|
+
|
|
32
34
|
const isDocumentLevel = props.path.length === 0
|
|
33
35
|
|
|
34
36
|
const {
|
|
@@ -47,7 +49,7 @@ export const assistFieldActions: DocumentFieldAction = {
|
|
|
47
49
|
// conditional hook _should_ be safe here since the logical path will be stable
|
|
48
50
|
isDocumentLevel
|
|
49
51
|
? // eslint-disable-next-line react-hooks/rules-of-hooks
|
|
50
|
-
useAssistDocumentContextValue(props.documentId,
|
|
52
|
+
useAssistDocumentContextValue(props.documentId, schemaType as ObjectSchemaType)
|
|
51
53
|
: // eslint-disable-next-line react-hooks/rules-of-hooks
|
|
52
54
|
useAssistDocumentContext()
|
|
53
55
|
|
|
@@ -6,30 +6,40 @@ export function isSchemaAssistEnabled(type: SchemaType) {
|
|
|
6
6
|
return !(type.options as AssistOptions | undefined)?.aiWritingAssistance?.exclude
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
export function isAssistSupported(type: SchemaType) {
|
|
9
|
+
export function isAssistSupported(type: SchemaType, allowReadonlyHidden = false) {
|
|
10
10
|
if (!isSchemaAssistEnabled(type)) {
|
|
11
11
|
return false
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
if (
|
|
14
|
+
if (isDisabled(type, allowReadonlyHidden)) {
|
|
15
15
|
return false
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
if (type.jsonType === 'array') {
|
|
19
|
-
const unsupportedArray = type.of.every((t) =>
|
|
19
|
+
const unsupportedArray = type.of.every((t) => isDisabled(t, allowReadonlyHidden))
|
|
20
20
|
return !unsupportedArray
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
if (type.jsonType === 'object') {
|
|
24
|
-
const unsupportedObject = type.fields.every((field) =>
|
|
24
|
+
const unsupportedObject = type.fields.every((field) =>
|
|
25
|
+
isDisabled(field.type, allowReadonlyHidden)
|
|
26
|
+
)
|
|
25
27
|
return !unsupportedObject
|
|
26
28
|
}
|
|
27
29
|
return true
|
|
28
30
|
}
|
|
29
31
|
|
|
30
|
-
function
|
|
32
|
+
function isDisabled(type: SchemaType, allowReadonlyHidden: boolean) {
|
|
33
|
+
const readonlyHidden = !!type.readOnly || !!type.hidden
|
|
31
34
|
return (
|
|
32
35
|
!isSchemaAssistEnabled(type) ||
|
|
36
|
+
isUnsupportedType(type) ||
|
|
37
|
+
(!allowReadonlyHidden && readonlyHidden)
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function isUnsupportedType(type: SchemaType) {
|
|
42
|
+
return (
|
|
33
43
|
type.jsonType === 'number' ||
|
|
34
44
|
type.name === 'sanity.imageCrop' ||
|
|
35
45
|
type.name === 'sanity.imageHotspot' ||
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// eslint-disable-next-line react/no-unused-prop-types
|
|
2
2
|
import {FormNodePresence} from 'sanity'
|
|
3
3
|
import {Card, Flex, Text, Tooltip} from '@sanity/ui'
|
|
4
|
-
import {
|
|
4
|
+
import {FadeInContent} from '../components/FadeInContent'
|
|
5
5
|
import {AssistAvatar} from './AssistAvatar'
|
|
6
6
|
|
|
7
7
|
export function AiFieldPresence(props: {presence: FormNodePresence}) {
|
|
@@ -17,11 +17,9 @@ export function AiFieldPresence(props: {presence: FormNodePresence}) {
|
|
|
17
17
|
</Card>
|
|
18
18
|
}
|
|
19
19
|
>
|
|
20
|
-
<
|
|
21
|
-
<
|
|
22
|
-
|
|
23
|
-
</Delay>
|
|
24
|
-
</div>
|
|
20
|
+
<FadeInContent durationMs={300}>
|
|
21
|
+
<AssistAvatar state="active" />
|
|
22
|
+
</FadeInContent>
|
|
25
23
|
</Tooltip>
|
|
26
24
|
</Card>
|
|
27
25
|
)
|
|
@@ -391,4 +391,30 @@ describe('serializeSchema', () => {
|
|
|
391
391
|
{name: 'list', title: 'String', type: 'string', values: ['a', 'b']},
|
|
392
392
|
])
|
|
393
393
|
})
|
|
394
|
+
|
|
395
|
+
test('should exclude truthy hidden and readonly', () => {
|
|
396
|
+
const schema = Schema.compile({
|
|
397
|
+
name: 'test',
|
|
398
|
+
types: [
|
|
399
|
+
{
|
|
400
|
+
type: 'document',
|
|
401
|
+
name: 'article',
|
|
402
|
+
fields: [
|
|
403
|
+
{type: 'string', name: 'title', hidden: () => true},
|
|
404
|
+
{type: 'some', name: 'some'},
|
|
405
|
+
],
|
|
406
|
+
},
|
|
407
|
+
defineType({
|
|
408
|
+
type: 'object',
|
|
409
|
+
name: 'some',
|
|
410
|
+
readOnly: true,
|
|
411
|
+
fields: [{type: 'string', name: 'title'}],
|
|
412
|
+
}),
|
|
413
|
+
],
|
|
414
|
+
})
|
|
415
|
+
|
|
416
|
+
const serializedTypes = serializeSchema(schema, {leanFormat: true})
|
|
417
|
+
|
|
418
|
+
expect(serializedTypes).toEqual([])
|
|
419
|
+
})
|
|
394
420
|
})
|
|
@@ -29,6 +29,7 @@ export function serializeSchema(schema: Schema, options?: Options): SerializedSc
|
|
|
29
29
|
.filter((t) => !(hiddenTypes.includes(t) || t.startsWith('sanity.')))
|
|
30
30
|
.map((t) => schema.get(t))
|
|
31
31
|
.filter((t): t is SchemaType => !!t)
|
|
32
|
+
.filter((t) => !t.hidden && !t.readOnly)
|
|
32
33
|
.map((t) => getSchemaStub(t, schema, options))
|
|
33
34
|
.filter((t) => {
|
|
34
35
|
if ('to' in t && t.to && !t.to.length) {
|
|
@@ -106,6 +107,7 @@ function serializeFields(
|
|
|
106
107
|
return schemaType.fields
|
|
107
108
|
.filter((f) => !['sanity.imageHotspot', 'sanity.imageCrop'].includes(f.type?.name ?? ''))
|
|
108
109
|
.filter((f) => isAssistSupported(f.type))
|
|
110
|
+
.filter((f) => !f.type.hidden && !f.type.readOnly)
|
|
109
111
|
.map((field) => serializeMember(schema, field.type, field.name, options))
|
|
110
112
|
}
|
|
111
113
|
|
package/src/components/Delay.tsx
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import {motion} from 'framer-motion'
|
|
2
|
-
import {ReactElement, ReactNode} from 'react'
|
|
3
|
-
|
|
4
|
-
export function Delay({
|
|
5
|
-
children,
|
|
6
|
-
ms = 1000,
|
|
7
|
-
durationMs = 250,
|
|
8
|
-
}: {
|
|
9
|
-
children?: ReactNode
|
|
10
|
-
ms?: number
|
|
11
|
-
durationMs?: number
|
|
12
|
-
}): ReactElement {
|
|
13
|
-
return (
|
|
14
|
-
<motion.div
|
|
15
|
-
initial={{opacity: 0, scale: 0.75}}
|
|
16
|
-
animate={{opacity: 1, scale: 1}}
|
|
17
|
-
transition={{
|
|
18
|
-
delay: ms / 1000,
|
|
19
|
-
duration: durationMs / 1000,
|
|
20
|
-
}}
|
|
21
|
-
>
|
|
22
|
-
{children}
|
|
23
|
-
</motion.div>
|
|
24
|
-
)
|
|
25
|
-
}
|