sanity-plugin-internationalized-array 2.0.1-canary.0 → 2.1.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/lib/index.esm.js +44 -44
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +46 -45
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +44 -44
- package/lib/index.mjs.map +1 -1
- package/package.json +24 -18
- package/src/components/InternationalizedArrayContext.tsx +1 -3
- package/src/schema/array.ts +1 -7
- package/src/schema/object.ts +1 -1
package/lib/index.js
CHANGED
|
@@ -5,7 +5,8 @@ function _interopDefaultCompat(e) {
|
|
|
5
5
|
return e && typeof e == "object" && "default" in e ? e : { default: e };
|
|
6
6
|
}
|
|
7
7
|
function _interopNamespaceCompat(e) {
|
|
8
|
-
if (e && typeof e == "object" && "default" in e)
|
|
8
|
+
if (e && typeof e == "object" && "default" in e)
|
|
9
|
+
return e;
|
|
9
10
|
var n = /* @__PURE__ */ Object.create(null);
|
|
10
11
|
return e && Object.keys(e).forEach(function(k) {
|
|
11
12
|
if (k !== "default") {
|
|
@@ -31,10 +32,11 @@ const namespace = "sanity-plugin-internationalized-array", version = "v0", prelo
|
|
|
31
32
|
}, getDocumentsToTranslate = (value, rootPath = []) => {
|
|
32
33
|
if (Array.isArray(value)) {
|
|
33
34
|
const arrayRootPath = [...rootPath], internationalizedValues = value.filter((item) => {
|
|
34
|
-
if (Array.isArray(item))
|
|
35
|
+
if (Array.isArray(item))
|
|
36
|
+
return !1;
|
|
35
37
|
if (typeof item == "object") {
|
|
36
|
-
const type = item
|
|
37
|
-
return type
|
|
38
|
+
const type = item == null ? void 0 : item._type;
|
|
39
|
+
return (type == null ? void 0 : type.startsWith("internationalizedArray")) && (type == null ? void 0 : type.endsWith("Value"));
|
|
38
40
|
}
|
|
39
41
|
return !1;
|
|
40
42
|
});
|
|
@@ -65,7 +67,7 @@ function AddButtons(props) {
|
|
|
65
67
|
tone: "primary",
|
|
66
68
|
mode: "ghost",
|
|
67
69
|
fontSize: 1,
|
|
68
|
-
disabled: readOnly || !!value
|
|
70
|
+
disabled: readOnly || !!(value != null && value.find((item) => item._key === language.id)),
|
|
69
71
|
text: language.id.toUpperCase(),
|
|
70
72
|
icon: languages.length > MAX_COLUMNS ? void 0 : icons.AddIcon,
|
|
71
73
|
value: language.id,
|
|
@@ -86,7 +88,7 @@ function DocumentAddButtons(props) {
|
|
|
86
88
|
return;
|
|
87
89
|
}
|
|
88
90
|
const alreadyTranslated = documentsToTranslation.filter(
|
|
89
|
-
(translation) => translation
|
|
91
|
+
(translation) => (translation == null ? void 0 : translation._key) === languageId
|
|
90
92
|
), removeDuplicates = documentsToTranslation.reduce((filteredTranslations, translation) => alreadyTranslated.filter(
|
|
91
93
|
(alreadyTranslation) => alreadyTranslation.pathString === translation.pathString
|
|
92
94
|
).length > 0 || filteredTranslations.filter(
|
|
@@ -138,7 +140,7 @@ const getSelectedValue = (select, document) => {
|
|
|
138
140
|
for (const [key, path] of Object.entries(selection)) {
|
|
139
141
|
let value = get__default.default(document, path);
|
|
140
142
|
Array.isArray(value) && (value = value.filter(
|
|
141
|
-
(item) => typeof item == "object" ? item
|
|
143
|
+
(item) => typeof item == "object" ? (item == null ? void 0 : item._type) === "reference" && "_ref" in item : !0
|
|
142
144
|
)), selectedValue[key] = value;
|
|
143
145
|
}
|
|
144
146
|
return selectedValue;
|
|
@@ -151,9 +153,7 @@ function useInternationalizedArrayContext() {
|
|
|
151
153
|
return react.useContext(InternationalizedArrayContext);
|
|
152
154
|
}
|
|
153
155
|
function InternationalizedArrayProvider(props) {
|
|
154
|
-
const { internationalizedArray: internationalizedArray2 } = props, client = sanity.useClient({ apiVersion: internationalizedArray2.apiVersion }), workspace = sanity.useWorkspace(), { value: document } = sanity.useFormBuilder()
|
|
155
|
-
console.log({ document }, sanity.useFormBuilder());
|
|
156
|
-
const deferredDocument = react.useDeferredValue(document), selectedValue = react.useMemo(
|
|
156
|
+
const { internationalizedArray: internationalizedArray2 } = props, client = sanity.useClient({ apiVersion: internationalizedArray2.apiVersion }), workspace = sanity.useWorkspace(), { value: document } = sanity.useFormBuilder(), deferredDocument = react.useDeferredValue(document), selectedValue = react.useMemo(
|
|
157
157
|
() => getSelectedValue(internationalizedArray2.select, deferredDocument),
|
|
158
158
|
[internationalizedArray2.select, deferredDocument]
|
|
159
159
|
), languages = Array.isArray(internationalizedArray2.languages) ? internationalizedArray2.languages : suspend.suspend(
|
|
@@ -167,7 +167,7 @@ function InternationalizedArrayProvider(props) {
|
|
|
167
167
|
(language) => selectedLanguageIds.includes(language.id)
|
|
168
168
|
) : languages;
|
|
169
169
|
}, [deferredDocument, languageFilterOptions, languages, selectedLanguageIds]), showDocumentButtons = internationalizedArray2.buttonLocations.includes("document");
|
|
170
|
-
return
|
|
170
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
171
171
|
InternationalizedArrayContext.Provider,
|
|
172
172
|
{
|
|
173
173
|
value: {
|
|
@@ -193,7 +193,7 @@ function checkAllLanguagesArePresent(languages, value) {
|
|
|
193
193
|
return languagesInUseIds.length === filteredLanguageIds.length && languagesInUseIds.every((l) => filteredLanguageIds.includes(l));
|
|
194
194
|
}
|
|
195
195
|
function createAddAllTitle(value, languages) {
|
|
196
|
-
return value
|
|
196
|
+
return value != null && value.length ? `Add missing ${languages.length - value.length === 1 ? "language" : "languages"}` : languages.length === 1 ? `Add ${languages[0].title} Field` : "Add all languages";
|
|
197
197
|
}
|
|
198
198
|
function createValueSchemaTypeName(schemaType) {
|
|
199
199
|
return `${schemaType.name}Value`;
|
|
@@ -210,11 +210,11 @@ function createAddLanguagePatches(config) {
|
|
|
210
210
|
...itemBase,
|
|
211
211
|
_key: id
|
|
212
212
|
})) : filteredLanguages.filter(
|
|
213
|
-
(language) => value
|
|
213
|
+
(language) => value != null && value.length ? !value.find((v) => v._key === language.id) : !0
|
|
214
214
|
).map((language) => ({
|
|
215
215
|
...itemBase,
|
|
216
216
|
_key: language.id
|
|
217
|
-
})), languagesInUse = value
|
|
217
|
+
})), languagesInUse = value != null && value.length ? value.map((v) => v) : [];
|
|
218
218
|
return newItems.map((item) => {
|
|
219
219
|
const languageIndex = languages.findIndex((l) => item._key === l.id), remainingLanguages = languages.slice(languageIndex + 1), nextLanguageIndex = languagesInUse.findIndex(
|
|
220
220
|
(l) => (
|
|
@@ -232,7 +232,7 @@ function createAddLanguagePatches(config) {
|
|
|
232
232
|
});
|
|
233
233
|
}
|
|
234
234
|
const createTranslateFieldActions = (fieldActionProps, { languages, filteredLanguages }) => languages.map((language) => {
|
|
235
|
-
const value = sanity.useFormValue(fieldActionProps.path), disabled = value && Array.isArray(value) ? !!value
|
|
235
|
+
const value = sanity.useFormValue(fieldActionProps.path), disabled = value && Array.isArray(value) ? !!(value != null && value.find((item) => item._key === language.id)) : !1, hidden = !filteredLanguages.some((f) => f.id === language.id), { onChange } = structure.useDocumentPane(), onAction = react.useCallback(() => {
|
|
236
236
|
const { schemaType, path } = fieldActionProps, addLanguageKeys = [language.id], patches = createAddLanguagePatches({
|
|
237
237
|
addLanguageKeys,
|
|
238
238
|
schemaType,
|
|
@@ -274,7 +274,8 @@ const createTranslateFieldActions = (fieldActionProps, { languages, filteredLang
|
|
|
274
274
|
}, internationalizedArrayFieldAction = sanity.defineDocumentFieldAction({
|
|
275
275
|
name: "internationalizedArray",
|
|
276
276
|
useAction(fieldActionProps) {
|
|
277
|
-
|
|
277
|
+
var _a, _b;
|
|
278
|
+
const isInternationalizedArrayField = (_b = (_a = fieldActionProps == null ? void 0 : fieldActionProps.schemaType) == null ? void 0 : _a.type) == null ? void 0 : _b.name.startsWith(
|
|
278
279
|
"internationalizedArray"
|
|
279
280
|
), { languages, filteredLanguages } = useInternationalizedArrayContext(), translateFieldActions = createTranslateFieldActions(
|
|
280
281
|
fieldActionProps,
|
|
@@ -351,9 +352,10 @@ function InternationalizedArray(props) {
|
|
|
351
352
|
[languageFilterEnabled, members, languageFilterOptions, selectedLanguageIds]
|
|
352
353
|
), handleAddLanguage = react.useCallback(
|
|
353
354
|
async (param) => {
|
|
354
|
-
|
|
355
|
+
var _a;
|
|
356
|
+
if (!(filteredLanguages != null && filteredLanguages.length))
|
|
355
357
|
return;
|
|
356
|
-
const addLanguageKeys = Array.isArray(param) ? param : [param
|
|
358
|
+
const addLanguageKeys = Array.isArray(param) ? param : [(_a = param == null ? void 0 : param.currentTarget) == null ? void 0 : _a.value].filter(Boolean), patches = createAddLanguagePatches({
|
|
357
359
|
addLanguageKeys,
|
|
358
360
|
schemaType,
|
|
359
361
|
languages,
|
|
@@ -371,23 +373,23 @@ function InternationalizedArray(props) {
|
|
|
371
373
|
};
|
|
372
374
|
}, [defaultLanguages, documentCreatedAt, handleAddLanguage, value]);
|
|
373
375
|
const handleRestoreOrder = react.useCallback(() => {
|
|
374
|
-
if (!value
|
|
376
|
+
if (!(value != null && value.length) || !(languages != null && languages.length))
|
|
375
377
|
return;
|
|
376
378
|
const updatedValue = value.reduce((acc, v) => {
|
|
377
|
-
const newIndex = languages.findIndex((l) => l.id === v
|
|
379
|
+
const newIndex = languages.findIndex((l) => l.id === (v == null ? void 0 : v._key));
|
|
378
380
|
return newIndex > -1 && (acc[newIndex] = v), acc;
|
|
379
381
|
}, []).filter(Boolean);
|
|
380
|
-
value
|
|
382
|
+
(value == null ? void 0 : value.length) !== updatedValue.length && toast.push({
|
|
381
383
|
title: "There was an error reordering languages",
|
|
382
384
|
status: "warning"
|
|
383
385
|
}), onChange(sanity.set(updatedValue));
|
|
384
|
-
}, [toast, languages, onChange, value]), allKeysAreLanguages = react.useMemo(() => !value
|
|
385
|
-
() => languages && languages.length > 1 ? languages.filter((l) => value
|
|
386
|
+
}, [toast, languages, onChange, value]), allKeysAreLanguages = react.useMemo(() => !(value != null && value.length) || !(languages != null && languages.length) ? !0 : value == null ? void 0 : value.every((v) => languages.find((l) => (l == null ? void 0 : l.id) === (v == null ? void 0 : v._key))), [value, languages]), languagesInUse = react.useMemo(
|
|
387
|
+
() => languages && languages.length > 1 ? languages.filter((l) => value == null ? void 0 : value.find((v) => v._key === l.id)) : [],
|
|
386
388
|
[languages, value]
|
|
387
|
-
), languagesOutOfOrder = react.useMemo(() => !value
|
|
389
|
+
), languagesOutOfOrder = react.useMemo(() => !(value != null && value.length) || !languagesInUse.length ? [] : value.map(
|
|
388
390
|
(v, vIndex) => vIndex === languagesInUse.findIndex((l) => l.id === v._key) ? null : v
|
|
389
391
|
).filter(Boolean), [value, languagesInUse]), languagesAreValid = react.useMemo(
|
|
390
|
-
() => !languages
|
|
392
|
+
() => !(languages != null && languages.length) || (languages == null ? void 0 : languages.length) && languages.every((item) => item.id && item.title),
|
|
391
393
|
[languages]
|
|
392
394
|
);
|
|
393
395
|
react.useEffect(() => {
|
|
@@ -402,9 +404,9 @@ function InternationalizedArray(props) {
|
|
|
402
404
|
const addButtonsAreVisible = (
|
|
403
405
|
// Plugin was configured to display buttons here (default!)
|
|
404
406
|
buttonLocations.includes("field") && // There's at least one language visible
|
|
405
|
-
filteredLanguages
|
|
407
|
+
(filteredLanguages == null ? void 0 : filteredLanguages.length) > 0 && // Not every language has a value yet
|
|
406
408
|
!allLanguagesArePresent
|
|
407
|
-
), fieldHasMembers = members
|
|
409
|
+
), fieldHasMembers = (members == null ? void 0 : members.length) > 0;
|
|
408
410
|
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 2, children: [
|
|
409
411
|
fieldHasMembers ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: filteredMembers.map((member) => member.kind === "item" ? /* @__PURE__ */ react.createElement(
|
|
410
412
|
sanity.ArrayOfObjectsItem,
|
|
@@ -440,7 +442,8 @@ function InternationalizedArray(props) {
|
|
|
440
442
|
] });
|
|
441
443
|
}
|
|
442
444
|
function getLanguagesFieldOption(schemaType) {
|
|
443
|
-
|
|
445
|
+
var _a;
|
|
446
|
+
return schemaType ? ((_a = schemaType.options) == null ? void 0 : _a.languages) || getLanguagesFieldOption(schemaType.type) : void 0;
|
|
444
447
|
}
|
|
445
448
|
var array = (config) => {
|
|
446
449
|
const { apiVersion, select, languages, type } = config, typeName = typeof type == "string" ? type : type.name, arrayName = createFieldName(typeName), objectName = createFieldName(typeName, !0);
|
|
@@ -452,12 +455,7 @@ var array = (config) => {
|
|
|
452
455
|
input: InternationalizedArray
|
|
453
456
|
},
|
|
454
457
|
// These options are required for validation rules – not the custom input component
|
|
455
|
-
options: {
|
|
456
|
-
// @ts-expect-error - find out why it fails
|
|
457
|
-
apiVersion,
|
|
458
|
-
select,
|
|
459
|
-
languages
|
|
460
|
-
},
|
|
458
|
+
options: { apiVersion, select, languages },
|
|
461
459
|
of: [
|
|
462
460
|
sanity.defineField({
|
|
463
461
|
...typeof type == "string" ? {} : type,
|
|
@@ -465,16 +463,15 @@ var array = (config) => {
|
|
|
465
463
|
type: objectName
|
|
466
464
|
})
|
|
467
465
|
],
|
|
468
|
-
// @ts-expect-error - find out why it fails
|
|
469
466
|
validation: (rule) => rule.custom(async (value, context) => {
|
|
470
467
|
if (!value)
|
|
471
468
|
return !0;
|
|
472
469
|
const selectedValue = getSelectedValue(select, context.document), client = context.getClient({ apiVersion });
|
|
473
470
|
let contextLanguages = [];
|
|
474
|
-
const languagesFieldOption = getLanguagesFieldOption(context
|
|
471
|
+
const languagesFieldOption = getLanguagesFieldOption(context == null ? void 0 : context.type);
|
|
475
472
|
if (Array.isArray(languagesFieldOption) ? contextLanguages = languagesFieldOption : Array.isArray(peek(selectedValue)) ? contextLanguages = peek(selectedValue) || [] : typeof languagesFieldOption == "function" && (contextLanguages = await languagesFieldOption(client, selectedValue)), value && value.length > contextLanguages.length)
|
|
476
473
|
return `Cannot be more than ${contextLanguages.length === 1 ? "1 item" : `${contextLanguages.length} items`}`;
|
|
477
|
-
const nonLanguageKeys = value
|
|
474
|
+
const nonLanguageKeys = value != null && value.length ? value.filter(
|
|
478
475
|
(item) => !contextLanguages.find((language) => item._key === language.id)
|
|
479
476
|
) : [];
|
|
480
477
|
if (nonLanguageKeys.length)
|
|
@@ -482,10 +479,10 @@ var array = (config) => {
|
|
|
482
479
|
message: "Array item keys must be valid languages registered to the field type",
|
|
483
480
|
paths: nonLanguageKeys.map((item) => [{ _key: item._key }])
|
|
484
481
|
};
|
|
485
|
-
const valuesByLanguage = value
|
|
482
|
+
const valuesByLanguage = value != null && value.length ? value.filter((item) => !!(item != null && item._key)).reduce((acc, cur) => acc[cur._key] ? { ...acc, [cur._key]: [...acc[cur._key], cur] } : {
|
|
486
483
|
...acc,
|
|
487
484
|
[cur._key]: [cur]
|
|
488
|
-
}, {}) : {}, duplicateValues = Object.values(valuesByLanguage).filter((item) => item
|
|
485
|
+
}, {}) : {}, duplicateValues = Object.values(valuesByLanguage).filter((item) => (item == null ? void 0 : item.length) > 1).flat();
|
|
489
486
|
return duplicateValues.length ? {
|
|
490
487
|
message: "There can only be one field per language",
|
|
491
488
|
paths: duplicateValues.map((item) => [{ _key: item._key }])
|
|
@@ -501,7 +498,7 @@ function InternationalizedField(props) {
|
|
|
501
498
|
}) : props.children;
|
|
502
499
|
}
|
|
503
500
|
function getToneFromValidation(validations) {
|
|
504
|
-
if (!validations
|
|
501
|
+
if (!(validations != null && validations.length))
|
|
505
502
|
return;
|
|
506
503
|
const validationLevels = validations.map((v) => v.level);
|
|
507
504
|
if (validationLevels.includes("error"))
|
|
@@ -522,12 +519,16 @@ function InternationalizedInput(props) {
|
|
|
522
519
|
// TODO: Remove this as it shouldn't be necessary?
|
|
523
520
|
value: props.value
|
|
524
521
|
}, { validation, value, onChange, readOnly } = inlineProps, { languages } = useInternationalizedArrayContext(), languageKeysInUse = react.useMemo(
|
|
525
|
-
() =>
|
|
522
|
+
() => {
|
|
523
|
+
var _a;
|
|
524
|
+
return (_a = parentValue == null ? void 0 : parentValue.map((v) => v._key)) != null ? _a : [];
|
|
525
|
+
},
|
|
526
526
|
[parentValue]
|
|
527
|
-
), keyIsValid = languages
|
|
527
|
+
), keyIsValid = languages != null && languages.length ? languages.find((l) => l.id === value._key) : !1, handleKeyChange = react.useCallback(
|
|
528
528
|
(event) => {
|
|
529
|
-
|
|
530
|
-
|
|
529
|
+
var _a;
|
|
530
|
+
const languageId = (_a = event == null ? void 0 : event.currentTarget) == null ? void 0 : _a.value;
|
|
531
|
+
!value || !(languages != null && languages.length) || !languages.find((l) => l.id === languageId) || onChange([sanity.set(languageId, ["_key"])]);
|
|
531
532
|
},
|
|
532
533
|
[onChange, value, languages]
|
|
533
534
|
), handleUnset = react.useCallback(() => {
|
|
@@ -575,9 +576,9 @@ var object = (config) => {
|
|
|
575
576
|
title: `Internationalized array ${type}`,
|
|
576
577
|
type: "object",
|
|
577
578
|
components: {
|
|
578
|
-
// @ts-expect-error - find out why it fails
|
|
579
579
|
item: InternationalizedInput
|
|
580
580
|
},
|
|
581
|
+
// @ts-expect-error - Address this typing issue with the inner object
|
|
581
582
|
fields: [
|
|
582
583
|
typeof type == "string" ? (
|
|
583
584
|
// Define a simple field if all we have is the name as a string
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/cache.ts","../src/constants.ts","../src/utils/getDocumentsToTranslate.ts","../src/components/AddButtons.tsx","../src/components/DocumentAddButtons.tsx","../src/components/getSelectedValue.ts","../src/components/InternationalizedArrayContext.tsx","../src/components/Preload.tsx","../src/utils/checkAllLanguagesArePresent.ts","../src/utils/createAddAllTitle.ts","../src/utils/createValueSchemaTypeName.ts","../src/utils/createAddLanguagePatches.ts","../src/fieldActions/index.ts","../src/components/createFieldName.ts","../src/components/Feedback.tsx","../src/components/InternationalizedArray.tsx","../src/utils/getLanguagesFieldOption.ts","../src/schema/array.ts","../src/components/InternationalizedField.tsx","../src/components/getToneFromValidation.ts","../src/components/InternationalizedInput.tsx","../src/schema/object.ts","../src/utils/flattenSchemaType.ts","../src/plugin.tsx"],"sourcesContent":["/* eslint-disable @typescript-eslint/explicit-module-boundary-types */\n\nimport * as suspend from 'suspend-react'\n\nimport type {Language} from './types'\n\nexport const namespace = 'sanity-plugin-internationalized-array'\n\nexport const version = 'v0'\n\n// https://github.com/pmndrs/suspend-react#preloading\nexport const preload = (fn: () => Promise<Language[]>) =>\n suspend.preload(() => fn(), [version, namespace])\n\n// https://github.com/pmndrs/suspend-react#cache-busting\nexport const clear = () => suspend.clear([version, namespace])\n\n// https://github.com/pmndrs/suspend-react#peeking-into-entries-outside-of-suspense\nexport const peek = (selectedValue: Record<string, unknown>) =>\n suspend.peek([version, namespace, selectedValue]) as Language[] | undefined\n","import {PluginConfig} from './types'\n\nexport const MAX_COLUMNS = 7\n\nexport const CONFIG_DEFAULT: Required<PluginConfig> = {\n languages: [],\n select: {},\n defaultLanguages: [],\n fieldTypes: [],\n apiVersion: '2022-11-27',\n buttonLocations: ['field'],\n buttonAddAll: true,\n}\n","import {SanityDocument} from 'sanity'\n\nexport interface DocumentsToTranslate {\n path: (string | number)[]\n pathString: string\n _key: string\n _type: string\n [key: string]: unknown\n}\n\nexport const getDocumentsToTranslate = (\n value: SanityDocument | unknown,\n rootPath: (string | number)[] = []\n): DocumentsToTranslate[] => {\n if (Array.isArray(value)) {\n const arrayRootPath = [...rootPath]\n\n // if item contains internationalized return array\n const internationalizedValues = value.filter((item) => {\n if (Array.isArray(item)) return false\n\n if (typeof item === 'object') {\n const type = item?._type as string | undefined\n return (\n type?.startsWith('internationalizedArray') && type?.endsWith('Value')\n )\n }\n return false\n })\n\n if (internationalizedValues.length > 0) {\n return internationalizedValues.map((internationalizedValue) => {\n return {\n ...internationalizedValue,\n path: arrayRootPath,\n pathString: arrayRootPath.join('.'),\n }\n })\n }\n\n if (value.length > 0) {\n return value\n .map((item, index) =>\n getDocumentsToTranslate(item, [...arrayRootPath, index])\n )\n .flat()\n }\n\n return []\n }\n if (typeof value === 'object' && value) {\n const startsWithUnderscoreRegex = /^_/\n const itemKeys = Object.keys(value).filter(\n (key) => !key.match(startsWithUnderscoreRegex)\n ) as (keyof typeof value)[]\n\n return itemKeys\n .map((item) => {\n const selectedValue = value[item] as unknown\n const path = [...rootPath, item]\n return getDocumentsToTranslate(selectedValue, path)\n })\n .flat()\n }\n return []\n}\n","import {AddIcon} from '@sanity/icons'\nimport {Button, Grid} from '@sanity/ui'\nimport type React from 'react'\n\nimport {MAX_COLUMNS} from '../constants'\nimport type {Language, Value} from '../types'\n\ntype AddButtonsProps = {\n languages: Language[]\n readOnly: boolean\n value: Value[] | undefined\n onClick: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void\n}\n\nexport default function AddButtons(props: AddButtonsProps) {\n const {languages, readOnly, value, onClick} = props\n\n return languages.length > 0 ? (\n <Grid columns={Math.min(languages.length, MAX_COLUMNS)} gap={2}>\n {languages.map((language) => (\n <Button\n key={language.id}\n tone=\"primary\"\n mode=\"ghost\"\n fontSize={1}\n disabled={\n readOnly ||\n Boolean(value?.find((item) => item._key === language.id))\n }\n text={language.id.toUpperCase()}\n // Only show plus icon if there's one row or less\n icon={languages.length > MAX_COLUMNS ? undefined : AddIcon}\n value={language.id}\n onClick={onClick}\n />\n ))}\n </Grid>\n ) : null\n}\n","import {Box, Stack, Text, useToast} from '@sanity/ui'\nimport React, {useCallback} from 'react'\nimport {\n FormInsertPatch,\n FormSetIfMissingPatch,\n insert,\n isSanityDocument,\n PatchEvent,\n setIfMissing,\n} from 'sanity'\nimport {useDocumentPane} from 'sanity/structure'\n\nimport {\n DocumentsToTranslate,\n getDocumentsToTranslate,\n} from '../utils/getDocumentsToTranslate'\nimport AddButtons from './AddButtons'\nimport {useInternationalizedArrayContext} from './InternationalizedArrayContext'\n\ntype DocumentAddButtonsProps = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n value: Record<string, any> | undefined\n}\nexport default function DocumentAddButtons(props: DocumentAddButtonsProps) {\n const {filteredLanguages} = useInternationalizedArrayContext()\n const value = isSanityDocument(props.value) ? props.value : undefined\n\n const toast = useToast()\n const {onChange} = useDocumentPane()\n\n const documentsToTranslation = getDocumentsToTranslate(value, [])\n\n const handleDocumentButtonClick = useCallback(\n async (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {\n const languageId = event.currentTarget.value\n if (!languageId) {\n toast.push({\n status: 'error',\n title: 'No language selected',\n })\n return\n }\n const alreadyTranslated = documentsToTranslation.filter(\n (translation) => translation?._key === languageId\n )\n const removeDuplicates = documentsToTranslation.reduce<\n DocumentsToTranslate[]\n >((filteredTranslations, translation) => {\n if (\n alreadyTranslated.filter(\n (alreadyTranslation) =>\n alreadyTranslation.pathString === translation.pathString\n ).length > 0\n ) {\n return filteredTranslations\n }\n const translationAlreadyExists = filteredTranslations.filter(\n (filteredTranslation) => filteredTranslation.path === translation.path\n )\n\n if (translationAlreadyExists.length > 0) {\n return filteredTranslations\n }\n return [...filteredTranslations, translation]\n }, [])\n if (removeDuplicates.length === 0) {\n toast.push({\n status: 'error',\n title: 'No internationalizedArray fields found in document root',\n })\n return\n }\n\n // Write a new patch for each empty field\n const patches: (FormSetIfMissingPatch | FormInsertPatch)[] = []\n\n for (const toTranslate of removeDuplicates) {\n const path = toTranslate.path\n\n const ifMissing = setIfMissing([], path)\n const insertValue = insert(\n [\n {\n _key: languageId,\n _type: toTranslate._type,\n value: undefined,\n },\n ],\n 'after',\n [...path, -1]\n )\n patches.push(ifMissing)\n patches.push(insertValue)\n }\n\n onChange(PatchEvent.from(patches.flat()))\n },\n [documentsToTranslation, onChange, toast]\n )\n return (\n <Stack space={3}>\n <Box>\n <Text size={1} weight=\"semibold\">\n Add translation to internationalized fields\n </Text>\n </Box>\n <AddButtons\n languages={filteredLanguages}\n readOnly={false}\n value={undefined}\n onClick={handleDocumentButtonClick}\n />\n </Stack>\n )\n}\n","import {get} from 'lodash'\n\nexport const getSelectedValue = (\n select: Record<string, string> | undefined,\n document:\n | {\n [x: string]: unknown\n }\n | undefined\n): Record<string, unknown> => {\n if (!select || !document) {\n return {}\n }\n\n const selection: Record<string, string> = select || {}\n const selectedValue: Record<string, unknown> = {}\n for (const [key, path] of Object.entries(selection)) {\n let value = get(document, path)\n if (Array.isArray(value)) {\n // If there are references in the array, ensure they have `_ref` set, otherwise they are considered empty and can safely be ignored\n value = value.filter((item) =>\n typeof item === 'object'\n ? item?._type === 'reference' && '_ref' in item\n : true\n )\n }\n selectedValue[key] = value\n }\n\n return selectedValue\n}\n","import {useLanguageFilterStudioContext} from '@sanity/language-filter'\nimport {Stack} from '@sanity/ui'\nimport equal from 'fast-deep-equal'\nimport {createContext, useContext, useDeferredValue, useMemo} from 'react'\nimport {\n type ObjectInputProps,\n useClient,\n useFormBuilder,\n useWorkspace,\n} from 'sanity'\nimport {suspend} from 'suspend-react'\n\nimport {namespace, version} from '../cache'\nimport {CONFIG_DEFAULT} from '../constants'\nimport type {Language, PluginConfig} from '../types'\nimport DocumentAddButtons from './DocumentAddButtons'\nimport {getSelectedValue} from './getSelectedValue'\n\n// This provider makes the plugin config available to all components in the document form\n// But with languages resolved and filtered languages updated base on @sanity/language-filter\n\ntype InternationalizedArrayContextProps = Required<PluginConfig> & {\n languages: Language[]\n filteredLanguages: Language[]\n}\n\nexport const InternationalizedArrayContext =\n createContext<InternationalizedArrayContextProps>({\n ...CONFIG_DEFAULT,\n languages: [],\n filteredLanguages: [],\n })\n\nexport function useInternationalizedArrayContext() {\n return useContext(InternationalizedArrayContext)\n}\n\ntype InternationalizedArrayProviderProps = ObjectInputProps & {\n internationalizedArray: Required<PluginConfig>\n}\n\nexport function InternationalizedArrayProvider(\n props: InternationalizedArrayProviderProps\n) {\n const {internationalizedArray} = props\n\n const client = useClient({apiVersion: internationalizedArray.apiVersion})\n const workspace = useWorkspace()\n // @ts-expect-error - TODO fix\n const {value: document} = useFormBuilder()\n console.log({document}, useFormBuilder())\n const deferredDocument = useDeferredValue(document)\n const selectedValue = useMemo(\n () => getSelectedValue(internationalizedArray.select, deferredDocument),\n [internationalizedArray.select, deferredDocument]\n )\n\n // Fetch or return languages\n const languages = Array.isArray(internationalizedArray.languages)\n ? internationalizedArray.languages\n : suspend(\n // eslint-disable-next-line require-await\n async () => {\n if (typeof internationalizedArray.languages === 'function') {\n return internationalizedArray.languages(client, selectedValue)\n }\n return internationalizedArray.languages\n },\n [version, namespace, selectedValue, workspace],\n {equal}\n )\n\n // Filter out some languages if language filter is enabled\n const {selectedLanguageIds, options: languageFilterOptions} =\n useLanguageFilterStudioContext()\n\n const filteredLanguages = useMemo(() => {\n const documentType = deferredDocument ? deferredDocument._type : undefined\n const languageFilterEnabled =\n typeof documentType === 'string' &&\n languageFilterOptions.documentTypes.includes(documentType)\n\n return languageFilterEnabled\n ? languages.filter((language) =>\n selectedLanguageIds.includes(language.id)\n )\n : languages\n }, [deferredDocument, languageFilterOptions, languages, selectedLanguageIds])\n\n const showDocumentButtons =\n internationalizedArray.buttonLocations.includes('document')\n console.log({showDocumentButtons})\n return (\n <InternationalizedArrayContext.Provider\n value={{\n ...internationalizedArray,\n languages,\n filteredLanguages,\n }}\n >\n {showDocumentButtons ? (\n <Stack space={5}>\n <DocumentAddButtons value={props.value} />\n {props.renderDefault(props)}\n </Stack>\n ) : (\n props.renderDefault(props)\n )}\n </InternationalizedArrayContext.Provider>\n )\n}\n","import {memo} from 'react'\nimport {useClient} from 'sanity'\n\nimport {peek, preload} from '../cache'\nimport type {PluginConfig} from '../types'\n\nexport default memo(function Preload(\n props: Required<Pick<PluginConfig, 'apiVersion' | 'languages'>>\n) {\n const client = useClient({apiVersion: props.apiVersion})\n if (!Array.isArray(peek({}))) {\n // eslint-disable-next-line require-await\n preload(async () =>\n Array.isArray(props.languages)\n ? props.languages\n : props.languages(client, {})\n )\n }\n\n return null\n})\n","import {Language, Value} from '../types'\n\nexport function checkAllLanguagesArePresent(\n languages: Language[],\n value: Value[] | undefined\n): boolean {\n const filteredLanguageIds = languages.map((l) => l.id)\n const languagesInUseIds = value ? value.map((v) => v._key) : []\n\n return (\n languagesInUseIds.length === filteredLanguageIds.length &&\n languagesInUseIds.every((l) => filteredLanguageIds.includes(l))\n )\n}\n","import {Language, Value} from '../types'\n\nexport function createAddAllTitle(\n value: Value[] | undefined,\n languages: Language[]\n): string {\n if (value?.length) {\n return `Add missing ${\n languages.length - value.length === 1 ? `language` : `languages`\n }`\n }\n\n return languages.length === 1\n ? `Add ${languages[0].title} Field`\n : `Add all languages`\n}\n","import {SchemaType} from 'sanity'\n\nexport function createValueSchemaTypeName(schemaType: SchemaType): string {\n return `${schemaType.name}Value`\n}\n","import {FormInsertPatch, insert, Path, SchemaType} from 'sanity'\n\nimport {Language, Value} from '../types'\nimport {createValueSchemaTypeName} from './createValueSchemaTypeName'\n\ntype AddConfig = {\n // New keys to add to the field\n addLanguageKeys: string[]\n // Schema of the current field\n schemaType: SchemaType\n // All languages registered in the plugin\n languages: Language[]\n // Languages that are currently visible\n filteredLanguages: Language[]\n // Current value of the internationalizedArray field\n value?: Value[]\n // Path to this item\n path?: Path\n}\n\nexport function createAddLanguagePatches(config: AddConfig): FormInsertPatch[] {\n const {\n addLanguageKeys,\n schemaType,\n languages,\n filteredLanguages,\n value,\n path = [],\n } = config\n\n const itemBase = {_type: createValueSchemaTypeName(schemaType)}\n\n // Create new items\n const getNewItems = () => {\n if (Array.isArray(addLanguageKeys) && addLanguageKeys.length > 0) {\n return addLanguageKeys.map((id) => ({\n ...itemBase,\n _key: id,\n }))\n }\n\n return filteredLanguages\n .filter((language) =>\n value?.length ? !value.find((v) => v._key === language.id) : true\n )\n .map((language) => ({\n ...itemBase,\n _key: language.id,\n }))\n }\n const newItems = getNewItems()\n\n // Insert new items in the correct order\n const languagesInUse = value?.length ? value.map((v) => v) : []\n\n const insertions = newItems.map((item) => {\n // What's the original index of this language?\n const languageIndex = languages.findIndex((l) => item._key === l.id)\n\n // What languages are there beyond that index?\n const remainingLanguages = languages.slice(languageIndex + 1)\n\n // So what is the index in the current value array of the next language in the language array?\n const nextLanguageIndex = languagesInUse.findIndex((l) =>\n // eslint-disable-next-line max-nested-callbacks\n remainingLanguages.find((r) => r.id === l._key)\n )\n\n // Keep local state up to date incase multiple insertions are being made\n if (nextLanguageIndex < 0) {\n languagesInUse.push(item)\n } else {\n languagesInUse.splice(nextLanguageIndex, 0, item)\n }\n\n return nextLanguageIndex < 0\n ? // No next language (-1), add to end of array\n insert([item], 'after', [...path, nextLanguageIndex])\n : // Next language found, insert before that\n insert([item], 'before', [...path, nextLanguageIndex])\n })\n\n return insertions\n}\n","import {AddIcon, TranslateIcon} from '@sanity/icons'\nimport {useCallback} from 'react'\nimport {\n defineDocumentFieldAction,\n type DocumentFieldActionItem,\n type DocumentFieldActionProps,\n PatchEvent,\n setIfMissing,\n useFormValue,\n} from 'sanity'\nimport {useDocumentPane} from 'sanity/structure'\n\nimport {useInternationalizedArrayContext} from '../components/InternationalizedArrayContext'\nimport type {Language, Value} from '../types'\nimport {checkAllLanguagesArePresent} from '../utils/checkAllLanguagesArePresent'\nimport {createAddAllTitle} from '../utils/createAddAllTitle'\nimport {createAddLanguagePatches} from '../utils/createAddLanguagePatches'\n\nconst createTranslateFieldActions: (\n fieldActionProps: DocumentFieldActionProps,\n context: {\n languages: Language[]\n filteredLanguages: Language[]\n }\n) => DocumentFieldActionItem[] = (\n fieldActionProps,\n {languages, filteredLanguages}\n) =>\n languages.map((language) => {\n const value = useFormValue(fieldActionProps.path) as Value[]\n const disabled =\n value && Array.isArray(value)\n ? Boolean(value?.find((item) => item._key === language.id))\n : false\n const hidden = !filteredLanguages.some((f) => f.id === language.id)\n\n const {onChange} = useDocumentPane()\n\n const onAction = useCallback(() => {\n const {schemaType, path} = fieldActionProps\n\n const addLanguageKeys = [language.id]\n const patches = createAddLanguagePatches({\n addLanguageKeys,\n schemaType,\n languages,\n filteredLanguages,\n value,\n path,\n })\n\n onChange(PatchEvent.from([setIfMissing([], path), ...patches]))\n }, [language.id, value, onChange])\n\n return {\n type: 'action',\n icon: AddIcon,\n onAction,\n title: language.title,\n hidden,\n disabled,\n }\n })\n\nconst AddMissingTranslationsFieldAction: (\n fieldActionProps: DocumentFieldActionProps,\n context: {\n languages: Language[]\n filteredLanguages: Language[]\n }\n) => DocumentFieldActionItem = (\n fieldActionProps,\n {languages, filteredLanguages}\n) => {\n const value = useFormValue(fieldActionProps.path) as Value[]\n const disabled = value && value.length === filteredLanguages.length\n const hidden = checkAllLanguagesArePresent(filteredLanguages, value)\n\n const {onChange} = useDocumentPane()\n\n const onAction = useCallback(() => {\n const {schemaType, path} = fieldActionProps\n\n const addLanguageKeys: string[] = []\n const patches = createAddLanguagePatches({\n addLanguageKeys,\n schemaType,\n languages,\n filteredLanguages,\n value,\n path,\n })\n\n onChange(PatchEvent.from([setIfMissing([], path), ...patches]))\n }, [fieldActionProps, filteredLanguages, languages, onChange, value])\n\n return {\n type: 'action',\n icon: AddIcon,\n onAction,\n title: createAddAllTitle(value, filteredLanguages),\n disabled,\n hidden,\n }\n}\n\nexport const internationalizedArrayFieldAction = defineDocumentFieldAction({\n name: 'internationalizedArray',\n useAction(fieldActionProps) {\n const isInternationalizedArrayField =\n fieldActionProps?.schemaType?.type?.name.startsWith(\n 'internationalizedArray'\n )\n const {languages, filteredLanguages} = useInternationalizedArrayContext()\n\n const translateFieldActions = createTranslateFieldActions(\n fieldActionProps,\n {languages, filteredLanguages}\n )\n\n return {\n type: 'group',\n icon: TranslateIcon,\n title: 'Add Translation',\n renderAsButton: true,\n children: isInternationalizedArrayField\n ? [\n ...translateFieldActions,\n AddMissingTranslationsFieldAction(fieldActionProps, {\n languages,\n filteredLanguages,\n }),\n ]\n : [],\n hidden: !isInternationalizedArrayField,\n }\n },\n})\n","export function camelCase(string: string): string {\n return string.replace(/-([a-z])/g, (g) => g[1].toUpperCase())\n}\n\nexport function titleCase(string: string): string {\n return string\n .split(` `)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(` `)\n}\n\nexport function pascalCase(string: string): string {\n return titleCase(camelCase(string))\n}\n\nexport function createFieldName(name: string, addValue = false): string {\n return addValue\n ? [`internationalizedArray`, pascalCase(name), `Value`].join(``)\n : [`internationalizedArray`, pascalCase(name)].join(``)\n}\n","import {Card, Code, Stack, Text} from '@sanity/ui'\n\nconst schemaExample = {\n languages: [\n {id: 'en', title: 'English'},\n {id: 'no', title: 'Norsk'},\n ],\n}\n\nexport default function Feedback() {\n return (\n <Card tone=\"caution\" border radius={2} padding={3}>\n <Stack space={4}>\n <Text>\n An array of language objects must be passed into the{' '}\n <code>internationalizedArray</code> helper function, each with an{' '}\n <code>id</code> and <code>title</code> field. Example:\n </Text>\n <Card padding={2} border radius={2}>\n <Code size={1} language=\"javascript\">\n {JSON.stringify(schemaExample, null, 2)}\n </Code>\n </Card>\n </Stack>\n </Card>\n )\n}\n","import {AddIcon} from '@sanity/icons'\nimport {useLanguageFilterStudioContext} from '@sanity/language-filter'\nimport {Button, Card, Stack, Text, useToast} from '@sanity/ui'\nimport type React from 'react'\nimport {useCallback, useEffect, useMemo, useRef} from 'react'\nimport {\n type ArrayOfObjectsInputProps,\n ArrayOfObjectsItem,\n type ArraySchemaType,\n MemberItemError,\n set,\n setIfMissing,\n useFormValue,\n} from 'sanity'\n\nimport type {Value} from '../types'\nimport {checkAllLanguagesArePresent} from '../utils/checkAllLanguagesArePresent'\nimport {createAddAllTitle} from '../utils/createAddAllTitle'\nimport {createAddLanguagePatches} from '../utils/createAddLanguagePatches'\nimport AddButtons from './AddButtons'\nimport Feedback from './Feedback'\nimport {useInternationalizedArrayContext} from './InternationalizedArrayContext'\n\nexport type InternationalizedArrayProps = ArrayOfObjectsInputProps<\n Value,\n ArraySchemaType\n>\n\nexport default function InternationalizedArray(\n props: InternationalizedArrayProps\n) {\n const {members, value, schemaType, onChange} = props\n\n const readOnly =\n typeof schemaType.readOnly === 'boolean' ? schemaType.readOnly : false\n const toast = useToast()\n\n const {\n languages,\n filteredLanguages,\n defaultLanguages,\n buttonAddAll,\n buttonLocations,\n } = useInternationalizedArrayContext()\n\n // Support updating the UI if languageFilter is installed\n const {selectedLanguageIds, options: languageFilterOptions} =\n useLanguageFilterStudioContext()\n const documentType = useFormValue(['_type'])\n const languageFilterEnabled =\n typeof documentType === 'string' &&\n languageFilterOptions.documentTypes.includes(documentType)\n\n const filteredMembers = useMemo(\n () =>\n languageFilterEnabled\n ? members.filter((member) => {\n // This member is the outer object created by the plugin\n // Satisfy TS\n if (member.kind !== 'item') {\n return false\n }\n\n // This is the inner \"value\" field member created by this plugin\n const valueMember = member.item.members[0]\n\n // Satisfy TS\n if (valueMember.kind !== 'field') {\n return false\n }\n\n return languageFilterOptions.filterField(\n member.item.schemaType,\n valueMember,\n selectedLanguageIds\n )\n })\n : members,\n [languageFilterEnabled, members, languageFilterOptions, selectedLanguageIds]\n )\n\n const handleAddLanguage = useCallback(\n async (\n param?: React.MouseEvent<HTMLButtonElement, MouseEvent> | string[]\n ) => {\n if (!filteredLanguages?.length) {\n return\n }\n\n const addLanguageKeys: string[] = Array.isArray(param)\n ? param\n : ([param?.currentTarget?.value].filter(Boolean) as string[])\n\n const patches = createAddLanguagePatches({\n addLanguageKeys,\n schemaType,\n languages,\n filteredLanguages,\n value,\n })\n\n onChange([setIfMissing([]), ...patches])\n },\n [filteredLanguages, languages, onChange, schemaType, value]\n )\n\n // Create default fields if the document is not yet created\n const documentCreatedAt = useFormValue(['_createdAt'])\n const hasAddedDefaultLanguages = useRef(Boolean(documentCreatedAt))\n\n // Write default languages\n useEffect(() => {\n const shouldAddDefaultLanguages =\n !hasAddedDefaultLanguages.current &&\n !value &&\n !documentCreatedAt &&\n Array.isArray(defaultLanguages) &&\n defaultLanguages.length > 0\n\n if (shouldAddDefaultLanguages) {\n handleAddLanguage(defaultLanguages)\n }\n\n return () => {\n if (shouldAddDefaultLanguages) {\n hasAddedDefaultLanguages.current = true\n }\n }\n }, [defaultLanguages, documentCreatedAt, handleAddLanguage, value])\n\n // TODO: This is reordering and re-setting the whole array, it could be surgical\n const handleRestoreOrder = useCallback(() => {\n if (!value?.length || !languages?.length) {\n return\n }\n\n // Create a new value array in the correct order\n // This would also strip out values that don't have a language as the key\n const updatedValue = value\n .reduce((acc, v) => {\n const newIndex = languages.findIndex((l) => l.id === v?._key)\n\n if (newIndex > -1) {\n acc[newIndex] = v\n }\n\n return acc\n }, [] as Value[])\n .filter(Boolean)\n\n if (value?.length !== updatedValue.length) {\n toast.push({\n title: 'There was an error reordering languages',\n status: 'warning',\n })\n }\n\n onChange(set(updatedValue))\n }, [toast, languages, onChange, value])\n\n const allKeysAreLanguages = useMemo(() => {\n if (!value?.length || !languages?.length) {\n return true\n }\n\n return value?.every((v) => languages.find((l) => l?.id === v?._key))\n }, [value, languages])\n\n // Check languages are in the correct order\n const languagesInUse = useMemo(\n () =>\n languages && languages.length > 1\n ? languages.filter((l) => value?.find((v) => v._key === l.id))\n : [],\n [languages, value]\n )\n\n const languagesOutOfOrder = useMemo(() => {\n if (!value?.length || !languagesInUse.length) {\n return []\n }\n\n return value\n .map((v, vIndex) =>\n vIndex === languagesInUse.findIndex((l) => l.id === v._key) ? null : v\n )\n .filter(Boolean)\n }, [value, languagesInUse])\n\n const languagesAreValid = useMemo(\n () =>\n !languages?.length ||\n (languages?.length && languages.every((item) => item.id && item.title)),\n [languages]\n )\n\n // Automatically restore order of fields\n useEffect(() => {\n if (languagesOutOfOrder.length > 0 && allKeysAreLanguages) {\n handleRestoreOrder()\n }\n }, [languagesOutOfOrder, allKeysAreLanguages, handleRestoreOrder])\n\n // compare value keys with possible languages\n const allLanguagesArePresent = useMemo(\n () => checkAllLanguagesArePresent(filteredLanguages, value),\n [filteredLanguages, value]\n )\n\n if (!languagesAreValid) {\n return <Feedback />\n }\n\n const addButtonsAreVisible =\n // Plugin was configured to display buttons here (default!)\n buttonLocations.includes('field') &&\n // There's at least one language visible\n filteredLanguages?.length > 0 &&\n // Not every language has a value yet\n !allLanguagesArePresent\n const fieldHasMembers = members?.length > 0\n\n return (\n <Stack space={2}>\n {fieldHasMembers ? (\n <>\n {filteredMembers.map((member) => {\n if (member.kind === 'item') {\n return (\n <ArrayOfObjectsItem\n {...props}\n key={member.key}\n member={member}\n />\n )\n }\n\n return <MemberItemError key={member.key} member={member} />\n })}\n </>\n ) : null}\n\n {/* Give some feedback in the UI so the field doesn't look \"missing\" */}\n {!addButtonsAreVisible && !fieldHasMembers ? (\n <Card border tone=\"transparent\" padding={3} radius={2}>\n <Text size={1}>\n This internationalized field currently has no translations.\n </Text>\n </Card>\n ) : null}\n\n {addButtonsAreVisible ? (\n <Stack space={2}>\n <AddButtons\n languages={filteredLanguages}\n value={value}\n readOnly={readOnly}\n onClick={handleAddLanguage}\n />\n {buttonAddAll ? (\n <Button\n tone=\"primary\"\n mode=\"ghost\"\n disabled={readOnly || allLanguagesArePresent}\n icon={AddIcon}\n text={createAddAllTitle(value, filteredLanguages)}\n onClick={handleAddLanguage}\n />\n ) : null}\n </Stack>\n ) : null}\n </Stack>\n )\n}\n","import {SchemaType} from 'sanity'\n\nimport {ArrayFieldOptions} from '../schema/array'\n\nexport function getLanguagesFieldOption(\n schemaType: SchemaType | undefined\n): ArrayFieldOptions['languages'] | undefined {\n if (!schemaType) {\n return undefined\n }\n const languagesOption = (schemaType.options as ArrayFieldOptions)?.languages\n if (languagesOption) {\n return languagesOption\n }\n return getLanguagesFieldOption(schemaType.type)\n}\n","/* eslint-disable no-nested-ternary */\nimport {defineField, type FieldDefinition, type Rule} from 'sanity'\n\nimport {peek} from '../cache'\nimport {createFieldName} from '../components/createFieldName'\nimport {getSelectedValue} from '../components/getSelectedValue'\nimport InternationalizedArray from '../components/InternationalizedArray'\nimport type {Language, LanguageCallback, Value} from '../types'\nimport {getLanguagesFieldOption} from '../utils/getLanguagesFieldOption'\n\ntype ArrayFactoryConfig = {\n apiVersion: string\n select?: Record<string, string>\n languages: Language[] | LanguageCallback\n defaultLanguages?: string[]\n type: string | FieldDefinition\n}\n\nexport type ArrayFieldOptions = Pick<\n ArrayFactoryConfig,\n 'apiVersion' | 'select' | 'languages'\n>\n\nexport default (config: ArrayFactoryConfig): FieldDefinition<'array'> => {\n const {apiVersion, select, languages, type} = config\n const typeName = typeof type === `string` ? type : type.name\n const arrayName = createFieldName(typeName)\n const objectName = createFieldName(typeName, true)\n\n return defineField({\n name: arrayName,\n title: 'Internationalized array',\n type: 'array',\n components: {\n input: InternationalizedArray,\n },\n // These options are required for validation rules – not the custom input component\n options: {\n // @ts-expect-error - find out why it fails\n apiVersion,\n select,\n languages,\n },\n of: [\n defineField({\n ...(typeof type === 'string' ? {} : type),\n name: objectName,\n type: objectName,\n }),\n ],\n // @ts-expect-error - find out why it fails\n validation: (rule: Rule) =>\n rule.custom<Value[]>(async (value, context) => {\n if (!value) {\n return true\n }\n\n const selectedValue = getSelectedValue(select, context.document)\n const client = context.getClient({apiVersion})\n\n let contextLanguages: Language[] = []\n const languagesFieldOption = getLanguagesFieldOption(context?.type)\n\n if (Array.isArray(languagesFieldOption)) {\n contextLanguages = languagesFieldOption\n } else if (Array.isArray(peek(selectedValue))) {\n contextLanguages = peek(selectedValue) || []\n } else if (typeof languagesFieldOption === 'function') {\n contextLanguages = await languagesFieldOption(client, selectedValue)\n }\n\n if (value && value.length > contextLanguages.length) {\n return `Cannot be more than ${\n contextLanguages.length === 1\n ? `1 item`\n : `${contextLanguages.length} items`\n }`\n }\n\n const nonLanguageKeys = value?.length\n ? value.filter(\n (item) =>\n !contextLanguages.find((language) => item._key === language.id)\n )\n : []\n if (nonLanguageKeys.length) {\n return {\n message: `Array item keys must be valid languages registered to the field type`,\n paths: nonLanguageKeys.map((item) => [{_key: item._key}]),\n }\n }\n\n // Ensure there's no duplicate `language` fields\n type KeyedValues = {\n [key: string]: Value[]\n }\n\n const valuesByLanguage = value?.length\n ? value\n .filter((item) => Boolean(item?._key))\n .reduce((acc, cur) => {\n if (acc[cur._key]) {\n return {...acc, [cur._key]: [...acc[cur._key], cur]}\n }\n return {\n ...acc,\n [cur._key]: [cur],\n }\n }, {} as KeyedValues)\n : {}\n const duplicateValues = Object.values(valuesByLanguage)\n .filter((item) => item?.length > 1)\n .flat()\n if (duplicateValues.length) {\n return {\n message: 'There can only be one field per language',\n paths: duplicateValues.map((item) => [{_key: item._key}]),\n }\n }\n\n return true\n }),\n })\n}\n","import type {FieldProps} from 'sanity'\n\nexport default function InternationalizedField(props: FieldProps) {\n // Show reference field selector if there's a value\n if (props.schemaType.name === 'reference' && props.value) {\n return props.renderDefault({\n ...props,\n title: '',\n level: 0,\n })\n }\n\n return props.children\n}\n","import type {CardTone} from '@sanity/ui'\nimport type {FormNodeValidation} from 'sanity'\n\nexport function getToneFromValidation(\n validations: FormNodeValidation[]\n): CardTone | undefined {\n if (!validations?.length) {\n return undefined\n }\n\n const validationLevels = validations.map((v) => v.level)\n\n if (validationLevels.includes('error')) {\n return `critical`\n } else if (validationLevels.includes('warning')) {\n return `caution`\n }\n\n return undefined\n}\n","import {RemoveCircleIcon} from '@sanity/icons'\nimport {\n Button,\n Card,\n Flex,\n Label,\n Menu,\n MenuButton,\n MenuItem,\n Spinner,\n Stack,\n} from '@sanity/ui'\nimport type React from 'react'\nimport {useCallback, useMemo} from 'react'\nimport {type ObjectItemProps, useFormValue} from 'sanity'\nimport {set, unset} from 'sanity'\n\nimport {getToneFromValidation} from './getToneFromValidation'\nimport {useInternationalizedArrayContext} from './InternationalizedArrayContext'\n\ntype InternationalizedValue = {\n _type: string\n _key: string\n value: string\n}\n\nexport default function InternationalizedInput(\n props: ObjectItemProps<InternationalizedValue>\n) {\n const parentValue = useFormValue(\n props.path.slice(0, -1)\n ) as InternationalizedValue[]\n\n const inlineProps = {\n ...props.inputProps,\n // This is the magic that makes inline editing work?\n members: props.inputProps.members.filter(\n (m) => m.kind === 'field' && m.name === 'value'\n ),\n // This just overrides the type\n // TODO: Remove this as it shouldn't be necessary?\n value: props.value as InternationalizedValue,\n }\n\n const {validation, value, onChange, readOnly} = inlineProps\n\n // The parent array contains the languages from the plugin config\n const {languages} = useInternationalizedArrayContext()\n\n const languageKeysInUse = useMemo(\n () => parentValue?.map((v) => v._key) ?? [],\n [parentValue]\n )\n const keyIsValid = languages?.length\n ? languages.find((l) => l.id === value._key)\n : false\n\n // Changes the key of this item, ideally to a valid language\n const handleKeyChange = useCallback(\n (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {\n const languageId = event?.currentTarget?.value\n\n if (\n !value ||\n !languages?.length ||\n !languages.find((l) => l.id === languageId)\n ) {\n return\n }\n\n onChange([set(languageId, ['_key'])])\n },\n [onChange, value, languages]\n )\n\n // Removes this item from the array\n const handleUnset = useCallback(() => {\n onChange(unset())\n }, [onChange])\n\n if (!languages) {\n return <Spinner />\n }\n\n return (\n <Card paddingTop={2} tone={getToneFromValidation(validation)}>\n <Stack space={2}>\n <Card tone=\"inherit\">\n {keyIsValid ? (\n <Label muted size={1}>\n {value._key}\n </Label>\n ) : (\n <MenuButton\n button={<Button fontSize={1} text={`Change \"${value._key}\"`} />}\n id={`${value._key}-change-key`}\n menu={\n <Menu>\n {languages.map((language) => (\n <MenuItem\n disabled={languageKeysInUse.includes(language.id)}\n fontSize={1}\n key={language.id}\n text={language.id.toLocaleUpperCase()}\n value={language.id}\n // @ts-expect-error - fix typings\n onClick={handleKeyChange}\n />\n ))}\n </Menu>\n }\n popover={{portal: true}}\n />\n )}\n </Card>\n <Flex align=\"center\" gap={2}>\n <Card flex={1} tone=\"inherit\">\n {props.inputProps.renderInput(props.inputProps)}\n </Card>\n\n <Card tone=\"inherit\">\n <Button\n mode=\"bleed\"\n icon={RemoveCircleIcon}\n tone=\"critical\"\n disabled={readOnly}\n onClick={handleUnset}\n />\n </Card>\n </Flex>\n </Stack>\n </Card>\n )\n}\n","import {defineField, FieldDefinition} from 'sanity'\n\nimport {createFieldName} from '../components/createFieldName'\nimport InternationalizedField from '../components/InternationalizedField'\nimport InternationalizedInput from '../components/InternationalizedInput'\n\ntype ObjectFactoryConfig = {\n type: string | FieldDefinition\n}\n\nexport default (config: ObjectFactoryConfig): FieldDefinition<'object'> => {\n const {type} = config\n const typeName = typeof type === `string` ? type : type.name\n const objectName = createFieldName(typeName, true)\n\n return defineField({\n name: objectName,\n title: `Internationalized array ${type}`,\n type: 'object',\n components: {\n // @ts-expect-error - find out why it fails\n item: InternationalizedInput,\n },\n fields: [\n typeof type === `string`\n ? // Define a simple field if all we have is the name as a string\n defineField({\n name: 'value',\n type,\n components: {\n field: InternationalizedField,\n },\n })\n : // Pass in the configured options, but overwrite the name\n {\n ...type,\n name: 'value',\n components: {\n field: InternationalizedField,\n },\n },\n ],\n preview: {\n select: {\n title: 'value',\n subtitle: '_key',\n },\n },\n })\n}\n","import {\n isDocumentSchemaType,\n type ObjectField,\n type Path,\n type SchemaType,\n} from 'sanity'\n\ntype ObjectFieldWithPath = ObjectField<SchemaType> & {path: Path}\n\n/**\n * Flattens a document's schema type into a flat array of fields and includes their path\n */\nexport function flattenSchemaType(\n schemaType: SchemaType\n): ObjectFieldWithPath[] {\n if (!isDocumentSchemaType(schemaType)) {\n console.error(`Schema type is not a document`)\n return []\n }\n\n return extractInnerFields(schemaType.fields, [], 3)\n}\n\nfunction extractInnerFields(\n fields: ObjectField<SchemaType>[],\n path: Path,\n maxDepth: number\n): ObjectFieldWithPath[] {\n if (path.length >= maxDepth) {\n return []\n }\n\n return fields.reduce<ObjectFieldWithPath[]>((acc, field) => {\n const thisFieldWithPath = {path: [...path, field.name], ...field}\n\n if (field.type.jsonType === 'object') {\n const innerFields = extractInnerFields(\n field.type.fields,\n [...path, field.name],\n maxDepth\n )\n\n return [...acc, thisFieldWithPath, ...innerFields]\n } else if (\n field.type.jsonType === 'array' &&\n field.type.of.length &&\n field.type.of.some((item) => 'fields' in item)\n ) {\n const innerFields = extractInnerFields(\n // @ts-expect-error - Fix TS assertion for array fields\n field.type.of[0].fields,\n [...path, field.name],\n maxDepth\n )\n\n return [...acc, thisFieldWithPath, ...innerFields]\n }\n\n return [...acc, thisFieldWithPath]\n }, [])\n}\n","import {definePlugin, isObjectInputProps} from 'sanity'\n\nimport {InternationalizedArrayProvider} from './components/InternationalizedArrayContext'\nimport Preload from './components/Preload'\nimport {CONFIG_DEFAULT} from './constants'\nimport {internationalizedArrayFieldAction} from './fieldActions'\nimport array from './schema/array'\nimport object from './schema/object'\nimport {PluginConfig} from './types'\nimport {flattenSchemaType} from './utils/flattenSchemaType'\n\nexport const internationalizedArray = definePlugin<PluginConfig>((config) => {\n const pluginConfig = {...CONFIG_DEFAULT, ...config}\n const {\n apiVersion = '2022-11-27',\n select,\n languages,\n fieldTypes,\n defaultLanguages,\n buttonLocations,\n } = pluginConfig\n\n return {\n name: 'sanity-plugin-internationalized-array',\n // Preload languages for use throughout the Studio\n studio: Array.isArray(languages)\n ? undefined\n : {\n components: {\n layout: (props) => (\n <>\n <Preload apiVersion={apiVersion} languages={languages} />\n {props.renderDefault(props)}\n </>\n ),\n },\n },\n // Optional: render \"add language\" buttons as field actions\n document: {\n unstable_fieldActions: buttonLocations.includes('unstable__fieldAction')\n ? (prev) => [...prev, internationalizedArrayFieldAction]\n : undefined,\n },\n // Wrap document editor with a language provider\n form: {\n components: {\n input: (props) => {\n const isRootInput = props.id === 'root' && isObjectInputProps(props)\n\n if (!isRootInput) {\n return props.renderDefault(props)\n }\n\n const flatFieldTypeNames = flattenSchemaType(props.schemaType).map(\n (field) => field.type.name\n )\n const hasInternationalizedArray = flatFieldTypeNames.some((name) =>\n name.startsWith('internationalizedArray')\n )\n\n if (!hasInternationalizedArray) {\n return props.renderDefault(props)\n }\n\n return InternationalizedArrayProvider({\n ...props,\n internationalizedArray: pluginConfig,\n })\n },\n },\n },\n // Register custom schema types for the outer array and the inner object\n schema: {\n types: [\n ...fieldTypes.map((type) =>\n array({type, apiVersion, select, languages, defaultLanguages})\n ),\n ...fieldTypes.map((type) => object({type})),\n ],\n },\n }\n})\n"],"names":["suspend","jsx","Grid","Button","AddIcon","isSanityDocument","useToast","useDocumentPane","useCallback","setIfMissing","insert","PatchEvent","jsxs","Stack","Box","Text","get","createContext","useContext","internationalizedArray","useClient","useWorkspace","useFormBuilder","useDeferredValue","useMemo","equal","useLanguageFilterStudioContext","memo","useFormValue","defineDocumentFieldAction","TranslateIcon","Card","Code","useRef","useEffect","set","createElement","ArrayOfObjectsItem","MemberItemError","defineField","unset","Label","MenuButton","Menu","MenuItem","Flex","RemoveCircleIcon","Spinner","isDocumentSchemaType","definePlugin","Fragment","isObjectInputProps"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/cache.ts","../src/constants.ts","../src/utils/getDocumentsToTranslate.ts","../src/components/AddButtons.tsx","../src/components/DocumentAddButtons.tsx","../src/components/getSelectedValue.ts","../src/components/InternationalizedArrayContext.tsx","../src/components/Preload.tsx","../src/utils/checkAllLanguagesArePresent.ts","../src/utils/createAddAllTitle.ts","../src/utils/createValueSchemaTypeName.ts","../src/utils/createAddLanguagePatches.ts","../src/fieldActions/index.ts","../src/components/createFieldName.ts","../src/components/Feedback.tsx","../src/components/InternationalizedArray.tsx","../src/utils/getLanguagesFieldOption.ts","../src/schema/array.ts","../src/components/InternationalizedField.tsx","../src/components/getToneFromValidation.ts","../src/components/InternationalizedInput.tsx","../src/schema/object.ts","../src/utils/flattenSchemaType.ts","../src/plugin.tsx"],"sourcesContent":["/* eslint-disable @typescript-eslint/explicit-module-boundary-types */\n\nimport * as suspend from 'suspend-react'\n\nimport type {Language} from './types'\n\nexport const namespace = 'sanity-plugin-internationalized-array'\n\nexport const version = 'v0'\n\n// https://github.com/pmndrs/suspend-react#preloading\nexport const preload = (fn: () => Promise<Language[]>) =>\n suspend.preload(() => fn(), [version, namespace])\n\n// https://github.com/pmndrs/suspend-react#cache-busting\nexport const clear = () => suspend.clear([version, namespace])\n\n// https://github.com/pmndrs/suspend-react#peeking-into-entries-outside-of-suspense\nexport const peek = (selectedValue: Record<string, unknown>) =>\n suspend.peek([version, namespace, selectedValue]) as Language[] | undefined\n","import {PluginConfig} from './types'\n\nexport const MAX_COLUMNS = 7\n\nexport const CONFIG_DEFAULT: Required<PluginConfig> = {\n languages: [],\n select: {},\n defaultLanguages: [],\n fieldTypes: [],\n apiVersion: '2022-11-27',\n buttonLocations: ['field'],\n buttonAddAll: true,\n}\n","import {SanityDocument} from 'sanity'\n\nexport interface DocumentsToTranslate {\n path: (string | number)[]\n pathString: string\n _key: string\n _type: string\n [key: string]: unknown\n}\n\nexport const getDocumentsToTranslate = (\n value: SanityDocument | unknown,\n rootPath: (string | number)[] = []\n): DocumentsToTranslate[] => {\n if (Array.isArray(value)) {\n const arrayRootPath = [...rootPath]\n\n // if item contains internationalized return array\n const internationalizedValues = value.filter((item) => {\n if (Array.isArray(item)) return false\n\n if (typeof item === 'object') {\n const type = item?._type as string | undefined\n return (\n type?.startsWith('internationalizedArray') && type?.endsWith('Value')\n )\n }\n return false\n })\n\n if (internationalizedValues.length > 0) {\n return internationalizedValues.map((internationalizedValue) => {\n return {\n ...internationalizedValue,\n path: arrayRootPath,\n pathString: arrayRootPath.join('.'),\n }\n })\n }\n\n if (value.length > 0) {\n return value\n .map((item, index) =>\n getDocumentsToTranslate(item, [...arrayRootPath, index])\n )\n .flat()\n }\n\n return []\n }\n if (typeof value === 'object' && value) {\n const startsWithUnderscoreRegex = /^_/\n const itemKeys = Object.keys(value).filter(\n (key) => !key.match(startsWithUnderscoreRegex)\n ) as (keyof typeof value)[]\n\n return itemKeys\n .map((item) => {\n const selectedValue = value[item] as unknown\n const path = [...rootPath, item]\n return getDocumentsToTranslate(selectedValue, path)\n })\n .flat()\n }\n return []\n}\n","import {AddIcon} from '@sanity/icons'\nimport {Button, Grid} from '@sanity/ui'\nimport type React from 'react'\n\nimport {MAX_COLUMNS} from '../constants'\nimport type {Language, Value} from '../types'\n\ntype AddButtonsProps = {\n languages: Language[]\n readOnly: boolean\n value: Value[] | undefined\n onClick: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void\n}\n\nexport default function AddButtons(props: AddButtonsProps) {\n const {languages, readOnly, value, onClick} = props\n\n return languages.length > 0 ? (\n <Grid columns={Math.min(languages.length, MAX_COLUMNS)} gap={2}>\n {languages.map((language) => (\n <Button\n key={language.id}\n tone=\"primary\"\n mode=\"ghost\"\n fontSize={1}\n disabled={\n readOnly ||\n Boolean(value?.find((item) => item._key === language.id))\n }\n text={language.id.toUpperCase()}\n // Only show plus icon if there's one row or less\n icon={languages.length > MAX_COLUMNS ? undefined : AddIcon}\n value={language.id}\n onClick={onClick}\n />\n ))}\n </Grid>\n ) : null\n}\n","import {Box, Stack, Text, useToast} from '@sanity/ui'\nimport React, {useCallback} from 'react'\nimport {\n FormInsertPatch,\n FormSetIfMissingPatch,\n insert,\n isSanityDocument,\n PatchEvent,\n setIfMissing,\n} from 'sanity'\nimport {useDocumentPane} from 'sanity/structure'\n\nimport {\n DocumentsToTranslate,\n getDocumentsToTranslate,\n} from '../utils/getDocumentsToTranslate'\nimport AddButtons from './AddButtons'\nimport {useInternationalizedArrayContext} from './InternationalizedArrayContext'\n\ntype DocumentAddButtonsProps = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n value: Record<string, any> | undefined\n}\nexport default function DocumentAddButtons(props: DocumentAddButtonsProps) {\n const {filteredLanguages} = useInternationalizedArrayContext()\n const value = isSanityDocument(props.value) ? props.value : undefined\n\n const toast = useToast()\n const {onChange} = useDocumentPane()\n\n const documentsToTranslation = getDocumentsToTranslate(value, [])\n\n const handleDocumentButtonClick = useCallback(\n async (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {\n const languageId = event.currentTarget.value\n if (!languageId) {\n toast.push({\n status: 'error',\n title: 'No language selected',\n })\n return\n }\n const alreadyTranslated = documentsToTranslation.filter(\n (translation) => translation?._key === languageId\n )\n const removeDuplicates = documentsToTranslation.reduce<\n DocumentsToTranslate[]\n >((filteredTranslations, translation) => {\n if (\n alreadyTranslated.filter(\n (alreadyTranslation) =>\n alreadyTranslation.pathString === translation.pathString\n ).length > 0\n ) {\n return filteredTranslations\n }\n const translationAlreadyExists = filteredTranslations.filter(\n (filteredTranslation) => filteredTranslation.path === translation.path\n )\n\n if (translationAlreadyExists.length > 0) {\n return filteredTranslations\n }\n return [...filteredTranslations, translation]\n }, [])\n if (removeDuplicates.length === 0) {\n toast.push({\n status: 'error',\n title: 'No internationalizedArray fields found in document root',\n })\n return\n }\n\n // Write a new patch for each empty field\n const patches: (FormSetIfMissingPatch | FormInsertPatch)[] = []\n\n for (const toTranslate of removeDuplicates) {\n const path = toTranslate.path\n\n const ifMissing = setIfMissing([], path)\n const insertValue = insert(\n [\n {\n _key: languageId,\n _type: toTranslate._type,\n value: undefined,\n },\n ],\n 'after',\n [...path, -1]\n )\n patches.push(ifMissing)\n patches.push(insertValue)\n }\n\n onChange(PatchEvent.from(patches.flat()))\n },\n [documentsToTranslation, onChange, toast]\n )\n return (\n <Stack space={3}>\n <Box>\n <Text size={1} weight=\"semibold\">\n Add translation to internationalized fields\n </Text>\n </Box>\n <AddButtons\n languages={filteredLanguages}\n readOnly={false}\n value={undefined}\n onClick={handleDocumentButtonClick}\n />\n </Stack>\n )\n}\n","import {get} from 'lodash'\n\nexport const getSelectedValue = (\n select: Record<string, string> | undefined,\n document:\n | {\n [x: string]: unknown\n }\n | undefined\n): Record<string, unknown> => {\n if (!select || !document) {\n return {}\n }\n\n const selection: Record<string, string> = select || {}\n const selectedValue: Record<string, unknown> = {}\n for (const [key, path] of Object.entries(selection)) {\n let value = get(document, path)\n if (Array.isArray(value)) {\n // If there are references in the array, ensure they have `_ref` set, otherwise they are considered empty and can safely be ignored\n value = value.filter((item) =>\n typeof item === 'object'\n ? item?._type === 'reference' && '_ref' in item\n : true\n )\n }\n selectedValue[key] = value\n }\n\n return selectedValue\n}\n","import {useLanguageFilterStudioContext} from '@sanity/language-filter'\nimport {Stack} from '@sanity/ui'\nimport equal from 'fast-deep-equal'\nimport {createContext, useContext, useDeferredValue, useMemo} from 'react'\nimport {\n type ObjectInputProps,\n useClient,\n useFormBuilder,\n useWorkspace,\n} from 'sanity'\nimport {suspend} from 'suspend-react'\n\nimport {namespace, version} from '../cache'\nimport {CONFIG_DEFAULT} from '../constants'\nimport type {Language, PluginConfig} from '../types'\nimport DocumentAddButtons from './DocumentAddButtons'\nimport {getSelectedValue} from './getSelectedValue'\n\n// This provider makes the plugin config available to all components in the document form\n// But with languages resolved and filtered languages updated base on @sanity/language-filter\n\ntype InternationalizedArrayContextProps = Required<PluginConfig> & {\n languages: Language[]\n filteredLanguages: Language[]\n}\n\nexport const InternationalizedArrayContext =\n createContext<InternationalizedArrayContextProps>({\n ...CONFIG_DEFAULT,\n languages: [],\n filteredLanguages: [],\n })\n\nexport function useInternationalizedArrayContext() {\n return useContext(InternationalizedArrayContext)\n}\n\ntype InternationalizedArrayProviderProps = ObjectInputProps & {\n internationalizedArray: Required<PluginConfig>\n}\n\nexport function InternationalizedArrayProvider(\n props: InternationalizedArrayProviderProps\n) {\n const {internationalizedArray} = props\n\n const client = useClient({apiVersion: internationalizedArray.apiVersion})\n const workspace = useWorkspace()\n const {value: document} = useFormBuilder()\n const deferredDocument = useDeferredValue(document)\n const selectedValue = useMemo(\n () => getSelectedValue(internationalizedArray.select, deferredDocument),\n [internationalizedArray.select, deferredDocument]\n )\n\n // Fetch or return languages\n const languages = Array.isArray(internationalizedArray.languages)\n ? internationalizedArray.languages\n : suspend(\n // eslint-disable-next-line require-await\n async () => {\n if (typeof internationalizedArray.languages === 'function') {\n return internationalizedArray.languages(client, selectedValue)\n }\n return internationalizedArray.languages\n },\n [version, namespace, selectedValue, workspace],\n {equal}\n )\n\n // Filter out some languages if language filter is enabled\n const {selectedLanguageIds, options: languageFilterOptions} =\n useLanguageFilterStudioContext()\n\n const filteredLanguages = useMemo(() => {\n const documentType = deferredDocument ? deferredDocument._type : undefined\n const languageFilterEnabled =\n typeof documentType === 'string' &&\n languageFilterOptions.documentTypes.includes(documentType)\n\n return languageFilterEnabled\n ? languages.filter((language) =>\n selectedLanguageIds.includes(language.id)\n )\n : languages\n }, [deferredDocument, languageFilterOptions, languages, selectedLanguageIds])\n\n const showDocumentButtons =\n internationalizedArray.buttonLocations.includes('document')\n\n return (\n <InternationalizedArrayContext.Provider\n value={{\n ...internationalizedArray,\n languages,\n filteredLanguages,\n }}\n >\n {showDocumentButtons ? (\n <Stack space={5}>\n <DocumentAddButtons value={props.value} />\n {props.renderDefault(props)}\n </Stack>\n ) : (\n props.renderDefault(props)\n )}\n </InternationalizedArrayContext.Provider>\n )\n}\n","import {memo} from 'react'\nimport {useClient} from 'sanity'\n\nimport {peek, preload} from '../cache'\nimport type {PluginConfig} from '../types'\n\nexport default memo(function Preload(\n props: Required<Pick<PluginConfig, 'apiVersion' | 'languages'>>\n) {\n const client = useClient({apiVersion: props.apiVersion})\n if (!Array.isArray(peek({}))) {\n // eslint-disable-next-line require-await\n preload(async () =>\n Array.isArray(props.languages)\n ? props.languages\n : props.languages(client, {})\n )\n }\n\n return null\n})\n","import {Language, Value} from '../types'\n\nexport function checkAllLanguagesArePresent(\n languages: Language[],\n value: Value[] | undefined\n): boolean {\n const filteredLanguageIds = languages.map((l) => l.id)\n const languagesInUseIds = value ? value.map((v) => v._key) : []\n\n return (\n languagesInUseIds.length === filteredLanguageIds.length &&\n languagesInUseIds.every((l) => filteredLanguageIds.includes(l))\n )\n}\n","import {Language, Value} from '../types'\n\nexport function createAddAllTitle(\n value: Value[] | undefined,\n languages: Language[]\n): string {\n if (value?.length) {\n return `Add missing ${\n languages.length - value.length === 1 ? `language` : `languages`\n }`\n }\n\n return languages.length === 1\n ? `Add ${languages[0].title} Field`\n : `Add all languages`\n}\n","import {SchemaType} from 'sanity'\n\nexport function createValueSchemaTypeName(schemaType: SchemaType): string {\n return `${schemaType.name}Value`\n}\n","import {FormInsertPatch, insert, Path, SchemaType} from 'sanity'\n\nimport {Language, Value} from '../types'\nimport {createValueSchemaTypeName} from './createValueSchemaTypeName'\n\ntype AddConfig = {\n // New keys to add to the field\n addLanguageKeys: string[]\n // Schema of the current field\n schemaType: SchemaType\n // All languages registered in the plugin\n languages: Language[]\n // Languages that are currently visible\n filteredLanguages: Language[]\n // Current value of the internationalizedArray field\n value?: Value[]\n // Path to this item\n path?: Path\n}\n\nexport function createAddLanguagePatches(config: AddConfig): FormInsertPatch[] {\n const {\n addLanguageKeys,\n schemaType,\n languages,\n filteredLanguages,\n value,\n path = [],\n } = config\n\n const itemBase = {_type: createValueSchemaTypeName(schemaType)}\n\n // Create new items\n const getNewItems = () => {\n if (Array.isArray(addLanguageKeys) && addLanguageKeys.length > 0) {\n return addLanguageKeys.map((id) => ({\n ...itemBase,\n _key: id,\n }))\n }\n\n return filteredLanguages\n .filter((language) =>\n value?.length ? !value.find((v) => v._key === language.id) : true\n )\n .map((language) => ({\n ...itemBase,\n _key: language.id,\n }))\n }\n const newItems = getNewItems()\n\n // Insert new items in the correct order\n const languagesInUse = value?.length ? value.map((v) => v) : []\n\n const insertions = newItems.map((item) => {\n // What's the original index of this language?\n const languageIndex = languages.findIndex((l) => item._key === l.id)\n\n // What languages are there beyond that index?\n const remainingLanguages = languages.slice(languageIndex + 1)\n\n // So what is the index in the current value array of the next language in the language array?\n const nextLanguageIndex = languagesInUse.findIndex((l) =>\n // eslint-disable-next-line max-nested-callbacks\n remainingLanguages.find((r) => r.id === l._key)\n )\n\n // Keep local state up to date incase multiple insertions are being made\n if (nextLanguageIndex < 0) {\n languagesInUse.push(item)\n } else {\n languagesInUse.splice(nextLanguageIndex, 0, item)\n }\n\n return nextLanguageIndex < 0\n ? // No next language (-1), add to end of array\n insert([item], 'after', [...path, nextLanguageIndex])\n : // Next language found, insert before that\n insert([item], 'before', [...path, nextLanguageIndex])\n })\n\n return insertions\n}\n","import {AddIcon, TranslateIcon} from '@sanity/icons'\nimport {useCallback} from 'react'\nimport {\n defineDocumentFieldAction,\n type DocumentFieldActionItem,\n type DocumentFieldActionProps,\n PatchEvent,\n setIfMissing,\n useFormValue,\n} from 'sanity'\nimport {useDocumentPane} from 'sanity/structure'\n\nimport {useInternationalizedArrayContext} from '../components/InternationalizedArrayContext'\nimport type {Language, Value} from '../types'\nimport {checkAllLanguagesArePresent} from '../utils/checkAllLanguagesArePresent'\nimport {createAddAllTitle} from '../utils/createAddAllTitle'\nimport {createAddLanguagePatches} from '../utils/createAddLanguagePatches'\n\nconst createTranslateFieldActions: (\n fieldActionProps: DocumentFieldActionProps,\n context: {\n languages: Language[]\n filteredLanguages: Language[]\n }\n) => DocumentFieldActionItem[] = (\n fieldActionProps,\n {languages, filteredLanguages}\n) =>\n languages.map((language) => {\n const value = useFormValue(fieldActionProps.path) as Value[]\n const disabled =\n value && Array.isArray(value)\n ? Boolean(value?.find((item) => item._key === language.id))\n : false\n const hidden = !filteredLanguages.some((f) => f.id === language.id)\n\n const {onChange} = useDocumentPane()\n\n const onAction = useCallback(() => {\n const {schemaType, path} = fieldActionProps\n\n const addLanguageKeys = [language.id]\n const patches = createAddLanguagePatches({\n addLanguageKeys,\n schemaType,\n languages,\n filteredLanguages,\n value,\n path,\n })\n\n onChange(PatchEvent.from([setIfMissing([], path), ...patches]))\n }, [language.id, value, onChange])\n\n return {\n type: 'action',\n icon: AddIcon,\n onAction,\n title: language.title,\n hidden,\n disabled,\n }\n })\n\nconst AddMissingTranslationsFieldAction: (\n fieldActionProps: DocumentFieldActionProps,\n context: {\n languages: Language[]\n filteredLanguages: Language[]\n }\n) => DocumentFieldActionItem = (\n fieldActionProps,\n {languages, filteredLanguages}\n) => {\n const value = useFormValue(fieldActionProps.path) as Value[]\n const disabled = value && value.length === filteredLanguages.length\n const hidden = checkAllLanguagesArePresent(filteredLanguages, value)\n\n const {onChange} = useDocumentPane()\n\n const onAction = useCallback(() => {\n const {schemaType, path} = fieldActionProps\n\n const addLanguageKeys: string[] = []\n const patches = createAddLanguagePatches({\n addLanguageKeys,\n schemaType,\n languages,\n filteredLanguages,\n value,\n path,\n })\n\n onChange(PatchEvent.from([setIfMissing([], path), ...patches]))\n }, [fieldActionProps, filteredLanguages, languages, onChange, value])\n\n return {\n type: 'action',\n icon: AddIcon,\n onAction,\n title: createAddAllTitle(value, filteredLanguages),\n disabled,\n hidden,\n }\n}\n\nexport const internationalizedArrayFieldAction = defineDocumentFieldAction({\n name: 'internationalizedArray',\n useAction(fieldActionProps) {\n const isInternationalizedArrayField =\n fieldActionProps?.schemaType?.type?.name.startsWith(\n 'internationalizedArray'\n )\n const {languages, filteredLanguages} = useInternationalizedArrayContext()\n\n const translateFieldActions = createTranslateFieldActions(\n fieldActionProps,\n {languages, filteredLanguages}\n )\n\n return {\n type: 'group',\n icon: TranslateIcon,\n title: 'Add Translation',\n renderAsButton: true,\n children: isInternationalizedArrayField\n ? [\n ...translateFieldActions,\n AddMissingTranslationsFieldAction(fieldActionProps, {\n languages,\n filteredLanguages,\n }),\n ]\n : [],\n hidden: !isInternationalizedArrayField,\n }\n },\n})\n","export function camelCase(string: string): string {\n return string.replace(/-([a-z])/g, (g) => g[1].toUpperCase())\n}\n\nexport function titleCase(string: string): string {\n return string\n .split(` `)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(` `)\n}\n\nexport function pascalCase(string: string): string {\n return titleCase(camelCase(string))\n}\n\nexport function createFieldName(name: string, addValue = false): string {\n return addValue\n ? [`internationalizedArray`, pascalCase(name), `Value`].join(``)\n : [`internationalizedArray`, pascalCase(name)].join(``)\n}\n","import {Card, Code, Stack, Text} from '@sanity/ui'\n\nconst schemaExample = {\n languages: [\n {id: 'en', title: 'English'},\n {id: 'no', title: 'Norsk'},\n ],\n}\n\nexport default function Feedback() {\n return (\n <Card tone=\"caution\" border radius={2} padding={3}>\n <Stack space={4}>\n <Text>\n An array of language objects must be passed into the{' '}\n <code>internationalizedArray</code> helper function, each with an{' '}\n <code>id</code> and <code>title</code> field. Example:\n </Text>\n <Card padding={2} border radius={2}>\n <Code size={1} language=\"javascript\">\n {JSON.stringify(schemaExample, null, 2)}\n </Code>\n </Card>\n </Stack>\n </Card>\n )\n}\n","import {AddIcon} from '@sanity/icons'\nimport {useLanguageFilterStudioContext} from '@sanity/language-filter'\nimport {Button, Card, Stack, Text, useToast} from '@sanity/ui'\nimport type React from 'react'\nimport {useCallback, useEffect, useMemo, useRef} from 'react'\nimport {\n type ArrayOfObjectsInputProps,\n ArrayOfObjectsItem,\n type ArraySchemaType,\n MemberItemError,\n set,\n setIfMissing,\n useFormValue,\n} from 'sanity'\n\nimport type {Value} from '../types'\nimport {checkAllLanguagesArePresent} from '../utils/checkAllLanguagesArePresent'\nimport {createAddAllTitle} from '../utils/createAddAllTitle'\nimport {createAddLanguagePatches} from '../utils/createAddLanguagePatches'\nimport AddButtons from './AddButtons'\nimport Feedback from './Feedback'\nimport {useInternationalizedArrayContext} from './InternationalizedArrayContext'\n\nexport type InternationalizedArrayProps = ArrayOfObjectsInputProps<\n Value,\n ArraySchemaType\n>\n\nexport default function InternationalizedArray(\n props: InternationalizedArrayProps\n) {\n const {members, value, schemaType, onChange} = props\n\n const readOnly =\n typeof schemaType.readOnly === 'boolean' ? schemaType.readOnly : false\n const toast = useToast()\n\n const {\n languages,\n filteredLanguages,\n defaultLanguages,\n buttonAddAll,\n buttonLocations,\n } = useInternationalizedArrayContext()\n\n // Support updating the UI if languageFilter is installed\n const {selectedLanguageIds, options: languageFilterOptions} =\n useLanguageFilterStudioContext()\n const documentType = useFormValue(['_type'])\n const languageFilterEnabled =\n typeof documentType === 'string' &&\n languageFilterOptions.documentTypes.includes(documentType)\n\n const filteredMembers = useMemo(\n () =>\n languageFilterEnabled\n ? members.filter((member) => {\n // This member is the outer object created by the plugin\n // Satisfy TS\n if (member.kind !== 'item') {\n return false\n }\n\n // This is the inner \"value\" field member created by this plugin\n const valueMember = member.item.members[0]\n\n // Satisfy TS\n if (valueMember.kind !== 'field') {\n return false\n }\n\n return languageFilterOptions.filterField(\n member.item.schemaType,\n valueMember,\n selectedLanguageIds\n )\n })\n : members,\n [languageFilterEnabled, members, languageFilterOptions, selectedLanguageIds]\n )\n\n const handleAddLanguage = useCallback(\n async (\n param?: React.MouseEvent<HTMLButtonElement, MouseEvent> | string[]\n ) => {\n if (!filteredLanguages?.length) {\n return\n }\n\n const addLanguageKeys: string[] = Array.isArray(param)\n ? param\n : ([param?.currentTarget?.value].filter(Boolean) as string[])\n\n const patches = createAddLanguagePatches({\n addLanguageKeys,\n schemaType,\n languages,\n filteredLanguages,\n value,\n })\n\n onChange([setIfMissing([]), ...patches])\n },\n [filteredLanguages, languages, onChange, schemaType, value]\n )\n\n // Create default fields if the document is not yet created\n const documentCreatedAt = useFormValue(['_createdAt'])\n const hasAddedDefaultLanguages = useRef(Boolean(documentCreatedAt))\n\n // Write default languages\n useEffect(() => {\n const shouldAddDefaultLanguages =\n !hasAddedDefaultLanguages.current &&\n !value &&\n !documentCreatedAt &&\n Array.isArray(defaultLanguages) &&\n defaultLanguages.length > 0\n\n if (shouldAddDefaultLanguages) {\n handleAddLanguage(defaultLanguages)\n }\n\n return () => {\n if (shouldAddDefaultLanguages) {\n hasAddedDefaultLanguages.current = true\n }\n }\n }, [defaultLanguages, documentCreatedAt, handleAddLanguage, value])\n\n // TODO: This is reordering and re-setting the whole array, it could be surgical\n const handleRestoreOrder = useCallback(() => {\n if (!value?.length || !languages?.length) {\n return\n }\n\n // Create a new value array in the correct order\n // This would also strip out values that don't have a language as the key\n const updatedValue = value\n .reduce((acc, v) => {\n const newIndex = languages.findIndex((l) => l.id === v?._key)\n\n if (newIndex > -1) {\n acc[newIndex] = v\n }\n\n return acc\n }, [] as Value[])\n .filter(Boolean)\n\n if (value?.length !== updatedValue.length) {\n toast.push({\n title: 'There was an error reordering languages',\n status: 'warning',\n })\n }\n\n onChange(set(updatedValue))\n }, [toast, languages, onChange, value])\n\n const allKeysAreLanguages = useMemo(() => {\n if (!value?.length || !languages?.length) {\n return true\n }\n\n return value?.every((v) => languages.find((l) => l?.id === v?._key))\n }, [value, languages])\n\n // Check languages are in the correct order\n const languagesInUse = useMemo(\n () =>\n languages && languages.length > 1\n ? languages.filter((l) => value?.find((v) => v._key === l.id))\n : [],\n [languages, value]\n )\n\n const languagesOutOfOrder = useMemo(() => {\n if (!value?.length || !languagesInUse.length) {\n return []\n }\n\n return value\n .map((v, vIndex) =>\n vIndex === languagesInUse.findIndex((l) => l.id === v._key) ? null : v\n )\n .filter(Boolean)\n }, [value, languagesInUse])\n\n const languagesAreValid = useMemo(\n () =>\n !languages?.length ||\n (languages?.length && languages.every((item) => item.id && item.title)),\n [languages]\n )\n\n // Automatically restore order of fields\n useEffect(() => {\n if (languagesOutOfOrder.length > 0 && allKeysAreLanguages) {\n handleRestoreOrder()\n }\n }, [languagesOutOfOrder, allKeysAreLanguages, handleRestoreOrder])\n\n // compare value keys with possible languages\n const allLanguagesArePresent = useMemo(\n () => checkAllLanguagesArePresent(filteredLanguages, value),\n [filteredLanguages, value]\n )\n\n if (!languagesAreValid) {\n return <Feedback />\n }\n\n const addButtonsAreVisible =\n // Plugin was configured to display buttons here (default!)\n buttonLocations.includes('field') &&\n // There's at least one language visible\n filteredLanguages?.length > 0 &&\n // Not every language has a value yet\n !allLanguagesArePresent\n const fieldHasMembers = members?.length > 0\n\n return (\n <Stack space={2}>\n {fieldHasMembers ? (\n <>\n {filteredMembers.map((member) => {\n if (member.kind === 'item') {\n return (\n <ArrayOfObjectsItem\n {...props}\n key={member.key}\n member={member}\n />\n )\n }\n\n return <MemberItemError key={member.key} member={member} />\n })}\n </>\n ) : null}\n\n {/* Give some feedback in the UI so the field doesn't look \"missing\" */}\n {!addButtonsAreVisible && !fieldHasMembers ? (\n <Card border tone=\"transparent\" padding={3} radius={2}>\n <Text size={1}>\n This internationalized field currently has no translations.\n </Text>\n </Card>\n ) : null}\n\n {addButtonsAreVisible ? (\n <Stack space={2}>\n <AddButtons\n languages={filteredLanguages}\n value={value}\n readOnly={readOnly}\n onClick={handleAddLanguage}\n />\n {buttonAddAll ? (\n <Button\n tone=\"primary\"\n mode=\"ghost\"\n disabled={readOnly || allLanguagesArePresent}\n icon={AddIcon}\n text={createAddAllTitle(value, filteredLanguages)}\n onClick={handleAddLanguage}\n />\n ) : null}\n </Stack>\n ) : null}\n </Stack>\n )\n}\n","import {SchemaType} from 'sanity'\n\nimport {ArrayFieldOptions} from '../schema/array'\n\nexport function getLanguagesFieldOption(\n schemaType: SchemaType | undefined\n): ArrayFieldOptions['languages'] | undefined {\n if (!schemaType) {\n return undefined\n }\n const languagesOption = (schemaType.options as ArrayFieldOptions)?.languages\n if (languagesOption) {\n return languagesOption\n }\n return getLanguagesFieldOption(schemaType.type)\n}\n","/* eslint-disable no-nested-ternary */\nimport {defineField, type FieldDefinition, type Rule} from 'sanity'\n\nimport {peek} from '../cache'\nimport {createFieldName} from '../components/createFieldName'\nimport {getSelectedValue} from '../components/getSelectedValue'\nimport InternationalizedArray from '../components/InternationalizedArray'\nimport type {Language, LanguageCallback, Value} from '../types'\nimport {getLanguagesFieldOption} from '../utils/getLanguagesFieldOption'\n\ntype ArrayFactoryConfig = {\n apiVersion: string\n select?: Record<string, string>\n languages: Language[] | LanguageCallback\n defaultLanguages?: string[]\n type: string | FieldDefinition\n}\n\nexport type ArrayFieldOptions = Pick<\n ArrayFactoryConfig,\n 'apiVersion' | 'select' | 'languages'\n>\n\nexport default (config: ArrayFactoryConfig): FieldDefinition<'array'> => {\n const {apiVersion, select, languages, type} = config\n const typeName = typeof type === `string` ? type : type.name\n const arrayName = createFieldName(typeName)\n const objectName = createFieldName(typeName, true)\n\n return defineField({\n name: arrayName,\n title: 'Internationalized array',\n type: 'array',\n components: {\n input: InternationalizedArray,\n },\n // These options are required for validation rules – not the custom input component\n options: {apiVersion, select, languages},\n of: [\n defineField({\n ...(typeof type === 'string' ? {} : type),\n name: objectName,\n type: objectName,\n }),\n ],\n validation: (rule: Rule) =>\n rule.custom<Value[]>(async (value, context) => {\n if (!value) {\n return true\n }\n\n const selectedValue = getSelectedValue(select, context.document)\n const client = context.getClient({apiVersion})\n\n let contextLanguages: Language[] = []\n const languagesFieldOption = getLanguagesFieldOption(context?.type)\n\n if (Array.isArray(languagesFieldOption)) {\n contextLanguages = languagesFieldOption\n } else if (Array.isArray(peek(selectedValue))) {\n contextLanguages = peek(selectedValue) || []\n } else if (typeof languagesFieldOption === 'function') {\n contextLanguages = await languagesFieldOption(client, selectedValue)\n }\n\n if (value && value.length > contextLanguages.length) {\n return `Cannot be more than ${\n contextLanguages.length === 1\n ? `1 item`\n : `${contextLanguages.length} items`\n }`\n }\n\n const nonLanguageKeys = value?.length\n ? value.filter(\n (item) =>\n !contextLanguages.find((language) => item._key === language.id)\n )\n : []\n if (nonLanguageKeys.length) {\n return {\n message: `Array item keys must be valid languages registered to the field type`,\n paths: nonLanguageKeys.map((item) => [{_key: item._key}]),\n }\n }\n\n // Ensure there's no duplicate `language` fields\n type KeyedValues = {\n [key: string]: Value[]\n }\n\n const valuesByLanguage = value?.length\n ? value\n .filter((item) => Boolean(item?._key))\n .reduce((acc, cur) => {\n if (acc[cur._key]) {\n return {...acc, [cur._key]: [...acc[cur._key], cur]}\n }\n return {\n ...acc,\n [cur._key]: [cur],\n }\n }, {} as KeyedValues)\n : {}\n const duplicateValues = Object.values(valuesByLanguage)\n .filter((item) => item?.length > 1)\n .flat()\n if (duplicateValues.length) {\n return {\n message: 'There can only be one field per language',\n paths: duplicateValues.map((item) => [{_key: item._key}]),\n }\n }\n\n return true\n }),\n })\n}\n","import type {FieldProps} from 'sanity'\n\nexport default function InternationalizedField(props: FieldProps) {\n // Show reference field selector if there's a value\n if (props.schemaType.name === 'reference' && props.value) {\n return props.renderDefault({\n ...props,\n title: '',\n level: 0,\n })\n }\n\n return props.children\n}\n","import type {CardTone} from '@sanity/ui'\nimport type {FormNodeValidation} from 'sanity'\n\nexport function getToneFromValidation(\n validations: FormNodeValidation[]\n): CardTone | undefined {\n if (!validations?.length) {\n return undefined\n }\n\n const validationLevels = validations.map((v) => v.level)\n\n if (validationLevels.includes('error')) {\n return `critical`\n } else if (validationLevels.includes('warning')) {\n return `caution`\n }\n\n return undefined\n}\n","import {RemoveCircleIcon} from '@sanity/icons'\nimport {\n Button,\n Card,\n Flex,\n Label,\n Menu,\n MenuButton,\n MenuItem,\n Spinner,\n Stack,\n} from '@sanity/ui'\nimport type React from 'react'\nimport {useCallback, useMemo} from 'react'\nimport {type ObjectItemProps, useFormValue} from 'sanity'\nimport {set, unset} from 'sanity'\n\nimport {getToneFromValidation} from './getToneFromValidation'\nimport {useInternationalizedArrayContext} from './InternationalizedArrayContext'\n\ntype InternationalizedValue = {\n _type: string\n _key: string\n value: string\n}\n\nexport default function InternationalizedInput(\n props: ObjectItemProps<InternationalizedValue>\n) {\n const parentValue = useFormValue(\n props.path.slice(0, -1)\n ) as InternationalizedValue[]\n\n const inlineProps = {\n ...props.inputProps,\n // This is the magic that makes inline editing work?\n members: props.inputProps.members.filter(\n (m) => m.kind === 'field' && m.name === 'value'\n ),\n // This just overrides the type\n // TODO: Remove this as it shouldn't be necessary?\n value: props.value as InternationalizedValue,\n }\n\n const {validation, value, onChange, readOnly} = inlineProps\n\n // The parent array contains the languages from the plugin config\n const {languages} = useInternationalizedArrayContext()\n\n const languageKeysInUse = useMemo(\n () => parentValue?.map((v) => v._key) ?? [],\n [parentValue]\n )\n const keyIsValid = languages?.length\n ? languages.find((l) => l.id === value._key)\n : false\n\n // Changes the key of this item, ideally to a valid language\n const handleKeyChange = useCallback(\n (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {\n const languageId = event?.currentTarget?.value\n\n if (\n !value ||\n !languages?.length ||\n !languages.find((l) => l.id === languageId)\n ) {\n return\n }\n\n onChange([set(languageId, ['_key'])])\n },\n [onChange, value, languages]\n )\n\n // Removes this item from the array\n const handleUnset = useCallback(() => {\n onChange(unset())\n }, [onChange])\n\n if (!languages) {\n return <Spinner />\n }\n\n return (\n <Card paddingTop={2} tone={getToneFromValidation(validation)}>\n <Stack space={2}>\n <Card tone=\"inherit\">\n {keyIsValid ? (\n <Label muted size={1}>\n {value._key}\n </Label>\n ) : (\n <MenuButton\n button={<Button fontSize={1} text={`Change \"${value._key}\"`} />}\n id={`${value._key}-change-key`}\n menu={\n <Menu>\n {languages.map((language) => (\n <MenuItem\n disabled={languageKeysInUse.includes(language.id)}\n fontSize={1}\n key={language.id}\n text={language.id.toLocaleUpperCase()}\n value={language.id}\n // @ts-expect-error - fix typings\n onClick={handleKeyChange}\n />\n ))}\n </Menu>\n }\n popover={{portal: true}}\n />\n )}\n </Card>\n <Flex align=\"center\" gap={2}>\n <Card flex={1} tone=\"inherit\">\n {props.inputProps.renderInput(props.inputProps)}\n </Card>\n\n <Card tone=\"inherit\">\n <Button\n mode=\"bleed\"\n icon={RemoveCircleIcon}\n tone=\"critical\"\n disabled={readOnly}\n onClick={handleUnset}\n />\n </Card>\n </Flex>\n </Stack>\n </Card>\n )\n}\n","import {defineField, FieldDefinition} from 'sanity'\n\nimport {createFieldName} from '../components/createFieldName'\nimport InternationalizedField from '../components/InternationalizedField'\nimport InternationalizedInput from '../components/InternationalizedInput'\n\ntype ObjectFactoryConfig = {\n type: string | FieldDefinition\n}\n\nexport default (config: ObjectFactoryConfig): FieldDefinition<'object'> => {\n const {type} = config\n const typeName = typeof type === `string` ? type : type.name\n const objectName = createFieldName(typeName, true)\n\n return defineField({\n name: objectName,\n title: `Internationalized array ${type}`,\n type: 'object',\n components: {\n item: InternationalizedInput,\n },\n // @ts-expect-error - Address this typing issue with the inner object\n fields: [\n typeof type === `string`\n ? // Define a simple field if all we have is the name as a string\n defineField({\n name: 'value',\n type,\n components: {\n field: InternationalizedField,\n },\n })\n : // Pass in the configured options, but overwrite the name\n {\n ...type,\n name: 'value',\n components: {\n field: InternationalizedField,\n },\n },\n ],\n preview: {\n select: {\n title: 'value',\n subtitle: '_key',\n },\n },\n })\n}\n","import {\n isDocumentSchemaType,\n type ObjectField,\n type Path,\n type SchemaType,\n} from 'sanity'\n\ntype ObjectFieldWithPath = ObjectField<SchemaType> & {path: Path}\n\n/**\n * Flattens a document's schema type into a flat array of fields and includes their path\n */\nexport function flattenSchemaType(\n schemaType: SchemaType\n): ObjectFieldWithPath[] {\n if (!isDocumentSchemaType(schemaType)) {\n console.error(`Schema type is not a document`)\n return []\n }\n\n return extractInnerFields(schemaType.fields, [], 3)\n}\n\nfunction extractInnerFields(\n fields: ObjectField<SchemaType>[],\n path: Path,\n maxDepth: number\n): ObjectFieldWithPath[] {\n if (path.length >= maxDepth) {\n return []\n }\n\n return fields.reduce<ObjectFieldWithPath[]>((acc, field) => {\n const thisFieldWithPath = {path: [...path, field.name], ...field}\n\n if (field.type.jsonType === 'object') {\n const innerFields = extractInnerFields(\n field.type.fields,\n [...path, field.name],\n maxDepth\n )\n\n return [...acc, thisFieldWithPath, ...innerFields]\n } else if (\n field.type.jsonType === 'array' &&\n field.type.of.length &&\n field.type.of.some((item) => 'fields' in item)\n ) {\n const innerFields = extractInnerFields(\n // @ts-expect-error - Fix TS assertion for array fields\n field.type.of[0].fields,\n [...path, field.name],\n maxDepth\n )\n\n return [...acc, thisFieldWithPath, ...innerFields]\n }\n\n return [...acc, thisFieldWithPath]\n }, [])\n}\n","import {definePlugin, isObjectInputProps} from 'sanity'\n\nimport {InternationalizedArrayProvider} from './components/InternationalizedArrayContext'\nimport Preload from './components/Preload'\nimport {CONFIG_DEFAULT} from './constants'\nimport {internationalizedArrayFieldAction} from './fieldActions'\nimport array from './schema/array'\nimport object from './schema/object'\nimport {PluginConfig} from './types'\nimport {flattenSchemaType} from './utils/flattenSchemaType'\n\nexport const internationalizedArray = definePlugin<PluginConfig>((config) => {\n const pluginConfig = {...CONFIG_DEFAULT, ...config}\n const {\n apiVersion = '2022-11-27',\n select,\n languages,\n fieldTypes,\n defaultLanguages,\n buttonLocations,\n } = pluginConfig\n\n return {\n name: 'sanity-plugin-internationalized-array',\n // Preload languages for use throughout the Studio\n studio: Array.isArray(languages)\n ? undefined\n : {\n components: {\n layout: (props) => (\n <>\n <Preload apiVersion={apiVersion} languages={languages} />\n {props.renderDefault(props)}\n </>\n ),\n },\n },\n // Optional: render \"add language\" buttons as field actions\n document: {\n unstable_fieldActions: buttonLocations.includes('unstable__fieldAction')\n ? (prev) => [...prev, internationalizedArrayFieldAction]\n : undefined,\n },\n // Wrap document editor with a language provider\n form: {\n components: {\n input: (props) => {\n const isRootInput = props.id === 'root' && isObjectInputProps(props)\n\n if (!isRootInput) {\n return props.renderDefault(props)\n }\n\n const flatFieldTypeNames = flattenSchemaType(props.schemaType).map(\n (field) => field.type.name\n )\n const hasInternationalizedArray = flatFieldTypeNames.some((name) =>\n name.startsWith('internationalizedArray')\n )\n\n if (!hasInternationalizedArray) {\n return props.renderDefault(props)\n }\n\n return InternationalizedArrayProvider({\n ...props,\n internationalizedArray: pluginConfig,\n })\n },\n },\n },\n // Register custom schema types for the outer array and the inner object\n schema: {\n types: [\n ...fieldTypes.map((type) =>\n array({type, apiVersion, select, languages, defaultLanguages})\n ),\n ...fieldTypes.map((type) => object({type})),\n ],\n },\n }\n})\n"],"names":["suspend","jsx","Grid","Button","AddIcon","isSanityDocument","useToast","useDocumentPane","useCallback","setIfMissing","insert","PatchEvent","jsxs","Stack","Box","Text","get","createContext","useContext","internationalizedArray","useClient","useWorkspace","useFormBuilder","useDeferredValue","useMemo","equal","useLanguageFilterStudioContext","memo","useFormValue","defineDocumentFieldAction","TranslateIcon","Card","Code","useRef","useEffect","set","createElement","ArrayOfObjectsItem","MemberItemError","defineField","unset","Label","MenuButton","Menu","MenuItem","Flex","RemoveCircleIcon","Spinner","isDocumentSchemaType","definePlugin","Fragment","isObjectInputProps"],"mappings":"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"}
|