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