sanity-plugin-internationalized-array 2.0.0 → 2.0.1-canary.1
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/lib/index.d.mts +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.esm.js +123 -109
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +122 -109
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +123 -109
- package/lib/index.mjs.map +1 -1
- package/package.json +25 -31
- package/src/cache.ts +1 -1
- package/src/components/AddButtons.tsx +4 -1
- package/src/components/DocumentAddButtons.tsx +53 -52
- package/src/components/InternationalizedArray.tsx +3 -1
- package/src/components/InternationalizedArrayContext.tsx +10 -19
- package/src/fieldActions/index.ts +8 -2
- package/src/plugin.tsx +6 -4
- package/src/schema/array.ts +7 -1
- package/src/schema/object.ts +1 -1
- package/src/types.ts +1 -1
- package/src/utils/createAddLanguagePatches.ts +18 -10
- package/src/utils/getDocumentsToTranslate.ts +66 -0
|
@@ -2,12 +2,8 @@ import {useLanguageFilterStudioContext} from '@sanity/language-filter'
|
|
|
2
2
|
import {Stack} from '@sanity/ui'
|
|
3
3
|
import equal from 'fast-deep-equal'
|
|
4
4
|
import {createContext, useContext, useDeferredValue, useMemo} from 'react'
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
useClient,
|
|
8
|
-
useFormBuilder,
|
|
9
|
-
useWorkspace,
|
|
10
|
-
} from 'sanity'
|
|
5
|
+
import {type ObjectInputProps, useClient, useWorkspace} from 'sanity'
|
|
6
|
+
import {useDocumentPane} from 'sanity/structure'
|
|
11
7
|
import {suspend} from 'suspend-react'
|
|
12
8
|
|
|
13
9
|
import {namespace, version} from '../cache'
|
|
@@ -46,8 +42,8 @@ export function InternationalizedArrayProvider(
|
|
|
46
42
|
|
|
47
43
|
const client = useClient({apiVersion: internationalizedArray.apiVersion})
|
|
48
44
|
const workspace = useWorkspace()
|
|
49
|
-
const {
|
|
50
|
-
const deferredDocument = useDeferredValue(
|
|
45
|
+
const {formState} = useDocumentPane()
|
|
46
|
+
const deferredDocument = useDeferredValue(formState?.value)
|
|
51
47
|
const selectedValue = useMemo(
|
|
52
48
|
() => getSelectedValue(internationalizedArray.select, deferredDocument),
|
|
53
49
|
[internationalizedArray.select, deferredDocument]
|
|
@@ -87,21 +83,16 @@ export function InternationalizedArrayProvider(
|
|
|
87
83
|
|
|
88
84
|
const showDocumentButtons =
|
|
89
85
|
internationalizedArray.buttonLocations.includes('document')
|
|
86
|
+
const context = useMemo(
|
|
87
|
+
() => ({...internationalizedArray, languages, filteredLanguages}),
|
|
88
|
+
[filteredLanguages, internationalizedArray, languages]
|
|
89
|
+
)
|
|
90
90
|
|
|
91
91
|
return (
|
|
92
|
-
<InternationalizedArrayContext.Provider
|
|
93
|
-
value={{
|
|
94
|
-
...internationalizedArray,
|
|
95
|
-
languages,
|
|
96
|
-
filteredLanguages,
|
|
97
|
-
}}
|
|
98
|
-
>
|
|
92
|
+
<InternationalizedArrayContext.Provider value={context}>
|
|
99
93
|
{showDocumentButtons ? (
|
|
100
94
|
<Stack space={5}>
|
|
101
|
-
<DocumentAddButtons
|
|
102
|
-
schemaType={props.schemaType}
|
|
103
|
-
value={props.value}
|
|
104
|
-
/>
|
|
95
|
+
<DocumentAddButtons value={props.value} />
|
|
105
96
|
{props.renderDefault(props)}
|
|
106
97
|
</Stack>
|
|
107
98
|
) : (
|
|
@@ -18,7 +18,10 @@ import {createAddLanguagePatches} from '../utils/createAddLanguagePatches'
|
|
|
18
18
|
|
|
19
19
|
const createTranslateFieldActions: (
|
|
20
20
|
fieldActionProps: DocumentFieldActionProps,
|
|
21
|
-
context: {
|
|
21
|
+
context: {
|
|
22
|
+
languages: Language[]
|
|
23
|
+
filteredLanguages: Language[]
|
|
24
|
+
}
|
|
22
25
|
) => DocumentFieldActionItem[] = (
|
|
23
26
|
fieldActionProps,
|
|
24
27
|
{languages, filteredLanguages}
|
|
@@ -61,7 +64,10 @@ const createTranslateFieldActions: (
|
|
|
61
64
|
|
|
62
65
|
const AddMissingTranslationsFieldAction: (
|
|
63
66
|
fieldActionProps: DocumentFieldActionProps,
|
|
64
|
-
context: {
|
|
67
|
+
context: {
|
|
68
|
+
languages: Language[]
|
|
69
|
+
filteredLanguages: Language[]
|
|
70
|
+
}
|
|
65
71
|
) => DocumentFieldActionItem = (
|
|
66
72
|
fieldActionProps,
|
|
67
73
|
{languages, filteredLanguages}
|
package/src/plugin.tsx
CHANGED
|
@@ -62,10 +62,12 @@ export const internationalizedArray = definePlugin<PluginConfig>((config) => {
|
|
|
62
62
|
return props.renderDefault(props)
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
return
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
return (
|
|
66
|
+
<InternationalizedArrayProvider
|
|
67
|
+
{...props}
|
|
68
|
+
internationalizedArray={pluginConfig}
|
|
69
|
+
/>
|
|
70
|
+
)
|
|
69
71
|
},
|
|
70
72
|
},
|
|
71
73
|
},
|
package/src/schema/array.ts
CHANGED
|
@@ -35,7 +35,12 @@ export default (config: ArrayFactoryConfig): FieldDefinition<'array'> => {
|
|
|
35
35
|
input: InternationalizedArray,
|
|
36
36
|
},
|
|
37
37
|
// These options are required for validation rules – not the custom input component
|
|
38
|
-
options: {
|
|
38
|
+
options: {
|
|
39
|
+
// @ts-expect-error - find out why it fails
|
|
40
|
+
apiVersion,
|
|
41
|
+
select,
|
|
42
|
+
languages,
|
|
43
|
+
},
|
|
39
44
|
of: [
|
|
40
45
|
defineField({
|
|
41
46
|
...(typeof type === 'string' ? {} : type),
|
|
@@ -43,6 +48,7 @@ export default (config: ArrayFactoryConfig): FieldDefinition<'array'> => {
|
|
|
43
48
|
type: objectName,
|
|
44
49
|
}),
|
|
45
50
|
],
|
|
51
|
+
// @ts-expect-error - find out why it fails
|
|
46
52
|
validation: (rule: Rule) =>
|
|
47
53
|
rule.custom<Value[]>(async (value, context) => {
|
|
48
54
|
if (!value) {
|
package/src/schema/object.ts
CHANGED
|
@@ -18,9 +18,9 @@ export default (config: ObjectFactoryConfig): FieldDefinition<'object'> => {
|
|
|
18
18
|
title: `Internationalized array ${type}`,
|
|
19
19
|
type: 'object',
|
|
20
20
|
components: {
|
|
21
|
+
// @ts-expect-error - find out why it fails
|
|
21
22
|
item: InternationalizedInput,
|
|
22
23
|
},
|
|
23
|
-
// @ts-expect-error - Address this typing issue with the inner object
|
|
24
24
|
fields: [
|
|
25
25
|
typeof type === `string`
|
|
26
26
|
? // Define a simple field if all we have is the name as a string
|
package/src/types.ts
CHANGED
|
@@ -31,16 +31,24 @@ export function createAddLanguagePatches(config: AddConfig): FormInsertPatch[] {
|
|
|
31
31
|
const itemBase = {_type: createValueSchemaTypeName(schemaType)}
|
|
32
32
|
|
|
33
33
|
// Create new items
|
|
34
|
-
const
|
|
35
|
-
Array.isArray(addLanguageKeys) && addLanguageKeys.length > 0
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
34
|
+
const getNewItems = () => {
|
|
35
|
+
if (Array.isArray(addLanguageKeys) && addLanguageKeys.length > 0) {
|
|
36
|
+
return addLanguageKeys.map((id) => ({
|
|
37
|
+
...itemBase,
|
|
38
|
+
_key: id,
|
|
39
|
+
}))
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return filteredLanguages
|
|
43
|
+
.filter((language) =>
|
|
44
|
+
value?.length ? !value.find((v) => v._key === language.id) : true
|
|
45
|
+
)
|
|
46
|
+
.map((language) => ({
|
|
47
|
+
...itemBase,
|
|
48
|
+
_key: language.id,
|
|
49
|
+
}))
|
|
50
|
+
}
|
|
51
|
+
const newItems = getNewItems()
|
|
44
52
|
|
|
45
53
|
// Insert new items in the correct order
|
|
46
54
|
const languagesInUse = value?.length ? value.map((v) => v) : []
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import {SanityDocument} from 'sanity'
|
|
2
|
+
|
|
3
|
+
export interface DocumentsToTranslate {
|
|
4
|
+
path: (string | number)[]
|
|
5
|
+
pathString: string
|
|
6
|
+
_key: string
|
|
7
|
+
_type: string
|
|
8
|
+
[key: string]: unknown
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const getDocumentsToTranslate = (
|
|
12
|
+
value: SanityDocument | unknown,
|
|
13
|
+
rootPath: (string | number)[] = []
|
|
14
|
+
): DocumentsToTranslate[] => {
|
|
15
|
+
if (Array.isArray(value)) {
|
|
16
|
+
const arrayRootPath = [...rootPath]
|
|
17
|
+
|
|
18
|
+
// if item contains internationalized return array
|
|
19
|
+
const internationalizedValues = value.filter((item) => {
|
|
20
|
+
if (Array.isArray(item)) return false
|
|
21
|
+
|
|
22
|
+
if (typeof item === 'object') {
|
|
23
|
+
const type = item?._type as string | undefined
|
|
24
|
+
return (
|
|
25
|
+
type?.startsWith('internationalizedArray') && type?.endsWith('Value')
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
return false
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
if (internationalizedValues.length > 0) {
|
|
32
|
+
return internationalizedValues.map((internationalizedValue) => {
|
|
33
|
+
return {
|
|
34
|
+
...internationalizedValue,
|
|
35
|
+
path: arrayRootPath,
|
|
36
|
+
pathString: arrayRootPath.join('.'),
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (value.length > 0) {
|
|
42
|
+
return value
|
|
43
|
+
.map((item, index) =>
|
|
44
|
+
getDocumentsToTranslate(item, [...arrayRootPath, index])
|
|
45
|
+
)
|
|
46
|
+
.flat()
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return []
|
|
50
|
+
}
|
|
51
|
+
if (typeof value === 'object' && value) {
|
|
52
|
+
const startsWithUnderscoreRegex = /^_/
|
|
53
|
+
const itemKeys = Object.keys(value).filter(
|
|
54
|
+
(key) => !key.match(startsWithUnderscoreRegex)
|
|
55
|
+
) as (keyof typeof value)[]
|
|
56
|
+
|
|
57
|
+
return itemKeys
|
|
58
|
+
.map((item) => {
|
|
59
|
+
const selectedValue = value[item] as unknown
|
|
60
|
+
const path = [...rootPath, item]
|
|
61
|
+
return getDocumentsToTranslate(selectedValue, path)
|
|
62
|
+
})
|
|
63
|
+
.flat()
|
|
64
|
+
}
|
|
65
|
+
return []
|
|
66
|
+
}
|