sanity-plugin-internationalized-array
5.2.15.2.2
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":["Language","LanguageCallback","namespace","version","functionKeyCache","WeakMap","promiseCache","Map","Promise","functionCache","stringifyCacheKey","key","JSON","stringify","preloadWithKey","fn","keyStr","has","set","clear","peek","selectedValue","Record","promise","get","status","_status","_value","undefined","createCacheKey","workspaceId","selectedValueHash","createOrGetPromise","getFunctionKey","cachedKey","fnStr","toString","hash","maxLength","Math","min","length","i","char","charCodeAt","abs","createFunctionCacheKey","functionKey","getFunctionCache","setFunctionCache","languages","PluginConfig","LANGUAGE_FIELD_NAME","const","MAX_COLUMNS","codeOnly","titleOnly","titleAndCode","CONFIG_DEFAULT","Required","languages","select","defaultLanguages","fieldTypes","apiVersion","buttonLocations","buttonAddAll","restoreOrder","languageDisplay","includeForDocumentType","documentType","languageFilter","documentTypes","SanityDocument","DocumentsToTranslate","path","pathString","_key","language","_type","key","getDocumentsToTranslate","value","rootPath","Array","isArray","arrayRootPath","internationalizedValues","filter","item","type","startsWith","endsWith","length","map","internationalizedValue","Object","assign","join","flatMap","index","startsWithUnderscoreRegex","itemKeys","keys","match","selectedValue","LanguageDisplay","getLanguageDisplay","languageDisplay","title","code","toUpperCase","get","getSelectedValue","select","Record","document","x","selection","selectedValue","key","path","Object","entries","value","Array","isArray","filter","item","_type","useLanguageFilterStudioContext","React","createContext","use","useContext","useDeferredValue","useMemo","useClient","useWorkspace","useDocumentPane","createCacheKey","createOrGetPromise","setFunctionCache","CONFIG_DEFAULT","Language","PluginConfig","getSelectedValue","InternationalizedArrayContextProps","Required","languages","filteredLanguages","InternationalizedArrayContext","useInternationalizedArrayContext","InternationalizedArrayProviderProps","internationalizedArray","documentType","InternationalizedArrayProvider","props","$","_c","t0","apiVersion","client","workspace","formState","deferredDocument","value","t1","select","selectedValue","t2","bb0","name","t3","t4","title","t5","workspaceKey","JSON","stringify","workspaceId","cacheKey","bb1","Array","isArray","result","t6","languagesPromise","selectedLanguageIds","options","languageFilterOptions","documentTypes","includes","languageFilterEnabled","filter","language","id","t7","context","t8","children","AddIcon","Button","Grid","MAX_COLUMNS","getLanguageDisplay","useInternationalizedArrayContext","AddButtonsProps","readOnly","handleClick","languageId","languagesInUse","AddButtons","props","$","_c","languageDisplay","filteredLanguages","languages","length","t0","Math","min","t1","t2","language","languageTitle","title","id","includes","undefined","map","Box","Stack","Text","useToast","randomKey","ReactElement","useCallback","FormInsertPatch","FormSetIfMissingPatch","insert","isSanityDocument","PatchEvent","setIfMissing","useGetFormValue","useSchema","useDocumentPane","LANGUAGE_FIELD_NAME","DocumentsToTranslate","getDocumentsToTranslate","AddButtons","useInternationalizedArrayContext","DocumentAddButtons","$","_c","getFormValue","filteredLanguages","toast","onChange","formState","schema","t0","typeName","match","baseTypeName","charAt","toLowerCase","slice","arrayBasedTypes","Set","has","schemaType","get","fields","Array","name","type","jsonType","of","valueField","find","_temp","fieldType","undefined","getInitialValueForType","t1","languageId","value","push","status","title","documentsToTranslation","alreadyTranslated","filter","translation","removeDuplicates","reduce","filteredTranslations","translation_0","alreadyTranslation","pathString","length","translationAlreadyExists","filteredTranslation","path","language","l","id","patches","toTranslate","initialValue","_type","ifMissing","insertValue","_key","from","flat","handleDocumentButtonClick","t2","Symbol","for","t3","Boolean","readOnly","t4","t5","f","Stack","ObjectInputProps","PluginConfig","DocumentAddButtons","InternationalizedArrayFormInput","props","$","_c","showDocumentButtons","pluginConfig","buttonLocations","includes","t0","Symbol","for","t1","renderDefault","t2","isDocumentSchemaType","ObjectField","SchemaType","hasInternationalizedArrayField","schemaType","hasInternationalizedArrayInFields","fields","visited","Set","field","has","type","add","name","startsWith","jsonType","of","length","item","Array","isArray","useSchema","DocumentLayoutProps","PluginConfig","hasInternationalizedArrayField","InternationalizedArrayProvider","InternationalizedArrayLayout","props","$","_c","schema","schemaType","get","documentType","console","error","t0","renderDefault","hasInternationalizedArray","pluginConfig","includeForDocumentType","t1","t2","t3","useClient","createCacheKey","peek","preloadWithKey","setFunctionCache","PluginConfig","Preload","props","$","_c","t0","apiVersion","client","cacheKey","Array","isArray","languages","result","LANGUAGE_FIELD_NAME","Language","InternationalizedArrayItem","checkAllLanguagesArePresent","languages","value","filteredLanguageIds","Set","map","l","id","languagesInUseIds","v","length","size","every","key","has","Language","InternationalizedArrayItem","createAddAllTitle","value","languages","length","title","LanguageFilterConfig","FieldDefinition","Rule","RuleTypeConstraint","SanityClient","Language","id","Intl","UnicodeBCP47LocaleIdentifier","title","AllowedType","ArrayConfig","name","type","languages","group","hidden","readOnly","validation","field","key","options","Value","_key","language","value","isInternationalizedArrayItemType","InternationalizedArrayItem","startsWith","endsWith","T","_type","LanguageCallback","client","selectedValue","Record","Promise","LanguageDisplay","PluginConfig","apiVersion","select","defaultLanguages","fieldTypes","buttonLocations","buttonAddAll","restoreOrder","languageDisplay","includeForDocumentType","documentType","languageFilter","documentTypes","Required","randomKey","FormInsertPatch","insert","Path","LANGUAGE_FIELD_NAME","Language","InternationalizedArrayItem","isInternationalizedArrayItemType","AddConfig","addLanguageKeys","schemaTypeName","languages","filteredLanguages","value","path","createAddLanguagePatches","config","type","Error","itemBase","_type","getNewItems","Array","isArray","length","filter","id","find","v","map","Object","assign","_key","language","newItems","languagesInUse","insertions","item","itemLanguage","languageIndex","findIndex","l","remainingLanguages","slice","nextLanguageIndex","r","push","splice","AddIcon","TranslateIcon","useCallback","defineDocumentFieldAction","DocumentFieldActionItem","DocumentFieldActionProps","PatchEvent","setIfMissing","useFormValue","useDocumentPane","useInternationalizedArrayContext","LANGUAGE_FIELD_NAME","Language","InternationalizedArrayItem","checkAllLanguagesArePresent","createAddAllTitle","createAddLanguagePatches","createTranslateFieldActions","fieldActionProps","context","languages","filteredLanguages","map","language","value","path","onChange","formState","disabled","Boolean","readOnly","Array","isArray","find","item","id","hidden","some","f","onAction","schemaType","addLanguageKeys","patches","schemaTypeName","name","from","type","icon","title","AddMissingTranslationsFieldAction","length","internationalizedArrayFieldAction","useAction","isInternationalizedArrayField","startsWith","translateFieldActions","renderAsButton","children","camelCase","upperFirst","pascalCase","string","createFieldName","name","addValue","join","ObjectSchemaType","FieldMember","FieldsetState","LANGUAGE_FIELD_NAME","isInternationalizedArrayItemType","Language","internationalizedArrayLanguageFilter","enclosingType","_member","selectedLanguageIds","parentValue","Record","languages","name","language","isAValidLanguage","find","l","id","includes","Card","Stack","Text","Code","React","schemaExample","languages","id","title","Feedback","$","_c","t0","Symbol","for","t1","t2","t3","JSON","stringify","WarningOutlineIcon","Box","Card","Flex","Stack","Text","ReactElement","InternationalizedArrayItem","MigrationBannerProps","itemsNeedingMigration","MigrationBanner","t0","$","_c","length","t1","Symbol","for","t2","t3","t4","t5","t6","t7","t8","t9","AddIcon","useLanguageFilterStudioContext","Button","Card","Stack","Text","useToast","React","useCallback","useEffect","useMemo","ArrayOfObjectsInputProps","ArrayOfObjectsItem","MemberItemError","set","setIfMissing","useFormValue","useGetFormValue","useDocumentPane","LANGUAGE_FIELD_NAME","InternationalizedArrayItem","checkAllLanguagesArePresent","createAddAllTitle","createAddLanguagePatches","internationalizedArrayLanguageFilter","AddButtons","Feedback","useInternationalizedArrayContext","MigrationBanner","InternationalizedArray","props","$","_c","members","value","_value","schemaType","onChange","readOnly","documentReadOnly","t0","filter","_temp","itemsNeedingMigration","shouldMigrateArray","length","Boolean","toast","getFormValue","languages","filteredLanguages","defaultLanguages","buttonAddAll","buttonLocations","restoreOrder","languageFilter","builtInLanguageFilter","selectedLanguageIds","options","languageFilterOptions","t1","Symbol","for","documentType","t2","documentTypes","includes","usingLanguageFilterPlugin","t3","usingBuiltInLanguageFilter","t4","member","kind","valueMember","item","filterField","filteredMembers","t5","path","addLanguageKeys","formValue","patches","Array","isArray","schemaTypeName","name","handleAddLanguages","isDeleted","isDeleting","t6","documentExists","t7","map","_temp2","join","languageKeysFromValue","t8","bb0","languageKeys","split","t9","l","find","key","id","_temp3","addedLanguages","t10","hasAddedDefaultLanguages","language","l_1","every","language_0","languagesToAdd","language_1","language_2","l_2","timeout","setTimeout","clearTimeout","t11","updatedValue","reduce","acc","v_1","newIndex","findIndex","l_3","v","push","title","status","handleRestoreOrder","t12","bb1","t13","v_2","l_4","allKeysAreLanguages","bb2","t14","t15","v_3","vIndex","language_3","languagesOutOfOrder","languagesAreValid","_temp4","t16","allLanguagesArePresent","t17","_temp5","addAllMissingLanguages","t18","addButtonsAreVisible","fieldHasMembers","t19","addAllTitle","t20","t21","member_0","t22","t23","t24","language_4","l_0","v_0","_key","SchemaType","ArrayFieldOptions","getLanguagesFieldOption","schemaType","undefined","languagesOption","options","languages","type","defineField","FieldDefinition","FieldProps","Rule","getFunctionCache","peek","setFunctionCache","createFieldName","getSelectedValue","InternationalizedArray","LANGUAGE_FIELD_NAME","Language","LanguageCallback","InternationalizedArrayItem","getLanguagesFieldOption","ArrayFactoryConfig","apiVersion","select","Record","languages","defaultLanguages","type","ArrayFieldOptions","Pick","config","typeName","name","arrayName","objectName","title","components","field","props","renderDefault","level","input","options","of","validation","rule","custom","value","context","length","itemsMissingLanguage","filter","item","_key","message","paths","flatMap","selectedValue","document","client","getClient","contextLanguages","languagesFieldOption","Array","isArray","cachedLanguages","suspendCachedLanguages","languageIds","Set","map","lang","id","nonLanguageKeys","has","seenLanguages","duplicateValues","push","add","CardTone","FormNodeValidation","getToneFromValidation","validations","length","undefined","validationLevels","Set","map","v","level","has","RemoveCircleIcon","Box","Button","Card","Flex","Label","Spinner","Text","Menu","MenuButton","MenuItem","Tooltip","React","ReactNode","useCallback","useMemo","FormPatch","ObjectItemProps","PatchEvent","Path","useFormValue","set","unset","LANGUAGE_FIELD_NAME","InternationalizedArrayItem","getLanguageDisplay","getToneFromValidation","useInternationalizedArrayContext","ChangeLanguageButton","props","$","_c","value","onChange","path","t0","slice","parentValue","languages","t1","map","_temp","languageKeysInUse","t2","event","languageId","currentTarget","length","find","l","id","handleKeyChange","t3","t4","t5","t6","t7","lang","includes","toLocaleUpperCase","t8","Symbol","for","portal","t9","v","RemoveButton","isDefault","readOnly","handleUnset","paddingBottom","InternationalizedInput","originalOnChange","inputProps","patches","Array","isArray","Parameters","valueField","isEmptyOrUndefined","undefined","hasProblematicInsert","some","_temp2","initPatch","type","fixedPatches","_temp3","allPatches","wrappedOnChange","languageDisplay","defaultLanguages","Boolean","keyIsValid","language","l_0","title","languageTitle","members","member","kind","field","schemaType","itemNeedsMigration","Object","assign","filter","_temp4","inlineProps","validation","renderInput","t10","t11","t12","t13","m","name","patch_0","patch","fixedPath","fixedPatch","isTargetingValue","defineField","FieldDefinition","FieldProps","createFieldName","InternationalizedInput","LANGUAGE_FIELD_NAME","ObjectFactoryConfig","type","config","typeName","name","objectName","title","components","item","field","props","renderDefault","level","fields","hidden","validation","Rule","required","preview","select","subtitle","languageFilter","definePlugin","isObjectInputProps","InternationalizedArrayFormInput","InternationalizedArrayLayout","Preload","CONFIG_DEFAULT","internationalizedArrayFieldAction","array","object","PluginConfig","hasInternationalizedArrayField","internationalizedArray","config","pluginConfig","apiVersion","select","languages","fieldTypes","defaultLanguages","buttonLocations","languageFilterConfig","name","studio","Array","isArray","undefined","components","layout","props","renderDefault","document","unstable_layout","unstable_fieldActions","includes","prev","form","input","isRootInput","id","hasInternationalizedArray","schemaType","includeForDocumentType","schema","types","map","type","plugins","documentTypes","length","supportedLanguages"],"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/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 // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n const itemKeys = Object.keys(value).filter(\n (key) => !key.match(startsWithUnderscoreRegex),\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 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 return `Add missing ${languages.length - value.length === 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 * @defaultValue ['field']\n * */\n buttonLocations?: ('field' | 'unstable__fieldAction' | 'document')[]\n /**\n * Show or hide the \"Add missing languages\" button\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 {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, useEffect, useMemo} from 'react'\nimport {\n type ArrayOfObjectsInputProps,\n ArrayOfObjectsItem,\n MemberItemError,\n set,\n setIfMissing,\n useFormValue,\n useGetFormValue,\n} from 'sanity'\nimport {useDocumentPane} from 'sanity/structure'\n\nimport {LANGUAGE_FIELD_NAME} from '../constants'\nimport type {InternationalizedArrayItem} from '../types'\nimport {checkAllLanguagesArePresent} from '../utils/checkAllLanguagesArePresent'\nimport {createAddAllTitle} from '../utils/createAddAllTitle'\nimport {createAddLanguagePatches} from '../utils/createAddLanguagePatches'\nimport {internationalizedArrayLanguageFilter} from '../utils/internationalizedArrayLanguageFilter'\nimport AddButtons from './AddButtons'\nimport Feedback from './Feedback'\nimport {useInternationalizedArrayContext} from './InternationalizedArrayContext'\nimport {MigrationBanner} from './MigrationBanner'\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 and an \"Add all / Add\n * missing languages\" button (controlled by `buttonAddAll` and\n * `buttonLocations` config). Dispatches `setIfMissing` + `insert` patches.\n * - **Default languages**: Automatically adds entries for languages listed in\n * `defaultLanguages` when those entries are missing. Only runs once the\n * document exists in the dataset (it has a `_rev`), so the effect never\n * recreates a just-deleted document or creates a draft before the user's\n * first edit.\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 readOnly = Boolean(documentReadOnly) || schemaType.readOnly === true\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\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 handleAddLanguages = useCallback(\n (addLanguageKeys: string[] | string) => {\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],\n )\n\n const {isDeleted, isDeleting} = useDocumentPane()\n\n // The document only has a revision once it exists in the dataset. Patching\n // a nonexistent document would create it: auto-adding default languages to\n // a just-deleted document resurrects it as an empty draft (and the deleted\n // pane can outrace `isDeleted`), and auto-adding to an unsaved new document\n // creates a draft before the user has made any edits.\n const documentExists = Boolean(useFormValue(['_rev']))\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 documentExists &&\n !isDeleting &&\n !isDeleted &&\n !hasAddedDefaultLanguages &&\n !shouldMigrateArray\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 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 (!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])\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 // compare value keys with possible languages\n const allLanguagesArePresent = useMemo(\n () => checkAllLanguagesArePresent(filteredLanguages, value),\n [filteredLanguages, value],\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 addButtonsAreVisible =\n !shouldMigrateArray &&\n // Plugin was configured to display buttons here (default!)\n buttonLocations.includes('field') &&\n // There's at least one language visible\n filteredLanguages?.length > 0 &&\n // Not every language has a value yet\n !allLanguagesArePresent\n const fieldHasMembers = members?.length > 0\n const addAllTitle = createAddAllTitle(value, filteredLanguages)\n\n return (\n <Stack gap={2}>\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 {!addButtonsAreVisible && !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 {addButtonsAreVisible ? (\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 || allLanguagesArePresent}\n icon={AddIcon}\n text={addAllTitle}\n onClick={addAllMissingLanguages}\n />\n ) : null}\n </Stack>\n ) : null}\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'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":";;;;;;;;;;;;;;;;;;;;AAEA,MAAME,YAAY,yCAKZE,mCAAmB,IAAIC,QAAkC,GAGzDC,+BAAe,IAAIC,IAAiC,GAGpDE,gCAAgB,IAAIF,IAAwB;AAGlD,SAASG,kBAAkBC,KAAwB;CACjD,OAAOC,KAAKC,UAAUF,GAAG;AAC3B;AAGA,MAAaG,kBAAkBC,IAA+BJ,QAA6B;CACzF,IAAMK,SAASN,kBAAkBC,GAAG;CACpC,AAAKL,aAAaW,IAAID,MAAM,KAC1BV,aAAaY,IAAIF,QAAQD,GAAG,CAAC;AAEjC,GAGaI,cAAc;CACzBb,aAAaa,MAAM;AACrB,GAGaC,QAAQC,kBAA2C;CAC9D,IAAMV,MAAMD,kBAAkB;EAACP;EAASD;EAAWmB;CAAa,CAAC,GAC3DE,UAAUjB,aAAakB,IAAIb,GAAG;CACpC,IAAIY,WAGcA,QAAgBG,YACjB,aAEb,OAAQH,QAAgBI;AAI9B,GAGaE,kBAAkBR,eAAwCS,gBAAyB;CAC9F,IAAMC,oBAAoBnB,KAAKC,UAAUQ,aAAa;CACtD,OAAOS,cACH;EAAC3B;EAASD;EAAW6B;EAAmBD;CAAW,IACnD;EAAC3B;EAASD;EAAW6B;CAAiB;AAC5C,GAGaC,sBACXjB,IACAJ,QACwB;CACxB,IAAMK,SAASN,kBAAkBC,GAAG;CACpC,IAAIL,aAAaW,IAAID,MAAM,GACzB,OAAOV,aAAakB,IAAIR,MAAM;CAEhC,IAAMO,UAAUR,GAAG;CAEnB,OADAT,aAAaY,IAAIF,QAAQO,OAAO,GACzBA;AACT,GAGMU,kBAAkBlB,OAAiC;CAEvD,IAAMmB,YAAY9B,iBAAiBoB,IAAIT,EAAE;CACzC,IAAImB,WACF,OAAOA;CAIT,IAAMC,QAAQpB,GAAGqB,SAAS,GACtBC,OAAO,GAELC,YAAYC,KAAKC,IAAIL,MAAMM,QAAQ,GAAG;CAC5C,KAAK,IAAIC,IAAI,GAAGA,IAAIJ,WAAWI,KAAK;EAClC,IAAMC,OAAOR,MAAMS,WAAWF,CAAC;EAE/BL,AADAA,QAAQA,QAAQ,KAAKA,OAAOM,MAC5BN,QAAQA;CACV;CACA,IAAM1B,MAAM,aAAa4B,KAAKM,IAAIR,IAAI;CAEtC,OADAjC,iBAAiBc,IAAIH,IAAIJ,GAAG,GACrBA;AACT,GAGMmC,0BACJ/B,IACAM,eACAS,gBACW;CACX,IAAMiB,cAAcd,eAAelB,EAAE,GAC/BgB,oBAAoBnB,KAAKC,UAAUQ,aAAa;CACtD,OAAOS,cACH,GAAGiB,YAAW,GAAIhB,kBAAiB,GAAID,gBACvC,GAAGiB,YAAW,GAAIhB;AACxB,GAGaiB,oBACXjC,IACAM,eACAS,gBAC2B;CAC3B,IAAMnB,MAAMmC,uBAAuB/B,IAAIM,eAAeS,WAAW;CACjE,OAAOrB,cAAce,IAAIb,GAAG;AAC9B,GAEasC,oBACXlC,IACAM,eACA6B,WACApB,gBACS;CACT,IAAMnB,MAAMmC,uBAAuB/B,IAAIM,eAAeS,WAAW;CACjErB,cAAcS,IAAIP,KAAKuC,SAAS;AAClC,GCpGaE,sBAAsB,YAEtBE,cAAc;CACzBC,UAAU;CACVC,WAAW;CACXC,cAAc;AAChB,GAEaC,iBAAyC;CACpDE,WAAW,CAAA;CACXC,QAAQ,CAAC;CACTC,kBAAkB,CAAA;CAClBC,YAAY,CAAA;CACZC,YAAY;CACZC,iBAAiB,CAAC,OAAO;CACzBC,cAAc;CACdC,cAAc;CACdC,iBAAiB;CACjBC,yBAAyBC,iBAAiBA,iBAAiB;CAC3DC,gBAAgB,EACdC,eAAe,CAAA,EACjB;AACF,GCvBaS,2BAEXC,OACAC,WAAgC,CAAA,MACL;CAC3B,IAAIC,MAAMC,QAAQH,KAAK,GAAG;EACxB,IAAMI,gBAAgB,CAAC,GAAGH,QAAQ,GAG5BI,0BAA0BL,MAAMM,QAAQC,SAAS;GACrD,IAAIL,MAAMC,QAAQI,IAAI,GAAG,OAAO;GAEhC,IAAI,OAAOA,QAAS,UAAU;IAE5B,IAAMC,OAAOD,MAAMV;IACnB,OAAOW,MAAMC,WAAW,wBAAwB,KAAKD,MAAME,SAAS,OAAO;GAC7E;GACA,OAAO;EACT,CAAC;EAiBD,OAfIL,wBAAwBM,SAAS,IAC5BN,wBAAwBO,KAAKC,2BAC3BC,OAAOC,OAAO,CAAC,GAAGF,wBAAwB;GAC/CpB,MAAMW;GACNV,YAAYU,cAAcY,KAAK,GAAG;EACpC,CAAC,CACF,IAGChB,MAAMW,SAAS,IACVX,MAAMiB,SAASV,MAAMW,UAC1BnB,wBAAwBQ,MAAM,CAAC,GAAGH,eAAec,KAAK,CAAC,CACzD,IAGK,CAAA;CACT;CACA,IAAI,OAAOlB,SAAU,YAAYA,OAAO;EACtC,IAAMmB,4BAA4B;EAMlC,OAJiBL,OAAOO,KAAKrB,KAAK,CAAC,CAACM,QACjCR,QAAQ,CAACA,IAAIwB,MAAMH,yBAAyB,CAGxCC,CAAQ,CAACH,SAASV,SAAS;GAChC,IAAMgB,gBAAgBvB,MAAMO,OACtBd,OAAO,CAAC,GAAGQ,UAAUM,IAAI;GAC/B,OAAOR,wBAAwBwB,eAAe9B,IAAI;EACpD,CAAC;CACH;CACA,OAAO,CAAA;AACT;;;;;;;;;;;AC/DA,SAAgBgC,mBACdC,iBACAC,OACAC,MACQ;CAIR,OAHIF,oBAAoB,aAAmBE,KAAKC,YAAY,IACxDH,oBAAoB,cAAoBC,QACxCD,oBAAoB,iBAAuB,GAAGC,MAAK,IAAKC,KAAKC,YAAY,EAAC,KACvEF;AACT;;;;;;;;;;;;;;ACNA,MAAaI,oBACXC,QACAE,aAK4B;CAC5B,IAAI,CAACF,UAAU,CAACE,UACd,OAAO,CAAC;CAGV,IAAME,YAAoCJ,UAAU,CAAC,GAC/CK,gBAAyC,CAAC;CAChD,KAAK,IAAM,CAACC,KAAKC,SAASC,OAAOC,QAAQL,SAAS,GAAG;EACnD,IAAIM,QAAQZ,IAAII,UAAUK,IAAI;EAO9BF,AANIM,MAAMC,QAAQF,KAAK,MAErBA,QAAQA,MAAMG,QAAQC,SACpB,OAAOA,QAAS,YAAWA,MAAMC,UAAU,eAAe,UAAUD,IACtE,IAEFT,cAAcC,OAAOI;CACvB;CAEA,OAAOL;AACT,GCtBMgC,gCAAgCnB,cAAkD;CACtF,GAAGW;CACHM,WAAW,CAAA;CACXC,mBAAmB,CAAA;AACrB,CAAC;AAED,SAAOE,mCAAA;CAAA,OACElB,WAAWiB,6BAA6B;AAAC;AAQlD,SAAOK,+BAAAC,OAAA;CAAA,IAAAC,IAAAC,EAAA,EAAA,GAGL,EAAAL,wBAAAC,iBAA+CE,OAAKG;CAAA,AAAAF,EAAA,OAAAJ,uBAAAO,aAEoBD,KAAAF,EAAA,MAA/CE,KAAA,EAAAC,YAAaP,uBAAsBO,WAAW,GAACH,EAAA,KAAAJ,uBAAAO,YAAAH,EAAA,KAAAE;CAAxE,IAAAE,SAAezB,UAAUuB,EAA+C,GACxEG,YAAkBzB,aAAa,GAC/B,EAAA0B,cAAoBzB,gBAAgB,GACpC0B,mBAAyB9B,iBAAiB6B,WAASE,KAAO,GAACC;CAAA,AAAAT,EAAA,OAAAO,oBAAAP,EAAA,OAAAJ,uBAAAc,UAEnDD,KAAArB,iBAAiBQ,uBAAsBc,QAASH,gBAAgB,GAACP,EAAA,KAAAO,kBAAAP,EAAA,KAAAJ,uBAAAc,QAAAV,EAAA,KAAAS,MAAAA,KAAAT,EAAA;CADzE,IAAAW,gBACQF,IAEPG;CAAAC,KAAA;EAKC,IAAIR,WAASS,MAAM;GACjBF,KAAOP,UAASS;GAAhB,MAAAD;EAAqB;EAIf,IAAAE,KAAAV,WAASS,MACRE,KAAAX,WAASY,OAAOC;EAGzBN,AAHyBZ,EAAA,OAAAe,MAAAf,EAAA,OAAAgB,MAGlBE,KAAAE,KAAIC,UAAWF;GALDL,MACbC;GAAeE,OACdD;EAGaG,CAAY,GAACnB,EAAA,KAAAe,IAAAf,EAAA,KAAAgB,IAAAhB,EAAA,KAAAkB,MAAAA,KAAAlB,EAAA,IAAnCY,KAAOM;CAA4B;CAXrC,IAAAI,cAAoBV,IAYLG;CAAA,AAAAf,EAAA,OAAAW,iBAAAX,EAAA,OAAAsB,eAIPP,KAAAjC,eAAe6B,eAAeW,WAAW,GAACtB,EAAA,KAAAW,eAAAX,EAAA,KAAAsB,aAAAtB,EAAA,MAAAe,MAAAA,KAAAf,EAAA;CADlD,IAAAuB,WACQR,IAEPC;CAAAQ,KAAA;EAIC,IAAIC,MAAKC,QAAS9B,uBAAsBL,SAAU,GAAC;GACjDyB,KAAO;GAAP,MAAAQ;EAAW;EACZ,IAAAN;EAAA,AAAAlB,EAAA,QAAAI,UAAAJ,EAAA,QAAAJ,0BAAAI,EAAA,QAAAW,iBAAAX,EAAA,QAAAsB,eAGyBJ,KAAA,YAAA;GACxB,IAAI,OAAOtB,uBAAsBL,aAAe,YAAU;IACxD,IAAAoC,SAAe,MAAM/B,uBAAsBL,UAAWa,QAAQO,aAAa;IAEW,OAAtF3B,iBAAiBY,uBAAsBL,WAAYoB,eAAegB,QAAQL,WAAW,GAC9EK;GAAM;GACd,OACM/B,uBAAsBL;EAAU,GACxCS,EAAA,MAAAI,QAAAJ,EAAA,MAAAJ,wBAAAI,EAAA,MAAAW,eAAAX,EAAA,MAAAsB,aAAAtB,EAAA,MAAAkB,MAAAA,KAAAlB,EAAA;EAAA,IAAA4B;EARDZ,AAQChB,EAAA,QAAAuB,YAAAvB,EAAA,QAAAkB,MARMU,KAAA7C,mBAAmBmC,IAQvBK,QAAQ,GAACvB,EAAA,MAAAuB,UAAAvB,EAAA,MAAAkB,IAAAlB,EAAA,MAAA4B,MAAAA,KAAA5B,EAAA,KARZgB,KAAOY;CAQK;CAdd,IAAAC,mBAAyBb,IAkBzBzB,YAAkBsC,mBACdtD,IAAIsD,gBAE2C,IAA9CjC,uBAAsBL,WAG3B,EAAAuC,qBAAAC,SAAAC,0BAA8D5D,+BAA+B,GAAC8C;CAAA,AAAAlB,EAAA,QAAAH,gBAAAG,EAAA,QAAAgC,sBAAAC,iBAG9Df,KAAAc,sBAAqBC,cAAcC,SAAUrC,YAAY,GAACG,EAAA,MAAAH,cAAAG,EAAA,MAAAgC,sBAAAC,eAAAjC,EAAA,MAAAkB,MAAAA,KAAAlB,EAAA;CAAxF,IAAAmC,wBAA8BjB,IAA0DU;CAAA,AAAA5B,EAAA,QAAAmC,yBAAAnC,EAAA,QAAAT,aAAAS,EAAA,QAAA8B,uBAEjFF,KAAAO,wBACH5C,UAAS6C,QAAQC,aAAcP,oBAAmBI,SAAUG,SAAQC,EAAG,CAC/D,IAFL/C,WAEMS,EAAA,MAAAmC,uBAAAnC,EAAA,MAAAT,WAAAS,EAAA,MAAA8B,qBAAA9B,EAAA,MAAA4B,MAAAA,KAAA5B,EAAA;CALf,IAAAR,oBAGEoC,IAGuEW;CAAA,AAAAvC,EAAA,QAAAR,qBAAAQ,EAAA,QAAAJ,0BAAAI,EAAA,QAAAT,aAGhEgD,KAAA;EAAA,GAAI3C;EAAsBL;EAAAC;CAA8B,GAACQ,EAAA,MAAAR,mBAAAQ,EAAA,MAAAJ,wBAAAI,EAAA,MAAAT,WAAAS,EAAA,MAAAuC,MAAAA,KAAAvC,EAAA;CADlE,IAAAwC,UACSD,IAERE;CAK0C,OAL1CzC,EAAA,QAAAwC,WAAAxC,EAAA,QAAAD,MAAA2C,YAGCD,KAAA,oBAAA,8BAAA,UAAA;EAA+CD,OAAAA;EAC5CzC,UAAAA,MAAK2C;CACR,CAAA,GAAyC1C,EAAA,MAAAwC,SAAAxC,EAAA,MAAAD,MAAA2C,UAAA1C,EAAA,MAAAyC,MAAAA,KAAAzC,EAAA,KAFzCyC;AAEyC;;;;;;;;;;;;;;;;ACnF7C,SAAAa,WAAAC,OAAA;CAAA,IAAAC,IAAAC,EAAA,EAAA,GACE,EAAAP,UAAAG,gBAAAF,gBAAgDI,OAChD,EAAAG,iBAAAC,mBAAAC,cAAwDZ,iCAAiC;CAEzF,IAAI,CAACY,UAASC,QAAO,OAAS;CAIL,IAAAC,KAAAC,KAAIC,IAAKJ,UAASC,QAASf,YAAYY,gBAAgB,GAACO;CAAA,IAAAT,EAAA,OAAAL,eAAAK,EAAA,OAAAE,mBAAAF,EAAA,OAAAI,aAAAJ,EAAA,OAAAH,kBAAAG,EAAA,OAAAN,UAAA;EAAA,IAAAgB;EA6B3EV,AA7B2EA,EAAA,OAAAL,eAAAK,EAAA,OAAAE,mBAAAF,EAAA,OAAAI,UAAAC,UAAAL,EAAA,OAAAH,kBAAAG,EAAA,QAAAN,YAI9DgB,MAAAC,aAAA;GACb,IAAAC,gBAA8BrB,mBAC5BW,iBACAS,SAAQE,OACRF,SAAQG,EACV;GAAC,OAEC,oBAAC,QAAD;IAEO,MAAA;IACA,MAAA;IACK,UAAA;IACG,eAAA,OAAOH,SAAQG;IAClB,UAAApB,YAAYG,eAAckB,SAAUJ,SAAQG,EAAG;IACnDF,MAAAA;IAGJ,MAAAR,UAASC,SAAUf,YAAYY,oBAAoBA,oBAAoB,aAAvEc,KAAAA,IAAA7B;IAIK,OAAAwB,SAAQG;IACN,eAAMnB,YAAYgB,SAAQG,EAAG;GAAC,GAdlCH,SAAQG,EAc0B;EACvC,GAELd,EAAA,KAAAL,aAAAK,EAAA,KAAAE,iBAAAF,EAAA,KAAAI,UAAAC,QAAAL,EAAA,KAAAH,gBAAAG,EAAA,MAAAN,UAAAM,EAAA,MAAAU,MAAAA,KAAAV,EAAA,KAzBAS,KAAAL,UAASa,IAAKP,EAyBd,GAACV,EAAA,KAAAL,aAAAK,EAAA,KAAAE,iBAAAF,EAAA,KAAAI,WAAAJ,EAAA,KAAAH,gBAAAG,EAAA,KAAAN,UAAAM,EAAA,KAAAS;CAAA,OAAAA,KAAAT,EAAA;CAAA,IAAAU;CACG,OADHV,EAAA,QAAAM,MAAAN,EAAA,QAAAS,MA9BJC,KAAA,oBAAC,MAAD;EACuB,qBAAAJ;EAChB,KAAA;EACO,eAAA;EAEXG,UAAAA;CALE,CAAA,GA+BET,EAAA,MAAAM,IAAAN,EAAA,MAAAS,IAAAT,EAAA,MAAAU,MAAAA,KAAAV,EAAA,KA/BPU;AA+BO;;;;;;;;;;;;;;;;;;;AC3BX,SAAe6B,qBAAA;CAAA,IAAAC,IAAAC,EAAA,EAAA,GACbC,eAAqBX,gBAAgB,GACrC,EAAAY,sBAA4BL,iCAAiC,GAE7DM,QAAcvB,SAAS,GACvB,EAAAwB,UAAAC,cAA8Bb,gBAAgB,GAC9Cc,SAAef,UAAU,GAACgB;CAAA,AAAAR,EAAA,OAAAO,SA8CvBC,KAAAR,EAAA,MA1CDQ,MAAAC,aAAA;EACE,IAAI,CAACA,UAAQ;EAIb,IAAAC,QAAcD,SAAQC,MAAO,mCAAmC;EAChE,IAAI,CAACA,SAAD,CAAWA,MAAK,IAAG;EAEvB,IAAAC,eAAqBD,MAAK,EAAG,CAAAE,OAAQ,CAAC,CAAC,CAAAC,YAAa,IAAIH,MAAK,EAAG,CAAAI,MAAO,CAAC,GAGxEC,kCAAwB,IAAIC,IAAI;GAAC;GAAQ;GAAe;GAAgB;EAAc,CAAC;EACvF,IAAID,gBAAeE,IAAKN,YAAY,GAAC,OAC5B,CAAA;EAIT,IAAAO,aAAmBX,OAAMY,IAAKV,QAAQ;EACtC,IAAIS,cAAc,YAAYA,YAAU;GAOtC,IAAAQ,aAJeR,WAAUE,OAIAO,KAAMC,OAAyB;GACxD,IAAIF,YAAU;IACZ,IAAAG,YAAkBH,WAAUH;IAE5B,IACEM,WAASL,aAAe,WACxBK,WAASP,SAAW,WACpBO,WAASN,SAAW,WACpBM,WAASJ,OAASK,KAAAA,KACjBD,WAASP,QAAUP,gBAAeE,IAAKY,UAASP,IAAK,GAAE,OAEjD,CAAA;GACR;EACF;CACF,GAGFtB,EAAA,KAAAO,QAAAP,EAAA,KAAAQ;CA3CH,IAAAuB,yBAA+BvB,IA6C9BwB;CAAA,AAAAhC,EAAA,OAAAG,qBAAAH,EAAA,OAAAE,gBAAAF,EAAA,OAAA+B,0BAAA/B,EAAA,OAAAK,YAAAL,EAAA,OAAAI,SAGC4B,KAAA,OAAAC,eAAA;EACE,IAAAC,QAAchC,aAAa,CAAA,CAAE;EAC7B,IAAI,CAACd,iBAAiB8C,KAAK,GAAC;GAC1B9B,MAAK+B,KAAM;IAAAC,QACD;IAAOC,OACR;GACT,CAAC;GAAC;EAAA;EAGJ,IAAAC,yBAA+B1C,wBAAwBsC,OAAO,CAAA,CAAE,GAEhEK,oBAA0BD,uBAAsBE,QAC9CC,gBAAiBA,cAAc/C,yBAAyBuC,UAC1D,GACAS,mBAAyBJ,uBAAsBK,QAC7CC,sBAAAC,mBAEIN,kBAAiBC,QACfM,uBAAwBA,mBAAkBC,eAAgBN,cAAWM,UACvE,CAAC,CAAAC,SAAU,KAIoBJ,qBAAoBJ,QACnDU,wBAAyBA,oBAAmBC,SAAUV,cAAWU,IAG/DF,CAAwB,CAAAD,SAAU,KAGtCJ,qBAAoBT,KAAMM,aAAW,GAF5BG,uBAKX,CAAA,CACF;EACA,IAAIF,iBAAgBM,WAAY,GAAC;GAC/B,IAAAI,WAAiBjD,kBAAiBwB,MAAM0B,MAAOA,EAACC,OAAQrB,UAAU;GAClE7B,MAAK+B,KAAM;IAAAC,QACD;IAASC,OACV,+BAA+Be,UAAQf,SAARJ,WAA6B;GACrE,CAAC;GAAC;EAAA;EAKJ,IAAAsB,UAA6D,CAAA;EAE7D,KAAK,IAAAC,eAAqBd,kBAAgB;GACxC,IAAAS,OAAaK,YAAWL,MAExBM,eAAqB1B,uBAAuByB,YAAWE,KAAM,GAE7DC,YAAkBrE,aAAa,CAAA,GAAI6D,IAAI,GACvCS,cAAoBzE,OAClB,CACE;IAAA0E,MACQ/E,UAAU;KACfY,sBAAsBuC;IAAUyB,OAC1BF,YAAWE;IAAMxB,OACjBuB;GACT,CAAC,GAEH,SACA,CAAA,GAAIN,MAAM,EAAE,CACd;GAEAI,AADAA,QAAOpB,KAAMwB,SAAS,GACtBJ,QAAOpB,KAAMyB,WAAW;EAAC;EAG3BvD,SAAShB,WAAUyE,KAAMP,QAAOQ,KAAM,CAAC,CAAC;CAAC,GAC1C/D,EAAA,KAAAG,mBAAAH,EAAA,KAAAE,cAAAF,EAAA,KAAA+B,wBAAA/B,EAAA,KAAAK,UAAAL,EAAA,KAAAI,OAAAJ,EAAA,KAAAgC,MAAAA,KAAAhC,EAAA;CAvEH,IAAAgE,4BAAkChC,IAyEjCiC;CAAA,AAAAjE,EAAA,OAAAkE,OAAAC,IAAA,2BAAA,KAGGF,KAAA,oBAAC,KAAD,EAAA,UACE,oBAAC,MAAD;EAAY,MAAA;EAAU,QAAA;EAAW,UAAA;CAA5B,CAAA,EADH,CAAA,GAIEjE,EAAA,KAAAiE,MAAAA,KAAAjE,EAAA;CAEM,IAAAoE,KAAAC,EAAQ/D,WAASgE,UAAWC;CAAA,AAAAvE,EAAA,OAAAkE,OAAAC,IAAA,2BAAA,KAEtBI,KAAA,CAAA,GAAEvE,EAAA,KAAAuE,MAAAA,KAAAvE,EAAA;CAAA,IAAAwE;CAEd,OAFcxE,EAAA,QAAAgE,6BAAAhE,EAAA,QAAAoE,MATtBI,KAAA,qBAAC,OAAD;EAAY,KAAA;EAAe,eAAA;EAA3B,UAAA,CACEP,IAKA,oBAAC,YAAD;GACY,UAAAG;GACGJ,aAAAA;GACG,gBAAAO;EAAE,CAAA,CAThB;KAWEvE,EAAA,MAAAgE,2BAAAhE,EAAA,MAAAoE,IAAApE,EAAA,MAAAwE,MAAAA,KAAAxE,EAAA,KAXRwE;AAWQ;AA9IG,SAAA5C,QAAA6C,GAAA;CAAA,OAmC+BA,EAACnD,SAAU;AAAO;;;;;ACjEhE,SAAOwD,gCAAAC,OAAA;CAAA,IAAAC,IAAAC,EAAA,CAAA;CAKL,IAF4BF,MAAKI,cAA8BC,iBAAUC,SAAC,UAAU,GAE7D;EAAA,IAAAC;EAAA,AAAAN,EAAA,OAAAO,OAAAC,IAAA,2BAAA,KAGjBF,KAAA,oBAAC,oBAAD,CAAmB,CAAA,GAAGN,EAAA,KAAAM,MAAAA,KAAAN,EAAA;EAAA,IAAAS;EAAA,AAAAT,EAAA,OAAAD,QACKU,KAAAT,EAAA,MAA1BS,KAAAV,MAAKW,cAAeX,KAAK,GAACC,EAAA,KAAAD,OAAAC,EAAA,KAAAS;EAAA,IAAAE;EACrB,OADqBX,EAAA,OAAAS,KACrBE,KAAAX,EAAA,MAHRW,KAAA,qBAAC,OAAD;GAAY,KAAA;GAAZ,UAAA,CACEL,IACCG,EAFG;MAGET,EAAA,KAAAS,IAAAT,EAAA,KAAAW,KAHRA;CAGQ;CAEX,IAAAL;CACgC,OADhCN,EAAA,OAAAD,QACgCO,KAAAN,EAAA,MAA1BM,KAAAP,MAAKW,cAAeX,KAAK,GAACC,EAAA,KAAAD,OAAAC,EAAA,KAAAM,KAA1BA;AAA0B;;;;;;;ACfnC,SAAgBS,+BAA+BC,YAAiC;CAK9E,OAJKJ,qBAAqBI,UAAU,IAI7BC,kCAAkCD,WAAWE,MAAM,IAHjD;AAIX;AAEA,SAASD,kCACPC,QACAC,0BAAU,IAAIC,IAAa,GAClB;CACT,KAAK,IAAMC,SAASH,QACdC,aAAQG,IAAID,MAAME,IAAI,GAS1B;MANAJ,QAAQK,IAAIH,MAAME,IAAI,GAElBF,MAAME,KAAKE,KAAKC,WAAW,wBAAwB,KAKrDL,MAAME,KAAKI,aAAa,YACxBV,kCAAkCI,MAAME,KAAKL,QAAQC,OAAO,GAE5D,OAAO;EAGT,IAAIE,MAAME,KAAKI,aAAa,WAAWN,MAAME,KAAKK,GAAGC,SAAS,GAC5D,KAAK,IAAMC,QAAQT,MAAME,KAAKK,IAAI;GAChC,IACE,UAAUE,QACV,OAAOA,KAAKL,QAAS,YACrBK,KAAKL,KAAKC,WAAW,wBAAwB,GAE7C,OAAO;GAGT,IAAI,YAAYI,QAAQC,MAAMC,QAAQF,KAAKZ,MAAM,GAAG;IAClD,IAAIC,QAAQG,IAAIQ,IAAI,GAClB;IAIF,IAFAX,QAAQK,IAAIM,IAAI,GAEZb,kCAAkCa,KAAKZ,QAAQC,OAAO,GACxD,OAAO;GAEX;EACF;CAvBO;CA2BX,OAAO;AACT;ACxDA,SAAOmB,6BAAAC,OAAA;CAAA,IAAAC,IAAAC,EAAA,EAAA,GAILE,aADeV,UACIS,CAAM,CAAAE,IAAKL,MAAKM,YAAa;CAEhD,IAAI,CAACF,YAAU;EACbG,QAAOC,MAAO,0BAA0BR,MAAKM,cAAe;EAAC,IAAAG;EAC5B,OAD4BR,EAAA,OAAAD,QAC5BS,KAAAR,EAAA,MAA1BQ,KAAAT,MAAKU,cAAeV,KAAK,GAACC,EAAA,KAAAD,OAAAC,EAAA,KAAAQ,KAA1BA;CAA0B;CAInC,IADkCZ,+BAA+BO,UAC7DO,KAA6BX,MAAKY,aAAaC,uBAAwBb,MAAKM,YAAa,GAAC;EAGhE,IAAAG,KAAAT,MAAKY,cACfE,KAAAd,MAAKM,cAAaS;EAAA,AAAAd,EAAA,OAAAD,QAELe,KAAAd,EAAA,MAA1Bc,KAAAf,MAAKU,cAAeV,KAAK,GAACC,EAAA,KAAAD,OAAAC,EAAA,KAAAc;EAAA,IAAAC;EACI,OADJf,EAAA,OAAAD,MAAAM,gBAAAL,EAAA,OAAAD,MAAAY,gBAAAX,EAAA,OAAAc,MAJ7BC,KAAA,oBAAC,gCAAD;GAC0B,wBAAAP;GACV,cAAAK;GAEbC,UAAAA;EAJ4B,CAAA,GAKEd,EAAA,KAAAD,MAAAM,cAAAL,EAAA,KAAAD,MAAAY,cAAAX,EAAA,KAAAc,IAAAd,EAAA,KAAAe,MAAAA,KAAAf,EAAA,IALjCe;CAKiC;CAEpC,IAAAP;CAEgC,OAFhCR,EAAA,OAAAD,QAEgCS,KAAAR,EAAA,MAA1BQ,KAAAT,MAAKU,cAAeV,KAAK,GAACC,EAAA,KAAAD,OAAAC,EAAA,KAAAQ,KAA1BA;AAA0B;ACxBnC,SAAec,QAAAC,OAAA;CAAA,IAAAC,IAAAC,EAAA,CAAA,GAAAC;CAAA,AAAAF,EAAA,OAAAD,MAAAI,aAC0CD,KAAAF,EAAA,MAA9BE,KAAA,EAAAC,YAAaJ,MAAKI,WAAW,GAACH,EAAA,KAAAD,MAAAI,YAAAH,EAAA,KAAAE;CAAvD,IAAAE,SAAeZ,UAAUU,EAA8B,GAIvDG,WAAiBZ,eAAe,CAAC,CAAC;CAajC,OAXIa,MAAKC,QAASb,KAAK,CAAC,CAAC,CAAC,KACzBC,eAAe,YAAA;EACb,IAAIW,MAAKC,QAASR,MAAKS,SAAU,GAAC,OACzBT,MAAKS;EAEd,IAAAC,SAAe,MAAMV,MAAKS,UAAWJ,QAAQ,CAAC,CAAC;EAGF,OAA7CR,iBAAiBG,MAAKS,WAAY,CAAC,GAAGC,MAAM,GACrCA;CAAM,GACZJ,QAAQ,GAGN;AAAI;;;;;;;;;;;ACZb,SAAgBQ,4BACdC,WACAC,OACS;CACT,IAAMC,sBAAsB,IAAIC,IAAIH,UAAUI,KAAKC,MAAMA,EAAEC,EAAE,CAAC,GACxDC,oBAAoBN,QAAQA,MAAMG,KAAKI,MAAMA,EAAEZ,oBAAoB,IAAI,CAAA;CAI7E,OAFIW,kBAAkBE,WAAWP,oBAAoBQ,QACjD,IAAIP,IAAII,iBAAiB,CAAC,CAACG,SAASH,kBAAkBE,SAAe,KAClEF,kBAAkBI,OAAOC,QAAQV,oBAAoBW,IAAID,GAAG,CAAC;AACtE;;;;;;;;;ACbA,SAAgBI,kBACdC,OACAC,WACQ;CAKR,OAJID,OAAOE,SACF,eAAeD,UAAUC,SAASF,MAAME,WAAW,IAAI,aAAa,gBAGtED,UAAUC,WAAW,KAAKD,UAAU,KACvC,OAAOA,UAAU,EAAE,CAACE,MAAK,UACzB;AACN;ACUA,SAAgB2B,iCACdb,MAC6C;CAC7C,OAAOA,KAAKe,WAAW,wBAAwB,KAAKf,KAAKgB,SAAS,OAAO;AAC3E;;;;;;;;;;;;;;;;;ACMA,SAAgBsC,yBAAyBC,QAAsC;CAC7E,IAAM,EAACP,iBAAiBC,gBAAgBC,WAAWC,mBAAmBC,OAAOC,OAAO,CAAA,MAAME,QAEpFC,OAAO,GAAGP,eAAc;CAC9B,IAAI,CAACH,iCAAiCU,IAAI,GACxC,MAAUC,MAAM,yCAAyCD,MAAM;CAEjE,IAAME,WAAW,EAACC,OAAOH,KAAI,GAGvBI,oBACAC,MAAMC,QAAQd,eAAe,KAAKA,gBAAgBe,SAAS,IACtDf,gBACJgB,QAAQC,OACP,CAAIb,OAAOW,UAEF,CAACX,MAAMc,MAAMC,MAAMA,EAAExB,yBAAyBsB,EAAE,CAG1D,CAAC,CACDG,KAAKH,OAAOI,OAAOC,OAAO,CAAC,GAAGZ,UAAU;EAACa,MAAMhC,UAAU;GAAII,sBAAsBsB;CAAE,CAAC,CAAC,IAGrFd,kBACJa,QAAQQ,aACApB,QAAOW,UAAS,CAACX,MAAMc,MAAMC,MAAMA,EAAExB,yBAAyB6B,SAASP,EAAE,CACjF,CAAC,CACDG,KAAKI,aACJH,OAAOC,OAAO,CAAC,GAAGZ,UAAU;EAACa,MAAMhC,UAAU;GAAII,sBAAsB6B,SAASP;CAAE,CAAC,CACrF,GAEEQ,WAAWb,YAAY,GAGvBc,iBAAiBtB,OAAOW,SAASX,MAAMgB,KAAKD,MAAMA,CAAC,IAAI,CAAA;CA6B7D,OA3BmBM,SAASL,KAAKQ,SAAS;EAExC,IAAMC,eAAeD,KAAKjC,sBACpBmC,gBAAgB5B,UAAU6B,WAAWC,MAAMH,iBAAiBG,EAAEf,EAAE,GAGhEgB,qBAAqB/B,UAAUgC,MAAMJ,gBAAgB,CAAC,GAGtDK,oBAAoBT,eAAeK,WAAWC,MAClDC,mBAAmBf,MAAMkB,MAAMA,EAAEnB,OAAOe,EAAErC,oBAAoB,CAChE;EASA,OANIwC,oBAAoB,IACtBT,eAAeW,KAAKT,IAAI,IAExBF,eAAeY,OAAOH,mBAAmB,GAAGP,IAAI,GAG3CO,oBAAoB,IAEvB1C,OAAO,CAACmC,IAAI,GAAG,SAAS,CAAC,GAAGvB,MAAM8B,iBAAiB,CAAC,IAEpD1C,OAAO,CAACmC,IAAI,GAAG,UAAU,CAAC,GAAGvB,MAAM8B,iBAAiB,CAAC;CAC3D,CAEOR;AACT;ACrFA,MAAM6B,+BAM4BC,kBAAkB,EAACE,WAAWC,wBAC9DD,UAAUE,KAAKC,aAAa;CAE1B,IAAMC,QAAQhB,aAAaU,iBAAiBO,IAAI,GAC1C,EAACC,UAAUC,cAAalB,gBAAgB,GACxCmB,WACJC,EAAQF,WAAWG,aAClBN,SAASO,MAAMC,QAAQR,KAAK,IACzBK,EAAQL,OAAOS,MAAMC,SAASA,KAAAA,aAA8BX,SAASY,EAAE,IACvE,KACAC,SAAS,CAACf,kBAAkBgB,MAAMC,MAAMA,EAAEH,OAAOZ,SAASY,EAAE,GAE5DI,WAAWrC,kBAAkB;EACjC,IAAM,EAACsC,YAAYf,SAAQP,kBAGrBwB,UAAU1B,yBAAyB;GACvCyB,kBAFuBlB,SAASY,EAEhCM;GACAE,gBAAgBH,WAAWI;GAC3BxB;GACAC;GACAG;GACAC;EACF,CAAC;EAEDC,SAASpB,WAAWuC,KAAK,CAACtC,aAAa,CAAA,GAAIkB,IAAI,GAAG,GAAGiB,OAAO,CAAC,CAAC;CAChE,GAAG;EAACnB,SAASY;EAAIX;EAAOE;CAAQ,CAAC;CAEjC,OAAO;EACLoB,MAAM;EACNC,MAAM/C;EACNuC;EACAS,OAAOzB,SAASyB;EAChBZ;EACAR;CACF;AACF,CAAC,GAEGqB,qCAM0B/B,kBAAkB,EAACE,WAAWC,wBAAuB;CAEnF,IAAMG,QAAQhB,aAAaU,iBAAiBO,IAAI,GAC1C,EAACC,UAAUC,cAAalB,gBAAgB,GACxCmB,WACJC,EAAQF,WAAWG,YAAcN,SAASA,MAAM0B,WAAW7B,kBAAkB6B,QACzEd,SAAStB,4BAA4BO,mBAAmBG,KAAK,GAE7De,WAAWrC,kBAAkB;EACjC,IAAM,EAACsC,YAAYf,SAAQP,kBAGrBwB,UAAU1B,yBAAyB;GACvCyB,iBAAAA,CAAAA;GACAE,gBAAgBH,WAAWI;GAC3BxB;GACAC;GACAG;GACAC;EACF,CAAC;EAEDC,SAASpB,WAAWuC,KAAK,CAACtC,aAAa,CAAA,GAAIkB,IAAI,GAAG,GAAGiB,OAAO,CAAC,CAAC;CAChE,GAAG;EAACxB;EAAkBG;EAAmBD;EAAWM;EAAUF;CAAK,CAAC;CAEpE,OAAO;EACLsB,MAAM;EACNC,MAAM/C;EACNuC;EACAS,OAAOjC,kBAAkBS,OAAOH,iBAAiB;EACjDO;EACAQ;CACF;AACF,GAEae,oCAAoChD,0BAA0B;CACzEyC,MAAM;CACNQ,UAAUlC,kBAAkB;EAC1B,IAAMmC,gCACJnC,kBAAkBsB,YAAYM,MAAMF,KAAKU,WAAW,wBAAwB,GACxE,EAAClC,WAAWC,sBAAqBX,iCAAiC,GAElE6C,wBAAwBtC,4BAA4BC,kBAAkB;GAC1EE;GACAC;EACF,CAAC;EAED,OAAO;GACLyB,MAAM;GACNC,MAAM9C;GACN+C,OAAO;GACPQ,gBAAgB;GAChBC,UAAUJ,gCACN,CACE,GAAGE,uBACHN,kCAAkC/B,kBAAkB;IAClDE;IACAC;GACF,CAAC,CAAC,IAEJ,CAAA;GACJe,QAAQ,CAACiB;EACX;CACF;AACF,CAAC;;;;AC/HD,SAAgBO,WAAWC,QAAwB;CACjD,OAAOF,WAAWD,UAAUG,MAAM,CAAC;AACrC;;;;;;;;;;;;AAaA,SAAgBC,gBAAgBC,MAAcC,WAAW,IAAe;CACtE,OAAOA,WACH;EAAC;EAA0BJ,WAAWG,IAAI;EAAG;CAAO,CAAC,CAACE,KAAK,EAAE,IAC7D,CAAC,0BAA0BL,WAAWG,IAAI,CAAC,CAAC,CAACE,KAAK,EAAE;AAC1D;;;;;AChBA,MAAaO,wCACXC,eACAC,SACAC,qBACAC,aACAE,cACG;CACH,IAAIR,iCAAiCG,cAAcM,IAAI,GAAG;EACxD,IAAMC,WACJ,OAAOJ,aAAAA,YAAuC,WAC1CA,cAAcP,uBACd,OAAOO,aAAc,QAAY,WAC/BA,aAAc,OACd;EAQR,OANyBI,aAAWF,UAAUI,MAAMC,MAAMA,EAAEC,OAAOJ,QAAQ,IAMpEA,WAAWL,oBAAoBU,SAASL,QAAQ,IAAI,KAFlD;CAGX;CACA,OAAO;AACT,GC7BMW,gBAAgB,EACpBC,WAAW,CACT;CAACC,IAAI;CAAMC,OAAO;AAAS,GAC3B;CAACD,IAAI;CAAMC,OAAO;AAAO,CAAC,EAE9B;AAEA,SAAeC,WAAA;CAAA,IAAAC,IAAAC,EAAA,CAAA,GAAAC;CAAA,AAAAF,EAAA,OAAAG,OAAAC,IAAA,2BAAA,KAKgDF,KAAA,oBAAA,QAAA,EAAA,UAAM,yBAA6B,CAAA,GAAAF,EAAA,KAAAE,MAAAA,KAAAF,EAAA;CAAA,IAAAK;CAAA,AAAAL,EAAA,OAAAG,OAAAC,IAAA,2BAAA,KAC1DC,KAAA,oBAAA,QAAA,EAAA,UAAM,KAAS,CAAA,GAAAL,EAAA,KAAAK,MAAAA,KAAAL,EAAA;CAAA,IAAAM;CAAA,AAAAN,EAAA,OAAAG,OAAAC,IAAA,2BAAA,KAF/CE,KAAA,qBAAC,MAAD,EAAA,UAAA;EAAM;EACiDJ;EAAoC;EAAI;EAC/DG;EAAe;EAAK,oBAAA,QAAA,EAAA,UAAM,QAAY,CAAA;EAAA;CAFjE,EAAA,CAAA,GAGEL,EAAA,KAAAM,MAAAA,KAAAN,EAAA;CAAA,IAAAO;CAOJ,OAPIP,EAAA,OAAAG,OAAAC,IAAA,2BAAA,KALXG,KAAA,oBAAC,MAAD;EAAW,MAAA;EAAU,QAAA;EAAe,QAAA;EAAY,SAAA;EAC9C,UAAA,qBAAC,OAAD;GAAY,KAAA;GAAZ,UAAA,CACED,IAIA,oBAAC,MAAD;IAAe,SAAA;IAAG,QAAA;IAAe,QAAA;IAC/B,UAAA,oBAAC,MAAD;KAAY,MAAA;KAAY,UAAA;KACrBE,UAAAA,KAAIC,UAAWd,eAAe,MAAM,CAAC;IADnC,CAAA;GADF,CAAA,CALD;;CADH,CAAA,GAYEK,EAAA,KAAAO,MAAAA,KAAAP,EAAA,IAZPO;AAYO;;;;ACZX,SAAOa,gBAAAC,IAAA;CAAA,IAAAC,IAAAC,EAAA,EAAA,GAAyB,EAAAJ,0BAAAE;CAI9B,IAAI,CAACF,sBAAqBK,QAAO,OACxB;CACR,IAAAC;CAAA,AAAAH,EAAA,OAAAI,OAAAC,IAAA,2BAAA,KAKKF,KAAA,oBAAC,KAAD,EAAA,UACE,oBAAC,MAAD;EAAY,MAAA;EACV,UAAA,oBAAC,oBAAD,CAAmB,CAAA;CADhB,CAAA,EADH,CAAA,GAIEH,EAAA,KAAAG,MAAAA,KAAAH,EAAA;CAAA,IAAAM;CAAA,AAAAN,EAAA,OAAAI,OAAAC,IAAA,2BAAA,KAEJC,KAAA,oBAAC,MAAD;EAAY,MAAA;EAAU,QAAA;EAAW,UAAA;CAA5B,CAAA,GAEEN,EAAA,KAAAM,MAAAA,KAAAN,EAAA;CAGJ,IAAAO,KAAAV,sBAAqBK,WAAY,IAAjC,KAAA,KACAM,KAAAX,sBAAqBK,WAAY,IAAjC,UAAA,QAAqDO;CAAA,AAAAT,EAAA,OAAAH,sBAAAK,UAAAF,EAAA,OAAAO,MAAAP,EAAA,OAAAQ,MAHxDC,KAAA,qBAAC,MAAD;EAAY,MAAA;EAAG,OAAA;EAAf,UAAA;GACGZ,sBAAqBK;GAAQ;GAC7BK;GAA+C;GAC/CC;GAAsD;EAHpD;KAIER,EAAA,KAAAH,sBAAAK,QAAAF,EAAA,KAAAO,IAAAP,EAAA,KAAAQ,IAAAR,EAAA,KAAAS,MAAAA,KAAAT,EAAA;CAAA,IAAAU;CAAA,AAAAV,EAAA,OAAAI,OAAAC,IAAA,2BAAA,KAG6DK,KAAA,oBAAA,QAAA,EAAA,UAAM,OAAW,CAAA,GAAAV,EAAA,KAAAU,MAAAA,KAAAV,EAAA;CAAA,IAAAW;CAAA,AAAAX,EAAA,OAAAI,OAAAC,IAAA,2BAAA,KAC5BM,KAAA,oBAAA,QAAA,EAAA,UAAM,WAAe,CAAA,GAAAX,EAAA,KAAAW,MAAAA,KAAAX,EAAA;CAAA,IAAAY;CAAA,AAAAZ,EAAA,OAAAI,OAAAC,IAAA,2BAAA,KAH9EO,KAAA,oBAAC,KAAD;EAAgB,WAAA;EACd,UAAA,qBAAC,MAAD;GAAY,MAAA;GAAZ,UAAA;IAAe;IACmDF;IAAiB;IAC5BC;IAAqB;IAAE;IAC5E,oBAAA,KAAA;KACM,KAAA;KACG,QAAA;KACF,MAAA;KACN,UAAA;IAEG,CAAA;IAAA;GATD;;CADH,CAAA,GAaEX,EAAA,KAAAY,MAAAA,KAAAZ,EAAA;CAAA,IAAAa;CAGL,OAHKb,EAAA,OAAAS,KAGLI,KAAAb,EAAA,OAhCPa,KAAA,oBAAC,MAAD;EAAW,MAAA;EAAmB,SAAA;EAAW,QAAA;EAAG,QAAA;EAC1C,UAAA,qBAAC,MAAD;GAAW,KAAA;GAAS,OAAA;GAApB,UAAA,CACEV,IAKA,qBAAC,OAAD;IAAY,KAAA;IAAS,MAAA;IAArB,UAAA;KACEG;KAGAG;KAKAG;IATI;GANH,CAAA,CAAA;;CADF,CAAA,GAgCEZ,EAAA,KAAAS,IAAAT,EAAA,MAAAa,KAhCPA;AAgCO;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAX,SAAe8B,uBAAAC,OAAA;CAAA,IAAAC,IAAAC,EAAA,GAAA,GAGb,EAAAC,SAAAC,OAAAC,QAAAC,YAAAC,UAAAC,UAAAC,qBAAmFT,OAEnFI,QAAcC,QAAsCK;CAAA,AAAAT,EAAA,OAAAG,QAC6BM,KAAAT,EAAA,MAAnDS,KAAAN,OAAKO,OAASC,OAAoC,KAAlD,CAAA,GAAmDX,EAAA,KAAAG,OAAAH,EAAA,KAAAS;CAAjF,IAAAG,wBAA8BH,IAC9BI,qBAA2BD,sBAAqBE,SAAU,GAC1DP,WAAiBQ,EAAQP,oBAAqBH,WAAUE,aAAc,IACtES,QAAczC,SAAS,GAEvB0C,eAAqB/B,gBAAgB,GACrC,EAAAgC,WAAAC,mBAAAC,kBAAAC,cAAAC,iBAAAC,cAAAC,gBAAAC,0BAQI7B,iCAAiC,GAGrC,EAAA8B,qBAAAC,SAAAC,0BAA8D1D,+BAA+B,GAAC2D;CAAA,AAAA7B,EAAA,OAAA8B,OAAAC,IAAA,2BAAA,KAC5DF,KAAA,CAAC,OAAO,GAAC7B,EAAA,KAAA6B,MAAAA,KAAA7B,EAAA;CAA3C,IAAAgC,eAAqB/C,aAAa4C,EAAS,GAACI;CAAA,AAAAjC,EAAA,OAAAgC,gBAAAhC,EAAA,OAAA4B,yBAE1CK,KAAA,OAAOD,gBAAiB,YAAYJ,sBAAqBM,cAAcC,SAAUH,YAAY,GAAChC,EAAA,KAAAgC,cAAAhC,EAAA,KAAA4B,uBAAA5B,EAAA,KAAAiC,MAAAA,KAAAjC,EAAA;CADhG,IAAAoC,4BACEH,IAA8FI;CAAA,AAAArC,EAAA,OAAAyB,yBAAAzB,EAAA,OAAAgC,gBAE9FK,KAAA,OAAOL,gBAAiB,YAAYP,sBAAqBS,cAAcC,SAAUH,YAAY,GAAChC,EAAA,KAAAyB,uBAAAzB,EAAA,KAAAgC,cAAAhC,EAAA,KAAAqC,MAAAA,KAAArC,EAAA;CADhG,IAAAsC,6BACED,IAA8FE;CAAA,AAAAvC,EAAA,OAAA4B,yBAAA5B,EAAA,QAAAkB,aAAAlB,EAAA,QAAAE,WAAAF,EAAA,QAAA0B,uBAAA1B,EAAA,QAAAsC,8BAAAtC,EAAA,QAAAoC,6BAK5FG,KAAAH,6BAAAE,6BACIpC,QAAOQ,QAAQ8B,WAAA;EAGb,IAAIA,OAAMC,SAAU,QAAM,OACjB;EAIT,IAAAC,cAAoBF,OAAMG,KAAKzC,QAAQ;EAKtC,OAFG,CAACwC,eAAeA,YAAWD,SAAU,UAChC,KAKFH,6BACH7C,qCACE+C,OAAMG,KAAKtC,YACXqC,aACAhB,qBACAc,OAAMG,KAAKxC,OACXe,SAOF,IALAU,sBAAqBgB,YACnBJ,OAAMG,KAAKtC,YACXqC,aACAhB,qBACAc,OAAMG,KAAKxC,KACb;CAAC,CAED,IAjCVD,SAiCWF,EAAA,KAAA4B,uBAAA5B,EAAA,MAAAkB,WAAAlB,EAAA,MAAAE,SAAAF,EAAA,MAAA0B,qBAAA1B,EAAA,MAAAsC,4BAAAtC,EAAA,MAAAoC,2BAAApC,EAAA,MAAAuC,MAAAA,KAAAvC,EAAA;CAnCf,IAAA6C,kBAEIN,IA0CHO;CAAA,AAAA9C,EAAA,QAAAmB,qBAAAnB,EAAA,QAAAiB,gBAAAjB,EAAA,QAAAkB,aAAAlB,EAAA,QAAAM,YAAAN,EAAA,QAAAD,MAAAgD,QAAA/C,EAAA,QAAAK,cAGCyC,MAAAE,oBAAA;EAEE,IAAAC,YAAkBhC,aAAalB,MAAKgD,IAAK;EACzC,IAAI,CAAC5B,mBAAiBL,QAAQ;EAI9B,IAAAoC,UAAgB1D,yBAAyB;GAAAwD,iBACtBG,MAAKC,QAASJ,eAAqD,IAAnEA,kBAAA,CAAoDA,eAAe;GAACK,gBACrEhD,WAAUiD;GAAKpC;GAAAC;GAAAhB,OAGxB8C;EACT,CAAC;EAED3C,SAAS,CAACtB,aAAa,CAAA,CAAE,GAAC,GAAKkE,OAAO,CAAC;CAAC,GACzClD,EAAA,MAAAmB,mBAAAnB,EAAA,MAAAiB,cAAAjB,EAAA,MAAAkB,WAAAlB,EAAA,MAAAM,UAAAN,EAAA,MAAAD,MAAAgD,MAAA/C,EAAA,MAAAK,YAAAL,EAAA,MAAA8C,MAAAA,KAAA9C,EAAA;CAjBH,IAAAuD,qBAA2BT,IAqB3B,EAAAU,WAAAC,eAAgCtE,gBAAgB,GAACuE;CAAA,AAAA1D,EAAA,QAAA8B,OAAAC,IAAA,2BAAA,KAOL2B,KAAA,CAAC,MAAM,GAAC1D,EAAA,MAAA0D,MAAAA,KAAA1D,EAAA;CAApD,IAAA2D,iBAAuB5C,EAAQ9B,aAAayE,EAAQ,GAAEE;CAAA,AAAA5D,EAAA,QAAAG,QAM1CyD,KAAA5D,EAAA,OAHkB4D,KAAAzD,OAAK0D,IAC3BC,QACA,CAAC,CAAApD,OAACK,OACJ,CAAC,CAAAgD,KAAC,GAAG,GAAC/D,EAAA,MAAAG,OAAAH,EAAA,MAAA4D;CAHZ,IAAAI,wBAA8BJ,IAGlBK;CAAA,IAAAjE,EAAA,QAAAgE,yBAAAhE,EAAA,QAAAkB,WAAA;EAAAgD,KAAA;GAGV,IAAAC,eAAqBH,uBAAqBI,MAAQ,GAAS,KAAtC,CAAA;GACrB,IAAI,CAACD,cAAYrD,QAAQ;IAAA,IAAAuD;IAAEJ,AAAFjE,EAAA,QAAA8B,OAAAC,IAAA,2BAAA,KAASsC,KAAA,CAAA,GAAErE,EAAA,MAAAqE,MAAAA,KAAArE,EAAA,KAATiE,KAAOI;IAAP,MAAAH;GAAS;GACpC,IAAI,CAAChD,WAASJ,QAAQ;IAAA,IAAAuD;IAAEJ,AAAFjE,EAAA,QAAA8B,OAAAC,IAAA,2BAAA,KAASsC,KAAA,CAAA,GAAErE,EAAA,MAAAqE,MAAAA,KAAArE,EAAA,KAATiE,KAAOI;IAAP,MAAAH;GAAS;GAEjCD,KAAO/C,UAASR,QAAQ4D,MAAOH,cAAYI,MAAOC,QAASA,QAAQF,EAACG,EAAG,CAAC,CAAC,CAAAZ,IAAKa,QAAW;EAAC;EAAA1E,AAAAA,EAAA,MAAAgE,uBAAAhE,EAAA,MAAAkB,WAAAlB,EAAA,MAAAiE;CAAA,OAAAA,KAAAjE,EAAA;CAL5F,IAAA2E,iBAAuBV,IAMeW,KAAAP;CAEtC3F,AAFsCsB,EAAA,QAAA2E,kBAAA3E,EAAA,QAAAoB,oBAAApB,EAAA,QAAA2D,kBAAA3D,EAAA,QAAAuD,sBAAAvD,EAAA,QAAAwD,aAAAxD,EAAA,QAAAyD,cAAAzD,EAAA,QAAAkB,aAAAlB,EAAA,QAAAO,YAAAP,EAAA,QAAAa,sBAE5BwD,WAAA;EACR,IAAAQ,2BAAiCzD,iBAAgBV,QACvCoE,aAAc5D,UAASqD,MAAMQ,QAAOT,IAACG,OAAQK,QAAQ,CAAC,CAAC,CAAAE,OACxDC,eAAcN,eAAcxC,SAAU2C,UAAQ,CAAC;EAExD,IACEnB,kBAAA,CACCF,cADD,CAECD,aAFD,CAGCqB,4BAHD,CAIChE,oBAAkB;GAEnB,IAAAqE,iBAAuB9D,iBAAgBV,QAC7ByE,eAAc,CAACR,eAAcxC,SAAU2C,UAAQ,CAAC,CAAC,CAAApE,QACjD0E,eAAclE,UAASqD,MAAMc,QAAOf,IAACG,OAAQK,UAAQ,CAAC,GAEhEQ,UAAgBC,iBAAW;IACzB,AAAKhF,YAAUgD,mBAAmB2B,cAAc;GAAC,CAClD;GAAC,aACWM,aAAaF,OAAO;EAAC;CACnC,GAEAV,MAAA;EACDjB;EACAH;EACAC;EACAF;EACAnC;EACAuD;EACAzD;EACAX;EACAM;CAAkB,GACnBb,EAAA,MAAA2E,gBAAA3E,EAAA,MAAAoB,kBAAApB,EAAA,MAAA2D,gBAAA3D,EAAA,MAAAuD,oBAAAvD,EAAA,MAAAwD,WAAAxD,EAAA,MAAAyD,YAAAzD,EAAA,MAAAkB,WAAAlB,EAAA,MAAAO,UAAAP,EAAA,MAAAa,oBAAAb,EAAA,MAAA4E,KAAA5E,EAAA,MAAAqE,OAAAO,MAAA5E,EAAA,KAAAqE,KAAArE,EAAA,MAhCDtB,UAAU2F,IAsBPO,GAUF;CAAC,IAAAa;CAAA,AAAAzF,EAAA,QAAAkB,aAAAlB,EAAA,QAAAM,YAAAN,EAAA,QAAAgB,SAAAhB,EAAA,QAAAG,SAGqCsF,YAAA;EACrC,IAAI,CAACtF,OAAKW,UAAN,CAAmBI,WAASJ,QAAQ;EAMxC,IAAA4E,eAAqBvF,MAAKwF,QAChBC,KAAAC,QAAA;GACN,IAAAC,WAAiB5E,UAAS6E,WAAWC,QAAO1B,IAACG,OAAQwB,MAAI7G,oBAAoB;GAI5E,OAFG0G,WAAW,OACbF,IAAIE,YAAYG,MAGXL;EAAG,GACT,CAAA,CAAkC,CAAC,CAAAlF,OAC9BK,OAAO;EASjBT,AAPIH,OAAKW,WAAa4E,aAAY5E,UAChCE,MAAKkF,KAAM;GAAAC,OACF;GAAyCC,QACxC;EACV,CAAC,GAGH9F,SAASvB,IAAI2G,YAAY,CAAC;CAAC,GAC5B1F,EAAA,MAAAkB,WAAAlB,EAAA,MAAAM,UAAAN,EAAA,MAAAgB,OAAAhB,EAAA,MAAAG,OAAAH,EAAA,MAAAyF,OAAAA,MAAAzF,EAAA;CA3BD,IAAAqG,qBAA2BZ,KA2BYa;CAAAC,KAAA;EAGrC,IAAI,CAACpG,OAAKW,UAAN,CAAmBI,WAASJ,QAAQ;GACtCwF,MAAO;GAAP,MAAAC;EAAW;EACZ,IAAAC;EAEDF,AAFCtG,EAAA,QAAAkB,aAAAlB,EAAA,QAAAG,SAEMqG,MAAArG,OAAK6E,OAAQyB,QAAOvF,UAASqD,MAAMmC,QAAOpC,KAACG,OAASwB,MAAI7G,oBAAoB,CAAC,GAACY,EAAA,MAAAkB,WAAAlB,EAAA,MAAAG,OAAAH,EAAA,MAAAwG,OAAAA,MAAAxG,EAAA,KAArFsG,MAAOE;CAA8E;CALvF,IAAAG,sBAA4BL,KAMNE;CAAAI,KAAA;EAGpB,IAAI,CAACzG,OAAKW,UAAN,CAAmB6D,eAAc7D,QAAO;GAAA,IAAA+F;GAC1CL,AAD0CxG,EAAA,QAAA8B,OAAAC,IAAA,2BAAA,KACnC8E,MAAA,CAAA,GAAE7G,EAAA,MAAA6G,OAAAA,MAAA7G,EAAA,KAATwG,MAAOK;GAAP,MAAAD;EAAS;EACV,IAAAC;EAAA,IAAA7G,EAAA,QAAA2E,kBAAA3E,EAAA,QAAAG,OAAA;GAAA,IAAA2G;GAQiB9G,AARjBA,EAAA,QAAA2E,iBAMQmC,MAAA9G,EAAA,OAHF8G,OAAAC,KAAAC,WACHA,WAAWrC,eAAcoB,WAAWkB,eAAcnC,eAAamB,IAAAA,QAAsB,IAArF,OAAAc,KAEK/G,EAAA,MAAA2E,gBAAA3E,EAAA,MAAA8G,MAJFD,MAAA1G,MAAK0D,IACLiD,GAIL,CAAC,CAAApG,OACOK,OAAO,GAACf,EAAA,MAAA2E,gBAAA3E,EAAA,MAAAG,OAAAH,EAAA,MAAA6G;EAAA,OAAAA,MAAA7G,EAAA;EANlBwG,MAAOK;CAMW;CAXpB,IAAAK,sBAA4BV,KAc5BW,oBAEI,CAACjG,WAASJ,UAAaI,WAASJ,UAAYI,UAAS8D,MAAOoC,QAA+B,GAE9FP,KAAAC;CAGDpI,AAHCsB,EAAA,QAAA2G,uBAAA3G,EAAA,QAAAqG,sBAAArG,EAAA,QAAAkH,uBAAAlH,EAAA,QAAAO,YAAAP,EAAA,QAAAuB,gBAGSsF,YAAA;EACR,AAAItF,gBAAgB2F,oBAAmBpG,SAAU,KAA7C6F,uBAAA,CAA0EpG,YAC5E8F,mBAAmB;CACpB,GACAS,MAAA;EAACvF;EAAc2F;EAAqBP;EAAqBN;EAAoB9F;CAAQ,GAACP,EAAA,MAAA2G,qBAAA3G,EAAA,MAAAqG,oBAAArG,EAAA,MAAAkH,qBAAAlH,EAAA,MAAAO,UAAAP,EAAA,MAAAuB,cAAAvB,EAAA,MAAA6G,KAAA7G,EAAA,MAAA8G,QAAAD,MAAA7G,EAAA,KAAA8G,MAAA9G,EAAA,MAJzFtB,UAAUmI,KAIPC,GAAsF;CAAC,IAAAO;CAAA,AAAArH,EAAA,QAAAmB,qBAAAnB,EAAA,QAAAG,SAIlFkH,MAAA/H,4BAA4B6B,mBAAmBhB,KAAK,GAACH,EAAA,MAAAmB,mBAAAnB,EAAA,MAAAG,OAAAH,EAAA,MAAAqH,OAAAA,MAAArH,EAAA;CAD7D,IAAAsH,yBACQD,KAEPE;CAAA,AAAAvH,EAAA,QAAAmB,qBAAAnB,EAAA,QAAAuD,sBAC0CgE,YAAA;EACzChE,mBAAmBpC,kBAAiB0C,IAAK2D,MAAyB,CAAC;CAAC,GACrExH,EAAA,MAAAmB,mBAAAnB,EAAA,MAAAuD,oBAAAvD,EAAA,MAAAuH,OAAAA,MAAAvH,EAAA;CAFD,IAAAyH,yBAA+BF;CAI/B,IAAI,CAACJ,mBAAiB;EAAA,IAAAO;EACD,OADC1H,EAAA,QAAA8B,OAAAC,IAAA,2BAAA,KACb2F,MAAA,oBAAC,UAAD,CAAS,CAAA,GAAG1H,EAAA,MAAA0H,OAAAA,MAAA1H,EAAA,KAAZ0H;CAAY;CACpB,IAAAA;CAAA,AAAA1H,EAAA,QAAAsH,0BAAAtH,EAAA,QAAAsB,mBAAAtB,EAAA,QAAAmB,kBAAAL,UAAAd,EAAA,QAAAa,sBAGC6G,MAAA,CAAC7G,sBAEDS,gBAAea,SAAU,OAAO,KAEhChB,mBAAiBL,SAAW,KAJ5B,CAMCwG,wBAAsBtH,EAAA,MAAAsH,wBAAAtH,EAAA,MAAAsB,iBAAAtB,EAAA,MAAAmB,kBAAAL,QAAAd,EAAA,MAAAa,oBAAAb,EAAA,MAAA0H,OAAAA,MAAA1H,EAAA;CAPzB,IAAA2H,uBACED,KAOFE,kBAAwB1H,SAAOY,SAAW,GAAC+G;CAAA,AAAA7H,EAAA,QAAAmB,qBAAAnB,EAAA,QAAAG,SACvB0H,MAAAtI,kBAAkBY,OAAOgB,iBAAiB,GAACnB,EAAA,MAAAmB,mBAAAnB,EAAA,MAAAG,OAAAH,EAAA,MAAA6H,OAAAA,MAAA7H,EAAA;CAA/D,IAAA8H,cAAoBD,KAA2CE;CAAA,IAAA/H,EAAA,QAAA6C,mBAAA7C,EAAA,QAAAD,OAAA;EAAA,IAAAiI;EASzDhI,AATyDA,EAAA,QAAAD,QAS1DiI,MAAAhI,EAAA,OALoBgI,OAAAC,aACfzF,SAAMC,SAAU,SACX,8BAAC,oBAAD;GAAmB,GAAK1C;GAAY,KAAAyC,SAAMgC;GAAchC,QAAAA;EAAM,CAAA,IAEhE,oBAAC,iBAAD,EAA0CA,QAAAA,SAAM,GAA1BA,SAAMgC,GAAoB,GACxDxE,EAAA,MAAAD,OAAAC,EAAA,MAAAgI,MALAD,MAAAlF,gBAAegB,IAAKmE,GAKpB,GAAChI,EAAA,MAAA6C,iBAAA7C,EAAA,MAAAD,OAAAC,EAAA,MAAA+H;CAAA,OAAAA,MAAA/H,EAAA;CAAA,IAAAgI;CAAA,AAAAhI,EAAA,QAAAY,wBAC+DoH,MAAAhI,EAAA,OAAjEgI,MAAA,oBAAC,iBAAD,EAAwCpH,sBAAqB,CAAA,GAAIZ,EAAA,MAAAY,uBAAAZ,EAAA,MAAAgI;CAAA,IAAAE;CAAA,AAAAlI,EAAA,QAAA2H,wBAAA3H,EAAA,QAAA4H,mBAGhEM,MAAA,CAACP,wBAAD,CAA0BC,kBACzB,oBAAC,MAAD;EAAM,QAAA;EAAY,MAAA;EAAuB,SAAA;EAAW,QAAA;EAClD,UAAA,oBAAC,MAAD;GAAY,MAAA;GAAG,UAAA;EAAV,CAAA;CADF,CAAA,IADN,MAIO5H,EAAA,MAAA2H,sBAAA3H,EAAA,MAAA4H,iBAAA5H,EAAA,MAAAkI,OAAAA,MAAAlI,EAAA;CAAA,IAAAmI;CAAA,AAAAnI,EAAA,QAAAyH,0BAAAzH,EAAA,QAAA8H,eAAA9H,EAAA,QAAA2H,wBAAA3H,EAAA,QAAA2E,kBAAA3E,EAAA,QAAAsH,0BAAAtH,EAAA,QAAAqB,gBAAArB,EAAA,QAAAuD,sBAAAvD,EAAA,QAAAO,YAEP4H,MAAAR,uBACC,qBAAC,OAAD;EAAY,KAAA;EAAZ,UAAA,CACE,oBAAC,YAAD;GACkBhD,gBAAAA;GACNpE;GACGgD,aAAAA;EAAkB,CAAA,GAEhClC,eACC,oBAAC,QAAD;GACO,MAAA;GACA,MAAA;GACO,eAAA;GACF,UAAAd,YAAA+G;GACJrJ,MAAAA;GACA6J,MAAAA;GACGL,SAAAA;EAAsB,CAAA,IARlC,IANG;CADP,CAAA,IAAA,MAmBOzH,EAAA,MAAAyH,wBAAAzH,EAAA,MAAA8H,aAAA9H,EAAA,MAAA2H,sBAAA3H,EAAA,MAAA2E,gBAAA3E,EAAA,MAAAsH,wBAAAtH,EAAA,MAAAqB,cAAArB,EAAA,MAAAuD,oBAAAvD,EAAA,MAAAO,UAAAP,EAAA,MAAAmI,OAAAA,MAAAnI,EAAA;CAAA,IAAAoI;CACF,OADEpI,EAAA,QAAA+H,OAAA/H,EAAA,QAAAgI,OAAAhI,EAAA,QAAAkI,OAAAlI,EAAA,SAAAmI,OAnCVC,MAAA,qBAAC,OAAD;EAAY,KAAA;EAAZ,UAAA;GACGL;GAMDC;GAGCE;GAMAC;EAhBG;KAoCEnI,EAAA,MAAA+H,KAAA/H,EAAA,MAAAgI,KAAAhI,EAAA,MAAAkI,KAAAlI,EAAA,OAAAmI,KAAAnI,EAAA,OAAAoI,OAAAA,MAAApI,EAAA,MApCRoI;AAoCQ;AAzRG,SAAAZ,OAAAa,YAAA;CAAA,OAkO4CvD,WAAQL;AAAG;AAlOvD,SAAA2C,SAAAzE,MAAA;CAAA,OAiN6DA,KAAI8B,MAAO9B,KAAIwD;AAAM;AAjNlF,SAAAzB,SAAA4D,KAAA;CAAA,OAsH0EhE,IAACG;AAAG;AAtH9E,SAAAX,SAAAyE,KAAA;CAAA,OA6GEtC,IAAAA,YAA0BA,IAACuC;AAAK;AA7GlC,SAAA7H,QAAAsF,GAAA;CAAA,OAMsC,CAACA,EAAE7G;AAAoB;ACxD5E,SAAgBuJ,wBACdC,YAC4C;CAS5C,OARKA,aAIoBA,WAAWG,SAA+BC,aAI5DL,wBAAwBC,WAAWK,IAAI,IAP5C;AAQJ;ACIA,IAAA,iBAAgByB,WAA+B;CAC7C,IAAM,EAACR,YAAYC,QAAQE,WAAWE,SAAQG,QACxCC,WAAW,OAAOJ,QAAS,WAAWA,OAAOA,KAAKK,MAClDC,YAAYpB,gBAAgBkB,QAAQ,GACpCG,aAAarB,gBAAgBkB,UAAU,EAAI;CAEjD,OAAOzB,YAAY;EACjB0B,MAAMC;EACNE,OAAO;EACPR,MAAM;EACNS,YAAY;GACVC,QAAQC,UACNA,MAAMC,cAAc;IAClB,GAAGD;IAEHE,OAAO;GACT,CAAC;GACHC,OAAO1B;EACT;EACA2B,SAAS;GAEPpB;GACAC;GACAE;EACF;EACAkB,IAAI,CACFrC,YAAY;GACV,GAAI,OAAOqB,QAAS,WAAW,CAAC,IAAIA;GACpCK,MAAME;GACNP,MAAMO;EACR,CAAC,CAAC;EAGJU,aAAaC,SACXA,KAAKC,OAAqC,OAAOC,OAAOC,YAAY;GAClE,IAAI,CAACD,SAASA,MAAME,WAAW,GAC7B,OAAO;GAIT,IAAMC,uBAAuBH,MAAMI,QAChCC,SAASA,QAAQ,CAACA,KAAAA,YAA6BA,KAAKC,IACvD;GACA,IAAIH,qBAAqBD,SAAS,GAChC,OAAO;IACLK,SACE;IACFC,OAAOL,qBAAqBM,SAASJ,SAAS,CAC5C,CAAC,EAACC,MAAMD,KAAKC,KAAI,CAAC,GAClB,CAAC,EAACA,MAAMD,KAAKC,KAAI,GAAG,OAAO,CAAC,CAC7B;GACH;GAIF,IAAIN,MAAME,WAAW,KAAK,CAACF,MAAM,EAAE,EAAA,UACjC,OAAO;GAGT,IAAMU,gBAAgB3C,iBAAiBS,QAAQyB,QAAQU,QAAQ,GACzDC,SAASX,QAAQY,UAAU,EAACtC,WAAU,CAAC,GAEzCuC,mBAA+B,CAAA,GAC7BC,uBAAuB1C,wBAAwB4B,SAASrB,IAAI;GAElE,IAAIoC,MAAMC,QAAQF,oBAAoB,GACpCD,mBAAmBC;QACd,IAAIC,MAAMC,QAAQrD,KAAK8C,aAAa,CAAC,GAC1CI,mBAAmBlD,KAAK8C,aAAa,KAAK,CAAA;QACrC,IAAI,OAAOK,wBAAyB,YAAY;IAErD,IAAMG,kBAAkBvD,iBAAiBoD,sBAAsBL,aAAa;IAE5E,IAAIM,MAAMC,QAAQC,eAAe,GAC/BJ,mBAAmBI;SACd;KAEL,IAAMC,yBAAyBvD,KAAK8C,aAAa;KACjD,AAAIM,MAAMC,QAAQE,sBAAsB,IACtCL,mBAAmBK,0BAGnBL,mBAAmB,MAAMC,qBAAqBH,QAAQF,aAAa,GAEnE7C,iBAAiBkD,sBAAsBL,eAAeI,gBAAgB;IAE1E;GACF;GAEA,IAAId,SAASA,MAAME,SAASY,iBAAiBZ,QAC3C,OAAO,uBACLY,iBAAiBZ,WAAW,IAAI,WAAW,GAAGY,iBAAiBZ,OAAM;GAKzE,IAAMkB,cAAc,IAAIC,IAAIP,iBAAiBQ,KAAKC,SAASA,KAAKC,EAAE,CAAC,GAG7DC,kBAAkBzB,MAAMI,QAC3BC,SAASA,MAAAA,YAA+B,CAACe,YAAYM,IAAIrB,KAAAA,QAAyB,CACrF;GACA,IAAIoB,gBAAgBvB,QAClB,OAAO;IACLK,SAAS;IACTC,OAAOiB,gBAAgBH,KAAKjB,SAAS,CAAC,EAACC,MAAMD,KAAKC,KAAI,CAAC,CAAC;GAC1D;GAIF,IAAMqB,gCAAgB,IAAIN,IAAY,GAChCO,kBAAgD,CAAA;GAEtD,KAAK,IAAMvB,QAAQL,OACjB,AAAIK,MAAAA,aACEsB,cAAcD,IAAIrB,KAAAA,QAAyB,IAC7CuB,gBAAgBC,KAAKxB,IAAI,IAEzBsB,cAAcG,IAAIzB,KAAKpC,oBAAoB;GAYjD,OAPA,CAAI2D,gBAAgB1B,UACX;IACLK,SAAS;IACTC,OAAOoB,gBAAgBN,KAAKjB,SAAS,CAAC,EAACC,MAAMD,KAAKC,KAAI,CAAC,CAAC;GAC1D;EAIJ,CAAC;CACL,CAAC;AACH;;;;;;;;;;;AC5IA,SAAgB2B,sBAAsBC,aAAyD;CAC7F,IAAI,CAACA,aAAaC,QAChB;CAGF,IAAME,mBAAmB,IAAIC,IAAIJ,YAAYK,KAAKC,MAAMA,EAAEC,KAAK,CAAC;CAEhE,IAAIJ,iBAAiBK,IAAI,OAAO,GAC9B,OAAO;CACF,IAAIL,iBAAiBK,IAAI,SAAS,GACvC,OAAO;AAIX;ACZA,SAAA6B,qBAAAC,OAAA;CAAA,IAAAC,IAAAC,EAAA,EAAA,GAKE,EAAAC,OAAAC,UAAAC,SAAgCL,OAAKM;CAAA,AAAAL,EAAA,OAAAI,OAEaC,KAAAL,EAAA,MAAjBK,KAAAD,KAAIE,MAAO,GAAG,EAAE,GAACN,EAAA,KAAAI,MAAAJ,EAAA,KAAAK;CAAlD,IAAAE,cAAoBjB,aAAae,EAAiB,GAClD,EAAAG,cAAoBX,iCAAiC,GAACY;CAAA,AAAAT,EAAA,OAAAO,cAGOE,KAAAT,EAAA,MAArDS,KAAAF,aAAWG,IAAMC,KAAmC,KAApD,CAAA,GAAqDX,EAAA,KAAAO,aAAAP,EAAA,KAAAS;CAD7D,IAAAG,oBACQH,IAEPI;CAAA,AAAAb,EAAA,OAAAQ,aAAAR,EAAA,OAAAG,YAAAH,EAAA,OAAAE,SAGuBW,MAAAC,UAAA;EACtB,IAAAC,aAAmBD,OAAKE,eAAsBd;EAE1C,CAACA,SAAD,CAAWM,WAASS,UAApB,CAAiCT,UAASU,MAAMC,MAAOA,EAACC,OAAQL,UAAU,KAI9EZ,SAAS,CAACZ,IAAIwB,YAAY,CAACtB,mBAAmB,CAAC,CAAC,CAAC;CAAC,GACnDO,EAAA,KAAAQ,WAAAR,EAAA,KAAAG,UAAAH,EAAA,KAAAE,OAAAF,EAAA,KAAAa,MAAAA,KAAAb,EAAA;CARD,IAAAqB,kBAAwBR,IAYeS,KAAA,WAAWpB,MAAMT,qBAAoB,IAAG8B;CAAA,AAAAvB,EAAA,OAAAsB,KAAIC,KAAAvB,EAAA,MAAvEuB,KAAA,oBAAC,QAAD;EAAkB,UAAA;EAAS,MAAAD;CAAwC,CAAA,GAAItB,EAAA,KAAAsB,IAAAtB,EAAA,KAAAuB;CAC3E,IAAAC,KAAA,GAAGtB,MAAMT,qBAAoB,cAAagC;CAAA,IAAAzB,EAAA,QAAAqB,mBAAArB,EAAA,QAAAY,qBAAAZ,EAAA,QAAAQ,WAAA;EAAA,IAAAkB;EAYxC1B,AAZwCA,EAAA,QAAAqB,mBAAArB,EAAA,QAAAY,qBAG3Bc,MAAAC,SACb,oBAAC,UAAD;GACY,UAAAf,kBAAiBgB,SAAUD,KAAIP,EAAG;GAClC,UAAA;GAEJ,MAAAO,KAAIP,GAAGS,kBAAmB;GACzB,OAAAF,KAAIP;GACFC,SAAAA;EAAe,GAHnBM,KAAIP,EAGe,GAE3BpB,EAAA,MAAAqB,iBAAArB,EAAA,MAAAY,mBAAAZ,EAAA,MAAA0B,MAAAA,KAAA1B,EAAA,KATAyB,KAAAjB,UAASE,IAAKgB,EASd,GAAC1B,EAAA,MAAAqB,iBAAArB,EAAA,MAAAY,mBAAAZ,EAAA,MAAAQ,WAAAR,EAAA,MAAAyB;CAAA,OAAAA,KAAAzB,EAAA;CAAA,IAAA0B;CAAA,AAAA1B,EAAA,QAAAyB,KACGC,KAAA1B,EAAA,OAXP0B,KAAA,oBAAC,MAAD,EAAA,UACGD,GADE,CAAA,GAWEzB,EAAA,MAAAyB,IAAAzB,EAAA,MAAA0B;CAAA,IAAAI;CAAA,AAAA9B,EAAA,QAAA+B,OAAAC,IAAA,2BAAA,KAEAF,KAAA,EAAAG,QAAS,GAAI,GAACjC,EAAA,MAAA8B,MAAAA,KAAA9B,EAAA;CAAA,IAAAkC;CACvB,OADuBlC,EAAA,QAAAuB,MAAAvB,EAAA,QAAAwB,MAAAxB,EAAA,QAAA0B,MAjBzBQ,KAAA,oBAAC,YAAD;EACU,QAAAX;EACJ,IAAAC;EAEF,MAAAE;EAaO,SAAAI;CAAc,CAAA,GACvB9B,EAAA,MAAAuB,IAAAvB,EAAA,MAAAwB,IAAAxB,EAAA,MAAA0B,IAAA1B,EAAA,MAAAkC,MAAAA,KAAAlC,EAAA,KAlBFkC;AAkBE;AA7CN,SAAAvB,MAAAwB,GAAA;CAAA,OAWkCA,EAAE1C;AAAoB;AAsCxD,SAAA2C,aAAA/B,IAAA;CAAA,IAAAL,IAAAC,EAAA,EAAA,GAAsB,EAAAoC,WAAAC,UAAAnC,aAAAE,IAQrBI;CAAA,AAAAT,EAAA,OAAAG,WAIEM,KAAAT,EAAA,MAFmBS,WAAA;EAClBN,SAASX,MAAM,CAAC;CAAC,GAClBQ,EAAA,KAAAG,UAAAH,EAAA,KAAAS;CAFD,IAAA8B,cAAoB9B,IAONI,KAAA,CAACwB,WAASf,IAAAC;CAAA,AAAAvB,EAAA,OAAA+B,OAAAC,IAAA,2BAAA,KAElBV,KAAA,oBAAC,MAAD;EAAM,OAAA;EAAY,MAAA;EAAG,UAAA;CAAhB,CAAA,GAIaC,KAAA,CAAC,SAAS,MAAM,GAACvB,EAAA,KAAAsB,IAAAtB,EAAA,KAAAuB,OAAAD,KAAAtB,EAAA,IAAAuB,KAAAvB,EAAA;CAAA,IAAAwB;CAAA,AAAAxB,EAAA,OAAA+B,OAAAC,IAAA,2BAAA,KAIxBR,KAAA,EAAAgB,eAAgB,MAAK,GAACxC,EAAA,KAAAwB,MAAAA,KAAAxB,EAAA;CAKrB,IAAAyB,KAAAa,YAAAD,WAAqBX;CAAA,AAAA1B,EAAA,OAAAuC,eAAAvC,EAAA,OAAAyB,MALnCC,KAAA,oBAAA,QAAA;EAAa,OAAAF;EACX,UAAA,oBAAC,QAAD;GACO,MAAA;GACCtD,MAAAA;GACD,MAAA;GACK,UAAAuD;GACDc,SAAAA;EAAW,CAAA;CAEjB,CAAA,GAAAvC,EAAA,KAAAuC,aAAAvC,EAAA,KAAAyB,IAAAzB,EAAA,KAAA0B,MAAAA,KAAA1B,EAAA;CAAA,IAAA8B;CACC,OADD9B,EAAA,OAAAa,MAAAb,EAAA,OAAA0B,MApBTI,KAAA,oBAAC,SAAD;EACE,SAAA;EACU,UAAAjB;EAER,SAAAS;EAIkB,oBAAAC;EACV,WAAA;EACV,QAAA;EAEAG,UAAAA;CAZM,CAAA,GAqBE1B,EAAA,KAAAa,IAAAb,EAAA,KAAA0B,IAAA1B,EAAA,MAAA8B,MAAAA,KAAA9B,EAAA,KArBV8B;AAqBU;;;;;;;;;;;;;;;;AAmBd,SAAeW,uBAAA1C,OAAA;CAAA,IAAAC,IAAAC,EAAA,EAAA,GAIbyC,mBAAyB3C,MAAK4C,WAAWxC,UAASE;CA2E7BN,AA3E6BC,EAAA,OAAA0C,oBAAA1C,EAAA,OAAAD,MAAAG,OAAAA,SAIhDG,MAAAuC,YAAA;EAGE,IAAI,CAACC,MAAKC,QAASF,OAAO,GAAC,OAElBF,iBAAiBE,OAAiD;EAI3E,IAAAI,aAAmBjD,MAAKG,OAAaA;EAMrC,KAJE8C,cACe,QACdH,MAAKC,QAASE,UAAqC,KAAtBA,WAAU/B,WAAY,MAIvB2B,QAAOQ,KAAMC,MAoBtCF,GAAoB;GAEtB,IAAAG,YACEN,eAAeE,KAAAA,IAAf;IAAAK,MAAkC;IAAcnD,MAAQ,CAAC,OAAO;IAACF,OAAS,CAAA;GAAS,IAAnF,MAGFsD,eAAqBZ,QAAOlC,IAC1B+C,MAcF,GAGAC,aAAmBJ,YAAA,CAAaA,WAAS,GAAKE,YAAY,IAAvCA;GAAuD,OAGnEd,iBAAiBgB,UAAoD;EAAC;EAEhF,OAGMhB,iBAAiBE,OAAiD;CAAC,GAC3E5C,EAAA,KAAA0C,kBAAA1C,EAAA,KAAAD,MAAAG,OAAAA,OAAAF,EAAA,KAAAK,MAAAA,KAAAL,EAAA,IACkBD,MAAKG,OAAaA;CAxEvC,IAAAyD,kBAAwBtD,IA4ExB,EAAAG,WAAAoD,iBAAAC,qBAAuDhE,iCAAiC,GAACY;CAAA,AAAAT,EAAA,OAAAQ,aAAAR,EAAA,OAAAD,MAAAG,SAEtEO,KAAAD,WAASS,SACxB6C,EAAQtD,UAASU,MAAMC,MAAOA,EAACC,OAAQrB,MAAKG,MAAOT,oBAAoB,IADxD,IAEVO,EAAA,KAAAQ,WAAAR,EAAA,KAAAD,MAAAG,OAAAF,EAAA,KAAAS,MAAAA,KAAAT,EAAA;CAFT,IAAA+D,aAAmBtD,IAEVI;CAAA,IAAAb,EAAA,OAAA+D,cAAA/D,EAAA,OAAA4D,mBAAA5D,EAAA,OAAAQ,aAAAR,EAAA,OAAAD,MAAAG,OAAA;EAET,IAAA8D,WAAiBxD,WAASU,MAAO+C,QAAO9C,IAACC,OAAQrB,MAAKG,MAAOT,oBAAoB;EAEeO,AAA9Fa,KAAAkD,cAAAC,WAAyBrE,mBAAmBiE,iBAAiBI,SAAQE,OAAQF,SAAQ5C,EAAQ,IAA7F,IAA8FpB,EAAA,KAAA+D,YAAA/D,EAAA,KAAA4D,iBAAA5D,EAAA,KAAAQ,WAAAR,EAAA,KAAAD,MAAAG,OAAAF,EAAA,MAAAa;CAAA,OAAAA,KAAAb,EAAA;CADhG,IAAAmE,gBACEtD,IAIKS,KAAAvB,MAAK4C,YAAWpB;CAAA,IAAAvB,EAAA,QAAA+D,cAAA/D,EAAA,QAAAmE,iBAAAnE,EAAA,QAAA0C,oBAAA1C,EAAA,QAAAD,MAAA4C,WAAAyB,WAAApE,EAAA,QAAAD,MAAAK,QAAAJ,EAAA,QAAAD,MAAAG,OAAA;EAAA,IAAAsB;EA6BfxB,AA7BeA,EAAA,QAAA+D,cAAA/D,EAAA,QAAAmE,iBAAAnE,EAAA,QAAA0C,oBAAA1C,EAAA,QAAAD,MAAAK,QAAAJ,EAAA,QAAAD,MAAAG,SAGZsB,MAAA6C,WAAA;GACH,IAAIA,OAAMC,SAAU,SAAO,OAClBD;GAGT,IAAAE,QAAcF,OAAME,OACpBC,aAAmBD,OAAKC,YAGxBN,QAF4BnE,MAAKG,MAAAA,WAES6D,aACxC,oBAAC,OAAD;IAAO,OAAA;IAAY,MAAA;IAChBI,UAAAA;GADG,CAAA,IAIN,oBAAC,sBAAD;IACS,OAAApE,MAAKG;IACN,MAAAH,MAAKK;IACDsC,UAAAA;GAAgB,CAAA,IARhB;GAUb,OAEMgC,OAAMC,OAAQ,CAAC,GAAGN,QAAQ,EAAAE,OACxBG,OAAMC,OAAQ,CAAC,GAAGJ,OAAO,EAAAC,YAClBE,OAAMC,OAAQ,CAAC,GAAGH,YAAY,EAAAN,MAAM,CAAC,EACnD,CAAC,EACH,CAAC;EAAC,GACHlE,EAAA,MAAA+D,YAAA/D,EAAA,MAAAmE,eAAAnE,EAAA,MAAA0C,kBAAA1C,EAAA,MAAAD,MAAAK,MAAAJ,EAAA,MAAAD,MAAAG,OAAAF,EAAA,MAAAwB,MAAAA,KAAAxB,EAAA,KA5BMuB,KAAAxB,MAAK4C,WAAWyB,QAAQQ,OACvBC,MAA+C,CAAC,CAAAnE,IACnDc,EA0BJ,GAACxB,EAAA,MAAA+D,YAAA/D,EAAA,MAAAmE,eAAAnE,EAAA,MAAA0C,kBAAA1C,EAAA,MAAAD,MAAA4C,WAAAyB,SAAApE,EAAA,MAAAD,MAAAK,MAAAJ,EAAA,MAAAD,MAAAG,OAAAF,EAAA,MAAAuB;CAAA,OAAAA,KAAAvB,EAAA;CAAA,IAAAwB;CAAA,AAAAxB,EAAA,QAAAD,MAAA4C,cAAA3C,EAAA,QAAAD,MAAAG,SAAAF,EAAA,QAAAuB,MAAAvB,EAAA,QAAA2D,mBA9BCnC,KAAA;EAAA,GACFF;EAAgB8C,SACV7C;EA4BLrB,OACGH,MAAKG;EAAMC,UAERwD;CACZ,GAAC3D,EAAA,MAAAD,MAAA4C,YAAA3C,EAAA,MAAAD,MAAAG,OAAAF,EAAA,MAAAuB,IAAAvB,EAAA,MAAA2D,iBAAA3D,EAAA,MAAAwB,MAAAA,KAAAxB,EAAA;CAnCH,IAAA8E,cACStD,IA8CT,EAAAuD,YAAA7E,OAAAoC,aAAsCwC;CAEtC,IAAI,CAACtE,WAAS;EAAA,IAAAiB;EACM,OADNzB,EAAA,QAAA+B,OAAAC,IAAA,2BAAA,KACLP,KAAA,oBAAC,SAAD,CAAQ,CAAA,GAAGzB,EAAA,MAAAyB,MAAAA,KAAAzB,EAAA,KAAXyB;CAAW;CACnB,IAAAA;CAAA,AAAAzB,EAAA,QAAA6D,oBAAA7D,EAAA,QAAAE,SAEiBuB,KAAAoC,iBAAgBjC,SAAU1B,MAAMT,oBAAoB,GAACO,EAAA,MAAA6D,kBAAA7D,EAAA,MAAAE,OAAAF,EAAA,MAAAyB,MAAAA,KAAAzB,EAAA;CAAvE,IAAAqC,YAAkBZ,IAAqDC;CAAA,AAAA1B,EAAA,QAAA+E,aAGTrD,KAAA1B,EAAA,OAAjC0B,KAAA9B,sBAAsBmF,UAAU,GAAC/E,EAAA,MAAA+E,YAAA/E,EAAA,MAAA0B;CAAA,IAAAI;CAAA,AAAA9B,EAAA,QAAA8E,eAAA9E,EAAA,QAAAD,MAAA4C,cAEzCb,KAAA/B,MAAK4C,WAAWqC,YAAaF,WAAW,GAAC9E,EAAA,MAAA8E,aAAA9E,EAAA,MAAAD,MAAA4C,YAAA3C,EAAA,MAAA8B,MAAAA,KAAA9B,EAAA;CAAA,IAAAkC;CAAA,AAAAlC,EAAA,QAAA8B,KAAOI,KAAAlC,EAAA,OAA/DkC,KAAA,oBAAC,KAAD;EAAW,MAAA;EAAIJ,UAAAA;CAAX,CAAA,GAA2D9B,EAAA,MAAA8B,IAAA9B,EAAA,MAAAkC;CAGnD,IAAA+C,MAAAnB,EAAQxB,UAAS4C;CAAA,AAAAlF,EAAA,QAAAqC,aAAArC,EAAA,QAAA0C,oBAAA1C,EAAA,QAAAiF,OAF7BC,MAAA,oBAAC,cAAD;EACa7C;EACD,UAAA4C;EACAvC,UAAAA;CAAgB,CAAA,GAC1B1C,EAAA,MAAAqC,WAAArC,EAAA,MAAA0C,kBAAA1C,EAAA,MAAAiF,KAAAjF,EAAA,MAAAkF,OAAAA,MAAAlF,EAAA;CAAA,IAAAmF;CAAA,AAAAnF,EAAA,QAAAkF,OAAAlF,EAAA,QAAAkC,MANJiD,MAAA,qBAAC,MAAD;EAAY,OAAA;EAAgB,KAAA;EAA5B,UAAA,CACEjD,IACAgD,GAFG;KAOElF,EAAA,MAAAkF,KAAAlF,EAAA,MAAAkC,IAAAlC,EAAA,MAAAmF,OAAAA,MAAAnF,EAAA;CAAA,IAAAoF;CACF,OADEpF,EAAA,QAAAmF,OAAAnF,EAAA,QAAA0B,MART0D,MAAA,oBAAC,MAAD;EAAkB,YAAA;EAAS,MAAA1D;EACzByD,UAAAA;CADG,CAAA,GASEnF,EAAA,MAAAmF,KAAAnF,EAAA,MAAA0B,IAAA1B,EAAA,MAAAoF,OAAAA,MAAApF,EAAA,KATPoF;AASO;AA9JI,SAAAP,OAAAQ,GAAA;CAAA,OAiGQA,EAACf,SAAU,WAAWe,EAACC,SAAU;AAAO;AAjGhD,SAAA7B,OAAA8B,SAAA;CAsDD,IAAI,CAACC,WAAS,OAAOA,WAAU,UAAQ,OAC9BA;CAGT,IAAIA,QAAKjC,SAAU,YAAYiC,QAAKpF,QAASyC,MAAKC,QAAS0C,QAAKpF,IAAK,GAAC;EAEpE,IAAAqF,YAAkBD,QAAKpF,KAAK,OAAQ,UAAUoF,QAAKpF,OAAjC,CAA0C,SAAO,GAAKoF,QAAKpF,IAAK;EACpC,OACvCsF;GADY,GAAIF;GAAKpF,MAAQqF;EAC7BC;CAAU;CAClB,OACMF;AAAK;AAhEX,SAAAnC,OAAAmC,OAAA;CAyCJ,OAdG,CAACA,SAAS,OAAOA,SAAU,WACtB,KAKPA,MAAKjC,SAAU,YACfiC,MAAKpF,QACLyC,MAAKC,QAAS0C,MAAKpF,IAAK,KACxBoF,MAAKpF,KAAKa,SAAU,IAGKuE,MAAKpF,KAAK,OAAQ,WAAW,OAAOoF,MAAKpF,KAAK,MAAQ,WAG1E;AAAK;ACvJtB,IAAA,kBAAgBgG,WAAgC;CAC9C,IAAM,EAACD,SAAQC,QACTC,WAAW,OAAOF,QAAS,WAAWA,OAAOA,KAAKG,MAClDC,aAAaR,gBAAgBM,UAAU,EAAI;CAEjD,OAAOT,YAAY;EACjBU,MAAMC;EACNC,OAAO,2BAA2BH;EAClCF,MAAM;EACNM,YAAY;GAEVC,MAAMV;GACNW,QAAQC,UACNA,MAAMC,cAAc;IAClB,GAAGD;IAEHE,OAAO;GACT,CAAC;EACL;EACAC,QAAQ,CACNnB,YAAY;GACV,GAAI,OAAOO,QAAS,WAAW,EAACA,KAAI,IAAIA;GACxCG,MAAM;EACR,CAAC,GAGDV,YAAY;GACVU,MAAM;GACNH,MAAM;GACNa,QAAQ;GACRC,aAAaC,SAASA,KAAKC,SAAS;EACtC,CAAC,CAAC;EAEJC,SAAS,EACPC,QAAQ;GACNb,OAAO;GACPc,UAAUrB;EACZ,EACF;CACF,CAAC;AACH;ACrCA,MAAakC,yBAAyBX,cAA4BY,WAAW;CAC3E,IAAMC,eAAe;EAAC,GAAGR;EAAgB,GAAGO;CAAM,GAC5C,EAEJE,aAAa,cACbC,QACAC,WACAC,YACAC,kBACAC,iBACApB,gBAAgBqB,yBACdP;CAEJ,OAAO;EACLQ,MAAM;EAENC,QAAQC,MAAMC,QAAQR,SAAS,IAC3BS,KAAAA,IACA,EACEC,YAAY,EACVC,SAASC,UACP,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,SAAD;GAAqBd;GAAuBE;EAAU,CAAA,GACrDY,MAAMC,cAAcD,KAAK,CAC5B,EAAA,CAAA,EAEJ,EACF;EAEJE,UAAU;GACRJ,YAAY,EACVK,kBAAkBH,UAChB,oBAAC,8BAAD;IAA8B,GAAIA;IAAqBf;GAAa,CAAA,EAExE;GACAmB,uBAAuBb,gBAAgBc,SAAS,uBAAuB,KAClEC,SAAS,CAAC,GAAGA,MAAM5B,iCAAiC,IACrDmB,KAAAA;EACN;EAEAU,MAAM,EACJT,YAAY,EACVU,QAAQR,UACcA,MAAMU,OAAO,UAAUrC,mBAAmB2B,KAAK,KAMjClB,+BAA+BkB,MAAMY,UAGrED,KACA1B,aAAa4B,uBAAuBb,MAAMY,WAAWnB,IAAI,IAElD,oBAAC,iCAAD;GAAiC,GAAIO;GAAqBf;EAAa,CAAA,IAEzEe,MAAMC,cAAcD,KAAK,EAEpC,EACF;EAEAc,QAAQ,EACNC,OAAO,CACL,GAAG1B,WAAW2B,KAAKC,SAAStC,cAAM;GAACsC;GAAM/B;GAAYC;GAAQC;GAAWE;EAAgB,CAAC,CAAC,GAC1F,GAAGD,WAAW2B,KAAKC,SAASrC,eAAO,EAACqC,KAAI,CAAC,CAAC,CAAC,EAE/C;EACAC,SACE1B,sBAAsB2B,eAAeC,SAAS,IAC1C,CACEjD,eAAe;GACbgD,eAAe3B,qBAAqB2B;GACpCE,oBAAoBjC;GACpBE,kBAAkBE,qBAAqBF;EAIzC,CAAC,CAAC,IAEJO,KAAAA;CACR;AACF,CAAC"}
\ 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","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])","(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)","<DocumentAddButtons />","props.renderDefault(props)","props.renderDefault","<Stack gap={5}>\n <DocumentAddButtons />\n {props.renderDefault(props)}\n </Stack>","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","{apiVersion: props.apiVersion}","apiVersion","<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>","{\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>","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 // 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 // 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],\n )","['_rev']","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 documentExists,\n isDeleted,\n isDeleting,\n handleAddLanguages,\n defaultLanguages,\n addedLanguages,\n languages,\n readOnly,\n shouldMigrateArray,\n ]","() => {\n const hasAddedDefaultLanguages = defaultLanguages\n .filter((language) => languages.find((l) => l.id === language))\n .every((language) => addedLanguages.includes(language))\n\n if (\n documentExists &&\n !isDeleting &&\n !isDeleted &&\n !hasAddedDefaultLanguages &&\n !shouldMigrateArray\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 }","l","language","() => {\n if (!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 (!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])","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","checkAllLanguagesArePresent(filteredLanguages, value)","useMemo(\n () => checkAllLanguagesArePresent(filteredLanguages, value),\n [filteredLanguages, value],\n )","() => {\n handleAddLanguages(filteredLanguages.map((language) => language.id))\n }","(language) => language.id","useCallback(() => {\n handleAddLanguages(filteredLanguages.map((language) => language.id))\n }, [filteredLanguages, handleAddLanguages])","<Feedback />","!shouldMigrateArray &&\n // Plugin was configured to display buttons here (default!)\n buttonLocations.includes('field') &&\n // There's at least one language visible\n filteredLanguages?.length > 0 &&\n // Not every language has a value yet\n !allLanguagesArePresent","length","createAddAllTitle(value, filteredLanguages)","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} />","!addButtonsAreVisible && !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","addButtonsAreVisible ? (\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 || allLanguagesArePresent}\n icon={AddIcon}\n text={addAllTitle}\n onClick={addAllMissingLanguages}\n />\n ) : null}\n </Stack>\n ) : null","<Stack gap={2}>\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 {!addButtonsAreVisible && !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 {addButtonsAreVisible ? (\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 || allLanguagesArePresent}\n icon={AddIcon}\n text={addAllTitle}\n onClick={addAllMissingLanguages}\n />\n ) : null}\n </Stack>\n ) : null}\n </Stack>","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'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'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"],"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/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 // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion\n const itemKeys = Object.keys(value).filter(\n (key) => !key.match(startsWithUnderscoreRegex),\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 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 return `Add missing ${languages.length - value.length === 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 * @defaultValue ['field']\n * */\n buttonLocations?: ('field' | 'unstable__fieldAction' | 'document')[]\n /**\n * Show or hide the \"Add missing languages\" button\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 {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, useEffect, useMemo} from 'react'\nimport {\n type ArrayOfObjectsInputProps,\n ArrayOfObjectsItem,\n MemberItemError,\n set,\n setIfMissing,\n useFormValue,\n useGetFormValue,\n} from 'sanity'\nimport {useDocumentPane} from 'sanity/structure'\n\nimport {LANGUAGE_FIELD_NAME} from '../constants'\nimport type {InternationalizedArrayItem} from '../types'\nimport {checkAllLanguagesArePresent} from '../utils/checkAllLanguagesArePresent'\nimport {createAddAllTitle} from '../utils/createAddAllTitle'\nimport {createAddLanguagePatches} from '../utils/createAddLanguagePatches'\nimport {internationalizedArrayLanguageFilter} from '../utils/internationalizedArrayLanguageFilter'\nimport AddButtons from './AddButtons'\nimport Feedback from './Feedback'\nimport {useInternationalizedArrayContext} from './InternationalizedArrayContext'\nimport {MigrationBanner} from './MigrationBanner'\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 and an \"Add all / Add\n * missing languages\" button (controlled by `buttonAddAll` and\n * `buttonLocations` config). Dispatches `setIfMissing` + `insert` patches.\n * - **Default languages**: Automatically adds entries for languages listed in\n * `defaultLanguages` when those entries are missing. Only runs once the\n * document exists in the dataset (it has a `_rev`), so the effect never\n * recreates a just-deleted document or creates a draft before the user's\n * first edit.\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 readOnly = Boolean(documentReadOnly) || schemaType.readOnly === true\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\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 handleAddLanguages = useCallback(\n (addLanguageKeys: string[] | string) => {\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],\n )\n\n const {isDeleted, isDeleting} = useDocumentPane()\n\n // The document only has a revision once it exists in the dataset. Patching\n // a nonexistent document would create it: auto-adding default languages to\n // a just-deleted document resurrects it as an empty draft (and the deleted\n // pane can outrace `isDeleted`), and auto-adding to an unsaved new document\n // creates a draft before the user has made any edits.\n const documentExists = Boolean(useFormValue(['_rev']))\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 documentExists &&\n !isDeleting &&\n !isDeleted &&\n !hasAddedDefaultLanguages &&\n !shouldMigrateArray\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 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 (!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])\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 // compare value keys with possible languages\n const allLanguagesArePresent = useMemo(\n () => checkAllLanguagesArePresent(filteredLanguages, value),\n [filteredLanguages, value],\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 addButtonsAreVisible =\n !shouldMigrateArray &&\n // Plugin was configured to display buttons here (default!)\n buttonLocations.includes('field') &&\n // There's at least one language visible\n filteredLanguages?.length > 0 &&\n // Not every language has a value yet\n !allLanguagesArePresent\n const fieldHasMembers = members?.length > 0\n const addAllTitle = createAddAllTitle(value, filteredLanguages)\n\n return (\n <Stack gap={2}>\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 {!addButtonsAreVisible && !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 {addButtonsAreVisible ? (\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 || allLanguagesArePresent}\n icon={AddIcon}\n text={addAllTitle}\n onClick={addAllMissingLanguages}\n />\n ) : null}\n </Stack>\n ) : null}\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'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