sanity-plugin-internationalized-array 0.0.7 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +82 -32
  3. package/lib/cjs/index.js +487 -0
  4. package/lib/cjs/index.js.map +1 -0
  5. package/lib/esm/index.js +480 -0
  6. package/lib/esm/index.js.map +1 -0
  7. package/lib/types/index.d.ts +12 -0
  8. package/lib/types/index.d.ts.map +1 -0
  9. package/package.json +50 -36
  10. package/sanity.json +7 -6
  11. package/src/components/Feedback.tsx +27 -0
  12. package/src/components/InternationalizedArrayInput.tsx +222 -0
  13. package/src/{LanguageArray → components}/Table.tsx +0 -0
  14. package/src/components/createFieldName.ts +20 -0
  15. package/src/components/getToneFromValidation.ts +18 -0
  16. package/src/index.ts +1 -3
  17. package/src/plugin.tsx +23 -0
  18. package/src/schema/array.ts +69 -0
  19. package/src/schema/object.ts +29 -0
  20. package/src/types.ts +19 -9
  21. package/v2-incompatible.js +11 -0
  22. package/lib/LanguageArray/Table.js +0 -88
  23. package/lib/LanguageArray/Table.js.map +0 -1
  24. package/lib/LanguageArray/ValueInput.js +0 -17
  25. package/lib/LanguageArray/ValueInput.js.map +0 -1
  26. package/lib/LanguageArray/index.js +0 -253
  27. package/lib/LanguageArray/index.js.map +0 -1
  28. package/lib/hooks/useUnsetInputComponent.js +0 -32
  29. package/lib/hooks/useUnsetInputComponent.js.map +0 -1
  30. package/lib/index.js +0 -13
  31. package/lib/index.js.map +0 -1
  32. package/lib/internationalizedArray.js +0 -105
  33. package/lib/internationalizedArray.js.map +0 -1
  34. package/lib/types.js +0 -2
  35. package/lib/types.js.map +0 -1
  36. package/migrations/transformObjectToArray.js +0 -94
  37. package/src/LanguageArray/ValueInput.tsx +0 -6
  38. package/src/LanguageArray/index.tsx +0 -311
  39. package/src/hooks/useUnsetInputComponent.tsx +0 -17
  40. package/src/internationalizedArray.ts +0 -84
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2021 Simeon Griggs
3
+ Copyright (c) 2022 Simeon Griggs
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,48 +1,98 @@
1
1
  # sanity-plugin-internationalized-array
2
2
 
3
- A helper function that renders a custom input component for writing localised fields of content into an array.
3
+ > NOTE This is for the Studio v3 version of the plugin
4
4
 
5
- **This an early proof-of-concept and should not yet be used without thorough testing.**
5
+ A helper function that renders a custom input component for writing localized fields of content into an array.
6
6
 
7
- ![2022-07-13 12 53 29](https://user-images.githubusercontent.com/9684022/178729823-cbb1059f-4ae0-4ab0-900d-4f22b030c1d1.gif)
7
+ ![2022-07-27 12 26 25](https://user-images.githubusercontent.com/9684022/181235876-45a6a4c5-e6d3-48a2-a6a0-523ee7196184.gif)
8
8
 
9
9
  ## Installation
10
10
 
11
11
  ```
12
- sanity install internationalized-array
12
+ npm install --save sanity-plugin-internationalized-array@studio-v3
13
13
  ```
14
14
 
15
- Add an array to your schema by importing the helper function.
15
+ or
16
16
 
17
- ```js
18
- import { internationalizedArray } from "sanity-plugin-internationalized-array";
19
-
20
- // ./src/schema/person.js
21
- export default {
22
- name: "person",
23
- title: "Person",
24
- type: "document",
25
- fields: [
26
- // ...all your other fields
17
+ ```
18
+ yarn add sanity-plugin-internationalized-array-v3@studio-v3
19
+ ```
20
+
21
+ ## Usage (simple)
22
+
23
+ Add it as a plugin in sanity.config.ts (or .js):
24
+
25
+ ```ts
26
+ import {createConfig} from 'sanity'
27
+ import {internationalizedArray} from 'sanity-plugin-internationalized-array'
28
+
29
+ export const createConfig({
30
+ // ...
31
+ plugins: [
27
32
  internationalizedArray({
28
- // Required, the `name` of the outer array
29
- name: "greeting",
30
- // Required, the `type` of the inner field
31
- // One of: string | text | number | boolean
32
- type: "string",
33
- // Required, must be an array of objects
34
33
  languages: [
35
- { id: "en", title: "English" },
36
- { id: "fr", title: "French" },
34
+ {id: 'en', title: 'English'},
35
+ {id: 'fr', title: 'French'}
37
36
  ],
38
- // Optional: just for debugging
39
- showNativeInput: false,
40
- }),
41
- ],
42
- };
37
+ fieldTypes: ['string'],
38
+ })
39
+ ]
40
+ })
43
41
  ```
44
42
 
45
- This will create an Array field where `string` fields can be added with the name `title`. The custom input contains buttons which will add new array items with the language as the `_key` value. Data returned from this array will look like this:
43
+ This will register two new fields to the schema, based on the settings passed into `fieldTypes`:
44
+
45
+ - `internationalizedArrayString` an array field of:
46
+ - `internationalizedArrayStringValue` an object field, with a single `string` field inside called `value`
47
+
48
+ You can pass in more registered schema type names to generate more internationalized arrays. Use them in your schema like this:
49
+
50
+ ```ts
51
+ defineField({
52
+ name: 'greeting',
53
+ type: 'internationalizedArrayString',
54
+ }),
55
+ ```
56
+
57
+ ## Usage (advanced)
58
+
59
+ For more control over the `value` field, you can pass a schema definition into the `fieldTypes` array.
60
+
61
+ ```ts
62
+ import {createConfig} from 'sanity'
63
+ import {internationalizedArray} from 'sanity-plugin-internationalized-array'
64
+
65
+ export const createConfig({
66
+ // ...
67
+ plugins: [
68
+ internationalizedArray({
69
+ languages: [
70
+ {id: 'en', title: 'English'},
71
+ {id: 'fr', title: 'French'}
72
+ ],
73
+ fieldTypes: [
74
+ defineField({
75
+ name: 'featuredProduct',
76
+ type: 'reference',
77
+ to: [{type: 'product'}]
78
+ hidden: (({document}) => !document?.title)
79
+ })
80
+ ],
81
+ })
82
+ ]
83
+ })
84
+ ```
85
+
86
+ This would also create two new fields in your schema.
87
+
88
+ - `internationalizedArrayFeaturedProduct` an array field of:
89
+ - `internationalizedArrayFeaturedProductValue` an object field, with a single `string` field inside called `value`
90
+
91
+ Note that the `name` key in the field gets rewritten to `value` and is instead used to name the object field.
92
+
93
+ ## Shape of stored data
94
+
95
+ The custom input contains buttons which will add new array items with the language as the `_key` value. Data returned from this array will look like this:
46
96
 
47
97
  ```json
48
98
  "greeting": [
@@ -51,6 +101,8 @@ This will create an Array field where `string` fields can be added with the name
51
101
  ]
52
102
  ```
53
103
 
104
+ ## Querying data
105
+
54
106
  Using GROQ filters you can query for a specific language key like so:
55
107
 
56
108
  ```js
@@ -67,7 +119,7 @@ Follow the instructions inside the script and set the `_type` and field name you
67
119
 
68
120
  Please take a backup first!
69
121
 
70
- ### Why store localised field data like this?
122
+ ### Why store localized field data like this?
71
123
 
72
124
  The most popular way to store field-level translated content is in an object using the method prescribed in [@sanity/language-filter](https://www.npmjs.com/package/@sanity/language-filter). This works well and creates tidy object structures, but also create a unique field path for every unique field name, multiplied by the number of languages in your dataset.
73
125
 
@@ -105,7 +157,5 @@ greeting[].value
105
157
 
106
158
  By using this plugin you can safely extend the number of languages without adding any additional query paths.
107
159
 
108
- ## License
109
-
110
160
  MIT © Simeon Griggs
111
161
  See LICENSE
@@ -0,0 +1,487 @@
1
+ var $k7rGe$sanity = require("sanity");
2
+ var $k7rGe$reactjsxruntime = require("react/jsx-runtime");
3
+ var $k7rGe$react = require("react");
4
+ var $k7rGe$sanityform = require("sanity/form");
5
+ var $k7rGe$sanityui = require("@sanity/ui");
6
+ var $k7rGe$sanityicons = require("@sanity/icons");
7
+ var $k7rGe$styledcomponents = require("styled-components");
8
+
9
+ function $parcel$export(e, n, v, s) {
10
+ Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
11
+ }
12
+ function $parcel$interopDefault(a) {
13
+ return a && a.__esModule ? a.default : a;
14
+ }
15
+
16
+ $parcel$export(module.exports, "internationalizedArray", () => $45e3093e7de8dca2$export$bec7eb13daf35f0e);
17
+
18
+
19
+ function $a0eca5cb1c058e2c$export$8a7688a96d852767(string) {
20
+ return string.replace(/-([a-z])/g, (g)=>g[1].toUpperCase());
21
+ }
22
+ function $a0eca5cb1c058e2c$export$348afa8c9ff47183(string) {
23
+ return string.split(` `).map((word)=>word.charAt(0).toUpperCase() + word.slice(1)).join(` `);
24
+ }
25
+ function $a0eca5cb1c058e2c$export$26c6f48841fe1a8a(string) {
26
+ return $a0eca5cb1c058e2c$export$348afa8c9ff47183($a0eca5cb1c058e2c$export$8a7688a96d852767(string));
27
+ }
28
+ function $a0eca5cb1c058e2c$export$ab1ce2a474f41f52(name, addValue = false) {
29
+ return addValue ? [
30
+ `internationalizedArray`,
31
+ $a0eca5cb1c058e2c$export$26c6f48841fe1a8a(name),
32
+ `Value`
33
+ ].join(``) : [
34
+ `internationalizedArray`,
35
+ $a0eca5cb1c058e2c$export$26c6f48841fe1a8a(name)
36
+ ].join(``);
37
+ }
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+
47
+
48
+ // Wrappers required because of bug with passing down "as" prop
49
+ // https://github.com/styled-components/styled-components/issues/2449
50
+ // Table
51
+ const $acfbfc6ee2363807$var$TableWrapper = (props = {})=>{
52
+ return /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Box), {
53
+ as: "table",
54
+ ...props
55
+ });
56
+ };
57
+ const $acfbfc6ee2363807$var$StyledTable = (0, ($parcel$interopDefault($k7rGe$styledcomponents)))($acfbfc6ee2363807$var$TableWrapper)(()=>(0, $k7rGe$styledcomponents.css)`
58
+ display: table;
59
+ width: 100%;
60
+
61
+ &:not([hidden]) {
62
+ display: table;
63
+ }
64
+ `);
65
+ function $acfbfc6ee2363807$export$54ec01a60f47d33d(props) {
66
+ const { children: children , ...rest } = props;
67
+ return /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)($acfbfc6ee2363807$var$StyledTable, {
68
+ ...rest,
69
+ children: children
70
+ });
71
+ }
72
+ // Row
73
+ const $acfbfc6ee2363807$var$RowWrapper = (props = {})=>{
74
+ return /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Card), {
75
+ as: "tr",
76
+ ...props
77
+ });
78
+ };
79
+ const $acfbfc6ee2363807$var$StyledRow = (0, ($parcel$interopDefault($k7rGe$styledcomponents)))($acfbfc6ee2363807$var$RowWrapper)(()=>(0, $k7rGe$styledcomponents.css)`
80
+ display: table-row;
81
+
82
+ &:not([hidden]) {
83
+ display: table-row;
84
+ }
85
+ `);
86
+ function $acfbfc6ee2363807$export$b05581f4e764e162(props) {
87
+ const { children: children , ...rest } = props;
88
+ return /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)($acfbfc6ee2363807$var$StyledRow, {
89
+ ...rest,
90
+ children: children
91
+ });
92
+ }
93
+ // Cell
94
+ const $acfbfc6ee2363807$var$CellWrapper = (props = {})=>{
95
+ return /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Box), {
96
+ as: "td",
97
+ ...props
98
+ });
99
+ };
100
+ const $acfbfc6ee2363807$var$StyledCell = (0, ($parcel$interopDefault($k7rGe$styledcomponents)))($acfbfc6ee2363807$var$CellWrapper)(()=>(0, $k7rGe$styledcomponents.css)`
101
+ display: table-cell;
102
+
103
+ &:not([hidden]) {
104
+ display: table-cell;
105
+ }
106
+ `);
107
+ function $acfbfc6ee2363807$export$1e4baea7053fc0e3(props) {
108
+ const { children: children , ...rest } = props;
109
+ return /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)($acfbfc6ee2363807$var$StyledCell, {
110
+ ...rest,
111
+ children: children
112
+ });
113
+ }
114
+
115
+
116
+
117
+
118
+
119
+
120
+ const $aaf4d804384afd00$var$schemaExample = {
121
+ languages: [
122
+ {
123
+ id: "en",
124
+ title: "English"
125
+ },
126
+ {
127
+ id: "no",
128
+ title: "Norsk"
129
+ },
130
+ ]
131
+ };
132
+ function $aaf4d804384afd00$export$2e2bcd8739ae039() {
133
+ return /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Card), {
134
+ tone: "caution",
135
+ border: true,
136
+ radius: 2,
137
+ padding: 3,
138
+ children: /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsxs)((0, $k7rGe$sanityui.Stack), {
139
+ space: 4,
140
+ children: [
141
+ /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsxs)((0, $k7rGe$sanityui.Text), {
142
+ children: [
143
+ "An array of language objects must be passed into the ",
144
+ /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)("code", {
145
+ children: "internationalizedArray"
146
+ }),
147
+ " ",
148
+ "helper function, each with an ",
149
+ /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)("code", {
150
+ children: "id"
151
+ }),
152
+ " and ",
153
+ /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)("code", {
154
+ children: "title"
155
+ }),
156
+ " field. Example:"
157
+ ]
158
+ }),
159
+ /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Card), {
160
+ padding: 2,
161
+ border: true,
162
+ radius: 2,
163
+ children: /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Code), {
164
+ size: 1,
165
+ language: "javascript",
166
+ children: JSON.stringify($aaf4d804384afd00$var$schemaExample, null, 2)
167
+ })
168
+ })
169
+ ]
170
+ })
171
+ });
172
+ }
173
+
174
+
175
+ function $6a9b28384eb7074d$export$16423358d6ebe294(validations) {
176
+ if (!validations.length) return `default`;
177
+ const validationLevels = validations.map((v)=>v.level);
178
+ if (validationLevels.includes("error")) return `critical`;
179
+ else if (validationLevels.includes("warning")) return `caution`;
180
+ return `default`;
181
+ }
182
+
183
+
184
+ function $7e790a73eaf2b445$export$2e2bcd8739ae039(props) {
185
+ const { members: members , value: value , schemaType: schemaType , onChange: onChange } = props;
186
+ const readOnly = typeof schemaType.readOnly === "boolean" ? schemaType.readOnly : false;
187
+ const { options: options } = schemaType;
188
+ const languages = (0, $k7rGe$react.useMemo)(()=>options?.languages ?? [], [
189
+ options
190
+ ]);
191
+ const handleAddLanguage = (0, $k7rGe$react.useCallback)((languageId)=>{
192
+ // Create new items
193
+ const newItems = languageId ? [
194
+ {
195
+ _key: languageId
196
+ }
197
+ ] : languages.filter((language)=>value?.length ? !value.find((v)=>v._key === language.id) : true).map((language)=>({
198
+ _key: language.id
199
+ }));
200
+ // Insert new items in the correct order
201
+ const languagesInUse = value?.length ? value.map((v)=>v) : [];
202
+ const insertions = newItems.map((item)=>{
203
+ // What's the original index of this language?
204
+ const languageIndex = languages.findIndex((l)=>item._key === l.id);
205
+ // What languages are there beyond that index?
206
+ const remainingLanguages = languages.slice(languageIndex + 1);
207
+ // So what is the index in the current value array of the next language in the language array?
208
+ const nextLanguageIndex = languagesInUse.findIndex((l)=>// eslint-disable-next-line max-nested-callbacks
209
+ remainingLanguages.find((r)=>r.id === l._key));
210
+ // Keep local state up to date incase multiple insertions are being made
211
+ if (nextLanguageIndex < 0) languagesInUse.push(item);
212
+ else languagesInUse.splice(nextLanguageIndex, 0, item);
213
+ return nextLanguageIndex < 0 ? (0, $k7rGe$sanityform.insert)([
214
+ item
215
+ ], "after", [
216
+ nextLanguageIndex
217
+ ]) : (0, $k7rGe$sanityform.insert)([
218
+ item
219
+ ], "before", [
220
+ nextLanguageIndex
221
+ ]);
222
+ });
223
+ onChange([
224
+ (0, $k7rGe$sanityform.setIfMissing)([]),
225
+ ...insertions
226
+ ]);
227
+ }, [
228
+ languages,
229
+ onChange,
230
+ value
231
+ ]);
232
+ const handleUnsetByKey = (0, $k7rGe$react.useCallback)((_key)=>{
233
+ onChange((0, $k7rGe$sanityform.unset)([
234
+ {
235
+ _key: _key
236
+ }
237
+ ]));
238
+ }, [
239
+ onChange
240
+ ]);
241
+ // TODO: This is lazy, reordering and re-setting the whole array – it could be surgical
242
+ const handleRestoreOrder = (0, $k7rGe$react.useCallback)(()=>{
243
+ if (!value?.length) return;
244
+ // Create a new value array in the correct order
245
+ // This would also strip out values that don't have a language as the key
246
+ const updatedValue = value.reduce((acc, v)=>{
247
+ const newIndex = languages.findIndex((l)=>l.id === v?._key);
248
+ if (newIndex) acc[newIndex] = v;
249
+ return acc;
250
+ }, []).filter(Boolean);
251
+ onChange((0, $k7rGe$sanityform.set)(updatedValue));
252
+ }, [
253
+ languages,
254
+ onChange,
255
+ value
256
+ ]);
257
+ const allKeysAreLanguages = (0, $k7rGe$react.useMemo)(()=>{
258
+ return value?.every((v)=>languages.find((l)=>l?.id === v?._key));
259
+ }, [
260
+ value,
261
+ languages
262
+ ]);
263
+ // Check languages are in the correct order
264
+ const languagesOutOfOrder = (0, $k7rGe$react.useMemo)(()=>{
265
+ if (!value?.length) return [];
266
+ const languagesInUse = languages.filter((l)=>value.find((v)=>v._key === l.id));
267
+ return value.map((v, vIndex)=>vIndex === languagesInUse.findIndex((l)=>l.id === v._key) ? null : v).filter(Boolean);
268
+ }, [
269
+ value,
270
+ languages
271
+ ]);
272
+ const languagesAreValid = (0, $k7rGe$react.useMemo)(()=>!languages?.length || languages?.length && languages.every((item)=>item.id && item.title), [
273
+ languages
274
+ ]);
275
+ if (!languagesAreValid) return /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $aaf4d804384afd00$export$2e2bcd8739ae039), {});
276
+ return /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsxs)((0, $k7rGe$sanityui.Stack), {
277
+ space: 2,
278
+ children: [
279
+ members?.length > 0 ? /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $acfbfc6ee2363807$export$54ec01a60f47d33d), {
280
+ children: /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)("tbody", {
281
+ children: members.map((member)=>/*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsxs)((0, $acfbfc6ee2363807$export$b05581f4e764e162), {
282
+ tone: member?.item?.validation?.length > 0 ? (0, $6a9b28384eb7074d$export$16423358d6ebe294)(member.item.validation) : undefined,
283
+ children: [
284
+ /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $acfbfc6ee2363807$export$1e4baea7053fc0e3), {
285
+ style: {
286
+ verticalAlign: "bottom"
287
+ },
288
+ children: /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Box), {
289
+ paddingY: 3,
290
+ paddingRight: 2,
291
+ children: /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Label), {
292
+ muted: true,
293
+ size: 1,
294
+ children: member.key
295
+ })
296
+ })
297
+ }),
298
+ /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $acfbfc6ee2363807$export$1e4baea7053fc0e3), {
299
+ paddingRight: 2,
300
+ style: {
301
+ width: `100%`
302
+ },
303
+ children: /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityform.MemberItem), {
304
+ ...props,
305
+ member: member
306
+ })
307
+ }),
308
+ /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $acfbfc6ee2363807$export$1e4baea7053fc0e3), {
309
+ style: {
310
+ verticalAlign: "bottom"
311
+ },
312
+ children: /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsxs)((0, $k7rGe$sanityui.Flex), {
313
+ align: "center",
314
+ justify: "flex-end",
315
+ gap: 3,
316
+ children: [
317
+ member?.item?.validation?.length > 0 ? /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Box), {
318
+ paddingLeft: 2,
319
+ children: /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityform.FormFieldValidationStatus), {
320
+ validation: member.item.validation
321
+ })
322
+ }) : null,
323
+ /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Button), {
324
+ mode: "ghost",
325
+ icon: (0, $k7rGe$sanityicons.RemoveIcon),
326
+ tone: "critical",
327
+ disabled: typeof readOnly === "boolean" ? readOnly : false,
328
+ onClick: ()=>handleUnsetByKey(member.key)
329
+ })
330
+ ]
331
+ })
332
+ })
333
+ ]
334
+ }, member.key))
335
+ })
336
+ }) : null,
337
+ languagesOutOfOrder.length > 0 && allKeysAreLanguages ? /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Button), {
338
+ tone: "caution",
339
+ icon: (0, $k7rGe$sanityicons.RestoreIcon),
340
+ onClick: ()=>handleRestoreOrder(),
341
+ text: "Restore order of languages"
342
+ }) : null,
343
+ languages?.length > 0 ? /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsxs)((0, $k7rGe$sanityui.Stack), {
344
+ space: 2,
345
+ children: [
346
+ /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Grid), {
347
+ columns: Math.min(languages.length, 5),
348
+ gap: 2,
349
+ children: languages.map((language)=>/*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Button), {
350
+ tone: "primary",
351
+ mode: "ghost",
352
+ fontSize: 1,
353
+ disabled: readOnly || Boolean(value?.find((item)=>item._key === language.id)),
354
+ text: language.id.toUpperCase(),
355
+ icon: (0, $k7rGe$sanityicons.AddIcon),
356
+ onClick: ()=>handleAddLanguage(language.id)
357
+ }, language.id))
358
+ }),
359
+ /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Button), {
360
+ tone: "primary",
361
+ mode: "ghost",
362
+ disabled: readOnly || value && value?.length >= languages?.length,
363
+ icon: (0, $k7rGe$sanityicons.AddIcon),
364
+ text: value?.length ? `Add missing languages` : `Add all languages`,
365
+ onClick: ()=>handleAddLanguage()
366
+ })
367
+ ]
368
+ }) : null
369
+ ]
370
+ });
371
+ }
372
+
373
+
374
+ var $0437df2e2e149362$export$2e2bcd8739ae039 = (config)=>{
375
+ const { languages: languages , type: type } = config;
376
+ const typeName = typeof type === `string` ? type : type.name;
377
+ const arrayName = (0, $a0eca5cb1c058e2c$export$ab1ce2a474f41f52)(typeName);
378
+ const objectName = (0, $a0eca5cb1c058e2c$export$ab1ce2a474f41f52)(typeName, true);
379
+ return (0, $k7rGe$sanity.defineField)({
380
+ name: arrayName,
381
+ title: "Internationalized array",
382
+ type: "array",
383
+ components: {
384
+ input: (0, $7e790a73eaf2b445$export$2e2bcd8739ae039)
385
+ },
386
+ options: {
387
+ languages: languages
388
+ },
389
+ of: [
390
+ (0, $k7rGe$sanity.defineField)({
391
+ name: objectName,
392
+ type: objectName
393
+ })
394
+ ],
395
+ validation: (rule)=>rule.max(languages?.length).custom((value, context)=>{
396
+ const { languages: contextLanguages } = context?.type?.options ?? {};
397
+ const nonLanguageKeys = value?.length ? value.filter((item)=>!contextLanguages.find((language)=>item._key === language.id)) : [];
398
+ if (nonLanguageKeys.length) return {
399
+ message: `Array item keys must be valid languages registered to the field type`,
400
+ paths: nonLanguageKeys.map((item)=>[
401
+ {
402
+ _key: item._key
403
+ }
404
+ ])
405
+ };
406
+ const valuesByLanguage = value?.length ? value.filter((item)=>Boolean(item?._key)).reduce((acc, cur)=>{
407
+ if (acc[cur._key]) return {
408
+ ...acc,
409
+ [cur._key]: [
410
+ ...acc[cur._key],
411
+ cur
412
+ ]
413
+ };
414
+ return {
415
+ ...acc,
416
+ [cur._key]: [
417
+ cur
418
+ ]
419
+ };
420
+ }, {}) : {};
421
+ const duplicateValues = Object.values(valuesByLanguage).filter((item)=>item?.length > 1).flat();
422
+ if (duplicateValues.length) return {
423
+ message: "There can only be one field per language",
424
+ paths: duplicateValues.map((item)=>[
425
+ {
426
+ _key: item._key
427
+ }
428
+ ])
429
+ };
430
+ return true;
431
+ })
432
+ });
433
+ };
434
+
435
+
436
+
437
+
438
+ var $f727fb16d5d00f8f$export$2e2bcd8739ae039 = (config)=>{
439
+ const { type: type } = config;
440
+ const typeName = typeof type === `string` ? type : type.name;
441
+ const objectName = (0, $a0eca5cb1c058e2c$export$ab1ce2a474f41f52)(typeName, true);
442
+ return (0, $k7rGe$sanity.defineField)({
443
+ name: objectName,
444
+ title: `Internationalized array ${type}`,
445
+ type: "object",
446
+ fields: [
447
+ typeof type === `string` ? (0, $k7rGe$sanity.defineField)({
448
+ name: "value",
449
+ type: type
450
+ }) : {
451
+ ...type,
452
+ name: "value"
453
+ },
454
+ ]
455
+ });
456
+ };
457
+
458
+
459
+ const $45e3093e7de8dca2$var$CONFIG_DEFAULT = {
460
+ languages: [],
461
+ fieldTypes: []
462
+ };
463
+ const $45e3093e7de8dca2$export$bec7eb13daf35f0e = (0, $k7rGe$sanity.createPlugin)((config = $45e3093e7de8dca2$var$CONFIG_DEFAULT)=>{
464
+ const { languages: languages , fieldTypes: fieldTypes } = {
465
+ ...$45e3093e7de8dca2$var$CONFIG_DEFAULT,
466
+ ...config
467
+ };
468
+ return {
469
+ name: "sanity-plugin-internationalized-array",
470
+ schema: {
471
+ types: [
472
+ ...fieldTypes.map((type)=>(0, $0437df2e2e149362$export$2e2bcd8739ae039)({
473
+ type: type,
474
+ languages: languages
475
+ })),
476
+ ...fieldTypes.map((type)=>(0, $f727fb16d5d00f8f$export$2e2bcd8739ae039)({
477
+ type: type
478
+ })),
479
+ ]
480
+ }
481
+ };
482
+ });
483
+
484
+
485
+
486
+
487
+ //# sourceMappingURL=index.js.map