sanity-plugin-internationalized-array 1.6.2 → 1.8.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/README.md +135 -7
- package/lib/index.d.ts +19 -9
- package/lib/index.esm.js +21 -12
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +21 -12
- package/lib/index.js.map +1 -1
- package/package.json +5 -3
- package/src/components/InternationalizedArray.tsx +159 -160
- package/src/components/InternationalizedArrayContext.tsx +91 -0
- package/src/components/InternationalizedInput.tsx +8 -5
- package/src/constants.ts +13 -0
- package/src/fieldActions/index.ts +132 -0
- package/src/plugin.tsx +73 -38
- package/src/schema/array.ts +2 -0
- package/src/types.ts +19 -9
- package/src/utils/checkAllLanguagesArePresent.ts +14 -0
- package/src/utils/createAddAllTitle.ts +16 -0
- package/src/utils/createAddLanguagePatches.ts +75 -0
- package/src/components/languageContext.tsx +0 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sanity-plugin-internationalized-array",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "Store localized fields in an array to save on attributes",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@sanity/icons": "^2.2.2",
|
|
53
53
|
"@sanity/incompatible-plugin": "^1.0.4",
|
|
54
|
+
"@sanity/language-filter": "^3.1.2",
|
|
54
55
|
"@sanity/ui": "^1.2.2",
|
|
55
56
|
"fast-deep-equal": "^3.1.3",
|
|
56
57
|
"lodash.get": "^4.4.2",
|
|
@@ -82,7 +83,7 @@
|
|
|
82
83
|
"react-dom": "^18",
|
|
83
84
|
"react-is": "^18",
|
|
84
85
|
"rimraf": "^4.1.2",
|
|
85
|
-
"sanity": "^3.
|
|
86
|
+
"sanity": "^3.14.1",
|
|
86
87
|
"semantic-release": "^20.1.0",
|
|
87
88
|
"typescript": "^4.9.5"
|
|
88
89
|
},
|
|
@@ -97,7 +98,8 @@
|
|
|
97
98
|
},
|
|
98
99
|
"sanityPlugin": {
|
|
99
100
|
"verifyPackage": {
|
|
100
|
-
"eslintImports": false
|
|
101
|
+
"eslintImports": false,
|
|
102
|
+
"dependencies": false
|
|
101
103
|
}
|
|
102
104
|
}
|
|
103
105
|
}
|
|
@@ -1,117 +1,121 @@
|
|
|
1
1
|
import {AddIcon} from '@sanity/icons'
|
|
2
|
+
import {useLanguageFilterStudioContext} from '@sanity/language-filter'
|
|
2
3
|
import {Button, Grid, Stack, useToast} from '@sanity/ui'
|
|
3
|
-
import
|
|
4
|
-
import {useCallback, useDeferredValue, useEffect, useMemo} from 'react'
|
|
4
|
+
import React, {useCallback, useEffect, useMemo} from 'react'
|
|
5
5
|
import {
|
|
6
6
|
ArrayOfObjectsInputProps,
|
|
7
7
|
ArrayOfObjectsItem,
|
|
8
|
-
|
|
9
|
-
insert,
|
|
8
|
+
ArraySchemaType,
|
|
10
9
|
set,
|
|
11
10
|
setIfMissing,
|
|
12
|
-
|
|
13
|
-
useFormBuilder,
|
|
11
|
+
useFormValue,
|
|
14
12
|
} from 'sanity'
|
|
15
|
-
import {suspend} from 'suspend-react'
|
|
16
13
|
|
|
17
|
-
import {
|
|
18
|
-
import type {
|
|
14
|
+
import {MAX_COLUMNS} from '../constants'
|
|
15
|
+
import type {Value} from '../types'
|
|
16
|
+
import {checkAllLanguagesArePresent} from '../utils/checkAllLanguagesArePresent'
|
|
17
|
+
import {createAddAllTitle} from '../utils/createAddAllTitle'
|
|
18
|
+
import {createAddLanguagePatches} from '../utils/createAddLanguagePatches'
|
|
19
19
|
import Feedback from './Feedback'
|
|
20
|
-
import {
|
|
21
|
-
// TODO: Move this provider to the root component
|
|
22
|
-
import {LanguageProvider} from './languageContext'
|
|
20
|
+
import {useInternationalizedArrayContext} from './InternationalizedArrayContext'
|
|
23
21
|
|
|
24
22
|
export type InternationalizedArrayProps = ArrayOfObjectsInputProps<
|
|
25
23
|
Value,
|
|
26
|
-
|
|
24
|
+
ArraySchemaType
|
|
27
25
|
>
|
|
28
26
|
|
|
29
27
|
export default function InternationalizedArray(
|
|
30
28
|
props: InternationalizedArrayProps
|
|
31
29
|
) {
|
|
32
30
|
const {members, value, schemaType, onChange} = props
|
|
31
|
+
|
|
33
32
|
const readOnly =
|
|
34
33
|
typeof schemaType.readOnly === 'boolean' ? schemaType.readOnly : false
|
|
35
|
-
const {options} = schemaType
|
|
36
34
|
const toast = useToast()
|
|
37
|
-
const {value: document} = useFormBuilder()
|
|
38
|
-
const deferredDocument = useDeferredValue(document)
|
|
39
|
-
const selectedValue = useMemo(
|
|
40
|
-
() => getSelectedValue(options.select, deferredDocument),
|
|
41
|
-
[options.select, deferredDocument]
|
|
42
|
-
)
|
|
43
35
|
|
|
44
|
-
const {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
36
|
+
const {
|
|
37
|
+
languages,
|
|
38
|
+
filteredLanguages,
|
|
39
|
+
defaultLanguages,
|
|
40
|
+
buttonAddAll,
|
|
41
|
+
buttonLocations,
|
|
42
|
+
} = useInternationalizedArrayContext()
|
|
43
|
+
|
|
44
|
+
// Support updating the UI if languageFilter is installed
|
|
45
|
+
const {selectedLanguageIds, options: languageFilterOptions} =
|
|
46
|
+
useLanguageFilterStudioContext()
|
|
47
|
+
const documentType = useFormValue(['_type'])
|
|
48
|
+
const languageFilterEnabled =
|
|
49
|
+
typeof documentType === 'string' &&
|
|
50
|
+
languageFilterOptions.documentTypes.includes(documentType)
|
|
51
|
+
|
|
52
|
+
const filteredMembers = useMemo(
|
|
53
|
+
() =>
|
|
54
|
+
languageFilterEnabled
|
|
55
|
+
? members.filter((member) => {
|
|
56
|
+
// This member is the outer object created by the plugin
|
|
57
|
+
// Satisfy TS
|
|
58
|
+
if (member.kind !== 'item') {
|
|
59
|
+
return false
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// This is the inner "value" field member created by this plugin
|
|
63
|
+
const valueMember = member.item.members[0]
|
|
64
|
+
|
|
65
|
+
// Satisfy TS
|
|
66
|
+
if (valueMember.kind !== 'field') {
|
|
67
|
+
return false
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return languageFilterOptions.filterField(
|
|
71
|
+
member.item.schemaType,
|
|
72
|
+
valueMember,
|
|
73
|
+
selectedLanguageIds
|
|
74
|
+
)
|
|
75
|
+
})
|
|
76
|
+
: members,
|
|
77
|
+
[languageFilterEnabled, members, languageFilterOptions, selectedLanguageIds]
|
|
78
|
+
)
|
|
59
79
|
|
|
60
80
|
const handleAddLanguage = useCallback(
|
|
61
|
-
(
|
|
62
|
-
if (!
|
|
81
|
+
(param?: React.MouseEvent<HTMLButtonElement, MouseEvent> | string[]) => {
|
|
82
|
+
if (!filteredLanguages?.length) {
|
|
63
83
|
return
|
|
64
84
|
}
|
|
65
85
|
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const newItems = languageId
|
|
70
|
-
? // Just one for this language
|
|
71
|
-
[{...itemBase, _key: languageId}]
|
|
72
|
-
: // Or one for every missing language
|
|
73
|
-
languages
|
|
74
|
-
.filter((language) =>
|
|
75
|
-
value?.length ? !value.find((v) => v._key === language.id) : true
|
|
76
|
-
)
|
|
77
|
-
.map((language) => ({...itemBase, _key: language.id}))
|
|
78
|
-
|
|
79
|
-
// Insert new items in the correct order
|
|
80
|
-
const languagesInUse = value?.length ? value.map((v) => v) : []
|
|
81
|
-
|
|
82
|
-
const insertions = newItems.map((item) => {
|
|
83
|
-
// What's the original index of this language?
|
|
84
|
-
const languageIndex = languages.findIndex((l) => item._key === l.id)
|
|
86
|
+
const addLanguageKeys: string[] = Array.isArray(param)
|
|
87
|
+
? param
|
|
88
|
+
: ([param?.currentTarget?.value].filter(Boolean) as string[])
|
|
85
89
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
remainingLanguages.find((r) => r.id === l._key)
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
// Keep local state up to date incase multiple insertions are being made
|
|
96
|
-
if (nextLanguageIndex < 0) {
|
|
97
|
-
languagesInUse.push(item)
|
|
98
|
-
} else {
|
|
99
|
-
languagesInUse.splice(nextLanguageIndex, 0, item)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return nextLanguageIndex < 0
|
|
103
|
-
? // No next language (-1), add to end of array
|
|
104
|
-
insert([item], 'after', [nextLanguageIndex])
|
|
105
|
-
: // Next language found, insert before that
|
|
106
|
-
insert([item], 'before', [nextLanguageIndex])
|
|
90
|
+
const patches = createAddLanguagePatches({
|
|
91
|
+
addLanguageKeys,
|
|
92
|
+
schemaType,
|
|
93
|
+
languages,
|
|
94
|
+
filteredLanguages,
|
|
95
|
+
value,
|
|
107
96
|
})
|
|
108
97
|
|
|
109
|
-
onChange([setIfMissing([]), ...
|
|
98
|
+
onChange([setIfMissing([]), ...patches])
|
|
110
99
|
},
|
|
111
|
-
[languages, onChange, schemaType
|
|
100
|
+
[filteredLanguages, languages, onChange, schemaType, value]
|
|
112
101
|
)
|
|
113
102
|
|
|
114
|
-
//
|
|
103
|
+
// Create default fields if the document is not yet created
|
|
104
|
+
const documentCreatedAt = useFormValue(['_createdAt'])
|
|
105
|
+
|
|
106
|
+
if (
|
|
107
|
+
// Array field is empty
|
|
108
|
+
!value &&
|
|
109
|
+
// Document form is in "not yet created" state
|
|
110
|
+
!documentCreatedAt &&
|
|
111
|
+
// Plugin config included default languages
|
|
112
|
+
defaultLanguages &&
|
|
113
|
+
defaultLanguages?.length > 0
|
|
114
|
+
) {
|
|
115
|
+
handleAddLanguage(defaultLanguages)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// TODO: This is reordering and re-setting the whole array, it could be surgical
|
|
115
119
|
const handleRestoreOrder = useCallback(() => {
|
|
116
120
|
if (!value?.length || !languages?.length) {
|
|
117
121
|
return
|
|
@@ -177,101 +181,96 @@ export default function InternationalizedArray(
|
|
|
177
181
|
[languages]
|
|
178
182
|
)
|
|
179
183
|
|
|
184
|
+
// Automatically restore order of fields
|
|
180
185
|
useEffect(() => {
|
|
181
186
|
if (languagesOutOfOrder.length > 0 && allKeysAreLanguages) {
|
|
182
187
|
handleRestoreOrder()
|
|
183
188
|
}
|
|
184
189
|
}, [languagesOutOfOrder, allKeysAreLanguages, handleRestoreOrder])
|
|
185
190
|
|
|
191
|
+
// compare value keys with possible languages
|
|
192
|
+
const allLanguagesArePresent = useMemo(
|
|
193
|
+
() => checkAllLanguagesArePresent(filteredLanguages, value),
|
|
194
|
+
[filteredLanguages, value]
|
|
195
|
+
)
|
|
196
|
+
|
|
186
197
|
if (!languagesAreValid) {
|
|
187
198
|
return <Feedback />
|
|
188
199
|
}
|
|
189
200
|
|
|
201
|
+
const addButtonsAreVisible =
|
|
202
|
+
// Plugin was configured to display buttons here (default!)
|
|
203
|
+
buttonLocations.includes('field') &&
|
|
204
|
+
// There's at least one language visible
|
|
205
|
+
filteredLanguages?.length > 0 &&
|
|
206
|
+
// Not every language has a value yet
|
|
207
|
+
!allLanguagesArePresent
|
|
208
|
+
|
|
190
209
|
return (
|
|
191
|
-
<
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
text={language.id.toUpperCase()}
|
|
245
|
-
icon={AddIcon}
|
|
246
|
-
onClick={() => handleAddLanguage(language.id)}
|
|
247
|
-
/>
|
|
248
|
-
))}
|
|
249
|
-
</Grid>
|
|
250
|
-
) : null}
|
|
210
|
+
<Stack space={2}>
|
|
211
|
+
{members?.length > 0 ? (
|
|
212
|
+
<>
|
|
213
|
+
{filteredMembers.map((member) => {
|
|
214
|
+
if (member.kind === 'item') {
|
|
215
|
+
return (
|
|
216
|
+
<ArrayOfObjectsItem
|
|
217
|
+
key={member.key}
|
|
218
|
+
member={member}
|
|
219
|
+
renderItem={props.renderItem}
|
|
220
|
+
renderField={props.renderField}
|
|
221
|
+
renderInput={props.renderInput}
|
|
222
|
+
renderPreview={props.renderPreview}
|
|
223
|
+
/>
|
|
224
|
+
)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return null
|
|
228
|
+
})}
|
|
229
|
+
</>
|
|
230
|
+
) : null}
|
|
231
|
+
|
|
232
|
+
{addButtonsAreVisible ? (
|
|
233
|
+
<Stack space={2}>
|
|
234
|
+
{/* Hide language-specific buttons if there's only one */}
|
|
235
|
+
{/* No more than 7 columns */}
|
|
236
|
+
{filteredLanguages.length > 1 ? (
|
|
237
|
+
<Grid
|
|
238
|
+
columns={Math.min(filteredLanguages.length, MAX_COLUMNS)}
|
|
239
|
+
gap={2}
|
|
240
|
+
>
|
|
241
|
+
{filteredLanguages.map((language) => (
|
|
242
|
+
<Button
|
|
243
|
+
key={language.id}
|
|
244
|
+
tone="primary"
|
|
245
|
+
mode="ghost"
|
|
246
|
+
fontSize={1}
|
|
247
|
+
disabled={
|
|
248
|
+
readOnly ||
|
|
249
|
+
Boolean(value?.find((item) => item._key === language.id))
|
|
250
|
+
}
|
|
251
|
+
text={language.id.toUpperCase()}
|
|
252
|
+
// Only show plus icon if there's one row or less
|
|
253
|
+
icon={
|
|
254
|
+
filteredLanguages.length > MAX_COLUMNS ? undefined : AddIcon
|
|
255
|
+
}
|
|
256
|
+
value={language.id}
|
|
257
|
+
onClick={handleAddLanguage}
|
|
258
|
+
/>
|
|
259
|
+
))}
|
|
260
|
+
</Grid>
|
|
261
|
+
) : null}
|
|
262
|
+
{buttonAddAll ? (
|
|
251
263
|
<Button
|
|
252
264
|
tone="primary"
|
|
253
265
|
mode="ghost"
|
|
254
|
-
disabled={
|
|
255
|
-
readOnly || (value && value?.length >= languages?.length)
|
|
256
|
-
}
|
|
266
|
+
disabled={readOnly || allLanguagesArePresent}
|
|
257
267
|
icon={AddIcon}
|
|
258
|
-
text={
|
|
259
|
-
|
|
260
|
-
value?.length
|
|
261
|
-
? `Add missing ${
|
|
262
|
-
languages.length - value.length === 1
|
|
263
|
-
? `language`
|
|
264
|
-
: `languages`
|
|
265
|
-
}`
|
|
266
|
-
: languages.length === 1
|
|
267
|
-
? `Add ${languages[0].title} Field`
|
|
268
|
-
: `Add all languages`
|
|
269
|
-
}
|
|
270
|
-
onClick={() => handleAddLanguage()}
|
|
268
|
+
text={createAddAllTitle(value, filteredLanguages)}
|
|
269
|
+
onClick={handleAddLanguage}
|
|
271
270
|
/>
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
</
|
|
271
|
+
) : null}
|
|
272
|
+
</Stack>
|
|
273
|
+
) : null}
|
|
274
|
+
</Stack>
|
|
276
275
|
)
|
|
277
276
|
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import {useLanguageFilterStudioContext} from '@sanity/language-filter'
|
|
2
|
+
import equal from 'fast-deep-equal'
|
|
3
|
+
import {createContext, useContext, useDeferredValue, useMemo} from 'react'
|
|
4
|
+
import {ObjectInputProps, useClient, useFormBuilder} from 'sanity'
|
|
5
|
+
import {suspend} from 'suspend-react'
|
|
6
|
+
|
|
7
|
+
import {namespace, version} from '../cache'
|
|
8
|
+
import {CONFIG_DEFAULT} from '../constants'
|
|
9
|
+
import {Language, PluginConfig} from '../types'
|
|
10
|
+
import {getSelectedValue} from './getSelectedValue'
|
|
11
|
+
|
|
12
|
+
// This provider makes the plugin config available to all components in the document form
|
|
13
|
+
// But with languages resolved and filtered languages updated base on @sanity/language-filter
|
|
14
|
+
|
|
15
|
+
type InternationalizedArrayContextProps = Required<PluginConfig> & {
|
|
16
|
+
languages: Language[]
|
|
17
|
+
filteredLanguages: Language[]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const InternationalizedArrayContext =
|
|
21
|
+
createContext<InternationalizedArrayContextProps>({
|
|
22
|
+
...CONFIG_DEFAULT,
|
|
23
|
+
languages: [],
|
|
24
|
+
filteredLanguages: [],
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
export function useInternationalizedArrayContext() {
|
|
28
|
+
return useContext(InternationalizedArrayContext)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
type InternationalizedArrayProviderProps = ObjectInputProps & {
|
|
32
|
+
internationalizedArray: Required<PluginConfig>
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function InternationalizedArrayProvider(
|
|
36
|
+
props: InternationalizedArrayProviderProps
|
|
37
|
+
) {
|
|
38
|
+
const {internationalizedArray} = props
|
|
39
|
+
|
|
40
|
+
const client = useClient({apiVersion: internationalizedArray.apiVersion})
|
|
41
|
+
const {value: document} = useFormBuilder()
|
|
42
|
+
const deferredDocument = useDeferredValue(document)
|
|
43
|
+
const selectedValue = useMemo(
|
|
44
|
+
() => getSelectedValue(internationalizedArray.select, deferredDocument),
|
|
45
|
+
[internationalizedArray.select, deferredDocument]
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
// Fetch or return languages
|
|
49
|
+
const languages = Array.isArray(internationalizedArray.languages)
|
|
50
|
+
? internationalizedArray.languages
|
|
51
|
+
: suspend(
|
|
52
|
+
// eslint-disable-next-line require-await
|
|
53
|
+
async () => {
|
|
54
|
+
if (typeof internationalizedArray.languages === 'function') {
|
|
55
|
+
return internationalizedArray.languages(client, selectedValue)
|
|
56
|
+
}
|
|
57
|
+
return internationalizedArray.languages
|
|
58
|
+
},
|
|
59
|
+
[version, namespace],
|
|
60
|
+
{equal}
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
// Filter out some languages if language filter is enabled
|
|
64
|
+
const {selectedLanguageIds, options: languageFilterOptions} =
|
|
65
|
+
useLanguageFilterStudioContext()
|
|
66
|
+
|
|
67
|
+
const filteredLanguages = useMemo(() => {
|
|
68
|
+
const documentType = deferredDocument ? deferredDocument._type : undefined
|
|
69
|
+
const languageFilterEnabled =
|
|
70
|
+
typeof documentType === 'string' &&
|
|
71
|
+
languageFilterOptions.documentTypes.includes(documentType)
|
|
72
|
+
|
|
73
|
+
return languageFilterEnabled
|
|
74
|
+
? languages.filter((language) =>
|
|
75
|
+
selectedLanguageIds.includes(language.id)
|
|
76
|
+
)
|
|
77
|
+
: languages
|
|
78
|
+
}, [deferredDocument, languageFilterOptions, languages, selectedLanguageIds])
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<InternationalizedArrayContext.Provider
|
|
82
|
+
value={{
|
|
83
|
+
...internationalizedArray,
|
|
84
|
+
languages,
|
|
85
|
+
filteredLanguages,
|
|
86
|
+
}}
|
|
87
|
+
>
|
|
88
|
+
{props.renderDefault(props)}
|
|
89
|
+
</InternationalizedArrayContext.Provider>
|
|
90
|
+
)
|
|
91
|
+
}
|
|
@@ -15,7 +15,7 @@ import {ObjectItemProps, useFormValue} from 'sanity'
|
|
|
15
15
|
import {set, unset} from 'sanity'
|
|
16
16
|
|
|
17
17
|
import {getToneFromValidation} from './getToneFromValidation'
|
|
18
|
-
import {
|
|
18
|
+
import {useInternationalizedArrayContext} from './InternationalizedArrayContext'
|
|
19
19
|
|
|
20
20
|
type InternationalizedValue = {
|
|
21
21
|
_type: string
|
|
@@ -44,7 +44,7 @@ export default function InternationalizedInput(
|
|
|
44
44
|
const {validation, value, onChange, readOnly} = inlineProps
|
|
45
45
|
|
|
46
46
|
// The parent array contains the languages from the plugin config
|
|
47
|
-
const {languages} =
|
|
47
|
+
const {languages} = useInternationalizedArrayContext()
|
|
48
48
|
|
|
49
49
|
const languageKeysInUse = useMemo(
|
|
50
50
|
() => parentValue?.map((v) => v._key) ?? [],
|
|
@@ -56,7 +56,9 @@ export default function InternationalizedInput(
|
|
|
56
56
|
|
|
57
57
|
// Changes the key of this item, ideally to a valid language
|
|
58
58
|
const handleKeyChange = useCallback(
|
|
59
|
-
(
|
|
59
|
+
(event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
|
60
|
+
const languageId = event?.currentTarget?.value
|
|
61
|
+
|
|
60
62
|
if (
|
|
61
63
|
!value ||
|
|
62
64
|
!languages?.length ||
|
|
@@ -99,12 +101,13 @@ export default function InternationalizedInput(
|
|
|
99
101
|
fontSize={1}
|
|
100
102
|
key={language.id}
|
|
101
103
|
text={language.id.toLocaleUpperCase()}
|
|
102
|
-
|
|
104
|
+
value={language.id}
|
|
105
|
+
// @ts-expect-error
|
|
106
|
+
onClick={handleKeyChange}
|
|
103
107
|
/>
|
|
104
108
|
))}
|
|
105
109
|
</Menu>
|
|
106
110
|
}
|
|
107
|
-
placement="right"
|
|
108
111
|
popover={{portal: true}}
|
|
109
112
|
/>
|
|
110
113
|
)}
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import {PluginConfig} from './types'
|
|
2
|
+
|
|
3
|
+
export const MAX_COLUMNS = 7
|
|
4
|
+
|
|
5
|
+
export const CONFIG_DEFAULT: Required<PluginConfig> = {
|
|
6
|
+
languages: [],
|
|
7
|
+
select: {},
|
|
8
|
+
defaultLanguages: [],
|
|
9
|
+
fieldTypes: [],
|
|
10
|
+
apiVersion: '2022-11-27',
|
|
11
|
+
buttonLocations: ['field'],
|
|
12
|
+
buttonAddAll: true,
|
|
13
|
+
}
|