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