sanity-plugin-internationalized-array

5.3.35.3.4
dist/index.js.map
~dist/index.js.mapModified
+1−1
Index: package/dist/index.js.map
===================================================================
--- package/dist/index.js.map
+++ package/dist/index.js.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"index.js","names":["{apiVersion: internationalizedArray.apiVersion}","apiVersion","getSelectedValue(internationalizedArray.select, deferredDocument)","select","useMemo(\n    () => getSelectedValue(internationalizedArray.select, deferredDocument),\n    [internationalizedArray.select, deferredDocument],\n  )","useMemo(() => {\n    // Use workspace name if available, otherwise create a stable hash\n    if (workspace?.name) {\n      return workspace.name\n    }\n    // Create a stable hash from workspace properties that matter for caching\n    const workspaceKey = {\n      name: workspace?.name,\n      title: workspace?.title,\n      // Add other stable properties as needed\n    }\n    return JSON.stringify(workspaceKey)\n  }, [workspace])","JSON.stringify(workspaceKey)","workspace?.name","workspace?.title","createCacheKey(selectedValue, workspaceId)","useMemo(\n    () => createCacheKey(selectedValue, workspaceId),\n    [selectedValue, workspaceId],\n  )","useMemo(() => {\n    if (Array.isArray(internationalizedArray.languages)) {\n      return null // Return null for synchronous arrays\n    }\n\n    // Create or get cached promise for React.use\n    return createOrGetPromise(async () => {\n      if (typeof internationalizedArray.languages === 'function') {\n        const result = await internationalizedArray.languages(client, selectedValue)\n        // Populate function cache for use outside React context\n        setFunctionCache(internationalizedArray.languages, selectedValue, result, workspaceId)\n        return result\n      }\n      return internationalizedArray.languages\n    }, cacheKey)\n  }, [internationalizedArray, client, selectedValue, workspaceId, cacheKey])","async () => {\n      if (typeof internationalizedArray.languages === 'function') {\n        const result = await internationalizedArray.languages(client, selectedValue)\n        // Populate function cache for use outside React context\n        setFunctionCache(internationalizedArray.languages, selectedValue, result, workspaceId)\n        return result\n      }\n      return internationalizedArray.languages\n    }","internationalizedArray.languages","createOrGetPromise(async () => {\n      if (typeof internationalizedArray.languages === 'function') {\n        const result = await internationalizedArray.languages(client, selectedValue)\n        // Populate function cache for use outside React context\n        setFunctionCache(internationalizedArray.languages, selectedValue, result, workspaceId)\n        return result\n      }\n      return internationalizedArray.languages\n    }, cacheKey)","languageFilterOptions.documentTypes.includes(documentType)","documentTypes","languageFilterEnabled\n      ? languages.filter((language) => selectedLanguageIds.includes(language.id))\n      : languages","useMemo(() => {\n    const languageFilterEnabled = languageFilterOptions.documentTypes.includes(documentType)\n\n    return languageFilterEnabled\n      ? languages.filter((language) => selectedLanguageIds.includes(language.id))\n      : languages\n  }, [documentType, languageFilterOptions, languages, selectedLanguageIds])","{...internationalizedArray, languages, filteredLanguages}","useMemo(\n    () => ({...internationalizedArray, languages, filteredLanguages}),\n    [filteredLanguages, internationalizedArray, languages],\n  )","<InternationalizedArrayContext.Provider value={context}>\n      {props.children}\n    </InternationalizedArrayContext.Provider>","children","InternationalizedArrayContext.Provider","_c","languages.map((language) => {\n        const languageTitle: string = getLanguageDisplay(\n          languageDisplay,\n          language.title,\n          language.id,\n        )\n        return (\n          <Button\n            key={language.id}\n            tone=\"primary\"\n            mode=\"ghost\"\n            fontSize={1}\n            data-testid={`add-${language.id}`}\n            disabled={readOnly || languagesInUse.includes(language.id)}\n            text={languageTitle}\n            // Only show plus icon if there's one row or less AND only showing codes\n            icon={\n              languages.length > MAX_COLUMNS[languageDisplay] && languageDisplay === 'codeOnly'\n                ? undefined\n                : AddIcon\n            }\n            value={language.id}\n            onClick={() => handleClick(language.id)}\n          />\n        )\n      })","languages.length","(language) => {\n        const languageTitle: string = getLanguageDisplay(\n          languageDisplay,\n          language.title,\n          language.id,\n        )\n        return (\n          <Button\n            key={language.id}\n            tone=\"primary\"\n            mode=\"ghost\"\n            fontSize={1}\n            data-testid={`add-${language.id}`}\n            disabled={readOnly || languagesInUse.includes(language.id)}\n            text={languageTitle}\n            // Only show plus icon if there's one row or less AND only showing codes\n            icon={\n              languages.length > MAX_COLUMNS[languageDisplay] && languageDisplay === 'codeOnly'\n                ? undefined\n                : AddIcon\n            }\n            value={language.id}\n            onClick={() => handleClick(language.id)}\n          />\n        )\n      }","length","<Grid\n      gridTemplateColumns={Math.min(languages.length, MAX_COLUMNS[languageDisplay])}\n      gap={2}\n      data-testid=\"add-buttons-grid\"\n    >\n      {languages.map((language) => {\n        const languageTitle: string = getLanguageDisplay(\n          languageDisplay,\n          language.title,\n          language.id,\n        )\n        return (\n          <Button\n            key={language.id}\n            tone=\"primary\"\n            mode=\"ghost\"\n            fontSize={1}\n            data-testid={`add-${language.id}`}\n            disabled={readOnly || languagesInUse.includes(language.id)}\n            text={languageTitle}\n            // Only show plus icon if there's one row or less AND only showing codes\n            icon={\n              languages.length > MAX_COLUMNS[languageDisplay] && languageDisplay === 'codeOnly'\n                ? undefined\n                : AddIcon\n            }\n            value={language.id}\n            onClick={() => handleClick(language.id)}\n          />\n        )\n      })}\n    </Grid>","Math.min(languages.length, MAX_COLUMNS[languageDisplay])","_c","(typeName: string): unknown => {\n      if (!typeName) return undefined\n\n      // Extract the base type name from internationalized array type\n      // e.g., \"internationalizedArrayBodyValue\" -> \"body\"\n      const match = typeName.match(/^internationalizedArray(.+)Value$/)\n      if (!match || !match[1]) return undefined\n\n      const baseTypeName = match[1].charAt(0).toLowerCase() + match[1].slice(1)\n\n      // Check if it's a known array-based type (Portable Text fields)\n      const arrayBasedTypes = new Set(['body', 'htmlContent', 'blockContent', 'portableText'])\n      if (arrayBasedTypes.has(baseTypeName)) {\n        return []\n      }\n\n      // Try to look up the schema type to determine if it's an array\n      const schemaType = schema.get(typeName)\n      if (schemaType && 'fields' in schemaType) {\n        // Check if this is an object type with a 'value' field\n        // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n        const fields = schemaType.fields as Array<{\n          name: string\n          type?: {jsonType?: string; name?: string; type?: string; of?: unknown}\n        }>\n        const valueField = fields.find((f) => f.name === 'value')\n        if (valueField) {\n          const fieldType = valueField.type\n          // Check if the value field is an array type\n          if (\n            fieldType?.jsonType === 'array' ||\n            fieldType?.name === 'array' ||\n            fieldType?.type === 'array' ||\n            fieldType?.of !== undefined ||\n            (fieldType?.name && arrayBasedTypes.has(fieldType.name))\n          ) {\n            return []\n          }\n        }\n      }\n\n      return undefined\n    }","(f) => f.name === 'value'","useCallback(\n    (typeName: string): unknown => {\n      if (!typeName) return undefined\n\n      // Extract the base type name from internationalized array type\n      // e.g., \"internationalizedArrayBodyValue\" -> \"body\"\n      const match = typeName.match(/^internationalizedArray(.+)Value$/)\n      if (!match || !match[1]) return undefined\n\n      const baseTypeName = match[1].charAt(0).toLowerCase() + match[1].slice(1)\n\n      // Check if it's a known array-based type (Portable Text fields)\n      const arrayBasedTypes = new Set(['body', 'htmlContent', 'blockContent', 'portableText'])\n      if (arrayBasedTypes.has(baseTypeName)) {\n        return []\n      }\n\n      // Try to look up the schema type to determine if it's an array\n      const schemaType = schema.get(typeName)\n      if (schemaType && 'fields' in schemaType) {\n        // Check if this is an object type with a 'value' field\n        // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n        const fields = schemaType.fields as Array<{\n          name: string\n          type?: {jsonType?: string; name?: string; type?: string; of?: unknown}\n        }>\n        const valueField = fields.find((f) => f.name === 'value')\n        if (valueField) {\n          const fieldType = valueField.type\n          // Check if the value field is an array type\n          if (\n            fieldType?.jsonType === 'array' ||\n            fieldType?.name === 'array' ||\n            fieldType?.type === 'array' ||\n            fieldType?.of !== undefined ||\n            (fieldType?.name && arrayBasedTypes.has(fieldType.name))\n          ) {\n            return []\n          }\n        }\n      }\n\n      return undefined\n    },\n    [schema],\n  )","async (languageId: string) => {\n      const value = getFormValue([])\n      if (!isSanityDocument(value)) {\n        toast.push({\n          status: 'error',\n          title: 'No document value found',\n        })\n        return\n      }\n      const documentsToTranslation = getDocumentsToTranslate(value, [])\n\n      const alreadyTranslated = documentsToTranslation.filter(\n        (translation) => translation?.[LANGUAGE_FIELD_NAME] === languageId,\n      )\n      const removeDuplicates = documentsToTranslation.reduce<DocumentsToTranslate[]>(\n        (filteredTranslations, translation) => {\n          if (\n            alreadyTranslated.filter(\n              (alreadyTranslation) => alreadyTranslation.pathString === translation.pathString,\n            ).length > 0\n          ) {\n            return filteredTranslations\n          }\n          const translationAlreadyExists = filteredTranslations.filter(\n            (filteredTranslation) => filteredTranslation.path === translation.path,\n          )\n\n          if (translationAlreadyExists.length > 0) {\n            return filteredTranslations\n          }\n          filteredTranslations.push(translation)\n          return filteredTranslations\n        },\n        [],\n      )\n      if (removeDuplicates.length === 0) {\n        const language = filteredLanguages.find((l) => l.id === languageId)\n        toast.push({\n          status: 'warning',\n          title: `No missing translations for ${language?.title || languageId} found.`,\n        })\n        return\n      }\n\n      // Build patches for each field missing the selected language\n      const patches: (FormSetIfMissingPatch | FormInsertPatch)[] = []\n\n      for (const toTranslate of removeDuplicates) {\n        const path = toTranslate.path\n\n        const initialValue = getInitialValueForType(toTranslate._type)\n\n        const ifMissing = setIfMissing([], path)\n        const insertValue = insert(\n          [\n            {\n              _key: randomKey(),\n              [LANGUAGE_FIELD_NAME]: languageId,\n              _type: toTranslate._type,\n              value: initialValue,\n            },\n          ],\n          'after',\n          [...path, -1],\n        )\n        patches.push(ifMissing)\n        patches.push(insertValue)\n      }\n\n      onChange(PatchEvent.from(patches.flat()))\n    }","translation","useCallback(\n    async (languageId: string) => {\n      const value = getFormValue([])\n      if (!isSanityDocument(value)) {\n        toast.push({\n          status: 'error',\n          title: 'No document value found',\n        })\n        return\n      }\n      const documentsToTranslation = getDocumentsToTranslate(value, [])\n\n      const alreadyTranslated = documentsToTranslation.filter(\n        (translation) => translation?.[LANGUAGE_FIELD_NAME] === languageId,\n      )\n      const removeDuplicates = documentsToTranslation.reduce<DocumentsToTranslate[]>(\n        (filteredTranslations, translation) => {\n          if (\n            alreadyTranslated.filter(\n              (alreadyTranslation) => alreadyTranslation.pathString === translation.pathString,\n            ).length > 0\n          ) {\n            return filteredTranslations\n          }\n          const translationAlreadyExists = filteredTranslations.filter(\n            (filteredTranslation) => filteredTranslation.path === translation.path,\n          )\n\n          if (translationAlreadyExists.length > 0) {\n            return filteredTranslations\n          }\n          filteredTranslations.push(translation)\n          return filteredTranslations\n        },\n        [],\n      )\n      if (removeDuplicates.length === 0) {\n        const language = filteredLanguages.find((l) => l.id === languageId)\n        toast.push({\n          status: 'warning',\n          title: `No missing translations for ${language?.title || languageId} found.`,\n        })\n        return\n      }\n\n      // Build patches for each field missing the selected language\n      const patches: (FormSetIfMissingPatch | FormInsertPatch)[] = []\n\n      for (const toTranslate of removeDuplicates) {\n        const path = toTranslate.path\n\n        const initialValue = getInitialValueForType(toTranslate._type)\n\n        const ifMissing = setIfMissing([], path)\n        const insertValue = insert(\n          [\n            {\n              _key: randomKey(),\n              [LANGUAGE_FIELD_NAME]: languageId,\n              _type: toTranslate._type,\n              value: initialValue,\n            },\n          ],\n          'after',\n          [...path, -1],\n        )\n        patches.push(ifMissing)\n        patches.push(insertValue)\n      }\n\n      onChange(PatchEvent.from(patches.flat()))\n    },\n    [getInitialValueForType, onChange, toast, getFormValue, filteredLanguages],\n  )","<Box>\n        <Text size={1} weight=\"semibold\">\n          Add translation to internationalized fields\n        </Text>\n      </Box>","[]","<Stack gap={3} data-testid=\"document-add-buttons\">\n      <Box>\n        <Text size={1} weight=\"semibold\">\n          Add translation to internationalized fields\n        </Text>\n      </Box>\n      <AddButtons\n        readOnly={Boolean(formState?.readOnly)}\n        handleClick={handleDocumentButtonClick}\n        languagesInUse={[]}\n      />\n    </Stack>","Boolean(formState?.readOnly)","_c","_temp","<DocumentAddButtons />","props.renderDefault(props)","props.renderDefault","<Stack gap={5}>\n        <DocumentAddButtons />\n        {props.renderDefault(props)}\n      </Stack>","_c","props.renderDefault(props)","props.renderDefault","<InternationalizedArrayProvider\n        internationalizedArray={props.pluginConfig}\n        documentType={props.documentType}\n      >\n        {props.renderDefault(props)}\n      </InternationalizedArrayProvider>","documentType","pluginConfig","props.pluginConfig","props.documentType","_c","{apiVersion: props.apiVersion}","apiVersion","_c","{portal: true, placement: 'bottom-end'}","<Button\n            mode=\"bleed\"\n            tone=\"default\"\n            fontSize={1}\n            padding={2}\n            icon={TranslateIcon}\n            aria-label=\"Add translation\"\n            title=\"Add translation\"\n            data-testid=\"add-translation-menu\"\n            disabled={readOnly}\n          />","languages.map((language) => (\n              <MenuItem\n                key={language.id}\n                text={getLanguageDisplay(languageDisplay, language.title, language.id)}\n                icon={AddIcon}\n                disabled={readOnly || languagesInUse.includes(language.id)}\n                data-testid={`field-menu-add-${language.id}`}\n                onClick={() => handleClick(language.id)}\n              />\n            ))","(language) => (\n              <MenuItem\n                key={language.id}\n                text={getLanguageDisplay(languageDisplay, language.title, language.id)}\n                icon={AddIcon}\n                disabled={readOnly || languagesInUse.includes(language.id)}\n                data-testid={`field-menu-add-${language.id}`}\n                onClick={() => handleClick(language.id)}\n              />\n            )","buttonAddAll ? (\n              <>\n                <MenuDivider />\n                <MenuItem\n                  text={addAllTitle}\n                  icon={TranslateIcon}\n                  disabled={readOnly || allFilteredLanguagesArePresent}\n                  data-testid=\"field-menu-add-all\"\n                  onClick={onAddAll}\n                />\n              </>\n            ) : null","<Menu>\n            {languages.map((language) => (\n              <MenuItem\n                key={language.id}\n                text={getLanguageDisplay(languageDisplay, language.title, language.id)}\n                icon={AddIcon}\n                disabled={readOnly || languagesInUse.includes(language.id)}\n                data-testid={`field-menu-add-${language.id}`}\n                onClick={() => handleClick(language.id)}\n              />\n            ))}\n            {buttonAddAll ? (\n              <>\n                <MenuDivider />\n                <MenuItem\n                  text={addAllTitle}\n                  icon={TranslateIcon}\n                  disabled={readOnly || allFilteredLanguagesArePresent}\n                  data-testid=\"field-menu-add-all\"\n                  onClick={onAddAll}\n                />\n              </>\n            ) : null}\n          </Menu>","<Flex justify=\"flex-end\" data-testid=\"field-menu\">\n      <MenuButton\n        id={menuId}\n        popover={{portal: true, placement: 'bottom-end'}}\n        button={\n          <Button\n            mode=\"bleed\"\n            tone=\"default\"\n            fontSize={1}\n            padding={2}\n            icon={TranslateIcon}\n            aria-label=\"Add translation\"\n            title=\"Add translation\"\n            data-testid=\"add-translation-menu\"\n            disabled={readOnly}\n          />\n        }\n        menu={\n          <Menu>\n            {languages.map((language) => (\n              <MenuItem\n                key={language.id}\n                text={getLanguageDisplay(languageDisplay, language.title, language.id)}\n                icon={AddIcon}\n                disabled={readOnly || languagesInUse.includes(language.id)}\n                data-testid={`field-menu-add-${language.id}`}\n                onClick={() => handleClick(language.id)}\n              />\n            ))}\n            {buttonAddAll ? (\n              <>\n                <MenuDivider />\n                <MenuItem\n                  text={addAllTitle}\n                  icon={TranslateIcon}\n                  disabled={readOnly || allFilteredLanguagesArePresent}\n                  data-testid=\"field-menu-add-all\"\n                  onClick={onAddAll}\n                />\n              </>\n            ) : null}\n          </Menu>\n        }\n      />\n    </Flex>","_c","_Fragment","<code>internationalizedArray</code>","<code>id</code>","<Text>\n          An array of language objects must be passed into the <code>internationalizedArray</code>{' '}\n          helper function, each with an <code>id</code> and <code>title</code> field. Example:\n        </Text>","<Card tone=\"caution\" border radius={2} padding={3}>\n      <Stack gap={4}>\n        <Text>\n          An array of language objects must be passed into the <code>internationalizedArray</code>{' '}\n          helper function, each with an <code>id</code> and <code>title</code> field. Example:\n        </Text>\n        <Card padding={2} border radius={2}>\n          <Code size={1} language=\"javascript\">\n            {JSON.stringify(schemaExample, null, 2)}\n          </Code>\n        </Card>\n      </Stack>\n    </Card>","_c","{\n  itemsNeedingMigration,\n}: MigrationBannerProps","<Box>\n          <Text size={1}>\n            <WarningOutlineIcon />\n          </Text>\n        </Box>","<Text size={1} weight=\"semibold\">\n            Data migration required\n          </Text>","<Text size={1} muted>\n            {itemsNeedingMigration.length} item\n            {itemsNeedingMigration.length === 1 ? '' : 's'}{' '}\n            {itemsNeedingMigration.length === 1 ? 'needs' : 'need'} to be migrated to the v5 format.\n          </Text>","length","itemsNeedingMigration.length === 1 ? '' : 's'","itemsNeedingMigration.length === 1 ? 'needs' : 'need'","<code>_key</code>","<code>language</code>","<Box marginTop={2}>\n            <Text size={1}>\n              This field still uses the v4 format where language is stored in <code>_key</code>.\n              Migrate to the v5 format where language is stored in <code>language</code>.{' '}\n              <a\n                rel=\"noopener noreferrer\"\n                target=\"_blank\"\n                href=\"https://github.com/sanity-io/plugins/blob/main/plugins/sanity-plugin-internationalized-array/README.md#migrate-from-v4-to-v5\"\n              >\n                Learn more\n              </a>\n              .\n            </Text>\n          </Box>","<Card tone=\"caution\" padding={3} radius={2} border>\n      <Flex gap={3} align=\"center\">\n        <Box>\n          <Text size={1}>\n            <WarningOutlineIcon />\n          </Text>\n        </Box>\n        <Stack gap={2} flex={1}>\n          <Text size={1} weight=\"semibold\">\n            Data migration required\n          </Text>\n          <Text size={1} muted>\n            {itemsNeedingMigration.length} item\n            {itemsNeedingMigration.length === 1 ? '' : 's'}{' '}\n            {itemsNeedingMigration.length === 1 ? 'needs' : 'need'} to be migrated to the v5 format.\n          </Text>\n          <Box marginTop={2}>\n            <Text size={1}>\n              This field still uses the v4 format where language is stored in <code>_key</code>.\n              Migrate to the v5 format where language is stored in <code>language</code>.{' '}\n              <a\n                rel=\"noopener noreferrer\"\n                target=\"_blank\"\n                href=\"https://github.com/sanity-io/plugins/blob/main/plugins/sanity-plugin-internationalized-array/README.md#migrate-from-v4-to-v5\"\n              >\n                Learn more\n              </a>\n              .\n            </Text>\n          </Box>\n        </Stack>\n      </Flex>\n    </Card>","_c","value?.filter((v) => !v[LANGUAGE_FIELD_NAME]) ?? []","(v) => !v[LANGUAGE_FIELD_NAME]","value?.filter","['_type']","typeof documentType === 'string' && languageFilterOptions.documentTypes.includes(documentType)","languageFilterOptions.documentTypes","typeof documentType === 'string' && builtInLanguageFilter.documentTypes.includes(documentType)","builtInLanguageFilter.documentTypes","usingLanguageFilterPlugin || usingBuiltInLanguageFilter\n        ? members.filter((member) => {\n            // This member is the outer object created by the plugin\n            // Satisfy TS\n            if (member.kind !== 'item') {\n              return false\n            }\n\n            // This is the inner \"value\" field member created by this plugin\n            const valueMember = member.item.members[0]\n\n            // Satisfy TS\n            if (!valueMember || valueMember.kind !== 'field') {\n              return false\n            }\n            // The built-in filter receives the full languages list so it can\n            // surface fields with invalid language IDs rather than hiding them.\n            // The language filter plugin does not support this.\n            return usingBuiltInLanguageFilter\n              ? internationalizedArrayLanguageFilter(\n                  member.item.schemaType,\n                  valueMember,\n                  selectedLanguageIds,\n                  member.item.value,\n                  languages,\n                )\n              : languageFilterOptions.filterField(\n                  member.item.schemaType,\n                  valueMember,\n                  selectedLanguageIds,\n                  member.item.value,\n                )\n          })\n        : members","useMemo(\n    () =>\n      usingLanguageFilterPlugin || usingBuiltInLanguageFilter\n        ? members.filter((member) => {\n            // This member is the outer object created by the plugin\n            // Satisfy TS\n            if (member.kind !== 'item') {\n              return false\n            }\n\n            // This is the inner \"value\" field member created by this plugin\n            const valueMember = member.item.members[0]\n\n            // Satisfy TS\n            if (!valueMember || valueMember.kind !== 'field') {\n              return false\n            }\n            // The built-in filter receives the full languages list so it can\n            // surface fields with invalid language IDs rather than hiding them.\n            // The language filter plugin does not support this.\n            return usingBuiltInLanguageFilter\n              ? internationalizedArrayLanguageFilter(\n                  member.item.schemaType,\n                  valueMember,\n                  selectedLanguageIds,\n                  member.item.value,\n                  languages,\n                )\n              : languageFilterOptions.filterField(\n                  member.item.schemaType,\n                  valueMember,\n                  selectedLanguageIds,\n                  member.item.value,\n                )\n          })\n        : members,\n    [\n      usingLanguageFilterPlugin,\n      usingBuiltInLanguageFilter,\n      members,\n      selectedLanguageIds,\n      languages,\n      languageFilterOptions,\n    ],\n  )","(addLanguageKeys: string[] | string) => {\n      if (readOnly) {\n        return\n      }\n      // oxlint-disable-next-line typescript/no-unsafe-type-assertion\n      const formValue = getFormValue(props.path) as InternationalizedArrayItem[]\n      if (!filteredLanguages?.length) {\n        return\n      }\n\n      const patches = createAddLanguagePatches({\n        addLanguageKeys: Array.isArray(addLanguageKeys) ? addLanguageKeys : [addLanguageKeys],\n        schemaTypeName: schemaType.name,\n        languages,\n        filteredLanguages,\n        value: formValue,\n      })\n\n      onChange([setIfMissing([]), ...patches])\n    }","filteredLanguages?.length","path","schemaType.name","useCallback(\n    (addLanguageKeys: string[] | string) => {\n      if (readOnly) {\n        return\n      }\n      // oxlint-disable-next-line typescript/no-unsafe-type-assertion\n      const formValue = getFormValue(props.path) as InternationalizedArrayItem[]\n      if (!filteredLanguages?.length) {\n        return\n      }\n\n      const patches = createAddLanguagePatches({\n        addLanguageKeys: Array.isArray(addLanguageKeys) ? addLanguageKeys : [addLanguageKeys],\n        schemaTypeName: schemaType.name,\n        languages,\n        filteredLanguages,\n        value: formValue,\n      })\n\n      onChange([setIfMissing([]), ...patches])\n    },\n    [filteredLanguages, languages, onChange, schemaType, getFormValue, props.path, readOnly],\n  )","['_rev']","isPristineDocument(useContext(EventsContext))","useContext(EventsContext)","value\n    ?.map((v) => v[LANGUAGE_FIELD_NAME] ?? v._key)\n    .filter(Boolean)\n    .join(',')","(v) => v[LANGUAGE_FIELD_NAME] ?? v._key","value\n    ?.map","useMemo(() => {\n    const languageKeys = languageKeysFromValue?.split(',') || []\n    if (!languageKeys?.length) return []\n    if (!languages?.length) return []\n\n    return languages.filter((l) => languageKeys?.find((key) => key === l.id)).map((l) => l.id)\n  }, [languageKeysFromValue, languages])","languageKeysFromValue?.split","languages?.length","[]","(l) => l.id","() => {\n    const hasAddedDefaultLanguages = defaultLanguages\n      .filter((language) => languages.find((l) => l.id === language))\n      .every((language) => addedLanguages.includes(language))\n\n    if (\n      (isPristine || documentExists) &&\n      !isDeleting &&\n      !isDeleted &&\n      !hasAddedDefaultLanguages &&\n      !shouldMigrateArray &&\n      !readOnly\n    ) {\n      const languagesToAdd = defaultLanguages\n        .filter((language) => !addedLanguages.includes(language))\n        .filter((language) => languages.find((l) => l.id === language))\n      // Account for strict mode by scheduling the update.\n      const timeout = setTimeout(() => {\n        if (!readOnly) handleAddLanguages(languagesToAdd)\n      })\n      return () => clearTimeout(timeout)\n    }\n    return undefined\n  }","[\n    isPristine,\n    documentExists,\n    isDeleted,\n    isDeleting,\n    handleAddLanguages,\n    defaultLanguages,\n    addedLanguages,\n    languages,\n    readOnly,\n    shouldMigrateArray,\n  ]","l","language","() => {\n    if (readOnly || !value?.length || !languages?.length) {\n      return\n    }\n\n    // Create a new value array in the correct order\n    // This would also strip out values that don't have a language as the key\n    const updatedValue = value\n      .reduce((acc, v) => {\n        const newIndex = languages.findIndex((l) => l.id === v?.[LANGUAGE_FIELD_NAME])\n\n        if (newIndex > -1) {\n          acc[newIndex] = v\n        }\n\n        return acc\n      }, [] as InternationalizedArrayItem[])\n      .filter(Boolean)\n\n    if (value?.length !== updatedValue.length) {\n      toast.push({\n        title: 'There was an error reordering languages',\n        status: 'warning',\n      })\n    }\n\n    onChange(set(updatedValue))\n  }","value?.length","v","useCallback(() => {\n    if (readOnly || !value?.length || !languages?.length) {\n      return\n    }\n\n    // Create a new value array in the correct order\n    // This would also strip out values that don't have a language as the key\n    const updatedValue = value\n      .reduce((acc, v) => {\n        const newIndex = languages.findIndex((l) => l.id === v?.[LANGUAGE_FIELD_NAME])\n\n        if (newIndex > -1) {\n          acc[newIndex] = v\n        }\n\n        return acc\n      }, [] as InternationalizedArrayItem[])\n      .filter(Boolean)\n\n    if (value?.length !== updatedValue.length) {\n      toast.push({\n        title: 'There was an error reordering languages',\n        status: 'warning',\n      })\n    }\n\n    onChange(set(updatedValue))\n  }, [toast, languages, onChange, value, readOnly])","useMemo(() => {\n    if (!value?.length || !languages?.length) {\n      return true\n    }\n\n    return value?.every((v) => languages.find((l) => l?.id === v?.[LANGUAGE_FIELD_NAME]))\n  }, [value, languages])","value?.every((v) => languages.find((l) => l?.id === v?.[LANGUAGE_FIELD_NAME]))","value?.every","useMemo(() => {\n    if (!value?.length || !addedLanguages.length) {\n      return []\n    }\n\n    return value\n      .map((v, vIndex) =>\n        vIndex === addedLanguages.findIndex((language) => language === v[LANGUAGE_FIELD_NAME])\n          ? null\n          : v,\n      )\n      .filter(Boolean)\n  }, [value, addedLanguages])","value\n      .map((v, vIndex) =>\n        vIndex === addedLanguages.findIndex((language) => language === v[LANGUAGE_FIELD_NAME])\n          ? null\n          : v,\n      )\n      .filter(Boolean)","(v, vIndex) =>\n        vIndex === addedLanguages.findIndex((language) => language === v[LANGUAGE_FIELD_NAME])\n          ? null\n          : v","(item) => item.id && item.title","() => {\n    if (restoreOrder && languagesOutOfOrder.length > 0 && allKeysAreLanguages && !readOnly) {\n      handleRestoreOrder()\n    }\n  }","[restoreOrder, languagesOutOfOrder, allKeysAreLanguages, handleRestoreOrder, readOnly]","languagesOutOfOrder.length","filteredLanguages.every((language) => addedLanguages.includes(language.id))","(language) => addedLanguages.includes(language.id)","useMemo(\n    () => filteredLanguages.every((language) => addedLanguages.includes(language.id)),\n    [filteredLanguages, addedLanguages],\n  )","() => {\n    handleAddLanguages(filteredLanguages.map((language) => language.id))\n  }","(language) => language.id","useCallback(() => {\n    handleAddLanguages(filteredLanguages.map((language) => language.id))\n  }, [filteredLanguages, handleAddLanguages])","<Feedback />","canAddLanguages && buttonLocations.includes('fieldMenu')","canAddLanguages && buttonLocations.includes('field') && !allFilteredLanguagesArePresent","createAddAllTitle(value, filteredLanguages)","showFieldButtons ? (\n    <Stack gap={2}>\n      <AddButtons\n        languagesInUse={addedLanguages}\n        readOnly={readOnly}\n        handleClick={handleAddLanguages}\n      />\n      {buttonAddAll ? (\n        <Button\n          tone=\"primary\"\n          mode=\"ghost\"\n          data-testid=\"add-all-languages\"\n          disabled={readOnly || allFilteredLanguagesArePresent}\n          icon={AddIcon}\n          text={addAllTitle}\n          onClick={addAllMissingLanguages}\n        />\n      ) : null}\n    </Stack>\n  ) : null","showFieldMenu ? (\n        <CompactAddButton\n          languagesInUse={addedLanguages}\n          readOnly={readOnly}\n          handleClick={handleAddLanguages}\n          onAddAll={addAllMissingLanguages}\n          buttonAddAll={buttonAddAll}\n          addAllTitle={addAllTitle}\n          allFilteredLanguagesArePresent={allFilteredLanguagesArePresent}\n        />\n      ) : null","filteredMembers.map((member) => {\n        if (member.kind === 'item') {\n          return <ArrayOfObjectsItem {...props} key={member.key} member={member} />\n        }\n        return <MemberItemError key={member.key} member={member} />\n      })","(member) => {\n        if (member.kind === 'item') {\n          return <ArrayOfObjectsItem {...props} key={member.key} member={member} />\n        }\n        return <MemberItemError key={member.key} member={member} />\n      }","member","<MigrationBanner itemsNeedingMigration={itemsNeedingMigration} />","!showFieldMenu && !showFieldButtons && !fieldHasMembers ? (\n        <Card border tone=\"transparent\" padding={3} radius={2}>\n          <Text size={1}>This internationalized field currently has no translations.</Text>\n        </Card>\n      ) : null","<Stack gap={2}>\n      {showFieldMenu ? (\n        <CompactAddButton\n          languagesInUse={addedLanguages}\n          readOnly={readOnly}\n          handleClick={handleAddLanguages}\n          onAddAll={addAllMissingLanguages}\n          buttonAddAll={buttonAddAll}\n          addAllTitle={addAllTitle}\n          allFilteredLanguagesArePresent={allFilteredLanguagesArePresent}\n        />\n      ) : null}\n      {filteredMembers.map((member) => {\n        if (member.kind === 'item') {\n          return <ArrayOfObjectsItem {...props} key={member.key} member={member} />\n        }\n        return <MemberItemError key={member.key} member={member} />\n      })}\n      <MigrationBanner itemsNeedingMigration={itemsNeedingMigration} />\n\n      {/* Give some feedback in the UI so the field doesn't look \"missing\" */}\n      {!showFieldMenu && !showFieldButtons && !fieldHasMembers ? (\n        <Card border tone=\"transparent\" padding={3} radius={2}>\n          <Text size={1}>This internationalized field currently has no translations.</Text>\n        </Card>\n      ) : null}\n\n      {fieldButtons}\n    </Stack>","_c","_temp","_temp2","_temp3","_temp4","path.slice(0, -1)","parentValue?.map((v) => v[LANGUAGE_FIELD_NAME]) ?? []","(v) => v[LANGUAGE_FIELD_NAME]","parentValue?.map","useMemo(\n    () => parentValue?.map((v) => v[LANGUAGE_FIELD_NAME]) ?? [],\n    [parentValue],\n  )","(event: React.MouseEvent<HTMLButtonElement>): void => {\n    const languageId = event?.currentTarget?.value\n\n    if (!value || !languages?.length || !languages.find((l) => l.id === languageId)) {\n      return\n    }\n\n    onChange([set(languageId, [LANGUAGE_FIELD_NAME])])\n  }","languages?.length","<Button fontSize={1} text={`Change \"${value[LANGUAGE_FIELD_NAME]}\"`} />","`Change \"${value[LANGUAGE_FIELD_NAME]}\"`","languages.map((lang) => (\n            <MenuItem\n              disabled={languageKeysInUse.includes(lang.id)}\n              fontSize={1}\n              key={lang.id}\n              text={lang.id.toLocaleUpperCase()}\n              value={lang.id}\n              onClick={handleKeyChange}\n            />\n          ))","(lang) => (\n            <MenuItem\n              disabled={languageKeysInUse.includes(lang.id)}\n              fontSize={1}\n              key={lang.id}\n              text={lang.id.toLocaleUpperCase()}\n              value={lang.id}\n              onClick={handleKeyChange}\n            />\n          )","<Menu>\n          {languages.map((lang) => (\n            <MenuItem\n              disabled={languageKeysInUse.includes(lang.id)}\n              fontSize={1}\n              key={lang.id}\n              text={lang.id.toLocaleUpperCase()}\n              value={lang.id}\n              onClick={handleKeyChange}\n            />\n          ))}\n        </Menu>","{portal: true}","<MenuButton\n      button={<Button fontSize={1} text={`Change \"${value[LANGUAGE_FIELD_NAME]}\"`} />}\n      id={`${value[LANGUAGE_FIELD_NAME]}-change-key`}\n      menu={\n        <Menu>\n          {languages.map((lang) => (\n            <MenuItem\n              disabled={languageKeysInUse.includes(lang.id)}\n              fontSize={1}\n              key={lang.id}\n              text={lang.id.toLocaleUpperCase()}\n              value={lang.id}\n              onClick={handleKeyChange}\n            />\n          ))}\n        </Menu>\n      }\n      popover={{portal: true}}\n    />","`${value[LANGUAGE_FIELD_NAME]}-change-key`","{\n  isDefault,\n  readOnly,\n  onChange,\n}: {\n  isDefault: boolean\n  readOnly: boolean\n  onChange: (patch: FormPatch[] | PatchEvent | FormPatch) => void\n}","(): void => {\n    onChange(unset())\n  }","<Text muted size={1}>\n          Can&apos;t remove default language\n        </Text>","['right', 'left']","{paddingBottom: '2px'}","<span style={{paddingBottom: '2px'}}>\n        <Button\n          mode=\"bleed\"\n          icon={RemoveCircleIcon}\n          tone=\"critical\"\n          disabled={readOnly || isDefault}\n          onClick={handleUnset}\n        />\n      </span>","readOnly || isDefault","<Tooltip\n      animate\n      disabled={!isDefault}\n      content={\n        <Text muted size={1}>\n          Can&apos;t remove default language\n        </Text>\n      }\n      fallbackPlacements={['right', 'left']}\n      placement=\"top\"\n      portal\n    >\n      <span style={{paddingBottom: '2px'}}>\n        <Button\n          mode=\"bleed\"\n          icon={RemoveCircleIcon}\n          tone=\"critical\"\n          disabled={readOnly || isDefault}\n          onClick={handleUnset}\n        />\n      </span>\n    </Tooltip>","!isDefault","(patches: unknown) => {\n      // Ensure patches is an array before proceeding with paste logic\n      // For single patch operations (like unset), pass through directly\n      if (!Array.isArray(patches)) {\n        // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n        return originalOnChange(patches as Parameters<typeof originalOnChange>[0])\n      }\n\n      // Check if this is a paste operation into an empty or uninitialized Portable Text field\n      const valueField = props.value?.value\n      const isEmptyOrUndefined =\n        valueField === undefined ||\n        valueField === null ||\n        (Array.isArray(valueField) && valueField.length === 0)\n\n      if (isEmptyOrUndefined) {\n        // Check for insert patches that are trying to operate on a non-existent structure\n        const hasProblematicInsert = patches.some((patch: {type?: string; path?: unknown[]}) => {\n          // Ensure patch exists and has required properties\n          if (!patch || typeof patch !== 'object') {\n            return false\n          }\n\n          // Look for insert patches targeting the value field or direct array index\n          if (\n            patch.type === 'insert' &&\n            patch.path &&\n            Array.isArray(patch.path) &&\n            patch.path.length > 0\n          ) {\n            // The path might be ['value', index] or just [index] depending on context\n            const isTargetingValue = patch.path[0] === 'value' || typeof patch.path[0] === 'number'\n            return isTargetingValue\n          }\n          return false\n        })\n\n        if (hasProblematicInsert) {\n          // First, ensure the value field exists as an empty array if it doesn't\n          const initPatch =\n            valueField === undefined ? {type: 'setIfMissing', path: ['value'], value: []} : null\n\n          // Transform the patches to ensure they work with the nested structure\n          const fixedPatches = patches.map(\n            (patch: {type?: string; path?: unknown[]; [key: string]: unknown}) => {\n              // Ensure patch exists and has required properties\n              if (!patch || typeof patch !== 'object') {\n                return patch\n              }\n\n              if (patch.type === 'insert' && patch.path && Array.isArray(patch.path)) {\n                // Ensure the path is correct for the nested structure\n                const fixedPath = patch.path[0] === 'value' ? patch.path : ['value', ...patch.path]\n                const fixedPatch = {...patch, path: fixedPath}\n                return fixedPatch\n              }\n              return patch\n            },\n          )\n\n          // If we need to initialize the field, include that patch first\n          const allPatches = initPatch ? [initPatch, ...fixedPatches] : fixedPatches\n\n          // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n          return originalOnChange(allPatches as Parameters<typeof originalOnChange>[0])\n        }\n      }\n\n      // For all other cases, pass through unchanged\n      return originalOnChange(patches as Parameters<typeof originalOnChange>[0])\n    }","value","(patch: {type?: string; path?: unknown[]}) => {\n          // Ensure patch exists and has required properties\n          if (!patch || typeof patch !== 'object') {\n            return false\n          }\n\n          // Look for insert patches targeting the value field or direct array index\n          if (\n            patch.type === 'insert' &&\n            patch.path &&\n            Array.isArray(patch.path) &&\n            patch.path.length > 0\n          ) {\n            // The path might be ['value', index] or just [index] depending on context\n            const isTargetingValue = patch.path[0] === 'value' || typeof patch.path[0] === 'number'\n            return isTargetingValue\n          }\n          return false\n        }","(patch: {type?: string; path?: unknown[]; [key: string]: unknown}) => {\n              // Ensure patch exists and has required properties\n              if (!patch || typeof patch !== 'object') {\n                return patch\n              }\n\n              if (patch.type === 'insert' && patch.path && Array.isArray(patch.path)) {\n                // Ensure the path is correct for the nested structure\n                const fixedPath = patch.path[0] === 'value' ? patch.path : ['value', ...patch.path]\n                const fixedPatch = {...patch, path: fixedPath}\n                return fixedPatch\n              }\n              return patch\n            }","useCallback(\n    (patches: unknown) => {\n      // Ensure patches is an array before proceeding with paste logic\n      // For single patch operations (like unset), pass through directly\n      if (!Array.isArray(patches)) {\n        // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n        return originalOnChange(patches as Parameters<typeof originalOnChange>[0])\n      }\n\n      // Check if this is a paste operation into an empty or uninitialized Portable Text field\n      const valueField = props.value?.value\n      const isEmptyOrUndefined =\n        valueField === undefined ||\n        valueField === null ||\n        (Array.isArray(valueField) && valueField.length === 0)\n\n      if (isEmptyOrUndefined) {\n        // Check for insert patches that are trying to operate on a non-existent structure\n        const hasProblematicInsert = patches.some((patch: {type?: string; path?: unknown[]}) => {\n          // Ensure patch exists and has required properties\n          if (!patch || typeof patch !== 'object') {\n            return false\n          }\n\n          // Look for insert patches targeting the value field or direct array index\n          if (\n            patch.type === 'insert' &&\n            patch.path &&\n            Array.isArray(patch.path) &&\n            patch.path.length > 0\n          ) {\n            // The path might be ['value', index] or just [index] depending on context\n            const isTargetingValue = patch.path[0] === 'value' || typeof patch.path[0] === 'number'\n            return isTargetingValue\n          }\n          return false\n        })\n\n        if (hasProblematicInsert) {\n          // First, ensure the value field exists as an empty array if it doesn't\n          const initPatch =\n            valueField === undefined ? {type: 'setIfMissing', path: ['value'], value: []} : null\n\n          // Transform the patches to ensure they work with the nested structure\n          const fixedPatches = patches.map(\n            (patch: {type?: string; path?: unknown[]; [key: string]: unknown}) => {\n              // Ensure patch exists and has required properties\n              if (!patch || typeof patch !== 'object') {\n                return patch\n              }\n\n              if (patch.type === 'insert' && patch.path && Array.isArray(patch.path)) {\n                // Ensure the path is correct for the nested structure\n                const fixedPath = patch.path[0] === 'value' ? patch.path : ['value', ...patch.path]\n                const fixedPatch = {...patch, path: fixedPath}\n                return fixedPatch\n              }\n              return patch\n            },\n          )\n\n          // If we need to initialize the field, include that patch first\n          const allPatches = initPatch ? [initPatch, ...fixedPatches] : fixedPatches\n\n          // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n          return originalOnChange(allPatches as Parameters<typeof originalOnChange>[0])\n        }\n      }\n\n      // For all other cases, pass through unchanged\n      return originalOnChange(patches as Parameters<typeof originalOnChange>[0])\n    },\n    [originalOnChange, props.value?.value],\n  )","languages?.length\n    ? Boolean(languages.find((l) => l.id === props.value[LANGUAGE_FIELD_NAME]))\n    : false","keyIsValid && language ? getLanguageDisplay(languageDisplay, language.title, language.id) : ''","languages?.find","l","props.inputProps.members\n        .filter((m) => m.kind === 'field' && m.name === 'value')\n        .map((member) => {\n          if (member.kind !== 'field') {\n            return member\n          }\n\n          const field = member.field\n          const schemaType = field?.schemaType\n          const itemNeedsMigration = !props.value[LANGUAGE_FIELD_NAME]\n\n          const title = itemNeedsMigration ? null : keyIsValid ? (\n            <Label muted size={1}>\n              {languageTitle}\n            </Label>\n          ) : (\n            <ChangeLanguageButton\n              value={props.value}\n              path={props.path}\n              onChange={originalOnChange}\n            />\n          )\n\n          return Object.assign({}, member, {\n            field: Object.assign({}, field, {\n              schemaType: Object.assign({}, schemaType, {title}),\n            }),\n          })\n        })","members","path","(member) => {\n          if (member.kind !== 'field') {\n            return member\n          }\n\n          const field = member.field\n          const schemaType = field?.schemaType\n          const itemNeedsMigration = !props.value[LANGUAGE_FIELD_NAME]\n\n          const title = itemNeedsMigration ? null : keyIsValid ? (\n            <Label muted size={1}>\n              {languageTitle}\n            </Label>\n          ) : (\n            <ChangeLanguageButton\n              value={props.value}\n              path={props.path}\n              onChange={originalOnChange}\n            />\n          )\n\n          return Object.assign({}, member, {\n            field: Object.assign({}, field, {\n              schemaType: Object.assign({}, schemaType, {title}),\n            }),\n          })\n        }","(m) => m.kind === 'field' && m.name === 'value'","{\n      ...props.inputProps,\n      members: props.inputProps.members\n        .filter((m) => m.kind === 'field' && m.name === 'value')\n        .map((member) => {\n          if (member.kind !== 'field') {\n            return member\n          }\n\n          const field = member.field\n          const schemaType = field?.schemaType\n          const itemNeedsMigration = !props.value[LANGUAGE_FIELD_NAME]\n\n          const title = itemNeedsMigration ? null : keyIsValid ? (\n            <Label muted size={1}>\n              {languageTitle}\n            </Label>\n          ) : (\n            <ChangeLanguageButton\n              value={props.value}\n              path={props.path}\n              onChange={originalOnChange}\n            />\n          )\n\n          return Object.assign({}, member, {\n            field: Object.assign({}, field, {\n              schemaType: Object.assign({}, schemaType, {title}),\n            }),\n          })\n        }),\n      value: props.value,\n      // Use our wrapped onChange handler\n      onChange: wrappedOnChange,\n    }","inputProps","props.inputProps","useMemo(\n    () => ({\n      ...props.inputProps,\n      members: props.inputProps.members\n        .filter((m) => m.kind === 'field' && m.name === 'value')\n        .map((member) => {\n          if (member.kind !== 'field') {\n            return member\n          }\n\n          const field = member.field\n          const schemaType = field?.schemaType\n          const itemNeedsMigration = !props.value[LANGUAGE_FIELD_NAME]\n\n          const title = itemNeedsMigration ? null : keyIsValid ? (\n            <Label muted size={1}>\n              {languageTitle}\n            </Label>\n          ) : (\n            <ChangeLanguageButton\n              value={props.value}\n              path={props.path}\n              onChange={originalOnChange}\n            />\n          )\n\n          return Object.assign({}, member, {\n            field: Object.assign({}, field, {\n              schemaType: Object.assign({}, schemaType, {title}),\n            }),\n          })\n        }),\n      value: props.value,\n      // Use our wrapped onChange handler\n      onChange: wrappedOnChange,\n    }),\n    [\n      props.inputProps,\n      props.value,\n      wrappedOnChange,\n      languageTitle,\n      keyIsValid,\n      originalOnChange,\n      props.path,\n    ],\n  )","<Spinner />","defaultLanguages.includes(value[LANGUAGE_FIELD_NAME])","getToneFromValidation(validation)","props.inputProps.renderInput(inlineProps)","<Box flex={1}>{props.inputProps.renderInput(inlineProps)}</Box>","<RemoveButton\n          isDefault={isDefault}\n          readOnly={Boolean(readOnly)}\n          onChange={originalOnChange}\n        />","Boolean(readOnly)","<Flex align=\"flex-end\" gap={2}>\n        <Box flex={1}>{props.inputProps.renderInput(inlineProps)}</Box>\n        <RemoveButton\n          isDefault={isDefault}\n          readOnly={Boolean(readOnly)}\n          onChange={originalOnChange}\n        />\n      </Flex>","<Card paddingTop={2} tone={getToneFromValidation(validation)}>\n      <Flex align=\"flex-end\" gap={2}>\n        <Box flex={1}>{props.inputProps.renderInput(inlineProps)}</Box>\n        <RemoveButton\n          isDefault={isDefault}\n          readOnly={Boolean(readOnly)}\n          onChange={originalOnChange}\n        />\n      </Flex>\n    </Card>","patch","_c","_Fragment","array","object","\"language\"","\"_key\""],"sources":["../src/cache.ts","../src/constants.ts","../src/utils/getDocumentsToTranslate.ts","../src/utils/getLanguageDisplay.ts","../src/components/getSelectedValue.ts","../src/components/InternationalizedArrayContext.tsx","../src/components/AddButtons.tsx","../src/components/DocumentAddButtons.tsx","../src/components/InternationalizedArrayFormInput.tsx","../src/utils/hasInternationalizedArrayField.ts","../src/components/InternationalizedArrayLayout.tsx","../src/components/Preload.tsx","../src/utils/checkAllLanguagesArePresent.ts","../src/utils/createAddAllTitle.ts","../src/types.ts","../src/utils/createAddLanguagePatches.ts","../src/fieldActions/index.ts","../src/components/createFieldName.ts","../src/utils/internationalizedArrayLanguageFilter.ts","../src/components/CompactAddButton.tsx","../src/components/Feedback.tsx","../src/components/MigrationBanner.tsx","../src/components/InternationalizedArray.tsx","../src/utils/getLanguagesFieldOption.ts","../src/schema/array.ts","../src/components/getToneFromValidation.ts","../src/components/InternationalizedInput.tsx","../src/schema/object.ts","../src/plugin.tsx"],"sourcesContent":["import type {Language, LanguageCallback} from './types'\n\nconst namespace = 'sanity-plugin-internationalized-array'\n\nconst version = 'v1'\n\n// Cache for function keys to avoid recalculating them\nconst functionKeyCache = new WeakMap<LanguageCallback, string>()\n\n// Cache for React.use promises\nconst promiseCache = new Map<string, Promise<Language[]>>()\n\n// Cache for function references to enable sharing between same functions\nconst functionCache = new Map<string, Language[]>()\n\n// Helper to create a cache key string from an array\nfunction stringifyCacheKey(key: unknown[]): string {\n  return JSON.stringify(key)\n}\n\n// Enhanced preload function that can use custom cache keys\nexport const preloadWithKey = (fn: () => Promise<Language[]>, key: (string | number)[]) => {\n  const keyStr = stringifyCacheKey(key)\n  if (!promiseCache.has(keyStr)) {\n    promiseCache.set(keyStr, fn())\n  }\n}\n\n// Cache busting: clear all promise caches\nexport const clear = () => {\n  promiseCache.clear()\n}\n\n// Peeking into entries outside of suspense\nexport const peek = (selectedValue: Record<string, unknown>) => {\n  const key = stringifyCacheKey([version, namespace, selectedValue])\n  const promise = promiseCache.get(key)\n  if (promise) {\n    // Check if promise is resolved\n    // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n    const status = (promise as any)._status\n    if (status === 'fulfilled') {\n      // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n      return (promise as any)._value as Language[] | undefined\n    }\n  }\n  return undefined\n}\n\n// Helper function to create a stable cache key that matches the component's key structure\nexport const createCacheKey = (selectedValue: Record<string, unknown>, workspaceId?: string) => {\n  const selectedValueHash = JSON.stringify(selectedValue)\n  return workspaceId\n    ? [version, namespace, selectedValueHash, workspaceId]\n    : [version, namespace, selectedValueHash]\n}\n\n// Create or get cached promise for React.use\nexport const createOrGetPromise = (\n  fn: () => Promise<Language[]>,\n  key: (string | number | Record<string, unknown>)[],\n): Promise<Language[]> => {\n  const keyStr = stringifyCacheKey(key)\n  if (promiseCache.has(keyStr)) {\n    return promiseCache.get(keyStr)!\n  }\n  const promise = fn()\n  promiseCache.set(keyStr, promise)\n  return promise\n}\n\n// Generate a unique key for a function reference (cached for performance)\nconst getFunctionKey = (fn: LanguageCallback): string => {\n  // Check if we already have a cached key for this function\n  const cachedKey = functionKeyCache.get(fn)\n  if (cachedKey) {\n    return cachedKey\n  }\n\n  // Create a hash for functions (only when needed)\n  const fnStr = fn.toString()\n  let hash = 0\n  // Only hash the first 100 characters for performance\n  const maxLength = Math.min(fnStr.length, 100)\n  for (let i = 0; i < maxLength; i++) {\n    const char = fnStr.charCodeAt(i)\n    hash = (hash << 5) - hash + char\n    hash &= hash // Convert to 32-bit integer\n  }\n  const key = `anonymous_${Math.abs(hash)}`\n  functionKeyCache.set(fn, key)\n  return key\n}\n\n// Create a cache key that includes function identity\nconst createFunctionCacheKey = (\n  fn: LanguageCallback,\n  selectedValue: Record<string, unknown>,\n  workspaceId?: string,\n): string => {\n  const functionKey = getFunctionKey(fn)\n  const selectedValueHash = JSON.stringify(selectedValue)\n  return workspaceId\n    ? `${functionKey}:${selectedValueHash}:${workspaceId}`\n    : `${functionKey}:${selectedValueHash}`\n}\n\n// Function-aware cache operations\nexport const getFunctionCache = (\n  fn: LanguageCallback,\n  selectedValue: Record<string, unknown>,\n  workspaceId?: string,\n): Language[] | undefined => {\n  const key = createFunctionCacheKey(fn, selectedValue, workspaceId)\n  return functionCache.get(key)\n}\n\nexport const setFunctionCache = (\n  fn: LanguageCallback,\n  selectedValue: Record<string, unknown>,\n  languages: Language[],\n  workspaceId?: string,\n): void => {\n  const key = createFunctionCacheKey(fn, selectedValue, workspaceId)\n  functionCache.set(key, languages)\n}\n","import type {PluginConfig} from './types'\n\n/**\n * The field name used to identify the language of an internationalized array item.\n *\n * In v4.x this was '_key', in v5+ this is 'language'.\n * ```ts\n * {\n *    \"description\": [\n *      {\n *        \"_key\": \"kjjNvZHK8Y2QpTEf3K5jc\",\n *        \"_type\": \"internationalizedArrayTextValue\",\n *        \"language\": \"en\"\n *        \"value\": \"This is the description in English\"\n *      },\n *      {\n *        \"_key\": \"kjjNvZHK8Y2QpTEf3K5jc\",\n *        \"_type\": \"internationalizedArrayTextValue\",\n *        \"language\": \"es\"\n *        \"value\": \"This is the description in Spanish\"\n *      },\n *    ]\n * }\n * ```\n */\nexport const LANGUAGE_FIELD_NAME = 'language' as const\n\nexport const MAX_COLUMNS = {\n  codeOnly: 5,\n  titleOnly: 4,\n  titleAndCode: 3,\n}\n\nexport const CONFIG_DEFAULT: Required<PluginConfig> = {\n  languages: [],\n  select: {},\n  defaultLanguages: [],\n  fieldTypes: [],\n  apiVersion: '2025-10-15',\n  buttonLocations: ['field'],\n  buttonAddAll: true,\n  restoreOrder: true,\n  languageDisplay: 'codeOnly',\n  includeForDocumentType: (documentType) => documentType !== 'translation.metadata',\n  languageFilter: {\n    documentTypes: [],\n  },\n}\n","import type {SanityDocument} from 'sanity'\n\nexport interface DocumentsToTranslate {\n  path: (string | number)[]\n  pathString: string\n  _key: string\n  /** Language identifier (e.g., 'en', 'fr'). Added in v5. */\n  language: string\n  _type: string\n  [key: string]: unknown\n}\n\n/**\n * Recursively traverses a Sanity document (or any nested value) and collects\n * all internationalized array items found within it.\n *\n * An item is considered an internationalized array value when its `_type`\n * starts with `\"internationalizedArray\"` and ends with `\"Value\"`.\n *\n * The function walks through objects and arrays, skipping keys that start\n * with `_` (internal Sanity fields like `_id`, `_type`, `_rev`). Each\n * returned item includes the original properties plus `path` (array of\n * segments) and `pathString` (dot-joined) indicating where it was found.\n */\nexport const getDocumentsToTranslate = (\n  // oxlint-disable-next-line typescript-eslint/no-redundant-type-constituents\n  value: SanityDocument | unknown,\n  rootPath: (string | number)[] = [],\n): DocumentsToTranslate[] => {\n  if (Array.isArray(value)) {\n    const arrayRootPath = [...rootPath]\n\n    // if item contains internationalized return array\n    const internationalizedValues = value.filter((item) => {\n      if (Array.isArray(item)) return false\n\n      if (typeof item === 'object') {\n        // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n        const type = item?._type as string | undefined\n        return type?.startsWith('internationalizedArray') && type?.endsWith('Value')\n      }\n      return false\n    })\n\n    if (internationalizedValues.length > 0) {\n      return internationalizedValues.map((internationalizedValue) => {\n        return Object.assign({}, internationalizedValue, {\n          path: arrayRootPath,\n          pathString: arrayRootPath.join('.'),\n        })\n      })\n    }\n\n    if (value.length > 0) {\n      return value.flatMap((item, index) =>\n        getDocumentsToTranslate(item, [...arrayRootPath, index]),\n      )\n    }\n\n    return []\n  }\n  if (typeof value === 'object' && value) {\n    const startsWithUnderscoreRegex = /^_/\n    const itemKeys = Object.keys(value).filter(\n      (key) => !key.match(startsWithUnderscoreRegex),\n      // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n    ) as (keyof typeof value)[]\n\n    return itemKeys.flatMap((item) => {\n      const selectedValue = value[item] as unknown\n      const path = [...rootPath, item]\n      return getDocumentsToTranslate(selectedValue, path)\n    })\n  }\n  return []\n}\n","import type {LanguageDisplay} from '../types'\n\n/**\n * Formats a language label for display in buttons and field headers\n * based on the configured `languageDisplay` mode:\n *\n * - `'codeOnly'`      -> uppercase code, e.g. `\"EN\"`\n * - `'titleOnly'`     -> title as-is, e.g. `\"English\"`\n * - `'titleAndCode'`  -> title with uppercase code, e.g. `\"English (EN)\"`\n *\n * Falls back to `title` for any unrecognized display mode.\n */\nexport function getLanguageDisplay(\n  languageDisplay: LanguageDisplay,\n  title: string,\n  code: string,\n): string {\n  if (languageDisplay === 'codeOnly') return code.toUpperCase()\n  if (languageDisplay === 'titleOnly') return title\n  if (languageDisplay === 'titleAndCode') return `${title} (${code.toUpperCase()})`\n  return title\n}\n","import get from 'lodash-es/get.js'\n\n/**\n * Extracts a subset of values from a Sanity document based on a `select`\n * mapping (as configured in the plugin's `select` option).\n *\n * Each key in `select` becomes a key in the returned object, with its value\n * resolved from the document using the corresponding dot-path (via lodash `get`).\n *\n * Array values are filtered to remove incomplete references (objects with\n * `_type: 'reference'` but no `_ref`), since those represent empty reference\n * fields that should be ignored.\n *\n * Returns an empty object when either `select` or `document` is undefined.\n */\nexport const getSelectedValue = (\n  select: Record<string, string> | undefined,\n  document:\n    | {\n        [x: string]: unknown\n      }\n    | undefined,\n): Record<string, unknown> => {\n  if (!select || !document) {\n    return {}\n  }\n\n  const selection: Record<string, string> = select || {}\n  const selectedValue: Record<string, unknown> = {}\n  for (const [key, path] of Object.entries(selection)) {\n    let value = get(document, path)\n    if (Array.isArray(value)) {\n      // If there are references in the array, ensure they have `_ref` set, otherwise they are considered empty and can safely be ignored\n      value = value.filter((item) =>\n        typeof item === 'object' ? item?._type === 'reference' && '_ref' in item : true,\n      )\n    }\n    selectedValue[key] = value\n  }\n\n  return selectedValue\n}\n","import {useLanguageFilterStudioContext} from '@sanity/language-filter'\nimport type React from 'react'\nimport {createContext, use, useContext, useDeferredValue, useMemo} from 'react'\nimport {useClient, useWorkspace} from 'sanity'\nimport {useDocumentPane} from 'sanity/structure'\n\nimport {createCacheKey, createOrGetPromise, setFunctionCache} from '../cache'\nimport {CONFIG_DEFAULT} from '../constants'\nimport type {Language, PluginConfig} from '../types'\nimport {getSelectedValue} from './getSelectedValue'\n\n// This provider makes the plugin config available to all components in the document form\n// But with languages resolved and filtered languages updated base on @sanity/language-filter\n\nexport type InternationalizedArrayContextProps = Required<PluginConfig> & {\n  languages: Language[]\n  filteredLanguages: Language[]\n}\n\nconst InternationalizedArrayContext = createContext<InternationalizedArrayContextProps>({\n  ...CONFIG_DEFAULT,\n  languages: [],\n  filteredLanguages: [],\n})\n\nexport function useInternationalizedArrayContext(): InternationalizedArrayContextProps {\n  return useContext(InternationalizedArrayContext)\n}\n\ntype InternationalizedArrayProviderProps = {\n  internationalizedArray: Required<PluginConfig>\n  documentType: string\n}\n\nexport function InternationalizedArrayProvider(\n  props: React.PropsWithChildren<InternationalizedArrayProviderProps>,\n): React.ReactElement {\n  const {internationalizedArray, documentType} = props\n\n  const client = useClient({apiVersion: internationalizedArray.apiVersion})\n  const workspace = useWorkspace()\n  const {formState} = useDocumentPane()\n  const deferredDocument = useDeferredValue(formState?.value)\n  const selectedValue = useMemo(\n    () => getSelectedValue(internationalizedArray.select, deferredDocument),\n    [internationalizedArray.select, deferredDocument],\n  )\n\n  // Use a stable workspace identifier to prevent unnecessary re-renders\n  const workspaceId = useMemo(() => {\n    // Use workspace name if available, otherwise create a stable hash\n    if (workspace?.name) {\n      return workspace.name\n    }\n    // Create a stable hash from workspace properties that matter for caching\n    const workspaceKey = {\n      name: workspace?.name,\n      title: workspace?.title,\n      // Add other stable properties as needed\n    }\n    return JSON.stringify(workspaceKey)\n  }, [workspace])\n\n  // Memoize the cache key to prevent expensive JSON.stringify calls\n  const cacheKey = useMemo(\n    () => createCacheKey(selectedValue, workspaceId),\n    [selectedValue, workspaceId],\n  )\n\n  // Fetch or return languages\n  const languagesPromise = useMemo(() => {\n    if (Array.isArray(internationalizedArray.languages)) {\n      return null // Return null for synchronous arrays\n    }\n\n    // Create or get cached promise for React.use\n    return createOrGetPromise(async () => {\n      if (typeof internationalizedArray.languages === 'function') {\n        const result = await internationalizedArray.languages(client, selectedValue)\n        // Populate function cache for use outside React context\n        setFunctionCache(internationalizedArray.languages, selectedValue, result, workspaceId)\n        return result\n      }\n      return internationalizedArray.languages\n    }, cacheKey)\n  }, [internationalizedArray, client, selectedValue, workspaceId, cacheKey])\n\n  // Use React.use to handle the promise with Suspense, or return array directly\n  const languages = languagesPromise\n    ? use(languagesPromise)\n    : // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n      (internationalizedArray.languages as Language[])\n\n  // Filter out some languages if language filter is enabled\n  const {selectedLanguageIds, options: languageFilterOptions} = useLanguageFilterStudioContext()\n\n  const filteredLanguages = useMemo(() => {\n    const languageFilterEnabled = languageFilterOptions.documentTypes.includes(documentType)\n\n    return languageFilterEnabled\n      ? languages.filter((language) => selectedLanguageIds.includes(language.id))\n      : languages\n  }, [documentType, languageFilterOptions, languages, selectedLanguageIds])\n\n  const context = useMemo(\n    () => ({...internationalizedArray, languages, filteredLanguages}),\n    [filteredLanguages, internationalizedArray, languages],\n  )\n\n  return (\n    <InternationalizedArrayContext.Provider value={context}>\n      {props.children}\n    </InternationalizedArrayContext.Provider>\n  )\n}\n","import {AddIcon} from '@sanity/icons/Add'\nimport {Button, Grid} from '@sanity/ui'\n\nimport {MAX_COLUMNS} from '../constants'\nimport {getLanguageDisplay} from '../utils/getLanguageDisplay'\nimport {useInternationalizedArrayContext} from './InternationalizedArrayContext'\n\ntype AddButtonsProps = {\n  readOnly: boolean\n  handleClick: (languageId: string) => void\n  // Keys of languages that are already in use\n  languagesInUse: string[]\n}\n\n/**\n * Renders a grid of \"add language\" buttons — one per configured language.\n *\n * Returns `null` when the `languages` array is empty.\n *\n * Each button is disabled when:\n * - `readOnly` is `true`, or\n * - the language already exists in the current `value` array\n *   (matched via `LANGUAGE_FIELD_NAME`).\n *\n * The button label is formatted according to the `languageDisplay` setting\n * from the plugin context (e.g. code-only, title-only, or both).\n * An `AddIcon` is shown unless there are more languages than fit in one row\n * and the display mode is `'codeOnly'`.\n */\nfunction AddButtons(props: AddButtonsProps) {\n  const {readOnly, languagesInUse, handleClick} = props\n  const {languageDisplay, filteredLanguages: languages} = useInternationalizedArrayContext()\n\n  if (!languages.length) return null\n\n  return (\n    <Grid\n      gridTemplateColumns={Math.min(languages.length, MAX_COLUMNS[languageDisplay])}\n      gap={2}\n      data-testid=\"add-buttons-grid\"\n    >\n      {languages.map((language) => {\n        const languageTitle: string = getLanguageDisplay(\n          languageDisplay,\n          language.title,\n          language.id,\n        )\n        return (\n          <Button\n            key={language.id}\n            tone=\"primary\"\n            mode=\"ghost\"\n            fontSize={1}\n            data-testid={`add-${language.id}`}\n            disabled={readOnly || languagesInUse.includes(language.id)}\n            text={languageTitle}\n            // Only show plus icon if there's one row or less AND only showing codes\n            icon={\n              languages.length > MAX_COLUMNS[languageDisplay] && languageDisplay === 'codeOnly'\n                ? undefined\n                : AddIcon\n            }\n            value={language.id}\n            onClick={() => handleClick(language.id)}\n          />\n        )\n      })}\n    </Grid>\n  )\n}\n\nexport default AddButtons\n","import {Box, Stack, Text} from '@sanity/ui'\nimport {useToast} from '@sanity/ui/toast'\nimport {randomKey} from '@sanity/util/content'\nimport {type ReactElement, useCallback} from 'react'\nimport {\n  type FormInsertPatch,\n  type FormSetIfMissingPatch,\n  insert,\n  isSanityDocument,\n  PatchEvent,\n  setIfMissing,\n  useGetFormValue,\n  useSchema,\n} from 'sanity'\nimport {useDocumentPane} from 'sanity/structure'\n\nimport {LANGUAGE_FIELD_NAME} from '../constants'\nimport type {DocumentsToTranslate} from '../utils/getDocumentsToTranslate'\nimport {getDocumentsToTranslate} from '../utils/getDocumentsToTranslate'\nimport AddButtons from './AddButtons'\nimport {useInternationalizedArrayContext} from './InternationalizedArrayContext'\n\n/**\n * Document-level \"add translation\" panel that appears outside individual\n * internationalized array fields (when `buttonLocations` includes `'document'`).\n *\n * Renders a heading and a row of per-language buttons. When a language button\n * is clicked the component:\n *\n * 1. Scans the current document for all internationalized array fields\n *    using `getDocumentsToTranslate`.\n * 2. Filters out fields that already contain a translation for the selected\n *    language, and deduplicates by field path.\n * 3. Shows an error toast if no eligible fields remain.\n * 4. Creates `setIfMissing` + `insert` patches to add the new language\n *    entry to each eligible field, dispatching them via `onChange`.\n *\n * For Portable Text and other array-based value fields, the initial value\n * is set to an empty array (`[]`) rather than `undefined`.\n */\nexport default function DocumentAddButtons(): ReactElement {\n  const getFormValue = useGetFormValue()\n  const {filteredLanguages} = useInternationalizedArrayContext()\n\n  const toast = useToast()\n  const {onChange, formState} = useDocumentPane()\n  const schema = useSchema()\n\n  // Array-based types (e.g. Portable Text) need [] as initial value, not undefined\n  const getInitialValueForType = useCallback(\n    (typeName: string): unknown => {\n      if (!typeName) return undefined\n\n      // Extract the base type name from internationalized array type\n      // e.g., \"internationalizedArrayBodyValue\" -> \"body\"\n      const match = typeName.match(/^internationalizedArray(.+)Value$/)\n      if (!match || !match[1]) return undefined\n\n      const baseTypeName = match[1].charAt(0).toLowerCase() + match[1].slice(1)\n\n      // Check if it's a known array-based type (Portable Text fields)\n      const arrayBasedTypes = new Set(['body', 'htmlContent', 'blockContent', 'portableText'])\n      if (arrayBasedTypes.has(baseTypeName)) {\n        return []\n      }\n\n      // Try to look up the schema type to determine if it's an array\n      const schemaType = schema.get(typeName)\n      if (schemaType && 'fields' in schemaType) {\n        // Check if this is an object type with a 'value' field\n        // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n        const fields = schemaType.fields as Array<{\n          name: string\n          type?: {jsonType?: string; name?: string; type?: string; of?: unknown}\n        }>\n        const valueField = fields.find((f) => f.name === 'value')\n        if (valueField) {\n          const fieldType = valueField.type\n          // Check if the value field is an array type\n          if (\n            fieldType?.jsonType === 'array' ||\n            fieldType?.name === 'array' ||\n            fieldType?.type === 'array' ||\n            fieldType?.of !== undefined ||\n            (fieldType?.name && arrayBasedTypes.has(fieldType.name))\n          ) {\n            return []\n          }\n        }\n      }\n\n      return undefined\n    },\n    [schema],\n  )\n\n  const handleDocumentButtonClick = useCallback(\n    async (languageId: string) => {\n      const value = getFormValue([])\n      if (!isSanityDocument(value)) {\n        toast.push({\n          status: 'error',\n          title: 'No document value found',\n        })\n        return\n      }\n      const documentsToTranslation = getDocumentsToTranslate(value, [])\n\n      const alreadyTranslated = documentsToTranslation.filter(\n        (translation) => translation?.[LANGUAGE_FIELD_NAME] === languageId,\n      )\n      const removeDuplicates = documentsToTranslation.reduce<DocumentsToTranslate[]>(\n        (filteredTranslations, translation) => {\n          if (\n            alreadyTranslated.filter(\n              (alreadyTranslation) => alreadyTranslation.pathString === translation.pathString,\n            ).length > 0\n          ) {\n            return filteredTranslations\n          }\n          const translationAlreadyExists = filteredTranslations.filter(\n            (filteredTranslation) => filteredTranslation.path === translation.path,\n          )\n\n          if (translationAlreadyExists.length > 0) {\n            return filteredTranslations\n          }\n          filteredTranslations.push(translation)\n          return filteredTranslations\n        },\n        [],\n      )\n      if (removeDuplicates.length === 0) {\n        const language = filteredLanguages.find((l) => l.id === languageId)\n        toast.push({\n          status: 'warning',\n          title: `No missing translations for ${language?.title || languageId} found.`,\n        })\n        return\n      }\n\n      // Build patches for each field missing the selected language\n      const patches: (FormSetIfMissingPatch | FormInsertPatch)[] = []\n\n      for (const toTranslate of removeDuplicates) {\n        const path = toTranslate.path\n\n        const initialValue = getInitialValueForType(toTranslate._type)\n\n        const ifMissing = setIfMissing([], path)\n        const insertValue = insert(\n          [\n            {\n              _key: randomKey(),\n              [LANGUAGE_FIELD_NAME]: languageId,\n              _type: toTranslate._type,\n              value: initialValue,\n            },\n          ],\n          'after',\n          [...path, -1],\n        )\n        patches.push(ifMissing)\n        patches.push(insertValue)\n      }\n\n      onChange(PatchEvent.from(patches.flat()))\n    },\n    [getInitialValueForType, onChange, toast, getFormValue, filteredLanguages],\n  )\n  return (\n    <Stack gap={3} data-testid=\"document-add-buttons\">\n      <Box>\n        <Text size={1} weight=\"semibold\">\n          Add translation to internationalized fields\n        </Text>\n      </Box>\n      <AddButtons\n        readOnly={Boolean(formState?.readOnly)}\n        handleClick={handleDocumentButtonClick}\n        languagesInUse={[]}\n      />\n    </Stack>\n  )\n}\n","import {Stack} from '@sanity/ui'\nimport type {ObjectInputProps} from 'sanity'\n\nimport type {PluginConfig} from '../types'\nimport DocumentAddButtons from './DocumentAddButtons'\n\n/**\n * An input component for the root object of an internationalized array.\n * It renders the document add buttons if the buttonLocations include 'document'.\n */\nexport function InternationalizedArrayFormInput(\n  props: ObjectInputProps & {pluginConfig: PluginConfig},\n) {\n  const showDocumentButtons = props.pluginConfig?.buttonLocations?.includes('document')\n\n  if (showDocumentButtons) {\n    return (\n      <Stack gap={5}>\n        <DocumentAddButtons />\n        {props.renderDefault(props)}\n      </Stack>\n    )\n  }\n  return props.renderDefault(props)\n}\n","import {isDocumentSchemaType, type ObjectField, type SchemaType} from 'sanity'\n\n/**\n * Returns true when a document schema contains any field (including nested\n * object/array item fields) whose type name starts with `internationalizedArray`.\n *\n * Traversal short-circuits on first match to avoid unnecessary work.\n */\nexport function hasInternationalizedArrayField(schemaType: SchemaType): boolean {\n  if (!isDocumentSchemaType(schemaType)) {\n    return false\n  }\n\n  return hasInternationalizedArrayInFields(schemaType.fields)\n}\n\nfunction hasInternationalizedArrayInFields(\n  fields: ObjectField[],\n  visited = new Set<unknown>(),\n): boolean {\n  for (const field of fields) {\n    if (visited.has(field.type)) {\n      continue\n    }\n    visited.add(field.type)\n\n    if (field.type.name.startsWith('internationalizedArray')) {\n      return true\n    }\n\n    if (\n      field.type.jsonType === 'object' &&\n      hasInternationalizedArrayInFields(field.type.fields, visited)\n    ) {\n      return true\n    }\n\n    if (field.type.jsonType === 'array' && field.type.of.length > 0) {\n      for (const item of field.type.of) {\n        if (\n          'name' in item &&\n          typeof item.name === 'string' &&\n          item.name.startsWith('internationalizedArray')\n        ) {\n          return true\n        }\n\n        if ('fields' in item && Array.isArray(item.fields)) {\n          if (visited.has(item)) {\n            continue\n          }\n          visited.add(item)\n\n          if (hasInternationalizedArrayInFields(item.fields, visited)) {\n            return true\n          }\n        }\n      }\n    }\n  }\n\n  return false\n}\n","import {useSchema, type DocumentLayoutProps} from 'sanity'\n\nimport type {PluginConfig} from '../types'\nimport {hasInternationalizedArrayField} from '../utils/hasInternationalizedArrayField'\nimport {InternationalizedArrayProvider} from './InternationalizedArrayContext'\n\nexport function InternationalizedArrayLayout(\n  props: DocumentLayoutProps & {pluginConfig: Required<PluginConfig>},\n) {\n  const schema = useSchema()\n  const schemaType = schema.get(props.documentType)\n\n  if (!schemaType) {\n    console.error(`Schema type not found: ${props.documentType}`)\n    return props.renderDefault(props)\n  }\n\n  const hasInternationalizedArray = hasInternationalizedArrayField(schemaType)\n  if (hasInternationalizedArray && props.pluginConfig.includeForDocumentType(props.documentType)) {\n    return (\n      <InternationalizedArrayProvider\n        internationalizedArray={props.pluginConfig}\n        documentType={props.documentType}\n      >\n        {props.renderDefault(props)}\n      </InternationalizedArrayProvider>\n    )\n  }\n\n  return props.renderDefault(props)\n}\n","import {useClient} from 'sanity'\n\nimport {createCacheKey, peek, preloadWithKey, setFunctionCache} from '../cache'\nimport type {PluginConfig} from '../types'\n\nexport default function Preload(props: Required<Pick<PluginConfig, 'apiVersion' | 'languages'>>) {\n  const client = useClient({apiVersion: props.apiVersion})\n\n  // Use the same cache key structure as the main component\n  // This should match the main component when selectedValue is empty\n  const cacheKey = createCacheKey({})\n\n  if (!Array.isArray(peek({}))) {\n    preloadWithKey(async () => {\n      if (Array.isArray(props.languages)) {\n        return props.languages\n      }\n      const result = await props.languages(client, {})\n      // Populate function cache for sharing with other components\n      // Use the same key structure as the main component\n      setFunctionCache(props.languages, {}, result)\n      return result\n    }, cacheKey)\n  }\n\n  return null\n}\n","import {LANGUAGE_FIELD_NAME} from '../constants'\nimport type {Language, InternationalizedArrayItem} from '../types'\n\n/**\n * Checks whether every language in the provided list has a corresponding entry\n * in the value array. It extracts language IDs from value items using\n * `LANGUAGE_FIELD_NAME` and compares them against the expected language IDs.\n *\n * Returns `true` only when the value array length matches the number of unique\n * languages and every value language ID is found in the languages list\n * (order does not matter). The length check ensures duplicates in value are\n * correctly rejected.\n */\nexport function checkAllLanguagesArePresent(\n  languages: Language[],\n  value: InternationalizedArrayItem[] | undefined,\n): boolean {\n  const filteredLanguageIds = new Set(languages.map((l) => l.id))\n  const languagesInUseIds = value ? value.map((v) => v[LANGUAGE_FIELD_NAME]) : []\n\n  if (languagesInUseIds.length !== filteredLanguageIds.size) return false\n  if (new Set(languagesInUseIds).size !== languagesInUseIds.length) return false\n  return languagesInUseIds.every((key) => filteredLanguageIds.has(key))\n}\n","import {LANGUAGE_FIELD_NAME} from '../constants'\nimport type {Language, InternationalizedArrayItem} from '../types'\n\n/**\n * Generates the label text for the \"add all / add missing languages\" button.\n *\n * - When there is no existing value: returns `\"Add {title} Field\"` for a\n *   single language, or `\"Add all languages\"` for multiple.\n * - When some values already exist: returns `\"Add missing language\"` (singular)\n *   or `\"Add missing languages\"` (plural) depending on how many are left.\n */\nexport function createAddAllTitle(\n  value: InternationalizedArrayItem[] | undefined,\n  languages: Language[],\n): string {\n  if (value?.length) {\n    const languagesInUse = new Set(value.map((item) => item[LANGUAGE_FIELD_NAME]))\n    const missingCount = languages.filter((language) => !languagesInUse.has(language.id)).length\n    return `Add missing ${missingCount === 1 ? `language` : `languages`}`\n  }\n\n  return languages.length === 1 && languages[0]\n    ? `Add ${languages[0].title} Field`\n    : `Add all languages`\n}\n","import type {LanguageFilterConfig} from '@sanity/language-filter'\nimport type {FieldDefinition, Rule, RuleTypeConstraint, SanityClient} from 'sanity'\nexport type Language = {\n  id: Intl.UnicodeBCP47LocaleIdentifier\n  title: string\n}\n\nexport type AllowedType = 'string' | 'number' | 'boolean' | 'text' | 'reference'\n\nexport type ArrayConfig = {\n  name: string\n  type: AllowedType\n  languages: Language[]\n  title?: string\n  group?: string\n  hidden?: boolean | (() => boolean)\n  readOnly?: boolean | (() => boolean)\n  validation?: Rule | Rule[]\n  field?: {[key: string]: unknown; options: {[key: string]: unknown}}\n}\n\n/**\n * @deprecated Use InternationalizedArrayItem instead\n */\nexport type Value = {\n  _key: string\n  /** Language identifier (e.g., 'en', 'fr'). Added in v5. */\n  language: string\n  value?: unknown\n}\n\nexport function isInternationalizedArrayItemType(\n  type: string,\n): type is InternationalizedArrayItem['_type'] {\n  return type.startsWith('internationalizedArray') && type.endsWith('Value')\n}\n\nexport type InternationalizedArrayItem<T = unknown> = {\n  _key: string\n  value?: T\n  /** Language identifier (e.g., 'en', 'fr'). Added in v5. */\n  language: string\n  /**\n   * string that starts with \"internationalizedArray\" and ends with \"Value\"\n   */\n  _type: `internationalizedArray${string}Value`\n}\n\nexport type LanguageCallback = (\n  client: SanityClient,\n  selectedValue: Record<string, unknown>,\n) => Promise<Language[]>\n\nexport type LanguageDisplay = 'titleOnly' | 'codeOnly' | 'titleAndCode'\n\nexport type PluginConfig = {\n  /**\n   * https://www.sanity.io/docs/api-versioning\n   * @defaultValue '2025-10-15'\n   */\n  apiVersion?: string\n  /**\n   * Specify fields that should be available in the language callback:\n   * ```tsx\n   * {\n   *   select: {\n   *     markets: 'markets'\n   *   },\n   *   languages: (client, {markets}) =>\n   *     query.fetch(groq`*[_type == \"language\" && market in $markets]{id,title}`, {markets})\n   * }\n   * ```\n   */\n  select?: Record<string, string>\n  /**\n   * You can give it an array of language definitions:\n   * ```tsx\n   * {\n   *   languages: [\n   *     {id: 'en', title: 'English'},\n   *     {id: 'fr', title: 'French'}\n   *   ]\n   * }\n   * ```\n   * You can load them async by passing a function that returns a promise:\n   * ```tsx\n   * {\n   *   languages: async () => {\n   *     const response = await fetch('https://example.com/languages')\n   *     return response.json()\n   *   }\n   * }\n   * ```\n   * You can query your dataset for languages::\n   * ```tsx\n   * {\n   *   languages: (client) =>\n   *     query.fetch(groq`*[_type == \"language\"]{id,title}`)\n   * }\n   * ```\n   */\n  languages: Language[] | LanguageCallback\n  /**\n   * You can specify a list of language IDs that should be pre-filled when creating a new document\n   * ```tsx\n   * {\n   *  defaultLanguages: ['en']\n   * }\n   * ```\n   */\n  defaultLanguages?: string[]\n  /**\n   * Can be a string matching core field types, as well as custom ones:\n   * ```tsx\n   * {\n   *   fieldTypes: [\n   *     \"date\", \"datetime\", \"file\", \"image\", \"number\", \"string\", \"text\", \"url\"\n   *   ]\n   * }\n   * ```\n   * You can also define a type directly:\n   * ```tsx\n   * {\n   *   fieldTypes: [\n   *     defineField({\n   *       name: 'featuredProduct',\n   *       type: 'reference',\n   *       to: [{type: 'product'}]\n   *       hidden: (({document}) => !document?.title)\n   *     })\n   *   ]\n   * }\n   * ```\n   */\n  // oxlint-disable-next-line typescript-eslint/no-redundant-type-constituents\n  fieldTypes: (string | RuleTypeConstraint | FieldDefinition)[]\n  /**\n   * Locations where the \"+ EN\" add language buttons are visible.\n   * `fieldMenu` is one translate icon per field that opens a\n   * language menu (compact; stable UI; no field actions). All locations are\n   * additive, so `field`, `fieldMenu`, and `document` can be combined.\n   * `unstable__fieldAction` is still accepted but crashes the editor from\n   * plugin 4.0.4 onward on Studio 4 and above.\n   * @defaultValue ['field']\n   * */\n  buttonLocations?: ('field' | 'fieldMenu' | 'unstable__fieldAction' | 'document')[]\n  /**\n   * Show or hide the \"Add all languages\" / \"Add missing languages\" control.\n   * Under `field` this is the bar below the per-language buttons. Under\n   * `fieldMenu` it is the bulk item inside the language menu.\n   * @defaultValue true\n   * */\n  buttonAddAll?: boolean\n  /**\n   * Automatically reorder array items to match the configured `languages` order\n   * when a document is opened.\n   *\n   * Disable this if you want to preserve a custom item order and avoid the\n   * plugin writing a patch (which creates a draft / history entry) for published\n   * documents whose order differs from the language config.\n   *\n   * @defaultValue true\n   */\n  restoreOrder?: boolean\n  /**\n   * How to display the languages on buttons and fields\n   * @defaultValue 'code'\n   * */\n  languageDisplay?: LanguageDisplay\n  /**\n   * @internal\n   * Function to determine if the plugin layout and root input should be included for a given document type.\n   * @defaultValue (documentType) => documentType !== 'translation.metadata'\n   * @example\n   * {\n   *   includeForDocumentType: (documentType) => documentType === 'translation.metadata'\n   * }\n   */\n  includeForDocumentType?: (documentType: string) => boolean\n  /**\n   * Configure the language filter for the plugin by providing the document types that should show the filter.\n   * ```tsx\n   * {\n   *   languageFilter: {\n   *     documentTypes: ['internationalizedPost', 'lesson'],\n   *     defaultLanguages: ['en']\n   *   }\n   * }\n   * ```\n   */\n  languageFilter?: {\n    documentTypes: Required<LanguageFilterConfig>['documentTypes']\n    defaultLanguages?: LanguageFilterConfig['defaultLanguages']\n  }\n}\n","import {randomKey} from '@sanity/util/content'\nimport {type FormInsertPatch, insert, type Path} from 'sanity'\n\nimport {LANGUAGE_FIELD_NAME} from '../constants'\nimport {\n  type Language,\n  type InternationalizedArrayItem,\n  isInternationalizedArrayItemType,\n} from '../types'\n\ntype AddConfig = {\n  // New keys to add to the field\n  addLanguageKeys: string[]\n  // Schema of the current field\n  schemaTypeName: string\n  // All languages registered in the plugin\n  languages: Language[]\n  // Languages that are currently visible\n  filteredLanguages: Language[]\n  // Current value of the internationalizedArray field\n  value?: InternationalizedArrayItem[]\n  // Path to this item\n  path?: Path\n}\n\n/**\n * Creates an array of Sanity `FormInsertPatch` objects that add new language\n * entries to an internationalized array field.\n *\n * If `addLanguageKeys` is provided, patches are created for those specific\n * language IDs. Otherwise, patches are created for all filtered languages\n * that are not already present in the current `value` array, for example when adding all missing languages.\n *\n * Each new item is assigned the correct `_type` (derived from the schema)\n * and the language identifier via `LANGUAGE_FIELD_NAME`.\n *\n * Insertions are ordered to maintain the same sequence as the master\n * `languages` list: each new item is inserted before the next existing\n * language in the value array, or appended at the end if no subsequent\n * language exists.\n */\nexport function createAddLanguagePatches(config: AddConfig): FormInsertPatch[] {\n  const {addLanguageKeys, schemaTypeName, languages, filteredLanguages, value, path = []} = config\n\n  const type = `${schemaTypeName}Value`\n  if (!isInternationalizedArrayItemType(type)) {\n    throw new Error(`Invalid internationalized array type: ${type}`)\n  }\n  const itemBase = {_type: type}\n\n  // Create new items with random _key and language identifier\n  const getNewItems = () => {\n    if (Array.isArray(addLanguageKeys) && addLanguageKeys.length > 0) {\n      return addLanguageKeys\n        .filter((id) => {\n          if (value?.length) {\n            // Check if the language is already in the value and filter it out if it exists to avoid duplicates\n            return !value.find((v) => v[LANGUAGE_FIELD_NAME] === id)\n          }\n          return true\n        })\n        .map((id) => Object.assign({}, itemBase, {_key: randomKey(), [LANGUAGE_FIELD_NAME]: id}))\n    }\n\n    return filteredLanguages\n      .filter((language) => {\n        return value?.length ? !value.find((v) => v[LANGUAGE_FIELD_NAME] === language.id) : true\n      })\n      .map((language) =>\n        Object.assign({}, itemBase, {_key: randomKey(), [LANGUAGE_FIELD_NAME]: language.id}),\n      )\n  }\n  const newItems = getNewItems()\n\n  // Insert new items in the correct order\n  const languagesInUse = value?.length ? value.map((v) => v) : []\n\n  const insertions = newItems.map((item) => {\n    // What's the original index of this language?\n    const itemLanguage = item[LANGUAGE_FIELD_NAME]\n    const languageIndex = languages.findIndex((l) => itemLanguage === l.id)\n\n    // What languages are there beyond that index?\n    const remainingLanguages = languages.slice(languageIndex + 1)\n\n    // So what is the index in the current value array of the next language in the language array?\n    const nextLanguageIndex = languagesInUse.findIndex((l) =>\n      remainingLanguages.find((r) => r.id === l[LANGUAGE_FIELD_NAME]),\n    )\n\n    // Keep local state up to date incase multiple insertions are being made\n    if (nextLanguageIndex < 0) {\n      languagesInUse.push(item)\n    } else {\n      languagesInUse.splice(nextLanguageIndex, 0, item)\n    }\n\n    return nextLanguageIndex < 0\n      ? // No next language (-1), add to end of array\n        insert([item], 'after', [...path, nextLanguageIndex])\n      : // Next language found, insert before that\n        insert([item], 'before', [...path, nextLanguageIndex])\n  })\n\n  return insertions\n}\n","import {AddIcon} from '@sanity/icons/Add'\nimport {TranslateIcon} from '@sanity/icons/Translate'\nimport {useCallback} from 'react'\nimport {\n  defineDocumentFieldAction,\n  type DocumentFieldActionItem,\n  type DocumentFieldActionProps,\n  PatchEvent,\n  setIfMissing,\n  useFormValue,\n} from 'sanity'\nimport {useDocumentPane} from 'sanity/structure'\n\nimport {useInternationalizedArrayContext} from '../components/InternationalizedArrayContext'\nimport {LANGUAGE_FIELD_NAME} from '../constants'\nimport type {Language, InternationalizedArrayItem} from '../types'\nimport {checkAllLanguagesArePresent} from '../utils/checkAllLanguagesArePresent'\nimport {createAddAllTitle} from '../utils/createAddAllTitle'\nimport {createAddLanguagePatches} from '../utils/createAddLanguagePatches'\n\nconst createTranslateFieldActions: (\n  fieldActionProps: DocumentFieldActionProps,\n  context: {\n    languages: Language[]\n    filteredLanguages: Language[]\n  },\n) => DocumentFieldActionItem[] = (fieldActionProps, {languages, filteredLanguages}) =>\n  languages.map((language) => {\n    // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n    const value = useFormValue(fieldActionProps.path) as InternationalizedArrayItem[]\n    const {onChange, formState} = useDocumentPane()\n    const disabled =\n      Boolean(formState?.readOnly) ||\n      (value && Array.isArray(value)\n        ? Boolean(value?.find((item) => item[LANGUAGE_FIELD_NAME] === language.id))\n        : false)\n    const hidden = !filteredLanguages.some((f) => f.id === language.id)\n\n    const onAction = useCallback(() => {\n      const {schemaType, path} = fieldActionProps\n\n      const addLanguageKeys = [language.id]\n      const patches = createAddLanguagePatches({\n        addLanguageKeys,\n        schemaTypeName: schemaType.name,\n        languages,\n        filteredLanguages,\n        value,\n        path,\n      })\n\n      onChange(PatchEvent.from([setIfMissing([], path), ...patches]))\n    }, [language.id, value, onChange])\n\n    return {\n      type: 'action',\n      icon: AddIcon,\n      onAction,\n      title: language.title,\n      hidden,\n      disabled,\n    }\n  })\n\nconst AddMissingTranslationsFieldAction: (\n  fieldActionProps: DocumentFieldActionProps,\n  context: {\n    languages: Language[]\n    filteredLanguages: Language[]\n  },\n) => DocumentFieldActionItem = (fieldActionProps, {languages, filteredLanguages}) => {\n  // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n  const value = useFormValue(fieldActionProps.path) as InternationalizedArrayItem[]\n  const {onChange, formState} = useDocumentPane()\n  const disabled =\n    Boolean(formState?.readOnly) || (value && value.length === filteredLanguages.length)\n  const hidden = checkAllLanguagesArePresent(filteredLanguages, value)\n\n  const onAction = useCallback(() => {\n    const {schemaType, path} = fieldActionProps\n\n    const addLanguageKeys: string[] = []\n    const patches = createAddLanguagePatches({\n      addLanguageKeys,\n      schemaTypeName: schemaType.name,\n      languages,\n      filteredLanguages,\n      value,\n      path,\n    })\n\n    onChange(PatchEvent.from([setIfMissing([], path), ...patches]))\n  }, [fieldActionProps, filteredLanguages, languages, onChange, value])\n\n  return {\n    type: 'action',\n    icon: AddIcon,\n    onAction,\n    title: createAddAllTitle(value, filteredLanguages),\n    disabled,\n    hidden,\n  }\n}\n\nexport const internationalizedArrayFieldAction = defineDocumentFieldAction({\n  name: 'internationalizedArray',\n  useAction(fieldActionProps) {\n    const isInternationalizedArrayField =\n      fieldActionProps?.schemaType?.type?.name.startsWith('internationalizedArray')\n    const {languages, filteredLanguages} = useInternationalizedArrayContext()\n\n    const translateFieldActions = createTranslateFieldActions(fieldActionProps, {\n      languages,\n      filteredLanguages,\n    })\n\n    return {\n      type: 'group',\n      icon: TranslateIcon,\n      title: 'Add Translation',\n      renderAsButton: true,\n      children: isInternationalizedArrayField\n        ? [\n            ...translateFieldActions,\n            AddMissingTranslationsFieldAction(fieldActionProps, {\n              languages,\n              filteredLanguages,\n            }),\n          ]\n        : [],\n      hidden: !isInternationalizedArrayField,\n    }\n  },\n})\n","import camelCase from 'lodash-es/camelCase.js'\nimport upperFirst from 'lodash-es/upperFirst.js'\n\n/**\n * Converts a string to PascalCase (e.g. `\"my-field\"` -> `\"MyField\"`).\n */\nexport function pascalCase(string: string): string {\n  return upperFirst(camelCase(string))\n}\n\n/**\n * Generates the schema type name for an internationalized array field.\n *\n * - Without the value suffix: `\"internationalizedArray{PascalName}\"`\n *   (used for the outer array type)\n * - With the value suffix: `\"internationalizedArray{PascalName}Value\"`\n *   (used for the inner object type that wraps each language entry)\n *\n * For example, `createFieldName('block-content', true)` returns\n * `\"internationalizedArrayBlockContentValue\"`.\n */\nexport function createFieldName(name: string, addValue = false): string {\n  return addValue\n    ? [`internationalizedArray`, pascalCase(name), `Value`].join(``)\n    : [`internationalizedArray`, pascalCase(name)].join(``)\n}\n","import type {ObjectSchemaType, FieldMember, FieldsetState} from 'sanity'\n\nimport {LANGUAGE_FIELD_NAME} from '../constants'\nimport {isInternationalizedArrayItemType, type Language} from '../types'\n\n/**\n * Default filter function for the internationalized array field.\n * It filter the field base on the `language` value of the object.\n */\nexport const internationalizedArrayLanguageFilter = (\n  enclosingType: ObjectSchemaType,\n  _member: FieldMember | FieldsetState,\n  selectedLanguageIds: string[],\n  parentValue: Record<string, unknown> | undefined,\n  languages: Language[],\n) => {\n  if (isInternationalizedArrayItemType(enclosingType.name)) {\n    const language =\n      typeof parentValue?.[LANGUAGE_FIELD_NAME] === 'string'\n        ? parentValue?.[LANGUAGE_FIELD_NAME]\n        : typeof parentValue?.['_key'] === 'string'\n          ? parentValue?.['_key']\n          : null\n\n    const isAValidLanguage = language ? languages.find((l) => l.id === language) : true\n    if (!isAValidLanguage) {\n      // If it's not a valid language we should not hide it, because it needs to be surfaced to the user to fix it.\n      // We need to update language-filter plugin so it doesn't hide the field later.\n      return true\n    }\n    return language ? selectedLanguageIds.includes(language) : false\n  }\n  return true\n}\n","import {AddIcon} from '@sanity/icons/Add'\nimport {TranslateIcon} from '@sanity/icons/Translate'\nimport {Button, Flex} from '@sanity/ui'\nimport {Menu, MenuButton, MenuDivider, MenuItem} from '@sanity/ui/menu'\nimport {useId} from 'react'\n\nimport {getLanguageDisplay} from '../utils/getLanguageDisplay'\nimport {useInternationalizedArrayContext} from './InternationalizedArrayContext'\n\ntype CompactAddButtonProps = {\n  readOnly: boolean\n  handleClick: (languageId: string) => void\n  languagesInUse: string[]\n  onAddAll: () => void\n  buttonAddAll: boolean\n  addAllTitle: string\n  allFilteredLanguagesArePresent: boolean\n}\n\n/**\n * One translate-icon button that opens a language menu — the `fieldMenu`\n * location. Compact, uses only stable `@sanity/ui`, and stays visible even\n * when every language is already present.\n */\nfunction CompactAddButton(props: CompactAddButtonProps) {\n  const {\n    readOnly,\n    languagesInUse,\n    handleClick,\n    onAddAll,\n    buttonAddAll,\n    addAllTitle,\n    allFilteredLanguagesArePresent,\n  } = props\n  const {languageDisplay, filteredLanguages: languages} = useInternationalizedArrayContext()\n  const menuId = useId()\n\n  if (!languages.length) return null\n\n  return (\n    <Flex justify=\"flex-end\" data-testid=\"field-menu\">\n      <MenuButton\n        id={menuId}\n        popover={{portal: true, placement: 'bottom-end'}}\n        button={\n          <Button\n            mode=\"bleed\"\n            tone=\"default\"\n            fontSize={1}\n            padding={2}\n            icon={TranslateIcon}\n            aria-label=\"Add translation\"\n            title=\"Add translation\"\n            data-testid=\"add-translation-menu\"\n            disabled={readOnly}\n          />\n        }\n        menu={\n          <Menu>\n            {languages.map((language) => (\n              <MenuItem\n                key={language.id}\n                text={getLanguageDisplay(languageDisplay, language.title, language.id)}\n                icon={AddIcon}\n                disabled={readOnly || languagesInUse.includes(language.id)}\n                data-testid={`field-menu-add-${language.id}`}\n                onClick={() => handleClick(language.id)}\n              />\n            ))}\n            {buttonAddAll ? (\n              <>\n                <MenuDivider />\n                <MenuItem\n                  text={addAllTitle}\n                  icon={TranslateIcon}\n                  disabled={readOnly || allFilteredLanguagesArePresent}\n                  data-testid=\"field-menu-add-all\"\n                  onClick={onAddAll}\n                />\n              </>\n            ) : null}\n          </Menu>\n        }\n      />\n    </Flex>\n  )\n}\n\nexport default CompactAddButton\n","import {Card, Stack, Text} from '@sanity/ui'\nimport {Code} from '@sanity/ui/code'\nimport type React from 'react'\n\nconst schemaExample = {\n  languages: [\n    {id: 'en', title: 'English'},\n    {id: 'no', title: 'Norsk'},\n  ],\n}\n\nexport default function Feedback(): React.ReactElement {\n  return (\n    <Card tone=\"caution\" border radius={2} padding={3}>\n      <Stack gap={4}>\n        <Text>\n          An array of language objects must be passed into the <code>internationalizedArray</code>{' '}\n          helper function, each with an <code>id</code> and <code>title</code> field. Example:\n        </Text>\n        <Card padding={2} border radius={2}>\n          <Code size={1} language=\"javascript\">\n            {JSON.stringify(schemaExample, null, 2)}\n          </Code>\n        </Card>\n      </Stack>\n    </Card>\n  )\n}\n","import {WarningOutlineIcon} from '@sanity/icons/WarningOutline'\nimport {Box, Card, Flex, Stack, Text} from '@sanity/ui'\nimport {type ReactElement} from 'react'\n\nimport type {InternationalizedArrayItem} from '../types'\n\nexport type MigrationBannerProps = {\n  itemsNeedingMigration: InternationalizedArrayItem[]\n}\n\n/**\n * Migration banner component that displays a warning if the items need to be migrated to the v5 format.\n */\nexport function MigrationBanner({\n  itemsNeedingMigration,\n}: MigrationBannerProps): ReactElement | null {\n  // Don't render if no migration is needed\n  if (!itemsNeedingMigration.length) {\n    return null\n  }\n\n  return (\n    <Card tone=\"caution\" padding={3} radius={2} border>\n      <Flex gap={3} align=\"center\">\n        <Box>\n          <Text size={1}>\n            <WarningOutlineIcon />\n          </Text>\n        </Box>\n        <Stack gap={2} flex={1}>\n          <Text size={1} weight=\"semibold\">\n            Data migration required\n          </Text>\n          <Text size={1} muted>\n            {itemsNeedingMigration.length} item\n            {itemsNeedingMigration.length === 1 ? '' : 's'}{' '}\n            {itemsNeedingMigration.length === 1 ? 'needs' : 'need'} to be migrated to the v5 format.\n          </Text>\n          <Box marginTop={2}>\n            <Text size={1}>\n              This field still uses the v4 format where language is stored in <code>_key</code>.\n              Migrate to the v5 format where language is stored in <code>language</code>.{' '}\n              <a\n                rel=\"noopener noreferrer\"\n                target=\"_blank\"\n                href=\"https://github.com/sanity-io/plugins/blob/main/plugins/sanity-plugin-internationalized-array/README.md#migrate-from-v4-to-v5\"\n              >\n                Learn more\n              </a>\n              .\n            </Text>\n          </Box>\n        </Stack>\n      </Flex>\n    </Card>\n  )\n}\n","import {AddIcon} from '@sanity/icons/Add'\nimport {useLanguageFilterStudioContext} from '@sanity/language-filter'\nimport {Button, Card, Stack, Text} from '@sanity/ui'\nimport {useToast} from '@sanity/ui/toast'\nimport type React from 'react'\nimport {useCallback, useContext, useEffect, useMemo} from 'react'\nimport {\n  type ArrayOfObjectsInputProps,\n  ArrayOfObjectsItem,\n  MemberItemError,\n  set,\n  setIfMissing,\n  useFormValue,\n  useGetFormValue,\n} from 'sanity'\nimport {EventsContext} from 'sanity/_singletons'\nimport {useDocumentPane} from 'sanity/structure'\n\nimport {LANGUAGE_FIELD_NAME} from '../constants'\nimport type {InternationalizedArrayItem} from '../types'\nimport {createAddAllTitle} from '../utils/createAddAllTitle'\nimport {createAddLanguagePatches} from '../utils/createAddLanguagePatches'\nimport {internationalizedArrayLanguageFilter} from '../utils/internationalizedArrayLanguageFilter'\nimport AddButtons from './AddButtons'\nimport CompactAddButton from './CompactAddButton'\nimport Feedback from './Feedback'\nimport {useInternationalizedArrayContext} from './InternationalizedArrayContext'\nimport {MigrationBanner} from './MigrationBanner'\n\n/**\n * The events store has finished loading and recorded no history. That is a\n * brand-new document.\n *\n * `sanity/_singletons` is internal; this is the same context `useEvents()`\n * reads. Using the context directly avoids throwing when the events API is\n * off (legacy timeline has no `EventsProvider`).\n */\nfunction isPristineDocument(\n  events: {events: readonly unknown[]; loading: boolean} | null,\n): boolean {\n  if (!events || events.loading) {\n    return false\n  }\n  return events.events.length === 0\n}\n\n/**\n * Main array input component for internationalized array fields.\n *\n * Replaces the default Sanity array input and manages the full lifecycle of\n * language entries:\n *\n * - **Language filter integration**: When `@sanity/language-filter` is active\n *   for the current document type, array members are filtered to only show\n *   languages matching the user's selection.\n * - **Adding languages**: Exposes per-language buttons, an optional compact\n *   `fieldMenu`, and an \"Add all / Add missing languages\" button (controlled\n *   by `buttonAddAll` and `buttonLocations`). Dispatches `setIfMissing` +\n *   `insert` patches.\n * - **Default languages**: Automatically adds entries for languages listed in\n *   `defaultLanguages` when those entries are missing. Seeds brand-new\n *   documents once the events store reports they are pristine (no history),\n *   and seeds persisted documents that already have a `_rev`. A document\n *   that existed and was deleted is not pristine, so opening it — even in a\n *   fresh pane — does not recreate it. Newly created documents stay\n *   read-only until initial value templates resolve, and the field-level\n *   `readOnly` prop can lag that document-level lock. Skipping the patch\n *   until writable avoids \"Attempted to patch a read-only document\" toasts.\n * - **Ordering**: When `restoreOrder` is enabled (default), detects when value\n *   items are out of order relative to the master `languages` list and\n *   automatically re-sorts them. Set `restoreOrder: false` to keep the stored\n *   order and avoid silent draft creation on open.\n * - **Validation**: Shows a `<Feedback>` component if the languages\n *   configuration is invalid (e.g. missing `id` or `title`).\n * - **Empty state**: Displays a \"no translations\" message when the field has\n *   no entries and the add buttons are not visible.\n */\nexport default function InternationalizedArray(\n  props: ArrayOfObjectsInputProps,\n): React.ReactElement {\n  const {members, value: _value, schemaType, onChange, readOnly: documentReadOnly} = props\n  // oxlint-disable-next-line typescript/no-unsafe-type-assertion\n  const value = _value as InternationalizedArrayItem[]\n  const itemsNeedingMigration = value?.filter((v) => !v[LANGUAGE_FIELD_NAME]) ?? []\n  const shouldMigrateArray = itemsNeedingMigration.length > 0\n  const toast = useToast()\n\n  const getFormValue = useGetFormValue()\n  const {\n    languages,\n    filteredLanguages,\n    defaultLanguages,\n    buttonAddAll,\n    buttonLocations,\n    restoreOrder,\n    languageFilter: builtInLanguageFilter,\n  } = useInternationalizedArrayContext()\n  // Support updating the UI if languageFilter is installed\n  const {selectedLanguageIds, options: languageFilterOptions} = useLanguageFilterStudioContext()\n  const documentType = useFormValue(['_type'])\n  const usingLanguageFilterPlugin =\n    typeof documentType === 'string' && languageFilterOptions.documentTypes.includes(documentType)\n  const usingBuiltInLanguageFilter =\n    typeof documentType === 'string' && builtInLanguageFilter.documentTypes.includes(documentType)\n\n  // TODO: Is this redundant? The filter plugin already filters members at its own level.\n  const filteredMembers = useMemo(\n    () =>\n      usingLanguageFilterPlugin || usingBuiltInLanguageFilter\n        ? members.filter((member) => {\n            // This member is the outer object created by the plugin\n            // Satisfy TS\n            if (member.kind !== 'item') {\n              return false\n            }\n\n            // This is the inner \"value\" field member created by this plugin\n            const valueMember = member.item.members[0]\n\n            // Satisfy TS\n            if (!valueMember || valueMember.kind !== 'field') {\n              return false\n            }\n            // The built-in filter receives the full languages list so it can\n            // surface fields with invalid language IDs rather than hiding them.\n            // The language filter plugin does not support this.\n            return usingBuiltInLanguageFilter\n              ? internationalizedArrayLanguageFilter(\n                  member.item.schemaType,\n                  valueMember,\n                  selectedLanguageIds,\n                  member.item.value,\n                  languages,\n                )\n              : languageFilterOptions.filterField(\n                  member.item.schemaType,\n                  valueMember,\n                  selectedLanguageIds,\n                  member.item.value,\n                )\n          })\n        : members,\n    [\n      usingLanguageFilterPlugin,\n      usingBuiltInLanguageFilter,\n      members,\n      selectedLanguageIds,\n      languages,\n      languageFilterOptions,\n    ],\n  )\n\n  const {isDeleted, isDeleting, isInitialValueLoading, formState} = useDocumentPane()\n\n  // Document-level locks (initial-value templates, permissions, history) are\n  // not always reflected on the field's `readOnly` prop in the same tick as\n  // the patch channel. Gating on both prevents toasts from auto-patches.\n  const readOnly =\n    Boolean(documentReadOnly) ||\n    schemaType.readOnly === true ||\n    Boolean(formState?.readOnly) ||\n    Boolean(isInitialValueLoading)\n\n  const handleAddLanguages = useCallback(\n    (addLanguageKeys: string[] | string) => {\n      if (readOnly) {\n        return\n      }\n      // oxlint-disable-next-line typescript/no-unsafe-type-assertion\n      const formValue = getFormValue(props.path) as InternationalizedArrayItem[]\n      if (!filteredLanguages?.length) {\n        return\n      }\n\n      const patches = createAddLanguagePatches({\n        addLanguageKeys: Array.isArray(addLanguageKeys) ? addLanguageKeys : [addLanguageKeys],\n        schemaTypeName: schemaType.name,\n        languages,\n        filteredLanguages,\n        value: formValue,\n      })\n\n      onChange([setIfMissing([]), ...patches])\n    },\n    [filteredLanguages, languages, onChange, schemaType, getFormValue, props.path, readOnly],\n  )\n\n  // `_rev` means the document is in the dataset. No `_rev` is either a\n  // brand-new form or a deleted one. The events store distinguishes those:\n  // pristine (loaded, zero events) has never existed; any history means it\n  // did — including a fresh open of a deleted id, where this pane never saw\n  // a `_rev`.\n  const documentExists = Boolean(useFormValue(['_rev']))\n  const isPristine = isPristineDocument(useContext(EventsContext))\n\n  // Create a stable dependency string that only changes when language keys change\n  const languageKeysFromValue = value\n    ?.map((v) => v[LANGUAGE_FIELD_NAME] ?? v._key)\n    .filter(Boolean)\n    .join(',')\n\n  const addedLanguages = useMemo(() => {\n    const languageKeys = languageKeysFromValue?.split(',') || []\n    if (!languageKeys?.length) return []\n    if (!languages?.length) return []\n\n    return languages.filter((l) => languageKeys?.find((key) => key === l.id)).map((l) => l.id)\n  }, [languageKeysFromValue, languages])\n\n  useEffect(() => {\n    const hasAddedDefaultLanguages = defaultLanguages\n      .filter((language) => languages.find((l) => l.id === language))\n      .every((language) => addedLanguages.includes(language))\n\n    if (\n      (isPristine || documentExists) &&\n      !isDeleting &&\n      !isDeleted &&\n      !hasAddedDefaultLanguages &&\n      !shouldMigrateArray &&\n      !readOnly\n    ) {\n      const languagesToAdd = defaultLanguages\n        .filter((language) => !addedLanguages.includes(language))\n        .filter((language) => languages.find((l) => l.id === language))\n      // Account for strict mode by scheduling the update.\n      const timeout = setTimeout(() => {\n        if (!readOnly) handleAddLanguages(languagesToAdd)\n      })\n      return () => clearTimeout(timeout)\n    }\n    return undefined\n  }, [\n    isPristine,\n    documentExists,\n    isDeleted,\n    isDeleting,\n    handleAddLanguages,\n    defaultLanguages,\n    addedLanguages,\n    languages,\n    readOnly,\n    shouldMigrateArray,\n  ])\n\n  // NOTE: This is reordering and re-setting the whole array, it could be surgical\n  const handleRestoreOrder = useCallback(() => {\n    if (readOnly || !value?.length || !languages?.length) {\n      return\n    }\n\n    // Create a new value array in the correct order\n    // This would also strip out values that don't have a language as the key\n    const updatedValue = value\n      .reduce((acc, v) => {\n        const newIndex = languages.findIndex((l) => l.id === v?.[LANGUAGE_FIELD_NAME])\n\n        if (newIndex > -1) {\n          acc[newIndex] = v\n        }\n\n        return acc\n      }, [] as InternationalizedArrayItem[])\n      .filter(Boolean)\n\n    if (value?.length !== updatedValue.length) {\n      toast.push({\n        title: 'There was an error reordering languages',\n        status: 'warning',\n      })\n    }\n\n    onChange(set(updatedValue))\n  }, [toast, languages, onChange, value, readOnly])\n\n  const allKeysAreLanguages = useMemo(() => {\n    if (!value?.length || !languages?.length) {\n      return true\n    }\n\n    return value?.every((v) => languages.find((l) => l?.id === v?.[LANGUAGE_FIELD_NAME]))\n  }, [value, languages])\n\n  const languagesOutOfOrder = useMemo(() => {\n    if (!value?.length || !addedLanguages.length) {\n      return []\n    }\n\n    return value\n      .map((v, vIndex) =>\n        vIndex === addedLanguages.findIndex((language) => language === v[LANGUAGE_FIELD_NAME])\n          ? null\n          : v,\n      )\n      .filter(Boolean)\n  }, [value, addedLanguages])\n\n  const languagesAreValid = useMemo(\n    () =>\n      !languages?.length || (languages?.length && languages.every((item) => item.id && item.title)),\n    [languages],\n  )\n\n  // Automatically restore order of fields (opt out with restoreOrder: false)\n  useEffect(() => {\n    if (restoreOrder && languagesOutOfOrder.length > 0 && allKeysAreLanguages && !readOnly) {\n      handleRestoreOrder()\n    }\n  }, [restoreOrder, languagesOutOfOrder, allKeysAreLanguages, handleRestoreOrder, readOnly])\n\n  const allFilteredLanguagesArePresent = useMemo(\n    () => filteredLanguages.every((language) => addedLanguages.includes(language.id)),\n    [filteredLanguages, addedLanguages],\n  )\n  const addAllMissingLanguages = useCallback(() => {\n    handleAddLanguages(filteredLanguages.map((language) => language.id))\n  }, [filteredLanguages, handleAddLanguages])\n\n  if (!languagesAreValid) {\n    return <Feedback />\n  }\n\n  const canAddLanguages = !shouldMigrateArray && filteredLanguages?.length > 0\n  const showFieldMenu = canAddLanguages && buttonLocations.includes('fieldMenu')\n  const showFieldButtons =\n    canAddLanguages && buttonLocations.includes('field') && !allFilteredLanguagesArePresent\n  const fieldHasMembers = members?.length > 0\n  const addAllTitle = createAddAllTitle(value, filteredLanguages)\n\n  const fieldButtons = showFieldButtons ? (\n    <Stack gap={2}>\n      <AddButtons\n        languagesInUse={addedLanguages}\n        readOnly={readOnly}\n        handleClick={handleAddLanguages}\n      />\n      {buttonAddAll ? (\n        <Button\n          tone=\"primary\"\n          mode=\"ghost\"\n          data-testid=\"add-all-languages\"\n          disabled={readOnly || allFilteredLanguagesArePresent}\n          icon={AddIcon}\n          text={addAllTitle}\n          onClick={addAllMissingLanguages}\n        />\n      ) : null}\n    </Stack>\n  ) : null\n\n  return (\n    <Stack gap={2}>\n      {showFieldMenu ? (\n        <CompactAddButton\n          languagesInUse={addedLanguages}\n          readOnly={readOnly}\n          handleClick={handleAddLanguages}\n          onAddAll={addAllMissingLanguages}\n          buttonAddAll={buttonAddAll}\n          addAllTitle={addAllTitle}\n          allFilteredLanguagesArePresent={allFilteredLanguagesArePresent}\n        />\n      ) : null}\n      {filteredMembers.map((member) => {\n        if (member.kind === 'item') {\n          return <ArrayOfObjectsItem {...props} key={member.key} member={member} />\n        }\n        return <MemberItemError key={member.key} member={member} />\n      })}\n      <MigrationBanner itemsNeedingMigration={itemsNeedingMigration} />\n\n      {/* Give some feedback in the UI so the field doesn't look \"missing\" */}\n      {!showFieldMenu && !showFieldButtons && !fieldHasMembers ? (\n        <Card border tone=\"transparent\" padding={3} radius={2}>\n          <Text size={1}>This internationalized field currently has no translations.</Text>\n        </Card>\n      ) : null}\n\n      {fieldButtons}\n    </Stack>\n  )\n}\n","import type {SchemaType} from 'sanity'\n\nimport type {ArrayFieldOptions} from '../schema/array'\n\nexport function getLanguagesFieldOption(\n  schemaType: SchemaType | undefined,\n): ArrayFieldOptions['languages'] | undefined {\n  if (!schemaType) {\n    return undefined\n  }\n  // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n  const languagesOption = (schemaType.options as ArrayFieldOptions)?.languages\n  if (languagesOption) {\n    return languagesOption\n  }\n  return getLanguagesFieldOption(schemaType.type)\n}\n","import {defineField, type FieldDefinition, type FieldProps, type Rule} from 'sanity'\n\nimport {getFunctionCache, peek, setFunctionCache} from '../cache'\nimport {createFieldName} from '../components/createFieldName'\nimport {getSelectedValue} from '../components/getSelectedValue'\nimport InternationalizedArray from '../components/InternationalizedArray'\nimport {LANGUAGE_FIELD_NAME} from '../constants'\nimport type {Language, LanguageCallback, InternationalizedArrayItem} from '../types'\nimport {getLanguagesFieldOption} from '../utils/getLanguagesFieldOption'\n\ntype ArrayFactoryConfig = {\n  apiVersion: string\n  select?: Record<string, string>\n  languages: Language[] | LanguageCallback\n  defaultLanguages?: string[]\n  type: string | FieldDefinition\n}\n\nexport type ArrayFieldOptions = Pick<ArrayFactoryConfig, 'apiVersion' | 'select' | 'languages'>\n\nexport default (config: ArrayFactoryConfig) => {\n  const {apiVersion, select, languages, type} = config\n  const typeName = typeof type === `string` ? type : type.name\n  const arrayName = createFieldName(typeName)\n  const objectName = createFieldName(typeName, true)\n\n  return defineField({\n    name: arrayName,\n    title: 'Internationalized array',\n    type: 'array',\n    components: {\n      field: (props: FieldProps) =>\n        props.renderDefault({\n          ...props,\n          // Reset the level to avoid nested styling\n          level: 0,\n        }),\n      input: InternationalizedArray,\n    },\n    options: {\n      // @ts-expect-error - these options are required for validation rules – not the custom input component\n      apiVersion,\n      select,\n      languages,\n    },\n    of: [\n      defineField({\n        ...(typeof type === 'string' ? {} : type),\n        name: objectName,\n        type: objectName,\n      }),\n    ],\n    // @ts-expect-error - fix typings\n    validation: (rule: Rule) =>\n      rule.custom<InternationalizedArrayItem[]>(async (value, context) => {\n        if (!value || value.length === 0) {\n          return true\n        }\n\n        // Check for items missing the language field (unmigrated data)\n        const itemsMissingLanguage = value.filter(\n          (item) => item && !item[LANGUAGE_FIELD_NAME] && item._key,\n        )\n        if (itemsMissingLanguage.length > 0) {\n          return {\n            message:\n              'Language is required for each array item. Run the migration to update your data from the old format.',\n            paths: itemsMissingLanguage.flatMap((item) => [\n              [{_key: item._key}],\n              [{_key: item._key}, 'value'],\n            ]),\n          }\n        }\n\n        // Early return for simple cases to avoid expensive operations\n        if (value.length === 1 && !value[0]?.[LANGUAGE_FIELD_NAME]) {\n          return true\n        }\n\n        const selectedValue = getSelectedValue(select, context.document)\n        const client = context.getClient({apiVersion})\n\n        let contextLanguages: Language[] = []\n        const languagesFieldOption = getLanguagesFieldOption(context?.type)\n\n        if (Array.isArray(languagesFieldOption)) {\n          contextLanguages = languagesFieldOption\n        } else if (Array.isArray(peek(selectedValue))) {\n          contextLanguages = peek(selectedValue) || []\n        } else if (typeof languagesFieldOption === 'function') {\n          // Try to get from function cache first (if it's the same function as the component)\n          const cachedLanguages = getFunctionCache(languagesFieldOption, selectedValue)\n\n          if (Array.isArray(cachedLanguages)) {\n            contextLanguages = cachedLanguages\n          } else {\n            // Try suspend cache as fallback\n            const suspendCachedLanguages = peek(selectedValue)\n            if (Array.isArray(suspendCachedLanguages)) {\n              contextLanguages = suspendCachedLanguages\n            } else {\n              // Only make the async call if we don't have cached data\n              contextLanguages = await languagesFieldOption(client, selectedValue)\n              // Cache the result for future validation calls\n              setFunctionCache(languagesFieldOption, selectedValue, contextLanguages)\n            }\n          }\n        }\n\n        if (value && value.length > contextLanguages.length) {\n          return `Cannot be more than ${\n            contextLanguages.length === 1 ? `1 item` : `${contextLanguages.length} items`\n          }`\n        }\n\n        // Create a Set for faster language ID lookups\n        const languageIds = new Set(contextLanguages.map((lang) => lang.id))\n\n        // Check for invalid language keys\n        const nonLanguageKeys = value.filter(\n          (item) => item?.[LANGUAGE_FIELD_NAME] && !languageIds.has(item[LANGUAGE_FIELD_NAME]),\n        )\n        if (nonLanguageKeys.length) {\n          return {\n            message: `Array item keys must be valid languages registered to the field type`,\n            paths: nonLanguageKeys.map((item) => [{_key: item._key}]),\n          }\n        }\n\n        // Check for duplicate language keys (more efficient)\n        const seenLanguages = new Set<string>()\n        const duplicateValues: InternationalizedArrayItem[] = []\n\n        for (const item of value) {\n          if (item?.[LANGUAGE_FIELD_NAME]) {\n            if (seenLanguages.has(item[LANGUAGE_FIELD_NAME])) {\n              duplicateValues.push(item)\n            } else {\n              seenLanguages.add(item[LANGUAGE_FIELD_NAME])\n            }\n          }\n        }\n\n        if (duplicateValues.length) {\n          return {\n            message: 'There can only be one field per language',\n            paths: duplicateValues.map((item) => [{_key: item._key}]),\n          }\n        }\n\n        return true\n      }),\n  })\n}\n","import type {CardTone} from '@sanity/ui'\nimport type {FormNodeValidation} from 'sanity'\n\n/**\n * Maps an array of Sanity form validation entries to a `@sanity/ui` `CardTone`\n * for visual feedback on internationalized array items.\n *\n * - Returns `'critical'` if any validation has `level: 'error'`\n * - Returns `'caution'` if any validation has `level: 'warning'` (and no errors)\n * - Returns `undefined` otherwise (no tone applied)\n *\n * Error level always takes precedence over warning.\n */\nexport function getToneFromValidation(validations: FormNodeValidation[]): CardTone | undefined {\n  if (!validations?.length) {\n    return undefined\n  }\n\n  const validationLevels = new Set(validations.map((v) => v.level))\n\n  if (validationLevels.has('error')) {\n    return `critical`\n  } else if (validationLevels.has('warning')) {\n    return `caution`\n  }\n\n  return undefined\n}\n","import {RemoveCircleIcon} from '@sanity/icons/RemoveCircle'\nimport {Box, Button, Card, Flex, Label, Spinner, Text} from '@sanity/ui'\nimport {Menu, MenuButton, MenuItem} from '@sanity/ui/menu'\nimport {Tooltip} from '@sanity/ui/tooltip'\nimport type React from 'react'\nimport {type ReactNode, useCallback, useMemo} from 'react'\nimport {type FormPatch, type ObjectItemProps, PatchEvent, type Path, useFormValue} from 'sanity'\nimport {set, unset} from 'sanity'\n\nimport {LANGUAGE_FIELD_NAME} from '../constants'\nimport type {InternationalizedArrayItem} from '../types'\nimport {getLanguageDisplay} from '../utils/getLanguageDisplay'\nimport {getToneFromValidation} from './getToneFromValidation'\nimport {useInternationalizedArrayContext} from './InternationalizedArrayContext'\n\nfunction ChangeLanguageButton(props: {\n  value: InternationalizedArrayItem\n  path: Path\n  onChange: (patch: FormPatch[] | PatchEvent | FormPatch) => void\n}): ReactNode {\n  const {value, onChange, path} = props\n  // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n  const parentValue = useFormValue(path.slice(0, -1)) as InternationalizedArrayItem[]\n  const {languages} = useInternationalizedArrayContext()\n\n  const languageKeysInUse = useMemo(\n    () => parentValue?.map((v) => v[LANGUAGE_FIELD_NAME]) ?? [],\n    [parentValue],\n  )\n\n  // Changes the key of this item, ideally to a valid language\n  const handleKeyChange = (event: React.MouseEvent<HTMLButtonElement>): void => {\n    const languageId = event?.currentTarget?.value\n\n    if (!value || !languages?.length || !languages.find((l) => l.id === languageId)) {\n      return\n    }\n\n    onChange([set(languageId, [LANGUAGE_FIELD_NAME])])\n  }\n\n  return (\n    <MenuButton\n      button={<Button fontSize={1} text={`Change \"${value[LANGUAGE_FIELD_NAME]}\"`} />}\n      id={`${value[LANGUAGE_FIELD_NAME]}-change-key`}\n      menu={\n        <Menu>\n          {languages.map((lang) => (\n            <MenuItem\n              disabled={languageKeysInUse.includes(lang.id)}\n              fontSize={1}\n              key={lang.id}\n              text={lang.id.toLocaleUpperCase()}\n              value={lang.id}\n              onClick={handleKeyChange}\n            />\n          ))}\n        </Menu>\n      }\n      popover={{portal: true}}\n    />\n  )\n}\n\nfunction RemoveButton({\n  isDefault,\n  readOnly,\n  onChange,\n}: {\n  isDefault: boolean\n  readOnly: boolean\n  onChange: (patch: FormPatch[] | PatchEvent | FormPatch) => void\n}): ReactNode {\n  // Removes this item from the array\n  const handleUnset = (): void => {\n    onChange(unset())\n  }\n\n  return (\n    <Tooltip\n      animate\n      disabled={!isDefault}\n      content={\n        <Text muted size={1}>\n          Can&apos;t remove default language\n        </Text>\n      }\n      fallbackPlacements={['right', 'left']}\n      placement=\"top\"\n      portal\n    >\n      <span style={{paddingBottom: '2px'}}>\n        <Button\n          mode=\"bleed\"\n          icon={RemoveCircleIcon}\n          tone=\"critical\"\n          disabled={readOnly || isDefault}\n          onClick={handleUnset}\n        />\n      </span>\n    </Tooltip>\n  )\n}\n\n/**\n * Renders a single row of an internationalized array: a language label (or\n * \"Change\" menu for invalid keys), the value input, and a remove button.\n *\n * Key behaviours:\n * - Wraps `onChange` to intercept paste operations into empty Portable Text\n *   fields, ensuring `setIfMissing` and correct path prefixing.\n * - Detects items needing migration (missing `LANGUAGE_FIELD_NAME`) and hides\n *   the language label in that state.\n * - Shows a `MenuButton` with available languages when the current key is\n *   not a valid language.\n * - Disables the remove button for languages listed in `defaultLanguages`.\n * - Shows a `Spinner` when languages have not been loaded yet.\n * - Applies a `CardTone` based on validation state via `getToneFromValidation`.\n */\nexport default function InternationalizedInput(\n  props: ObjectItemProps<InternationalizedArrayItem>,\n): ReactNode {\n  // Extract the original onChange to avoid dependency issues\n  const originalOnChange = props.inputProps.onChange\n\n  // Create a wrapped onChange handler to intercept patches for paste operations\n  const wrappedOnChange = useCallback(\n    (patches: unknown) => {\n      // Ensure patches is an array before proceeding with paste logic\n      // For single patch operations (like unset), pass through directly\n      if (!Array.isArray(patches)) {\n        // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n        return originalOnChange(patches as Parameters<typeof originalOnChange>[0])\n      }\n\n      // Check if this is a paste operation into an empty or uninitialized Portable Text field\n      const valueField = props.value?.value\n      const isEmptyOrUndefined =\n        valueField === undefined ||\n        valueField === null ||\n        (Array.isArray(valueField) && valueField.length === 0)\n\n      if (isEmptyOrUndefined) {\n        // Check for insert patches that are trying to operate on a non-existent structure\n        const hasProblematicInsert = patches.some((patch: {type?: string; path?: unknown[]}) => {\n          // Ensure patch exists and has required properties\n          if (!patch || typeof patch !== 'object') {\n            return false\n          }\n\n          // Look for insert patches targeting the value field or direct array index\n          if (\n            patch.type === 'insert' &&\n            patch.path &&\n            Array.isArray(patch.path) &&\n            patch.path.length > 0\n          ) {\n            // The path might be ['value', index] or just [index] depending on context\n            const isTargetingValue = patch.path[0] === 'value' || typeof patch.path[0] === 'number'\n            return isTargetingValue\n          }\n          return false\n        })\n\n        if (hasProblematicInsert) {\n          // First, ensure the value field exists as an empty array if it doesn't\n          const initPatch =\n            valueField === undefined ? {type: 'setIfMissing', path: ['value'], value: []} : null\n\n          // Transform the patches to ensure they work with the nested structure\n          const fixedPatches = patches.map(\n            (patch: {type?: string; path?: unknown[]; [key: string]: unknown}) => {\n              // Ensure patch exists and has required properties\n              if (!patch || typeof patch !== 'object') {\n                return patch\n              }\n\n              if (patch.type === 'insert' && patch.path && Array.isArray(patch.path)) {\n                // Ensure the path is correct for the nested structure\n                const fixedPath = patch.path[0] === 'value' ? patch.path : ['value', ...patch.path]\n                const fixedPatch = {...patch, path: fixedPath}\n                return fixedPatch\n              }\n              return patch\n            },\n          )\n\n          // If we need to initialize the field, include that patch first\n          const allPatches = initPatch ? [initPatch, ...fixedPatches] : fixedPatches\n\n          // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n          return originalOnChange(allPatches as Parameters<typeof originalOnChange>[0])\n        }\n      }\n\n      // For all other cases, pass through unchanged\n      return originalOnChange(patches as Parameters<typeof originalOnChange>[0])\n    },\n    [originalOnChange, props.value?.value],\n  )\n\n  // The parent array contains the languages from the plugin config\n  const {languages, languageDisplay, defaultLanguages} = useInternationalizedArrayContext()\n\n  const keyIsValid = languages?.length\n    ? Boolean(languages.find((l) => l.id === props.value[LANGUAGE_FIELD_NAME]))\n    : false\n\n  const language = languages?.find((l) => l.id === props.value[LANGUAGE_FIELD_NAME])\n  const languageTitle: string =\n    keyIsValid && language ? getLanguageDisplay(languageDisplay, language.title, language.id) : ''\n\n  const inlineProps = useMemo(\n    () => ({\n      ...props.inputProps,\n      members: props.inputProps.members\n        .filter((m) => m.kind === 'field' && m.name === 'value')\n        .map((member) => {\n          if (member.kind !== 'field') {\n            return member\n          }\n\n          const field = member.field\n          const schemaType = field?.schemaType\n          const itemNeedsMigration = !props.value[LANGUAGE_FIELD_NAME]\n\n          const title = itemNeedsMigration ? null : keyIsValid ? (\n            <Label muted size={1}>\n              {languageTitle}\n            </Label>\n          ) : (\n            <ChangeLanguageButton\n              value={props.value}\n              path={props.path}\n              onChange={originalOnChange}\n            />\n          )\n\n          return Object.assign({}, member, {\n            field: Object.assign({}, field, {\n              schemaType: Object.assign({}, schemaType, {title}),\n            }),\n          })\n        }),\n      value: props.value,\n      // Use our wrapped onChange handler\n      onChange: wrappedOnChange,\n    }),\n    [\n      props.inputProps,\n      props.value,\n      wrappedOnChange,\n      languageTitle,\n      keyIsValid,\n      originalOnChange,\n      props.path,\n    ],\n  )\n\n  const {validation, value, readOnly} = inlineProps\n\n  if (!languages) {\n    return <Spinner />\n  }\n\n  const isDefault = defaultLanguages.includes(value[LANGUAGE_FIELD_NAME])\n\n  return (\n    <Card paddingTop={2} tone={getToneFromValidation(validation)}>\n      <Flex align=\"flex-end\" gap={2}>\n        <Box flex={1}>{props.inputProps.renderInput(inlineProps)}</Box>\n        <RemoveButton\n          isDefault={isDefault}\n          readOnly={Boolean(readOnly)}\n          onChange={originalOnChange}\n        />\n      </Flex>\n    </Card>\n  )\n}\n","import {defineField, type FieldDefinition, type FieldProps} from 'sanity'\n\nimport {createFieldName} from '../components/createFieldName'\nimport InternationalizedInput from '../components/InternationalizedInput'\nimport {LANGUAGE_FIELD_NAME} from '../constants'\n\ntype ObjectFactoryConfig = {\n  type: string | FieldDefinition\n}\n\nexport default (config: ObjectFactoryConfig) => {\n  const {type} = config\n  const typeName = typeof type === `string` ? type : type.name\n  const objectName = createFieldName(typeName, true)\n\n  return defineField({\n    name: objectName,\n    title: `Internationalized array ${typeName}`,\n    type: 'object',\n    components: {\n      // @ts-expect-error - fix typings\n      item: InternationalizedInput,\n      field: (props: FieldProps) =>\n        props.renderDefault({\n          ...props,\n          // Reset the level to avoid nested styling\n          level: 0,\n        }),\n    },\n    fields: [\n      defineField({\n        ...(typeof type === 'string' ? {type} : type),\n        name: 'value',\n      }),\n      // Hidden language field - stores the language identifier (e.g., 'en', 'fr')\n      // This replaces the previous pattern of storing language in _key\n      defineField({\n        name: 'language',\n        type: 'string',\n        hidden: true,\n        validation: (Rule) => Rule.required(),\n      }),\n    ],\n    preview: {\n      select: {\n        title: 'value',\n        subtitle: LANGUAGE_FIELD_NAME,\n      },\n    },\n  })\n}\n","import {languageFilter} from '@sanity/language-filter'\nimport {definePlugin, isObjectInputProps} from 'sanity'\n\nimport {InternationalizedArrayFormInput} from './components/InternationalizedArrayFormInput'\nimport {InternationalizedArrayLayout} from './components/InternationalizedArrayLayout'\nimport Preload from './components/Preload'\nimport {CONFIG_DEFAULT} from './constants'\nimport {internationalizedArrayFieldAction} from './fieldActions'\nimport array from './schema/array'\nimport object from './schema/object'\nimport type {PluginConfig} from './types'\nimport {hasInternationalizedArrayField} from './utils/hasInternationalizedArrayField'\n\nexport const internationalizedArray = definePlugin<PluginConfig>((config) => {\n  const pluginConfig = {...CONFIG_DEFAULT, ...config}\n  const {\n    // oxlint-disable-next-line no-useless-default-assignment\n    apiVersion = '2025-10-15',\n    select,\n    languages,\n    fieldTypes,\n    defaultLanguages,\n    buttonLocations,\n    languageFilter: languageFilterConfig,\n  } = pluginConfig\n\n  return {\n    name: 'sanity-plugin-internationalized-array',\n    // Preload languages for use throughout the Studio\n    studio: Array.isArray(languages)\n      ? undefined\n      : {\n          components: {\n            layout: (props) => (\n              <>\n                <Preload apiVersion={apiVersion} languages={languages} />\n                {props.renderDefault(props)}\n              </>\n            ),\n          },\n        },\n    // Optional: render \"add language\" buttons as field actions\n    document: {\n      components: {\n        unstable_layout: (props) => (\n          <InternationalizedArrayLayout {...props} pluginConfig={pluginConfig} />\n        ),\n      },\n      unstable_fieldActions: buttonLocations.includes('unstable__fieldAction')\n        ? (prev) => [...prev, internationalizedArrayFieldAction]\n        : undefined,\n    },\n    // Wrap document editor with a language provider\n    form: {\n      components: {\n        input: (props) => {\n          const isRootInput = props.id === 'root' && isObjectInputProps(props)\n\n          if (!isRootInput) {\n            return props.renderDefault(props)\n          }\n\n          const hasInternationalizedArray = hasInternationalizedArrayField(props.schemaType)\n\n          if (\n            hasInternationalizedArray &&\n            pluginConfig.includeForDocumentType(props.schemaType.name)\n          ) {\n            return <InternationalizedArrayFormInput {...props} pluginConfig={pluginConfig} />\n          }\n          return props.renderDefault(props)\n        },\n      },\n    },\n    // Register custom schema types for the outer array and the inner object\n    schema: {\n      types: [\n        ...fieldTypes.map((type) => array({type, apiVersion, select, languages, defaultLanguages})),\n        ...fieldTypes.map((type) => object({type})),\n      ],\n    },\n    plugins:\n      languageFilterConfig?.documentTypes?.length > 0\n        ? [\n            languageFilter({\n              documentTypes: languageFilterConfig.documentTypes,\n              supportedLanguages: languages,\n              defaultLanguages: languageFilterConfig.defaultLanguages,\n              // This is specifically not adding filterField avoid the default filter field implementation.\n              // It will be filtered in `internationalizedArray` component and will have access to the resolved languages.\n              // Rendering the fields if the language key is incorrect, providing an improved UX\n            }),\n          ]\n        : undefined,\n  }\n})\n"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"index.js","names":["{apiVersion: internationalizedArray.apiVersion}","apiVersion","getSelectedValue(internationalizedArray.select, deferredDocument)","select","useMemo(\n    () => getSelectedValue(internationalizedArray.select, deferredDocument),\n    [internationalizedArray.select, deferredDocument],\n  )","useMemo(() => {\n    // Use workspace name if available, otherwise create a stable hash\n    if (workspace?.name) {\n      return workspace.name\n    }\n    // Create a stable hash from workspace properties that matter for caching\n    const workspaceKey = {\n      name: workspace?.name,\n      title: workspace?.title,\n      // Add other stable properties as needed\n    }\n    return JSON.stringify(workspaceKey)\n  }, [workspace])","JSON.stringify(workspaceKey)","workspace?.name","workspace?.title","createCacheKey(selectedValue, workspaceId)","useMemo(\n    () => createCacheKey(selectedValue, workspaceId),\n    [selectedValue, workspaceId],\n  )","useMemo(() => {\n    if (Array.isArray(internationalizedArray.languages)) {\n      return null // Return null for synchronous arrays\n    }\n\n    // Create or get cached promise for React.use\n    return createOrGetPromise(async () => {\n      if (typeof internationalizedArray.languages === 'function') {\n        const result = await internationalizedArray.languages(client, selectedValue)\n        // Populate function cache for use outside React context\n        setFunctionCache(internationalizedArray.languages, selectedValue, result, workspaceId)\n        return result\n      }\n      return internationalizedArray.languages\n    }, cacheKey)\n  }, [internationalizedArray, client, selectedValue, workspaceId, cacheKey])","async () => {\n      if (typeof internationalizedArray.languages === 'function') {\n        const result = await internationalizedArray.languages(client, selectedValue)\n        // Populate function cache for use outside React context\n        setFunctionCache(internationalizedArray.languages, selectedValue, result, workspaceId)\n        return result\n      }\n      return internationalizedArray.languages\n    }","internationalizedArray.languages","createOrGetPromise(async () => {\n      if (typeof internationalizedArray.languages === 'function') {\n        const result = await internationalizedArray.languages(client, selectedValue)\n        // Populate function cache for use outside React context\n        setFunctionCache(internationalizedArray.languages, selectedValue, result, workspaceId)\n        return result\n      }\n      return internationalizedArray.languages\n    }, cacheKey)","languageFilterOptions.documentTypes.includes(documentType)","documentTypes","languageFilterEnabled\n      ? languages.filter((language) => selectedLanguageIds.includes(language.id))\n      : languages","useMemo(() => {\n    const languageFilterEnabled = languageFilterOptions.documentTypes.includes(documentType)\n\n    return languageFilterEnabled\n      ? languages.filter((language) => selectedLanguageIds.includes(language.id))\n      : languages\n  }, [documentType, languageFilterOptions, languages, selectedLanguageIds])","{...internationalizedArray, languages, filteredLanguages}","useMemo(\n    () => ({...internationalizedArray, languages, filteredLanguages}),\n    [filteredLanguages, internationalizedArray, languages],\n  )","<InternationalizedArrayContext.Provider value={context}>\n      {props.children}\n    </InternationalizedArrayContext.Provider>","children","InternationalizedArrayContext.Provider","_c","languages.map((language) => {\n        const languageTitle: string = getLanguageDisplay(\n          languageDisplay,\n          language.title,\n          language.id,\n        )\n        return (\n          <Button\n            key={language.id}\n            tone=\"primary\"\n            mode=\"ghost\"\n            fontSize={1}\n            data-testid={`add-${language.id}`}\n            disabled={readOnly || languagesInUse.includes(language.id)}\n            text={languageTitle}\n            // Only show plus icon if there's one row or less AND only showing codes\n            icon={\n              languages.length > MAX_COLUMNS[languageDisplay] && languageDisplay === 'codeOnly'\n                ? undefined\n                : AddIcon\n            }\n            value={language.id}\n            onClick={() => handleClick(language.id)}\n          />\n        )\n      })","languages.length","(language) => {\n        const languageTitle: string = getLanguageDisplay(\n          languageDisplay,\n          language.title,\n          language.id,\n        )\n        return (\n          <Button\n            key={language.id}\n            tone=\"primary\"\n            mode=\"ghost\"\n            fontSize={1}\n            data-testid={`add-${language.id}`}\n            disabled={readOnly || languagesInUse.includes(language.id)}\n            text={languageTitle}\n            // Only show plus icon if there's one row or less AND only showing codes\n            icon={\n              languages.length > MAX_COLUMNS[languageDisplay] && languageDisplay === 'codeOnly'\n                ? undefined\n                : AddIcon\n            }\n            value={language.id}\n            onClick={() => handleClick(language.id)}\n          />\n        )\n      }","length","<Grid\n      gridTemplateColumns={Math.min(languages.length, MAX_COLUMNS[languageDisplay])}\n      gap={2}\n      data-testid=\"add-buttons-grid\"\n    >\n      {languages.map((language) => {\n        const languageTitle: string = getLanguageDisplay(\n          languageDisplay,\n          language.title,\n          language.id,\n        )\n        return (\n          <Button\n            key={language.id}\n            tone=\"primary\"\n            mode=\"ghost\"\n            fontSize={1}\n            data-testid={`add-${language.id}`}\n            disabled={readOnly || languagesInUse.includes(language.id)}\n            text={languageTitle}\n            // Only show plus icon if there's one row or less AND only showing codes\n            icon={\n              languages.length > MAX_COLUMNS[languageDisplay] && languageDisplay === 'codeOnly'\n                ? undefined\n                : AddIcon\n            }\n            value={language.id}\n            onClick={() => handleClick(language.id)}\n          />\n        )\n      })}\n    </Grid>","Math.min(languages.length, MAX_COLUMNS[languageDisplay])","_c","(typeName: string): unknown => {\n      if (!typeName) return undefined\n\n      // Extract the base type name from internationalized array type\n      // e.g., \"internationalizedArrayBodyValue\" -> \"body\"\n      const match = typeName.match(/^internationalizedArray(.+)Value$/)\n      if (!match || !match[1]) return undefined\n\n      const baseTypeName = match[1].charAt(0).toLowerCase() + match[1].slice(1)\n\n      // Check if it's a known array-based type (Portable Text fields)\n      const arrayBasedTypes = new Set(['body', 'htmlContent', 'blockContent', 'portableText'])\n      if (arrayBasedTypes.has(baseTypeName)) {\n        return []\n      }\n\n      // Try to look up the schema type to determine if it's an array\n      const schemaType = schema.get(typeName)\n      if (schemaType && 'fields' in schemaType) {\n        // Check if this is an object type with a 'value' field\n        // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n        const fields = schemaType.fields as Array<{\n          name: string\n          type?: {jsonType?: string; name?: string; type?: string; of?: unknown}\n        }>\n        const valueField = fields.find((f) => f.name === 'value')\n        if (valueField) {\n          const fieldType = valueField.type\n          // Check if the value field is an array type\n          if (\n            fieldType?.jsonType === 'array' ||\n            fieldType?.name === 'array' ||\n            fieldType?.type === 'array' ||\n            fieldType?.of !== undefined ||\n            (fieldType?.name && arrayBasedTypes.has(fieldType.name))\n          ) {\n            return []\n          }\n        }\n      }\n\n      return undefined\n    }","(f) => f.name === 'value'","useCallback(\n    (typeName: string): unknown => {\n      if (!typeName) return undefined\n\n      // Extract the base type name from internationalized array type\n      // e.g., \"internationalizedArrayBodyValue\" -> \"body\"\n      const match = typeName.match(/^internationalizedArray(.+)Value$/)\n      if (!match || !match[1]) return undefined\n\n      const baseTypeName = match[1].charAt(0).toLowerCase() + match[1].slice(1)\n\n      // Check if it's a known array-based type (Portable Text fields)\n      const arrayBasedTypes = new Set(['body', 'htmlContent', 'blockContent', 'portableText'])\n      if (arrayBasedTypes.has(baseTypeName)) {\n        return []\n      }\n\n      // Try to look up the schema type to determine if it's an array\n      const schemaType = schema.get(typeName)\n      if (schemaType && 'fields' in schemaType) {\n        // Check if this is an object type with a 'value' field\n        // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n        const fields = schemaType.fields as Array<{\n          name: string\n          type?: {jsonType?: string; name?: string; type?: string; of?: unknown}\n        }>\n        const valueField = fields.find((f) => f.name === 'value')\n        if (valueField) {\n          const fieldType = valueField.type\n          // Check if the value field is an array type\n          if (\n            fieldType?.jsonType === 'array' ||\n            fieldType?.name === 'array' ||\n            fieldType?.type === 'array' ||\n            fieldType?.of !== undefined ||\n            (fieldType?.name && arrayBasedTypes.has(fieldType.name))\n          ) {\n            return []\n          }\n        }\n      }\n\n      return undefined\n    },\n    [schema],\n  )","async (languageId: string) => {\n      const value = getFormValue([])\n      if (!isSanityDocument(value)) {\n        toast.push({\n          status: 'error',\n          title: 'No document value found',\n        })\n        return\n      }\n      const documentsToTranslation = getDocumentsToTranslate(value, [])\n\n      const alreadyTranslated = documentsToTranslation.filter(\n        (translation) => translation?.[LANGUAGE_FIELD_NAME] === languageId,\n      )\n      const removeDuplicates = documentsToTranslation.reduce<DocumentsToTranslate[]>(\n        (filteredTranslations, translation) => {\n          if (\n            alreadyTranslated.filter(\n              (alreadyTranslation) => alreadyTranslation.pathString === translation.pathString,\n            ).length > 0\n          ) {\n            return filteredTranslations\n          }\n          const translationAlreadyExists = filteredTranslations.filter(\n            (filteredTranslation) => filteredTranslation.path === translation.path,\n          )\n\n          if (translationAlreadyExists.length > 0) {\n            return filteredTranslations\n          }\n          filteredTranslations.push(translation)\n          return filteredTranslations\n        },\n        [],\n      )\n      if (removeDuplicates.length === 0) {\n        const language = filteredLanguages.find((l) => l.id === languageId)\n        toast.push({\n          status: 'warning',\n          title: `No missing translations for ${language?.title || languageId} found.`,\n        })\n        return\n      }\n\n      // Build patches for each field missing the selected language\n      const patches: (FormSetIfMissingPatch | FormInsertPatch)[] = []\n\n      for (const toTranslate of removeDuplicates) {\n        const path = toTranslate.path\n\n        const initialValue = getInitialValueForType(toTranslate._type)\n\n        const ifMissing = setIfMissing([], path)\n        const insertValue = insert(\n          [\n            {\n              _key: randomKey(),\n              [LANGUAGE_FIELD_NAME]: languageId,\n              _type: toTranslate._type,\n              value: initialValue,\n            },\n          ],\n          'after',\n          [...path, -1],\n        )\n        patches.push(ifMissing)\n        patches.push(insertValue)\n      }\n\n      onChange(PatchEvent.from(patches.flat()))\n    }","translation","useCallback(\n    async (languageId: string) => {\n      const value = getFormValue([])\n      if (!isSanityDocument(value)) {\n        toast.push({\n          status: 'error',\n          title: 'No document value found',\n        })\n        return\n      }\n      const documentsToTranslation = getDocumentsToTranslate(value, [])\n\n      const alreadyTranslated = documentsToTranslation.filter(\n        (translation) => translation?.[LANGUAGE_FIELD_NAME] === languageId,\n      )\n      const removeDuplicates = documentsToTranslation.reduce<DocumentsToTranslate[]>(\n        (filteredTranslations, translation) => {\n          if (\n            alreadyTranslated.filter(\n              (alreadyTranslation) => alreadyTranslation.pathString === translation.pathString,\n            ).length > 0\n          ) {\n            return filteredTranslations\n          }\n          const translationAlreadyExists = filteredTranslations.filter(\n            (filteredTranslation) => filteredTranslation.path === translation.path,\n          )\n\n          if (translationAlreadyExists.length > 0) {\n            return filteredTranslations\n          }\n          filteredTranslations.push(translation)\n          return filteredTranslations\n        },\n        [],\n      )\n      if (removeDuplicates.length === 0) {\n        const language = filteredLanguages.find((l) => l.id === languageId)\n        toast.push({\n          status: 'warning',\n          title: `No missing translations for ${language?.title || languageId} found.`,\n        })\n        return\n      }\n\n      // Build patches for each field missing the selected language\n      const patches: (FormSetIfMissingPatch | FormInsertPatch)[] = []\n\n      for (const toTranslate of removeDuplicates) {\n        const path = toTranslate.path\n\n        const initialValue = getInitialValueForType(toTranslate._type)\n\n        const ifMissing = setIfMissing([], path)\n        const insertValue = insert(\n          [\n            {\n              _key: randomKey(),\n              [LANGUAGE_FIELD_NAME]: languageId,\n              _type: toTranslate._type,\n              value: initialValue,\n            },\n          ],\n          'after',\n          [...path, -1],\n        )\n        patches.push(ifMissing)\n        patches.push(insertValue)\n      }\n\n      onChange(PatchEvent.from(patches.flat()))\n    },\n    [getInitialValueForType, onChange, toast, getFormValue, filteredLanguages],\n  )","<Box>\n        <Text size={1} weight=\"semibold\">\n          Add translation to internationalized fields\n        </Text>\n      </Box>","[]","<Stack gap={3} data-testid=\"document-add-buttons\">\n      <Box>\n        <Text size={1} weight=\"semibold\">\n          Add translation to internationalized fields\n        </Text>\n      </Box>\n      <AddButtons\n        readOnly={Boolean(formState?.readOnly)}\n        handleClick={handleDocumentButtonClick}\n        languagesInUse={[]}\n      />\n    </Stack>","Boolean(formState?.readOnly)","_c","_temp","<DocumentAddButtons />","props.renderDefault(props)","props.renderDefault","<Stack gap={5}>\n        <DocumentAddButtons />\n        {props.renderDefault(props)}\n      </Stack>","_c","props.renderDefault(props)","props.renderDefault","<InternationalizedArrayProvider\n        internationalizedArray={props.pluginConfig}\n        documentType={props.documentType}\n      >\n        {props.renderDefault(props)}\n      </InternationalizedArrayProvider>","documentType","pluginConfig","props.pluginConfig","props.documentType","_c","{apiVersion: props.apiVersion}","apiVersion","_c","{portal: true, placement: 'bottom-end'}","<Button\n            mode=\"bleed\"\n            tone=\"default\"\n            fontSize={1}\n            padding={2}\n            icon={TranslateIcon}\n            aria-label=\"Add translation\"\n            title=\"Add translation\"\n            data-testid=\"add-translation-menu\"\n            disabled={readOnly}\n          />","languages.map((language) => (\n              <MenuItem\n                key={language.id}\n                text={getLanguageDisplay(languageDisplay, language.title, language.id)}\n                icon={AddIcon}\n                disabled={readOnly || languagesInUse.includes(language.id)}\n                data-testid={`field-menu-add-${language.id}`}\n                onClick={() => handleClick(language.id)}\n              />\n            ))","(language) => (\n              <MenuItem\n                key={language.id}\n                text={getLanguageDisplay(languageDisplay, language.title, language.id)}\n                icon={AddIcon}\n                disabled={readOnly || languagesInUse.includes(language.id)}\n                data-testid={`field-menu-add-${language.id}`}\n                onClick={() => handleClick(language.id)}\n              />\n            )","buttonAddAll ? (\n              <>\n                <MenuDivider />\n                <MenuItem\n                  text={addAllTitle}\n                  icon={TranslateIcon}\n                  disabled={readOnly || allFilteredLanguagesArePresent}\n                  data-testid=\"field-menu-add-all\"\n                  onClick={onAddAll}\n                />\n              </>\n            ) : null","<Menu>\n            {languages.map((language) => (\n              <MenuItem\n                key={language.id}\n                text={getLanguageDisplay(languageDisplay, language.title, language.id)}\n                icon={AddIcon}\n                disabled={readOnly || languagesInUse.includes(language.id)}\n                data-testid={`field-menu-add-${language.id}`}\n                onClick={() => handleClick(language.id)}\n              />\n            ))}\n            {buttonAddAll ? (\n              <>\n                <MenuDivider />\n                <MenuItem\n                  text={addAllTitle}\n                  icon={TranslateIcon}\n                  disabled={readOnly || allFilteredLanguagesArePresent}\n                  data-testid=\"field-menu-add-all\"\n                  onClick={onAddAll}\n                />\n              </>\n            ) : null}\n          </Menu>","<Flex justify=\"flex-end\" data-testid=\"field-menu\">\n      <MenuButton\n        id={menuId}\n        popover={{portal: true, placement: 'bottom-end'}}\n        button={\n          <Button\n            mode=\"bleed\"\n            tone=\"default\"\n            fontSize={1}\n            padding={2}\n            icon={TranslateIcon}\n            aria-label=\"Add translation\"\n            title=\"Add translation\"\n            data-testid=\"add-translation-menu\"\n            disabled={readOnly}\n          />\n        }\n        menu={\n          <Menu>\n            {languages.map((language) => (\n              <MenuItem\n                key={language.id}\n                text={getLanguageDisplay(languageDisplay, language.title, language.id)}\n                icon={AddIcon}\n                disabled={readOnly || languagesInUse.includes(language.id)}\n                data-testid={`field-menu-add-${language.id}`}\n                onClick={() => handleClick(language.id)}\n              />\n            ))}\n            {buttonAddAll ? (\n              <>\n                <MenuDivider />\n                <MenuItem\n                  text={addAllTitle}\n                  icon={TranslateIcon}\n                  disabled={readOnly || allFilteredLanguagesArePresent}\n                  data-testid=\"field-menu-add-all\"\n                  onClick={onAddAll}\n                />\n              </>\n            ) : null}\n          </Menu>\n        }\n      />\n    </Flex>","_c","_Fragment","<code>internationalizedArray</code>","<code>id</code>","<Text>\n          An array of language objects must be passed into the <code>internationalizedArray</code>{' '}\n          helper function, each with an <code>id</code> and <code>title</code> field. Example:\n        </Text>","<Card tone=\"caution\" border radius={2} padding={3}>\n      <Stack gap={4}>\n        <Text>\n          An array of language objects must be passed into the <code>internationalizedArray</code>{' '}\n          helper function, each with an <code>id</code> and <code>title</code> field. Example:\n        </Text>\n        <Card padding={2} border radius={2}>\n          <Code size={1} language=\"javascript\">\n            {JSON.stringify(schemaExample, null, 2)}\n          </Code>\n        </Card>\n      </Stack>\n    </Card>","_c","{\n  itemsNeedingMigration,\n}: MigrationBannerProps","<Box>\n          <Text size={1}>\n            <WarningOutlineIcon />\n          </Text>\n        </Box>","<Text size={1} weight=\"semibold\">\n            Data migration required\n          </Text>","<Text size={1} muted>\n            {itemsNeedingMigration.length} item\n            {itemsNeedingMigration.length === 1 ? '' : 's'}{' '}\n            {itemsNeedingMigration.length === 1 ? 'needs' : 'need'} to be migrated to the v5 format.\n          </Text>","length","itemsNeedingMigration.length === 1 ? '' : 's'","itemsNeedingMigration.length === 1 ? 'needs' : 'need'","<code>_key</code>","<code>language</code>","<Box marginTop={2}>\n            <Text size={1}>\n              This field still uses the v4 format where language is stored in <code>_key</code>.\n              Migrate to the v5 format where language is stored in <code>language</code>.{' '}\n              <a\n                rel=\"noopener noreferrer\"\n                target=\"_blank\"\n                href=\"https://github.com/sanity-io/plugins/blob/main/plugins/sanity-plugin-internationalized-array/README.md#migrate-from-v4-to-v5\"\n              >\n                Learn more\n              </a>\n              .\n            </Text>\n          </Box>","<Card tone=\"caution\" padding={3} radius={2} border>\n      <Flex gap={3} align=\"center\">\n        <Box>\n          <Text size={1}>\n            <WarningOutlineIcon />\n          </Text>\n        </Box>\n        <Stack gap={2} flex={1}>\n          <Text size={1} weight=\"semibold\">\n            Data migration required\n          </Text>\n          <Text size={1} muted>\n            {itemsNeedingMigration.length} item\n            {itemsNeedingMigration.length === 1 ? '' : 's'}{' '}\n            {itemsNeedingMigration.length === 1 ? 'needs' : 'need'} to be migrated to the v5 format.\n          </Text>\n          <Box marginTop={2}>\n            <Text size={1}>\n              This field still uses the v4 format where language is stored in <code>_key</code>.\n              Migrate to the v5 format where language is stored in <code>language</code>.{' '}\n              <a\n                rel=\"noopener noreferrer\"\n                target=\"_blank\"\n                href=\"https://github.com/sanity-io/plugins/blob/main/plugins/sanity-plugin-internationalized-array/README.md#migrate-from-v4-to-v5\"\n              >\n                Learn more\n              </a>\n              .\n            </Text>\n          </Box>\n        </Stack>\n      </Flex>\n    </Card>","_c","value?.filter((v) => !v[LANGUAGE_FIELD_NAME]) ?? []","(v) => !v[LANGUAGE_FIELD_NAME]","value?.filter","['_type']","typeof documentType === 'string' && languageFilterOptions.documentTypes.includes(documentType)","languageFilterOptions.documentTypes","typeof documentType === 'string' && builtInLanguageFilter.documentTypes.includes(documentType)","builtInLanguageFilter.documentTypes","usingLanguageFilterPlugin || usingBuiltInLanguageFilter\n        ? members.filter((member) => {\n            // This member is the outer object created by the plugin\n            // Satisfy TS\n            if (member.kind !== 'item') {\n              return false\n            }\n\n            // This is the inner \"value\" field member created by this plugin\n            const valueMember = member.item.members[0]\n\n            // Satisfy TS\n            if (!valueMember || valueMember.kind !== 'field') {\n              return false\n            }\n            // The built-in filter receives the full languages list so it can\n            // surface fields with invalid language IDs rather than hiding them.\n            // The language filter plugin does not support this.\n            return usingBuiltInLanguageFilter\n              ? internationalizedArrayLanguageFilter(\n                  member.item.schemaType,\n                  valueMember,\n                  selectedLanguageIds,\n                  member.item.value,\n                  languages,\n                )\n              : languageFilterOptions.filterField(\n                  member.item.schemaType,\n                  valueMember,\n                  selectedLanguageIds,\n                  member.item.value,\n                )\n          })\n        : members","useMemo(\n    () =>\n      usingLanguageFilterPlugin || usingBuiltInLanguageFilter\n        ? members.filter((member) => {\n            // This member is the outer object created by the plugin\n            // Satisfy TS\n            if (member.kind !== 'item') {\n              return false\n            }\n\n            // This is the inner \"value\" field member created by this plugin\n            const valueMember = member.item.members[0]\n\n            // Satisfy TS\n            if (!valueMember || valueMember.kind !== 'field') {\n              return false\n            }\n            // The built-in filter receives the full languages list so it can\n            // surface fields with invalid language IDs rather than hiding them.\n            // The language filter plugin does not support this.\n            return usingBuiltInLanguageFilter\n              ? internationalizedArrayLanguageFilter(\n                  member.item.schemaType,\n                  valueMember,\n                  selectedLanguageIds,\n                  member.item.value,\n                  languages,\n                )\n              : languageFilterOptions.filterField(\n                  member.item.schemaType,\n                  valueMember,\n                  selectedLanguageIds,\n                  member.item.value,\n                )\n          })\n        : members,\n    [\n      usingLanguageFilterPlugin,\n      usingBuiltInLanguageFilter,\n      members,\n      selectedLanguageIds,\n      languages,\n      languageFilterOptions,\n    ],\n  )","(addLanguageKeys: string[] | string) => {\n      if (readOnly) {\n        return\n      }\n      // oxlint-disable-next-line typescript/no-unsafe-type-assertion\n      const formValue = getFormValue(props.path) as InternationalizedArrayItem[]\n      if (!filteredLanguages?.length) {\n        return\n      }\n\n      const patches = createAddLanguagePatches({\n        addLanguageKeys: Array.isArray(addLanguageKeys) ? addLanguageKeys : [addLanguageKeys],\n        schemaTypeName: schemaType.name,\n        languages,\n        filteredLanguages,\n        value: formValue,\n      })\n\n      onChange([setIfMissing([]), ...patches])\n    }","filteredLanguages?.length","path","schemaType.name","useCallback(\n    (addLanguageKeys: string[] | string) => {\n      if (readOnly) {\n        return\n      }\n      // oxlint-disable-next-line typescript/no-unsafe-type-assertion\n      const formValue = getFormValue(props.path) as InternationalizedArrayItem[]\n      if (!filteredLanguages?.length) {\n        return\n      }\n\n      const patches = createAddLanguagePatches({\n        addLanguageKeys: Array.isArray(addLanguageKeys) ? addLanguageKeys : [addLanguageKeys],\n        schemaTypeName: schemaType.name,\n        languages,\n        filteredLanguages,\n        value: formValue,\n      })\n\n      onChange([setIfMissing([]), ...patches])\n    },\n    [filteredLanguages, languages, onChange, schemaType, getFormValue, props.path, readOnly],\n  )","['_rev']","isPristineDocument(useContext(EventsContext))","useContext(EventsContext)","value\n    ?.map((v) => v[LANGUAGE_FIELD_NAME] ?? v._key)\n    .filter(Boolean)\n    .join(',')","(v) => v[LANGUAGE_FIELD_NAME] ?? v._key","value\n    ?.map","useMemo(() => {\n    const languageKeys = languageKeysFromValue?.split(',') || []\n    if (!languageKeys?.length) return []\n    if (!languages?.length) return []\n\n    return languages.filter((l) => languageKeys?.find((key) => key === l.id)).map((l) => l.id)\n  }, [languageKeysFromValue, languages])","languageKeysFromValue?.split","languages?.length","[]","(l) => l.id","() => {\n    const hasAddedDefaultLanguages = defaultLanguages\n      .filter((language) => languages.find((l) => l.id === language))\n      .every((language) => addedLanguages.includes(language))\n\n    if (\n      (isPristine || documentExists) &&\n      !isDeleting &&\n      !isDeleted &&\n      !hasAddedDefaultLanguages &&\n      !shouldMigrateArray &&\n      !readOnly\n    ) {\n      const languagesToAdd = defaultLanguages\n        .filter((language) => !addedLanguages.includes(language))\n        .filter((language) => languages.find((l) => l.id === language))\n      // Account for strict mode by scheduling the update.\n      const timeout = setTimeout(() => {\n        if (!readOnly) handleAddLanguages(languagesToAdd)\n      })\n      return () => clearTimeout(timeout)\n    }\n    return undefined\n  }","[\n    isPristine,\n    documentExists,\n    isDeleted,\n    isDeleting,\n    handleAddLanguages,\n    defaultLanguages,\n    addedLanguages,\n    languages,\n    readOnly,\n    shouldMigrateArray,\n  ]","l","language","() => {\n    if (readOnly || !value?.length || !languages?.length) {\n      return\n    }\n\n    // Create a new value array in the correct order\n    // This would also strip out values that don't have a language as the key\n    const updatedValue = value\n      .reduce((acc, v) => {\n        const newIndex = languages.findIndex((l) => l.id === v?.[LANGUAGE_FIELD_NAME])\n\n        if (newIndex > -1) {\n          acc[newIndex] = v\n        }\n\n        return acc\n      }, [] as InternationalizedArrayItem[])\n      .filter(Boolean)\n\n    if (value?.length !== updatedValue.length) {\n      toast.push({\n        title: 'There was an error reordering languages',\n        status: 'warning',\n      })\n    }\n\n    onChange(set(updatedValue))\n  }","value?.length","v","useCallback(() => {\n    if (readOnly || !value?.length || !languages?.length) {\n      return\n    }\n\n    // Create a new value array in the correct order\n    // This would also strip out values that don't have a language as the key\n    const updatedValue = value\n      .reduce((acc, v) => {\n        const newIndex = languages.findIndex((l) => l.id === v?.[LANGUAGE_FIELD_NAME])\n\n        if (newIndex > -1) {\n          acc[newIndex] = v\n        }\n\n        return acc\n      }, [] as InternationalizedArrayItem[])\n      .filter(Boolean)\n\n    if (value?.length !== updatedValue.length) {\n      toast.push({\n        title: 'There was an error reordering languages',\n        status: 'warning',\n      })\n    }\n\n    onChange(set(updatedValue))\n  }, [toast, languages, onChange, value, readOnly])","useMemo(() => {\n    if (!value?.length || !languages?.length) {\n      return true\n    }\n\n    return value?.every((v) => languages.find((l) => l?.id === v?.[LANGUAGE_FIELD_NAME]))\n  }, [value, languages])","value?.every((v) => languages.find((l) => l?.id === v?.[LANGUAGE_FIELD_NAME]))","value?.every","useMemo(() => {\n    if (!value?.length || !addedLanguages.length) {\n      return []\n    }\n\n    return value\n      .map((v, vIndex) =>\n        vIndex === addedLanguages.findIndex((language) => language === v[LANGUAGE_FIELD_NAME])\n          ? null\n          : v,\n      )\n      .filter(Boolean)\n  }, [value, addedLanguages])","value\n      .map((v, vIndex) =>\n        vIndex === addedLanguages.findIndex((language) => language === v[LANGUAGE_FIELD_NAME])\n          ? null\n          : v,\n      )\n      .filter(Boolean)","(v, vIndex) =>\n        vIndex === addedLanguages.findIndex((language) => language === v[LANGUAGE_FIELD_NAME])\n          ? null\n          : v","(item) => item.id && item.title","() => {\n    if (restoreOrder && languagesOutOfOrder.length > 0 && allKeysAreLanguages && !readOnly) {\n      handleRestoreOrder()\n    }\n  }","[restoreOrder, languagesOutOfOrder, allKeysAreLanguages, handleRestoreOrder, readOnly]","languagesOutOfOrder.length","filteredLanguages.every((language) => addedLanguages.includes(language.id))","(language) => addedLanguages.includes(language.id)","useMemo(\n    () => filteredLanguages.every((language) => addedLanguages.includes(language.id)),\n    [filteredLanguages, addedLanguages],\n  )","() => {\n    handleAddLanguages(filteredLanguages.map((language) => language.id))\n  }","(language) => language.id","useCallback(() => {\n    handleAddLanguages(filteredLanguages.map((language) => language.id))\n  }, [filteredLanguages, handleAddLanguages])","<Feedback />","canAddLanguages && buttonLocations.includes('fieldMenu')","canAddLanguages && buttonLocations.includes('field') && !allFilteredLanguagesArePresent","createAddAllTitle(value, filteredLanguages)","showFieldButtons ? (\n    <Stack gap={2}>\n      <AddButtons\n        languagesInUse={addedLanguages}\n        readOnly={readOnly}\n        handleClick={handleAddLanguages}\n      />\n      {buttonAddAll ? (\n        <Button\n          tone=\"primary\"\n          mode=\"ghost\"\n          data-testid=\"add-all-languages\"\n          disabled={readOnly || allFilteredLanguagesArePresent}\n          icon={AddIcon}\n          text={addAllTitle}\n          onClick={addAllMissingLanguages}\n        />\n      ) : null}\n    </Stack>\n  ) : null","showFieldMenu ? (\n        <CompactAddButton\n          languagesInUse={addedLanguages}\n          readOnly={readOnly}\n          handleClick={handleAddLanguages}\n          onAddAll={addAllMissingLanguages}\n          buttonAddAll={buttonAddAll}\n          addAllTitle={addAllTitle}\n          allFilteredLanguagesArePresent={allFilteredLanguagesArePresent}\n        />\n      ) : null","filteredMembers.map((member) => {\n        if (member.kind === 'item') {\n          return <ArrayOfObjectsItem {...props} key={member.key} member={member} />\n        }\n        return <MemberItemError key={member.key} member={member} />\n      })","(member) => {\n        if (member.kind === 'item') {\n          return <ArrayOfObjectsItem {...props} key={member.key} member={member} />\n        }\n        return <MemberItemError key={member.key} member={member} />\n      }","member","<MigrationBanner itemsNeedingMigration={itemsNeedingMigration} />","!showFieldMenu && !showFieldButtons && !fieldHasMembers ? (\n        <Card border tone=\"transparent\" padding={3} radius={2}>\n          <Text size={1}>This internationalized field currently has no translations.</Text>\n        </Card>\n      ) : null","<Stack gap={2}>\n      {showFieldMenu ? (\n        <CompactAddButton\n          languagesInUse={addedLanguages}\n          readOnly={readOnly}\n          handleClick={handleAddLanguages}\n          onAddAll={addAllMissingLanguages}\n          buttonAddAll={buttonAddAll}\n          addAllTitle={addAllTitle}\n          allFilteredLanguagesArePresent={allFilteredLanguagesArePresent}\n        />\n      ) : null}\n      {filteredMembers.map((member) => {\n        if (member.kind === 'item') {\n          return <ArrayOfObjectsItem {...props} key={member.key} member={member} />\n        }\n        return <MemberItemError key={member.key} member={member} />\n      })}\n      <MigrationBanner itemsNeedingMigration={itemsNeedingMigration} />\n\n      {/* Give some feedback in the UI so the field doesn't look \"missing\" */}\n      {!showFieldMenu && !showFieldButtons && !fieldHasMembers ? (\n        <Card border tone=\"transparent\" padding={3} radius={2}>\n          <Text size={1}>This internationalized field currently has no translations.</Text>\n        </Card>\n      ) : null}\n\n      {fieldButtons}\n    </Stack>","_c","_temp","_temp2","_temp3","_temp4","path.slice(0, -1)","parentValue?.map((v) => v[LANGUAGE_FIELD_NAME]) ?? []","(v) => v[LANGUAGE_FIELD_NAME]","parentValue?.map","useMemo(\n    () => parentValue?.map((v) => v[LANGUAGE_FIELD_NAME]) ?? [],\n    [parentValue],\n  )","(event: React.MouseEvent<HTMLButtonElement>): void => {\n    const languageId = event?.currentTarget?.value\n\n    if (!value || !languages?.length || !languages.find((l) => l.id === languageId)) {\n      return\n    }\n\n    onChange([set(languageId, [LANGUAGE_FIELD_NAME])])\n  }","languages?.length","<Button fontSize={1} text={`Change \"${value[LANGUAGE_FIELD_NAME]}\"`} />","`Change \"${value[LANGUAGE_FIELD_NAME]}\"`","languages.map((lang) => (\n            <MenuItem\n              disabled={languageKeysInUse.includes(lang.id)}\n              fontSize={1}\n              key={lang.id}\n              text={lang.id.toLocaleUpperCase()}\n              value={lang.id}\n              onClick={handleKeyChange}\n            />\n          ))","(lang) => (\n            <MenuItem\n              disabled={languageKeysInUse.includes(lang.id)}\n              fontSize={1}\n              key={lang.id}\n              text={lang.id.toLocaleUpperCase()}\n              value={lang.id}\n              onClick={handleKeyChange}\n            />\n          )","<Menu>\n          {languages.map((lang) => (\n            <MenuItem\n              disabled={languageKeysInUse.includes(lang.id)}\n              fontSize={1}\n              key={lang.id}\n              text={lang.id.toLocaleUpperCase()}\n              value={lang.id}\n              onClick={handleKeyChange}\n            />\n          ))}\n        </Menu>","{portal: true}","<MenuButton\n      button={<Button fontSize={1} text={`Change \"${value[LANGUAGE_FIELD_NAME]}\"`} />}\n      id={`${value[LANGUAGE_FIELD_NAME]}-change-key`}\n      menu={\n        <Menu>\n          {languages.map((lang) => (\n            <MenuItem\n              disabled={languageKeysInUse.includes(lang.id)}\n              fontSize={1}\n              key={lang.id}\n              text={lang.id.toLocaleUpperCase()}\n              value={lang.id}\n              onClick={handleKeyChange}\n            />\n          ))}\n        </Menu>\n      }\n      popover={{portal: true}}\n    />","`${value[LANGUAGE_FIELD_NAME]}-change-key`","{\n  isDefault,\n  readOnly,\n  onChange,\n}: {\n  isDefault: boolean\n  readOnly: boolean\n  onChange: (patch: FormPatch[] | PatchEvent | FormPatch) => void\n}","(): void => {\n    onChange(unset())\n  }","<Text muted size={1}>\n          Can&apos;t remove default language\n        </Text>","['right', 'left']","{paddingBottom: '2px'}","<span style={{paddingBottom: '2px'}}>\n        <Button\n          mode=\"bleed\"\n          icon={RemoveCircleIcon}\n          tone=\"critical\"\n          disabled={readOnly || isDefault}\n          onClick={handleUnset}\n        />\n      </span>","readOnly || isDefault","<Tooltip\n      animate\n      disabled={!isDefault}\n      content={\n        <Text muted size={1}>\n          Can&apos;t remove default language\n        </Text>\n      }\n      fallbackPlacements={['right', 'left']}\n      placement=\"top\"\n      portal\n    >\n      <span style={{paddingBottom: '2px'}}>\n        <Button\n          mode=\"bleed\"\n          icon={RemoveCircleIcon}\n          tone=\"critical\"\n          disabled={readOnly || isDefault}\n          onClick={handleUnset}\n        />\n      </span>\n    </Tooltip>","!isDefault","(patches: unknown) => {\n      // Ensure patches is an array before proceeding with paste logic\n      // For single patch operations (like unset), pass through directly\n      if (!Array.isArray(patches)) {\n        // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n        return originalOnChange(patches as Parameters<typeof originalOnChange>[0])\n      }\n\n      // Check if this is a paste operation into an empty or uninitialized Portable Text field\n      const valueField = props.value?.value\n      const isEmptyOrUndefined =\n        valueField === undefined ||\n        valueField === null ||\n        (Array.isArray(valueField) && valueField.length === 0)\n\n      if (isEmptyOrUndefined) {\n        // Check for insert patches that are trying to operate on a non-existent structure\n        const hasProblematicInsert = patches.some((patch: {type?: string; path?: unknown[]}) => {\n          // Ensure patch exists and has required properties\n          if (!patch || typeof patch !== 'object') {\n            return false\n          }\n\n          // Look for insert patches targeting the value field or direct array index\n          if (\n            patch.type === 'insert' &&\n            patch.path &&\n            Array.isArray(patch.path) &&\n            patch.path.length > 0\n          ) {\n            // The path might be ['value', index] or just [index] depending on context\n            const isTargetingValue = patch.path[0] === 'value' || typeof patch.path[0] === 'number'\n            return isTargetingValue\n          }\n          return false\n        })\n\n        if (hasProblematicInsert) {\n          // First, ensure the value field exists as an empty array if it doesn't\n          const initPatch =\n            valueField === undefined ? {type: 'setIfMissing', path: ['value'], value: []} : null\n\n          // Transform the patches to ensure they work with the nested structure\n          const fixedPatches = patches.map(\n            (patch: {type?: string; path?: unknown[]; [key: string]: unknown}) => {\n              // Ensure patch exists and has required properties\n              if (!patch || typeof patch !== 'object') {\n                return patch\n              }\n\n              if (patch.type === 'insert' && patch.path && Array.isArray(patch.path)) {\n                // Ensure the path is correct for the nested structure\n                const fixedPath = patch.path[0] === 'value' ? patch.path : ['value', ...patch.path]\n                const fixedPatch = {...patch, path: fixedPath}\n                return fixedPatch\n              }\n              return patch\n            },\n          )\n\n          // If we need to initialize the field, include that patch first\n          const allPatches = initPatch ? [initPatch, ...fixedPatches] : fixedPatches\n\n          // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n          return originalOnChange(allPatches as Parameters<typeof originalOnChange>[0])\n        }\n      }\n\n      // For all other cases, pass through unchanged\n      return originalOnChange(patches as Parameters<typeof originalOnChange>[0])\n    }","value","(patch: {type?: string; path?: unknown[]}) => {\n          // Ensure patch exists and has required properties\n          if (!patch || typeof patch !== 'object') {\n            return false\n          }\n\n          // Look for insert patches targeting the value field or direct array index\n          if (\n            patch.type === 'insert' &&\n            patch.path &&\n            Array.isArray(patch.path) &&\n            patch.path.length > 0\n          ) {\n            // The path might be ['value', index] or just [index] depending on context\n            const isTargetingValue = patch.path[0] === 'value' || typeof patch.path[0] === 'number'\n            return isTargetingValue\n          }\n          return false\n        }","(patch: {type?: string; path?: unknown[]; [key: string]: unknown}) => {\n              // Ensure patch exists and has required properties\n              if (!patch || typeof patch !== 'object') {\n                return patch\n              }\n\n              if (patch.type === 'insert' && patch.path && Array.isArray(patch.path)) {\n                // Ensure the path is correct for the nested structure\n                const fixedPath = patch.path[0] === 'value' ? patch.path : ['value', ...patch.path]\n                const fixedPatch = {...patch, path: fixedPath}\n                return fixedPatch\n              }\n              return patch\n            }","useCallback(\n    (patches: unknown) => {\n      // Ensure patches is an array before proceeding with paste logic\n      // For single patch operations (like unset), pass through directly\n      if (!Array.isArray(patches)) {\n        // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n        return originalOnChange(patches as Parameters<typeof originalOnChange>[0])\n      }\n\n      // Check if this is a paste operation into an empty or uninitialized Portable Text field\n      const valueField = props.value?.value\n      const isEmptyOrUndefined =\n        valueField === undefined ||\n        valueField === null ||\n        (Array.isArray(valueField) && valueField.length === 0)\n\n      if (isEmptyOrUndefined) {\n        // Check for insert patches that are trying to operate on a non-existent structure\n        const hasProblematicInsert = patches.some((patch: {type?: string; path?: unknown[]}) => {\n          // Ensure patch exists and has required properties\n          if (!patch || typeof patch !== 'object') {\n            return false\n          }\n\n          // Look for insert patches targeting the value field or direct array index\n          if (\n            patch.type === 'insert' &&\n            patch.path &&\n            Array.isArray(patch.path) &&\n            patch.path.length > 0\n          ) {\n            // The path might be ['value', index] or just [index] depending on context\n            const isTargetingValue = patch.path[0] === 'value' || typeof patch.path[0] === 'number'\n            return isTargetingValue\n          }\n          return false\n        })\n\n        if (hasProblematicInsert) {\n          // First, ensure the value field exists as an empty array if it doesn't\n          const initPatch =\n            valueField === undefined ? {type: 'setIfMissing', path: ['value'], value: []} : null\n\n          // Transform the patches to ensure they work with the nested structure\n          const fixedPatches = patches.map(\n            (patch: {type?: string; path?: unknown[]; [key: string]: unknown}) => {\n              // Ensure patch exists and has required properties\n              if (!patch || typeof patch !== 'object') {\n                return patch\n              }\n\n              if (patch.type === 'insert' && patch.path && Array.isArray(patch.path)) {\n                // Ensure the path is correct for the nested structure\n                const fixedPath = patch.path[0] === 'value' ? patch.path : ['value', ...patch.path]\n                const fixedPatch = {...patch, path: fixedPath}\n                return fixedPatch\n              }\n              return patch\n            },\n          )\n\n          // If we need to initialize the field, include that patch first\n          const allPatches = initPatch ? [initPatch, ...fixedPatches] : fixedPatches\n\n          // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n          return originalOnChange(allPatches as Parameters<typeof originalOnChange>[0])\n        }\n      }\n\n      // For all other cases, pass through unchanged\n      return originalOnChange(patches as Parameters<typeof originalOnChange>[0])\n    },\n    [originalOnChange, props.value?.value],\n  )","languages?.length\n    ? Boolean(languages.find((l) => l.id === props.value[LANGUAGE_FIELD_NAME]))\n    : false","keyIsValid && language ? getLanguageDisplay(languageDisplay, language.title, language.id) : ''","languages?.find","l","props.inputProps.members\n        .filter((m) => m.kind === 'field' && m.name === 'value')\n        .map((member) => {\n          if (member.kind !== 'field') {\n            return member\n          }\n\n          const field = member.field\n          const schemaType = field?.schemaType\n          const itemNeedsMigration = !props.value[LANGUAGE_FIELD_NAME]\n\n          const title = itemNeedsMigration ? null : keyIsValid ? (\n            <Label muted size={1}>\n              {languageTitle}\n            </Label>\n          ) : (\n            <ChangeLanguageButton\n              value={props.value}\n              path={props.path}\n              onChange={originalOnChange}\n            />\n          )\n\n          return Object.assign({}, member, {\n            field: Object.assign({}, field, {\n              schemaType: Object.assign({}, schemaType, {title}),\n            }),\n          })\n        })","members","path","(member) => {\n          if (member.kind !== 'field') {\n            return member\n          }\n\n          const field = member.field\n          const schemaType = field?.schemaType\n          const itemNeedsMigration = !props.value[LANGUAGE_FIELD_NAME]\n\n          const title = itemNeedsMigration ? null : keyIsValid ? (\n            <Label muted size={1}>\n              {languageTitle}\n            </Label>\n          ) : (\n            <ChangeLanguageButton\n              value={props.value}\n              path={props.path}\n              onChange={originalOnChange}\n            />\n          )\n\n          return Object.assign({}, member, {\n            field: Object.assign({}, field, {\n              schemaType: Object.assign({}, schemaType, {title}),\n            }),\n          })\n        }","(m) => m.kind === 'field' && m.name === 'value'","{\n      ...props.inputProps,\n      members: props.inputProps.members\n        .filter((m) => m.kind === 'field' && m.name === 'value')\n        .map((member) => {\n          if (member.kind !== 'field') {\n            return member\n          }\n\n          const field = member.field\n          const schemaType = field?.schemaType\n          const itemNeedsMigration = !props.value[LANGUAGE_FIELD_NAME]\n\n          const title = itemNeedsMigration ? null : keyIsValid ? (\n            <Label muted size={1}>\n              {languageTitle}\n            </Label>\n          ) : (\n            <ChangeLanguageButton\n              value={props.value}\n              path={props.path}\n              onChange={originalOnChange}\n            />\n          )\n\n          return Object.assign({}, member, {\n            field: Object.assign({}, field, {\n              schemaType: Object.assign({}, schemaType, {title}),\n            }),\n          })\n        }),\n      value: props.value,\n      // Use our wrapped onChange handler\n      onChange: wrappedOnChange,\n    }","inputProps","props.inputProps","useMemo(\n    () => ({\n      ...props.inputProps,\n      members: props.inputProps.members\n        .filter((m) => m.kind === 'field' && m.name === 'value')\n        .map((member) => {\n          if (member.kind !== 'field') {\n            return member\n          }\n\n          const field = member.field\n          const schemaType = field?.schemaType\n          const itemNeedsMigration = !props.value[LANGUAGE_FIELD_NAME]\n\n          const title = itemNeedsMigration ? null : keyIsValid ? (\n            <Label muted size={1}>\n              {languageTitle}\n            </Label>\n          ) : (\n            <ChangeLanguageButton\n              value={props.value}\n              path={props.path}\n              onChange={originalOnChange}\n            />\n          )\n\n          return Object.assign({}, member, {\n            field: Object.assign({}, field, {\n              schemaType: Object.assign({}, schemaType, {title}),\n            }),\n          })\n        }),\n      value: props.value,\n      // Use our wrapped onChange handler\n      onChange: wrappedOnChange,\n    }),\n    [\n      props.inputProps,\n      props.value,\n      wrappedOnChange,\n      languageTitle,\n      keyIsValid,\n      originalOnChange,\n      props.path,\n    ],\n  )","<Spinner />","defaultLanguages.includes(value[LANGUAGE_FIELD_NAME])","getToneFromValidation(validation)","props.inputProps.renderInput(inlineProps)","<Box flex={1}>{props.inputProps.renderInput(inlineProps)}</Box>","<RemoveButton\n          isDefault={isDefault}\n          readOnly={Boolean(readOnly)}\n          onChange={originalOnChange}\n        />","Boolean(readOnly)","<Flex align=\"flex-end\" gap={2}>\n        <Box flex={1}>{props.inputProps.renderInput(inlineProps)}</Box>\n        <RemoveButton\n          isDefault={isDefault}\n          readOnly={Boolean(readOnly)}\n          onChange={originalOnChange}\n        />\n      </Flex>","<Card paddingTop={2} tone={getToneFromValidation(validation)}>\n      <Flex align=\"flex-end\" gap={2}>\n        <Box flex={1}>{props.inputProps.renderInput(inlineProps)}</Box>\n        <RemoveButton\n          isDefault={isDefault}\n          readOnly={Boolean(readOnly)}\n          onChange={originalOnChange}\n        />\n      </Flex>\n    </Card>","patch","_c","_Fragment","array","object","\"language\"","\"_key\""],"sources":["../src/cache.ts","../src/constants.ts","../src/utils/getDocumentsToTranslate.ts","../src/utils/getLanguageDisplay.ts","../src/components/getSelectedValue.ts","../src/components/InternationalizedArrayContext.tsx","../src/components/AddButtons.tsx","../src/components/DocumentAddButtons.tsx","../src/components/InternationalizedArrayFormInput.tsx","../src/utils/hasInternationalizedArrayField.ts","../src/components/InternationalizedArrayLayout.tsx","../src/components/Preload.tsx","../src/utils/checkAllLanguagesArePresent.ts","../src/utils/createAddAllTitle.ts","../src/types.ts","../src/utils/createAddLanguagePatches.ts","../src/fieldActions/index.ts","../src/components/createFieldName.ts","../src/utils/internationalizedArrayLanguageFilter.ts","../src/components/CompactAddButton.tsx","../src/components/Feedback.tsx","../src/components/MigrationBanner.tsx","../src/components/InternationalizedArray.tsx","../src/utils/getLanguagesFieldOption.ts","../src/schema/array.ts","../src/components/getToneFromValidation.ts","../src/components/InternationalizedInput.tsx","../src/schema/object.ts","../src/plugin.tsx"],"sourcesContent":["import type {Language, LanguageCallback} from './types'\n\nconst namespace = 'sanity-plugin-internationalized-array'\n\nconst version = 'v1'\n\n// Cache for function keys to avoid recalculating them\nconst functionKeyCache = new WeakMap<LanguageCallback, string>()\n\n// Cache for React.use promises\nconst promiseCache = new Map<string, Promise<Language[]>>()\n\n// Cache for function references to enable sharing between same functions\nconst functionCache = new Map<string, Language[]>()\n\n// Helper to create a cache key string from an array\nfunction stringifyCacheKey(key: unknown[]): string {\n  return JSON.stringify(key)\n}\n\n// Enhanced preload function that can use custom cache keys\nexport const preloadWithKey = (fn: () => Promise<Language[]>, key: (string | number)[]) => {\n  const keyStr = stringifyCacheKey(key)\n  if (!promiseCache.has(keyStr)) {\n    promiseCache.set(keyStr, fn())\n  }\n}\n\n// Cache busting: clear all promise caches\nexport const clear = () => {\n  promiseCache.clear()\n}\n\n// Peeking into entries outside of suspense\nexport const peek = (selectedValue: Record<string, unknown>) => {\n  const key = stringifyCacheKey([version, namespace, selectedValue])\n  const promise = promiseCache.get(key)\n  if (promise) {\n    // Check if promise is resolved\n    // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n    const status = (promise as any)._status\n    if (status === 'fulfilled') {\n      // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n      return (promise as any)._value as Language[] | undefined\n    }\n  }\n  return undefined\n}\n\n// Helper function to create a stable cache key that matches the component's key structure\nexport const createCacheKey = (selectedValue: Record<string, unknown>, workspaceId?: string) => {\n  const selectedValueHash = JSON.stringify(selectedValue)\n  return workspaceId\n    ? [version, namespace, selectedValueHash, workspaceId]\n    : [version, namespace, selectedValueHash]\n}\n\n// Create or get cached promise for React.use\nexport const createOrGetPromise = (\n  fn: () => Promise<Language[]>,\n  key: (string | number | Record<string, unknown>)[],\n): Promise<Language[]> => {\n  const keyStr = stringifyCacheKey(key)\n  if (promiseCache.has(keyStr)) {\n    return promiseCache.get(keyStr)!\n  }\n  const promise = fn()\n  promiseCache.set(keyStr, promise)\n  return promise\n}\n\n// Generate a unique key for a function reference (cached for performance)\nconst getFunctionKey = (fn: LanguageCallback): string => {\n  // Check if we already have a cached key for this function\n  const cachedKey = functionKeyCache.get(fn)\n  if (cachedKey) {\n    return cachedKey\n  }\n\n  // Create a hash for functions (only when needed)\n  const fnStr = fn.toString()\n  let hash = 0\n  // Only hash the first 100 characters for performance\n  const maxLength = Math.min(fnStr.length, 100)\n  for (let i = 0; i < maxLength; i++) {\n    const char = fnStr.charCodeAt(i)\n    hash = (hash << 5) - hash + char\n    hash &= hash // Convert to 32-bit integer\n  }\n  const key = `anonymous_${Math.abs(hash)}`\n  functionKeyCache.set(fn, key)\n  return key\n}\n\n// Create a cache key that includes function identity\nconst createFunctionCacheKey = (\n  fn: LanguageCallback,\n  selectedValue: Record<string, unknown>,\n  workspaceId?: string,\n): string => {\n  const functionKey = getFunctionKey(fn)\n  const selectedValueHash = JSON.stringify(selectedValue)\n  return workspaceId\n    ? `${functionKey}:${selectedValueHash}:${workspaceId}`\n    : `${functionKey}:${selectedValueHash}`\n}\n\n// Function-aware cache operations\nexport const getFunctionCache = (\n  fn: LanguageCallback,\n  selectedValue: Record<string, unknown>,\n  workspaceId?: string,\n): Language[] | undefined => {\n  const key = createFunctionCacheKey(fn, selectedValue, workspaceId)\n  return functionCache.get(key)\n}\n\nexport const setFunctionCache = (\n  fn: LanguageCallback,\n  selectedValue: Record<string, unknown>,\n  languages: Language[],\n  workspaceId?: string,\n): void => {\n  const key = createFunctionCacheKey(fn, selectedValue, workspaceId)\n  functionCache.set(key, languages)\n}\n","import type {PluginConfig} from './types'\n\n/**\n * The field name used to identify the language of an internationalized array item.\n *\n * In v4.x this was '_key', in v5+ this is 'language'.\n * ```ts\n * {\n *    \"description\": [\n *      {\n *        \"_key\": \"kjjNvZHK8Y2QpTEf3K5jc\",\n *        \"_type\": \"internationalizedArrayTextValue\",\n *        \"language\": \"en\"\n *        \"value\": \"This is the description in English\"\n *      },\n *      {\n *        \"_key\": \"kjjNvZHK8Y2QpTEf3K5jc\",\n *        \"_type\": \"internationalizedArrayTextValue\",\n *        \"language\": \"es\"\n *        \"value\": \"This is the description in Spanish\"\n *      },\n *    ]\n * }\n * ```\n */\nexport const LANGUAGE_FIELD_NAME = 'language' as const\n\nexport const MAX_COLUMNS = {\n  codeOnly: 5,\n  titleOnly: 4,\n  titleAndCode: 3,\n}\n\nexport const CONFIG_DEFAULT: Required<PluginConfig> = {\n  languages: [],\n  select: {},\n  defaultLanguages: [],\n  fieldTypes: [],\n  apiVersion: '2025-10-15',\n  buttonLocations: ['field'],\n  buttonAddAll: true,\n  restoreOrder: true,\n  languageDisplay: 'codeOnly',\n  includeForDocumentType: (documentType) => documentType !== 'translation.metadata',\n  languageFilter: {\n    documentTypes: [],\n  },\n}\n","import type {SanityDocument} from 'sanity'\n\nexport interface DocumentsToTranslate {\n  path: (string | number)[]\n  pathString: string\n  _key: string\n  /** Language identifier (e.g., 'en', 'fr'). Added in v5. */\n  language: string\n  _type: string\n  [key: string]: unknown\n}\n\n/**\n * Recursively traverses a Sanity document (or any nested value) and collects\n * all internationalized array items found within it.\n *\n * An item is considered an internationalized array value when its `_type`\n * starts with `\"internationalizedArray\"` and ends with `\"Value\"`.\n *\n * The function walks through objects and arrays, skipping keys that start\n * with `_` (internal Sanity fields like `_id`, `_type`, `_rev`). Each\n * returned item includes the original properties plus `path` (array of\n * segments) and `pathString` (dot-joined) indicating where it was found.\n */\nexport const getDocumentsToTranslate = (\n  // oxlint-disable-next-line typescript-eslint/no-redundant-type-constituents\n  value: SanityDocument | unknown,\n  rootPath: (string | number)[] = [],\n): DocumentsToTranslate[] => {\n  if (Array.isArray(value)) {\n    const arrayRootPath = [...rootPath]\n\n    // if item contains internationalized return array\n    const internationalizedValues = value.filter((item) => {\n      if (Array.isArray(item)) return false\n\n      if (typeof item === 'object') {\n        // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n        const type = item?._type as string | undefined\n        return type?.startsWith('internationalizedArray') && type?.endsWith('Value')\n      }\n      return false\n    })\n\n    if (internationalizedValues.length > 0) {\n      return internationalizedValues.map((internationalizedValue) => {\n        return Object.assign({}, internationalizedValue, {\n          path: arrayRootPath,\n          pathString: arrayRootPath.join('.'),\n        })\n      })\n    }\n\n    if (value.length > 0) {\n      return value.flatMap((item, index) =>\n        getDocumentsToTranslate(item, [...arrayRootPath, index]),\n      )\n    }\n\n    return []\n  }\n  if (typeof value === 'object' && value) {\n    const startsWithUnderscoreRegex = /^_/\n    const itemKeys = Object.keys(value).filter(\n      (key) => !key.match(startsWithUnderscoreRegex),\n      // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n    ) as (keyof typeof value)[]\n\n    return itemKeys.flatMap((item) => {\n      const selectedValue = value[item] as unknown\n      const path = [...rootPath, item]\n      return getDocumentsToTranslate(selectedValue, path)\n    })\n  }\n  return []\n}\n","import type {LanguageDisplay} from '../types'\n\n/**\n * Formats a language label for display in buttons and field headers\n * based on the configured `languageDisplay` mode:\n *\n * - `'codeOnly'`      -> uppercase code, e.g. `\"EN\"`\n * - `'titleOnly'`     -> title as-is, e.g. `\"English\"`\n * - `'titleAndCode'`  -> title with uppercase code, e.g. `\"English (EN)\"`\n *\n * Falls back to `title` for any unrecognized display mode.\n */\nexport function getLanguageDisplay(\n  languageDisplay: LanguageDisplay,\n  title: string,\n  code: string,\n): string {\n  if (languageDisplay === 'codeOnly') return code.toUpperCase()\n  if (languageDisplay === 'titleOnly') return title\n  if (languageDisplay === 'titleAndCode') return `${title} (${code.toUpperCase()})`\n  return title\n}\n","import get from 'lodash-es/get.js'\n\n/**\n * Extracts a subset of values from a Sanity document based on a `select`\n * mapping (as configured in the plugin's `select` option).\n *\n * Each key in `select` becomes a key in the returned object, with its value\n * resolved from the document using the corresponding dot-path (via lodash `get`).\n *\n * Array values are filtered to remove incomplete references (objects with\n * `_type: 'reference'` but no `_ref`), since those represent empty reference\n * fields that should be ignored.\n *\n * Returns an empty object when either `select` or `document` is undefined.\n */\nexport const getSelectedValue = (\n  select: Record<string, string> | undefined,\n  document:\n    | {\n        [x: string]: unknown\n      }\n    | undefined,\n): Record<string, unknown> => {\n  if (!select || !document) {\n    return {}\n  }\n\n  const selection: Record<string, string> = select || {}\n  const selectedValue: Record<string, unknown> = {}\n  for (const [key, path] of Object.entries(selection)) {\n    let value = get(document, path)\n    if (Array.isArray(value)) {\n      // If there are references in the array, ensure they have `_ref` set, otherwise they are considered empty and can safely be ignored\n      value = value.filter((item) =>\n        typeof item === 'object' ? item?._type === 'reference' && '_ref' in item : true,\n      )\n    }\n    selectedValue[key] = value\n  }\n\n  return selectedValue\n}\n","import {useLanguageFilterStudioContext} from '@sanity/language-filter'\nimport type React from 'react'\nimport {createContext, use, useContext, useDeferredValue, useMemo} from 'react'\nimport {useClient, useWorkspace} from 'sanity'\nimport {useDocumentPane} from 'sanity/structure'\n\nimport {createCacheKey, createOrGetPromise, setFunctionCache} from '../cache'\nimport {CONFIG_DEFAULT} from '../constants'\nimport type {Language, PluginConfig} from '../types'\nimport {getSelectedValue} from './getSelectedValue'\n\n// This provider makes the plugin config available to all components in the document form\n// But with languages resolved and filtered languages updated base on @sanity/language-filter\n\nexport type InternationalizedArrayContextProps = Required<PluginConfig> & {\n  languages: Language[]\n  filteredLanguages: Language[]\n}\n\nconst InternationalizedArrayContext = createContext<InternationalizedArrayContextProps>({\n  ...CONFIG_DEFAULT,\n  languages: [],\n  filteredLanguages: [],\n})\n\nexport function useInternationalizedArrayContext(): InternationalizedArrayContextProps {\n  return useContext(InternationalizedArrayContext)\n}\n\ntype InternationalizedArrayProviderProps = {\n  internationalizedArray: Required<PluginConfig>\n  documentType: string\n}\n\nexport function InternationalizedArrayProvider(\n  props: React.PropsWithChildren<InternationalizedArrayProviderProps>,\n): React.ReactElement {\n  const {internationalizedArray, documentType} = props\n\n  const client = useClient({apiVersion: internationalizedArray.apiVersion})\n  const workspace = useWorkspace()\n  const {formState} = useDocumentPane()\n  const deferredDocument = useDeferredValue(formState?.value)\n  const selectedValue = useMemo(\n    () => getSelectedValue(internationalizedArray.select, deferredDocument),\n    [internationalizedArray.select, deferredDocument],\n  )\n\n  // Use a stable workspace identifier to prevent unnecessary re-renders\n  const workspaceId = useMemo(() => {\n    // Use workspace name if available, otherwise create a stable hash\n    if (workspace?.name) {\n      return workspace.name\n    }\n    // Create a stable hash from workspace properties that matter for caching\n    const workspaceKey = {\n      name: workspace?.name,\n      title: workspace?.title,\n      // Add other stable properties as needed\n    }\n    return JSON.stringify(workspaceKey)\n  }, [workspace])\n\n  // Memoize the cache key to prevent expensive JSON.stringify calls\n  const cacheKey = useMemo(\n    () => createCacheKey(selectedValue, workspaceId),\n    [selectedValue, workspaceId],\n  )\n\n  // Fetch or return languages\n  const languagesPromise = useMemo(() => {\n    if (Array.isArray(internationalizedArray.languages)) {\n      return null // Return null for synchronous arrays\n    }\n\n    // Create or get cached promise for React.use\n    return createOrGetPromise(async () => {\n      if (typeof internationalizedArray.languages === 'function') {\n        const result = await internationalizedArray.languages(client, selectedValue)\n        // Populate function cache for use outside React context\n        setFunctionCache(internationalizedArray.languages, selectedValue, result, workspaceId)\n        return result\n      }\n      return internationalizedArray.languages\n    }, cacheKey)\n  }, [internationalizedArray, client, selectedValue, workspaceId, cacheKey])\n\n  // Use React.use to handle the promise with Suspense, or return array directly\n  const languages = languagesPromise\n    ? use(languagesPromise)\n    : // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n      (internationalizedArray.languages as Language[])\n\n  // Filter out some languages if language filter is enabled\n  const {selectedLanguageIds, options: languageFilterOptions} = useLanguageFilterStudioContext()\n\n  const filteredLanguages = useMemo(() => {\n    const languageFilterEnabled = languageFilterOptions.documentTypes.includes(documentType)\n\n    return languageFilterEnabled\n      ? languages.filter((language) => selectedLanguageIds.includes(language.id))\n      : languages\n  }, [documentType, languageFilterOptions, languages, selectedLanguageIds])\n\n  const context = useMemo(\n    () => ({...internationalizedArray, languages, filteredLanguages}),\n    [filteredLanguages, internationalizedArray, languages],\n  )\n\n  return (\n    <InternationalizedArrayContext.Provider value={context}>\n      {props.children}\n    </InternationalizedArrayContext.Provider>\n  )\n}\n","import {AddIcon} from '@sanity/icons/Add'\nimport {Button, Grid} from '@sanity/ui'\n\nimport {MAX_COLUMNS} from '../constants'\nimport {getLanguageDisplay} from '../utils/getLanguageDisplay'\nimport {useInternationalizedArrayContext} from './InternationalizedArrayContext'\n\ntype AddButtonsProps = {\n  readOnly: boolean\n  handleClick: (languageId: string) => void\n  // Keys of languages that are already in use\n  languagesInUse: string[]\n}\n\n/**\n * Renders a grid of \"add language\" buttons — one per configured language.\n *\n * Returns `null` when the `languages` array is empty.\n *\n * Each button is disabled when:\n * - `readOnly` is `true`, or\n * - the language already exists in the current `value` array\n *   (matched via `LANGUAGE_FIELD_NAME`).\n *\n * The button label is formatted according to the `languageDisplay` setting\n * from the plugin context (e.g. code-only, title-only, or both).\n * An `AddIcon` is shown unless there are more languages than fit in one row\n * and the display mode is `'codeOnly'`.\n */\nfunction AddButtons(props: AddButtonsProps) {\n  const {readOnly, languagesInUse, handleClick} = props\n  const {languageDisplay, filteredLanguages: languages} = useInternationalizedArrayContext()\n\n  if (!languages.length) return null\n\n  return (\n    <Grid\n      gridTemplateColumns={Math.min(languages.length, MAX_COLUMNS[languageDisplay])}\n      gap={2}\n      data-testid=\"add-buttons-grid\"\n    >\n      {languages.map((language) => {\n        const languageTitle: string = getLanguageDisplay(\n          languageDisplay,\n          language.title,\n          language.id,\n        )\n        return (\n          <Button\n            key={language.id}\n            tone=\"primary\"\n            mode=\"ghost\"\n            fontSize={1}\n            data-testid={`add-${language.id}`}\n            disabled={readOnly || languagesInUse.includes(language.id)}\n            text={languageTitle}\n            // Only show plus icon if there's one row or less AND only showing codes\n            icon={\n              languages.length > MAX_COLUMNS[languageDisplay] && languageDisplay === 'codeOnly'\n                ? undefined\n                : AddIcon\n            }\n            value={language.id}\n            onClick={() => handleClick(language.id)}\n          />\n        )\n      })}\n    </Grid>\n  )\n}\n\nexport default AddButtons\n","import {Box, Stack, Text} from '@sanity/ui'\nimport {useToast} from '@sanity/ui/toast'\nimport {randomKey} from '@sanity/util/content'\nimport {type ReactElement, useCallback} from 'react'\nimport {\n  type FormInsertPatch,\n  type FormSetIfMissingPatch,\n  insert,\n  isSanityDocument,\n  PatchEvent,\n  setIfMissing,\n  useGetFormValue,\n  useSchema,\n} from 'sanity'\nimport {useDocumentPane} from 'sanity/structure'\n\nimport {LANGUAGE_FIELD_NAME} from '../constants'\nimport type {DocumentsToTranslate} from '../utils/getDocumentsToTranslate'\nimport {getDocumentsToTranslate} from '../utils/getDocumentsToTranslate'\nimport AddButtons from './AddButtons'\nimport {useInternationalizedArrayContext} from './InternationalizedArrayContext'\n\n/**\n * Document-level \"add translation\" panel that appears outside individual\n * internationalized array fields (when `buttonLocations` includes `'document'`).\n *\n * Renders a heading and a row of per-language buttons. When a language button\n * is clicked the component:\n *\n * 1. Scans the current document for all internationalized array fields\n *    using `getDocumentsToTranslate`.\n * 2. Filters out fields that already contain a translation for the selected\n *    language, and deduplicates by field path.\n * 3. Shows an error toast if no eligible fields remain.\n * 4. Creates `setIfMissing` + `insert` patches to add the new language\n *    entry to each eligible field, dispatching them via `onChange`.\n *\n * For Portable Text and other array-based value fields, the initial value\n * is set to an empty array (`[]`) rather than `undefined`.\n */\nexport default function DocumentAddButtons(): ReactElement {\n  const getFormValue = useGetFormValue()\n  const {filteredLanguages} = useInternationalizedArrayContext()\n\n  const toast = useToast()\n  const {onChange, formState} = useDocumentPane()\n  const schema = useSchema()\n\n  // Array-based types (e.g. Portable Text) need [] as initial value, not undefined\n  const getInitialValueForType = useCallback(\n    (typeName: string): unknown => {\n      if (!typeName) return undefined\n\n      // Extract the base type name from internationalized array type\n      // e.g., \"internationalizedArrayBodyValue\" -> \"body\"\n      const match = typeName.match(/^internationalizedArray(.+)Value$/)\n      if (!match || !match[1]) return undefined\n\n      const baseTypeName = match[1].charAt(0).toLowerCase() + match[1].slice(1)\n\n      // Check if it's a known array-based type (Portable Text fields)\n      const arrayBasedTypes = new Set(['body', 'htmlContent', 'blockContent', 'portableText'])\n      if (arrayBasedTypes.has(baseTypeName)) {\n        return []\n      }\n\n      // Try to look up the schema type to determine if it's an array\n      const schemaType = schema.get(typeName)\n      if (schemaType && 'fields' in schemaType) {\n        // Check if this is an object type with a 'value' field\n        // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n        const fields = schemaType.fields as Array<{\n          name: string\n          type?: {jsonType?: string; name?: string; type?: string; of?: unknown}\n        }>\n        const valueField = fields.find((f) => f.name === 'value')\n        if (valueField) {\n          const fieldType = valueField.type\n          // Check if the value field is an array type\n          if (\n            fieldType?.jsonType === 'array' ||\n            fieldType?.name === 'array' ||\n            fieldType?.type === 'array' ||\n            fieldType?.of !== undefined ||\n            (fieldType?.name && arrayBasedTypes.has(fieldType.name))\n          ) {\n            return []\n          }\n        }\n      }\n\n      return undefined\n    },\n    [schema],\n  )\n\n  const handleDocumentButtonClick = useCallback(\n    async (languageId: string) => {\n      const value = getFormValue([])\n      if (!isSanityDocument(value)) {\n        toast.push({\n          status: 'error',\n          title: 'No document value found',\n        })\n        return\n      }\n      const documentsToTranslation = getDocumentsToTranslate(value, [])\n\n      const alreadyTranslated = documentsToTranslation.filter(\n        (translation) => translation?.[LANGUAGE_FIELD_NAME] === languageId,\n      )\n      const removeDuplicates = documentsToTranslation.reduce<DocumentsToTranslate[]>(\n        (filteredTranslations, translation) => {\n          if (\n            alreadyTranslated.filter(\n              (alreadyTranslation) => alreadyTranslation.pathString === translation.pathString,\n            ).length > 0\n          ) {\n            return filteredTranslations\n          }\n          const translationAlreadyExists = filteredTranslations.filter(\n            (filteredTranslation) => filteredTranslation.path === translation.path,\n          )\n\n          if (translationAlreadyExists.length > 0) {\n            return filteredTranslations\n          }\n          filteredTranslations.push(translation)\n          return filteredTranslations\n        },\n        [],\n      )\n      if (removeDuplicates.length === 0) {\n        const language = filteredLanguages.find((l) => l.id === languageId)\n        toast.push({\n          status: 'warning',\n          title: `No missing translations for ${language?.title || languageId} found.`,\n        })\n        return\n      }\n\n      // Build patches for each field missing the selected language\n      const patches: (FormSetIfMissingPatch | FormInsertPatch)[] = []\n\n      for (const toTranslate of removeDuplicates) {\n        const path = toTranslate.path\n\n        const initialValue = getInitialValueForType(toTranslate._type)\n\n        const ifMissing = setIfMissing([], path)\n        const insertValue = insert(\n          [\n            {\n              _key: randomKey(),\n              [LANGUAGE_FIELD_NAME]: languageId,\n              _type: toTranslate._type,\n              value: initialValue,\n            },\n          ],\n          'after',\n          [...path, -1],\n        )\n        patches.push(ifMissing)\n        patches.push(insertValue)\n      }\n\n      onChange(PatchEvent.from(patches.flat()))\n    },\n    [getInitialValueForType, onChange, toast, getFormValue, filteredLanguages],\n  )\n  return (\n    <Stack gap={3} data-testid=\"document-add-buttons\">\n      <Box>\n        <Text size={1} weight=\"semibold\">\n          Add translation to internationalized fields\n        </Text>\n      </Box>\n      <AddButtons\n        readOnly={Boolean(formState?.readOnly)}\n        handleClick={handleDocumentButtonClick}\n        languagesInUse={[]}\n      />\n    </Stack>\n  )\n}\n","import {Stack} from '@sanity/ui'\nimport type {ObjectInputProps} from 'sanity'\n\nimport type {PluginConfig} from '../types'\nimport DocumentAddButtons from './DocumentAddButtons'\n\n/**\n * An input component for the root object of an internationalized array.\n * It renders the document add buttons if the buttonLocations include 'document'.\n */\nexport function InternationalizedArrayFormInput(\n  props: ObjectInputProps & {pluginConfig: PluginConfig},\n) {\n  const showDocumentButtons = props.pluginConfig?.buttonLocations?.includes('document')\n\n  if (showDocumentButtons) {\n    return (\n      <Stack gap={5}>\n        <DocumentAddButtons />\n        {props.renderDefault(props)}\n      </Stack>\n    )\n  }\n  return props.renderDefault(props)\n}\n","import {isDocumentSchemaType, type ObjectField, type SchemaType} from 'sanity'\n\n/**\n * Returns true when a document schema contains any field (including nested\n * object/array item fields) whose type name starts with `internationalizedArray`.\n *\n * Traversal short-circuits on first match to avoid unnecessary work.\n */\nexport function hasInternationalizedArrayField(schemaType: SchemaType): boolean {\n  if (!isDocumentSchemaType(schemaType)) {\n    return false\n  }\n\n  return hasInternationalizedArrayInFields(schemaType.fields)\n}\n\nfunction hasInternationalizedArrayInFields(\n  fields: ObjectField[],\n  visited = new Set<unknown>(),\n): boolean {\n  for (const field of fields) {\n    if (visited.has(field.type)) {\n      continue\n    }\n    visited.add(field.type)\n\n    if (field.type.name.startsWith('internationalizedArray')) {\n      return true\n    }\n\n    if (\n      field.type.jsonType === 'object' &&\n      hasInternationalizedArrayInFields(field.type.fields, visited)\n    ) {\n      return true\n    }\n\n    if (field.type.jsonType === 'array' && field.type.of.length > 0) {\n      for (const item of field.type.of) {\n        if (\n          'name' in item &&\n          typeof item.name === 'string' &&\n          item.name.startsWith('internationalizedArray')\n        ) {\n          return true\n        }\n\n        if ('fields' in item && Array.isArray(item.fields)) {\n          if (visited.has(item)) {\n            continue\n          }\n          visited.add(item)\n\n          if (hasInternationalizedArrayInFields(item.fields, visited)) {\n            return true\n          }\n        }\n      }\n    }\n  }\n\n  return false\n}\n","import {useSchema, type DocumentLayoutProps} from 'sanity'\n\nimport type {PluginConfig} from '../types'\nimport {hasInternationalizedArrayField} from '../utils/hasInternationalizedArrayField'\nimport {InternationalizedArrayProvider} from './InternationalizedArrayContext'\n\nexport function InternationalizedArrayLayout(\n  props: DocumentLayoutProps & {pluginConfig: Required<PluginConfig>},\n) {\n  const schema = useSchema()\n  const schemaType = schema.get(props.documentType)\n\n  if (!schemaType) {\n    console.error(`Schema type not found: ${props.documentType}`)\n    return props.renderDefault(props)\n  }\n\n  const hasInternationalizedArray = hasInternationalizedArrayField(schemaType)\n  if (hasInternationalizedArray && props.pluginConfig.includeForDocumentType(props.documentType)) {\n    return (\n      <InternationalizedArrayProvider\n        internationalizedArray={props.pluginConfig}\n        documentType={props.documentType}\n      >\n        {props.renderDefault(props)}\n      </InternationalizedArrayProvider>\n    )\n  }\n\n  return props.renderDefault(props)\n}\n","import {useClient} from 'sanity'\n\nimport {createCacheKey, peek, preloadWithKey, setFunctionCache} from '../cache'\nimport type {PluginConfig} from '../types'\n\nexport default function Preload(props: Required<Pick<PluginConfig, 'apiVersion' | 'languages'>>) {\n  const client = useClient({apiVersion: props.apiVersion})\n\n  // Use the same cache key structure as the main component\n  // This should match the main component when selectedValue is empty\n  const cacheKey = createCacheKey({})\n\n  if (!Array.isArray(peek({}))) {\n    preloadWithKey(async () => {\n      if (Array.isArray(props.languages)) {\n        return props.languages\n      }\n      const result = await props.languages(client, {})\n      // Populate function cache for sharing with other components\n      // Use the same key structure as the main component\n      setFunctionCache(props.languages, {}, result)\n      return result\n    }, cacheKey)\n  }\n\n  return null\n}\n","import {LANGUAGE_FIELD_NAME} from '../constants'\nimport type {Language, InternationalizedArrayItem} from '../types'\n\n/**\n * Checks whether every language in the provided list has a corresponding entry\n * in the value array. It extracts language IDs from value items using\n * `LANGUAGE_FIELD_NAME` and compares them against the expected language IDs.\n *\n * Returns `true` only when the value array length matches the number of unique\n * languages and every value language ID is found in the languages list\n * (order does not matter). The length check ensures duplicates in value are\n * correctly rejected.\n */\nexport function checkAllLanguagesArePresent(\n  languages: Language[],\n  value: InternationalizedArrayItem[] | undefined,\n): boolean {\n  const filteredLanguageIds = new Set(languages.map((l) => l.id))\n  const languagesInUseIds = value ? value.map((v) => v[LANGUAGE_FIELD_NAME]) : []\n\n  if (languagesInUseIds.length !== filteredLanguageIds.size) return false\n  if (new Set(languagesInUseIds).size !== languagesInUseIds.length) return false\n  return languagesInUseIds.every((key) => filteredLanguageIds.has(key))\n}\n","import {LANGUAGE_FIELD_NAME} from '../constants'\nimport type {Language, InternationalizedArrayItem} from '../types'\n\n/**\n * Generates the label text for the \"add all / add missing languages\" button.\n *\n * - When there is no existing value: returns `\"Add {title} Field\"` for a\n *   single language, or `\"Add all languages\"` for multiple.\n * - When some values already exist: returns `\"Add missing language\"` (singular)\n *   or `\"Add missing languages\"` (plural) depending on how many are left.\n */\nexport function createAddAllTitle(\n  value: InternationalizedArrayItem[] | undefined,\n  languages: Language[],\n): string {\n  if (value?.length) {\n    const languagesInUse = new Set(value.map((item) => item[LANGUAGE_FIELD_NAME]))\n    const missingCount = languages.filter((language) => !languagesInUse.has(language.id)).length\n    return `Add missing ${missingCount === 1 ? `language` : `languages`}`\n  }\n\n  return languages.length === 1 && languages[0]\n    ? `Add ${languages[0].title} Field`\n    : `Add all languages`\n}\n","import type {LanguageFilterConfig} from '@sanity/language-filter'\nimport type {FieldDefinition, Rule, RuleTypeConstraint, SanityClient} from 'sanity'\nexport type Language = {\n  id: Intl.UnicodeBCP47LocaleIdentifier\n  title: string\n}\n\nexport type AllowedType = 'string' | 'number' | 'boolean' | 'text' | 'reference'\n\nexport type ArrayConfig = {\n  name: string\n  type: AllowedType\n  languages: Language[]\n  title?: string\n  group?: string\n  hidden?: boolean | (() => boolean)\n  readOnly?: boolean | (() => boolean)\n  validation?: Rule | Rule[]\n  field?: {[key: string]: unknown; options: {[key: string]: unknown}}\n}\n\n/**\n * @deprecated Use InternationalizedArrayItem instead\n */\nexport type Value = {\n  _key: string\n  /** Language identifier (e.g., 'en', 'fr'). Added in v5. */\n  language: string\n  value?: unknown\n}\n\nexport function isInternationalizedArrayItemType(\n  type: string,\n): type is InternationalizedArrayItem['_type'] {\n  return type.startsWith('internationalizedArray') && type.endsWith('Value')\n}\n\nexport type InternationalizedArrayItem<T = unknown> = {\n  _key: string\n  value?: T\n  /** Language identifier (e.g., 'en', 'fr'). Added in v5. */\n  language: string\n  /**\n   * string that starts with \"internationalizedArray\" and ends with \"Value\"\n   */\n  _type: `internationalizedArray${string}Value`\n}\n\nexport type LanguageCallback = (\n  client: SanityClient,\n  selectedValue: Record<string, unknown>,\n) => Promise<Language[]>\n\nexport type LanguageDisplay = 'titleOnly' | 'codeOnly' | 'titleAndCode'\n\nexport type PluginConfig = {\n  /**\n   * https://www.sanity.io/docs/api-versioning\n   * @defaultValue '2025-10-15'\n   */\n  apiVersion?: string\n  /**\n   * Specify fields that should be available in the language callback:\n   * ```tsx\n   * {\n   *   select: {\n   *     markets: 'markets'\n   *   },\n   *   languages: (client, {markets}) =>\n   *     query.fetch(groq`*[_type == \"language\" && market in $markets]{id,title}`, {markets})\n   * }\n   * ```\n   */\n  select?: Record<string, string>\n  /**\n   * You can give it an array of language definitions:\n   * ```tsx\n   * {\n   *   languages: [\n   *     {id: 'en', title: 'English'},\n   *     {id: 'fr', title: 'French'}\n   *   ]\n   * }\n   * ```\n   * You can load them async by passing a function that returns a promise:\n   * ```tsx\n   * {\n   *   languages: async () => {\n   *     const response = await fetch('https://example.com/languages')\n   *     return response.json()\n   *   }\n   * }\n   * ```\n   * You can query your dataset for languages::\n   * ```tsx\n   * {\n   *   languages: (client) =>\n   *     query.fetch(groq`*[_type == \"language\"]{id,title}`)\n   * }\n   * ```\n   */\n  languages: Language[] | LanguageCallback\n  /**\n   * You can specify a list of language IDs that should be pre-filled when creating a new document\n   * ```tsx\n   * {\n   *  defaultLanguages: ['en']\n   * }\n   * ```\n   */\n  defaultLanguages?: string[]\n  /**\n   * Can be a string matching core field types, as well as custom ones:\n   * ```tsx\n   * {\n   *   fieldTypes: [\n   *     \"date\", \"datetime\", \"file\", \"image\", \"number\", \"string\", \"text\", \"url\"\n   *   ]\n   * }\n   * ```\n   * You can also define a type directly:\n   * ```tsx\n   * {\n   *   fieldTypes: [\n   *     defineField({\n   *       name: 'featuredProduct',\n   *       type: 'reference',\n   *       to: [{type: 'product'}]\n   *       hidden: (({document}) => !document?.title)\n   *     })\n   *   ]\n   * }\n   * ```\n   */\n  // oxlint-disable-next-line typescript-eslint/no-redundant-type-constituents\n  fieldTypes: (string | RuleTypeConstraint | FieldDefinition)[]\n  /**\n   * Locations where the \"+ EN\" add language buttons are visible.\n   * `fieldMenu` is one translate icon per field that opens a\n   * language menu (compact; stable UI; no field actions). All locations are\n   * additive, so `field`, `fieldMenu`, and `document` can be combined.\n   * `unstable__fieldAction` is still accepted but crashes the editor from\n   * plugin 4.0.4 onward on Studio 4 and above.\n   * @defaultValue ['field']\n   * */\n  buttonLocations?: ('field' | 'fieldMenu' | 'unstable__fieldAction' | 'document')[]\n  /**\n   * Show or hide the \"Add all languages\" / \"Add missing languages\" control.\n   * Under `field` this is the bar below the per-language buttons. Under\n   * `fieldMenu` it is the bulk item inside the language menu.\n   * @defaultValue true\n   * */\n  buttonAddAll?: boolean\n  /**\n   * Automatically reorder array items to match the configured `languages` order\n   * when a document is opened.\n   *\n   * Disable this if you want to preserve a custom item order and avoid the\n   * plugin writing a patch (which creates a draft / history entry) for published\n   * documents whose order differs from the language config.\n   *\n   * @defaultValue true\n   */\n  restoreOrder?: boolean\n  /**\n   * How to display the languages on buttons and fields\n   * @defaultValue 'code'\n   * */\n  languageDisplay?: LanguageDisplay\n  /**\n   * @internal\n   * Function to determine if the plugin layout and root input should be included for a given document type.\n   * @defaultValue (documentType) => documentType !== 'translation.metadata'\n   * @example\n   * {\n   *   includeForDocumentType: (documentType) => documentType === 'translation.metadata'\n   * }\n   */\n  includeForDocumentType?: (documentType: string) => boolean\n  /**\n   * Configure the language filter for the plugin by providing the document types that should show the filter.\n   * ```tsx\n   * {\n   *   languageFilter: {\n   *     documentTypes: ['internationalizedPost', 'lesson'],\n   *     defaultLanguages: ['en']\n   *   }\n   * }\n   * ```\n   */\n  languageFilter?: {\n    documentTypes: Required<LanguageFilterConfig>['documentTypes']\n    defaultLanguages?: LanguageFilterConfig['defaultLanguages']\n  }\n}\n","import {randomKey} from '@sanity/util/content'\nimport {type FormInsertPatch, insert, type Path} from 'sanity'\n\nimport {LANGUAGE_FIELD_NAME} from '../constants'\nimport {\n  type Language,\n  type InternationalizedArrayItem,\n  isInternationalizedArrayItemType,\n} from '../types'\n\ntype AddConfig = {\n  // New keys to add to the field\n  addLanguageKeys: string[]\n  // Schema of the current field\n  schemaTypeName: string\n  // All languages registered in the plugin\n  languages: Language[]\n  // Languages that are currently visible\n  filteredLanguages: Language[]\n  // Current value of the internationalizedArray field\n  value?: InternationalizedArrayItem[]\n  // Path to this item\n  path?: Path\n}\n\n/**\n * Creates an array of Sanity `FormInsertPatch` objects that add new language\n * entries to an internationalized array field.\n *\n * If `addLanguageKeys` is provided, patches are created for those specific\n * language IDs. Otherwise, patches are created for all filtered languages\n * that are not already present in the current `value` array, for example when adding all missing languages.\n *\n * Each new item is assigned the correct `_type` (derived from the schema)\n * and the language identifier via `LANGUAGE_FIELD_NAME`.\n *\n * Insertions are ordered to maintain the same sequence as the master\n * `languages` list: each new item is inserted before the next existing\n * language in the value array, or appended at the end if no subsequent\n * language exists.\n */\nexport function createAddLanguagePatches(config: AddConfig): FormInsertPatch[] {\n  const {addLanguageKeys, schemaTypeName, languages, filteredLanguages, value, path = []} = config\n\n  const type = `${schemaTypeName}Value`\n  if (!isInternationalizedArrayItemType(type)) {\n    throw new Error(`Invalid internationalized array type: ${type}`)\n  }\n  const itemBase = {_type: type}\n\n  // Create new items with random _key and language identifier\n  const getNewItems = () => {\n    if (Array.isArray(addLanguageKeys) && addLanguageKeys.length > 0) {\n      return addLanguageKeys\n        .filter((id) => {\n          if (value?.length) {\n            // Check if the language is already in the value and filter it out if it exists to avoid duplicates\n            return !value.find((v) => v[LANGUAGE_FIELD_NAME] === id)\n          }\n          return true\n        })\n        .map((id) => Object.assign({}, itemBase, {_key: randomKey(), [LANGUAGE_FIELD_NAME]: id}))\n    }\n\n    return filteredLanguages\n      .filter((language) => {\n        return value?.length ? !value.find((v) => v[LANGUAGE_FIELD_NAME] === language.id) : true\n      })\n      .map((language) =>\n        Object.assign({}, itemBase, {_key: randomKey(), [LANGUAGE_FIELD_NAME]: language.id}),\n      )\n  }\n  const newItems = getNewItems()\n\n  // Insert new items in the correct order\n  const languagesInUse = value?.length ? value.map((v) => v) : []\n\n  const insertions = newItems.map((item) => {\n    // What's the original index of this language?\n    const itemLanguage = item[LANGUAGE_FIELD_NAME]\n    const languageIndex = languages.findIndex((l) => itemLanguage === l.id)\n\n    // What languages are there beyond that index?\n    const remainingLanguages = languages.slice(languageIndex + 1)\n\n    // So what is the index in the current value array of the next language in the language array?\n    const nextLanguageIndex = languagesInUse.findIndex((l) =>\n      remainingLanguages.find((r) => r.id === l[LANGUAGE_FIELD_NAME]),\n    )\n\n    // Keep local state up to date incase multiple insertions are being made\n    if (nextLanguageIndex < 0) {\n      languagesInUse.push(item)\n    } else {\n      languagesInUse.splice(nextLanguageIndex, 0, item)\n    }\n\n    return nextLanguageIndex < 0\n      ? // No next language (-1), add to end of array\n        insert([item], 'after', [...path, nextLanguageIndex])\n      : // Next language found, insert before that\n        insert([item], 'before', [...path, nextLanguageIndex])\n  })\n\n  return insertions\n}\n","import {AddIcon} from '@sanity/icons/Add'\nimport {TranslateIcon} from '@sanity/icons/Translate'\nimport {useCallback} from 'react'\nimport {\n  defineDocumentFieldAction,\n  type DocumentFieldActionItem,\n  type DocumentFieldActionProps,\n  PatchEvent,\n  setIfMissing,\n  useFormValue,\n} from 'sanity'\nimport {useDocumentPane} from 'sanity/structure'\n\nimport {useInternationalizedArrayContext} from '../components/InternationalizedArrayContext'\nimport {LANGUAGE_FIELD_NAME} from '../constants'\nimport type {Language, InternationalizedArrayItem} from '../types'\nimport {checkAllLanguagesArePresent} from '../utils/checkAllLanguagesArePresent'\nimport {createAddAllTitle} from '../utils/createAddAllTitle'\nimport {createAddLanguagePatches} from '../utils/createAddLanguagePatches'\n\nconst createTranslateFieldActions: (\n  fieldActionProps: DocumentFieldActionProps,\n  context: {\n    languages: Language[]\n    filteredLanguages: Language[]\n  },\n) => DocumentFieldActionItem[] = (fieldActionProps, {languages, filteredLanguages}) =>\n  languages.map((language) => {\n    // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n    const value = useFormValue(fieldActionProps.path) as InternationalizedArrayItem[]\n    const {onChange, formState} = useDocumentPane()\n    const disabled =\n      Boolean(formState?.readOnly) ||\n      (value && Array.isArray(value)\n        ? Boolean(value?.find((item) => item[LANGUAGE_FIELD_NAME] === language.id))\n        : false)\n    const hidden = !filteredLanguages.some((f) => f.id === language.id)\n\n    const onAction = useCallback(() => {\n      const {schemaType, path} = fieldActionProps\n\n      const addLanguageKeys = [language.id]\n      const patches = createAddLanguagePatches({\n        addLanguageKeys,\n        schemaTypeName: schemaType.name,\n        languages,\n        filteredLanguages,\n        value,\n        path,\n      })\n\n      onChange(PatchEvent.from([setIfMissing([], path), ...patches]))\n    }, [language.id, value, onChange])\n\n    return {\n      type: 'action',\n      icon: AddIcon,\n      onAction,\n      title: language.title,\n      hidden,\n      disabled,\n    }\n  })\n\nconst AddMissingTranslationsFieldAction: (\n  fieldActionProps: DocumentFieldActionProps,\n  context: {\n    languages: Language[]\n    filteredLanguages: Language[]\n  },\n) => DocumentFieldActionItem = (fieldActionProps, {languages, filteredLanguages}) => {\n  // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n  const value = useFormValue(fieldActionProps.path) as InternationalizedArrayItem[]\n  const {onChange, formState} = useDocumentPane()\n  const disabled =\n    Boolean(formState?.readOnly) || (value && value.length === filteredLanguages.length)\n  const hidden = checkAllLanguagesArePresent(filteredLanguages, value)\n\n  const onAction = useCallback(() => {\n    const {schemaType, path} = fieldActionProps\n\n    const addLanguageKeys: string[] = []\n    const patches = createAddLanguagePatches({\n      addLanguageKeys,\n      schemaTypeName: schemaType.name,\n      languages,\n      filteredLanguages,\n      value,\n      path,\n    })\n\n    onChange(PatchEvent.from([setIfMissing([], path), ...patches]))\n  }, [fieldActionProps, filteredLanguages, languages, onChange, value])\n\n  return {\n    type: 'action',\n    icon: AddIcon,\n    onAction,\n    title: createAddAllTitle(value, filteredLanguages),\n    disabled,\n    hidden,\n  }\n}\n\nexport const internationalizedArrayFieldAction = defineDocumentFieldAction({\n  name: 'internationalizedArray',\n  useAction(fieldActionProps) {\n    const isInternationalizedArrayField =\n      fieldActionProps?.schemaType?.type?.name.startsWith('internationalizedArray')\n    const {languages, filteredLanguages} = useInternationalizedArrayContext()\n\n    const translateFieldActions = createTranslateFieldActions(fieldActionProps, {\n      languages,\n      filteredLanguages,\n    })\n\n    return {\n      type: 'group',\n      icon: TranslateIcon,\n      title: 'Add Translation',\n      renderAsButton: true,\n      children: isInternationalizedArrayField\n        ? [\n            ...translateFieldActions,\n            AddMissingTranslationsFieldAction(fieldActionProps, {\n              languages,\n              filteredLanguages,\n            }),\n          ]\n        : [],\n      hidden: !isInternationalizedArrayField,\n    }\n  },\n})\n","import camelCase from 'lodash-es/camelCase.js'\nimport upperFirst from 'lodash-es/upperFirst.js'\n\n/**\n * Converts a string to PascalCase (e.g. `\"my-field\"` -> `\"MyField\"`).\n */\nexport function pascalCase(string: string): string {\n  return upperFirst(camelCase(string))\n}\n\n/**\n * Generates the schema type name for an internationalized array field.\n *\n * - Without the value suffix: `\"internationalizedArray{PascalName}\"`\n *   (used for the outer array type)\n * - With the value suffix: `\"internationalizedArray{PascalName}Value\"`\n *   (used for the inner object type that wraps each language entry)\n *\n * For example, `createFieldName('block-content', true)` returns\n * `\"internationalizedArrayBlockContentValue\"`.\n */\nexport function createFieldName(name: string, addValue = false): string {\n  return addValue\n    ? [`internationalizedArray`, pascalCase(name), `Value`].join(``)\n    : [`internationalizedArray`, pascalCase(name)].join(``)\n}\n","import type {ObjectSchemaType, FieldMember, FieldsetState} from 'sanity'\n\nimport {LANGUAGE_FIELD_NAME} from '../constants'\nimport {isInternationalizedArrayItemType, type Language} from '../types'\n\n/**\n * Default filter function for the internationalized array field.\n * It filter the field base on the `language` value of the object.\n */\nexport const internationalizedArrayLanguageFilter = (\n  enclosingType: ObjectSchemaType,\n  _member: FieldMember | FieldsetState,\n  selectedLanguageIds: string[],\n  parentValue: Record<string, unknown> | undefined,\n  languages: Language[],\n) => {\n  if (isInternationalizedArrayItemType(enclosingType.name)) {\n    const language =\n      typeof parentValue?.[LANGUAGE_FIELD_NAME] === 'string'\n        ? parentValue?.[LANGUAGE_FIELD_NAME]\n        : typeof parentValue?.['_key'] === 'string'\n          ? parentValue?.['_key']\n          : null\n\n    const isAValidLanguage = language ? languages.find((l) => l.id === language) : true\n    if (!isAValidLanguage) {\n      // If it's not a valid language we should not hide it, because it needs to be surfaced to the user to fix it.\n      // We need to update language-filter plugin so it doesn't hide the field later.\n      return true\n    }\n    return language ? selectedLanguageIds.includes(language) : false\n  }\n  return true\n}\n","import {AddIcon} from '@sanity/icons/Add'\nimport {TranslateIcon} from '@sanity/icons/Translate'\nimport {Button, Flex} from '@sanity/ui'\nimport {Menu, MenuButton, MenuDivider, MenuItem} from '@sanity/ui/menu'\nimport {useId} from 'react'\n\nimport {getLanguageDisplay} from '../utils/getLanguageDisplay'\nimport {useInternationalizedArrayContext} from './InternationalizedArrayContext'\n\ntype CompactAddButtonProps = {\n  readOnly: boolean\n  handleClick: (languageId: string) => void\n  languagesInUse: string[]\n  onAddAll: () => void\n  buttonAddAll: boolean\n  addAllTitle: string\n  allFilteredLanguagesArePresent: boolean\n}\n\n/**\n * One translate-icon button that opens a language menu — the `fieldMenu`\n * location. Compact, uses only stable `@sanity/ui`, and stays visible even\n * when every language is already present.\n */\nfunction CompactAddButton(props: CompactAddButtonProps) {\n  const {\n    readOnly,\n    languagesInUse,\n    handleClick,\n    onAddAll,\n    buttonAddAll,\n    addAllTitle,\n    allFilteredLanguagesArePresent,\n  } = props\n  const {languageDisplay, filteredLanguages: languages} = useInternationalizedArrayContext()\n  const menuId = useId()\n\n  if (!languages.length) return null\n\n  return (\n    <Flex justify=\"flex-end\" data-testid=\"field-menu\">\n      <MenuButton\n        id={menuId}\n        popover={{portal: true, placement: 'bottom-end'}}\n        button={\n          <Button\n            mode=\"bleed\"\n            tone=\"default\"\n            fontSize={1}\n            padding={2}\n            icon={TranslateIcon}\n            aria-label=\"Add translation\"\n            title=\"Add translation\"\n            data-testid=\"add-translation-menu\"\n            disabled={readOnly}\n          />\n        }\n        menu={\n          <Menu>\n            {languages.map((language) => (\n              <MenuItem\n                key={language.id}\n                text={getLanguageDisplay(languageDisplay, language.title, language.id)}\n                icon={AddIcon}\n                disabled={readOnly || languagesInUse.includes(language.id)}\n                data-testid={`field-menu-add-${language.id}`}\n                onClick={() => handleClick(language.id)}\n              />\n            ))}\n            {buttonAddAll ? (\n              <>\n                <MenuDivider />\n                <MenuItem\n                  text={addAllTitle}\n                  icon={TranslateIcon}\n                  disabled={readOnly || allFilteredLanguagesArePresent}\n                  data-testid=\"field-menu-add-all\"\n                  onClick={onAddAll}\n                />\n              </>\n            ) : null}\n          </Menu>\n        }\n      />\n    </Flex>\n  )\n}\n\nexport default CompactAddButton\n","import {Card, Stack, Text} from '@sanity/ui'\nimport {Code} from '@sanity/ui/code'\nimport type React from 'react'\n\nconst schemaExample = {\n  languages: [\n    {id: 'en', title: 'English'},\n    {id: 'no', title: 'Norsk'},\n  ],\n}\n\nexport default function Feedback(): React.ReactElement {\n  return (\n    <Card tone=\"caution\" border radius={2} padding={3}>\n      <Stack gap={4}>\n        <Text>\n          An array of language objects must be passed into the <code>internationalizedArray</code>{' '}\n          helper function, each with an <code>id</code> and <code>title</code> field. Example:\n        </Text>\n        <Card padding={2} border radius={2}>\n          <Code size={1} language=\"javascript\">\n            {JSON.stringify(schemaExample, null, 2)}\n          </Code>\n        </Card>\n      </Stack>\n    </Card>\n  )\n}\n","import {WarningOutlineIcon} from '@sanity/icons/WarningOutline'\nimport {Box, Card, Flex, Stack, Text} from '@sanity/ui'\nimport {type ReactElement} from 'react'\n\nimport type {InternationalizedArrayItem} from '../types'\n\nexport type MigrationBannerProps = {\n  itemsNeedingMigration: InternationalizedArrayItem[]\n}\n\n/**\n * Migration banner component that displays a warning if the items need to be migrated to the v5 format.\n */\nexport function MigrationBanner({\n  itemsNeedingMigration,\n}: MigrationBannerProps): ReactElement | null {\n  // Don't render if no migration is needed\n  if (!itemsNeedingMigration.length) {\n    return null\n  }\n\n  return (\n    <Card tone=\"caution\" padding={3} radius={2} border>\n      <Flex gap={3} align=\"center\">\n        <Box>\n          <Text size={1}>\n            <WarningOutlineIcon />\n          </Text>\n        </Box>\n        <Stack gap={2} flex={1}>\n          <Text size={1} weight=\"semibold\">\n            Data migration required\n          </Text>\n          <Text size={1} muted>\n            {itemsNeedingMigration.length} item\n            {itemsNeedingMigration.length === 1 ? '' : 's'}{' '}\n            {itemsNeedingMigration.length === 1 ? 'needs' : 'need'} to be migrated to the v5 format.\n          </Text>\n          <Box marginTop={2}>\n            <Text size={1}>\n              This field still uses the v4 format where language is stored in <code>_key</code>.\n              Migrate to the v5 format where language is stored in <code>language</code>.{' '}\n              <a\n                rel=\"noopener noreferrer\"\n                target=\"_blank\"\n                href=\"https://github.com/sanity-io/plugins/blob/main/plugins/sanity-plugin-internationalized-array/README.md#migrate-from-v4-to-v5\"\n              >\n                Learn more\n              </a>\n              .\n            </Text>\n          </Box>\n        </Stack>\n      </Flex>\n    </Card>\n  )\n}\n","import {AddIcon} from '@sanity/icons/Add'\nimport {useLanguageFilterStudioContext} from '@sanity/language-filter'\nimport {Button, Card, Stack, Text} from '@sanity/ui'\nimport {useToast} from '@sanity/ui/toast'\nimport type React from 'react'\nimport {useCallback, useContext, useEffect, useMemo} from 'react'\nimport {\n  type ArrayOfObjectsInputProps,\n  ArrayOfObjectsItem,\n  MemberItemError,\n  set,\n  setIfMissing,\n  useFormValue,\n  useGetFormValue,\n} from 'sanity'\nimport {EventsContext} from 'sanity/_singletons'\nimport {useDocumentPane} from 'sanity/structure'\n\nimport {LANGUAGE_FIELD_NAME} from '../constants'\nimport type {InternationalizedArrayItem} from '../types'\nimport {createAddAllTitle} from '../utils/createAddAllTitle'\nimport {createAddLanguagePatches} from '../utils/createAddLanguagePatches'\nimport {internationalizedArrayLanguageFilter} from '../utils/internationalizedArrayLanguageFilter'\nimport AddButtons from './AddButtons'\nimport CompactAddButton from './CompactAddButton'\nimport Feedback from './Feedback'\nimport {useInternationalizedArrayContext} from './InternationalizedArrayContext'\nimport {MigrationBanner} from './MigrationBanner'\n\n/**\n * The events store has finished loading and recorded no history. That is a\n * brand-new document.\n *\n * `sanity/_singletons` is internal; this is the same context `useEvents()`\n * reads. Using the context directly avoids throwing when the events API is\n * off (legacy timeline has no `EventsProvider`).\n */\nfunction isPristineDocument(\n  events: {events: readonly unknown[]; loading: boolean} | null,\n): boolean {\n  if (!events || events.loading) {\n    return false\n  }\n  return events.events.length === 0\n}\n\n/**\n * Main array input component for internationalized array fields.\n *\n * Replaces the default Sanity array input and manages the full lifecycle of\n * language entries:\n *\n * - **Language filter integration**: When `@sanity/language-filter` is active\n *   for the current document type, array members are filtered to only show\n *   languages matching the user's selection.\n * - **Adding languages**: Exposes per-language buttons, an optional compact\n *   `fieldMenu`, and an \"Add all / Add missing languages\" button (controlled\n *   by `buttonAddAll` and `buttonLocations`). Dispatches `setIfMissing` +\n *   `insert` patches.\n * - **Default languages**: Automatically adds entries for languages listed in\n *   `defaultLanguages` when those entries are missing. Seeds brand-new\n *   documents once the events store reports they are pristine (no history),\n *   and seeds persisted documents that already have a `_rev`. A document\n *   that existed and was deleted is not pristine, so opening it — even in a\n *   fresh pane — does not recreate it. Newly created documents stay\n *   read-only until initial value templates resolve, and the field-level\n *   `readOnly` prop can lag that document-level lock. Skipping the patch\n *   until writable avoids \"Attempted to patch a read-only document\" toasts.\n * - **Ordering**: When `restoreOrder` is enabled (default), detects when value\n *   items are out of order relative to the master `languages` list and\n *   automatically re-sorts them. Set `restoreOrder: false` to keep the stored\n *   order and avoid silent draft creation on open.\n * - **Validation**: Shows a `<Feedback>` component if the languages\n *   configuration is invalid (e.g. missing `id` or `title`).\n * - **Empty state**: Displays a \"no translations\" message when the field has\n *   no entries and the add buttons are not visible.\n */\nexport default function InternationalizedArray(\n  props: ArrayOfObjectsInputProps,\n): React.ReactElement {\n  const {members, value: _value, schemaType, onChange, readOnly: documentReadOnly} = props\n  // oxlint-disable-next-line typescript/no-unsafe-type-assertion\n  const value = _value as InternationalizedArrayItem[]\n  const itemsNeedingMigration = value?.filter((v) => !v[LANGUAGE_FIELD_NAME]) ?? []\n  const shouldMigrateArray = itemsNeedingMigration.length > 0\n  const toast = useToast()\n\n  const getFormValue = useGetFormValue()\n  const {\n    languages,\n    filteredLanguages,\n    defaultLanguages,\n    buttonAddAll,\n    buttonLocations,\n    restoreOrder,\n    languageFilter: builtInLanguageFilter,\n  } = useInternationalizedArrayContext()\n  // Support updating the UI if languageFilter is installed\n  const {selectedLanguageIds, options: languageFilterOptions} = useLanguageFilterStudioContext()\n  const documentType = useFormValue(['_type'])\n  const usingLanguageFilterPlugin =\n    typeof documentType === 'string' && languageFilterOptions.documentTypes.includes(documentType)\n  const usingBuiltInLanguageFilter =\n    typeof documentType === 'string' && builtInLanguageFilter.documentTypes.includes(documentType)\n\n  // TODO: Is this redundant? The filter plugin already filters members at its own level.\n  const filteredMembers = useMemo(\n    () =>\n      usingLanguageFilterPlugin || usingBuiltInLanguageFilter\n        ? members.filter((member) => {\n            // This member is the outer object created by the plugin\n            // Satisfy TS\n            if (member.kind !== 'item') {\n              return false\n            }\n\n            // This is the inner \"value\" field member created by this plugin\n            const valueMember = member.item.members[0]\n\n            // Satisfy TS\n            if (!valueMember || valueMember.kind !== 'field') {\n              return false\n            }\n            // The built-in filter receives the full languages list so it can\n            // surface fields with invalid language IDs rather than hiding them.\n            // The language filter plugin does not support this.\n            return usingBuiltInLanguageFilter\n              ? internationalizedArrayLanguageFilter(\n                  member.item.schemaType,\n                  valueMember,\n                  selectedLanguageIds,\n                  member.item.value,\n                  languages,\n                )\n              : languageFilterOptions.filterField(\n                  member.item.schemaType,\n                  valueMember,\n                  selectedLanguageIds,\n                  member.item.value,\n                )\n          })\n        : members,\n    [\n      usingLanguageFilterPlugin,\n      usingBuiltInLanguageFilter,\n      members,\n      selectedLanguageIds,\n      languages,\n      languageFilterOptions,\n    ],\n  )\n\n  const {isDeleted, isDeleting, isInitialValueLoading, formState} = useDocumentPane()\n\n  // Document-level locks (initial-value templates, permissions, history) are\n  // not always reflected on the field's `readOnly` prop in the same tick as\n  // the patch channel. Gating on both prevents toasts from auto-patches.\n  const readOnly =\n    Boolean(documentReadOnly) ||\n    schemaType.readOnly === true ||\n    Boolean(formState?.readOnly) ||\n    Boolean(isInitialValueLoading)\n\n  const handleAddLanguages = useCallback(\n    (addLanguageKeys: string[] | string) => {\n      if (readOnly) {\n        return\n      }\n      // oxlint-disable-next-line typescript/no-unsafe-type-assertion\n      const formValue = getFormValue(props.path) as InternationalizedArrayItem[]\n      if (!filteredLanguages?.length) {\n        return\n      }\n\n      const patches = createAddLanguagePatches({\n        addLanguageKeys: Array.isArray(addLanguageKeys) ? addLanguageKeys : [addLanguageKeys],\n        schemaTypeName: schemaType.name,\n        languages,\n        filteredLanguages,\n        value: formValue,\n      })\n\n      onChange([setIfMissing([]), ...patches])\n    },\n    [filteredLanguages, languages, onChange, schemaType, getFormValue, props.path, readOnly],\n  )\n\n  // `_rev` means the document is in the dataset. No `_rev` is either a\n  // brand-new form or a deleted one. The events store distinguishes those:\n  // pristine (loaded, zero events) has never existed; any history means it\n  // did — including a fresh open of a deleted id, where this pane never saw\n  // a `_rev`.\n  const documentExists = Boolean(useFormValue(['_rev']))\n  const isPristine = isPristineDocument(useContext(EventsContext))\n\n  // Create a stable dependency string that only changes when language keys change\n  const languageKeysFromValue = value\n    ?.map((v) => v[LANGUAGE_FIELD_NAME] ?? v._key)\n    .filter(Boolean)\n    .join(',')\n\n  const addedLanguages = useMemo(() => {\n    const languageKeys = languageKeysFromValue?.split(',') || []\n    if (!languageKeys?.length) return []\n    if (!languages?.length) return []\n\n    return languages.filter((l) => languageKeys?.find((key) => key === l.id)).map((l) => l.id)\n  }, [languageKeysFromValue, languages])\n\n  useEffect(() => {\n    const hasAddedDefaultLanguages = defaultLanguages\n      .filter((language) => languages.find((l) => l.id === language))\n      .every((language) => addedLanguages.includes(language))\n\n    if (\n      (isPristine || documentExists) &&\n      !isDeleting &&\n      !isDeleted &&\n      !hasAddedDefaultLanguages &&\n      !shouldMigrateArray &&\n      !readOnly\n    ) {\n      const languagesToAdd = defaultLanguages\n        .filter((language) => !addedLanguages.includes(language))\n        .filter((language) => languages.find((l) => l.id === language))\n      // Account for strict mode by scheduling the update.\n      const timeout = setTimeout(() => {\n        if (!readOnly) handleAddLanguages(languagesToAdd)\n      })\n      return () => clearTimeout(timeout)\n    }\n    return undefined\n  }, [\n    isPristine,\n    documentExists,\n    isDeleted,\n    isDeleting,\n    handleAddLanguages,\n    defaultLanguages,\n    addedLanguages,\n    languages,\n    readOnly,\n    shouldMigrateArray,\n  ])\n\n  // NOTE: This is reordering and re-setting the whole array, it could be surgical\n  const handleRestoreOrder = useCallback(() => {\n    if (readOnly || !value?.length || !languages?.length) {\n      return\n    }\n\n    // Create a new value array in the correct order\n    // This would also strip out values that don't have a language as the key\n    const updatedValue = value\n      .reduce((acc, v) => {\n        const newIndex = languages.findIndex((l) => l.id === v?.[LANGUAGE_FIELD_NAME])\n\n        if (newIndex > -1) {\n          acc[newIndex] = v\n        }\n\n        return acc\n      }, [] as InternationalizedArrayItem[])\n      .filter(Boolean)\n\n    if (value?.length !== updatedValue.length) {\n      toast.push({\n        title: 'There was an error reordering languages',\n        status: 'warning',\n      })\n    }\n\n    onChange(set(updatedValue))\n  }, [toast, languages, onChange, value, readOnly])\n\n  const allKeysAreLanguages = useMemo(() => {\n    if (!value?.length || !languages?.length) {\n      return true\n    }\n\n    return value?.every((v) => languages.find((l) => l?.id === v?.[LANGUAGE_FIELD_NAME]))\n  }, [value, languages])\n\n  const languagesOutOfOrder = useMemo(() => {\n    if (!value?.length || !addedLanguages.length) {\n      return []\n    }\n\n    return value\n      .map((v, vIndex) =>\n        vIndex === addedLanguages.findIndex((language) => language === v[LANGUAGE_FIELD_NAME])\n          ? null\n          : v,\n      )\n      .filter(Boolean)\n  }, [value, addedLanguages])\n\n  const languagesAreValid = useMemo(\n    () =>\n      !languages?.length || (languages?.length && languages.every((item) => item.id && item.title)),\n    [languages],\n  )\n\n  // Automatically restore order of fields (opt out with restoreOrder: false)\n  useEffect(() => {\n    if (restoreOrder && languagesOutOfOrder.length > 0 && allKeysAreLanguages && !readOnly) {\n      handleRestoreOrder()\n    }\n  }, [restoreOrder, languagesOutOfOrder, allKeysAreLanguages, handleRestoreOrder, readOnly])\n\n  const allFilteredLanguagesArePresent = useMemo(\n    () => filteredLanguages.every((language) => addedLanguages.includes(language.id)),\n    [filteredLanguages, addedLanguages],\n  )\n  const addAllMissingLanguages = useCallback(() => {\n    handleAddLanguages(filteredLanguages.map((language) => language.id))\n  }, [filteredLanguages, handleAddLanguages])\n\n  if (!languagesAreValid) {\n    return <Feedback />\n  }\n\n  const canAddLanguages = !shouldMigrateArray && filteredLanguages?.length > 0\n  const showFieldMenu = canAddLanguages && buttonLocations.includes('fieldMenu')\n  const showFieldButtons =\n    canAddLanguages && buttonLocations.includes('field') && !allFilteredLanguagesArePresent\n  const fieldHasMembers = members?.length > 0\n  const addAllTitle = createAddAllTitle(value, filteredLanguages)\n\n  const fieldButtons = showFieldButtons ? (\n    <Stack gap={2}>\n      <AddButtons\n        languagesInUse={addedLanguages}\n        readOnly={readOnly}\n        handleClick={handleAddLanguages}\n      />\n      {buttonAddAll ? (\n        <Button\n          tone=\"primary\"\n          mode=\"ghost\"\n          data-testid=\"add-all-languages\"\n          disabled={readOnly || allFilteredLanguagesArePresent}\n          icon={AddIcon}\n          text={addAllTitle}\n          onClick={addAllMissingLanguages}\n        />\n      ) : null}\n    </Stack>\n  ) : null\n\n  return (\n    <Stack gap={2}>\n      {showFieldMenu ? (\n        <CompactAddButton\n          languagesInUse={addedLanguages}\n          readOnly={readOnly}\n          handleClick={handleAddLanguages}\n          onAddAll={addAllMissingLanguages}\n          buttonAddAll={buttonAddAll}\n          addAllTitle={addAllTitle}\n          allFilteredLanguagesArePresent={allFilteredLanguagesArePresent}\n        />\n      ) : null}\n      {filteredMembers.map((member) => {\n        if (member.kind === 'item') {\n          return <ArrayOfObjectsItem {...props} key={member.key} member={member} />\n        }\n        return <MemberItemError key={member.key} member={member} />\n      })}\n      <MigrationBanner itemsNeedingMigration={itemsNeedingMigration} />\n\n      {/* Give some feedback in the UI so the field doesn't look \"missing\" */}\n      {!showFieldMenu && !showFieldButtons && !fieldHasMembers ? (\n        <Card border tone=\"transparent\" padding={3} radius={2}>\n          <Text size={1}>This internationalized field currently has no translations.</Text>\n        </Card>\n      ) : null}\n\n      {fieldButtons}\n    </Stack>\n  )\n}\n","import type {SchemaType} from 'sanity'\n\nimport type {ArrayFieldOptions} from '../schema/array'\n\nexport function getLanguagesFieldOption(\n  schemaType: SchemaType | undefined,\n): ArrayFieldOptions['languages'] | undefined {\n  if (!schemaType) {\n    return undefined\n  }\n  // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n  const languagesOption = (schemaType.options as ArrayFieldOptions)?.languages\n  if (languagesOption) {\n    return languagesOption\n  }\n  return getLanguagesFieldOption(schemaType.type)\n}\n","import {defineField, type FieldDefinition, type FieldProps, type Rule} from 'sanity'\n\nimport {getFunctionCache, peek, setFunctionCache} from '../cache'\nimport {createFieldName} from '../components/createFieldName'\nimport {getSelectedValue} from '../components/getSelectedValue'\nimport InternationalizedArray from '../components/InternationalizedArray'\nimport {LANGUAGE_FIELD_NAME} from '../constants'\nimport type {Language, LanguageCallback, InternationalizedArrayItem} from '../types'\nimport {getLanguagesFieldOption} from '../utils/getLanguagesFieldOption'\n\ntype ArrayFactoryConfig = {\n  apiVersion: string\n  select?: Record<string, string>\n  languages: Language[] | LanguageCallback\n  defaultLanguages?: string[]\n  type: string | FieldDefinition\n}\n\nexport type ArrayFieldOptions = Pick<ArrayFactoryConfig, 'apiVersion' | 'select' | 'languages'>\n\nexport default (config: ArrayFactoryConfig) => {\n  const {apiVersion, select, languages, type} = config\n  const typeName = typeof type === `string` ? type : type.name\n  const arrayName = createFieldName(typeName)\n  const objectName = createFieldName(typeName, true)\n\n  return defineField({\n    name: arrayName,\n    title: 'Internationalized array',\n    type: 'array',\n    components: {\n      field: (props: FieldProps) =>\n        props.renderDefault({\n          ...props,\n          // Reset the level to avoid nested styling\n          level: 0,\n        }),\n      input: InternationalizedArray,\n    },\n    options: {\n      // @ts-expect-error - these options are required for validation rules – not the custom input component\n      apiVersion,\n      select,\n      languages,\n    },\n    of: [\n      defineField({\n        ...(typeof type === 'string' ? {} : type),\n        name: objectName,\n        type: objectName,\n      }),\n    ],\n    // @ts-expect-error - fix typings\n    validation: (rule: Rule) =>\n      rule.custom<InternationalizedArrayItem[]>(async (value, context) => {\n        if (!value || value.length === 0) {\n          return true\n        }\n\n        // Check for items missing the language field (unmigrated data)\n        const itemsMissingLanguage = value.filter(\n          (item) => item && !item[LANGUAGE_FIELD_NAME] && item._key,\n        )\n        if (itemsMissingLanguage.length > 0) {\n          return {\n            message:\n              'Language is required for each array item. Run the migration to update your data from the old format.',\n            paths: itemsMissingLanguage.flatMap((item) => [\n              [{_key: item._key}],\n              [{_key: item._key}, 'value'],\n            ]),\n          }\n        }\n\n        // Early return for simple cases to avoid expensive operations\n        if (value.length === 1 && !value[0]?.[LANGUAGE_FIELD_NAME]) {\n          return true\n        }\n\n        const selectedValue = getSelectedValue(select, context.document)\n        const client = context.getClient({apiVersion})\n\n        let contextLanguages: Language[] = []\n        const languagesFieldOption = getLanguagesFieldOption(context?.type)\n\n        if (Array.isArray(languagesFieldOption)) {\n          contextLanguages = languagesFieldOption\n        } else if (Array.isArray(peek(selectedValue))) {\n          contextLanguages = peek(selectedValue) || []\n        } else if (typeof languagesFieldOption === 'function') {\n          // Try to get from function cache first (if it's the same function as the component)\n          const cachedLanguages = getFunctionCache(languagesFieldOption, selectedValue)\n\n          if (Array.isArray(cachedLanguages)) {\n            contextLanguages = cachedLanguages\n          } else {\n            // Try suspend cache as fallback\n            const suspendCachedLanguages = peek(selectedValue)\n            if (Array.isArray(suspendCachedLanguages)) {\n              contextLanguages = suspendCachedLanguages\n            } else {\n              // Only make the async call if we don't have cached data\n              contextLanguages = await languagesFieldOption(client, selectedValue)\n              // Cache the result for future validation calls\n              setFunctionCache(languagesFieldOption, selectedValue, contextLanguages)\n            }\n          }\n        }\n\n        if (value && value.length > contextLanguages.length) {\n          return `Cannot be more than ${\n            contextLanguages.length === 1 ? `1 item` : `${contextLanguages.length} items`\n          }`\n        }\n\n        // Create a Set for faster language ID lookups\n        const languageIds = new Set(contextLanguages.map((lang) => lang.id))\n\n        // Check for invalid language keys\n        const nonLanguageKeys = value.filter(\n          (item) => item?.[LANGUAGE_FIELD_NAME] && !languageIds.has(item[LANGUAGE_FIELD_NAME]),\n        )\n        if (nonLanguageKeys.length) {\n          return {\n            message: `Array item keys must be valid languages registered to the field type`,\n            paths: nonLanguageKeys.map((item) => [{_key: item._key}]),\n          }\n        }\n\n        // Check for duplicate language keys (more efficient)\n        const seenLanguages = new Set<string>()\n        const duplicateValues: InternationalizedArrayItem[] = []\n\n        for (const item of value) {\n          if (item?.[LANGUAGE_FIELD_NAME]) {\n            if (seenLanguages.has(item[LANGUAGE_FIELD_NAME])) {\n              duplicateValues.push(item)\n            } else {\n              seenLanguages.add(item[LANGUAGE_FIELD_NAME])\n            }\n          }\n        }\n\n        if (duplicateValues.length) {\n          return {\n            message: 'There can only be one field per language',\n            paths: duplicateValues.map((item) => [{_key: item._key}]),\n          }\n        }\n\n        return true\n      }),\n  })\n}\n","import type {CardTone} from '@sanity/ui'\nimport type {FormNodeValidation} from 'sanity'\n\n/**\n * Maps an array of Sanity form validation entries to a `@sanity/ui` `CardTone`\n * for visual feedback on internationalized array items.\n *\n * - Returns `'critical'` if any validation has `level: 'error'`\n * - Returns `'caution'` if any validation has `level: 'warning'` (and no errors)\n * - Returns `undefined` otherwise (no tone applied)\n *\n * Error level always takes precedence over warning.\n */\nexport function getToneFromValidation(validations: FormNodeValidation[]): CardTone | undefined {\n  if (!validations?.length) {\n    return undefined\n  }\n\n  const validationLevels = new Set(validations.map((v) => v.level))\n\n  if (validationLevels.has('error')) {\n    return `critical`\n  } else if (validationLevels.has('warning')) {\n    return `caution`\n  }\n\n  return undefined\n}\n","import {RemoveCircleIcon} from '@sanity/icons/RemoveCircle'\nimport {Box, Button, Card, Flex, Label, Spinner, Text} from '@sanity/ui'\nimport {Menu, MenuButton, MenuItem} from '@sanity/ui/menu'\nimport {Tooltip} from '@sanity/ui/tooltip'\nimport type React from 'react'\nimport {type ReactNode, useCallback, useMemo} from 'react'\nimport {type FormPatch, type ObjectItemProps, PatchEvent, type Path, useFormValue} from 'sanity'\nimport {set, unset} from 'sanity'\n\nimport {LANGUAGE_FIELD_NAME} from '../constants'\nimport type {InternationalizedArrayItem} from '../types'\nimport {getLanguageDisplay} from '../utils/getLanguageDisplay'\nimport {getToneFromValidation} from './getToneFromValidation'\nimport {useInternationalizedArrayContext} from './InternationalizedArrayContext'\n\nfunction ChangeLanguageButton(props: {\n  value: InternationalizedArrayItem\n  path: Path\n  onChange: (patch: FormPatch[] | PatchEvent | FormPatch) => void\n}): ReactNode {\n  const {value, onChange, path} = props\n  // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n  const parentValue = useFormValue(path.slice(0, -1)) as InternationalizedArrayItem[]\n  const {languages} = useInternationalizedArrayContext()\n\n  const languageKeysInUse = useMemo(\n    () => parentValue?.map((v) => v[LANGUAGE_FIELD_NAME]) ?? [],\n    [parentValue],\n  )\n\n  // Changes the key of this item, ideally to a valid language\n  const handleKeyChange = (event: React.MouseEvent<HTMLButtonElement>): void => {\n    const languageId = event?.currentTarget?.value\n\n    if (!value || !languages?.length || !languages.find((l) => l.id === languageId)) {\n      return\n    }\n\n    onChange([set(languageId, [LANGUAGE_FIELD_NAME])])\n  }\n\n  return (\n    <MenuButton\n      button={<Button fontSize={1} text={`Change \"${value[LANGUAGE_FIELD_NAME]}\"`} />}\n      id={`${value[LANGUAGE_FIELD_NAME]}-change-key`}\n      menu={\n        <Menu>\n          {languages.map((lang) => (\n            <MenuItem\n              disabled={languageKeysInUse.includes(lang.id)}\n              fontSize={1}\n              key={lang.id}\n              text={lang.id.toLocaleUpperCase()}\n              value={lang.id}\n              onClick={handleKeyChange}\n            />\n          ))}\n        </Menu>\n      }\n      popover={{portal: true}}\n    />\n  )\n}\n\nfunction RemoveButton({\n  isDefault,\n  readOnly,\n  onChange,\n}: {\n  isDefault: boolean\n  readOnly: boolean\n  onChange: (patch: FormPatch[] | PatchEvent | FormPatch) => void\n}): ReactNode {\n  // Removes this item from the array\n  const handleUnset = (): void => {\n    onChange(unset())\n  }\n\n  return (\n    <Tooltip\n      animate\n      disabled={!isDefault}\n      content={\n        <Text muted size={1}>\n          Can&apos;t remove default language\n        </Text>\n      }\n      fallbackPlacements={['right', 'left']}\n      placement=\"top\"\n      portal\n    >\n      <span style={{paddingBottom: '2px'}}>\n        <Button\n          mode=\"bleed\"\n          icon={RemoveCircleIcon}\n          tone=\"critical\"\n          disabled={readOnly || isDefault}\n          onClick={handleUnset}\n        />\n      </span>\n    </Tooltip>\n  )\n}\n\n/**\n * Renders a single row of an internationalized array: a language label (or\n * \"Change\" menu for invalid keys), the value input, and a remove button.\n *\n * Key behaviours:\n * - Wraps `onChange` to intercept paste operations into empty Portable Text\n *   fields, ensuring `setIfMissing` and correct path prefixing.\n * - Detects items needing migration (missing `LANGUAGE_FIELD_NAME`) and hides\n *   the language label in that state.\n * - Shows a `MenuButton` with available languages when the current key is\n *   not a valid language.\n * - Disables the remove button for languages listed in `defaultLanguages`.\n * - Shows a `Spinner` when languages have not been loaded yet.\n * - Applies a `CardTone` based on validation state via `getToneFromValidation`.\n */\nexport default function InternationalizedInput(\n  props: ObjectItemProps<InternationalizedArrayItem>,\n): ReactNode {\n  // Extract the original onChange to avoid dependency issues\n  const originalOnChange = props.inputProps.onChange\n\n  // Create a wrapped onChange handler to intercept patches for paste operations\n  const wrappedOnChange = useCallback(\n    (patches: unknown) => {\n      // Ensure patches is an array before proceeding with paste logic\n      // For single patch operations (like unset), pass through directly\n      if (!Array.isArray(patches)) {\n        // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n        return originalOnChange(patches as Parameters<typeof originalOnChange>[0])\n      }\n\n      // Check if this is a paste operation into an empty or uninitialized Portable Text field\n      const valueField = props.value?.value\n      const isEmptyOrUndefined =\n        valueField === undefined ||\n        valueField === null ||\n        (Array.isArray(valueField) && valueField.length === 0)\n\n      if (isEmptyOrUndefined) {\n        // Check for insert patches that are trying to operate on a non-existent structure\n        const hasProblematicInsert = patches.some((patch: {type?: string; path?: unknown[]}) => {\n          // Ensure patch exists and has required properties\n          if (!patch || typeof patch !== 'object') {\n            return false\n          }\n\n          // Look for insert patches targeting the value field or direct array index\n          if (\n            patch.type === 'insert' &&\n            patch.path &&\n            Array.isArray(patch.path) &&\n            patch.path.length > 0\n          ) {\n            // The path might be ['value', index] or just [index] depending on context\n            const isTargetingValue = patch.path[0] === 'value' || typeof patch.path[0] === 'number'\n            return isTargetingValue\n          }\n          return false\n        })\n\n        if (hasProblematicInsert) {\n          // First, ensure the value field exists as an empty array if it doesn't\n          const initPatch =\n            valueField === undefined ? {type: 'setIfMissing', path: ['value'], value: []} : null\n\n          // Transform the patches to ensure they work with the nested structure\n          const fixedPatches = patches.map(\n            (patch: {type?: string; path?: unknown[]; [key: string]: unknown}) => {\n              // Ensure patch exists and has required properties\n              if (!patch || typeof patch !== 'object') {\n                return patch\n              }\n\n              if (patch.type === 'insert' && patch.path && Array.isArray(patch.path)) {\n                // Ensure the path is correct for the nested structure\n                const fixedPath = patch.path[0] === 'value' ? patch.path : ['value', ...patch.path]\n                const fixedPatch = {...patch, path: fixedPath}\n                return fixedPatch\n              }\n              return patch\n            },\n          )\n\n          // If we need to initialize the field, include that patch first\n          const allPatches = initPatch ? [initPatch, ...fixedPatches] : fixedPatches\n\n          // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n          return originalOnChange(allPatches as Parameters<typeof originalOnChange>[0])\n        }\n      }\n\n      // For all other cases, pass through unchanged\n      return originalOnChange(patches as Parameters<typeof originalOnChange>[0])\n    },\n    [originalOnChange, props.value?.value],\n  )\n\n  // The parent array contains the languages from the plugin config\n  const {languages, languageDisplay, defaultLanguages} = useInternationalizedArrayContext()\n\n  const keyIsValid = languages?.length\n    ? Boolean(languages.find((l) => l.id === props.value[LANGUAGE_FIELD_NAME]))\n    : false\n\n  const language = languages?.find((l) => l.id === props.value[LANGUAGE_FIELD_NAME])\n  const languageTitle: string =\n    keyIsValid && language ? getLanguageDisplay(languageDisplay, language.title, language.id) : ''\n\n  const inlineProps = useMemo(\n    () => ({\n      ...props.inputProps,\n      members: props.inputProps.members\n        .filter((m) => m.kind === 'field' && m.name === 'value')\n        .map((member) => {\n          if (member.kind !== 'field') {\n            return member\n          }\n\n          const field = member.field\n          const schemaType = field?.schemaType\n          const itemNeedsMigration = !props.value[LANGUAGE_FIELD_NAME]\n\n          const title = itemNeedsMigration ? null : keyIsValid ? (\n            <Label muted size={1}>\n              {languageTitle}\n            </Label>\n          ) : (\n            <ChangeLanguageButton\n              value={props.value}\n              path={props.path}\n              onChange={originalOnChange}\n            />\n          )\n\n          return Object.assign({}, member, {\n            field: Object.assign({}, field, {\n              schemaType: Object.assign({}, schemaType, {title}),\n            }),\n          })\n        }),\n      value: props.value,\n      // Use our wrapped onChange handler\n      onChange: wrappedOnChange,\n    }),\n    [\n      props.inputProps,\n      props.value,\n      wrappedOnChange,\n      languageTitle,\n      keyIsValid,\n      originalOnChange,\n      props.path,\n    ],\n  )\n\n  const {validation, value, readOnly} = inlineProps\n\n  if (!languages) {\n    return <Spinner />\n  }\n\n  const isDefault = defaultLanguages.includes(value[LANGUAGE_FIELD_NAME])\n\n  return (\n    <Card paddingTop={2} tone={getToneFromValidation(validation)}>\n      <Flex align=\"flex-end\" gap={2}>\n        <Box flex={1}>{props.inputProps.renderInput(inlineProps)}</Box>\n        <RemoveButton\n          isDefault={isDefault}\n          readOnly={Boolean(readOnly)}\n          onChange={originalOnChange}\n        />\n      </Flex>\n    </Card>\n  )\n}\n","import {defineField, type FieldDefinition, type FieldProps} from 'sanity'\n\nimport {createFieldName} from '../components/createFieldName'\nimport InternationalizedInput from '../components/InternationalizedInput'\nimport {LANGUAGE_FIELD_NAME} from '../constants'\n\ntype ObjectFactoryConfig = {\n  type: string | FieldDefinition\n}\n\nexport default (config: ObjectFactoryConfig) => {\n  const {type} = config\n  const typeName = typeof type === `string` ? type : type.name\n  const objectName = createFieldName(typeName, true)\n\n  return defineField({\n    name: objectName,\n    title: `Internationalized array ${typeName}`,\n    type: 'object',\n    components: {\n      // @ts-expect-error - fix typings\n      item: InternationalizedInput,\n      field: (props: FieldProps) =>\n        props.renderDefault({\n          ...props,\n          // Reset the level to avoid nested styling\n          level: 0,\n        }),\n    },\n    fields: [\n      defineField({\n        ...(typeof type === 'string' ? {type} : type),\n        name: 'value',\n      }),\n      // Hidden language field - stores the language identifier (e.g., 'en', 'fr')\n      // This replaces the previous pattern of storing language in _key\n      defineField({\n        name: 'language',\n        type: 'string',\n        hidden: true,\n        validation: (Rule) => Rule.required(),\n      }),\n    ],\n    preview: {\n      select: {\n        title: 'value',\n        subtitle: LANGUAGE_FIELD_NAME,\n      },\n    },\n  })\n}\n","import {languageFilter} from '@sanity/language-filter'\nimport {definePlugin, isObjectInputProps} from 'sanity'\n\nimport {InternationalizedArrayFormInput} from './components/InternationalizedArrayFormInput'\nimport {InternationalizedArrayLayout} from './components/InternationalizedArrayLayout'\nimport Preload from './components/Preload'\nimport {CONFIG_DEFAULT} from './constants'\nimport {internationalizedArrayFieldAction} from './fieldActions'\nimport array from './schema/array'\nimport object from './schema/object'\nimport type {PluginConfig} from './types'\nimport {hasInternationalizedArrayField} from './utils/hasInternationalizedArrayField'\n\nexport const internationalizedArray = definePlugin<PluginConfig>((config) => {\n  const pluginConfig = {...CONFIG_DEFAULT, ...config}\n  const {\n    // oxlint-disable-next-line no-useless-default-assignment\n    apiVersion = '2025-10-15',\n    select,\n    languages,\n    fieldTypes,\n    defaultLanguages,\n    buttonLocations,\n    languageFilter: languageFilterConfig,\n  } = pluginConfig\n\n  return {\n    name: 'sanity-plugin-internationalized-array',\n    // Preload languages for use throughout the Studio\n    studio: Array.isArray(languages)\n      ? undefined\n      : {\n          components: {\n            layout: (props) => (\n              <>\n                <Preload apiVersion={apiVersion} languages={languages} />\n                {props.renderDefault(props)}\n              </>\n            ),\n          },\n        },\n    // Optional: render \"add language\" buttons as field actions\n    document: {\n      components: {\n        unstable_layout: (props) => (\n          <InternationalizedArrayLayout {...props} pluginConfig={pluginConfig} />\n        ),\n      },\n      unstable_fieldActions: buttonLocations.includes('unstable__fieldAction')\n        ? (prev) => [...prev, internationalizedArrayFieldAction]\n        : undefined,\n    },\n    // Wrap document editor with a language provider\n    form: {\n      components: {\n        input: (props) => {\n          const isRootInput = props.id === 'root' && isObjectInputProps(props)\n\n          if (!isRootInput) {\n            return props.renderDefault(props)\n          }\n\n          const hasInternationalizedArray = hasInternationalizedArrayField(props.schemaType)\n\n          if (\n            hasInternationalizedArray &&\n            pluginConfig.includeForDocumentType(props.schemaType.name)\n          ) {\n            return <InternationalizedArrayFormInput {...props} pluginConfig={pluginConfig} />\n          }\n          return props.renderDefault(props)\n        },\n      },\n    },\n    // Register custom schema types for the outer array and the inner object\n    schema: {\n      types: [\n        ...fieldTypes.map((type) => array({type, apiVersion, select, languages, defaultLanguages})),\n        ...fieldTypes.map((type) => object({type})),\n      ],\n    },\n    plugins:\n      languageFilterConfig?.documentTypes?.length > 0\n        ? [\n            languageFilter({\n              documentTypes: languageFilterConfig.documentTypes,\n              supportedLanguages: languages,\n              defaultLanguages: languageFilterConfig.defaultLanguages,\n              // This is specifically not adding filterField avoid the default filter field implementation.\n              // It will be filtered in `internationalizedArray` component and will have access to the resolved languages.\n              // Rendering the fields if the language key is incorrect, providing an improved UX\n            }),\n          ]\n        : undefined,\n  }\n})\n"],"mappings":"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"}
\ No newline at end of file