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) 51 .join('') 52 .trim(); 53 embedProps = { 54 'data-snack-code': code, 55 }; 56 if (this.props.hasOwnProperty('name')) { 57 embedProps['data-snack-name'] = this.props.name; 58 } 59 if (this.props.hasOwnProperty('description')) { 60 embedProps['data-snack-description'] = this.props.description; 61 } 62 } 63 64 // fill in default options for snack styling 65 if (this.props.hasOwnProperty('platform')) { 66 embedProps['data-snack-platform'] = this.props.platform; 67 } else { 68 embedProps['data-snack-platform'] = 'ios'; 69 } 70 71 if (this.props.hasOwnProperty('preview')) { 72 embedProps['data-snack-preview'] = this.props.preview; 73 } else { 74 embedProps['data-snack-preview'] = false; 75 } 76 77 if (this.props.hasOwnProperty('theme')) { 78 embedProps['data-snack-theme'] = this.props.theme; 79 } else { 80 embedProps['data-snack-theme'] = 'light'; 81 } 82 83 var embedStyle = {}; 84 if (this.props.hasOwnProperty('style')) { 85 embedStyle = this.props.style!; 86 } 87 88 return ( 89 <div 90 {...embedProps} 91 style={{ 92 overflow: 'hidden', 93 background: '#fafafa', 94 borderWidth: 1, 95 borderStyle: 'solid', 96 height: 505, 97 maxWidth: '1200px', 98 borderRadius: 4, 99 borderColor: 'rgba(0,0,0,.16)', 100 ...embedStyle, 101 }} 102 /> 103 ); 104 } 105} 106