1import * as React from 'react'; 2 3import { SNACK_URL } from '../../common/snack'; 4 5import DocumentationPageContext from '~/components/DocumentationPageContext'; 6 7type Props = { 8 snackId?: string; 9 name?: string; 10 description?: string; 11 platform?: string; 12 preview?: boolean; 13 theme?: string; 14 style?: React.CSSProperties; 15}; 16 17export default class SnackEmbed extends React.Component<Props> { 18 static contextType = DocumentationPageContext; 19 20 componentDidMount() { 21 let script = document.getElementById('snack') as HTMLScriptElement; 22 // inject script if it hasn't been loaded by a previous page 23 if (!script) { 24 script = document.createElement('script'); 25 script.src = `${this.props.snackId ? 'https://snack.expo.io' : SNACK_URL}/embed.js`; 26 script.async = true; 27 script.id = 'snack'; 28 29 document.body.appendChild(script); 30 script.addEventListener('load', () => { 31 window.ExpoSnack.initialize(); 32 }); 33 } 34 35 if (window.ExpoSnack) { 36 window.ExpoSnack.initialize(); 37 } 38 } 39 40 render() { 41 // TODO(abi): Handle `data-snack-sdk-version` somehow 42 // maybe using `context`? 43 44 // get snack data from snack id or from inline code 45 // TODO (barthap): Type all possible keys for this 46 let embedProps: Record<string, any>; 47 if (this.props.snackId) { 48 embedProps = { 'data-snack-id': this.props.snackId }; 49 } else { 50 const code = React.Children.toArray(this.props.children).join('').trim(); 51 embedProps = { 52 'data-snack-code': code, 53 }; 54 if (this.props.hasOwnProperty('name')) { 55 embedProps['data-snack-name'] = this.props.name; 56 } 57 if (this.props.hasOwnProperty('description')) { 58 embedProps['data-snack-description'] = this.props.description; 59 } 60 } 61 62 // fill in default options for snack styling 63 if (this.props.hasOwnProperty('platform')) { 64 embedProps['data-snack-platform'] = this.props.platform; 65 } else { 66 embedProps['data-snack-platform'] = 'ios'; 67 } 68 69 if (this.props.hasOwnProperty('preview')) { 70 embedProps['data-snack-preview'] = this.props.preview; 71 } else { 72 embedProps['data-snack-preview'] = false; 73 } 74 75 if (this.props.hasOwnProperty('theme')) { 76 embedProps['data-snack-theme'] = this.props.theme; 77 } else { 78 embedProps['data-snack-theme'] = 'light'; 79 } 80 81 const embedStyle = this.props.hasOwnProperty('style') ? this.props.style! : {}; 82 83 return ( 84 <div 85 {...embedProps} 86 style={{ 87 overflow: 'hidden', 88 background: '#fafafa', 89 borderWidth: 1, 90 borderStyle: 'solid', 91 height: 505, 92 maxWidth: '1200px', 93 borderRadius: 4, 94 borderColor: 'rgba(0,0,0,.16)', 95 ...embedStyle, 96 }} 97 /> 98 ); 99 } 100} 101