sanity-plugin-internationalized-array 1.4.1 → 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 +117 -6
- package/package.json +20 -16
- package/src/cache.ts +19 -0
- package/src/components/InternationalizedArray.tsx +30 -22
- package/src/components/Preload.tsx +18 -0
- package/src/components/getSelectedValue.ts +29 -0
- package/src/index.ts +2 -0
- package/src/plugin.tsx +19 -4
- package/src/schema/array.ts +17 -7
- package/src/types.ts +80 -6
package/lib/src/index.d.ts
CHANGED
|
@@ -1,16 +1,127 @@
|
|
|
1
|
+
import type {ArraySchemaType} from 'sanity'
|
|
2
|
+
import type {FieldDefinition} from 'sanity'
|
|
1
3
|
import {Plugin as Plugin_2} from 'sanity'
|
|
2
|
-
import {
|
|
4
|
+
import type {Rule} from 'sanity'
|
|
5
|
+
import type {RuleTypeConstraint} from 'sanity'
|
|
6
|
+
import type {SanityClient} from 'sanity'
|
|
7
|
+
|
|
8
|
+
export declare type AllowedType = 'string' | 'number' | 'boolean' | 'text' | 'reference'
|
|
9
|
+
|
|
10
|
+
export declare type ArrayConfig = {
|
|
11
|
+
name: string
|
|
12
|
+
type: AllowedType
|
|
13
|
+
languages: Language[]
|
|
14
|
+
title?: string
|
|
15
|
+
group?: string
|
|
16
|
+
hidden?: boolean | (() => boolean)
|
|
17
|
+
readOnly?: boolean | (() => boolean)
|
|
18
|
+
validation?: Rule | Rule[]
|
|
19
|
+
field?: {
|
|
20
|
+
[key: string]: any
|
|
21
|
+
options: {
|
|
22
|
+
[key: string]: any
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export declare type ArraySchemaWithLanguageOptions = ArraySchemaType & {
|
|
28
|
+
options: {
|
|
29
|
+
select?: Record<string, string>
|
|
30
|
+
languages: Language[] | LanguageCallback
|
|
31
|
+
apiVersion: string
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export declare const clear: () => void
|
|
3
36
|
|
|
4
37
|
export declare const internationalizedArray: Plugin_2<PluginConfig>
|
|
5
38
|
|
|
6
|
-
declare type Language = {
|
|
7
|
-
id:
|
|
39
|
+
export declare type Language = {
|
|
40
|
+
id: Intl.UnicodeBCP47LocaleIdentifier
|
|
8
41
|
title: string
|
|
9
42
|
}
|
|
10
43
|
|
|
11
|
-
declare type
|
|
12
|
-
|
|
13
|
-
|
|
44
|
+
export declare type LanguageCallback = (
|
|
45
|
+
client: SanityClient,
|
|
46
|
+
selectedValue: Record<string, unknown>
|
|
47
|
+
) => Promise<Language[]>
|
|
48
|
+
|
|
49
|
+
export declare type PluginConfig = {
|
|
50
|
+
/**
|
|
51
|
+
* https://www.sanity.io/docs/api-versioning
|
|
52
|
+
* @defaultValue '2022-11-27'
|
|
53
|
+
*/
|
|
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>
|
|
68
|
+
/**
|
|
69
|
+
* You can give it an array of language definitions:
|
|
70
|
+
* ```tsx
|
|
71
|
+
* {
|
|
72
|
+
* languages: [
|
|
73
|
+
* {id: 'en', title: 'English'},
|
|
74
|
+
* {id: 'fr', title: 'French'}
|
|
75
|
+
* ]
|
|
76
|
+
* }
|
|
77
|
+
* ```
|
|
78
|
+
* You can load them async by passing a function that returns a promise:
|
|
79
|
+
* ```tsx
|
|
80
|
+
* {
|
|
81
|
+
* languages: async () => {
|
|
82
|
+
* const response = await fetch('https://example.com/languages')
|
|
83
|
+
* return response.json()
|
|
84
|
+
* }
|
|
85
|
+
* }
|
|
86
|
+
* ```
|
|
87
|
+
* You can query your dataset for languages::
|
|
88
|
+
* ```tsx
|
|
89
|
+
* {
|
|
90
|
+
* languages: (client) =>
|
|
91
|
+
* query.fetch(groq`*[_type == "language"]{id,title}`)
|
|
92
|
+
* }
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
languages: Language[] | LanguageCallback
|
|
96
|
+
/**
|
|
97
|
+
* Can be a string matching core field types, as well as custom ones:
|
|
98
|
+
* ```tsx
|
|
99
|
+
* {
|
|
100
|
+
* fieldTypes: [
|
|
101
|
+
* "date", "datetime", "file", "image", "number", "string", "text", "url"
|
|
102
|
+
* ]
|
|
103
|
+
* }
|
|
104
|
+
* ```
|
|
105
|
+
* You can also define a type directly:
|
|
106
|
+
* ```tsx
|
|
107
|
+
* {
|
|
108
|
+
* fieldTypes: [
|
|
109
|
+
* defineField({
|
|
110
|
+
* name: 'featuredProduct',
|
|
111
|
+
* type: 'reference',
|
|
112
|
+
* to: [{type: 'product'}]
|
|
113
|
+
* hidden: (({document}) => !document?.title)
|
|
114
|
+
* })
|
|
115
|
+
* ]
|
|
116
|
+
* }
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
fieldTypes: (string | RuleTypeConstraint | FieldDefinition)[]
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export declare type Value = {
|
|
123
|
+
_key: string
|
|
124
|
+
value?: string
|
|
14
125
|
}
|
|
15
126
|
|
|
16
127
|
export {}
|
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",
|
|
@@ -47,39 +47,43 @@
|
|
|
47
47
|
"watch": "pkg-utils watch"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@sanity/icons": "^
|
|
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",
|
|
55
|
+
"suspend-react": "^0.0.8"
|
|
53
56
|
},
|
|
54
57
|
"devDependencies": {
|
|
55
|
-
"@commitlint/cli": "^17.
|
|
56
|
-
"@commitlint/config-conventional": "^17.
|
|
58
|
+
"@commitlint/cli": "^17.3.0",
|
|
59
|
+
"@commitlint/config-conventional": "^17.3.0",
|
|
57
60
|
"@sanity/pkg-utils": "^1.18.0",
|
|
58
|
-
"@sanity/plugin-kit": "^2.1.
|
|
61
|
+
"@sanity/plugin-kit": "^2.1.17",
|
|
59
62
|
"@sanity/semantic-release-preset": "^2.0.2",
|
|
60
|
-
"@
|
|
63
|
+
"@types/lodash.get": "^4.4.7",
|
|
61
64
|
"@types/styled-components": "^5.1.26",
|
|
62
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
63
|
-
"@typescript-eslint/parser": "^5.
|
|
64
|
-
"eslint": "^8.
|
|
65
|
+
"@typescript-eslint/eslint-plugin": "^5.44.0",
|
|
66
|
+
"@typescript-eslint/parser": "^5.44.0",
|
|
67
|
+
"eslint": "^8.28.0",
|
|
65
68
|
"eslint-config-prettier": "^8.5.0",
|
|
66
69
|
"eslint-config-sanity": "^6.0.0",
|
|
67
70
|
"eslint-plugin-prettier": "^4.2.1",
|
|
68
|
-
"eslint-plugin-react": "^7.31.
|
|
71
|
+
"eslint-plugin-react": "^7.31.11",
|
|
69
72
|
"eslint-plugin-react-hooks": "^4.6.0",
|
|
70
73
|
"husky": "^8.0.2",
|
|
71
|
-
"lint-staged": "^13.0.
|
|
72
|
-
"prettier": "^2.
|
|
74
|
+
"lint-staged": "^13.0.4",
|
|
75
|
+
"prettier": "^2.8.0",
|
|
73
76
|
"prettier-plugin-packagejson": "^2.3.0",
|
|
74
77
|
"react": "^18",
|
|
75
78
|
"rimraf": "^3.0.2",
|
|
76
|
-
"sanity": "3.0.0-rc.
|
|
79
|
+
"sanity": "3.0.0-rc.3",
|
|
80
|
+
"styled-components": "^5.3.6",
|
|
77
81
|
"typescript": "^4.9.3"
|
|
78
82
|
},
|
|
79
83
|
"peerDependencies": {
|
|
80
|
-
"@sanity/ui": "1.0.0-beta.32",
|
|
81
84
|
"react": "^18",
|
|
82
|
-
"sanity": "dev-preview || 3.0.0-rc.
|
|
85
|
+
"sanity": "dev-preview || 3.0.0-rc.3 || ^3.0.0",
|
|
86
|
+
"styled-components": "^5.2"
|
|
83
87
|
},
|
|
84
88
|
"engines": {
|
|
85
89
|
"node": ">=14"
|
package/src/cache.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
|
2
|
+
|
|
3
|
+
import * as suspend from 'suspend-react'
|
|
4
|
+
import type {Language} from './types'
|
|
5
|
+
|
|
6
|
+
export const namespace = 'sanity-plugin-internationalized-array'
|
|
7
|
+
|
|
8
|
+
export const version = 'v0'
|
|
9
|
+
|
|
10
|
+
// https://github.com/pmndrs/suspend-react#preloading
|
|
11
|
+
export const preload = (fn: () => Promise<Language[]>) =>
|
|
12
|
+
suspend.preload(() => fn(), [version, namespace])
|
|
13
|
+
|
|
14
|
+
// https://github.com/pmndrs/suspend-react#cache-busting
|
|
15
|
+
export const clear = () => suspend.clear([version, namespace])
|
|
16
|
+
|
|
17
|
+
// https://github.com/pmndrs/suspend-react#peeking-into-entries-outside-of-suspense
|
|
18
|
+
export const peek = (selectedValue: Record<string, unknown>) =>
|
|
19
|
+
suspend.peek([version, namespace, selectedValue]) as Language[] | undefined
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {useCallback, useEffect, useMemo} from 'react'
|
|
1
|
+
import React, {useCallback, useDeferredValue, useEffect, useMemo} from 'react'
|
|
2
2
|
import {
|
|
3
3
|
insert,
|
|
4
4
|
set,
|
|
@@ -6,14 +6,20 @@ import {
|
|
|
6
6
|
ArrayOfObjectsItemMember,
|
|
7
7
|
ArrayOfObjectsItem,
|
|
8
8
|
ArrayOfObjectsInputProps,
|
|
9
|
+
useClient,
|
|
10
|
+
useFormBuilder,
|
|
9
11
|
} from 'sanity'
|
|
10
|
-
import {Button, Grid,
|
|
12
|
+
import {Button, Grid, Stack, useToast} from '@sanity/ui'
|
|
11
13
|
import {AddIcon} from '@sanity/icons'
|
|
14
|
+
import {suspend} from 'suspend-react'
|
|
15
|
+
import equal from 'fast-deep-equal'
|
|
12
16
|
|
|
13
|
-
import {
|
|
17
|
+
import type {Value, ArraySchemaWithLanguageOptions} from '../types'
|
|
14
18
|
import Feedback from './Feedback'
|
|
15
19
|
// TODO: Move this provider to the root component
|
|
16
20
|
import {LanguageProvider} from './languageContext'
|
|
21
|
+
import {namespace, version} from '../cache'
|
|
22
|
+
import {getSelectedValue} from './getSelectedValue'
|
|
17
23
|
|
|
18
24
|
export type InternationalizedArrayProps = ArrayOfObjectsInputProps<
|
|
19
25
|
Value,
|
|
@@ -25,22 +31,28 @@ export default function InternationalizedArray(props: InternationalizedArrayProp
|
|
|
25
31
|
const readOnly = typeof schemaType.readOnly === 'boolean' ? schemaType.readOnly : false
|
|
26
32
|
const {options} = schemaType
|
|
27
33
|
const toast = useToast()
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
|
|
34
|
+
const {value: document} = useFormBuilder()
|
|
35
|
+
const deferredDocument = useDeferredValue(document)
|
|
36
|
+
const selectedValue = useMemo(
|
|
37
|
+
() => getSelectedValue(options.select, deferredDocument),
|
|
38
|
+
[options.select, deferredDocument]
|
|
31
39
|
)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
|
|
41
|
+
const {apiVersion} = options
|
|
42
|
+
const client = useClient({apiVersion})
|
|
43
|
+
const languages = Array.isArray(options.languages)
|
|
44
|
+
? options.languages
|
|
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
|
+
)
|
|
44
56
|
|
|
45
57
|
const handleAddLanguage = useCallback(
|
|
46
58
|
(languageId?: string) => {
|
|
@@ -169,10 +181,6 @@ export default function InternationalizedArray(props: InternationalizedArrayProp
|
|
|
169
181
|
return <Feedback />
|
|
170
182
|
}
|
|
171
183
|
|
|
172
|
-
if (!languages) {
|
|
173
|
-
return <Spinner />
|
|
174
|
-
}
|
|
175
|
-
|
|
176
184
|
return (
|
|
177
185
|
<LanguageProvider value={{languages}}>
|
|
178
186
|
<Stack space={2}>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {peek, preload} from '../cache'
|
|
2
|
+
import {memo} from 'react'
|
|
3
|
+
import type {PluginConfig} from '../types'
|
|
4
|
+
import {useClient} from 'sanity'
|
|
5
|
+
|
|
6
|
+
export default memo(function Preload(
|
|
7
|
+
props: Required<Pick<PluginConfig, 'apiVersion' | 'languages'>>
|
|
8
|
+
) {
|
|
9
|
+
const client = useClient({apiVersion: props.apiVersion})
|
|
10
|
+
if (!Array.isArray(peek({}))) {
|
|
11
|
+
// eslint-disable-next-line require-await
|
|
12
|
+
preload(async () =>
|
|
13
|
+
Array.isArray(props.languages) ? props.languages : props.languages(client, {})
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return null
|
|
18
|
+
})
|
|
@@ -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/index.ts
CHANGED
package/src/plugin.tsx
CHANGED
|
@@ -1,21 +1,36 @@
|
|
|
1
|
+
import React from 'react'
|
|
1
2
|
import {definePlugin} from 'sanity'
|
|
2
|
-
import
|
|
3
|
+
import Preload from './components/Preload'
|
|
3
4
|
import array from './schema/array'
|
|
4
5
|
import object from './schema/object'
|
|
6
|
+
import {PluginConfig} from './types'
|
|
5
7
|
|
|
6
|
-
const CONFIG_DEFAULT = {
|
|
8
|
+
const CONFIG_DEFAULT: PluginConfig = {
|
|
7
9
|
languages: [],
|
|
8
10
|
fieldTypes: [],
|
|
9
11
|
}
|
|
10
12
|
|
|
11
13
|
export const internationalizedArray = definePlugin<PluginConfig>((config = CONFIG_DEFAULT) => {
|
|
12
|
-
const {languages, fieldTypes} = {...CONFIG_DEFAULT, ...config}
|
|
14
|
+
const {apiVersion = '2022-11-27', select, languages, fieldTypes} = {...CONFIG_DEFAULT, ...config}
|
|
13
15
|
|
|
14
16
|
return {
|
|
15
17
|
name: 'sanity-plugin-internationalized-array',
|
|
18
|
+
// If `languages` is a callback then let's preload it
|
|
19
|
+
studio: Array.isArray(languages)
|
|
20
|
+
? undefined
|
|
21
|
+
: {
|
|
22
|
+
components: {
|
|
23
|
+
layout: (props) => (
|
|
24
|
+
<>
|
|
25
|
+
<Preload apiVersion={apiVersion} languages={languages} />
|
|
26
|
+
{props.renderDefault(props)}
|
|
27
|
+
</>
|
|
28
|
+
),
|
|
29
|
+
},
|
|
30
|
+
},
|
|
16
31
|
schema: {
|
|
17
32
|
types: [
|
|
18
|
-
...fieldTypes.map((type) => array({type, languages})),
|
|
33
|
+
...fieldTypes.map((type) => array({type, apiVersion, select, languages})),
|
|
19
34
|
...fieldTypes.map((type) => object({type})),
|
|
20
35
|
],
|
|
21
36
|
},
|
package/src/schema/array.ts
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
/* eslint-disable no-nested-ternary */
|
|
2
|
+
import {defineField, type FieldDefinition, type Rule} from 'sanity'
|
|
3
|
+
import {peek} from '../cache'
|
|
2
4
|
|
|
3
5
|
import {createFieldName} from '../components/createFieldName'
|
|
6
|
+
import {getSelectedValue} from '../components/getSelectedValue'
|
|
4
7
|
import InternationalizedArray from '../components/InternationalizedArray'
|
|
5
|
-
import {Language, Value} from '../types'
|
|
8
|
+
import {Language, LanguageCallback, Value} from '../types'
|
|
6
9
|
|
|
7
10
|
type ArrayFactoryConfig = {
|
|
8
|
-
|
|
11
|
+
apiVersion: string
|
|
12
|
+
select?: Record<string, string>
|
|
13
|
+
languages: Language[] | LanguageCallback
|
|
9
14
|
type: string | FieldDefinition
|
|
10
15
|
}
|
|
11
16
|
|
|
12
17
|
export default (config: ArrayFactoryConfig): FieldDefinition<'array'> => {
|
|
13
|
-
const {languages, type} = config
|
|
18
|
+
const {apiVersion, select, languages, type} = config
|
|
14
19
|
const typeName = typeof type === `string` ? type : type.name
|
|
15
20
|
const arrayName = createFieldName(typeName)
|
|
16
21
|
const objectName = createFieldName(typeName, true)
|
|
@@ -24,11 +29,12 @@ export default (config: ArrayFactoryConfig): FieldDefinition<'array'> => {
|
|
|
24
29
|
components: {
|
|
25
30
|
input: InternationalizedArray,
|
|
26
31
|
},
|
|
27
|
-
options: {languages},
|
|
32
|
+
options: {apiVersion, select, languages},
|
|
28
33
|
// TODO: Resolve this typing issue with the inner object
|
|
29
34
|
// @ts-ignore
|
|
30
35
|
of: [
|
|
31
36
|
defineField({
|
|
37
|
+
...(typeof type === 'string' ? {} : type),
|
|
32
38
|
name: objectName,
|
|
33
39
|
type: objectName,
|
|
34
40
|
}),
|
|
@@ -39,9 +45,13 @@ export default (config: ArrayFactoryConfig): FieldDefinition<'array'> => {
|
|
|
39
45
|
return true
|
|
40
46
|
}
|
|
41
47
|
|
|
48
|
+
const selectedValue = getSelectedValue(select, context.document)
|
|
49
|
+
const client = context.getClient({apiVersion})
|
|
42
50
|
const contextLanguages: Language[] = Array.isArray(context?.type?.options?.languages)
|
|
43
|
-
? context
|
|
44
|
-
:
|
|
51
|
+
? context!.type!.options.languages
|
|
52
|
+
: Array.isArray(peek(selectedValue))
|
|
53
|
+
? peek(selectedValue)
|
|
54
|
+
: await context?.type?.options.languages(client, selectedValue)
|
|
45
55
|
|
|
46
56
|
if (value && value.length > contextLanguages.length) {
|
|
47
57
|
return `Cannot be more than ${
|
package/src/types.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {Rule, ArraySchemaType, RuleTypeConstraint} from 'sanity'
|
|
1
|
+
import type {Rule, ArraySchemaType, RuleTypeConstraint, SanityClient, FieldDefinition} from 'sanity'
|
|
2
2
|
|
|
3
3
|
export type Language = {
|
|
4
|
-
id:
|
|
4
|
+
id: Intl.UnicodeBCP47LocaleIdentifier
|
|
5
5
|
title: string
|
|
6
6
|
}
|
|
7
7
|
|
|
@@ -24,14 +24,88 @@ 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
|
-
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
/**
|
|
34
|
+
* https://www.sanity.io/docs/api-versioning
|
|
35
|
+
* @defaultValue '2022-11-27'
|
|
36
|
+
*/
|
|
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>
|
|
51
|
+
/**
|
|
52
|
+
* You can give it an array of language definitions:
|
|
53
|
+
* ```tsx
|
|
54
|
+
* {
|
|
55
|
+
* languages: [
|
|
56
|
+
* {id: 'en', title: 'English'},
|
|
57
|
+
* {id: 'fr', title: 'French'}
|
|
58
|
+
* ]
|
|
59
|
+
* }
|
|
60
|
+
* ```
|
|
61
|
+
* You can load them async by passing a function that returns a promise:
|
|
62
|
+
* ```tsx
|
|
63
|
+
* {
|
|
64
|
+
* languages: async () => {
|
|
65
|
+
* const response = await fetch('https://example.com/languages')
|
|
66
|
+
* return response.json()
|
|
67
|
+
* }
|
|
68
|
+
* }
|
|
69
|
+
* ```
|
|
70
|
+
* You can query your dataset for languages::
|
|
71
|
+
* ```tsx
|
|
72
|
+
* {
|
|
73
|
+
* languages: (client) =>
|
|
74
|
+
* query.fetch(groq`*[_type == "language"]{id,title}`)
|
|
75
|
+
* }
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
languages: Language[] | LanguageCallback
|
|
79
|
+
/**
|
|
80
|
+
* Can be a string matching core field types, as well as custom ones:
|
|
81
|
+
* ```tsx
|
|
82
|
+
* {
|
|
83
|
+
* fieldTypes: [
|
|
84
|
+
* "date", "datetime", "file", "image", "number", "string", "text", "url"
|
|
85
|
+
* ]
|
|
86
|
+
* }
|
|
87
|
+
* ```
|
|
88
|
+
* You can also define a type directly:
|
|
89
|
+
* ```tsx
|
|
90
|
+
* {
|
|
91
|
+
* fieldTypes: [
|
|
92
|
+
* defineField({
|
|
93
|
+
* name: 'featuredProduct',
|
|
94
|
+
* type: 'reference',
|
|
95
|
+
* to: [{type: 'product'}]
|
|
96
|
+
* hidden: (({document}) => !document?.title)
|
|
97
|
+
* })
|
|
98
|
+
* ]
|
|
99
|
+
* }
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
fieldTypes: (string | RuleTypeConstraint | FieldDefinition)[]
|
|
31
103
|
}
|
|
32
104
|
|
|
33
105
|
export type ArraySchemaWithLanguageOptions = ArraySchemaType & {
|
|
34
106
|
options: {
|
|
35
|
-
|
|
107
|
+
select?: Record<string, string>
|
|
108
|
+
languages: Language[] | LanguageCallback
|
|
109
|
+
apiVersion: string
|
|
36
110
|
}
|
|
37
111
|
}
|