sanity-plugin-internationalized-array 1.5.0 → 1.6.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/lib/index.esm.js +10 -1
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +10 -1
- package/lib/index.js.map +1 -1
- package/lib/src/index.d.ts +23 -3
- package/package.json +4 -1
- package/src/cache.ts +2 -1
- package/src/components/InternationalizedArray.tsx +21 -8
- package/src/components/Preload.tsx +2 -2
- package/src/components/getSelectedValue.ts +29 -0
- package/src/plugin.tsx +2 -2
- package/src/schema/array.ts +11 -8
- package/src/types.ts +23 -4
package/lib/src/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type {ArraySchemaType} from 'sanity'
|
|
2
|
+
import type {FieldDefinition} from 'sanity'
|
|
2
3
|
import {Plugin as Plugin_2} from 'sanity'
|
|
3
4
|
import type {Rule} from 'sanity'
|
|
4
5
|
import type {RuleTypeConstraint} from 'sanity'
|
|
@@ -25,7 +26,8 @@ export declare type ArrayConfig = {
|
|
|
25
26
|
|
|
26
27
|
export declare type ArraySchemaWithLanguageOptions = ArraySchemaType & {
|
|
27
28
|
options: {
|
|
28
|
-
|
|
29
|
+
select?: Record<string, string>
|
|
30
|
+
languages: Language[] | LanguageCallback
|
|
29
31
|
apiVersion: string
|
|
30
32
|
}
|
|
31
33
|
}
|
|
@@ -39,12 +41,30 @@ export declare type Language = {
|
|
|
39
41
|
title: string
|
|
40
42
|
}
|
|
41
43
|
|
|
44
|
+
export declare type LanguageCallback = (
|
|
45
|
+
client: SanityClient,
|
|
46
|
+
selectedValue: Record<string, unknown>
|
|
47
|
+
) => Promise<Language[]>
|
|
48
|
+
|
|
42
49
|
export declare type PluginConfig = {
|
|
43
50
|
/**
|
|
44
51
|
* https://www.sanity.io/docs/api-versioning
|
|
45
52
|
* @defaultValue '2022-11-27'
|
|
46
53
|
*/
|
|
47
54
|
apiVersion?: string
|
|
55
|
+
/**
|
|
56
|
+
* Specify fields that should be available in the language callback:
|
|
57
|
+
* ```tsx
|
|
58
|
+
* {
|
|
59
|
+
* select: {
|
|
60
|
+
* markets: 'markets'
|
|
61
|
+
* },
|
|
62
|
+
* languages: (client, {markets}) =>
|
|
63
|
+
* query.fetch(groq`*[_type == "language" && market in $markets]{id,title}`, {markets})
|
|
64
|
+
* }
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
select?: Record<string, string>
|
|
48
68
|
/**
|
|
49
69
|
* You can give it an array of language definitions:
|
|
50
70
|
* ```tsx
|
|
@@ -72,7 +92,7 @@ export declare type PluginConfig = {
|
|
|
72
92
|
* }
|
|
73
93
|
* ```
|
|
74
94
|
*/
|
|
75
|
-
languages: Language[] |
|
|
95
|
+
languages: Language[] | LanguageCallback
|
|
76
96
|
/**
|
|
77
97
|
* Can be a string matching core field types, as well as custom ones:
|
|
78
98
|
* ```tsx
|
|
@@ -96,7 +116,7 @@ export declare type PluginConfig = {
|
|
|
96
116
|
* }
|
|
97
117
|
* ```
|
|
98
118
|
*/
|
|
99
|
-
fieldTypes: (string | RuleTypeConstraint)[]
|
|
119
|
+
fieldTypes: (string | RuleTypeConstraint | FieldDefinition)[]
|
|
100
120
|
}
|
|
101
121
|
|
|
102
122
|
export declare type Value = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sanity-plugin-internationalized-array",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Store localized fields in an array to save on attributes",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -50,6 +50,8 @@
|
|
|
50
50
|
"@sanity/icons": "^2.0.0",
|
|
51
51
|
"@sanity/incompatible-plugin": "^1.0.4",
|
|
52
52
|
"@sanity/ui": "^1.0.0",
|
|
53
|
+
"fast-deep-equal": "^3.1.3",
|
|
54
|
+
"lodash.get": "^4.4.2",
|
|
53
55
|
"suspend-react": "^0.0.8"
|
|
54
56
|
},
|
|
55
57
|
"devDependencies": {
|
|
@@ -58,6 +60,7 @@
|
|
|
58
60
|
"@sanity/pkg-utils": "^1.18.0",
|
|
59
61
|
"@sanity/plugin-kit": "^2.1.17",
|
|
60
62
|
"@sanity/semantic-release-preset": "^2.0.2",
|
|
63
|
+
"@types/lodash.get": "^4.4.7",
|
|
61
64
|
"@types/styled-components": "^5.1.26",
|
|
62
65
|
"@typescript-eslint/eslint-plugin": "^5.44.0",
|
|
63
66
|
"@typescript-eslint/parser": "^5.44.0",
|
package/src/cache.ts
CHANGED
|
@@ -15,4 +15,5 @@ export const preload = (fn: () => Promise<Language[]>) =>
|
|
|
15
15
|
export const clear = () => suspend.clear([version, namespace])
|
|
16
16
|
|
|
17
17
|
// https://github.com/pmndrs/suspend-react#peeking-into-entries-outside-of-suspense
|
|
18
|
-
export const peek = (
|
|
18
|
+
export const peek = (selectedValue: Record<string, unknown>) =>
|
|
19
|
+
suspend.peek([version, namespace, selectedValue]) as Language[] | undefined
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {useCallback, useDeferredValue, useEffect, useMemo} from 'react'
|
|
2
2
|
import {
|
|
3
3
|
insert,
|
|
4
4
|
set,
|
|
@@ -7,16 +7,19 @@ import {
|
|
|
7
7
|
ArrayOfObjectsItem,
|
|
8
8
|
ArrayOfObjectsInputProps,
|
|
9
9
|
useClient,
|
|
10
|
+
useFormBuilder,
|
|
10
11
|
} from 'sanity'
|
|
11
12
|
import {Button, Grid, Stack, useToast} from '@sanity/ui'
|
|
12
13
|
import {AddIcon} from '@sanity/icons'
|
|
13
14
|
import {suspend} from 'suspend-react'
|
|
15
|
+
import equal from 'fast-deep-equal'
|
|
14
16
|
|
|
15
17
|
import type {Value, ArraySchemaWithLanguageOptions} from '../types'
|
|
16
18
|
import Feedback from './Feedback'
|
|
17
19
|
// TODO: Move this provider to the root component
|
|
18
20
|
import {LanguageProvider} from './languageContext'
|
|
19
21
|
import {namespace, version} from '../cache'
|
|
22
|
+
import {getSelectedValue} from './getSelectedValue'
|
|
20
23
|
|
|
21
24
|
export type InternationalizedArrayProps = ArrayOfObjectsInputProps<
|
|
22
25
|
Value,
|
|
@@ -28,18 +31,28 @@ export default function InternationalizedArray(props: InternationalizedArrayProp
|
|
|
28
31
|
const readOnly = typeof schemaType.readOnly === 'boolean' ? schemaType.readOnly : false
|
|
29
32
|
const {options} = schemaType
|
|
30
33
|
const toast = useToast()
|
|
34
|
+
const {value: document} = useFormBuilder()
|
|
35
|
+
const deferredDocument = useDeferredValue(document)
|
|
36
|
+
const selectedValue = useMemo(
|
|
37
|
+
() => getSelectedValue(options.select, deferredDocument),
|
|
38
|
+
[options.select, deferredDocument]
|
|
39
|
+
)
|
|
31
40
|
|
|
32
41
|
const {apiVersion} = options
|
|
33
42
|
const client = useClient({apiVersion})
|
|
34
43
|
const languages = Array.isArray(options.languages)
|
|
35
44
|
? options.languages
|
|
36
|
-
:
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
: suspend(
|
|
46
|
+
// eslint-disable-next-line require-await
|
|
47
|
+
async () => {
|
|
48
|
+
if (typeof options.languages === 'function') {
|
|
49
|
+
return options.languages(client, selectedValue)
|
|
50
|
+
}
|
|
51
|
+
return options.languages
|
|
52
|
+
},
|
|
53
|
+
[version, namespace, selectedValue],
|
|
54
|
+
{equal}
|
|
55
|
+
)
|
|
43
56
|
|
|
44
57
|
const handleAddLanguage = useCallback(
|
|
45
58
|
(languageId?: string) => {
|
|
@@ -7,10 +7,10 @@ export default memo(function Preload(
|
|
|
7
7
|
props: Required<Pick<PluginConfig, 'apiVersion' | 'languages'>>
|
|
8
8
|
) {
|
|
9
9
|
const client = useClient({apiVersion: props.apiVersion})
|
|
10
|
-
if (!Array.isArray(peek())) {
|
|
10
|
+
if (!Array.isArray(peek({}))) {
|
|
11
11
|
// eslint-disable-next-line require-await
|
|
12
12
|
preload(async () =>
|
|
13
|
-
Array.isArray(props.languages) ? props.languages : props.languages(client)
|
|
13
|
+
Array.isArray(props.languages) ? props.languages : props.languages(client, {})
|
|
14
14
|
)
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {get} from 'lodash'
|
|
2
|
+
|
|
3
|
+
export const getSelectedValue = (
|
|
4
|
+
select: Record<string, string> | undefined,
|
|
5
|
+
document:
|
|
6
|
+
| {
|
|
7
|
+
[x: string]: unknown
|
|
8
|
+
}
|
|
9
|
+
| undefined
|
|
10
|
+
): Record<string, unknown> => {
|
|
11
|
+
if (!select || !document) {
|
|
12
|
+
return {}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const selection: Record<string, string> = select || {}
|
|
16
|
+
const selectedValue: Record<string, unknown> = {}
|
|
17
|
+
for (const [key, path] of Object.entries(selection)) {
|
|
18
|
+
let value = get(document, path)
|
|
19
|
+
if (Array.isArray(value)) {
|
|
20
|
+
// If there are references in the array, ensure they have `_ref` set, otherwise they are considered empty and can safely be ignored
|
|
21
|
+
value = value.filter((item) =>
|
|
22
|
+
typeof item === 'object' ? item?._type === 'reference' && '_ref' in item : true
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
selectedValue[key] = value
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return selectedValue
|
|
29
|
+
}
|
package/src/plugin.tsx
CHANGED
|
@@ -11,7 +11,7 @@ const CONFIG_DEFAULT: PluginConfig = {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export const internationalizedArray = definePlugin<PluginConfig>((config = CONFIG_DEFAULT) => {
|
|
14
|
-
const {apiVersion = '2022-11-27', languages, fieldTypes} = {...CONFIG_DEFAULT, ...config}
|
|
14
|
+
const {apiVersion = '2022-11-27', select, languages, fieldTypes} = {...CONFIG_DEFAULT, ...config}
|
|
15
15
|
|
|
16
16
|
return {
|
|
17
17
|
name: 'sanity-plugin-internationalized-array',
|
|
@@ -30,7 +30,7 @@ export const internationalizedArray = definePlugin<PluginConfig>((config = CONFI
|
|
|
30
30
|
},
|
|
31
31
|
schema: {
|
|
32
32
|
types: [
|
|
33
|
-
...fieldTypes.map((type) => array({type, apiVersion, languages})),
|
|
33
|
+
...fieldTypes.map((type) => array({type, apiVersion, select, languages})),
|
|
34
34
|
...fieldTypes.map((type) => object({type})),
|
|
35
35
|
],
|
|
36
36
|
},
|
package/src/schema/array.ts
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
/* eslint-disable no-nested-ternary */
|
|
2
|
-
import {defineField, type FieldDefinition, type Rule
|
|
2
|
+
import {defineField, type FieldDefinition, type Rule} from 'sanity'
|
|
3
3
|
import {peek} from '../cache'
|
|
4
4
|
|
|
5
5
|
import {createFieldName} from '../components/createFieldName'
|
|
6
|
+
import {getSelectedValue} from '../components/getSelectedValue'
|
|
6
7
|
import InternationalizedArray from '../components/InternationalizedArray'
|
|
7
|
-
import {Language, Value} from '../types'
|
|
8
|
+
import {Language, LanguageCallback, Value} from '../types'
|
|
8
9
|
|
|
9
10
|
type ArrayFactoryConfig = {
|
|
10
11
|
apiVersion: string
|
|
11
|
-
|
|
12
|
+
select?: Record<string, string>
|
|
13
|
+
languages: Language[] | LanguageCallback
|
|
12
14
|
type: string | FieldDefinition
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
export default (config: ArrayFactoryConfig): FieldDefinition<'array'> => {
|
|
16
|
-
const {apiVersion, languages, type} = config
|
|
18
|
+
const {apiVersion, select, languages, type} = config
|
|
17
19
|
const typeName = typeof type === `string` ? type : type.name
|
|
18
20
|
const arrayName = createFieldName(typeName)
|
|
19
21
|
const objectName = createFieldName(typeName, true)
|
|
@@ -27,7 +29,7 @@ export default (config: ArrayFactoryConfig): FieldDefinition<'array'> => {
|
|
|
27
29
|
components: {
|
|
28
30
|
input: InternationalizedArray,
|
|
29
31
|
},
|
|
30
|
-
options: {apiVersion, languages},
|
|
32
|
+
options: {apiVersion, select, languages},
|
|
31
33
|
// TODO: Resolve this typing issue with the inner object
|
|
32
34
|
// @ts-ignore
|
|
33
35
|
of: [
|
|
@@ -43,12 +45,13 @@ export default (config: ArrayFactoryConfig): FieldDefinition<'array'> => {
|
|
|
43
45
|
return true
|
|
44
46
|
}
|
|
45
47
|
|
|
48
|
+
const selectedValue = getSelectedValue(select, context.document)
|
|
46
49
|
const client = context.getClient({apiVersion})
|
|
47
50
|
const contextLanguages: Language[] = Array.isArray(context?.type?.options?.languages)
|
|
48
51
|
? context!.type!.options.languages
|
|
49
|
-
: Array.isArray(peek())
|
|
50
|
-
? peek()
|
|
51
|
-
: await context?.type?.options.languages(client)
|
|
52
|
+
: Array.isArray(peek(selectedValue))
|
|
53
|
+
? peek(selectedValue)
|
|
54
|
+
: await context?.type?.options.languages(client, selectedValue)
|
|
52
55
|
|
|
53
56
|
if (value && value.length > contextLanguages.length) {
|
|
54
57
|
return `Cannot be more than ${
|
package/src/types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {Rule, ArraySchemaType, RuleTypeConstraint, SanityClient} from 'sanity'
|
|
1
|
+
import type {Rule, ArraySchemaType, RuleTypeConstraint, SanityClient, FieldDefinition} from 'sanity'
|
|
2
2
|
|
|
3
3
|
export type Language = {
|
|
4
4
|
id: Intl.UnicodeBCP47LocaleIdentifier
|
|
@@ -24,12 +24,30 @@ export type Value = {
|
|
|
24
24
|
value?: string
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
export type LanguageCallback = (
|
|
28
|
+
client: SanityClient,
|
|
29
|
+
selectedValue: Record<string, unknown>
|
|
30
|
+
) => Promise<Language[]>
|
|
31
|
+
|
|
27
32
|
export type PluginConfig = {
|
|
28
33
|
/**
|
|
29
34
|
* https://www.sanity.io/docs/api-versioning
|
|
30
35
|
* @defaultValue '2022-11-27'
|
|
31
36
|
*/
|
|
32
37
|
apiVersion?: string
|
|
38
|
+
/**
|
|
39
|
+
* Specify fields that should be available in the language callback:
|
|
40
|
+
* ```tsx
|
|
41
|
+
* {
|
|
42
|
+
* select: {
|
|
43
|
+
* markets: 'markets'
|
|
44
|
+
* },
|
|
45
|
+
* languages: (client, {markets}) =>
|
|
46
|
+
* query.fetch(groq`*[_type == "language" && market in $markets]{id,title}`, {markets})
|
|
47
|
+
* }
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
select?: Record<string, string>
|
|
33
51
|
/**
|
|
34
52
|
* You can give it an array of language definitions:
|
|
35
53
|
* ```tsx
|
|
@@ -57,7 +75,7 @@ export type PluginConfig = {
|
|
|
57
75
|
* }
|
|
58
76
|
* ```
|
|
59
77
|
*/
|
|
60
|
-
languages: Language[] |
|
|
78
|
+
languages: Language[] | LanguageCallback
|
|
61
79
|
/**
|
|
62
80
|
* Can be a string matching core field types, as well as custom ones:
|
|
63
81
|
* ```tsx
|
|
@@ -81,12 +99,13 @@ export type PluginConfig = {
|
|
|
81
99
|
* }
|
|
82
100
|
* ```
|
|
83
101
|
*/
|
|
84
|
-
fieldTypes: (string | RuleTypeConstraint)[]
|
|
102
|
+
fieldTypes: (string | RuleTypeConstraint | FieldDefinition)[]
|
|
85
103
|
}
|
|
86
104
|
|
|
87
105
|
export type ArraySchemaWithLanguageOptions = ArraySchemaType & {
|
|
88
106
|
options: {
|
|
89
|
-
|
|
107
|
+
select?: Record<string, string>
|
|
108
|
+
languages: Language[] | LanguageCallback
|
|
90
109
|
apiVersion: string
|
|
91
110
|
}
|
|
92
111
|
}
|