sanity-plugin-internationalized-array 5.1.14 → 5.1.15

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/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
- import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
- import { useLanguageFilterStudioContext, languageFilter } from "@sanity/language-filter";
3
- import { useClient, useWorkspace, useGetFormValue, useSchema, isSanityDocument, setIfMissing, insert, PatchEvent, isDocumentSchemaType, defineDocumentFieldAction, useFormValue, set, ArrayOfObjectsItem, MemberItemError, defineField, unset, definePlugin, isObjectInputProps } from "sanity";
1
+ import { languageFilter, useLanguageFilterStudioContext } from "@sanity/language-filter";
2
+ import { ArrayOfObjectsItem, MemberItemError, PatchEvent, defineDocumentFieldAction, defineField, definePlugin, insert, isDocumentSchemaType, isObjectInputProps, isSanityDocument, set, setIfMissing, unset, useClient, useFormValue, useGetFormValue, useSchema, useWorkspace } from "sanity";
4
3
  import { c } from "react/compiler-runtime";
5
- import { Grid, Button, useToast, Stack, Box, Text, Card, Code, Flex, Spinner, Label, MenuButton, Tooltip, MenuItem, Menu } from "@sanity/ui";
4
+ import { Box, Button, Card, Code, Flex, Grid, Label, Menu, MenuButton, MenuItem, Spinner, Stack, Text, Tooltip, useToast } from "@sanity/ui";
6
5
  import { randomKey } from "@sanity/util/content";
7
- import { createContext, useContext, useDeferredValue, use, useCallback, useEffect, createElement } from "react";
6
+ import { createContext, createElement, use, useCallback, useContext, useDeferredValue, useEffect } from "react";
8
7
  import { useDocumentPane } from "sanity/structure";
9
8
  import { AddIcon } from "@sanity/icons/Add";
10
9
  import get from "lodash-es/get.js";
10
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
11
11
  import { TranslateIcon } from "@sanity/icons/Translate";
12
12
  import camelCase from "lodash-es/camelCase.js";
13
13
  import upperFirst from "lodash-es/upperFirst.js";
@@ -15,1120 +15,1230 @@ import { WarningOutlineIcon } from "@sanity/icons/WarningOutline";
15
15
  import { RemoveCircleIcon } from "@sanity/icons/RemoveCircle";
16
16
  const namespace = "sanity-plugin-internationalized-array", functionKeyCache = /* @__PURE__ */ new WeakMap(), promiseCache = /* @__PURE__ */ new Map(), functionCache = /* @__PURE__ */ new Map();
17
17
  function stringifyCacheKey(key) {
18
- return JSON.stringify(key);
18
+ return JSON.stringify(key);
19
19
  }
20
20
  const preloadWithKey = (fn, key) => {
21
- const keyStr = stringifyCacheKey(key);
22
- promiseCache.has(keyStr) || promiseCache.set(keyStr, fn());
21
+ let keyStr = stringifyCacheKey(key);
22
+ promiseCache.has(keyStr) || promiseCache.set(keyStr, fn());
23
23
  }, clear = () => {
24
- promiseCache.clear();
24
+ promiseCache.clear();
25
25
  }, peek = (selectedValue) => {
26
- const key = stringifyCacheKey(["v1", namespace, selectedValue]), promise = promiseCache.get(key);
27
- if (promise && promise._status === "fulfilled")
28
- return promise._value;
26
+ let key = stringifyCacheKey([
27
+ "v1",
28
+ namespace,
29
+ selectedValue
30
+ ]), promise = promiseCache.get(key);
31
+ if (promise && promise._status === "fulfilled") return promise._value;
29
32
  }, createCacheKey = (selectedValue, workspaceId) => {
30
- const selectedValueHash = JSON.stringify(selectedValue);
31
- return workspaceId ? ["v1", namespace, selectedValueHash, workspaceId] : ["v1", namespace, selectedValueHash];
33
+ let selectedValueHash = JSON.stringify(selectedValue);
34
+ return workspaceId ? [
35
+ "v1",
36
+ namespace,
37
+ selectedValueHash,
38
+ workspaceId
39
+ ] : [
40
+ "v1",
41
+ namespace,
42
+ selectedValueHash
43
+ ];
32
44
  }, createOrGetPromise = (fn, key) => {
33
- const keyStr = stringifyCacheKey(key);
34
- if (promiseCache.has(keyStr))
35
- return promiseCache.get(keyStr);
36
- const promise = fn();
37
- return promiseCache.set(keyStr, promise), promise;
45
+ let keyStr = stringifyCacheKey(key);
46
+ if (promiseCache.has(keyStr)) return promiseCache.get(keyStr);
47
+ let promise = fn();
48
+ return promiseCache.set(keyStr, promise), promise;
38
49
  }, getFunctionKey = (fn) => {
39
- const cachedKey = functionKeyCache.get(fn);
40
- if (cachedKey)
41
- return cachedKey;
42
- const fnStr = fn.toString();
43
- let hash = 0;
44
- const maxLength = Math.min(fnStr.length, 100);
45
- for (let i = 0; i < maxLength; i++) {
46
- const char = fnStr.charCodeAt(i);
47
- hash = (hash << 5) - hash + char, hash &= hash;
48
- }
49
- const key = `anonymous_${Math.abs(hash)}`;
50
- return functionKeyCache.set(fn, key), key;
50
+ let cachedKey = functionKeyCache.get(fn);
51
+ if (cachedKey) return cachedKey;
52
+ let fnStr = fn.toString(), hash = 0, maxLength = Math.min(fnStr.length, 100);
53
+ for (let i = 0; i < maxLength; i++) {
54
+ let char = fnStr.charCodeAt(i);
55
+ hash = (hash << 5) - hash + char, hash &= hash;
56
+ }
57
+ let key = `anonymous_${Math.abs(hash)}`;
58
+ return functionKeyCache.set(fn, key), key;
51
59
  }, createFunctionCacheKey = (fn, selectedValue, workspaceId) => {
52
- const functionKey = getFunctionKey(fn), selectedValueHash = JSON.stringify(selectedValue);
53
- return workspaceId ? `${functionKey}:${selectedValueHash}:${workspaceId}` : `${functionKey}:${selectedValueHash}`;
60
+ let functionKey = getFunctionKey(fn), selectedValueHash = JSON.stringify(selectedValue);
61
+ return workspaceId ? `${functionKey}:${selectedValueHash}:${workspaceId}` : `${functionKey}:${selectedValueHash}`;
54
62
  }, getFunctionCache = (fn, selectedValue, workspaceId) => {
55
- const key = createFunctionCacheKey(fn, selectedValue, workspaceId);
56
- return functionCache.get(key);
63
+ let key = createFunctionCacheKey(fn, selectedValue, workspaceId);
64
+ return functionCache.get(key);
57
65
  }, setFunctionCache = (fn, selectedValue, languages, workspaceId) => {
58
- const key = createFunctionCacheKey(fn, selectedValue, workspaceId);
59
- functionCache.set(key, languages);
66
+ let key = createFunctionCacheKey(fn, selectedValue, workspaceId);
67
+ functionCache.set(key, languages);
60
68
  }, LANGUAGE_FIELD_NAME = "language", MAX_COLUMNS = {
61
- codeOnly: 5,
62
- titleOnly: 4,
63
- titleAndCode: 3
69
+ codeOnly: 5,
70
+ titleOnly: 4,
71
+ titleAndCode: 3
64
72
  }, CONFIG_DEFAULT = {
65
- languages: [],
66
- select: {},
67
- defaultLanguages: [],
68
- fieldTypes: [],
69
- apiVersion: "2025-10-15",
70
- buttonLocations: ["field"],
71
- buttonAddAll: !0,
72
- languageDisplay: "codeOnly",
73
- includeForDocumentType: (documentType) => documentType !== "translation.metadata",
74
- languageFilter: {
75
- documentTypes: []
76
- }
73
+ languages: [],
74
+ select: {},
75
+ defaultLanguages: [],
76
+ fieldTypes: [],
77
+ apiVersion: "2025-10-15",
78
+ buttonLocations: ["field"],
79
+ buttonAddAll: !0,
80
+ languageDisplay: "codeOnly",
81
+ includeForDocumentType: (documentType) => documentType !== "translation.metadata",
82
+ languageFilter: { documentTypes: [] }
77
83
  }, getDocumentsToTranslate = (value, rootPath = []) => {
78
- if (Array.isArray(value)) {
79
- const arrayRootPath = [...rootPath], internationalizedValues = value.filter((item) => {
80
- if (Array.isArray(item)) return !1;
81
- if (typeof item == "object") {
82
- const type = item?._type;
83
- return type?.startsWith("internationalizedArray") && type?.endsWith("Value");
84
- }
85
- return !1;
86
- });
87
- return internationalizedValues.length > 0 ? internationalizedValues.map((internationalizedValue) => Object.assign({}, internationalizedValue, {
88
- path: arrayRootPath,
89
- pathString: arrayRootPath.join(".")
90
- })) : value.length > 0 ? value.flatMap((item, index) => getDocumentsToTranslate(item, [...arrayRootPath, index])) : [];
91
- }
92
- if (typeof value == "object" && value) {
93
- const startsWithUnderscoreRegex = /^_/;
94
- return Object.keys(value).filter((key) => !key.match(startsWithUnderscoreRegex)).flatMap((item) => {
95
- const selectedValue = value[item], path = [...rootPath, item];
96
- return getDocumentsToTranslate(selectedValue, path);
97
- });
98
- }
99
- return [];
84
+ if (Array.isArray(value)) {
85
+ let arrayRootPath = [...rootPath], internationalizedValues = value.filter((item) => {
86
+ if (Array.isArray(item)) return !1;
87
+ if (typeof item == "object") {
88
+ let type = item?._type;
89
+ return type?.startsWith("internationalizedArray") && type?.endsWith("Value");
90
+ }
91
+ return !1;
92
+ });
93
+ return internationalizedValues.length > 0 ? internationalizedValues.map((internationalizedValue) => Object.assign({}, internationalizedValue, {
94
+ path: arrayRootPath,
95
+ pathString: arrayRootPath.join(".")
96
+ })) : value.length > 0 ? value.flatMap((item, index) => getDocumentsToTranslate(item, [...arrayRootPath, index])) : [];
97
+ }
98
+ if (typeof value == "object" && value) {
99
+ let startsWithUnderscoreRegex = /^_/;
100
+ return Object.keys(value).filter((key) => !key.match(startsWithUnderscoreRegex)).flatMap((item) => {
101
+ let selectedValue = value[item];
102
+ return getDocumentsToTranslate(selectedValue, [...rootPath, item]);
103
+ });
104
+ }
105
+ return [];
100
106
  };
107
+ /**
108
+ * Formats a language label for display in buttons and field headers
109
+ * based on the configured `languageDisplay` mode:
110
+ *
111
+ * - `'codeOnly'` -> uppercase code, e.g. `"EN"`
112
+ * - `'titleOnly'` -> title as-is, e.g. `"English"`
113
+ * - `'titleAndCode'` -> title with uppercase code, e.g. `"English (EN)"`
114
+ *
115
+ * Falls back to `title` for any unrecognized display mode.
116
+ */
101
117
  function getLanguageDisplay(languageDisplay, title, code) {
102
- return languageDisplay === "codeOnly" ? code.toUpperCase() : languageDisplay === "titleOnly" ? title : languageDisplay === "titleAndCode" ? `${title} (${code.toUpperCase()})` : title;
118
+ return languageDisplay === "codeOnly" ? code.toUpperCase() : languageDisplay === "titleOnly" ? title : languageDisplay === "titleAndCode" ? `${title} (${code.toUpperCase()})` : title;
103
119
  }
120
+ /**
121
+ * Extracts a subset of values from a Sanity document based on a `select`
122
+ * mapping (as configured in the plugin's `select` option).
123
+ *
124
+ * Each key in `select` becomes a key in the returned object, with its value
125
+ * resolved from the document using the corresponding dot-path (via lodash `get`).
126
+ *
127
+ * Array values are filtered to remove incomplete references (objects with
128
+ * `_type: 'reference'` but no `_ref`), since those represent empty reference
129
+ * fields that should be ignored.
130
+ *
131
+ * Returns an empty object when either `select` or `document` is undefined.
132
+ */
104
133
  const getSelectedValue = (select, document) => {
105
- if (!select || !document)
106
- return {};
107
- const selection = select || {}, selectedValue = {};
108
- for (const [key, path] of Object.entries(selection)) {
109
- let value = get(document, path);
110
- Array.isArray(value) && (value = value.filter((item) => typeof item == "object" ? item?._type === "reference" && "_ref" in item : !0)), selectedValue[key] = value;
111
- }
112
- return selectedValue;
134
+ if (!select || !document) return {};
135
+ let selection = select || {}, selectedValue = {};
136
+ for (let [key, path] of Object.entries(selection)) {
137
+ let value = get(document, path);
138
+ Array.isArray(value) && (value = value.filter((item) => typeof item == "object" ? item?._type === "reference" && "_ref" in item : !0)), selectedValue[key] = value;
139
+ }
140
+ return selectedValue;
113
141
  }, InternationalizedArrayContext = createContext({
114
- ...CONFIG_DEFAULT,
115
- languages: [],
116
- filteredLanguages: []
142
+ ...CONFIG_DEFAULT,
143
+ languages: [],
144
+ filteredLanguages: []
117
145
  });
118
146
  function useInternationalizedArrayContext() {
119
- return useContext(InternationalizedArrayContext);
147
+ return useContext(InternationalizedArrayContext);
120
148
  }
121
149
  function InternationalizedArrayProvider(props) {
122
- const $ = c(33), {
123
- internationalizedArray: internationalizedArray2,
124
- documentType
125
- } = props;
126
- let t0;
127
- $[0] !== internationalizedArray2.apiVersion ? (t0 = {
128
- apiVersion: internationalizedArray2.apiVersion
129
- }, $[0] = internationalizedArray2.apiVersion, $[1] = t0) : t0 = $[1];
130
- const client = useClient(t0), workspace = useWorkspace(), {
131
- formState
132
- } = useDocumentPane(), deferredDocument = useDeferredValue(formState?.value);
133
- let t1;
134
- $[2] !== deferredDocument || $[3] !== internationalizedArray2.select ? (t1 = getSelectedValue(internationalizedArray2.select, deferredDocument), $[2] = deferredDocument, $[3] = internationalizedArray2.select, $[4] = t1) : t1 = $[4];
135
- const selectedValue = t1;
136
- let t2;
137
- bb0: {
138
- if (workspace?.name) {
139
- t2 = workspace.name;
140
- break bb0;
141
- }
142
- const t32 = workspace?.name, t42 = workspace?.title;
143
- let t52;
144
- $[5] !== t32 || $[6] !== t42 ? (t52 = JSON.stringify({
145
- name: t32,
146
- title: t42
147
- }), $[5] = t32, $[6] = t42, $[7] = t52) : t52 = $[7], t2 = t52;
148
- }
149
- const workspaceId = t2;
150
- let t3;
151
- $[8] !== selectedValue || $[9] !== workspaceId ? (t3 = createCacheKey(selectedValue, workspaceId), $[8] = selectedValue, $[9] = workspaceId, $[10] = t3) : t3 = $[10];
152
- const cacheKey = t3;
153
- let t4;
154
- bb1: {
155
- if (Array.isArray(internationalizedArray2.languages)) {
156
- t4 = null;
157
- break bb1;
158
- }
159
- let t52;
160
- $[11] !== client || $[12] !== internationalizedArray2 || $[13] !== selectedValue || $[14] !== workspaceId ? (t52 = async () => {
161
- if (typeof internationalizedArray2.languages == "function") {
162
- const result = await internationalizedArray2.languages(client, selectedValue);
163
- return setFunctionCache(internationalizedArray2.languages, selectedValue, result, workspaceId), result;
164
- }
165
- return internationalizedArray2.languages;
166
- }, $[11] = client, $[12] = internationalizedArray2, $[13] = selectedValue, $[14] = workspaceId, $[15] = t52) : t52 = $[15];
167
- let t62;
168
- $[16] !== cacheKey || $[17] !== t52 ? (t62 = createOrGetPromise(t52, cacheKey), $[16] = cacheKey, $[17] = t52, $[18] = t62) : t62 = $[18], t4 = t62;
169
- }
170
- const languagesPromise = t4, languages = languagesPromise ? use(languagesPromise) : internationalizedArray2.languages, {
171
- selectedLanguageIds,
172
- options: languageFilterOptions
173
- } = useLanguageFilterStudioContext();
174
- let t5;
175
- $[19] !== documentType || $[20] !== languageFilterOptions.documentTypes ? (t5 = languageFilterOptions.documentTypes.includes(documentType), $[19] = documentType, $[20] = languageFilterOptions.documentTypes, $[21] = t5) : t5 = $[21];
176
- const languageFilterEnabled = t5;
177
- let t6;
178
- $[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];
179
- const filteredLanguages = t6;
180
- let t7;
181
- $[26] !== filteredLanguages || $[27] !== internationalizedArray2 || $[28] !== languages ? (t7 = {
182
- ...internationalizedArray2,
183
- languages,
184
- filteredLanguages
185
- }, $[26] = filteredLanguages, $[27] = internationalizedArray2, $[28] = languages, $[29] = t7) : t7 = $[29];
186
- const context = t7;
187
- let t8;
188
- return $[30] !== context || $[31] !== props.children ? (t8 = /* @__PURE__ */ jsx(InternationalizedArrayContext.Provider, { value: context, children: props.children }), $[30] = context, $[31] = props.children, $[32] = t8) : t8 = $[32], t8;
150
+ let $ = c(33), { internationalizedArray, documentType } = props, t0;
151
+ $[0] === internationalizedArray.apiVersion ? t0 = $[1] : (t0 = { apiVersion: internationalizedArray.apiVersion }, $[0] = internationalizedArray.apiVersion, $[1] = t0);
152
+ let client = useClient(t0), workspace = useWorkspace(), { formState } = useDocumentPane(), deferredDocument = useDeferredValue(formState?.value), t1;
153
+ $[2] !== deferredDocument || $[3] !== internationalizedArray.select ? (t1 = getSelectedValue(internationalizedArray.select, deferredDocument), $[2] = deferredDocument, $[3] = internationalizedArray.select, $[4] = t1) : t1 = $[4];
154
+ let selectedValue = t1, t2;
155
+ bb0: {
156
+ if (workspace?.name) {
157
+ t2 = workspace.name;
158
+ break bb0;
159
+ }
160
+ let t3 = workspace?.name, t4 = workspace?.title, t5;
161
+ $[5] !== t3 || $[6] !== t4 ? (t5 = JSON.stringify({
162
+ name: t3,
163
+ title: t4
164
+ }), $[5] = t3, $[6] = t4, $[7] = t5) : t5 = $[7], t2 = t5;
165
+ }
166
+ let workspaceId = t2, t3;
167
+ $[8] !== selectedValue || $[9] !== workspaceId ? (t3 = createCacheKey(selectedValue, workspaceId), $[8] = selectedValue, $[9] = workspaceId, $[10] = t3) : t3 = $[10];
168
+ let cacheKey = t3, t4;
169
+ bb1: {
170
+ if (Array.isArray(internationalizedArray.languages)) {
171
+ t4 = null;
172
+ break bb1;
173
+ }
174
+ let t5;
175
+ $[11] !== client || $[12] !== internationalizedArray || $[13] !== selectedValue || $[14] !== workspaceId ? (t5 = async () => {
176
+ if (typeof internationalizedArray.languages == "function") {
177
+ let result = await internationalizedArray.languages(client, selectedValue);
178
+ return setFunctionCache(internationalizedArray.languages, selectedValue, result, workspaceId), result;
179
+ }
180
+ return internationalizedArray.languages;
181
+ }, $[11] = client, $[12] = internationalizedArray, $[13] = selectedValue, $[14] = workspaceId, $[15] = t5) : t5 = $[15];
182
+ let t6;
183
+ $[16] !== cacheKey || $[17] !== t5 ? (t6 = createOrGetPromise(t5, cacheKey), $[16] = cacheKey, $[17] = t5, $[18] = t6) : t6 = $[18], t4 = t6;
184
+ }
185
+ let languagesPromise = t4, languages = languagesPromise ? use(languagesPromise) : internationalizedArray.languages, { selectedLanguageIds, options: languageFilterOptions } = useLanguageFilterStudioContext(), t5;
186
+ $[19] !== documentType || $[20] !== languageFilterOptions.documentTypes ? (t5 = languageFilterOptions.documentTypes.includes(documentType), $[19] = documentType, $[20] = languageFilterOptions.documentTypes, $[21] = t5) : t5 = $[21];
187
+ let languageFilterEnabled = t5, t6;
188
+ $[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];
189
+ let filteredLanguages = t6, t7;
190
+ $[26] !== filteredLanguages || $[27] !== internationalizedArray || $[28] !== languages ? (t7 = {
191
+ ...internationalizedArray,
192
+ languages,
193
+ filteredLanguages
194
+ }, $[26] = filteredLanguages, $[27] = internationalizedArray, $[28] = languages, $[29] = t7) : t7 = $[29];
195
+ let context = t7, t8;
196
+ return $[30] !== context || $[31] !== props.children ? (t8 = /* @__PURE__ */ jsx(InternationalizedArrayContext.Provider, {
197
+ value: context,
198
+ children: props.children
199
+ }), $[30] = context, $[31] = props.children, $[32] = t8) : t8 = $[32], t8;
189
200
  }
201
+ /**
202
+ * Renders a grid of "add language" buttons — one per configured language.
203
+ *
204
+ * Returns `null` when the `languages` array is empty.
205
+ *
206
+ * Each button is disabled when:
207
+ * - `readOnly` is `true`, or
208
+ * - the language already exists in the current `value` array
209
+ * (matched via `LANGUAGE_FIELD_NAME`).
210
+ *
211
+ * The button label is formatted according to the `languageDisplay` setting
212
+ * from the plugin context (e.g. code-only, title-only, or both).
213
+ * An `AddIcon` is shown unless there are more languages than fit in one row
214
+ * and the display mode is `'codeOnly'`.
215
+ */
190
216
  function AddButtons(props) {
191
- const $ = c(15), {
192
- readOnly,
193
- languagesInUse,
194
- handleClick
195
- } = props, {
196
- languageDisplay,
197
- filteredLanguages: languages
198
- } = useInternationalizedArrayContext();
199
- if (!languages.length)
200
- return null;
201
- const t0 = Math.min(languages.length, MAX_COLUMNS[languageDisplay]);
202
- let t1;
203
- if ($[0] !== handleClick || $[1] !== languageDisplay || $[2] !== languages || $[3] !== languagesInUse || $[4] !== readOnly) {
204
- let t22;
205
- $[6] !== handleClick || $[7] !== languageDisplay || $[8] !== languages.length || $[9] !== languagesInUse || $[10] !== readOnly ? (t22 = (language) => {
206
- const languageTitle = getLanguageDisplay(languageDisplay, language.title, language.id);
207
- return /* @__PURE__ */ jsx(Button, { tone: "primary", mode: "ghost", fontSize: 1, "data-testid": `add-${language.id}`, disabled: readOnly || languagesInUse.includes(language.id), text: languageTitle, icon: languages.length > MAX_COLUMNS[languageDisplay] && languageDisplay === "codeOnly" ? void 0 : AddIcon, value: language.id, onClick: () => handleClick(language.id) }, language.id);
208
- }, $[6] = handleClick, $[7] = languageDisplay, $[8] = languages.length, $[9] = languagesInUse, $[10] = readOnly, $[11] = t22) : t22 = $[11], t1 = languages.map(t22), $[0] = handleClick, $[1] = languageDisplay, $[2] = languages, $[3] = languagesInUse, $[4] = readOnly, $[5] = t1;
209
- } else
210
- t1 = $[5];
211
- let t2;
212
- return $[12] !== t0 || $[13] !== t1 ? (t2 = /* @__PURE__ */ jsx(Grid, { gridTemplateColumns: t0, gap: 2, "data-testid": "add-buttons-grid", children: t1 }), $[12] = t0, $[13] = t1, $[14] = t2) : t2 = $[14], t2;
217
+ let $ = c(15), { readOnly, languagesInUse, handleClick } = props, { languageDisplay, filteredLanguages: languages } = useInternationalizedArrayContext();
218
+ if (!languages.length) return null;
219
+ let t0 = Math.min(languages.length, MAX_COLUMNS[languageDisplay]), t1;
220
+ if ($[0] !== handleClick || $[1] !== languageDisplay || $[2] !== languages || $[3] !== languagesInUse || $[4] !== readOnly) {
221
+ let t2;
222
+ $[6] !== handleClick || $[7] !== languageDisplay || $[8] !== languages.length || $[9] !== languagesInUse || $[10] !== readOnly ? (t2 = (language) => {
223
+ let languageTitle = getLanguageDisplay(languageDisplay, language.title, language.id);
224
+ return /* @__PURE__ */ jsx(Button, {
225
+ tone: "primary",
226
+ mode: "ghost",
227
+ fontSize: 1,
228
+ "data-testid": `add-${language.id}`,
229
+ disabled: readOnly || languagesInUse.includes(language.id),
230
+ text: languageTitle,
231
+ icon: languages.length > MAX_COLUMNS[languageDisplay] && languageDisplay === "codeOnly" ? void 0 : AddIcon,
232
+ value: language.id,
233
+ onClick: () => handleClick(language.id)
234
+ }, language.id);
235
+ }, $[6] = handleClick, $[7] = languageDisplay, $[8] = languages.length, $[9] = languagesInUse, $[10] = readOnly, $[11] = t2) : t2 = $[11], t1 = languages.map(t2), $[0] = handleClick, $[1] = languageDisplay, $[2] = languages, $[3] = languagesInUse, $[4] = readOnly, $[5] = t1;
236
+ } else t1 = $[5];
237
+ let t2;
238
+ return $[12] !== t0 || $[13] !== t1 ? (t2 = /* @__PURE__ */ jsx(Grid, {
239
+ gridTemplateColumns: t0,
240
+ gap: 2,
241
+ "data-testid": "add-buttons-grid",
242
+ children: t1
243
+ }), $[12] = t0, $[13] = t1, $[14] = t2) : t2 = $[14], t2;
213
244
  }
245
+ /**
246
+ * Document-level "add translation" panel that appears outside individual
247
+ * internationalized array fields (when `buttonLocations` includes `'document'`).
248
+ *
249
+ * Renders a heading and a row of per-language buttons. When a language button
250
+ * is clicked the component:
251
+ *
252
+ * 1. Scans the current document for all internationalized array fields
253
+ * using `getDocumentsToTranslate`.
254
+ * 2. Filters out fields that already contain a translation for the selected
255
+ * language, and deduplicates by field path.
256
+ * 3. Shows an error toast if no eligible fields remain.
257
+ * 4. Creates `setIfMissing` + `insert` patches to add the new language
258
+ * entry to each eligible field, dispatching them via `onChange`.
259
+ *
260
+ * For Portable Text and other array-based value fields, the initial value
261
+ * is set to an empty array (`[]`) rather than `undefined`.
262
+ */
214
263
  function DocumentAddButtons() {
215
- const $ = c(13), getFormValue = useGetFormValue(), {
216
- filteredLanguages
217
- } = useInternationalizedArrayContext(), toast = useToast(), {
218
- onChange,
219
- formState
220
- } = useDocumentPane(), schema = useSchema();
221
- let t0;
222
- $[0] !== schema ? (t0 = (typeName) => {
223
- if (!typeName)
224
- return;
225
- const match = typeName.match(/^internationalizedArray(.+)Value$/);
226
- if (!match || !match[1])
227
- return;
228
- const baseTypeName = match[1].charAt(0).toLowerCase() + match[1].slice(1), arrayBasedTypes = /* @__PURE__ */ new Set(["body", "htmlContent", "blockContent", "portableText"]);
229
- if (arrayBasedTypes.has(baseTypeName))
230
- return [];
231
- const schemaType = schema.get(typeName);
232
- if (schemaType && "fields" in schemaType) {
233
- const valueField = schemaType.fields.find(_temp$2);
234
- if (valueField) {
235
- const fieldType = valueField.type;
236
- if (fieldType?.jsonType === "array" || fieldType?.name === "array" || fieldType?.type === "array" || fieldType?.of !== void 0 || fieldType?.name && arrayBasedTypes.has(fieldType.name))
237
- return [];
238
- }
239
- }
240
- }, $[0] = schema, $[1] = t0) : t0 = $[1];
241
- const getInitialValueForType = t0;
242
- let t1;
243
- $[2] !== filteredLanguages || $[3] !== getFormValue || $[4] !== getInitialValueForType || $[5] !== onChange || $[6] !== toast ? (t1 = async (languageId) => {
244
- const value = getFormValue([]);
245
- if (!isSanityDocument(value)) {
246
- toast.push({
247
- status: "error",
248
- title: "No document value found"
249
- });
250
- return;
251
- }
252
- const documentsToTranslation = getDocumentsToTranslate(value, []), 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), []);
253
- if (removeDuplicates.length === 0) {
254
- const language = filteredLanguages.find((l) => l.id === languageId);
255
- toast.push({
256
- status: "warning",
257
- title: `No missing translations for ${language?.title || languageId} found.`
258
- });
259
- return;
260
- }
261
- const patches = [];
262
- for (const toTranslate of removeDuplicates) {
263
- const path = toTranslate.path, initialValue = getInitialValueForType(toTranslate._type), ifMissing = setIfMissing([], path), insertValue = insert([{
264
- _key: randomKey(),
265
- [LANGUAGE_FIELD_NAME]: languageId,
266
- _type: toTranslate._type,
267
- value: initialValue
268
- }], "after", [...path, -1]);
269
- patches.push(ifMissing), patches.push(insertValue);
270
- }
271
- onChange(PatchEvent.from(patches.flat()));
272
- }, $[2] = filteredLanguages, $[3] = getFormValue, $[4] = getInitialValueForType, $[5] = onChange, $[6] = toast, $[7] = t1) : t1 = $[7];
273
- const handleDocumentButtonClick = t1;
274
- let t2;
275
- $[8] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t2 = /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { size: 1, weight: "semibold", children: "Add translation to internationalized fields" }) }), $[8] = t2) : t2 = $[8];
276
- const t3 = !!formState?.readOnly;
277
- let t4;
278
- $[9] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t4 = [], $[9] = t4) : t4 = $[9];
279
- let t5;
280
- return $[10] !== handleDocumentButtonClick || $[11] !== t3 ? (t5 = /* @__PURE__ */ jsxs(Stack, { gap: 3, children: [
281
- t2,
282
- /* @__PURE__ */ jsx(AddButtons, { readOnly: t3, handleClick: handleDocumentButtonClick, languagesInUse: t4 })
283
- ] }), $[10] = handleDocumentButtonClick, $[11] = t3, $[12] = t5) : t5 = $[12], t5;
264
+ let $ = c(13), getFormValue = useGetFormValue(), { filteredLanguages } = useInternationalizedArrayContext(), toast = useToast(), { onChange, formState } = useDocumentPane(), schema = useSchema(), t0;
265
+ $[0] === schema ? t0 = $[1] : (t0 = (typeName) => {
266
+ if (!typeName) return;
267
+ let match = typeName.match(/^internationalizedArray(.+)Value$/);
268
+ if (!match || !match[1]) return;
269
+ let baseTypeName = match[1].charAt(0).toLowerCase() + match[1].slice(1), arrayBasedTypes = /* @__PURE__ */ new Set([
270
+ "body",
271
+ "htmlContent",
272
+ "blockContent",
273
+ "portableText"
274
+ ]);
275
+ if (arrayBasedTypes.has(baseTypeName)) return [];
276
+ let schemaType = schema.get(typeName);
277
+ if (schemaType && "fields" in schemaType) {
278
+ let valueField = schemaType.fields.find(_temp$2);
279
+ if (valueField) {
280
+ let fieldType = valueField.type;
281
+ if (fieldType?.jsonType === "array" || fieldType?.name === "array" || fieldType?.type === "array" || fieldType?.of !== void 0 || fieldType?.name && arrayBasedTypes.has(fieldType.name)) return [];
282
+ }
283
+ }
284
+ }, $[0] = schema, $[1] = t0);
285
+ let getInitialValueForType = t0, t1;
286
+ $[2] !== filteredLanguages || $[3] !== getFormValue || $[4] !== getInitialValueForType || $[5] !== onChange || $[6] !== toast ? (t1 = async (languageId) => {
287
+ let value = getFormValue([]);
288
+ if (!isSanityDocument(value)) {
289
+ toast.push({
290
+ status: "error",
291
+ title: "No document value found"
292
+ });
293
+ return;
294
+ }
295
+ let documentsToTranslation = getDocumentsToTranslate(value, []), 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), []);
296
+ if (removeDuplicates.length === 0) {
297
+ let language = filteredLanguages.find((l) => l.id === languageId);
298
+ toast.push({
299
+ status: "warning",
300
+ title: `No missing translations for ${language?.title || languageId} found.`
301
+ });
302
+ return;
303
+ }
304
+ let patches = [];
305
+ for (let toTranslate of removeDuplicates) {
306
+ let path = toTranslate.path, initialValue = getInitialValueForType(toTranslate._type), ifMissing = setIfMissing([], path), insertValue = insert([{
307
+ _key: randomKey(),
308
+ [LANGUAGE_FIELD_NAME]: languageId,
309
+ _type: toTranslate._type,
310
+ value: initialValue
311
+ }], "after", [...path, -1]);
312
+ patches.push(ifMissing), patches.push(insertValue);
313
+ }
314
+ onChange(PatchEvent.from(patches.flat()));
315
+ }, $[2] = filteredLanguages, $[3] = getFormValue, $[4] = getInitialValueForType, $[5] = onChange, $[6] = toast, $[7] = t1) : t1 = $[7];
316
+ let handleDocumentButtonClick = t1, t2;
317
+ $[8] === Symbol.for("react.memo_cache_sentinel") ? (t2 = /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, {
318
+ size: 1,
319
+ weight: "semibold",
320
+ children: "Add translation to internationalized fields"
321
+ }) }), $[8] = t2) : t2 = $[8];
322
+ let t3 = !!formState?.readOnly, t4;
323
+ $[9] === Symbol.for("react.memo_cache_sentinel") ? (t4 = [], $[9] = t4) : t4 = $[9];
324
+ let t5;
325
+ return $[10] !== handleDocumentButtonClick || $[11] !== t3 ? (t5 = /* @__PURE__ */ jsxs(Stack, {
326
+ gap: 3,
327
+ children: [t2, /* @__PURE__ */ jsx(AddButtons, {
328
+ readOnly: t3,
329
+ handleClick: handleDocumentButtonClick,
330
+ languagesInUse: t4
331
+ })]
332
+ }), $[10] = handleDocumentButtonClick, $[11] = t3, $[12] = t5) : t5 = $[12], t5;
284
333
  }
285
334
  function _temp$2(f) {
286
- return f.name === "value";
335
+ return f.name === "value";
287
336
  }
337
+ /**
338
+ * An input component for the root object of an internationalized array.
339
+ * It renders the document add buttons if the buttonLocations include 'document'.
340
+ */
288
341
  function InternationalizedArrayFormInput(props) {
289
- const $ = c(7);
290
- if (props.pluginConfig?.buttonLocations?.includes("document")) {
291
- let t02;
292
- $[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t02 = /* @__PURE__ */ jsx(DocumentAddButtons, {}), $[0] = t02) : t02 = $[0];
293
- let t1;
294
- $[1] !== props ? (t1 = props.renderDefault(props), $[1] = props, $[2] = t1) : t1 = $[2];
295
- let t2;
296
- return $[3] !== t1 ? (t2 = /* @__PURE__ */ jsxs(Stack, { gap: 5, children: [
297
- t02,
298
- t1
299
- ] }), $[3] = t1, $[4] = t2) : t2 = $[4], t2;
300
- }
301
- let t0;
302
- return $[5] !== props ? (t0 = props.renderDefault(props), $[5] = props, $[6] = t0) : t0 = $[6], t0;
342
+ let $ = c(7);
343
+ if (props.pluginConfig?.buttonLocations?.includes("document")) {
344
+ let t0;
345
+ $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx(DocumentAddButtons, {}), $[0] = t0) : t0 = $[0];
346
+ let t1;
347
+ $[1] === props ? t1 = $[2] : (t1 = props.renderDefault(props), $[1] = props, $[2] = t1);
348
+ let t2;
349
+ return $[3] === t1 ? t2 = $[4] : (t2 = /* @__PURE__ */ jsxs(Stack, {
350
+ gap: 5,
351
+ children: [t0, t1]
352
+ }), $[3] = t1, $[4] = t2), t2;
353
+ }
354
+ let t0;
355
+ return $[5] === props ? t0 = $[6] : (t0 = props.renderDefault(props), $[5] = props, $[6] = t0), t0;
303
356
  }
357
+ /**
358
+ * Returns true when a document schema contains any field (including nested
359
+ * object/array item fields) whose type name starts with `internationalizedArray`.
360
+ *
361
+ * Traversal short-circuits on first match to avoid unnecessary work.
362
+ */
304
363
  function hasInternationalizedArrayField(schemaType) {
305
- return isDocumentSchemaType(schemaType) ? hasInternationalizedArrayInFields(schemaType.fields) : !1;
364
+ return isDocumentSchemaType(schemaType) ? hasInternationalizedArrayInFields(schemaType.fields) : !1;
306
365
  }
307
366
  function hasInternationalizedArrayInFields(fields, visited = /* @__PURE__ */ new Set()) {
308
- for (const field of fields)
309
- if (!visited.has(field.type)) {
310
- if (visited.add(field.type), field.type.name.startsWith("internationalizedArray") || field.type.jsonType === "object" && hasInternationalizedArrayInFields(field.type.fields, visited))
311
- return !0;
312
- if (field.type.jsonType === "array" && field.type.of.length > 0)
313
- for (const item of field.type.of) {
314
- if ("name" in item && typeof item.name == "string" && item.name.startsWith("internationalizedArray"))
315
- return !0;
316
- if ("fields" in item && Array.isArray(item.fields)) {
317
- if (visited.has(item))
318
- continue;
319
- if (visited.add(item), hasInternationalizedArrayInFields(item.fields, visited))
320
- return !0;
321
- }
322
- }
323
- }
324
- return !1;
367
+ for (let field of fields) if (!visited.has(field.type)) {
368
+ if (visited.add(field.type), field.type.name.startsWith("internationalizedArray") || field.type.jsonType === "object" && hasInternationalizedArrayInFields(field.type.fields, visited)) return !0;
369
+ if (field.type.jsonType === "array" && field.type.of.length > 0) for (let item of field.type.of) {
370
+ if ("name" in item && typeof item.name == "string" && item.name.startsWith("internationalizedArray")) return !0;
371
+ if ("fields" in item && Array.isArray(item.fields)) {
372
+ if (visited.has(item)) continue;
373
+ if (visited.add(item), hasInternationalizedArrayInFields(item.fields, visited)) return !0;
374
+ }
375
+ }
376
+ }
377
+ return !1;
325
378
  }
326
379
  function InternationalizedArrayLayout(props) {
327
- const $ = c(10), schemaType = useSchema().get(props.documentType);
328
- if (!schemaType) {
329
- console.error(`Schema type not found: ${props.documentType}`);
330
- let t02;
331
- return $[0] !== props ? (t02 = props.renderDefault(props), $[0] = props, $[1] = t02) : t02 = $[1], t02;
332
- }
333
- if (hasInternationalizedArrayField(schemaType) && props.pluginConfig.includeForDocumentType(props.documentType)) {
334
- const t02 = props.pluginConfig, t1 = props.documentType;
335
- let t2;
336
- $[2] !== props ? (t2 = props.renderDefault(props), $[2] = props, $[3] = t2) : t2 = $[3];
337
- let t3;
338
- return $[4] !== props.documentType || $[5] !== props.pluginConfig || $[6] !== t2 ? (t3 = /* @__PURE__ */ jsx(InternationalizedArrayProvider, { internationalizedArray: t02, documentType: t1, children: t2 }), $[4] = props.documentType, $[5] = props.pluginConfig, $[6] = t2, $[7] = t3) : t3 = $[7], t3;
339
- }
340
- let t0;
341
- return $[8] !== props ? (t0 = props.renderDefault(props), $[8] = props, $[9] = t0) : t0 = $[9], t0;
380
+ let $ = c(10), schemaType = useSchema().get(props.documentType);
381
+ if (!schemaType) {
382
+ console.error(`Schema type not found: ${props.documentType}`);
383
+ let t0;
384
+ return $[0] === props ? t0 = $[1] : (t0 = props.renderDefault(props), $[0] = props, $[1] = t0), t0;
385
+ }
386
+ if (hasInternationalizedArrayField(schemaType) && props.pluginConfig.includeForDocumentType(props.documentType)) {
387
+ let t0 = props.pluginConfig, t1 = props.documentType, t2;
388
+ $[2] === props ? t2 = $[3] : (t2 = props.renderDefault(props), $[2] = props, $[3] = t2);
389
+ let t3;
390
+ return $[4] !== props.documentType || $[5] !== props.pluginConfig || $[6] !== t2 ? (t3 = /* @__PURE__ */ jsx(InternationalizedArrayProvider, {
391
+ internationalizedArray: t0,
392
+ documentType: t1,
393
+ children: t2
394
+ }), $[4] = props.documentType, $[5] = props.pluginConfig, $[6] = t2, $[7] = t3) : t3 = $[7], t3;
395
+ }
396
+ let t0;
397
+ return $[8] === props ? t0 = $[9] : (t0 = props.renderDefault(props), $[8] = props, $[9] = t0), t0;
342
398
  }
343
399
  function Preload(props) {
344
- const $ = c(2);
345
- let t0;
346
- $[0] !== props.apiVersion ? (t0 = {
347
- apiVersion: props.apiVersion
348
- }, $[0] = props.apiVersion, $[1] = t0) : t0 = $[1];
349
- const client = useClient(t0), cacheKey = createCacheKey({});
350
- return Array.isArray(peek({})) || preloadWithKey(async () => {
351
- if (Array.isArray(props.languages))
352
- return props.languages;
353
- const result = await props.languages(client, {});
354
- return setFunctionCache(props.languages, {}, result), result;
355
- }, cacheKey), null;
400
+ let $ = c(2), t0;
401
+ $[0] === props.apiVersion ? t0 = $[1] : (t0 = { apiVersion: props.apiVersion }, $[0] = props.apiVersion, $[1] = t0);
402
+ let client = useClient(t0), cacheKey = createCacheKey({});
403
+ return Array.isArray(peek({})) || preloadWithKey(async () => {
404
+ if (Array.isArray(props.languages)) return props.languages;
405
+ let result = await props.languages(client, {});
406
+ return setFunctionCache(props.languages, {}, result), result;
407
+ }, cacheKey), null;
356
408
  }
409
+ /**
410
+ * Checks whether every language in the provided list has a corresponding entry
411
+ * in the value array. It extracts language IDs from value items using
412
+ * `LANGUAGE_FIELD_NAME` and compares them against the expected language IDs.
413
+ *
414
+ * Returns `true` only when the value array length matches the number of unique
415
+ * languages and every value language ID is found in the languages list
416
+ * (order does not matter). The length check ensures duplicates in value are
417
+ * correctly rejected.
418
+ */
357
419
  function checkAllLanguagesArePresent(languages, value) {
358
- const filteredLanguageIds = new Set(languages.map((l) => l.id)), languagesInUseIds = value ? value.map((v) => v[LANGUAGE_FIELD_NAME]) : [];
359
- return languagesInUseIds.length !== filteredLanguageIds.size || new Set(languagesInUseIds).size !== languagesInUseIds.length ? !1 : languagesInUseIds.every((key) => filteredLanguageIds.has(key));
420
+ let filteredLanguageIds = new Set(languages.map((l) => l.id)), languagesInUseIds = value ? value.map((v) => v[LANGUAGE_FIELD_NAME]) : [];
421
+ return languagesInUseIds.length !== filteredLanguageIds.size || new Set(languagesInUseIds).size !== languagesInUseIds.length ? !1 : languagesInUseIds.every((key) => filteredLanguageIds.has(key));
360
422
  }
423
+ /**
424
+ * Generates the label text for the "add all / add missing languages" button.
425
+ *
426
+ * - When there is no existing value: returns `"Add {title} Field"` for a
427
+ * single language, or `"Add all languages"` for multiple.
428
+ * - When some values already exist: returns `"Add missing language"` (singular)
429
+ * or `"Add missing languages"` (plural) depending on how many are left.
430
+ */
361
431
  function createAddAllTitle(value, languages) {
362
- 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";
432
+ 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";
363
433
  }
364
434
  function isInternationalizedArrayItemType(type) {
365
- return type.startsWith("internationalizedArray") && type.endsWith("Value");
435
+ return type.startsWith("internationalizedArray") && type.endsWith("Value");
366
436
  }
437
+ /**
438
+ * Creates an array of Sanity `FormInsertPatch` objects that add new language
439
+ * entries to an internationalized array field.
440
+ *
441
+ * If `addLanguageKeys` is provided, patches are created for those specific
442
+ * language IDs. Otherwise, patches are created for all filtered languages
443
+ * that are not already present in the current `value` array, for example when adding all missing languages.
444
+ *
445
+ * Each new item is assigned the correct `_type` (derived from the schema)
446
+ * and the language identifier via `LANGUAGE_FIELD_NAME`.
447
+ *
448
+ * Insertions are ordered to maintain the same sequence as the master
449
+ * `languages` list: each new item is inserted before the next existing
450
+ * language in the value array, or appended at the end if no subsequent
451
+ * language exists.
452
+ */
367
453
  function createAddLanguagePatches(config) {
368
- const {
369
- addLanguageKeys,
370
- schemaTypeName,
371
- languages,
372
- filteredLanguages,
373
- value,
374
- path = []
375
- } = config, type = `${schemaTypeName}Value`;
376
- if (!isInternationalizedArrayItemType(type))
377
- throw new Error(`Invalid internationalized array type: ${type}`);
378
- const itemBase = {
379
- _type: type
380
- }, newItems = Array.isArray(addLanguageKeys) && addLanguageKeys.length > 0 ? addLanguageKeys.filter((id) => value?.length ? !value.find((v) => v[LANGUAGE_FIELD_NAME] === id) : !0).map((id) => Object.assign({}, itemBase, {
381
- _key: randomKey(),
382
- [LANGUAGE_FIELD_NAME]: id
383
- })) : filteredLanguages.filter((language) => value?.length ? !value.find((v) => v[LANGUAGE_FIELD_NAME] === language.id) : !0).map((language) => Object.assign({}, itemBase, {
384
- _key: randomKey(),
385
- [LANGUAGE_FIELD_NAME]: language.id
386
- })), languagesInUse = value?.length ? value.map((v) => v) : [];
387
- return newItems.map((item) => {
388
- 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]));
389
- return nextLanguageIndex < 0 ? languagesInUse.push(item) : languagesInUse.splice(nextLanguageIndex, 0, item), nextLanguageIndex < 0 ? (
390
- // No next language (-1), add to end of array
391
- insert([item], "after", [...path, nextLanguageIndex])
392
- ) : (
393
- // Next language found, insert before that
394
- insert([item], "before", [...path, nextLanguageIndex])
395
- );
396
- });
454
+ let { addLanguageKeys, schemaTypeName, languages, filteredLanguages, value, path = [] } = config, type = `${schemaTypeName}Value`;
455
+ if (!isInternationalizedArrayItemType(type)) throw Error(`Invalid internationalized array type: ${type}`);
456
+ let itemBase = { _type: type }, newItems = Array.isArray(addLanguageKeys) && addLanguageKeys.length > 0 ? addLanguageKeys.filter((id) => value?.length ? !value.find((v) => v[LANGUAGE_FIELD_NAME] === id) : !0).map((id) => Object.assign({}, itemBase, {
457
+ _key: randomKey(),
458
+ [LANGUAGE_FIELD_NAME]: id
459
+ })) : filteredLanguages.filter((language) => value?.length ? !value.find((v) => v[LANGUAGE_FIELD_NAME] === language.id) : !0).map((language) => Object.assign({}, itemBase, {
460
+ _key: randomKey(),
461
+ [LANGUAGE_FIELD_NAME]: language.id
462
+ })), languagesInUse = value?.length ? value.map((v) => v) : [];
463
+ return newItems.map((item) => {
464
+ let 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]));
465
+ return nextLanguageIndex < 0 ? languagesInUse.push(item) : languagesInUse.splice(nextLanguageIndex, 0, item), nextLanguageIndex < 0 ? insert([item], "after", [...path, nextLanguageIndex]) : insert([item], "before", [...path, nextLanguageIndex]);
466
+ });
397
467
  }
398
- const createTranslateFieldActions = (fieldActionProps, {
399
- languages,
400
- filteredLanguages
401
- }) => languages.map((language) => {
402
- const value = useFormValue(fieldActionProps.path), {
403
- onChange,
404
- formState
405
- } = useDocumentPane(), disabled = !!formState?.readOnly || (value && Array.isArray(value) ? !!value?.find((item) => item[LANGUAGE_FIELD_NAME] === language.id) : !1), hidden = !filteredLanguages.some((f) => f.id === language.id), onAction = useCallback(() => {
406
- const {
407
- schemaType,
408
- path
409
- } = fieldActionProps, addLanguageKeys = [language.id], patches = createAddLanguagePatches({
410
- addLanguageKeys,
411
- schemaTypeName: schemaType.name,
412
- languages,
413
- filteredLanguages,
414
- value,
415
- path
416
- });
417
- onChange(PatchEvent.from([setIfMissing([], path), ...patches]));
418
- }, [language.id, value, onChange]);
419
- return {
420
- type: "action",
421
- icon: AddIcon,
422
- onAction,
423
- title: language.title,
424
- hidden,
425
- disabled
426
- };
427
- }), AddMissingTranslationsFieldAction = (fieldActionProps, {
428
- languages,
429
- filteredLanguages
430
- }) => {
431
- const value = useFormValue(fieldActionProps.path), {
432
- onChange,
433
- formState
434
- } = useDocumentPane(), disabled = !!formState?.readOnly || value && value.length === filteredLanguages.length, hidden = checkAllLanguagesArePresent(filteredLanguages, value), onAction = useCallback(() => {
435
- const {
436
- schemaType,
437
- path
438
- } = fieldActionProps, patches = createAddLanguagePatches({
439
- addLanguageKeys: [],
440
- schemaTypeName: schemaType.name,
441
- languages,
442
- filteredLanguages,
443
- value,
444
- path
445
- });
446
- onChange(PatchEvent.from([setIfMissing([], path), ...patches]));
447
- }, [fieldActionProps, filteredLanguages, languages, onChange, value]);
448
- return {
449
- type: "action",
450
- icon: AddIcon,
451
- onAction,
452
- title: createAddAllTitle(value, filteredLanguages),
453
- disabled,
454
- hidden
455
- };
468
+ const createTranslateFieldActions = (fieldActionProps, { languages, filteredLanguages }) => languages.map((language) => {
469
+ let value = useFormValue(fieldActionProps.path), { onChange, formState } = useDocumentPane(), disabled = !!formState?.readOnly || (value && Array.isArray(value) ? !!value?.find((item) => item.language === language.id) : !1), hidden = !filteredLanguages.some((f) => f.id === language.id);
470
+ return {
471
+ type: "action",
472
+ icon: AddIcon,
473
+ onAction: useCallback(() => {
474
+ let { schemaType, path } = fieldActionProps, patches = createAddLanguagePatches({
475
+ addLanguageKeys: [language.id],
476
+ schemaTypeName: schemaType.name,
477
+ languages,
478
+ filteredLanguages,
479
+ value,
480
+ path
481
+ });
482
+ onChange(PatchEvent.from([setIfMissing([], path), ...patches]));
483
+ }, [
484
+ language.id,
485
+ value,
486
+ onChange
487
+ ]),
488
+ title: language.title,
489
+ hidden,
490
+ disabled
491
+ };
492
+ }), AddMissingTranslationsFieldAction = (fieldActionProps, { languages, filteredLanguages }) => {
493
+ let value = useFormValue(fieldActionProps.path), { onChange, formState } = useDocumentPane(), disabled = !!formState?.readOnly || value && value.length === filteredLanguages.length, hidden = checkAllLanguagesArePresent(filteredLanguages, value);
494
+ return {
495
+ type: "action",
496
+ icon: AddIcon,
497
+ onAction: useCallback(() => {
498
+ let { schemaType, path } = fieldActionProps, patches = createAddLanguagePatches({
499
+ addLanguageKeys: [],
500
+ schemaTypeName: schemaType.name,
501
+ languages,
502
+ filteredLanguages,
503
+ value,
504
+ path
505
+ });
506
+ onChange(PatchEvent.from([setIfMissing([], path), ...patches]));
507
+ }, [
508
+ fieldActionProps,
509
+ filteredLanguages,
510
+ languages,
511
+ onChange,
512
+ value
513
+ ]),
514
+ title: createAddAllTitle(value, filteredLanguages),
515
+ disabled,
516
+ hidden
517
+ };
456
518
  }, internationalizedArrayFieldAction = defineDocumentFieldAction({
457
- name: "internationalizedArray",
458
- useAction(fieldActionProps) {
459
- const isInternationalizedArrayField = fieldActionProps?.schemaType?.type?.name.startsWith("internationalizedArray"), {
460
- languages,
461
- filteredLanguages
462
- } = useInternationalizedArrayContext(), translateFieldActions = createTranslateFieldActions(fieldActionProps, {
463
- languages,
464
- filteredLanguages
465
- });
466
- return {
467
- type: "group",
468
- icon: TranslateIcon,
469
- title: "Add Translation",
470
- renderAsButton: !0,
471
- children: isInternationalizedArrayField ? [...translateFieldActions, AddMissingTranslationsFieldAction(fieldActionProps, {
472
- languages,
473
- filteredLanguages
474
- })] : [],
475
- hidden: !isInternationalizedArrayField
476
- };
477
- }
519
+ name: "internationalizedArray",
520
+ useAction(fieldActionProps) {
521
+ let isInternationalizedArrayField = fieldActionProps?.schemaType?.type?.name.startsWith("internationalizedArray"), { languages, filteredLanguages } = useInternationalizedArrayContext(), translateFieldActions = createTranslateFieldActions(fieldActionProps, {
522
+ languages,
523
+ filteredLanguages
524
+ });
525
+ return {
526
+ type: "group",
527
+ icon: TranslateIcon,
528
+ title: "Add Translation",
529
+ renderAsButton: !0,
530
+ children: isInternationalizedArrayField ? [...translateFieldActions, AddMissingTranslationsFieldAction(fieldActionProps, {
531
+ languages,
532
+ filteredLanguages
533
+ })] : [],
534
+ hidden: !isInternationalizedArrayField
535
+ };
536
+ }
478
537
  });
538
+ /**
539
+ * Converts a string to PascalCase (e.g. `"my-field"` -> `"MyField"`).
540
+ */
479
541
  function pascalCase(string) {
480
- return upperFirst(camelCase(string));
542
+ return upperFirst(camelCase(string));
481
543
  }
544
+ /**
545
+ * Generates the schema type name for an internationalized array field.
546
+ *
547
+ * - Without the value suffix: `"internationalizedArray{PascalName}"`
548
+ * (used for the outer array type)
549
+ * - With the value suffix: `"internationalizedArray{PascalName}Value"`
550
+ * (used for the inner object type that wraps each language entry)
551
+ *
552
+ * For example, `createFieldName('block-content', true)` returns
553
+ * `"internationalizedArrayBlockContentValue"`.
554
+ */
482
555
  function createFieldName(name, addValue = !1) {
483
- return addValue ? ["internationalizedArray", pascalCase(name), "Value"].join("") : ["internationalizedArray", pascalCase(name)].join("");
556
+ return addValue ? [
557
+ "internationalizedArray",
558
+ pascalCase(name),
559
+ "Value"
560
+ ].join("") : ["internationalizedArray", pascalCase(name)].join("");
484
561
  }
562
+ /**
563
+ * Default filter function for the internationalized array field.
564
+ * It filter the field base on the `language` value of the object.
565
+ */
485
566
  const internationalizedArrayLanguageFilter = (enclosingType, _member, selectedLanguageIds, parentValue, languages) => {
486
- if (isInternationalizedArrayItemType(enclosingType.name)) {
487
- const language = typeof parentValue?.[LANGUAGE_FIELD_NAME] == "string" ? parentValue?.[LANGUAGE_FIELD_NAME] : typeof parentValue?._key == "string" ? parentValue?._key : null;
488
- return !language || languages.find((l) => l.id === language) ? language ? selectedLanguageIds.includes(language) : !1 : !0;
489
- }
490
- return !0;
491
- }, schemaExample = {
492
- languages: [{
493
- id: "en",
494
- title: "English"
495
- }, {
496
- id: "no",
497
- title: "Norsk"
498
- }]
499
- };
567
+ if (isInternationalizedArrayItemType(enclosingType.name)) {
568
+ let language = typeof parentValue?.language == "string" ? parentValue?.[LANGUAGE_FIELD_NAME] : typeof parentValue?._key == "string" ? parentValue?._key : null;
569
+ return !language || languages.find((l) => l.id === language) ? language ? selectedLanguageIds.includes(language) : !1 : !0;
570
+ }
571
+ return !0;
572
+ }, schemaExample = { languages: [{
573
+ id: "en",
574
+ title: "English"
575
+ }, {
576
+ id: "no",
577
+ title: "Norsk"
578
+ }] };
500
579
  function Feedback() {
501
- const $ = c(4);
502
- let t0;
503
- $[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("code", { children: "internationalizedArray" }), $[0] = t0) : t0 = $[0];
504
- let t1;
505
- $[1] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t1 = /* @__PURE__ */ jsx("code", { children: "id" }), $[1] = t1) : t1 = $[1];
506
- let t2;
507
- $[2] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t2 = /* @__PURE__ */ jsxs(Text, { children: [
508
- "An array of language objects must be passed into the ",
509
- t0,
510
- " ",
511
- "helper function, each with an ",
512
- t1,
513
- " and ",
514
- /* @__PURE__ */ jsx("code", { children: "title" }),
515
- " field. Example:"
516
- ] }), $[2] = t2) : t2 = $[2];
517
- let t3;
518
- 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, { gap: 4, children: [
519
- t2,
520
- /* @__PURE__ */ jsx(Card, { padding: 2, border: !0, radius: 2, children: /* @__PURE__ */ jsx(Code, { size: 1, language: "javascript", children: JSON.stringify(schemaExample, null, 2) }) })
521
- ] }) }), $[3] = t3) : t3 = $[3], t3;
580
+ let $ = c(4), t0;
581
+ $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("code", { children: "internationalizedArray" }), $[0] = t0) : t0 = $[0];
582
+ let t1;
583
+ $[1] === Symbol.for("react.memo_cache_sentinel") ? (t1 = /* @__PURE__ */ jsx("code", { children: "id" }), $[1] = t1) : t1 = $[1];
584
+ let t2;
585
+ $[2] === Symbol.for("react.memo_cache_sentinel") ? (t2 = /* @__PURE__ */ jsxs(Text, { children: [
586
+ "An array of language objects must be passed into the ",
587
+ t0,
588
+ " ",
589
+ "helper function, each with an ",
590
+ t1,
591
+ " and ",
592
+ /* @__PURE__ */ jsx("code", { children: "title" }),
593
+ " field. Example:"
594
+ ] }), $[2] = t2) : t2 = $[2];
595
+ let t3;
596
+ return $[3] === Symbol.for("react.memo_cache_sentinel") ? (t3 = /* @__PURE__ */ jsx(Card, {
597
+ tone: "caution",
598
+ border: !0,
599
+ radius: 2,
600
+ padding: 3,
601
+ children: /* @__PURE__ */ jsxs(Stack, {
602
+ gap: 4,
603
+ children: [t2, /* @__PURE__ */ jsx(Card, {
604
+ padding: 2,
605
+ border: !0,
606
+ radius: 2,
607
+ children: /* @__PURE__ */ jsx(Code, {
608
+ size: 1,
609
+ language: "javascript",
610
+ children: JSON.stringify(schemaExample, null, 2)
611
+ })
612
+ })]
613
+ })
614
+ }), $[3] = t3) : t3 = $[3], t3;
522
615
  }
616
+ /**
617
+ * Migration banner component that displays a warning if the items need to be migrated to the v5 format.
618
+ */
523
619
  function MigrationBanner(t0) {
524
- const $ = c(11), {
525
- itemsNeedingMigration
526
- } = t0;
527
- if (!itemsNeedingMigration.length)
528
- return null;
529
- let t1;
530
- $[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t1 = /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { size: 1, children: /* @__PURE__ */ jsx(WarningOutlineIcon, {}) }) }), $[0] = t1) : t1 = $[0];
531
- let t2;
532
- $[1] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t2 = /* @__PURE__ */ jsx(Text, { size: 1, weight: "semibold", children: "Data migration required" }), $[1] = t2) : t2 = $[1];
533
- const t3 = itemsNeedingMigration.length === 1 ? "" : "s", t4 = itemsNeedingMigration.length === 1 ? "needs" : "need";
534
- let t5;
535
- $[2] !== itemsNeedingMigration.length || $[3] !== t3 || $[4] !== t4 ? (t5 = /* @__PURE__ */ jsxs(Text, { size: 1, muted: !0, children: [
536
- itemsNeedingMigration.length,
537
- " item",
538
- t3,
539
- " ",
540
- t4,
541
- " to be migrated to the v5 format."
542
- ] }), $[2] = itemsNeedingMigration.length, $[3] = t3, $[4] = t4, $[5] = t5) : t5 = $[5];
543
- let t6;
544
- $[6] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t6 = /* @__PURE__ */ jsx("code", { children: "_key" }), $[6] = t6) : t6 = $[6];
545
- let t7;
546
- $[7] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t7 = /* @__PURE__ */ jsx("code", { children: "language" }), $[7] = t7) : t7 = $[7];
547
- let t8;
548
- $[8] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t8 = /* @__PURE__ */ jsx(Box, { marginTop: 2, children: /* @__PURE__ */ jsxs(Text, { size: 1, children: [
549
- "This field still uses the v4 format where language is stored in ",
550
- t6,
551
- ". Migrate to the v5 format where language is stored in ",
552
- t7,
553
- ".",
554
- " ",
555
- /* @__PURE__ */ jsx("a", { rel: "noopener noreferrer", target: "_blank", href: "https://github.com/sanity-io/plugins/blob/main/plugins/sanity-plugin-internationalized-array/README.md#migrate-from-v4-to-v5", children: "Learn more" }),
556
- "."
557
- ] }) }), $[8] = t8) : t8 = $[8];
558
- let t9;
559
- return $[9] !== t5 ? (t9 = /* @__PURE__ */ jsx(Card, { tone: "caution", padding: 3, radius: 2, border: !0, children: /* @__PURE__ */ jsxs(Flex, { gap: 3, align: "center", children: [
560
- t1,
561
- /* @__PURE__ */ jsxs(Stack, { gap: 2, flex: 1, children: [
562
- t2,
563
- t5,
564
- t8
565
- ] })
566
- ] }) }), $[9] = t5, $[10] = t9) : t9 = $[10], t9;
620
+ let $ = c(11), { itemsNeedingMigration } = t0;
621
+ if (!itemsNeedingMigration.length) return null;
622
+ let t1;
623
+ $[0] === Symbol.for("react.memo_cache_sentinel") ? (t1 = /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, {
624
+ size: 1,
625
+ children: /* @__PURE__ */ jsx(WarningOutlineIcon, {})
626
+ }) }), $[0] = t1) : t1 = $[0];
627
+ let t2;
628
+ $[1] === Symbol.for("react.memo_cache_sentinel") ? (t2 = /* @__PURE__ */ jsx(Text, {
629
+ size: 1,
630
+ weight: "semibold",
631
+ children: "Data migration required"
632
+ }), $[1] = t2) : t2 = $[1];
633
+ let t3 = itemsNeedingMigration.length === 1 ? "" : "s", t4 = itemsNeedingMigration.length === 1 ? "needs" : "need", t5;
634
+ $[2] !== itemsNeedingMigration.length || $[3] !== t3 || $[4] !== t4 ? (t5 = /* @__PURE__ */ jsxs(Text, {
635
+ size: 1,
636
+ muted: !0,
637
+ children: [
638
+ itemsNeedingMigration.length,
639
+ " item",
640
+ t3,
641
+ " ",
642
+ t4,
643
+ " to be migrated to the v5 format."
644
+ ]
645
+ }), $[2] = itemsNeedingMigration.length, $[3] = t3, $[4] = t4, $[5] = t5) : t5 = $[5];
646
+ let t6;
647
+ $[6] === Symbol.for("react.memo_cache_sentinel") ? (t6 = /* @__PURE__ */ jsx("code", { children: "_key" }), $[6] = t6) : t6 = $[6];
648
+ let t7;
649
+ $[7] === Symbol.for("react.memo_cache_sentinel") ? (t7 = /* @__PURE__ */ jsx("code", { children: "language" }), $[7] = t7) : t7 = $[7];
650
+ let t8;
651
+ $[8] === Symbol.for("react.memo_cache_sentinel") ? (t8 = /* @__PURE__ */ jsx(Box, {
652
+ marginTop: 2,
653
+ children: /* @__PURE__ */ jsxs(Text, {
654
+ size: 1,
655
+ children: [
656
+ "This field still uses the v4 format where language is stored in ",
657
+ t6,
658
+ ". Migrate to the v5 format where language is stored in ",
659
+ t7,
660
+ ".",
661
+ " ",
662
+ /* @__PURE__ */ jsx("a", {
663
+ rel: "noopener noreferrer",
664
+ target: "_blank",
665
+ href: "https://github.com/sanity-io/plugins/blob/main/plugins/sanity-plugin-internationalized-array/README.md#migrate-from-v4-to-v5",
666
+ children: "Learn more"
667
+ }),
668
+ "."
669
+ ]
670
+ })
671
+ }), $[8] = t8) : t8 = $[8];
672
+ let t9;
673
+ return $[9] === t5 ? t9 = $[10] : (t9 = /* @__PURE__ */ jsx(Card, {
674
+ tone: "caution",
675
+ padding: 3,
676
+ radius: 2,
677
+ border: !0,
678
+ children: /* @__PURE__ */ jsxs(Flex, {
679
+ gap: 3,
680
+ align: "center",
681
+ children: [t1, /* @__PURE__ */ jsxs(Stack, {
682
+ gap: 2,
683
+ flex: 1,
684
+ children: [
685
+ t2,
686
+ t5,
687
+ t8
688
+ ]
689
+ })]
690
+ })
691
+ }), $[9] = t5, $[10] = t9), t9;
567
692
  }
693
+ /**
694
+ * Main array input component for internationalized array fields.
695
+ *
696
+ * Replaces the default Sanity array input and manages the full lifecycle of
697
+ * language entries:
698
+ *
699
+ * - **Language filter integration**: When `@sanity/language-filter` is active
700
+ * for the current document type, array members are filtered to only show
701
+ * languages matching the user's selection.
702
+ * - **Adding languages**: Exposes per-language buttons and an "Add all / Add
703
+ * missing languages" button (controlled by `buttonAddAll` and
704
+ * `buttonLocations` config). Dispatches `setIfMissing` + `insert` patches.
705
+ * - **Default languages**: Automatically adds entries for languages listed in
706
+ * `defaultLanguages` when those entries are missing. Only runs once the
707
+ * document exists in the dataset (it has a `_rev`), so the effect never
708
+ * recreates a just-deleted document or creates a draft before the user's
709
+ * first edit.
710
+ * - **Ordering**: Detects when value items are out of order relative to the
711
+ * master `languages` list and automatically re-sorts them.
712
+ * - **Validation**: Shows a `<Feedback>` component if the languages
713
+ * configuration is invalid (e.g. missing `id` or `title`).
714
+ * - **Empty state**: Displays a "no translations" message when the field has
715
+ * no entries and the add buttons are not visible.
716
+ */
568
717
  function InternationalizedArray(props) {
569
- const $ = c(105), {
570
- members,
571
- value: _value,
572
- schemaType,
573
- onChange,
574
- readOnly: documentReadOnly
575
- } = props, value = _value;
576
- let t0;
577
- $[0] !== value ? (t0 = value?.filter(_temp$1) ?? [], $[0] = value, $[1] = t0) : t0 = $[1];
578
- const itemsNeedingMigration = t0, shouldMigrateArray = itemsNeedingMigration.length > 0, readOnly = !!documentReadOnly || schemaType.readOnly === !0, toast = useToast(), getFormValue = useGetFormValue(), {
579
- languages,
580
- filteredLanguages,
581
- defaultLanguages,
582
- buttonAddAll,
583
- buttonLocations,
584
- languageFilter: builtInLanguageFilter
585
- } = useInternationalizedArrayContext(), {
586
- selectedLanguageIds,
587
- options: languageFilterOptions
588
- } = useLanguageFilterStudioContext();
589
- let t1;
590
- $[2] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t1 = ["_type"], $[2] = t1) : t1 = $[2];
591
- const documentType = useFormValue(t1);
592
- let t2;
593
- $[3] !== documentType || $[4] !== languageFilterOptions ? (t2 = typeof documentType == "string" && languageFilterOptions.documentTypes.includes(documentType), $[3] = documentType, $[4] = languageFilterOptions, $[5] = t2) : t2 = $[5];
594
- const usingLanguageFilterPlugin = t2;
595
- let t3;
596
- $[6] !== builtInLanguageFilter || $[7] !== documentType ? (t3 = typeof documentType == "string" && builtInLanguageFilter.documentTypes.includes(documentType), $[6] = builtInLanguageFilter, $[7] = documentType, $[8] = t3) : t3 = $[8];
597
- const usingBuiltInLanguageFilter = t3;
598
- let t4;
599
- $[9] !== languageFilterOptions || $[10] !== languages || $[11] !== members || $[12] !== selectedLanguageIds || $[13] !== usingBuiltInLanguageFilter || $[14] !== usingLanguageFilterPlugin ? (t4 = usingLanguageFilterPlugin || usingBuiltInLanguageFilter ? members.filter((member) => {
600
- if (member.kind !== "item")
601
- return !1;
602
- const valueMember = member.item.members[0];
603
- return !valueMember || valueMember.kind !== "field" ? !1 : usingBuiltInLanguageFilter ? internationalizedArrayLanguageFilter(member.item.schemaType, valueMember, selectedLanguageIds, member.item.value, languages) : languageFilterOptions.filterField(member.item.schemaType, valueMember, selectedLanguageIds, member.item.value);
604
- }) : members, $[9] = languageFilterOptions, $[10] = languages, $[11] = members, $[12] = selectedLanguageIds, $[13] = usingBuiltInLanguageFilter, $[14] = usingLanguageFilterPlugin, $[15] = t4) : t4 = $[15];
605
- const filteredMembers = t4;
606
- let t5;
607
- $[16] !== filteredLanguages || $[17] !== getFormValue || $[18] !== languages || $[19] !== onChange || $[20] !== props.path || $[21] !== schemaType ? (t5 = (addLanguageKeys) => {
608
- const formValue = getFormValue(props.path);
609
- if (!filteredLanguages?.length)
610
- return;
611
- const patches = createAddLanguagePatches({
612
- addLanguageKeys: Array.isArray(addLanguageKeys) ? addLanguageKeys : [addLanguageKeys],
613
- schemaTypeName: schemaType.name,
614
- languages,
615
- filteredLanguages,
616
- value: formValue
617
- });
618
- onChange([setIfMissing([]), ...patches]);
619
- }, $[16] = filteredLanguages, $[17] = getFormValue, $[18] = languages, $[19] = onChange, $[20] = props.path, $[21] = schemaType, $[22] = t5) : t5 = $[22];
620
- const handleAddLanguages = t5, {
621
- isDeleted,
622
- isDeleting
623
- } = useDocumentPane();
624
- let t6;
625
- $[23] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t6 = ["_rev"], $[23] = t6) : t6 = $[23];
626
- const documentExists = !!useFormValue(t6);
627
- let t7;
628
- $[24] !== value ? (t7 = value?.map(_temp2$1).filter(Boolean).join(","), $[24] = value, $[25] = t7) : t7 = $[25];
629
- const languageKeysFromValue = t7;
630
- let t8;
631
- if ($[26] !== languageKeysFromValue || $[27] !== languages) {
632
- bb0: {
633
- const languageKeys = languageKeysFromValue?.split(",") || [];
634
- if (!languageKeys?.length) {
635
- let t92;
636
- $[29] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t92 = [], $[29] = t92) : t92 = $[29], t8 = t92;
637
- break bb0;
638
- }
639
- if (!languages?.length) {
640
- let t92;
641
- $[30] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t92 = [], $[30] = t92) : t92 = $[30], t8 = t92;
642
- break bb0;
643
- }
644
- t8 = languages.filter((l) => languageKeys?.find((key) => key === l.id)).map(_temp3$1);
645
- }
646
- $[26] = languageKeysFromValue, $[27] = languages, $[28] = t8;
647
- } else
648
- t8 = $[28];
649
- const addedLanguages = t8;
650
- let t10, t9;
651
- $[31] !== addedLanguages || $[32] !== defaultLanguages || $[33] !== documentExists || $[34] !== handleAddLanguages || $[35] !== isDeleted || $[36] !== isDeleting || $[37] !== languages || $[38] !== readOnly || $[39] !== shouldMigrateArray ? (t9 = () => {
652
- const hasAddedDefaultLanguages = defaultLanguages.filter((language) => languages.find((l_1) => l_1.id === language)).every((language_0) => addedLanguages.includes(language_0));
653
- if (documentExists && !isDeleting && !isDeleted && !hasAddedDefaultLanguages && !shouldMigrateArray) {
654
- const languagesToAdd = defaultLanguages.filter((language_1) => !addedLanguages.includes(language_1)).filter((language_2) => languages.find((l_2) => l_2.id === language_2)), timeout = setTimeout(() => {
655
- readOnly || handleAddLanguages(languagesToAdd);
656
- });
657
- return () => clearTimeout(timeout);
658
- }
659
- }, t10 = [documentExists, isDeleted, isDeleting, handleAddLanguages, defaultLanguages, addedLanguages, languages, readOnly, shouldMigrateArray], $[31] = addedLanguages, $[32] = defaultLanguages, $[33] = documentExists, $[34] = handleAddLanguages, $[35] = isDeleted, $[36] = isDeleting, $[37] = languages, $[38] = readOnly, $[39] = shouldMigrateArray, $[40] = t10, $[41] = t9) : (t10 = $[40], t9 = $[41]), useEffect(t9, t10);
660
- let t11;
661
- $[42] !== languages || $[43] !== onChange || $[44] !== toast || $[45] !== value ? (t11 = () => {
662
- if (!value?.length || !languages?.length)
663
- return;
664
- const updatedValue = value.reduce((acc, v_1) => {
665
- const newIndex = languages.findIndex((l_3) => l_3.id === v_1?.[LANGUAGE_FIELD_NAME]);
666
- return newIndex > -1 && (acc[newIndex] = v_1), acc;
667
- }, []).filter(Boolean);
668
- value?.length !== updatedValue.length && toast.push({
669
- title: "There was an error reordering languages",
670
- status: "warning"
671
- }), onChange(set(updatedValue));
672
- }, $[42] = languages, $[43] = onChange, $[44] = toast, $[45] = value, $[46] = t11) : t11 = $[46];
673
- const handleRestoreOrder = t11;
674
- let t12;
675
- bb1: {
676
- if (!value?.length || !languages?.length) {
677
- t12 = !0;
678
- break bb1;
679
- }
680
- let t132;
681
- $[47] !== languages || $[48] !== value ? (t132 = value?.every((v_2) => languages.find((l_4) => l_4?.id === v_2?.[LANGUAGE_FIELD_NAME])), $[47] = languages, $[48] = value, $[49] = t132) : t132 = $[49], t12 = t132;
682
- }
683
- const allKeysAreLanguages = t12;
684
- let t13;
685
- bb2: {
686
- if (!value?.length || !addedLanguages.length) {
687
- let t143;
688
- $[50] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t143 = [], $[50] = t143) : t143 = $[50], t13 = t143;
689
- break bb2;
690
- }
691
- let t142;
692
- if ($[51] !== addedLanguages || $[52] !== value) {
693
- let t152;
694
- $[54] !== addedLanguages ? (t152 = (v_3, vIndex) => vIndex === addedLanguages.findIndex((language_3) => language_3 === v_3[LANGUAGE_FIELD_NAME]) ? null : v_3, $[54] = addedLanguages, $[55] = t152) : t152 = $[55], t142 = value.map(t152).filter(Boolean), $[51] = addedLanguages, $[52] = value, $[53] = t142;
695
- } else
696
- t142 = $[53];
697
- t13 = t142;
698
- }
699
- const languagesOutOfOrder = t13, languagesAreValid = !languages?.length || languages?.length && languages.every(_temp4$1);
700
- let t14;
701
- $[56] !== allKeysAreLanguages || $[57] !== handleRestoreOrder || $[58] !== languagesOutOfOrder.length || $[59] !== readOnly ? (t14 = () => {
702
- languagesOutOfOrder.length > 0 && allKeysAreLanguages && !readOnly && handleRestoreOrder();
703
- }, $[56] = allKeysAreLanguages, $[57] = handleRestoreOrder, $[58] = languagesOutOfOrder.length, $[59] = readOnly, $[60] = t14) : t14 = $[60];
704
- let t15;
705
- $[61] !== allKeysAreLanguages || $[62] !== handleRestoreOrder || $[63] !== languagesOutOfOrder || $[64] !== readOnly ? (t15 = [languagesOutOfOrder, allKeysAreLanguages, handleRestoreOrder, readOnly], $[61] = allKeysAreLanguages, $[62] = handleRestoreOrder, $[63] = languagesOutOfOrder, $[64] = readOnly, $[65] = t15) : t15 = $[65], useEffect(t14, t15);
706
- let t16;
707
- $[66] !== filteredLanguages || $[67] !== value ? (t16 = checkAllLanguagesArePresent(filteredLanguages, value), $[66] = filteredLanguages, $[67] = value, $[68] = t16) : t16 = $[68];
708
- const allLanguagesArePresent = t16;
709
- let t17;
710
- $[69] !== filteredLanguages || $[70] !== handleAddLanguages ? (t17 = () => {
711
- handleAddLanguages(filteredLanguages.map(_temp5));
712
- }, $[69] = filteredLanguages, $[70] = handleAddLanguages, $[71] = t17) : t17 = $[71];
713
- const addAllMissingLanguages = t17;
714
- if (!languagesAreValid) {
715
- let t182;
716
- return $[72] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t182 = /* @__PURE__ */ jsx(Feedback, {}), $[72] = t182) : t182 = $[72], t182;
717
- }
718
- let t18;
719
- $[73] !== allLanguagesArePresent || $[74] !== buttonLocations || $[75] !== filteredLanguages.length || $[76] !== shouldMigrateArray ? (t18 = !shouldMigrateArray && buttonLocations.includes("field") && filteredLanguages?.length > 0 && !allLanguagesArePresent, $[73] = allLanguagesArePresent, $[74] = buttonLocations, $[75] = filteredLanguages.length, $[76] = shouldMigrateArray, $[77] = t18) : t18 = $[77];
720
- const addButtonsAreVisible = t18, fieldHasMembers = members?.length > 0;
721
- let t19;
722
- $[78] !== filteredLanguages || $[79] !== value ? (t19 = createAddAllTitle(value, filteredLanguages), $[78] = filteredLanguages, $[79] = value, $[80] = t19) : t19 = $[80];
723
- const addAllTitle = t19;
724
- let t20;
725
- if ($[81] !== filteredMembers || $[82] !== props) {
726
- let t212;
727
- $[84] !== props ? (t212 = (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), $[84] = props, $[85] = t212) : t212 = $[85], t20 = filteredMembers.map(t212), $[81] = filteredMembers, $[82] = props, $[83] = t20;
728
- } else
729
- t20 = $[83];
730
- let t21;
731
- $[86] !== itemsNeedingMigration ? (t21 = /* @__PURE__ */ jsx(MigrationBanner, { itemsNeedingMigration }), $[86] = itemsNeedingMigration, $[87] = t21) : t21 = $[87];
732
- let t22;
733
- $[88] !== addButtonsAreVisible || $[89] !== fieldHasMembers ? (t22 = !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, $[88] = addButtonsAreVisible, $[89] = fieldHasMembers, $[90] = t22) : t22 = $[90];
734
- let t23;
735
- $[91] !== addAllMissingLanguages || $[92] !== addAllTitle || $[93] !== addButtonsAreVisible || $[94] !== addedLanguages || $[95] !== allLanguagesArePresent || $[96] !== buttonAddAll || $[97] !== handleAddLanguages || $[98] !== readOnly ? (t23 = addButtonsAreVisible ? /* @__PURE__ */ jsxs(Stack, { gap: 2, children: [
736
- /* @__PURE__ */ jsx(AddButtons, { languagesInUse: addedLanguages, readOnly, handleClick: handleAddLanguages }),
737
- buttonAddAll ? /* @__PURE__ */ jsx(Button, { tone: "primary", mode: "ghost", "data-testid": "add-all-languages", disabled: readOnly || allLanguagesArePresent, icon: AddIcon, text: addAllTitle, onClick: addAllMissingLanguages }) : null
738
- ] }) : null, $[91] = addAllMissingLanguages, $[92] = addAllTitle, $[93] = addButtonsAreVisible, $[94] = addedLanguages, $[95] = allLanguagesArePresent, $[96] = buttonAddAll, $[97] = handleAddLanguages, $[98] = readOnly, $[99] = t23) : t23 = $[99];
739
- let t24;
740
- return $[100] !== t20 || $[101] !== t21 || $[102] !== t22 || $[103] !== t23 ? (t24 = /* @__PURE__ */ jsxs(Stack, { gap: 2, children: [
741
- t20,
742
- t21,
743
- t22,
744
- t23
745
- ] }), $[100] = t20, $[101] = t21, $[102] = t22, $[103] = t23, $[104] = t24) : t24 = $[104], t24;
718
+ let $ = c(105), { members, value: _value, schemaType, onChange, readOnly: documentReadOnly } = props, value = _value, t0;
719
+ $[0] === value ? t0 = $[1] : (t0 = value?.filter(_temp$1) ?? [], $[0] = value, $[1] = t0);
720
+ let itemsNeedingMigration = t0, shouldMigrateArray = itemsNeedingMigration.length > 0, readOnly = !!documentReadOnly || schemaType.readOnly === !0, toast = useToast(), getFormValue = useGetFormValue(), { languages, filteredLanguages, defaultLanguages, buttonAddAll, buttonLocations, languageFilter: builtInLanguageFilter } = useInternationalizedArrayContext(), { selectedLanguageIds, options: languageFilterOptions } = useLanguageFilterStudioContext(), t1;
721
+ $[2] === Symbol.for("react.memo_cache_sentinel") ? (t1 = ["_type"], $[2] = t1) : t1 = $[2];
722
+ let documentType = useFormValue(t1), t2;
723
+ $[3] !== documentType || $[4] !== languageFilterOptions ? (t2 = typeof documentType == "string" && languageFilterOptions.documentTypes.includes(documentType), $[3] = documentType, $[4] = languageFilterOptions, $[5] = t2) : t2 = $[5];
724
+ let usingLanguageFilterPlugin = t2, t3;
725
+ $[6] !== builtInLanguageFilter || $[7] !== documentType ? (t3 = typeof documentType == "string" && builtInLanguageFilter.documentTypes.includes(documentType), $[6] = builtInLanguageFilter, $[7] = documentType, $[8] = t3) : t3 = $[8];
726
+ let usingBuiltInLanguageFilter = t3, t4;
727
+ $[9] !== languageFilterOptions || $[10] !== languages || $[11] !== members || $[12] !== selectedLanguageIds || $[13] !== usingBuiltInLanguageFilter || $[14] !== usingLanguageFilterPlugin ? (t4 = usingLanguageFilterPlugin || usingBuiltInLanguageFilter ? members.filter((member) => {
728
+ if (member.kind !== "item") return !1;
729
+ let valueMember = member.item.members[0];
730
+ return !valueMember || valueMember.kind !== "field" ? !1 : usingBuiltInLanguageFilter ? internationalizedArrayLanguageFilter(member.item.schemaType, valueMember, selectedLanguageIds, member.item.value, languages) : languageFilterOptions.filterField(member.item.schemaType, valueMember, selectedLanguageIds, member.item.value);
731
+ }) : members, $[9] = languageFilterOptions, $[10] = languages, $[11] = members, $[12] = selectedLanguageIds, $[13] = usingBuiltInLanguageFilter, $[14] = usingLanguageFilterPlugin, $[15] = t4) : t4 = $[15];
732
+ let filteredMembers = t4, t5;
733
+ $[16] !== filteredLanguages || $[17] !== getFormValue || $[18] !== languages || $[19] !== onChange || $[20] !== props.path || $[21] !== schemaType ? (t5 = (addLanguageKeys) => {
734
+ let formValue = getFormValue(props.path);
735
+ if (!filteredLanguages?.length) return;
736
+ let patches = createAddLanguagePatches({
737
+ addLanguageKeys: Array.isArray(addLanguageKeys) ? addLanguageKeys : [addLanguageKeys],
738
+ schemaTypeName: schemaType.name,
739
+ languages,
740
+ filteredLanguages,
741
+ value: formValue
742
+ });
743
+ onChange([setIfMissing([]), ...patches]);
744
+ }, $[16] = filteredLanguages, $[17] = getFormValue, $[18] = languages, $[19] = onChange, $[20] = props.path, $[21] = schemaType, $[22] = t5) : t5 = $[22];
745
+ let handleAddLanguages = t5, { isDeleted, isDeleting } = useDocumentPane(), t6;
746
+ $[23] === Symbol.for("react.memo_cache_sentinel") ? (t6 = ["_rev"], $[23] = t6) : t6 = $[23];
747
+ let documentExists = !!useFormValue(t6), t7;
748
+ $[24] === value ? t7 = $[25] : (t7 = value?.map(_temp2$1).filter(Boolean).join(","), $[24] = value, $[25] = t7);
749
+ let languageKeysFromValue = t7, t8;
750
+ if ($[26] !== languageKeysFromValue || $[27] !== languages) {
751
+ bb0: {
752
+ let languageKeys = languageKeysFromValue?.split(",") || [];
753
+ if (!languageKeys?.length) {
754
+ let t9;
755
+ $[29] === Symbol.for("react.memo_cache_sentinel") ? (t9 = [], $[29] = t9) : t9 = $[29], t8 = t9;
756
+ break bb0;
757
+ }
758
+ if (!languages?.length) {
759
+ let t9;
760
+ $[30] === Symbol.for("react.memo_cache_sentinel") ? (t9 = [], $[30] = t9) : t9 = $[30], t8 = t9;
761
+ break bb0;
762
+ }
763
+ t8 = languages.filter((l) => languageKeys?.find((key) => key === l.id)).map(_temp3$1);
764
+ }
765
+ $[26] = languageKeysFromValue, $[27] = languages, $[28] = t8;
766
+ } else t8 = $[28];
767
+ let addedLanguages = t8, t10, t9;
768
+ $[31] !== addedLanguages || $[32] !== defaultLanguages || $[33] !== documentExists || $[34] !== handleAddLanguages || $[35] !== isDeleted || $[36] !== isDeleting || $[37] !== languages || $[38] !== readOnly || $[39] !== shouldMigrateArray ? (t9 = () => {
769
+ let hasAddedDefaultLanguages = defaultLanguages.filter((language) => languages.find((l_1) => l_1.id === language)).every((language_0) => addedLanguages.includes(language_0));
770
+ if (documentExists && !isDeleting && !isDeleted && !hasAddedDefaultLanguages && !shouldMigrateArray) {
771
+ let languagesToAdd = defaultLanguages.filter((language_1) => !addedLanguages.includes(language_1)).filter((language_2) => languages.find((l_2) => l_2.id === language_2)), timeout = setTimeout(() => {
772
+ readOnly || handleAddLanguages(languagesToAdd);
773
+ });
774
+ return () => clearTimeout(timeout);
775
+ }
776
+ }, t10 = [
777
+ documentExists,
778
+ isDeleted,
779
+ isDeleting,
780
+ handleAddLanguages,
781
+ defaultLanguages,
782
+ addedLanguages,
783
+ languages,
784
+ readOnly,
785
+ shouldMigrateArray
786
+ ], $[31] = addedLanguages, $[32] = defaultLanguages, $[33] = documentExists, $[34] = handleAddLanguages, $[35] = isDeleted, $[36] = isDeleting, $[37] = languages, $[38] = readOnly, $[39] = shouldMigrateArray, $[40] = t10, $[41] = t9) : (t10 = $[40], t9 = $[41]), useEffect(t9, t10);
787
+ let t11;
788
+ $[42] !== languages || $[43] !== onChange || $[44] !== toast || $[45] !== value ? (t11 = () => {
789
+ if (!value?.length || !languages?.length) return;
790
+ let updatedValue = value.reduce((acc, v_1) => {
791
+ let newIndex = languages.findIndex((l_3) => l_3.id === v_1?.[LANGUAGE_FIELD_NAME]);
792
+ return newIndex > -1 && (acc[newIndex] = v_1), acc;
793
+ }, []).filter(Boolean);
794
+ value?.length !== updatedValue.length && toast.push({
795
+ title: "There was an error reordering languages",
796
+ status: "warning"
797
+ }), onChange(set(updatedValue));
798
+ }, $[42] = languages, $[43] = onChange, $[44] = toast, $[45] = value, $[46] = t11) : t11 = $[46];
799
+ let handleRestoreOrder = t11, t12;
800
+ bb1: {
801
+ if (!value?.length || !languages?.length) {
802
+ t12 = !0;
803
+ break bb1;
804
+ }
805
+ let t13;
806
+ $[47] !== languages || $[48] !== value ? (t13 = value?.every((v_2) => languages.find((l_4) => l_4?.id === v_2?.[LANGUAGE_FIELD_NAME])), $[47] = languages, $[48] = value, $[49] = t13) : t13 = $[49], t12 = t13;
807
+ }
808
+ let allKeysAreLanguages = t12, t13;
809
+ bb2: {
810
+ if (!value?.length || !addedLanguages.length) {
811
+ let t14;
812
+ $[50] === Symbol.for("react.memo_cache_sentinel") ? (t14 = [], $[50] = t14) : t14 = $[50], t13 = t14;
813
+ break bb2;
814
+ }
815
+ let t14;
816
+ if ($[51] !== addedLanguages || $[52] !== value) {
817
+ let t15;
818
+ $[54] === addedLanguages ? t15 = $[55] : (t15 = (v_3, vIndex) => vIndex === addedLanguages.findIndex((language_3) => language_3 === v_3.language) ? null : v_3, $[54] = addedLanguages, $[55] = t15), t14 = value.map(t15).filter(Boolean), $[51] = addedLanguages, $[52] = value, $[53] = t14;
819
+ } else t14 = $[53];
820
+ t13 = t14;
821
+ }
822
+ let languagesOutOfOrder = t13, languagesAreValid = !languages?.length || languages?.length && languages.every(_temp4$1), t14;
823
+ $[56] !== allKeysAreLanguages || $[57] !== handleRestoreOrder || $[58] !== languagesOutOfOrder.length || $[59] !== readOnly ? (t14 = () => {
824
+ languagesOutOfOrder.length > 0 && allKeysAreLanguages && !readOnly && handleRestoreOrder();
825
+ }, $[56] = allKeysAreLanguages, $[57] = handleRestoreOrder, $[58] = languagesOutOfOrder.length, $[59] = readOnly, $[60] = t14) : t14 = $[60];
826
+ let t15;
827
+ $[61] !== allKeysAreLanguages || $[62] !== handleRestoreOrder || $[63] !== languagesOutOfOrder || $[64] !== readOnly ? (t15 = [
828
+ languagesOutOfOrder,
829
+ allKeysAreLanguages,
830
+ handleRestoreOrder,
831
+ readOnly
832
+ ], $[61] = allKeysAreLanguages, $[62] = handleRestoreOrder, $[63] = languagesOutOfOrder, $[64] = readOnly, $[65] = t15) : t15 = $[65], useEffect(t14, t15);
833
+ let t16;
834
+ $[66] !== filteredLanguages || $[67] !== value ? (t16 = checkAllLanguagesArePresent(filteredLanguages, value), $[66] = filteredLanguages, $[67] = value, $[68] = t16) : t16 = $[68];
835
+ let allLanguagesArePresent = t16, t17;
836
+ $[69] !== filteredLanguages || $[70] !== handleAddLanguages ? (t17 = () => {
837
+ handleAddLanguages(filteredLanguages.map(_temp5));
838
+ }, $[69] = filteredLanguages, $[70] = handleAddLanguages, $[71] = t17) : t17 = $[71];
839
+ let addAllMissingLanguages = t17;
840
+ if (!languagesAreValid) {
841
+ let t18;
842
+ return $[72] === Symbol.for("react.memo_cache_sentinel") ? (t18 = /* @__PURE__ */ jsx(Feedback, {}), $[72] = t18) : t18 = $[72], t18;
843
+ }
844
+ let t18;
845
+ $[73] !== allLanguagesArePresent || $[74] !== buttonLocations || $[75] !== filteredLanguages.length || $[76] !== shouldMigrateArray ? (t18 = !shouldMigrateArray && buttonLocations.includes("field") && filteredLanguages?.length > 0 && !allLanguagesArePresent, $[73] = allLanguagesArePresent, $[74] = buttonLocations, $[75] = filteredLanguages.length, $[76] = shouldMigrateArray, $[77] = t18) : t18 = $[77];
846
+ let addButtonsAreVisible = t18, fieldHasMembers = members?.length > 0, t19;
847
+ $[78] !== filteredLanguages || $[79] !== value ? (t19 = createAddAllTitle(value, filteredLanguages), $[78] = filteredLanguages, $[79] = value, $[80] = t19) : t19 = $[80];
848
+ let addAllTitle = t19, t20;
849
+ if ($[81] !== filteredMembers || $[82] !== props) {
850
+ let t21;
851
+ $[84] === props ? t21 = $[85] : (t21 = (member_0) => member_0.kind === "item" ? /* @__PURE__ */ createElement(ArrayOfObjectsItem, {
852
+ ...props,
853
+ key: member_0.key,
854
+ member: member_0
855
+ }) : /* @__PURE__ */ jsx(MemberItemError, { member: member_0 }, member_0.key), $[84] = props, $[85] = t21), t20 = filteredMembers.map(t21), $[81] = filteredMembers, $[82] = props, $[83] = t20;
856
+ } else t20 = $[83];
857
+ let t21;
858
+ $[86] === itemsNeedingMigration ? t21 = $[87] : (t21 = /* @__PURE__ */ jsx(MigrationBanner, { itemsNeedingMigration }), $[86] = itemsNeedingMigration, $[87] = t21);
859
+ let t22;
860
+ $[88] !== addButtonsAreVisible || $[89] !== fieldHasMembers ? (t22 = !addButtonsAreVisible && !fieldHasMembers ? /* @__PURE__ */ jsx(Card, {
861
+ border: !0,
862
+ tone: "transparent",
863
+ padding: 3,
864
+ radius: 2,
865
+ children: /* @__PURE__ */ jsx(Text, {
866
+ size: 1,
867
+ children: "This internationalized field currently has no translations."
868
+ })
869
+ }) : null, $[88] = addButtonsAreVisible, $[89] = fieldHasMembers, $[90] = t22) : t22 = $[90];
870
+ let t23;
871
+ $[91] !== addAllMissingLanguages || $[92] !== addAllTitle || $[93] !== addButtonsAreVisible || $[94] !== addedLanguages || $[95] !== allLanguagesArePresent || $[96] !== buttonAddAll || $[97] !== handleAddLanguages || $[98] !== readOnly ? (t23 = addButtonsAreVisible ? /* @__PURE__ */ jsxs(Stack, {
872
+ gap: 2,
873
+ children: [/* @__PURE__ */ jsx(AddButtons, {
874
+ languagesInUse: addedLanguages,
875
+ readOnly,
876
+ handleClick: handleAddLanguages
877
+ }), buttonAddAll ? /* @__PURE__ */ jsx(Button, {
878
+ tone: "primary",
879
+ mode: "ghost",
880
+ "data-testid": "add-all-languages",
881
+ disabled: readOnly || allLanguagesArePresent,
882
+ icon: AddIcon,
883
+ text: addAllTitle,
884
+ onClick: addAllMissingLanguages
885
+ }) : null]
886
+ }) : null, $[91] = addAllMissingLanguages, $[92] = addAllTitle, $[93] = addButtonsAreVisible, $[94] = addedLanguages, $[95] = allLanguagesArePresent, $[96] = buttonAddAll, $[97] = handleAddLanguages, $[98] = readOnly, $[99] = t23) : t23 = $[99];
887
+ let t24;
888
+ return $[100] !== t20 || $[101] !== t21 || $[102] !== t22 || $[103] !== t23 ? (t24 = /* @__PURE__ */ jsxs(Stack, {
889
+ gap: 2,
890
+ children: [
891
+ t20,
892
+ t21,
893
+ t22,
894
+ t23
895
+ ]
896
+ }), $[100] = t20, $[101] = t21, $[102] = t22, $[103] = t23, $[104] = t24) : t24 = $[104], t24;
746
897
  }
747
898
  function _temp5(language_4) {
748
- return language_4.id;
899
+ return language_4.id;
749
900
  }
750
901
  function _temp4$1(item) {
751
- return item.id && item.title;
902
+ return item.id && item.title;
752
903
  }
753
904
  function _temp3$1(l_0) {
754
- return l_0.id;
905
+ return l_0.id;
755
906
  }
756
907
  function _temp2$1(v_0) {
757
- return v_0[LANGUAGE_FIELD_NAME] ?? v_0._key;
908
+ return v_0.language ?? v_0._key;
758
909
  }
759
910
  function _temp$1(v) {
760
- return !v[LANGUAGE_FIELD_NAME];
911
+ return !v[LANGUAGE_FIELD_NAME];
761
912
  }
762
913
  function getLanguagesFieldOption(schemaType) {
763
- return schemaType ? schemaType.options?.languages || getLanguagesFieldOption(schemaType.type) : void 0;
914
+ return schemaType ? schemaType.options?.languages || getLanguagesFieldOption(schemaType.type) : void 0;
764
915
  }
765
- var array = (config) => {
766
- const {
767
- apiVersion,
768
- select,
769
- languages,
770
- type
771
- } = config, typeName = typeof type == "string" ? type : type.name, arrayName = createFieldName(typeName), objectName = createFieldName(typeName, !0);
772
- return defineField({
773
- name: arrayName,
774
- title: "Internationalized array",
775
- type: "array",
776
- components: {
777
- field: (props) => props.renderDefault({
778
- ...props,
779
- // Reset the level to avoid nested styling
780
- level: 0
781
- }),
782
- input: InternationalizedArray
783
- },
784
- options: {
785
- // @ts-expect-error - these options are required for validation rules – not the custom input component
786
- apiVersion,
787
- select,
788
- languages
789
- },
790
- of: [defineField({
791
- ...typeof type == "string" ? {} : type,
792
- name: objectName,
793
- type: objectName
794
- })],
795
- // @ts-expect-error - fix typings
796
- validation: (rule) => rule.custom(async (value, context) => {
797
- if (!value || value.length === 0)
798
- return !0;
799
- const itemsMissingLanguage = value.filter((item) => item && !item[LANGUAGE_FIELD_NAME] && item._key);
800
- if (itemsMissingLanguage.length > 0)
801
- return {
802
- message: "Language is required for each array item. Run the migration to update your data from the old format.",
803
- paths: itemsMissingLanguage.flatMap((item) => [[{
804
- _key: item._key
805
- }], [{
806
- _key: item._key
807
- }, "value"]])
808
- };
809
- if (value.length === 1 && !value[0]?.[LANGUAGE_FIELD_NAME])
810
- return !0;
811
- const selectedValue = getSelectedValue(select, context.document), client = context.getClient({
812
- apiVersion
813
- });
814
- let contextLanguages = [];
815
- const languagesFieldOption = getLanguagesFieldOption(context?.type);
816
- if (Array.isArray(languagesFieldOption))
817
- contextLanguages = languagesFieldOption;
818
- else if (Array.isArray(peek(selectedValue)))
819
- contextLanguages = peek(selectedValue) || [];
820
- else if (typeof languagesFieldOption == "function") {
821
- const cachedLanguages = getFunctionCache(languagesFieldOption, selectedValue);
822
- if (Array.isArray(cachedLanguages))
823
- contextLanguages = cachedLanguages;
824
- else {
825
- const suspendCachedLanguages = peek(selectedValue);
826
- Array.isArray(suspendCachedLanguages) ? contextLanguages = suspendCachedLanguages : (contextLanguages = await languagesFieldOption(client, selectedValue), setFunctionCache(languagesFieldOption, selectedValue, contextLanguages));
827
- }
828
- }
829
- if (value && value.length > contextLanguages.length)
830
- return `Cannot be more than ${contextLanguages.length === 1 ? "1 item" : `${contextLanguages.length} items`}`;
831
- const languageIds = new Set(contextLanguages.map((lang) => lang.id)), nonLanguageKeys = value.filter((item) => item?.[LANGUAGE_FIELD_NAME] && !languageIds.has(item[LANGUAGE_FIELD_NAME]));
832
- if (nonLanguageKeys.length)
833
- return {
834
- message: "Array item keys must be valid languages registered to the field type",
835
- paths: nonLanguageKeys.map((item) => [{
836
- _key: item._key
837
- }])
838
- };
839
- const seenLanguages = /* @__PURE__ */ new Set(), duplicateValues = [];
840
- for (const item of value)
841
- item?.[LANGUAGE_FIELD_NAME] && (seenLanguages.has(item[LANGUAGE_FIELD_NAME]) ? duplicateValues.push(item) : seenLanguages.add(item[LANGUAGE_FIELD_NAME]));
842
- return duplicateValues.length ? {
843
- message: "There can only be one field per language",
844
- paths: duplicateValues.map((item) => [{
845
- _key: item._key
846
- }])
847
- } : !0;
848
- })
849
- });
916
+ var array_default = (config) => {
917
+ let { apiVersion, select, languages, type } = config, typeName = typeof type == "string" ? type : type.name, arrayName = createFieldName(typeName), objectName = createFieldName(typeName, !0);
918
+ return defineField({
919
+ name: arrayName,
920
+ title: "Internationalized array",
921
+ type: "array",
922
+ components: {
923
+ field: (props) => props.renderDefault({
924
+ ...props,
925
+ level: 0
926
+ }),
927
+ input: InternationalizedArray
928
+ },
929
+ options: {
930
+ apiVersion,
931
+ select,
932
+ languages
933
+ },
934
+ of: [defineField({
935
+ ...typeof type == "string" ? {} : type,
936
+ name: objectName,
937
+ type: objectName
938
+ })],
939
+ validation: (rule) => rule.custom(async (value, context) => {
940
+ if (!value || value.length === 0) return !0;
941
+ let itemsMissingLanguage = value.filter((item) => item && !item.language && item._key);
942
+ if (itemsMissingLanguage.length > 0) return {
943
+ message: "Language is required for each array item. Run the migration to update your data from the old format.",
944
+ paths: itemsMissingLanguage.flatMap((item) => [[{ _key: item._key }], [{ _key: item._key }, "value"]])
945
+ };
946
+ if (value.length === 1 && !value[0]?.language) return !0;
947
+ let selectedValue = getSelectedValue(select, context.document), client = context.getClient({ apiVersion }), contextLanguages = [], languagesFieldOption = getLanguagesFieldOption(context?.type);
948
+ if (Array.isArray(languagesFieldOption)) contextLanguages = languagesFieldOption;
949
+ else if (Array.isArray(peek(selectedValue))) contextLanguages = peek(selectedValue) || [];
950
+ else if (typeof languagesFieldOption == "function") {
951
+ let cachedLanguages = getFunctionCache(languagesFieldOption, selectedValue);
952
+ if (Array.isArray(cachedLanguages)) contextLanguages = cachedLanguages;
953
+ else {
954
+ let suspendCachedLanguages = peek(selectedValue);
955
+ Array.isArray(suspendCachedLanguages) ? contextLanguages = suspendCachedLanguages : (contextLanguages = await languagesFieldOption(client, selectedValue), setFunctionCache(languagesFieldOption, selectedValue, contextLanguages));
956
+ }
957
+ }
958
+ if (value && value.length > contextLanguages.length) return `Cannot be more than ${contextLanguages.length === 1 ? "1 item" : `${contextLanguages.length} items`}`;
959
+ let languageIds = new Set(contextLanguages.map((lang) => lang.id)), nonLanguageKeys = value.filter((item) => item?.language && !languageIds.has(item.language));
960
+ if (nonLanguageKeys.length) return {
961
+ message: "Array item keys must be valid languages registered to the field type",
962
+ paths: nonLanguageKeys.map((item) => [{ _key: item._key }])
963
+ };
964
+ let seenLanguages = /* @__PURE__ */ new Set(), duplicateValues = [];
965
+ for (let item of value) item?.language && (seenLanguages.has(item.language) ? duplicateValues.push(item) : seenLanguages.add(item[LANGUAGE_FIELD_NAME]));
966
+ return duplicateValues.length ? {
967
+ message: "There can only be one field per language",
968
+ paths: duplicateValues.map((item) => [{ _key: item._key }])
969
+ } : !0;
970
+ })
971
+ });
850
972
  };
973
+ /**
974
+ * Maps an array of Sanity form validation entries to a `@sanity/ui` `CardTone`
975
+ * for visual feedback on internationalized array items.
976
+ *
977
+ * - Returns `'critical'` if any validation has `level: 'error'`
978
+ * - Returns `'caution'` if any validation has `level: 'warning'` (and no errors)
979
+ * - Returns `undefined` otherwise (no tone applied)
980
+ *
981
+ * Error level always takes precedence over warning.
982
+ */
851
983
  function getToneFromValidation(validations) {
852
- if (!validations?.length)
853
- return;
854
- const validationLevels = new Set(validations.map((v) => v.level));
855
- if (validationLevels.has("error"))
856
- return "critical";
857
- if (validationLevels.has("warning"))
858
- return "caution";
984
+ if (!validations?.length) return;
985
+ let validationLevels = new Set(validations.map((v) => v.level));
986
+ if (validationLevels.has("error")) return "critical";
987
+ if (validationLevels.has("warning")) return "caution";
859
988
  }
860
989
  function ChangeLanguageButton(props) {
861
- const $ = c(24), {
862
- value,
863
- onChange,
864
- path
865
- } = props;
866
- let t0;
867
- $[0] !== path ? (t0 = path.slice(0, -1), $[0] = path, $[1] = t0) : t0 = $[1];
868
- const parentValue = useFormValue(t0), {
869
- languages
870
- } = useInternationalizedArrayContext();
871
- let t1;
872
- $[2] !== parentValue ? (t1 = parentValue?.map(_temp) ?? [], $[2] = parentValue, $[3] = t1) : t1 = $[3];
873
- const languageKeysInUse = t1;
874
- let t2;
875
- $[4] !== languages || $[5] !== onChange || $[6] !== value ? (t2 = (event) => {
876
- const languageId = event?.currentTarget?.value;
877
- !value || !languages?.length || !languages.find((l) => l.id === languageId) || onChange([set(languageId, [LANGUAGE_FIELD_NAME])]);
878
- }, $[4] = languages, $[5] = onChange, $[6] = value, $[7] = t2) : t2 = $[7];
879
- const handleKeyChange = t2, t3 = `Change "${value[LANGUAGE_FIELD_NAME]}"`;
880
- let t4;
881
- $[8] !== t3 ? (t4 = /* @__PURE__ */ jsx(Button, { fontSize: 1, text: t3 }), $[8] = t3, $[9] = t4) : t4 = $[9];
882
- const t5 = `${value[LANGUAGE_FIELD_NAME]}-change-key`;
883
- let t6;
884
- if ($[10] !== handleKeyChange || $[11] !== languageKeysInUse || $[12] !== languages) {
885
- let t72;
886
- $[14] !== handleKeyChange || $[15] !== languageKeysInUse ? (t72 = (lang) => /* @__PURE__ */ jsx(MenuItem, { disabled: languageKeysInUse.includes(lang.id), fontSize: 1, text: lang.id.toLocaleUpperCase(), value: lang.id, onClick: handleKeyChange }, lang.id), $[14] = handleKeyChange, $[15] = languageKeysInUse, $[16] = t72) : t72 = $[16], t6 = languages.map(t72), $[10] = handleKeyChange, $[11] = languageKeysInUse, $[12] = languages, $[13] = t6;
887
- } else
888
- t6 = $[13];
889
- let t7;
890
- $[17] !== t6 ? (t7 = /* @__PURE__ */ jsx(Menu, { children: t6 }), $[17] = t6, $[18] = t7) : t7 = $[18];
891
- let t8;
892
- $[19] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t8 = {
893
- portal: !0
894
- }, $[19] = t8) : t8 = $[19];
895
- let t9;
896
- return $[20] !== t4 || $[21] !== t5 || $[22] !== t7 ? (t9 = /* @__PURE__ */ jsx(MenuButton, { button: t4, id: t5, menu: t7, popover: t8 }), $[20] = t4, $[21] = t5, $[22] = t7, $[23] = t9) : t9 = $[23], t9;
990
+ let $ = c(24), { value, onChange, path } = props, t0;
991
+ $[0] === path ? t0 = $[1] : (t0 = path.slice(0, -1), $[0] = path, $[1] = t0);
992
+ let parentValue = useFormValue(t0), { languages } = useInternationalizedArrayContext(), t1;
993
+ $[2] === parentValue ? t1 = $[3] : (t1 = parentValue?.map(_temp) ?? [], $[2] = parentValue, $[3] = t1);
994
+ let languageKeysInUse = t1, t2;
995
+ $[4] !== languages || $[5] !== onChange || $[6] !== value ? (t2 = (event) => {
996
+ let languageId = event?.currentTarget?.value;
997
+ !value || !languages?.length || !languages.find((l) => l.id === languageId) || onChange([set(languageId, [LANGUAGE_FIELD_NAME])]);
998
+ }, $[4] = languages, $[5] = onChange, $[6] = value, $[7] = t2) : t2 = $[7];
999
+ let handleKeyChange = t2, t3 = `Change "${value[LANGUAGE_FIELD_NAME]}"`, t4;
1000
+ $[8] === t3 ? t4 = $[9] : (t4 = /* @__PURE__ */ jsx(Button, {
1001
+ fontSize: 1,
1002
+ text: t3
1003
+ }), $[8] = t3, $[9] = t4);
1004
+ let t5 = `${value[LANGUAGE_FIELD_NAME]}-change-key`, t6;
1005
+ if ($[10] !== handleKeyChange || $[11] !== languageKeysInUse || $[12] !== languages) {
1006
+ let t7;
1007
+ $[14] !== handleKeyChange || $[15] !== languageKeysInUse ? (t7 = (lang) => /* @__PURE__ */ jsx(MenuItem, {
1008
+ disabled: languageKeysInUse.includes(lang.id),
1009
+ fontSize: 1,
1010
+ text: lang.id.toLocaleUpperCase(),
1011
+ value: lang.id,
1012
+ onClick: handleKeyChange
1013
+ }, lang.id), $[14] = handleKeyChange, $[15] = languageKeysInUse, $[16] = t7) : t7 = $[16], t6 = languages.map(t7), $[10] = handleKeyChange, $[11] = languageKeysInUse, $[12] = languages, $[13] = t6;
1014
+ } else t6 = $[13];
1015
+ let t7;
1016
+ $[17] === t6 ? t7 = $[18] : (t7 = /* @__PURE__ */ jsx(Menu, { children: t6 }), $[17] = t6, $[18] = t7);
1017
+ let t8;
1018
+ $[19] === Symbol.for("react.memo_cache_sentinel") ? (t8 = { portal: !0 }, $[19] = t8) : t8 = $[19];
1019
+ let t9;
1020
+ return $[20] !== t4 || $[21] !== t5 || $[22] !== t7 ? (t9 = /* @__PURE__ */ jsx(MenuButton, {
1021
+ button: t4,
1022
+ id: t5,
1023
+ menu: t7,
1024
+ popover: t8
1025
+ }), $[20] = t4, $[21] = t5, $[22] = t7, $[23] = t9) : t9 = $[23], t9;
897
1026
  }
898
1027
  function _temp(v) {
899
- return v[LANGUAGE_FIELD_NAME];
1028
+ return v[LANGUAGE_FIELD_NAME];
900
1029
  }
901
1030
  function RemoveButton(t0) {
902
- const $ = c(11), {
903
- isDefault,
904
- readOnly,
905
- onChange
906
- } = t0;
907
- let t1;
908
- $[0] !== onChange ? (t1 = () => {
909
- onChange(unset());
910
- }, $[0] = onChange, $[1] = t1) : t1 = $[1];
911
- const handleUnset = t1, t2 = !isDefault;
912
- let t3, t4;
913
- $[2] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t3 = /* @__PURE__ */ jsx(Text, { muted: !0, size: 1, children: "Can't remove default language" }), t4 = ["right", "left"], $[2] = t3, $[3] = t4) : (t3 = $[2], t4 = $[3]);
914
- let t5;
915
- $[4] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t5 = {
916
- paddingBottom: "2px"
917
- }, $[4] = t5) : t5 = $[4];
918
- const t6 = readOnly || isDefault;
919
- let t7;
920
- $[5] !== handleUnset || $[6] !== t6 ? (t7 = /* @__PURE__ */ jsx("span", { style: t5, children: /* @__PURE__ */ jsx(Button, { mode: "bleed", icon: RemoveCircleIcon, tone: "critical", disabled: t6, onClick: handleUnset }) }), $[5] = handleUnset, $[6] = t6, $[7] = t7) : t7 = $[7];
921
- let t8;
922
- return $[8] !== t2 || $[9] !== t7 ? (t8 = /* @__PURE__ */ jsx(Tooltip, { animate: !0, disabled: t2, content: t3, fallbackPlacements: t4, placement: "top", portal: !0, children: t7 }), $[8] = t2, $[9] = t7, $[10] = t8) : t8 = $[10], t8;
1031
+ let $ = c(11), { isDefault, readOnly, onChange } = t0, t1;
1032
+ $[0] === onChange ? t1 = $[1] : (t1 = () => {
1033
+ onChange(unset());
1034
+ }, $[0] = onChange, $[1] = t1);
1035
+ let handleUnset = t1, t2 = !isDefault, t3, t4;
1036
+ $[2] === Symbol.for("react.memo_cache_sentinel") ? (t3 = /* @__PURE__ */ jsx(Text, {
1037
+ muted: !0,
1038
+ size: 1,
1039
+ children: "Can't remove default language"
1040
+ }), t4 = ["right", "left"], $[2] = t3, $[3] = t4) : (t3 = $[2], t4 = $[3]);
1041
+ let t5;
1042
+ $[4] === Symbol.for("react.memo_cache_sentinel") ? (t5 = { paddingBottom: "2px" }, $[4] = t5) : t5 = $[4];
1043
+ let t6 = readOnly || isDefault, t7;
1044
+ $[5] !== handleUnset || $[6] !== t6 ? (t7 = /* @__PURE__ */ jsx("span", {
1045
+ style: t5,
1046
+ children: /* @__PURE__ */ jsx(Button, {
1047
+ mode: "bleed",
1048
+ icon: RemoveCircleIcon,
1049
+ tone: "critical",
1050
+ disabled: t6,
1051
+ onClick: handleUnset
1052
+ })
1053
+ }), $[5] = handleUnset, $[6] = t6, $[7] = t7) : t7 = $[7];
1054
+ let t8;
1055
+ return $[8] !== t2 || $[9] !== t7 ? (t8 = /* @__PURE__ */ jsx(Tooltip, {
1056
+ animate: !0,
1057
+ disabled: t2,
1058
+ content: t3,
1059
+ fallbackPlacements: t4,
1060
+ placement: "top",
1061
+ portal: !0,
1062
+ children: t7
1063
+ }), $[8] = t2, $[9] = t7, $[10] = t8) : t8 = $[10], t8;
923
1064
  }
1065
+ /**
1066
+ * Renders a single row of an internationalized array: a language label (or
1067
+ * "Change" menu for invalid keys), the value input, and a remove button.
1068
+ *
1069
+ * Key behaviours:
1070
+ * - Wraps `onChange` to intercept paste operations into empty Portable Text
1071
+ * fields, ensuring `setIfMissing` and correct path prefixing.
1072
+ * - Detects items needing migration (missing `LANGUAGE_FIELD_NAME`) and hides
1073
+ * the language label in that state.
1074
+ * - Shows a `MenuButton` with available languages when the current key is
1075
+ * not a valid language.
1076
+ * - Disables the remove button for languages listed in `defaultLanguages`.
1077
+ * - Shows a `Spinner` when languages have not been loaded yet.
1078
+ * - Applies a `CardTone` based on validation state via `getToneFromValidation`.
1079
+ */
924
1080
  function InternationalizedInput(props) {
925
- const $ = c(50), originalOnChange = props.inputProps.onChange;
926
- let t0;
927
- $[0] !== originalOnChange || $[1] !== props.value?.value ? (t0 = (patches) => {
928
- if (!Array.isArray(patches))
929
- return originalOnChange(patches);
930
- const valueField = props.value?.value;
931
- if ((valueField == null || Array.isArray(valueField) && valueField.length === 0) && patches.some(_temp2)) {
932
- const initPatch = valueField === void 0 ? {
933
- type: "setIfMissing",
934
- path: ["value"],
935
- value: []
936
- } : null, fixedPatches = patches.map(_temp3), allPatches = initPatch ? [initPatch, ...fixedPatches] : fixedPatches;
937
- return originalOnChange(allPatches);
938
- }
939
- return originalOnChange(patches);
940
- }, $[0] = originalOnChange, $[1] = props.value?.value, $[2] = t0) : t0 = $[2], props.value?.value;
941
- const wrappedOnChange = t0, {
942
- languages,
943
- languageDisplay,
944
- defaultLanguages
945
- } = useInternationalizedArrayContext();
946
- let t1;
947
- $[3] !== languages || $[4] !== props.value ? (t1 = languages?.length ? !!languages.find((l) => l.id === props.value[LANGUAGE_FIELD_NAME]) : !1, $[3] = languages, $[4] = props.value, $[5] = t1) : t1 = $[5];
948
- const keyIsValid = t1;
949
- let t2;
950
- if ($[6] !== keyIsValid || $[7] !== languageDisplay || $[8] !== languages || $[9] !== props.value) {
951
- const language = languages?.find((l_0) => l_0.id === props.value[LANGUAGE_FIELD_NAME]);
952
- t2 = keyIsValid && language ? getLanguageDisplay(languageDisplay, language.title, language.id) : "", $[6] = keyIsValid, $[7] = languageDisplay, $[8] = languages, $[9] = props.value, $[10] = t2;
953
- } else
954
- t2 = $[10];
955
- const languageTitle = t2, t3 = props.inputProps;
956
- let t4;
957
- if ($[11] !== keyIsValid || $[12] !== languageTitle || $[13] !== originalOnChange || $[14] !== props.inputProps.members || $[15] !== props.path || $[16] !== props.value) {
958
- let t52;
959
- $[18] !== keyIsValid || $[19] !== languageTitle || $[20] !== originalOnChange || $[21] !== props.path || $[22] !== props.value ? (t52 = (member) => {
960
- if (member.kind !== "field")
961
- return member;
962
- const field = member.field, schemaType = field?.schemaType, title = props.value[LANGUAGE_FIELD_NAME] ? keyIsValid ? /* @__PURE__ */ jsx(Label, { muted: !0, size: 1, children: languageTitle }) : /* @__PURE__ */ jsx(ChangeLanguageButton, { value: props.value, path: props.path, onChange: originalOnChange }) : null;
963
- return Object.assign({}, member, {
964
- field: Object.assign({}, field, {
965
- schemaType: Object.assign({}, schemaType, {
966
- title
967
- })
968
- })
969
- });
970
- }, $[18] = keyIsValid, $[19] = languageTitle, $[20] = originalOnChange, $[21] = props.path, $[22] = props.value, $[23] = t52) : t52 = $[23], t4 = props.inputProps.members.filter(_temp4).map(t52), $[11] = keyIsValid, $[12] = languageTitle, $[13] = originalOnChange, $[14] = props.inputProps.members, $[15] = props.path, $[16] = props.value, $[17] = t4;
971
- } else
972
- t4 = $[17];
973
- let t5;
974
- $[24] !== props.inputProps || $[25] !== props.value || $[26] !== t4 || $[27] !== wrappedOnChange ? (t5 = {
975
- ...t3,
976
- members: t4,
977
- value: props.value,
978
- onChange: wrappedOnChange
979
- }, $[24] = props.inputProps, $[25] = props.value, $[26] = t4, $[27] = wrappedOnChange, $[28] = t5) : t5 = $[28];
980
- const inlineProps = t5, {
981
- validation,
982
- value,
983
- readOnly
984
- } = inlineProps;
985
- if (!languages) {
986
- let t62;
987
- return $[29] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t62 = /* @__PURE__ */ jsx(Spinner, {}), $[29] = t62) : t62 = $[29], t62;
988
- }
989
- let t6;
990
- $[30] !== defaultLanguages || $[31] !== value ? (t6 = defaultLanguages.includes(value[LANGUAGE_FIELD_NAME]), $[30] = defaultLanguages, $[31] = value, $[32] = t6) : t6 = $[32];
991
- const isDefault = t6;
992
- let t7;
993
- $[33] !== validation ? (t7 = getToneFromValidation(validation), $[33] = validation, $[34] = t7) : t7 = $[34];
994
- let t8;
995
- $[35] !== inlineProps || $[36] !== props.inputProps ? (t8 = props.inputProps.renderInput(inlineProps), $[35] = inlineProps, $[36] = props.inputProps, $[37] = t8) : t8 = $[37];
996
- let t9;
997
- $[38] !== t8 ? (t9 = /* @__PURE__ */ jsx(Box, { flex: 1, children: t8 }), $[38] = t8, $[39] = t9) : t9 = $[39];
998
- const t10 = !!readOnly;
999
- let t11;
1000
- $[40] !== isDefault || $[41] !== originalOnChange || $[42] !== t10 ? (t11 = /* @__PURE__ */ jsx(RemoveButton, { isDefault, readOnly: t10, onChange: originalOnChange }), $[40] = isDefault, $[41] = originalOnChange, $[42] = t10, $[43] = t11) : t11 = $[43];
1001
- let t12;
1002
- $[44] !== t11 || $[45] !== t9 ? (t12 = /* @__PURE__ */ jsxs(Flex, { align: "flex-end", gap: 2, children: [
1003
- t9,
1004
- t11
1005
- ] }), $[44] = t11, $[45] = t9, $[46] = t12) : t12 = $[46];
1006
- let t13;
1007
- return $[47] !== t12 || $[48] !== t7 ? (t13 = /* @__PURE__ */ jsx(Card, { paddingTop: 2, tone: t7, children: t12 }), $[47] = t12, $[48] = t7, $[49] = t13) : t13 = $[49], t13;
1081
+ let $ = c(50), originalOnChange = props.inputProps.onChange, t0;
1082
+ $[0] !== originalOnChange || $[1] !== props.value?.value ? (t0 = (patches) => {
1083
+ if (!Array.isArray(patches)) return originalOnChange(patches);
1084
+ let valueField = props.value?.value;
1085
+ if ((valueField == null || Array.isArray(valueField) && valueField.length === 0) && patches.some(_temp2)) {
1086
+ let initPatch = valueField === void 0 ? {
1087
+ type: "setIfMissing",
1088
+ path: ["value"],
1089
+ value: []
1090
+ } : null, fixedPatches = patches.map(_temp3);
1091
+ return originalOnChange(initPatch ? [initPatch, ...fixedPatches] : fixedPatches);
1092
+ }
1093
+ return originalOnChange(patches);
1094
+ }, $[0] = originalOnChange, $[1] = props.value?.value, $[2] = t0) : t0 = $[2], props.value?.value;
1095
+ let wrappedOnChange = t0, { languages, languageDisplay, defaultLanguages } = useInternationalizedArrayContext(), t1;
1096
+ $[3] !== languages || $[4] !== props.value ? (t1 = languages?.length ? !!languages.find((l) => l.id === props.value[LANGUAGE_FIELD_NAME]) : !1, $[3] = languages, $[4] = props.value, $[5] = t1) : t1 = $[5];
1097
+ let keyIsValid = t1, t2;
1098
+ if ($[6] !== keyIsValid || $[7] !== languageDisplay || $[8] !== languages || $[9] !== props.value) {
1099
+ let language = languages?.find((l_0) => l_0.id === props.value[LANGUAGE_FIELD_NAME]);
1100
+ t2 = keyIsValid && language ? getLanguageDisplay(languageDisplay, language.title, language.id) : "", $[6] = keyIsValid, $[7] = languageDisplay, $[8] = languages, $[9] = props.value, $[10] = t2;
1101
+ } else t2 = $[10];
1102
+ let languageTitle = t2, t3 = props.inputProps, t4;
1103
+ if ($[11] !== keyIsValid || $[12] !== languageTitle || $[13] !== originalOnChange || $[14] !== props.inputProps.members || $[15] !== props.path || $[16] !== props.value) {
1104
+ let t5;
1105
+ $[18] !== keyIsValid || $[19] !== languageTitle || $[20] !== originalOnChange || $[21] !== props.path || $[22] !== props.value ? (t5 = (member) => {
1106
+ if (member.kind !== "field") return member;
1107
+ let field = member.field, schemaType = field?.schemaType, title = props.value.language ? keyIsValid ? /* @__PURE__ */ jsx(Label, {
1108
+ muted: !0,
1109
+ size: 1,
1110
+ children: languageTitle
1111
+ }) : /* @__PURE__ */ jsx(ChangeLanguageButton, {
1112
+ value: props.value,
1113
+ path: props.path,
1114
+ onChange: originalOnChange
1115
+ }) : null;
1116
+ return Object.assign({}, member, { field: Object.assign({}, field, { schemaType: Object.assign({}, schemaType, { title }) }) });
1117
+ }, $[18] = keyIsValid, $[19] = languageTitle, $[20] = originalOnChange, $[21] = props.path, $[22] = props.value, $[23] = t5) : t5 = $[23], t4 = props.inputProps.members.filter(_temp4).map(t5), $[11] = keyIsValid, $[12] = languageTitle, $[13] = originalOnChange, $[14] = props.inputProps.members, $[15] = props.path, $[16] = props.value, $[17] = t4;
1118
+ } else t4 = $[17];
1119
+ let t5;
1120
+ $[24] !== props.inputProps || $[25] !== props.value || $[26] !== t4 || $[27] !== wrappedOnChange ? (t5 = {
1121
+ ...t3,
1122
+ members: t4,
1123
+ value: props.value,
1124
+ onChange: wrappedOnChange
1125
+ }, $[24] = props.inputProps, $[25] = props.value, $[26] = t4, $[27] = wrappedOnChange, $[28] = t5) : t5 = $[28];
1126
+ let inlineProps = t5, { validation, value, readOnly } = inlineProps;
1127
+ if (!languages) {
1128
+ let t6;
1129
+ return $[29] === Symbol.for("react.memo_cache_sentinel") ? (t6 = /* @__PURE__ */ jsx(Spinner, {}), $[29] = t6) : t6 = $[29], t6;
1130
+ }
1131
+ let t6;
1132
+ $[30] !== defaultLanguages || $[31] !== value ? (t6 = defaultLanguages.includes(value[LANGUAGE_FIELD_NAME]), $[30] = defaultLanguages, $[31] = value, $[32] = t6) : t6 = $[32];
1133
+ let isDefault = t6, t7;
1134
+ $[33] === validation ? t7 = $[34] : (t7 = getToneFromValidation(validation), $[33] = validation, $[34] = t7);
1135
+ let t8;
1136
+ $[35] !== inlineProps || $[36] !== props.inputProps ? (t8 = props.inputProps.renderInput(inlineProps), $[35] = inlineProps, $[36] = props.inputProps, $[37] = t8) : t8 = $[37];
1137
+ let t9;
1138
+ $[38] === t8 ? t9 = $[39] : (t9 = /* @__PURE__ */ jsx(Box, {
1139
+ flex: 1,
1140
+ children: t8
1141
+ }), $[38] = t8, $[39] = t9);
1142
+ let t10 = !!readOnly, t11;
1143
+ $[40] !== isDefault || $[41] !== originalOnChange || $[42] !== t10 ? (t11 = /* @__PURE__ */ jsx(RemoveButton, {
1144
+ isDefault,
1145
+ readOnly: t10,
1146
+ onChange: originalOnChange
1147
+ }), $[40] = isDefault, $[41] = originalOnChange, $[42] = t10, $[43] = t11) : t11 = $[43];
1148
+ let t12;
1149
+ $[44] !== t11 || $[45] !== t9 ? (t12 = /* @__PURE__ */ jsxs(Flex, {
1150
+ align: "flex-end",
1151
+ gap: 2,
1152
+ children: [t9, t11]
1153
+ }), $[44] = t11, $[45] = t9, $[46] = t12) : t12 = $[46];
1154
+ let t13;
1155
+ return $[47] !== t12 || $[48] !== t7 ? (t13 = /* @__PURE__ */ jsx(Card, {
1156
+ paddingTop: 2,
1157
+ tone: t7,
1158
+ children: t12
1159
+ }), $[47] = t12, $[48] = t7, $[49] = t13) : t13 = $[49], t13;
1008
1160
  }
1009
1161
  function _temp4(m) {
1010
- return m.kind === "field" && m.name === "value";
1162
+ return m.kind === "field" && m.name === "value";
1011
1163
  }
1012
1164
  function _temp3(patch_0) {
1013
- if (!patch_0 || typeof patch_0 != "object")
1014
- return patch_0;
1015
- if (patch_0.type === "insert" && patch_0.path && Array.isArray(patch_0.path)) {
1016
- const fixedPath = patch_0.path[0] === "value" ? patch_0.path : ["value", ...patch_0.path];
1017
- return {
1018
- ...patch_0,
1019
- path: fixedPath
1020
- };
1021
- }
1022
- return patch_0;
1165
+ if (!patch_0 || typeof patch_0 != "object") return patch_0;
1166
+ if (patch_0.type === "insert" && patch_0.path && Array.isArray(patch_0.path)) {
1167
+ let fixedPath = patch_0.path[0] === "value" ? patch_0.path : ["value", ...patch_0.path];
1168
+ return {
1169
+ ...patch_0,
1170
+ path: fixedPath
1171
+ };
1172
+ }
1173
+ return patch_0;
1023
1174
  }
1024
1175
  function _temp2(patch) {
1025
- 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;
1176
+ 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;
1026
1177
  }
1027
- var object = (config) => {
1028
- const {
1029
- type
1030
- } = config, typeName = typeof type == "string" ? type : type.name, objectName = createFieldName(typeName, !0);
1031
- return defineField({
1032
- name: objectName,
1033
- title: `Internationalized array ${typeName}`,
1034
- type: "object",
1035
- components: {
1036
- // @ts-expect-error - fix typings
1037
- item: InternationalizedInput,
1038
- field: (props) => props.renderDefault({
1039
- ...props,
1040
- // Reset the level to avoid nested styling
1041
- level: 0
1042
- })
1043
- },
1044
- fields: [
1045
- defineField({
1046
- ...typeof type == "string" ? {
1047
- type
1048
- } : type,
1049
- name: "value"
1050
- }),
1051
- // Hidden language field - stores the language identifier (e.g., 'en', 'fr')
1052
- // This replaces the previous pattern of storing language in _key
1053
- defineField({
1054
- name: "language",
1055
- type: "string",
1056
- hidden: !0,
1057
- validation: (Rule) => Rule.required()
1058
- })
1059
- ],
1060
- preview: {
1061
- select: {
1062
- title: "value",
1063
- subtitle: LANGUAGE_FIELD_NAME
1064
- }
1065
- }
1066
- });
1178
+ var object_default = (config) => {
1179
+ let { type } = config, typeName = typeof type == "string" ? type : type.name;
1180
+ return defineField({
1181
+ name: createFieldName(typeName, !0),
1182
+ title: `Internationalized array ${typeName}`,
1183
+ type: "object",
1184
+ components: {
1185
+ item: InternationalizedInput,
1186
+ field: (props) => props.renderDefault({
1187
+ ...props,
1188
+ level: 0
1189
+ })
1190
+ },
1191
+ fields: [defineField({
1192
+ ...typeof type == "string" ? { type } : type,
1193
+ name: "value"
1194
+ }), defineField({
1195
+ name: "language",
1196
+ type: "string",
1197
+ hidden: !0,
1198
+ validation: (Rule) => Rule.required()
1199
+ })],
1200
+ preview: { select: {
1201
+ title: "value",
1202
+ subtitle: LANGUAGE_FIELD_NAME
1203
+ } }
1204
+ });
1067
1205
  };
1068
1206
  const internationalizedArray = definePlugin((config) => {
1069
- const pluginConfig = {
1070
- ...CONFIG_DEFAULT,
1071
- ...config
1072
- }, {
1073
- // oxlint-disable-next-line no-useless-default-assignment
1074
- apiVersion = "2025-10-15",
1075
- select,
1076
- languages,
1077
- fieldTypes,
1078
- defaultLanguages,
1079
- buttonLocations,
1080
- languageFilter: languageFilterConfig
1081
- } = pluginConfig;
1082
- return {
1083
- name: "sanity-plugin-internationalized-array",
1084
- // Preload languages for use throughout the Studio
1085
- studio: Array.isArray(languages) ? void 0 : {
1086
- components: {
1087
- layout: (props) => /* @__PURE__ */ jsxs(Fragment, { children: [
1088
- /* @__PURE__ */ jsx(Preload, { apiVersion, languages }),
1089
- props.renderDefault(props)
1090
- ] })
1091
- }
1092
- },
1093
- // Optional: render "add language" buttons as field actions
1094
- document: {
1095
- components: {
1096
- unstable_layout: (props) => /* @__PURE__ */ jsx(InternationalizedArrayLayout, { ...props, pluginConfig })
1097
- },
1098
- unstable_fieldActions: buttonLocations.includes("unstable__fieldAction") ? (prev) => [...prev, internationalizedArrayFieldAction] : void 0
1099
- },
1100
- // Wrap document editor with a language provider
1101
- form: {
1102
- components: {
1103
- input: (props) => props.id === "root" && isObjectInputProps(props) && hasInternationalizedArrayField(props.schemaType) && pluginConfig.includeForDocumentType(props.schemaType.name) ? /* @__PURE__ */ jsx(InternationalizedArrayFormInput, { ...props, pluginConfig }) : props.renderDefault(props)
1104
- }
1105
- },
1106
- // Register custom schema types for the outer array and the inner object
1107
- schema: {
1108
- types: [...fieldTypes.map((type) => array({
1109
- type,
1110
- apiVersion,
1111
- select,
1112
- languages
1113
- })), ...fieldTypes.map((type) => object({
1114
- type
1115
- }))]
1116
- },
1117
- plugins: languageFilterConfig?.documentTypes?.length > 0 ? [languageFilter({
1118
- documentTypes: languageFilterConfig.documentTypes,
1119
- supportedLanguages: languages,
1120
- defaultLanguages: languageFilterConfig.defaultLanguages
1121
- // This is specifically not adding filterField avoid the default filter field implementation.
1122
- // It will be filtered in `internationalizedArray` component and will have access to the resolved languages.
1123
- // Rendering the fields if the language key is incorrect, providing an improved UX
1124
- })] : void 0
1125
- };
1207
+ let pluginConfig = {
1208
+ ...CONFIG_DEFAULT,
1209
+ ...config
1210
+ }, { apiVersion = "2025-10-15", select, languages, fieldTypes, defaultLanguages, buttonLocations, languageFilter: languageFilterConfig } = pluginConfig;
1211
+ return {
1212
+ name: "sanity-plugin-internationalized-array",
1213
+ studio: Array.isArray(languages) ? void 0 : { components: { layout: (props) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Preload, {
1214
+ apiVersion,
1215
+ languages
1216
+ }), props.renderDefault(props)] }) } },
1217
+ document: {
1218
+ components: { unstable_layout: (props) => /* @__PURE__ */ jsx(InternationalizedArrayLayout, {
1219
+ ...props,
1220
+ pluginConfig
1221
+ }) },
1222
+ unstable_fieldActions: buttonLocations.includes("unstable__fieldAction") ? (prev) => [...prev, internationalizedArrayFieldAction] : void 0
1223
+ },
1224
+ form: { components: { input: (props) => props.id === "root" && isObjectInputProps(props) && hasInternationalizedArrayField(props.schemaType) && pluginConfig.includeForDocumentType(props.schemaType.name) ? /* @__PURE__ */ jsx(InternationalizedArrayFormInput, {
1225
+ ...props,
1226
+ pluginConfig
1227
+ }) : props.renderDefault(props) } },
1228
+ schema: { types: [...fieldTypes.map((type) => array_default({
1229
+ type,
1230
+ apiVersion,
1231
+ select,
1232
+ languages,
1233
+ defaultLanguages
1234
+ })), ...fieldTypes.map((type) => object_default({ type }))] },
1235
+ plugins: languageFilterConfig?.documentTypes?.length > 0 ? [languageFilter({
1236
+ documentTypes: languageFilterConfig.documentTypes,
1237
+ supportedLanguages: languages,
1238
+ defaultLanguages: languageFilterConfig.defaultLanguages
1239
+ })] : void 0
1240
+ };
1126
1241
  });
1127
- export {
1128
- LANGUAGE_FIELD_NAME,
1129
- clear,
1130
- internationalizedArray,
1131
- internationalizedArrayLanguageFilter,
1132
- isInternationalizedArrayItemType
1133
- };
1134
- //# sourceMappingURL=index.js.map
1242
+ export { LANGUAGE_FIELD_NAME, clear, internationalizedArray, internationalizedArrayLanguageFilter, isInternationalizedArrayItemType };
1243
+
1244
+ //# sourceMappingURL=index.js.map