1import { css } from '@emotion/react'; 2import { shadows, theme } from '@expo/styleguide'; 3import { borderRadius, spacing } from '@expo/styleguide-base'; 4import { ChevronDownIcon } from '@expo/styleguide-icons'; 5 6import { usePageApiVersion } from '~/providers/page-api-version'; 7import versions from '~/public/static/constants/versions.json'; 8import { A, LABEL } from '~/ui/components/Text'; 9 10const { VERSIONS, LATEST_VERSION, BETA_VERSION } = versions; 11 12// TODO(cedric): move this to a generic select input, so we can reuse it in the color scheme selector 13 14export function ApiVersionSelect() { 15 const { version, hasVersion, setVersion } = usePageApiVersion(); 16 17 if (!hasVersion) { 18 return null; 19 } 20 21 return ( 22 <div css={containerStyle}> 23 <label className="flex flex-row items-center" htmlFor="api-version-select"> 24 <LABEL className="flex">{versionToText(version)}</LABEL> 25 <ChevronDownIcon className="icon-sm shrink-0" /> 26 </label> 27 <select 28 id="api-version-select" 29 css={selectStyle} 30 value={version} 31 onChange={event => setVersion(event.target.value)}> 32 {VERSIONS.map(version => ( 33 <option key={version} value={version}> 34 {versionToText(version)} 35 </option> 36 ))} 37 </select> 38 {/* Changing versions is a JS only mechanism. To help crawlers find other versions, we add hidden links. */} 39 {VERSIONS.map(version => ( 40 <A className="hidden" key={version} href={`/versions/${version}`} /> 41 ))} 42 </div> 43 ); 44} 45 46function versionToText(version: string): string { 47 if (version === 'unversioned') { 48 return 'Unversioned'; 49 } else if (version === 'latest') { 50 return `${versionToText(LATEST_VERSION)} (latest)`; 51 } else if (BETA_VERSION && version === BETA_VERSION.toString()) { 52 return `${versionToText(BETA_VERSION.toString())} (beta)`; 53 } 54 return `SDK ${version.substring(1, 3)}`; 55} 56 57const containerStyle = css({ 58 position: 'relative', 59 background: theme.background.default, 60 border: `1px solid ${theme.border.default}`, 61 borderRadius: borderRadius.md, 62 boxShadow: shadows.xs, 63 margin: spacing[4], 64 padding: `${spacing[2]}px ${spacing[3]}px`, 65}); 66 67const selectStyle = css({ 68 borderRadius: 0, 69 position: 'absolute', 70 width: '100%', 71 height: '100%', 72 top: 0, 73 left: 0, 74 right: 0, 75 bottom: 0, 76 opacity: 0, 77 cursor: 'pointer', 78}); 79