diff --git a/studio/components/LanguageSelector.tsx b/studio/components/LanguageSelector.tsx index ffdfc902d..ff6a394a0 100644 --- a/studio/components/LanguageSelector.tsx +++ b/studio/components/LanguageSelector.tsx @@ -1,12 +1,16 @@ import { Box, Button, Card, Checkbox, Flex, Text, useTheme } from "@sanity/ui"; -import React from "react"; -import { ArrayOfObjectsInputProps, PatchEvent, set } from "sanity"; - +import React, { useMemo } from "react"; +import { PatchEvent, set } from "sanity"; import { Language, supportedLanguages, } from "internationalization/supportedLanguages"; +interface LanguageSelectorProps { + value?: Language[]; + onChange: (event: PatchEvent) => void; +} + const colorMap = { dark: { selected: "#29356a", @@ -18,129 +22,100 @@ const colorMap = { }, }; -const LanguageSelector = ({ - value = [], - onChange, -}: ArrayOfObjectsInputProps) => { +const LanguageSelector = ({ value = [], onChange }: LanguageSelectorProps) => { const theme = useTheme(); const prefersDark = theme.sanity.v2?.color._dark ?? false; + const themeType = prefersDark ? "dark" : "light"; - // Get the currently set default language + // Find current default language const currentDefaultLanguage = value.find((lang) => lang.default)?.id || null; const handleLanguageSelection = (lang: Language) => { const isSelected = value.some((item) => item.id === lang.id); - const updatedValue = isSelected - ? value.filter((item) => item.id !== lang.id) // Deselect language - : [...value, { ...lang, default: false }]; // Select language + let updatedValue; - const newDefaultLanguage = getNewDefaultLanguage( - updatedValue, - currentDefaultLanguage, - lang, - ); + if (isSelected) { + // Deselect language + updatedValue = value.filter((item) => item.id !== lang.id); - const finalValue = updatedValue.map((item) => ({ - ...item, - default: item.id === newDefaultLanguage, - })); + // If deselecting the default language, assign a new default + if (currentDefaultLanguage === lang.id && updatedValue.length > 0) { + updatedValue[0] = { ...updatedValue[0], default: true }; // Set the first language as default + } + } else { + // Add new language, without making it the default + updatedValue = [...value, { ...lang, default: false }]; + } - onChange(PatchEvent.from(set(finalValue))); + onChange(PatchEvent.from(set(updatedValue))); }; const handleDefaultSetting = (lang: Language) => { const updatedValue = value.map((item) => ({ ...item, - default: item.id === lang.id, // Set selected language as default + default: item.id === lang.id, // Only one language can be the default })); onChange(PatchEvent.from(set(updatedValue))); }; - const getBackgroundColor = (lang: Language) => { - const isSelected = value.some((item) => item.id === lang.id); - const theme = prefersDark ? "dark" : "light"; - - return isSelected ? colorMap[theme].selected : colorMap[theme].default; - }; - - return ( - - {supportedLanguages.map((lang) => ( - handleLanguageSelection(lang)} - > - - - item.id === lang.id)} - readOnly - disabled={ - value?.length <= 1 && currentDefaultLanguage === lang.id - } - /> - - + // Memoize value for performance and reusability + const languageCards = useMemo( + () => + supportedLanguages.map((lang) => { + const isSelected = value.some((item) => item.id === lang.id); + const backgroundColor = isSelected + ? colorMap[themeType].selected + : colorMap[themeType].default; + + return ( + handleLanguageSelection(lang)} + > + + + + - - + + + {isSelected && ( + + + + )} - {value.some((item) => item.id === lang.id) && ( - - - - )} - - - ))} - + + ); + }), + [value, currentDefaultLanguage, themeType] ); -}; - -// Helper function to determine the new default language -const getNewDefaultLanguage = ( - updatedLanguages: Language[], - currentDefault: string | null, - deselectedLang: Language, -): string | null => { - if (updatedLanguages.length === 1) { - return updatedLanguages[0].id; - } - - if (currentDefault === deselectedLang.id) { - // Find a new default language if the current default is deselected - return ( - supportedLanguages.find((lang) => - updatedLanguages.some((item) => item.id === lang.id), - )?.id || null - ); - } - return currentDefault; // Return existing default + return ( + + {languageCards} + + ); }; export default LanguageSelector;