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