sanity-plugin-internationalized-array 3.2.2 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +3 -34
  3. package/{lib → dist}/index.d.ts +41 -61
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +896 -0
  6. package/dist/index.js.map +1 -0
  7. package/package.json +36 -74
  8. package/lib/index.d.mts +0 -149
  9. package/lib/index.esm.js +0 -854
  10. package/lib/index.esm.js.map +0 -1
  11. package/lib/index.js +0 -863
  12. package/lib/index.js.map +0 -1
  13. package/lib/index.mjs +0 -854
  14. package/lib/index.mjs.map +0 -1
  15. package/sanity.json +0 -8
  16. package/src/cache.ts +0 -148
  17. package/src/components/AddButtons.tsx +0 -60
  18. package/src/components/DocumentAddButtons.tsx +0 -183
  19. package/src/components/Feedback.tsx +0 -28
  20. package/src/components/InternationalizedArray.tsx +0 -286
  21. package/src/components/InternationalizedArrayContext.tsx +0 -136
  22. package/src/components/InternationalizedField.tsx +0 -57
  23. package/src/components/InternationalizedInput.tsx +0 -257
  24. package/src/components/Preload.tsx +0 -31
  25. package/src/components/createFieldName.ts +0 -20
  26. package/src/components/getSelectedValue.ts +0 -31
  27. package/src/components/getToneFromValidation.ts +0 -20
  28. package/src/constants.ts +0 -18
  29. package/src/fieldActions/index.ts +0 -138
  30. package/src/index.ts +0 -3
  31. package/src/plugin.tsx +0 -87
  32. package/src/schema/array.ts +0 -148
  33. package/src/schema/object.ts +0 -36
  34. package/src/types.ts +0 -135
  35. package/src/utils/checkAllLanguagesArePresent.ts +0 -14
  36. package/src/utils/createAddAllTitle.ts +0 -16
  37. package/src/utils/createAddLanguagePatches.ts +0 -84
  38. package/src/utils/createValueSchemaTypeName.ts +0 -5
  39. package/src/utils/flattenSchemaType.ts +0 -63
  40. package/src/utils/getDocumentsToTranslate.ts +0 -66
  41. package/src/utils/getLanguageDisplay.ts +0 -13
  42. package/src/utils/getLanguagesFieldOption.ts +0 -16
  43. package/v2-incompatible.js +0 -11
package/dist/index.js ADDED
@@ -0,0 +1,896 @@
1
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
+ import { isSanityDocument, useSchema, setIfMissing, insert, PatchEvent, useClient, useWorkspace, useFormValue, defineDocumentFieldAction, ArrayOfObjectsItem, MemberItemError, set, defineField, unset, isDocumentSchemaType, definePlugin, isObjectInputProps } from "sanity";
3
+ import { c } from "react/compiler-runtime";
4
+ import { useLanguageFilterStudioContext } from "@sanity/language-filter";
5
+ import { Grid, Button, useToast, Stack, Box, Text, Card, Code, Spinner, Label, MenuButton, Menu, MenuItem, Flex, Tooltip } from "@sanity/ui";
6
+ import { createContext, useContext, useDeferredValue, use, useCallback, useEffect, createElement } from "react";
7
+ import { useDocumentPane } from "sanity/structure";
8
+ import { AddIcon, TranslateIcon, RemoveCircleIcon } from "@sanity/icons";
9
+ import { get, upperFirst, camelCase } from "lodash-es";
10
+ const namespace = "sanity-plugin-internationalized-array", functionCache = /* @__PURE__ */ new Map(), functionKeyCache = /* @__PURE__ */ new WeakMap(), promiseCache = /* @__PURE__ */ new Map();
11
+ function stringifyCacheKey(key) {
12
+ return JSON.stringify(key);
13
+ }
14
+ const preloadWithKey = (fn, key) => {
15
+ const keyStr = stringifyCacheKey(key);
16
+ promiseCache.has(keyStr) || promiseCache.set(keyStr, fn());
17
+ }, clear = () => {
18
+ promiseCache.clear();
19
+ }, peek = (selectedValue) => {
20
+ const key = stringifyCacheKey(["v1", namespace, selectedValue]), promise = promiseCache.get(key);
21
+ if (promise && promise._status === "fulfilled")
22
+ return promise._value;
23
+ }, createCacheKey = (selectedValue, workspaceId) => {
24
+ const selectedValueHash = JSON.stringify(selectedValue);
25
+ return workspaceId ? ["v1", namespace, selectedValueHash, workspaceId] : ["v1", namespace, selectedValueHash];
26
+ }, createOrGetPromise = (fn, key) => {
27
+ const keyStr = stringifyCacheKey(key);
28
+ if (promiseCache.has(keyStr))
29
+ return promiseCache.get(keyStr);
30
+ const promise = fn();
31
+ return promiseCache.set(keyStr, promise), promise;
32
+ }, getFunctionKey = (fn) => {
33
+ const cachedKey = functionKeyCache.get(fn);
34
+ if (cachedKey)
35
+ return cachedKey;
36
+ const fnStr = fn.toString();
37
+ let hash = 0;
38
+ const maxLength = Math.min(fnStr.length, 100);
39
+ for (let i = 0; i < maxLength; i++) {
40
+ const char = fnStr.charCodeAt(i);
41
+ hash = (hash << 5) - hash + char, hash &= hash;
42
+ }
43
+ const key = `anonymous_${Math.abs(hash)}`;
44
+ return functionKeyCache.set(fn, key), key;
45
+ }, createFunctionCacheKey = (fn, selectedValue, workspaceId) => {
46
+ const functionKey = getFunctionKey(fn), selectedValueHash = JSON.stringify(selectedValue);
47
+ return workspaceId ? `${functionKey}:${selectedValueHash}:${workspaceId}` : `${functionKey}:${selectedValueHash}`;
48
+ }, getFunctionCache = (fn, selectedValue, workspaceId) => {
49
+ const key = createFunctionCacheKey(fn, selectedValue, workspaceId);
50
+ return functionCache.get(key);
51
+ }, setFunctionCache = (fn, selectedValue, languages, workspaceId) => {
52
+ const key = createFunctionCacheKey(fn, selectedValue, workspaceId);
53
+ functionCache.set(key, languages);
54
+ }, LANGUAGE_FIELD_NAME = "_key", MAX_COLUMNS = {
55
+ codeOnly: 5,
56
+ titleOnly: 4,
57
+ titleAndCode: 3
58
+ }, CONFIG_DEFAULT = {
59
+ languages: [],
60
+ select: {},
61
+ defaultLanguages: [],
62
+ fieldTypes: [],
63
+ apiVersion: "2025-10-15",
64
+ buttonLocations: ["field"],
65
+ buttonAddAll: !0,
66
+ languageDisplay: "codeOnly"
67
+ }, getDocumentsToTranslate = (value, rootPath = []) => {
68
+ if (Array.isArray(value)) {
69
+ const arrayRootPath = [...rootPath], internationalizedValues = value.filter((item) => {
70
+ if (Array.isArray(item)) return !1;
71
+ if (typeof item == "object") {
72
+ const type = item?._type;
73
+ return type?.startsWith("internationalizedArray") && type?.endsWith("Value");
74
+ }
75
+ return !1;
76
+ });
77
+ return internationalizedValues.length > 0 ? internationalizedValues.map((internationalizedValue) => Object.assign({}, internationalizedValue, {
78
+ path: arrayRootPath,
79
+ pathString: arrayRootPath.join(".")
80
+ })) : value.length > 0 ? value.flatMap((item, index) => getDocumentsToTranslate(item, [...arrayRootPath, index])) : [];
81
+ }
82
+ if (typeof value == "object" && value) {
83
+ const startsWithUnderscoreRegex = /^_/;
84
+ return Object.keys(value).filter((key) => !key.match(startsWithUnderscoreRegex)).flatMap((item) => {
85
+ const selectedValue = value[item], path = [...rootPath, item];
86
+ return getDocumentsToTranslate(selectedValue, path);
87
+ });
88
+ }
89
+ return [];
90
+ };
91
+ function getLanguageDisplay(languageDisplay, title, code) {
92
+ return languageDisplay === "codeOnly" ? code.toUpperCase() : languageDisplay === "titleOnly" ? title : languageDisplay === "titleAndCode" ? `${title} (${code.toUpperCase()})` : title;
93
+ }
94
+ function AddButtons(props) {
95
+ const $ = c(6), {
96
+ languages,
97
+ readOnly,
98
+ value,
99
+ handleClick
100
+ } = props, {
101
+ languageDisplay
102
+ } = useInternationalizedArrayContext();
103
+ let t0;
104
+ return $[0] !== handleClick || $[1] !== languageDisplay || $[2] !== languages || $[3] !== readOnly || $[4] !== value ? (t0 = languages.length > 0 ? /* @__PURE__ */ jsx(Grid, { columns: Math.min(languages.length, MAX_COLUMNS[languageDisplay]), gap: 2, children: languages.map((language) => {
105
+ const languageTitle = getLanguageDisplay(languageDisplay, language.title, language.id);
106
+ return /* @__PURE__ */ jsx(Button, { tone: "primary", mode: "ghost", fontSize: 1, "data-testid": `add-${language.id}`, disabled: readOnly || !!value?.find((item) => item[LANGUAGE_FIELD_NAME] === language.id), text: languageTitle, icon: languages.length > MAX_COLUMNS[languageDisplay] && languageDisplay === "codeOnly" ? void 0 : AddIcon, value: language.id, onClick: () => handleClick(language.id) }, language.id);
107
+ }) }) : null, $[0] = handleClick, $[1] = languageDisplay, $[2] = languages, $[3] = readOnly, $[4] = value, $[5] = t0) : t0 = $[5], t0;
108
+ }
109
+ function DocumentAddButtons(props) {
110
+ const $ = c(13), {
111
+ filteredLanguages
112
+ } = useInternationalizedArrayContext(), value = isSanityDocument(props.value) ? props.value : void 0, toast = useToast(), {
113
+ onChange
114
+ } = useDocumentPane(), schema = useSchema();
115
+ let t0;
116
+ $[0] !== value ? (t0 = getDocumentsToTranslate(value, []), $[0] = value, $[1] = t0) : t0 = $[1];
117
+ const documentsToTranslation = t0;
118
+ let t1;
119
+ $[2] !== schema ? (t1 = (typeName) => {
120
+ if (!typeName)
121
+ return;
122
+ const match = typeName.match(/^internationalizedArray(.+)Value$/);
123
+ if (!match || !match[1])
124
+ return;
125
+ const baseTypeName = match[1].charAt(0).toLowerCase() + match[1].slice(1), arrayBasedTypes = /* @__PURE__ */ new Set(["body", "htmlContent", "blockContent", "portableText"]);
126
+ if (arrayBasedTypes.has(baseTypeName))
127
+ return [];
128
+ const schemaType = schema.get(typeName);
129
+ if (schemaType && "fields" in schemaType) {
130
+ const valueField = schemaType.fields.find(_temp$2);
131
+ if (valueField) {
132
+ const fieldType = valueField.type;
133
+ if (fieldType?.jsonType === "array" || fieldType?.name === "array" || fieldType?.type === "array" || fieldType?.of !== void 0 || fieldType?.name && arrayBasedTypes.has(fieldType.name))
134
+ return [];
135
+ }
136
+ }
137
+ }, $[2] = schema, $[3] = t1) : t1 = $[3];
138
+ const getInitialValueForType = t1;
139
+ let t2;
140
+ $[4] !== documentsToTranslation || $[5] !== getInitialValueForType || $[6] !== onChange || $[7] !== toast ? (t2 = async (languageId) => {
141
+ const alreadyTranslated = documentsToTranslation.filter((translation) => translation?.[LANGUAGE_FIELD_NAME] === languageId), removeDuplicates = documentsToTranslation.reduce((filteredTranslations, translation_0) => (alreadyTranslated.filter((alreadyTranslation) => alreadyTranslation.pathString === translation_0.pathString).length > 0 || filteredTranslations.filter((filteredTranslation) => filteredTranslation.path === translation_0.path).length > 0 || filteredTranslations.push(translation_0), filteredTranslations), []);
142
+ if (removeDuplicates.length === 0) {
143
+ toast.push({
144
+ status: "error",
145
+ title: "No internationalizedArray fields found in document root"
146
+ });
147
+ return;
148
+ }
149
+ const patches = [];
150
+ for (const toTranslate of removeDuplicates) {
151
+ const path = toTranslate.path, initialValue = getInitialValueForType(toTranslate._type), ifMissing = setIfMissing([], path), insertValue = insert([{
152
+ [LANGUAGE_FIELD_NAME]: languageId,
153
+ _type: toTranslate._type,
154
+ value: initialValue
155
+ }], "after", [...path, -1]);
156
+ patches.push(ifMissing), patches.push(insertValue);
157
+ }
158
+ onChange(PatchEvent.from(patches.flat()));
159
+ }, $[4] = documentsToTranslation, $[5] = getInitialValueForType, $[6] = onChange, $[7] = toast, $[8] = t2) : t2 = $[8];
160
+ const handleDocumentButtonClick = t2;
161
+ let t3;
162
+ $[9] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t3 = /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { size: 1, weight: "semibold", children: "Add translation to internationalized fields" }) }), $[9] = t3) : t3 = $[9];
163
+ let t4;
164
+ return $[10] !== filteredLanguages || $[11] !== handleDocumentButtonClick ? (t4 = /* @__PURE__ */ jsxs(Stack, { space: 3, children: [
165
+ t3,
166
+ /* @__PURE__ */ jsx(AddButtons, { languages: filteredLanguages, readOnly: !1, value: void 0, handleClick: handleDocumentButtonClick })
167
+ ] }), $[10] = filteredLanguages, $[11] = handleDocumentButtonClick, $[12] = t4) : t4 = $[12], t4;
168
+ }
169
+ function _temp$2(f) {
170
+ return f.name === "value";
171
+ }
172
+ const getSelectedValue = (select, document) => {
173
+ if (!select || !document)
174
+ return {};
175
+ const selection = select || {}, selectedValue = {};
176
+ for (const [key, path] of Object.entries(selection)) {
177
+ let value = get(document, path);
178
+ Array.isArray(value) && (value = value.filter((item) => typeof item == "object" ? item?._type === "reference" && "_ref" in item : !0)), selectedValue[key] = value;
179
+ }
180
+ return selectedValue;
181
+ }, InternationalizedArrayContext = createContext({
182
+ ...CONFIG_DEFAULT,
183
+ languages: [],
184
+ filteredLanguages: []
185
+ });
186
+ function useInternationalizedArrayContext() {
187
+ return useContext(InternationalizedArrayContext);
188
+ }
189
+ function InternationalizedArrayProvider(props) {
190
+ const $ = c(38), {
191
+ internationalizedArray: internationalizedArray2
192
+ } = props;
193
+ let t0;
194
+ $[0] !== internationalizedArray2.apiVersion ? (t0 = {
195
+ apiVersion: internationalizedArray2.apiVersion
196
+ }, $[0] = internationalizedArray2.apiVersion, $[1] = t0) : t0 = $[1];
197
+ const client = useClient(t0), workspace = useWorkspace(), {
198
+ formState
199
+ } = useDocumentPane(), deferredDocument = useDeferredValue(formState?.value);
200
+ let t1;
201
+ $[2] !== deferredDocument || $[3] !== internationalizedArray2.select ? (t1 = getSelectedValue(internationalizedArray2.select, deferredDocument), $[2] = deferredDocument, $[3] = internationalizedArray2.select, $[4] = t1) : t1 = $[4];
202
+ const selectedValue = t1;
203
+ let t2;
204
+ bb0: {
205
+ if (workspace?.name) {
206
+ t2 = workspace.name;
207
+ break bb0;
208
+ }
209
+ const t32 = workspace?.name, t42 = workspace?.title;
210
+ let t52;
211
+ $[5] !== t32 || $[6] !== t42 ? (t52 = JSON.stringify({
212
+ name: t32,
213
+ title: t42
214
+ }), $[5] = t32, $[6] = t42, $[7] = t52) : t52 = $[7], t2 = t52;
215
+ }
216
+ const workspaceId = t2;
217
+ let t3;
218
+ $[8] !== selectedValue || $[9] !== workspaceId ? (t3 = createCacheKey(selectedValue, workspaceId), $[8] = selectedValue, $[9] = workspaceId, $[10] = t3) : t3 = $[10];
219
+ const cacheKey = t3;
220
+ let t4;
221
+ bb1: {
222
+ if (Array.isArray(internationalizedArray2.languages)) {
223
+ t4 = null;
224
+ break bb1;
225
+ }
226
+ let t52;
227
+ $[11] !== client || $[12] !== internationalizedArray2 || $[13] !== selectedValue || $[14] !== workspaceId ? (t52 = async () => {
228
+ if (typeof internationalizedArray2.languages == "function") {
229
+ const result = await internationalizedArray2.languages(client, selectedValue);
230
+ return setFunctionCache(internationalizedArray2.languages, selectedValue, result, workspaceId), result;
231
+ }
232
+ return internationalizedArray2.languages;
233
+ }, $[11] = client, $[12] = internationalizedArray2, $[13] = selectedValue, $[14] = workspaceId, $[15] = t52) : t52 = $[15];
234
+ let t62;
235
+ $[16] !== cacheKey || $[17] !== t52 ? (t62 = createOrGetPromise(t52, cacheKey), $[16] = cacheKey, $[17] = t52, $[18] = t62) : t62 = $[18], t4 = t62;
236
+ }
237
+ const languagesPromise = t4, languages = languagesPromise ? use(languagesPromise) : internationalizedArray2.languages, {
238
+ selectedLanguageIds,
239
+ options: languageFilterOptions
240
+ } = useLanguageFilterStudioContext(), documentType = deferredDocument ? deferredDocument._type : void 0;
241
+ let t5;
242
+ $[19] !== documentType || $[20] !== languageFilterOptions ? (t5 = typeof documentType == "string" && languageFilterOptions.documentTypes.includes(documentType), $[19] = documentType, $[20] = languageFilterOptions, $[21] = t5) : t5 = $[21];
243
+ const languageFilterEnabled = t5;
244
+ let t6;
245
+ $[22] !== languageFilterEnabled || $[23] !== languages || $[24] !== selectedLanguageIds ? (t6 = languageFilterEnabled ? languages.filter((language) => selectedLanguageIds.includes(language.id)) : languages, $[22] = languageFilterEnabled, $[23] = languages, $[24] = selectedLanguageIds, $[25] = t6) : t6 = $[25];
246
+ const filteredLanguages = t6;
247
+ let t7;
248
+ $[26] !== internationalizedArray2.buttonLocations ? (t7 = internationalizedArray2.buttonLocations.includes("document"), $[26] = internationalizedArray2.buttonLocations, $[27] = t7) : t7 = $[27];
249
+ const showDocumentButtons = t7;
250
+ let t8;
251
+ $[28] !== filteredLanguages || $[29] !== internationalizedArray2 || $[30] !== languages ? (t8 = {
252
+ ...internationalizedArray2,
253
+ languages,
254
+ filteredLanguages
255
+ }, $[28] = filteredLanguages, $[29] = internationalizedArray2, $[30] = languages, $[31] = t8) : t8 = $[31];
256
+ const context = t8;
257
+ let t9;
258
+ $[32] !== props || $[33] !== showDocumentButtons ? (t9 = showDocumentButtons ? /* @__PURE__ */ jsxs(Stack, { space: 5, children: [
259
+ /* @__PURE__ */ jsx(DocumentAddButtons, { value: props.value }),
260
+ props.renderDefault(props)
261
+ ] }) : props.renderDefault(props), $[32] = props, $[33] = showDocumentButtons, $[34] = t9) : t9 = $[34];
262
+ let t10;
263
+ return $[35] !== context || $[36] !== t9 ? (t10 = /* @__PURE__ */ jsx(InternationalizedArrayContext.Provider, { value: context, children: t9 }), $[35] = context, $[36] = t9, $[37] = t10) : t10 = $[37], t10;
264
+ }
265
+ const getLanguageId = (fieldParent) => {
266
+ try {
267
+ return typeof fieldParent == "object" && fieldParent !== null && // Checks if it's an internationalized array item
268
+ "_type" in fieldParent && typeof fieldParent._type == "string" && fieldParent._type.startsWith("internationalizedArray") && // Checks if the language field name is in the field and if it's a string
269
+ LANGUAGE_FIELD_NAME in fieldParent && typeof fieldParent[LANGUAGE_FIELD_NAME] == "string" ? fieldParent[LANGUAGE_FIELD_NAME] : void 0;
270
+ } catch (error) {
271
+ console.error("Error getting language id", error);
272
+ return;
273
+ }
274
+ };
275
+ function InternationalizedField(props) {
276
+ const $ = c(11), {
277
+ languages
278
+ } = useInternationalizedArrayContext();
279
+ let t0;
280
+ $[0] !== props.path ? (t0 = props.path.slice(0, -1), $[0] = props.path, $[1] = t0) : t0 = $[1];
281
+ const fieldParent = useFormValue(t0), languageId = getLanguageId(fieldParent), hasValidLanguageId = languageId ? languages.some((l) => l.id === languageId) : !1, t1 = props.title?.toLowerCase() === "value" && hasValidLanguageId ? "" : props.title;
282
+ let t2;
283
+ $[2] !== props || $[3] !== t1 ? (t2 = {
284
+ ...props,
285
+ title: t1
286
+ }, $[2] = props, $[3] = t1, $[4] = t2) : t2 = $[4];
287
+ const customProps = t2;
288
+ if (!customProps.schemaType.name.startsWith("internationalizedArray")) {
289
+ let t32;
290
+ return $[5] !== customProps ? (t32 = customProps.renderDefault(customProps), $[5] = customProps, $[6] = t32) : t32 = $[6], t32;
291
+ }
292
+ if (customProps.schemaType.name === "reference" && customProps.value) {
293
+ let t32;
294
+ return $[7] !== customProps ? (t32 = customProps.renderDefault({
295
+ ...customProps,
296
+ title: "",
297
+ level: 0
298
+ }), $[7] = customProps, $[8] = t32) : t32 = $[8], t32;
299
+ }
300
+ if (customProps.schemaType.name === "string" || customProps.schemaType.name === "number" || customProps.schemaType.name === "text")
301
+ return customProps.children;
302
+ let t3;
303
+ return $[9] !== customProps ? (t3 = customProps.renderDefault({
304
+ ...customProps,
305
+ level: 0
306
+ }), $[9] = customProps, $[10] = t3) : t3 = $[10], t3;
307
+ }
308
+ function Preload(props) {
309
+ const $ = c(2);
310
+ let t0;
311
+ $[0] !== props.apiVersion ? (t0 = {
312
+ apiVersion: props.apiVersion
313
+ }, $[0] = props.apiVersion, $[1] = t0) : t0 = $[1];
314
+ const client = useClient(t0), cacheKey = createCacheKey({});
315
+ return Array.isArray(peek({})) || preloadWithKey(async () => {
316
+ if (Array.isArray(props.languages))
317
+ return props.languages;
318
+ const result = await props.languages(client, {});
319
+ return setFunctionCache(props.languages, {}, result), result;
320
+ }, cacheKey), null;
321
+ }
322
+ function checkAllLanguagesArePresent(languages, value) {
323
+ const filteredLanguageIds = new Set(languages.map((l) => l.id)), languagesInUseIds = value ? value.map((v) => v[LANGUAGE_FIELD_NAME]) : [];
324
+ return languagesInUseIds.length !== filteredLanguageIds.size || new Set(languagesInUseIds).size !== languagesInUseIds.length ? !1 : languagesInUseIds.every((key) => filteredLanguageIds.has(key));
325
+ }
326
+ function createAddAllTitle(value, languages) {
327
+ return value?.length ? `Add missing ${languages.length - value.length === 1 ? "language" : "languages"}` : languages.length === 1 && languages[0] ? `Add ${languages[0].title} Field` : "Add all languages";
328
+ }
329
+ function createAddLanguagePatches(config) {
330
+ const {
331
+ addLanguageKeys,
332
+ schemaTypeName,
333
+ languages,
334
+ filteredLanguages,
335
+ value,
336
+ path = []
337
+ } = config, itemBase = {
338
+ _type: `${schemaTypeName}Value`
339
+ }, newItems = Array.isArray(addLanguageKeys) && addLanguageKeys.length > 0 ? addLanguageKeys.map((id) => Object.assign({}, itemBase, {
340
+ [LANGUAGE_FIELD_NAME]: id
341
+ })) : filteredLanguages.filter((language) => value?.length ? !value.find((v) => v[LANGUAGE_FIELD_NAME] === language.id) : !0).map((language) => Object.assign({}, itemBase, {
342
+ [LANGUAGE_FIELD_NAME]: language.id
343
+ })), languagesInUse = value?.length ? value.map((v) => v) : [];
344
+ return newItems.map((item) => {
345
+ const itemLanguage = item[LANGUAGE_FIELD_NAME], languageIndex = languages.findIndex((l) => itemLanguage === l.id), remainingLanguages = languages.slice(languageIndex + 1), nextLanguageIndex = languagesInUse.findIndex((l) => remainingLanguages.find((r) => r.id === l[LANGUAGE_FIELD_NAME]));
346
+ return nextLanguageIndex < 0 ? languagesInUse.push(item) : languagesInUse.splice(nextLanguageIndex, 0, item), nextLanguageIndex < 0 ? (
347
+ // No next language (-1), add to end of array
348
+ insert([item], "after", [...path, nextLanguageIndex])
349
+ ) : (
350
+ // Next language found, insert before that
351
+ insert([item], "before", [...path, nextLanguageIndex])
352
+ );
353
+ });
354
+ }
355
+ const createTranslateFieldActions = (fieldActionProps, {
356
+ languages,
357
+ filteredLanguages
358
+ }) => languages.map((language) => {
359
+ const value = useFormValue(fieldActionProps.path), disabled = value && Array.isArray(value) ? !!value?.find((item) => item[LANGUAGE_FIELD_NAME] === language.id) : !1, hidden = !filteredLanguages.some((f) => f.id === language.id), {
360
+ onChange
361
+ } = useDocumentPane(), onAction = useCallback(() => {
362
+ const {
363
+ schemaType,
364
+ path
365
+ } = fieldActionProps, addLanguageKeys = [language.id], patches = createAddLanguagePatches({
366
+ addLanguageKeys,
367
+ schemaTypeName: schemaType.name,
368
+ languages,
369
+ filteredLanguages,
370
+ value,
371
+ path
372
+ });
373
+ onChange(PatchEvent.from([setIfMissing([], path), ...patches]));
374
+ }, [language.id, value, onChange]);
375
+ return {
376
+ type: "action",
377
+ icon: AddIcon,
378
+ onAction,
379
+ title: language.title,
380
+ hidden,
381
+ disabled
382
+ };
383
+ }), AddMissingTranslationsFieldAction = (fieldActionProps, {
384
+ languages,
385
+ filteredLanguages
386
+ }) => {
387
+ const value = useFormValue(fieldActionProps.path), disabled = value && value.length === filteredLanguages.length, hidden = checkAllLanguagesArePresent(filteredLanguages, value), {
388
+ onChange
389
+ } = useDocumentPane(), onAction = useCallback(() => {
390
+ const {
391
+ schemaType,
392
+ path
393
+ } = fieldActionProps, patches = createAddLanguagePatches({
394
+ addLanguageKeys: [],
395
+ schemaTypeName: schemaType.name,
396
+ languages,
397
+ filteredLanguages,
398
+ value,
399
+ path
400
+ });
401
+ onChange(PatchEvent.from([setIfMissing([], path), ...patches]));
402
+ }, [fieldActionProps, filteredLanguages, languages, onChange, value]);
403
+ return {
404
+ type: "action",
405
+ icon: AddIcon,
406
+ onAction,
407
+ title: createAddAllTitle(value, filteredLanguages),
408
+ disabled,
409
+ hidden
410
+ };
411
+ }, internationalizedArrayFieldAction = defineDocumentFieldAction({
412
+ name: "internationalizedArray",
413
+ useAction(fieldActionProps) {
414
+ const isInternationalizedArrayField = fieldActionProps?.schemaType?.type?.name.startsWith("internationalizedArray"), {
415
+ languages,
416
+ filteredLanguages
417
+ } = useInternationalizedArrayContext(), translateFieldActions = createTranslateFieldActions(fieldActionProps, {
418
+ languages,
419
+ filteredLanguages
420
+ });
421
+ return {
422
+ type: "group",
423
+ icon: TranslateIcon,
424
+ title: "Add Translation",
425
+ renderAsButton: !0,
426
+ children: isInternationalizedArrayField ? [...translateFieldActions, AddMissingTranslationsFieldAction(fieldActionProps, {
427
+ languages,
428
+ filteredLanguages
429
+ })] : [],
430
+ hidden: !isInternationalizedArrayField
431
+ };
432
+ }
433
+ });
434
+ function pascalCase(string) {
435
+ return upperFirst(camelCase(string));
436
+ }
437
+ function createFieldName(name, addValue = !1) {
438
+ return addValue ? ["internationalizedArray", pascalCase(name), "Value"].join("") : ["internationalizedArray", pascalCase(name)].join("");
439
+ }
440
+ const schemaExample = {
441
+ languages: [{
442
+ id: "en",
443
+ title: "English"
444
+ }, {
445
+ id: "no",
446
+ title: "Norsk"
447
+ }]
448
+ };
449
+ function Feedback() {
450
+ const $ = c(4);
451
+ let t0;
452
+ $[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("code", { children: "internationalizedArray" }), $[0] = t0) : t0 = $[0];
453
+ let t1;
454
+ $[1] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t1 = /* @__PURE__ */ jsx("code", { children: "id" }), $[1] = t1) : t1 = $[1];
455
+ let t2;
456
+ $[2] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t2 = /* @__PURE__ */ jsxs(Text, { children: [
457
+ "An array of language objects must be passed into the ",
458
+ t0,
459
+ " ",
460
+ "helper function, each with an ",
461
+ t1,
462
+ " and ",
463
+ /* @__PURE__ */ jsx("code", { children: "title" }),
464
+ " field. Example:"
465
+ ] }), $[2] = t2) : t2 = $[2];
466
+ let t3;
467
+ return $[3] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t3 = /* @__PURE__ */ jsx(Card, { tone: "caution", border: !0, radius: 2, padding: 3, children: /* @__PURE__ */ jsxs(Stack, { space: 4, children: [
468
+ t2,
469
+ /* @__PURE__ */ jsx(Card, { padding: 2, border: !0, radius: 2, children: /* @__PURE__ */ jsx(Code, { size: 1, language: "javascript", children: JSON.stringify(schemaExample, null, 2) }) })
470
+ ] }) }), $[3] = t3) : t3 = $[3], t3;
471
+ }
472
+ function InternationalizedArray(props) {
473
+ const $ = c(89), {
474
+ members,
475
+ value,
476
+ schemaType,
477
+ onChange,
478
+ readOnly: documentReadOnly
479
+ } = props, readOnly = typeof schemaType.readOnly == "boolean" ? schemaType.readOnly : !1, toast = useToast(), {
480
+ languages,
481
+ filteredLanguages,
482
+ defaultLanguages,
483
+ buttonAddAll,
484
+ buttonLocations
485
+ } = useInternationalizedArrayContext(), {
486
+ selectedLanguageIds,
487
+ options: languageFilterOptions
488
+ } = useLanguageFilterStudioContext();
489
+ let t0;
490
+ $[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t0 = ["_type"], $[0] = t0) : t0 = $[0];
491
+ const documentType = useFormValue(t0);
492
+ let t1;
493
+ $[1] !== documentType || $[2] !== languageFilterOptions ? (t1 = typeof documentType == "string" && languageFilterOptions.documentTypes.includes(documentType), $[1] = documentType, $[2] = languageFilterOptions, $[3] = t1) : t1 = $[3];
494
+ const languageFilterEnabled = t1;
495
+ let t2;
496
+ $[4] !== languageFilterEnabled || $[5] !== languageFilterOptions || $[6] !== members || $[7] !== selectedLanguageIds ? (t2 = languageFilterEnabled ? members.filter((member) => {
497
+ if (member.kind !== "item")
498
+ return !1;
499
+ const valueMember = member.item.members[0];
500
+ return !valueMember || valueMember.kind !== "field" ? !1 : languageFilterOptions.filterField(member.item.schemaType, valueMember, selectedLanguageIds);
501
+ }) : members, $[4] = languageFilterEnabled, $[5] = languageFilterOptions, $[6] = members, $[7] = selectedLanguageIds, $[8] = t2) : t2 = $[8];
502
+ const filteredMembers = t2;
503
+ let t3;
504
+ $[9] !== filteredLanguages || $[10] !== languages || $[11] !== onChange || $[12] !== schemaType.name || $[13] !== value ? (t3 = (addLanguageKeys) => {
505
+ if (!filteredLanguages?.length)
506
+ return;
507
+ const patches = createAddLanguagePatches({
508
+ addLanguageKeys: Array.isArray(addLanguageKeys) ? addLanguageKeys : [addLanguageKeys],
509
+ schemaTypeName: schemaType.name,
510
+ languages,
511
+ filteredLanguages,
512
+ value
513
+ });
514
+ onChange([setIfMissing([]), ...patches]);
515
+ }, $[9] = filteredLanguages, $[10] = languages, $[11] = onChange, $[12] = schemaType.name, $[13] = value, $[14] = t3) : t3 = $[14];
516
+ const handleAddLanguage = t3, {
517
+ isDeleting
518
+ } = useDocumentPane();
519
+ let t4;
520
+ bb0: {
521
+ if (!value?.length) {
522
+ let t53;
523
+ $[15] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t53 = [], $[15] = t53) : t53 = $[15], t4 = t53;
524
+ break bb0;
525
+ }
526
+ let t52;
527
+ $[16] !== value ? (t52 = value.map(_temp$1).filter(Boolean), $[16] = value, $[17] = t52) : t52 = $[17], t4 = t52;
528
+ }
529
+ const addedLanguages = t4;
530
+ let t5;
531
+ if ($[18] !== addedLanguages || $[19] !== defaultLanguages || $[20] !== languages) {
532
+ let t62;
533
+ $[22] !== languages ? (t62 = (language) => languages.find((l) => l.id === language), $[22] = languages, $[23] = t62) : t62 = $[23];
534
+ let t72;
535
+ $[24] !== addedLanguages ? (t72 = (language_0) => addedLanguages.includes(language_0), $[24] = addedLanguages, $[25] = t72) : t72 = $[25], t5 = defaultLanguages.filter(t62).every(t72), $[18] = addedLanguages, $[19] = defaultLanguages, $[20] = languages, $[21] = t5;
536
+ } else
537
+ t5 = $[21];
538
+ const hasAddedDefaultLanguages = t5;
539
+ let t6, t7;
540
+ $[26] !== addedLanguages || $[27] !== defaultLanguages || $[28] !== documentReadOnly || $[29] !== handleAddLanguage || $[30] !== hasAddedDefaultLanguages || $[31] !== isDeleting || $[32] !== languages ? (t6 = () => {
541
+ if (!isDeleting && !hasAddedDefaultLanguages) {
542
+ const languagesToAdd = defaultLanguages.filter((language_1) => !addedLanguages.includes(language_1)).filter((language_2) => languages.find((l_0) => l_0.id === language_2)), timeout = setTimeout(() => {
543
+ documentReadOnly || handleAddLanguage(languagesToAdd);
544
+ });
545
+ return () => clearTimeout(timeout);
546
+ }
547
+ }, t7 = [isDeleting, hasAddedDefaultLanguages, handleAddLanguage, defaultLanguages, addedLanguages, languages, documentReadOnly], $[26] = addedLanguages, $[27] = defaultLanguages, $[28] = documentReadOnly, $[29] = handleAddLanguage, $[30] = hasAddedDefaultLanguages, $[31] = isDeleting, $[32] = languages, $[33] = t6, $[34] = t7) : (t6 = $[33], t7 = $[34]), useEffect(t6, t7);
548
+ let t8;
549
+ $[35] !== languages || $[36] !== onChange || $[37] !== toast || $[38] !== value ? (t8 = () => {
550
+ if (!value?.length || !languages?.length)
551
+ return;
552
+ const updatedValue = value.reduce((acc, v_0) => {
553
+ const newIndex = languages.findIndex((l_1) => l_1.id === v_0?.[LANGUAGE_FIELD_NAME]);
554
+ return newIndex > -1 && (acc[newIndex] = v_0), acc;
555
+ }, []).filter(Boolean);
556
+ value?.length !== updatedValue.length && toast.push({
557
+ title: "There was an error reordering languages",
558
+ status: "warning"
559
+ }), onChange(set(updatedValue));
560
+ }, $[35] = languages, $[36] = onChange, $[37] = toast, $[38] = value, $[39] = t8) : t8 = $[39];
561
+ const handleRestoreOrder = t8;
562
+ let t9;
563
+ bb1: {
564
+ if (!value?.length || !languages?.length) {
565
+ t9 = !0;
566
+ break bb1;
567
+ }
568
+ let t102;
569
+ $[40] !== languages || $[41] !== value ? (t102 = value?.every((v_1) => languages.find((l_2) => l_2?.id === v_1?.[LANGUAGE_FIELD_NAME])), $[40] = languages, $[41] = value, $[42] = t102) : t102 = $[42], t9 = t102;
570
+ }
571
+ const allKeysAreLanguages = t9;
572
+ let t10;
573
+ $[43] !== languages || $[44] !== value ? (t10 = languages && languages.length > 1 ? languages.filter((l_3) => value?.find((v_2) => v_2[LANGUAGE_FIELD_NAME] === l_3.id)) : [], $[43] = languages, $[44] = value, $[45] = t10) : t10 = $[45];
574
+ const languagesInUse = t10;
575
+ let t11;
576
+ bb2: {
577
+ if (!value?.length || !languagesInUse.length) {
578
+ let t123;
579
+ $[46] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t123 = [], $[46] = t123) : t123 = $[46], t11 = t123;
580
+ break bb2;
581
+ }
582
+ let t122;
583
+ if ($[47] !== languagesInUse || $[48] !== value) {
584
+ let t132;
585
+ $[50] !== languagesInUse ? (t132 = (v_3, vIndex) => vIndex === languagesInUse.findIndex((l_4) => l_4.id === v_3[LANGUAGE_FIELD_NAME]) ? null : v_3, $[50] = languagesInUse, $[51] = t132) : t132 = $[51], t122 = value.map(t132).filter(Boolean), $[47] = languagesInUse, $[48] = value, $[49] = t122;
586
+ } else
587
+ t122 = $[49];
588
+ t11 = t122;
589
+ }
590
+ const languagesOutOfOrder = t11, languagesAreValid = !languages?.length || languages?.length && languages.every(_temp2$1);
591
+ let t12;
592
+ $[52] !== allKeysAreLanguages || $[53] !== documentReadOnly || $[54] !== handleRestoreOrder || $[55] !== languagesOutOfOrder.length ? (t12 = () => {
593
+ languagesOutOfOrder.length > 0 && allKeysAreLanguages && !documentReadOnly && handleRestoreOrder();
594
+ }, $[52] = allKeysAreLanguages, $[53] = documentReadOnly, $[54] = handleRestoreOrder, $[55] = languagesOutOfOrder.length, $[56] = t12) : t12 = $[56];
595
+ let t13;
596
+ $[57] !== allKeysAreLanguages || $[58] !== documentReadOnly || $[59] !== handleRestoreOrder || $[60] !== languagesOutOfOrder ? (t13 = [languagesOutOfOrder, allKeysAreLanguages, handleRestoreOrder, documentReadOnly], $[57] = allKeysAreLanguages, $[58] = documentReadOnly, $[59] = handleRestoreOrder, $[60] = languagesOutOfOrder, $[61] = t13) : t13 = $[61], useEffect(t12, t13);
597
+ let t14;
598
+ $[62] !== filteredLanguages || $[63] !== value ? (t14 = checkAllLanguagesArePresent(filteredLanguages, value), $[62] = filteredLanguages, $[63] = value, $[64] = t14) : t14 = $[64];
599
+ const allLanguagesArePresent = t14;
600
+ if (!languagesAreValid) {
601
+ let t152;
602
+ return $[65] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t152 = /* @__PURE__ */ jsx(Feedback, {}), $[65] = t152) : t152 = $[65], t152;
603
+ }
604
+ let t15;
605
+ $[66] !== allLanguagesArePresent || $[67] !== buttonLocations || $[68] !== filteredLanguages?.length ? (t15 = buttonLocations.includes("field") && filteredLanguages?.length > 0 && !allLanguagesArePresent, $[66] = allLanguagesArePresent, $[67] = buttonLocations, $[68] = filteredLanguages?.length, $[69] = t15) : t15 = $[69];
606
+ const addButtonsAreVisible = t15, fieldHasMembers = members?.length > 0;
607
+ let t16;
608
+ $[70] !== fieldHasMembers || $[71] !== filteredMembers || $[72] !== props ? (t16 = fieldHasMembers ? /* @__PURE__ */ jsx(Fragment, { children: filteredMembers.map((member_0) => member_0.kind === "item" ? /* @__PURE__ */ createElement(ArrayOfObjectsItem, { ...props, key: member_0.key, member: member_0 }) : /* @__PURE__ */ jsx(MemberItemError, { member: member_0 }, member_0.key)) }) : null, $[70] = fieldHasMembers, $[71] = filteredMembers, $[72] = props, $[73] = t16) : t16 = $[73];
609
+ let t17;
610
+ $[74] !== addButtonsAreVisible || $[75] !== fieldHasMembers ? (t17 = !addButtonsAreVisible && !fieldHasMembers ? /* @__PURE__ */ jsx(Card, { border: !0, tone: "transparent", padding: 3, radius: 2, children: /* @__PURE__ */ jsx(Text, { size: 1, children: "This internationalized field currently has no translations." }) }) : null, $[74] = addButtonsAreVisible, $[75] = fieldHasMembers, $[76] = t17) : t17 = $[76];
611
+ let t18;
612
+ $[77] !== addButtonsAreVisible || $[78] !== allLanguagesArePresent || $[79] !== buttonAddAll || $[80] !== filteredLanguages || $[81] !== handleAddLanguage || $[82] !== readOnly || $[83] !== value ? (t18 = addButtonsAreVisible ? /* @__PURE__ */ jsxs(Stack, { space: 2, children: [
613
+ /* @__PURE__ */ jsx(AddButtons, { languages: filteredLanguages, value, readOnly, handleClick: handleAddLanguage }),
614
+ buttonAddAll ? /* @__PURE__ */ jsx(Button, { tone: "primary", mode: "ghost", "data-testid": "add-all-languages", disabled: readOnly || allLanguagesArePresent, icon: AddIcon, text: createAddAllTitle(value, filteredLanguages), onClick: () => handleAddLanguage(filteredLanguages.map(_temp3$1)) }) : null
615
+ ] }) : null, $[77] = addButtonsAreVisible, $[78] = allLanguagesArePresent, $[79] = buttonAddAll, $[80] = filteredLanguages, $[81] = handleAddLanguage, $[82] = readOnly, $[83] = value, $[84] = t18) : t18 = $[84];
616
+ let t19;
617
+ return $[85] !== t16 || $[86] !== t17 || $[87] !== t18 ? (t19 = /* @__PURE__ */ jsxs(Stack, { space: 2, children: [
618
+ t16,
619
+ t17,
620
+ t18
621
+ ] }), $[85] = t16, $[86] = t17, $[87] = t18, $[88] = t19) : t19 = $[88], t19;
622
+ }
623
+ function _temp3$1(language_3) {
624
+ return language_3.id;
625
+ }
626
+ function _temp2$1(item) {
627
+ return item.id && item.title;
628
+ }
629
+ function _temp$1(v) {
630
+ return v[LANGUAGE_FIELD_NAME] ?? v._key;
631
+ }
632
+ function getLanguagesFieldOption(schemaType) {
633
+ return schemaType ? schemaType.options?.languages || getLanguagesFieldOption(schemaType.type) : void 0;
634
+ }
635
+ var array = (config) => {
636
+ const {
637
+ apiVersion,
638
+ select,
639
+ languages,
640
+ type
641
+ } = config, typeName = typeof type == "string" ? type : type.name, arrayName = createFieldName(typeName), objectName = createFieldName(typeName, !0);
642
+ return defineField({
643
+ name: arrayName,
644
+ title: "Internationalized array",
645
+ type: "array",
646
+ components: {
647
+ input: InternationalizedArray
648
+ },
649
+ options: {
650
+ // @ts-expect-error - these options are required for validation rules – not the custom input component
651
+ apiVersion,
652
+ select,
653
+ languages
654
+ },
655
+ of: [defineField({
656
+ ...typeof type == "string" ? {} : type,
657
+ name: objectName,
658
+ type: objectName
659
+ })],
660
+ // @ts-expect-error - fix typings
661
+ validation: (rule) => rule.custom(async (value, context) => {
662
+ if (!value || value.length === 0 || value.length === 1 && !value[0]?.[LANGUAGE_FIELD_NAME])
663
+ return !0;
664
+ const selectedValue = getSelectedValue(select, context.document), client = context.getClient({
665
+ apiVersion
666
+ });
667
+ let contextLanguages = [];
668
+ const languagesFieldOption = getLanguagesFieldOption(context?.type);
669
+ if (Array.isArray(languagesFieldOption))
670
+ contextLanguages = languagesFieldOption;
671
+ else if (Array.isArray(peek(selectedValue)))
672
+ contextLanguages = peek(selectedValue) || [];
673
+ else if (typeof languagesFieldOption == "function") {
674
+ const cachedLanguages = getFunctionCache(languagesFieldOption, selectedValue);
675
+ if (Array.isArray(cachedLanguages))
676
+ contextLanguages = cachedLanguages;
677
+ else {
678
+ const suspendCachedLanguages = peek(selectedValue);
679
+ Array.isArray(suspendCachedLanguages) ? contextLanguages = suspendCachedLanguages : (contextLanguages = await languagesFieldOption(client, selectedValue), setFunctionCache(languagesFieldOption, selectedValue, contextLanguages));
680
+ }
681
+ }
682
+ if (value && value.length > contextLanguages.length)
683
+ return `Cannot be more than ${contextLanguages.length === 1 ? "1 item" : `${contextLanguages.length} items`}`;
684
+ const languageIds = new Set(contextLanguages.map((lang) => lang.id)), nonLanguageKeys = value.filter((item) => item?.[LANGUAGE_FIELD_NAME] && !languageIds.has(item[LANGUAGE_FIELD_NAME]));
685
+ if (nonLanguageKeys.length)
686
+ return {
687
+ message: "Array item keys must be valid languages registered to the field type",
688
+ paths: nonLanguageKeys.map((item) => [{
689
+ _key: item._key
690
+ }])
691
+ };
692
+ const seenLanguages = /* @__PURE__ */ new Set(), duplicateValues = [];
693
+ for (const item of value)
694
+ item?.[LANGUAGE_FIELD_NAME] && (seenLanguages.has(item[LANGUAGE_FIELD_NAME]) ? duplicateValues.push(item) : seenLanguages.add(item[LANGUAGE_FIELD_NAME]));
695
+ return duplicateValues.length ? {
696
+ message: "There can only be one field per language",
697
+ paths: duplicateValues.map((item) => [{
698
+ _key: item._key
699
+ }])
700
+ } : !0;
701
+ })
702
+ });
703
+ };
704
+ function getToneFromValidation(validations) {
705
+ if (!validations?.length)
706
+ return;
707
+ const validationLevels = new Set(validations.map((v) => v.level));
708
+ if (validationLevels.has("error"))
709
+ return "critical";
710
+ if (validationLevels.has("warning"))
711
+ return "caution";
712
+ }
713
+ function InternationalizedInput(props) {
714
+ const $ = c(13);
715
+ let t0;
716
+ $[0] !== props.path ? (t0 = props.path.slice(0, -1), $[0] = props.path, $[1] = t0) : t0 = $[1];
717
+ const parentValue = useFormValue(t0), originalOnChange = props.inputProps.onChange;
718
+ let t1;
719
+ $[2] !== originalOnChange || $[3] !== props.value?.value ? (t1 = (patches) => {
720
+ if (!Array.isArray(patches))
721
+ return originalOnChange(patches);
722
+ const valueField = props.value?.value;
723
+ if ((valueField == null || Array.isArray(valueField) && valueField.length === 0) && patches.some(_temp)) {
724
+ const initPatch = valueField === void 0 ? {
725
+ type: "setIfMissing",
726
+ path: ["value"],
727
+ value: []
728
+ } : null, fixedPatches = patches.map(_temp2), allPatches = initPatch ? [initPatch, ...fixedPatches] : fixedPatches;
729
+ return originalOnChange(allPatches);
730
+ }
731
+ return originalOnChange(patches);
732
+ }, $[2] = originalOnChange, $[3] = props.value?.value, $[4] = t1) : t1 = $[4];
733
+ const wrappedOnChange = t1, inlineProps = {
734
+ ...props.inputProps,
735
+ members: props.inputProps.members.filter(_temp3),
736
+ value: props.value,
737
+ onChange: wrappedOnChange
738
+ }, {
739
+ validation,
740
+ value,
741
+ onChange,
742
+ readOnly
743
+ } = inlineProps, {
744
+ languages,
745
+ languageDisplay,
746
+ defaultLanguages
747
+ } = useInternationalizedArrayContext();
748
+ let t2;
749
+ $[5] !== parentValue ? (t2 = parentValue?.map(_temp4) ?? [], $[5] = parentValue, $[6] = t2) : t2 = $[6];
750
+ const languageKeysInUse = t2, keyIsValid = languages?.length ? languages.find((l) => l.id === value[LANGUAGE_FIELD_NAME]) : !1, handleKeyChange = (event) => {
751
+ const languageId = event?.currentTarget?.value;
752
+ !value || !languages?.length || !languages.find((l_0) => l_0.id === languageId) || onChange([set(languageId, [LANGUAGE_FIELD_NAME])]);
753
+ }, handleUnset = () => {
754
+ onChange(unset());
755
+ };
756
+ if (!languages) {
757
+ let t32;
758
+ return $[7] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t32 = /* @__PURE__ */ jsx(Spinner, {}), $[7] = t32) : t32 = $[7], t32;
759
+ }
760
+ const language = languages.find((l_1) => l_1.id === value[LANGUAGE_FIELD_NAME]), languageTitle = keyIsValid && language ? getLanguageDisplay(languageDisplay, language.title, language.id) : "", isDefault = defaultLanguages.includes(value[LANGUAGE_FIELD_NAME]), removeButton = /* @__PURE__ */ jsx(Button, { mode: "bleed", icon: RemoveCircleIcon, tone: "critical", disabled: readOnly || isDefault, onClick: handleUnset }), t3 = getToneFromValidation(validation), t4 = keyIsValid ? /* @__PURE__ */ jsx(Label, { muted: !0, size: 1, children: languageTitle }) : /* @__PURE__ */ jsx(MenuButton, { button: /* @__PURE__ */ jsx(Button, { fontSize: 1, text: `Change "${value[LANGUAGE_FIELD_NAME]}"` }), id: `${value[LANGUAGE_FIELD_NAME]}-change-key`, menu: /* @__PURE__ */ jsx(Menu, { children: languages.map((lang) => /* @__PURE__ */ jsx(MenuItem, { disabled: languageKeysInUse.includes(lang.id), fontSize: 1, text: lang.id.toLocaleUpperCase(), value: lang.id, onClick: handleKeyChange }, lang.id)) }), popover: {
761
+ portal: !0
762
+ } });
763
+ let t5;
764
+ $[8] !== t4 ? (t5 = /* @__PURE__ */ jsx(Card, { tone: "inherit", children: t4 }), $[8] = t4, $[9] = t5) : t5 = $[9];
765
+ const T0 = Card, t6 = 1, t7 = "inherit", t8 = props.inputProps.renderInput(inlineProps);
766
+ let t9;
767
+ return $[10] !== T0 || $[11] !== t8 ? (t9 = /* @__PURE__ */ jsx(T0, { flex: t6, tone: t7, children: t8 }), $[10] = T0, $[11] = t8, $[12] = t9) : t9 = $[12], /* @__PURE__ */ jsx(Card, { paddingTop: 2, tone: t3, children: /* @__PURE__ */ jsxs(Stack, { space: 2, children: [
768
+ t5,
769
+ /* @__PURE__ */ jsxs(Flex, { align: "center", gap: 2, children: [
770
+ t9,
771
+ /* @__PURE__ */ jsx(Card, { tone: "inherit", children: isDefault ? /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(Text, { muted: !0, size: 1, children: "Can't remove default language" }), fallbackPlacements: ["right", "left"], placement: "top", portal: !0, children: /* @__PURE__ */ jsx("span", { children: removeButton }) }) : removeButton })
772
+ ] })
773
+ ] }) });
774
+ }
775
+ function _temp4(v) {
776
+ return v[LANGUAGE_FIELD_NAME];
777
+ }
778
+ function _temp3(m) {
779
+ return m.kind === "field" && m.name === "value";
780
+ }
781
+ function _temp2(patch_0) {
782
+ if (!patch_0 || typeof patch_0 != "object")
783
+ return patch_0;
784
+ if (patch_0.type === "insert" && patch_0.path && Array.isArray(patch_0.path)) {
785
+ const fixedPath = patch_0.path[0] === "value" ? patch_0.path : ["value", ...patch_0.path];
786
+ return {
787
+ ...patch_0,
788
+ path: fixedPath
789
+ };
790
+ }
791
+ return patch_0;
792
+ }
793
+ function _temp(patch) {
794
+ return !patch || typeof patch != "object" ? !1 : patch.type === "insert" && patch.path && Array.isArray(patch.path) && patch.path.length > 0 ? patch.path[0] === "value" || typeof patch.path[0] == "number" : !1;
795
+ }
796
+ var object = (config) => {
797
+ const {
798
+ type
799
+ } = config, typeName = typeof type == "string" ? type : type.name, objectName = createFieldName(typeName, !0);
800
+ return defineField({
801
+ name: objectName,
802
+ title: `Internationalized array ${typeName}`,
803
+ type: "object",
804
+ components: {
805
+ // @ts-expect-error - fix typings
806
+ item: InternationalizedInput
807
+ },
808
+ fields: [defineField({
809
+ ...typeof type == "string" ? {
810
+ type
811
+ } : type,
812
+ name: "value"
813
+ })],
814
+ preview: {
815
+ select: {
816
+ title: "value",
817
+ subtitle: LANGUAGE_FIELD_NAME
818
+ }
819
+ }
820
+ });
821
+ };
822
+ function flattenSchemaType(schemaType) {
823
+ return isDocumentSchemaType(schemaType) ? extractInnerFields(schemaType.fields, [], 3) : (console.error("Schema type is not a document"), []);
824
+ }
825
+ function extractInnerFields(fields, path, maxDepth) {
826
+ return path.length >= maxDepth ? [] : fields.reduce((acc, field) => {
827
+ const thisFieldWithPath = {
828
+ path: [...path, field.name],
829
+ ...field
830
+ };
831
+ if (field.type.jsonType === "object") {
832
+ const innerFields = extractInnerFields(field.type.fields, [...path, field.name], maxDepth);
833
+ return acc.push(thisFieldWithPath, ...innerFields), acc;
834
+ } else if (field.type.jsonType === "array" && field.type.of.length && field.type.of.some((item) => "fields" in item)) {
835
+ const innerFields = field.type.of.flatMap((innerField) => extractInnerFields(
836
+ // @ts-expect-error - Fix TS assertion for array fields
837
+ innerField.fields,
838
+ [...path, field.name],
839
+ maxDepth
840
+ ));
841
+ return acc.push(thisFieldWithPath, ...innerFields), acc;
842
+ }
843
+ return acc.push(thisFieldWithPath), acc;
844
+ }, []);
845
+ }
846
+ const internationalizedArray = definePlugin((config) => {
847
+ const pluginConfig = {
848
+ ...CONFIG_DEFAULT,
849
+ ...config
850
+ }, {
851
+ apiVersion = "2025-10-15",
852
+ select,
853
+ languages,
854
+ fieldTypes,
855
+ buttonLocations
856
+ } = pluginConfig;
857
+ return {
858
+ name: "sanity-plugin-internationalized-array",
859
+ // Preload languages for use throughout the Studio
860
+ studio: Array.isArray(languages) ? void 0 : {
861
+ components: {
862
+ layout: (props) => /* @__PURE__ */ jsxs(Fragment, { children: [
863
+ /* @__PURE__ */ jsx(Preload, { apiVersion, languages }),
864
+ props.renderDefault(props)
865
+ ] })
866
+ }
867
+ },
868
+ // Optional: render "add language" buttons as field actions
869
+ document: {
870
+ unstable_fieldActions: buttonLocations.includes("unstable__fieldAction") ? (prev) => [...prev, internationalizedArrayFieldAction] : void 0
871
+ },
872
+ // Wrap document editor with a language provider
873
+ form: {
874
+ components: {
875
+ field: (props) => /* @__PURE__ */ jsx(InternationalizedField, { ...props }),
876
+ input: (props) => !(props.id === "root" && isObjectInputProps(props)) || !flattenSchemaType(props.schemaType).map((field) => field.type.name).some((name) => name.startsWith("internationalizedArray")) ? props.renderDefault(props) : /* @__PURE__ */ jsx(InternationalizedArrayProvider, { ...props, internationalizedArray: pluginConfig })
877
+ }
878
+ },
879
+ // Register custom schema types for the outer array and the inner object
880
+ schema: {
881
+ types: [...fieldTypes.map((type) => array({
882
+ type,
883
+ apiVersion,
884
+ select,
885
+ languages
886
+ })), ...fieldTypes.map((type) => object({
887
+ type
888
+ }))]
889
+ }
890
+ };
891
+ });
892
+ export {
893
+ clear,
894
+ internationalizedArray
895
+ };
896
+ //# sourceMappingURL=index.js.map