sanity-plugin-internationalized-array 2.0.1-canary.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.esm.js CHANGED
@@ -1,15 +1,15 @@
1
1
  import * as suspend from "suspend-react";
2
2
  import { suspend as suspend$1 } from "suspend-react";
3
3
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
4
- import { isSanityDocument, setIfMissing, insert, PatchEvent, useClient, useWorkspace, defineDocumentFieldAction, useFormValue, set, ArrayOfObjectsItem, MemberItemError, defineField, unset, isDocumentSchemaType, definePlugin, isObjectInputProps } from "sanity";
4
+ import { isSanityDocument, setIfMissing, insert, PatchEvent, useClient, useWorkspace, useFormBuilder, defineDocumentFieldAction, useFormValue, set, ArrayOfObjectsItem, MemberItemError, defineField, unset, isDocumentSchemaType, definePlugin, isObjectInputProps } from "sanity";
5
5
  import { useLanguageFilterStudioContext } from "@sanity/language-filter";
6
6
  import { Grid, Button, useToast, Stack, Box, Text, Card, Code, Label, MenuButton, Menu, MenuItem, Flex, Spinner } from "@sanity/ui";
7
7
  import equal from "fast-deep-equal";
8
- import { memo, useCallback, createContext, useContext, useDeferredValue, useMemo, useRef, useEffect, createElement } from "react";
8
+ import { useCallback, createContext, useContext, useDeferredValue, useMemo, memo, useRef, useEffect, createElement } from "react";
9
9
  import { useDocumentPane } from "sanity/structure";
10
10
  import { AddIcon, TranslateIcon, RemoveCircleIcon } from "@sanity/icons";
11
11
  import get from "lodash/get.js";
12
- const namespace = "sanity-plugin-internationalized-array", version = "v1", preload = (fn) => suspend.preload(() => fn(), [version, namespace]), clear = () => suspend.clear([version, namespace]), peek = (selectedValue) => suspend.peek([version, namespace, selectedValue]), MAX_COLUMNS = 7, CONFIG_DEFAULT = {
12
+ const namespace = "sanity-plugin-internationalized-array", version = "v0", preload = (fn) => suspend.preload(() => fn(), [version, namespace]), clear = () => suspend.clear([version, namespace]), peek = (selectedValue) => suspend.peek([version, namespace, selectedValue]), MAX_COLUMNS = 7, CONFIG_DEFAULT = {
13
13
  languages: [],
14
14
  select: {},
15
15
  defaultLanguages: [],
@@ -20,10 +20,11 @@ const namespace = "sanity-plugin-internationalized-array", version = "v1", prelo
20
20
  }, getDocumentsToTranslate = (value, rootPath = []) => {
21
21
  if (Array.isArray(value)) {
22
22
  const arrayRootPath = [...rootPath], internationalizedValues = value.filter((item) => {
23
- if (Array.isArray(item)) return !1;
23
+ if (Array.isArray(item))
24
+ return !1;
24
25
  if (typeof item == "object") {
25
- const type = item?._type;
26
- return type?.startsWith("internationalizedArray") && type?.endsWith("Value");
26
+ const type = item == null ? void 0 : item._type;
27
+ return (type == null ? void 0 : type.startsWith("internationalizedArray")) && (type == null ? void 0 : type.endsWith("Value"));
27
28
  }
28
29
  return !1;
29
30
  });
@@ -54,7 +55,7 @@ function AddButtons(props) {
54
55
  tone: "primary",
55
56
  mode: "ghost",
56
57
  fontSize: 1,
57
- disabled: readOnly || !!value?.find((item) => item._key === language.id),
58
+ disabled: readOnly || !!(value != null && value.find((item) => item._key === language.id)),
58
59
  text: language.id.toUpperCase(),
59
60
  icon: languages.length > MAX_COLUMNS ? void 0 : AddIcon,
60
61
  value: language.id,
@@ -63,7 +64,6 @@ function AddButtons(props) {
63
64
  language.id
64
65
  )) }) : null;
65
66
  }
66
- var AddButtons$1 = memo(AddButtons);
67
67
  function DocumentAddButtons(props) {
68
68
  const { filteredLanguages } = useInternationalizedArrayContext(), value = isSanityDocument(props.value) ? props.value : void 0, toast = useToast(), { onChange } = useDocumentPane(), documentsToTranslation = getDocumentsToTranslate(value, []), handleDocumentButtonClick = useCallback(
69
69
  async (event) => {
@@ -76,7 +76,7 @@ function DocumentAddButtons(props) {
76
76
  return;
77
77
  }
78
78
  const alreadyTranslated = documentsToTranslation.filter(
79
- (translation) => translation?._key === languageId
79
+ (translation) => (translation == null ? void 0 : translation._key) === languageId
80
80
  ), removeDuplicates = documentsToTranslation.reduce((filteredTranslations, translation) => alreadyTranslated.filter(
81
81
  (alreadyTranslation) => alreadyTranslation.pathString === translation.pathString
82
82
  ).length > 0 || filteredTranslations.filter(
@@ -111,7 +111,7 @@ function DocumentAddButtons(props) {
111
111
  return /* @__PURE__ */ jsxs(Stack, { space: 3, children: [
112
112
  /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { size: 1, weight: "semibold", children: "Add translation to internationalized fields" }) }),
113
113
  /* @__PURE__ */ jsx(
114
- AddButtons$1,
114
+ AddButtons,
115
115
  {
116
116
  languages: filteredLanguages,
117
117
  readOnly: !1,
@@ -128,7 +128,7 @@ const getSelectedValue = (select, document) => {
128
128
  for (const [key, path] of Object.entries(selection)) {
129
129
  let value = get(document, path);
130
130
  Array.isArray(value) && (value = value.filter(
131
- (item) => typeof item == "object" ? item?._type === "reference" && "_ref" in item : !0
131
+ (item) => typeof item == "object" ? (item == null ? void 0 : item._type) === "reference" && "_ref" in item : !0
132
132
  )), selectedValue[key] = value;
133
133
  }
134
134
  return selectedValue;
@@ -141,7 +141,7 @@ function useInternationalizedArrayContext() {
141
141
  return useContext(InternationalizedArrayContext);
142
142
  }
143
143
  function InternationalizedArrayProvider(props) {
144
- const { internationalizedArray: internationalizedArray2 } = props, client = useClient({ apiVersion: internationalizedArray2.apiVersion }), workspace = useWorkspace(), { formState } = useDocumentPane(), deferredDocument = useDeferredValue(formState?.value), selectedValue = useMemo(
144
+ const { internationalizedArray: internationalizedArray2 } = props, client = useClient({ apiVersion: internationalizedArray2.apiVersion }), workspace = useWorkspace(), { value: document } = useFormBuilder(), deferredDocument = useDeferredValue(document), selectedValue = useMemo(
145
145
  () => getSelectedValue(internationalizedArray2.select, deferredDocument),
146
146
  [internationalizedArray2.select, deferredDocument]
147
147
  ), languages = Array.isArray(internationalizedArray2.languages) ? internationalizedArray2.languages : suspend$1(
@@ -154,14 +154,21 @@ function InternationalizedArrayProvider(props) {
154
154
  return typeof documentType == "string" && languageFilterOptions.documentTypes.includes(documentType) ? languages.filter(
155
155
  (language) => selectedLanguageIds.includes(language.id)
156
156
  ) : languages;
157
- }, [deferredDocument, languageFilterOptions, languages, selectedLanguageIds]), showDocumentButtons = internationalizedArray2.buttonLocations.includes("document"), context = useMemo(
158
- () => ({ ...internationalizedArray2, languages, filteredLanguages }),
159
- [filteredLanguages, internationalizedArray2, languages]
157
+ }, [deferredDocument, languageFilterOptions, languages, selectedLanguageIds]), showDocumentButtons = internationalizedArray2.buttonLocations.includes("document");
158
+ return /* @__PURE__ */ jsx(
159
+ InternationalizedArrayContext.Provider,
160
+ {
161
+ value: {
162
+ ...internationalizedArray2,
163
+ languages,
164
+ filteredLanguages
165
+ },
166
+ children: showDocumentButtons ? /* @__PURE__ */ jsxs(Stack, { space: 5, children: [
167
+ /* @__PURE__ */ jsx(DocumentAddButtons, { value: props.value }),
168
+ props.renderDefault(props)
169
+ ] }) : props.renderDefault(props)
170
+ }
160
171
  );
161
- return /* @__PURE__ */ jsx(InternationalizedArrayContext.Provider, { value: context, children: showDocumentButtons ? /* @__PURE__ */ jsxs(Stack, { space: 5, children: [
162
- /* @__PURE__ */ jsx(DocumentAddButtons, { value: props.value }),
163
- props.renderDefault(props)
164
- ] }) : props.renderDefault(props) });
165
172
  }
166
173
  var Preload = memo(function(props) {
167
174
  const client = useClient({ apiVersion: props.apiVersion });
@@ -174,7 +181,7 @@ function checkAllLanguagesArePresent(languages, value) {
174
181
  return languagesInUseIds.length === filteredLanguageIds.length && languagesInUseIds.every((l) => filteredLanguageIds.includes(l));
175
182
  }
176
183
  function createAddAllTitle(value, languages) {
177
- return value?.length ? `Add missing ${languages.length - value.length === 1 ? "language" : "languages"}` : languages.length === 1 ? `Add ${languages[0].title} Field` : "Add all languages";
184
+ return value != null && value.length ? `Add missing ${languages.length - value.length === 1 ? "language" : "languages"}` : languages.length === 1 ? `Add ${languages[0].title} Field` : "Add all languages";
178
185
  }
179
186
  function createValueSchemaTypeName(schemaType) {
180
187
  return `${schemaType.name}Value`;
@@ -191,11 +198,11 @@ function createAddLanguagePatches(config) {
191
198
  ...itemBase,
192
199
  _key: id
193
200
  })) : filteredLanguages.filter(
194
- (language) => value?.length ? !value.find((v) => v._key === language.id) : !0
201
+ (language) => value != null && value.length ? !value.find((v) => v._key === language.id) : !0
195
202
  ).map((language) => ({
196
203
  ...itemBase,
197
204
  _key: language.id
198
- })), languagesInUse = value?.length ? value.map((v) => v) : [];
205
+ })), languagesInUse = value != null && value.length ? value.map((v) => v) : [];
199
206
  return newItems.map((item) => {
200
207
  const languageIndex = languages.findIndex((l) => item._key === l.id), remainingLanguages = languages.slice(languageIndex + 1), nextLanguageIndex = languagesInUse.findIndex(
201
208
  (l) => (
@@ -213,7 +220,7 @@ function createAddLanguagePatches(config) {
213
220
  });
214
221
  }
215
222
  const createTranslateFieldActions = (fieldActionProps, { languages, filteredLanguages }) => languages.map((language) => {
216
- const value = useFormValue(fieldActionProps.path), disabled = value && Array.isArray(value) ? !!value?.find((item) => item._key === language.id) : !1, hidden = !filteredLanguages.some((f) => f.id === language.id), { onChange } = useDocumentPane(), onAction = useCallback(() => {
223
+ const value = useFormValue(fieldActionProps.path), disabled = value && Array.isArray(value) ? !!(value != null && value.find((item) => item._key === language.id)) : !1, hidden = !filteredLanguages.some((f) => f.id === language.id), { onChange } = useDocumentPane(), onAction = useCallback(() => {
217
224
  const { schemaType, path } = fieldActionProps, addLanguageKeys = [language.id], patches = createAddLanguagePatches({
218
225
  addLanguageKeys,
219
226
  schemaType,
@@ -255,7 +262,8 @@ const createTranslateFieldActions = (fieldActionProps, { languages, filteredLang
255
262
  }, internationalizedArrayFieldAction = defineDocumentFieldAction({
256
263
  name: "internationalizedArray",
257
264
  useAction(fieldActionProps) {
258
- const isInternationalizedArrayField = fieldActionProps?.schemaType?.type?.name.startsWith(
265
+ var _a, _b;
266
+ const isInternationalizedArrayField = (_b = (_a = fieldActionProps == null ? void 0 : fieldActionProps.schemaType) == null ? void 0 : _a.type) == null ? void 0 : _b.name.startsWith(
259
267
  "internationalizedArray"
260
268
  ), { languages, filteredLanguages } = useInternationalizedArrayContext(), translateFieldActions = createTranslateFieldActions(
261
269
  fieldActionProps,
@@ -332,9 +340,10 @@ function InternationalizedArray(props) {
332
340
  [languageFilterEnabled, members, languageFilterOptions, selectedLanguageIds]
333
341
  ), handleAddLanguage = useCallback(
334
342
  async (param) => {
335
- if (!filteredLanguages?.length)
343
+ var _a;
344
+ if (!(filteredLanguages != null && filteredLanguages.length))
336
345
  return;
337
- const addLanguageKeys = Array.isArray(param) ? param : [param?.currentTarget?.value].filter(Boolean), patches = createAddLanguagePatches({
346
+ const addLanguageKeys = Array.isArray(param) ? param : [(_a = param == null ? void 0 : param.currentTarget) == null ? void 0 : _a.value].filter(Boolean), patches = createAddLanguagePatches({
338
347
  addLanguageKeys,
339
348
  schemaType,
340
349
  languages,
@@ -352,23 +361,23 @@ function InternationalizedArray(props) {
352
361
  };
353
362
  }, [defaultLanguages, documentCreatedAt, handleAddLanguage, value]);
354
363
  const handleRestoreOrder = useCallback(() => {
355
- if (!value?.length || !languages?.length)
364
+ if (!(value != null && value.length) || !(languages != null && languages.length))
356
365
  return;
357
366
  const updatedValue = value.reduce((acc, v) => {
358
- const newIndex = languages.findIndex((l) => l.id === v?._key);
367
+ const newIndex = languages.findIndex((l) => l.id === (v == null ? void 0 : v._key));
359
368
  return newIndex > -1 && (acc[newIndex] = v), acc;
360
369
  }, []).filter(Boolean);
361
- value?.length !== updatedValue.length && toast.push({
370
+ (value == null ? void 0 : value.length) !== updatedValue.length && toast.push({
362
371
  title: "There was an error reordering languages",
363
372
  status: "warning"
364
373
  }), onChange(set(updatedValue));
365
- }, [toast, languages, onChange, value]), allKeysAreLanguages = useMemo(() => !value?.length || !languages?.length ? !0 : value?.every((v) => languages.find((l) => l?.id === v?._key)), [value, languages]), languagesInUse = useMemo(
366
- () => languages && languages.length > 1 ? languages.filter((l) => value?.find((v) => v._key === l.id)) : [],
374
+ }, [toast, languages, onChange, value]), allKeysAreLanguages = useMemo(() => !(value != null && value.length) || !(languages != null && languages.length) ? !0 : value == null ? void 0 : value.every((v) => languages.find((l) => (l == null ? void 0 : l.id) === (v == null ? void 0 : v._key))), [value, languages]), languagesInUse = useMemo(
375
+ () => languages && languages.length > 1 ? languages.filter((l) => value == null ? void 0 : value.find((v) => v._key === l.id)) : [],
367
376
  [languages, value]
368
- ), languagesOutOfOrder = useMemo(() => !value?.length || !languagesInUse.length ? [] : value.map(
377
+ ), languagesOutOfOrder = useMemo(() => !(value != null && value.length) || !languagesInUse.length ? [] : value.map(
369
378
  (v, vIndex) => vIndex === languagesInUse.findIndex((l) => l.id === v._key) ? null : v
370
379
  ).filter(Boolean), [value, languagesInUse]), languagesAreValid = useMemo(
371
- () => !languages?.length || languages?.length && languages.every((item) => item.id && item.title),
380
+ () => !(languages != null && languages.length) || (languages == null ? void 0 : languages.length) && languages.every((item) => item.id && item.title),
372
381
  [languages]
373
382
  );
374
383
  useEffect(() => {
@@ -383,9 +392,9 @@ function InternationalizedArray(props) {
383
392
  const addButtonsAreVisible = (
384
393
  // Plugin was configured to display buttons here (default!)
385
394
  buttonLocations.includes("field") && // There's at least one language visible
386
- filteredLanguages?.length > 0 && // Not every language has a value yet
395
+ (filteredLanguages == null ? void 0 : filteredLanguages.length) > 0 && // Not every language has a value yet
387
396
  !allLanguagesArePresent
388
- ), fieldHasMembers = members?.length > 0;
397
+ ), fieldHasMembers = (members == null ? void 0 : members.length) > 0;
389
398
  return /* @__PURE__ */ jsxs(Stack, { space: 2, children: [
390
399
  fieldHasMembers ? /* @__PURE__ */ jsx(Fragment, { children: filteredMembers.map((member) => member.kind === "item" ? /* @__PURE__ */ createElement(
391
400
  ArrayOfObjectsItem,
@@ -398,7 +407,7 @@ function InternationalizedArray(props) {
398
407
  !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,
399
408
  addButtonsAreVisible ? /* @__PURE__ */ jsxs(Stack, { space: 2, children: [
400
409
  /* @__PURE__ */ jsx(
401
- AddButtons$1,
410
+ AddButtons,
402
411
  {
403
412
  languages: filteredLanguages,
404
413
  value,
@@ -421,7 +430,8 @@ function InternationalizedArray(props) {
421
430
  ] });
422
431
  }
423
432
  function getLanguagesFieldOption(schemaType) {
424
- return schemaType ? schemaType.options?.languages || getLanguagesFieldOption(schemaType.type) : void 0;
433
+ var _a;
434
+ return schemaType ? ((_a = schemaType.options) == null ? void 0 : _a.languages) || getLanguagesFieldOption(schemaType.type) : void 0;
425
435
  }
426
436
  var array = (config) => {
427
437
  const { apiVersion, select, languages, type } = config, typeName = typeof type == "string" ? type : type.name, arrayName = createFieldName(typeName), objectName = createFieldName(typeName, !0);
@@ -433,12 +443,7 @@ var array = (config) => {
433
443
  input: InternationalizedArray
434
444
  },
435
445
  // These options are required for validation rules – not the custom input component
436
- options: {
437
- // @ts-expect-error - find out why it fails
438
- apiVersion,
439
- select,
440
- languages
441
- },
446
+ options: { apiVersion, select, languages },
442
447
  of: [
443
448
  defineField({
444
449
  ...typeof type == "string" ? {} : type,
@@ -446,16 +451,15 @@ var array = (config) => {
446
451
  type: objectName
447
452
  })
448
453
  ],
449
- // @ts-expect-error - find out why it fails
450
454
  validation: (rule) => rule.custom(async (value, context) => {
451
455
  if (!value)
452
456
  return !0;
453
457
  const selectedValue = getSelectedValue(select, context.document), client = context.getClient({ apiVersion });
454
458
  let contextLanguages = [];
455
- const languagesFieldOption = getLanguagesFieldOption(context?.type);
459
+ const languagesFieldOption = getLanguagesFieldOption(context == null ? void 0 : context.type);
456
460
  if (Array.isArray(languagesFieldOption) ? contextLanguages = languagesFieldOption : Array.isArray(peek(selectedValue)) ? contextLanguages = peek(selectedValue) || [] : typeof languagesFieldOption == "function" && (contextLanguages = await languagesFieldOption(client, selectedValue)), value && value.length > contextLanguages.length)
457
461
  return `Cannot be more than ${contextLanguages.length === 1 ? "1 item" : `${contextLanguages.length} items`}`;
458
- const nonLanguageKeys = value?.length ? value.filter(
462
+ const nonLanguageKeys = value != null && value.length ? value.filter(
459
463
  (item) => !contextLanguages.find((language) => item._key === language.id)
460
464
  ) : [];
461
465
  if (nonLanguageKeys.length)
@@ -463,10 +467,10 @@ var array = (config) => {
463
467
  message: "Array item keys must be valid languages registered to the field type",
464
468
  paths: nonLanguageKeys.map((item) => [{ _key: item._key }])
465
469
  };
466
- const valuesByLanguage = value?.length ? value.filter((item) => !!item?._key).reduce((acc, cur) => acc[cur._key] ? { ...acc, [cur._key]: [...acc[cur._key], cur] } : {
470
+ const valuesByLanguage = value != null && value.length ? value.filter((item) => !!(item != null && item._key)).reduce((acc, cur) => acc[cur._key] ? { ...acc, [cur._key]: [...acc[cur._key], cur] } : {
467
471
  ...acc,
468
472
  [cur._key]: [cur]
469
- }, {}) : {}, duplicateValues = Object.values(valuesByLanguage).filter((item) => item?.length > 1).flat();
473
+ }, {}) : {}, duplicateValues = Object.values(valuesByLanguage).filter((item) => (item == null ? void 0 : item.length) > 1).flat();
470
474
  return duplicateValues.length ? {
471
475
  message: "There can only be one field per language",
472
476
  paths: duplicateValues.map((item) => [{ _key: item._key }])
@@ -482,7 +486,7 @@ function InternationalizedField(props) {
482
486
  }) : props.children;
483
487
  }
484
488
  function getToneFromValidation(validations) {
485
- if (!validations?.length)
489
+ if (!(validations != null && validations.length))
486
490
  return;
487
491
  const validationLevels = validations.map((v) => v.level);
488
492
  if (validationLevels.includes("error"))
@@ -503,12 +507,16 @@ function InternationalizedInput(props) {
503
507
  // TODO: Remove this as it shouldn't be necessary?
504
508
  value: props.value
505
509
  }, { validation, value, onChange, readOnly } = inlineProps, { languages } = useInternationalizedArrayContext(), languageKeysInUse = useMemo(
506
- () => parentValue?.map((v) => v._key) ?? [],
510
+ () => {
511
+ var _a;
512
+ return (_a = parentValue == null ? void 0 : parentValue.map((v) => v._key)) != null ? _a : [];
513
+ },
507
514
  [parentValue]
508
- ), keyIsValid = languages?.length ? languages.find((l) => l.id === value._key) : !1, handleKeyChange = useCallback(
515
+ ), keyIsValid = languages != null && languages.length ? languages.find((l) => l.id === value._key) : !1, handleKeyChange = useCallback(
509
516
  (event) => {
510
- const languageId = event?.currentTarget?.value;
511
- !value || !languages?.length || !languages.find((l) => l.id === languageId) || onChange([set(languageId, ["_key"])]);
517
+ var _a;
518
+ const languageId = (_a = event == null ? void 0 : event.currentTarget) == null ? void 0 : _a.value;
519
+ !value || !(languages != null && languages.length) || !languages.find((l) => l.id === languageId) || onChange([set(languageId, ["_key"])]);
512
520
  },
513
521
  [onChange, value, languages]
514
522
  ), handleUnset = useCallback(() => {
@@ -556,9 +564,9 @@ var object = (config) => {
556
564
  title: `Internationalized array ${type}`,
557
565
  type: "object",
558
566
  components: {
559
- // @ts-expect-error - find out why it fails
560
567
  item: InternationalizedInput
561
568
  },
569
+ // @ts-expect-error - Address this typing issue with the inner object
562
570
  fields: [
563
571
  typeof type == "string" ? (
564
572
  // Define a simple field if all we have is the name as a string
@@ -644,13 +652,10 @@ const internationalizedArray = definePlugin((config) => {
644
652
  (field) => field.type.name
645
653
  ).some(
646
654
  (name) => name.startsWith("internationalizedArray")
647
- ) ? props.renderDefault(props) : /* @__PURE__ */ jsx(
648
- InternationalizedArrayProvider,
649
- {
650
- ...props,
651
- internationalizedArray: pluginConfig
652
- }
653
- )
655
+ ) ? props.renderDefault(props) : InternationalizedArrayProvider({
656
+ ...props,
657
+ internationalizedArray: pluginConfig
658
+ })
654
659
  }
655
660
  },
656
661
  // Register custom schema types for the outer array and the inner object