The Node.js® Website
at main 88 lines 2.7 kB view raw
1'use client'; 2 3import { useTranslations } from 'next-intl'; 4import { useContext, useEffect, useMemo } from 'react'; 5import type { FC } from 'react'; 6 7import Select from '@/components/Common/Select'; 8import Apple from '@/components/Icons/Platform/Apple'; 9import Linux from '@/components/Icons/Platform/Linux'; 10import Microsoft from '@/components/Icons/Platform/Microsoft'; 11import { useDetectOS } from '@/hooks/react-client'; 12import { ReleaseContext } from '@/providers/releaseProvider'; 13import type { UserOS } from '@/types/userOS'; 14import { 15 formatDropdownItems, 16 operatingSystemItems, 17} from '@/util/downloadUtils'; 18 19type OperatingSystemDropdownProps = { exclude?: Array<UserOS> }; 20 21const OperatingSystemDropdown: FC<OperatingSystemDropdownProps> = ({ 22 exclude = [], 23}) => { 24 const { os: userOS } = useDetectOS(); 25 const { platform, os, setOS } = useContext(ReleaseContext); 26 const t = useTranslations(); 27 28 // we shouldn't react when "actions" change 29 // eslint-disable-next-line react-hooks/exhaustive-deps 30 useEffect(() => setOS(userOS), [userOS]); 31 32 // @TODO: We should have a proper utility that gives 33 // disabled OSs, Platforms, based on specific criteria 34 // this can be an optimisation for the future 35 // to remove this logic from this component 36 const disabledItems = useMemo(() => { 37 const disabledItems = exclude; 38 39 if (platform === 'BREW') { 40 disabledItems.push('WIN'); 41 } 42 43 if (platform === 'DOCKER') { 44 disabledItems.push('LINUX'); 45 } 46 47 return disabledItems; 48 }, [exclude, platform]); 49 50 // @TODO: We should have a proper utility that gives 51 // disabled OSs, Platforms, based on specific criteria 52 // this can be an optimisation for the future 53 // to remove this logic from this component 54 useEffect(() => { 55 const currentOSExcluded = disabledItems.includes(os); 56 57 const nonExcludedOS = operatingSystemItems 58 .map(({ value }) => value) 59 .find(os => !disabledItems.includes(os)); 60 61 if (currentOSExcluded && nonExcludedOS) { 62 setOS(nonExcludedOS); 63 } 64 // we shouldn't react when "actions" change 65 // eslint-disable-next-line react-hooks/exhaustive-deps 66 }, [os, disabledItems]); 67 68 return ( 69 <Select 70 label={t('layouts.download.dropdown.os')} 71 values={formatDropdownItems({ 72 items: operatingSystemItems, 73 disabledItems, 74 icons: { 75 WIN: <Microsoft width={16} height={16} />, 76 MAC: <Apple width={16} height={16} />, 77 LINUX: <Linux width={16} height={16} />, 78 }, 79 })} 80 defaultValue={os} 81 onChange={value => setOS(value as UserOS)} 82 className="w-[8.5rem]" 83 inline={true} 84 /> 85 ); 86}; 87 88export default OperatingSystemDropdown;