UNPKG

mdx-deck-live-code

Version:

A component for mdx-deck for live coding directly in your slides. 🤯

1 lines • 7.07 kB
{"version":3,"file":"index.mjs","sources":["../src/components/live-editor.tsx","../src/components/live-code.tsx"],"sourcesContent":["import * as React from 'react';\nimport {\n\tLiveEditor as BaseLiveEditor,\n\tLiveEditorProps as BaseLiveEditorProps,\n} from 'react-live';\nimport styled from 'styled-components';\n\nconst isMacLike =\n\ttypeof window !== 'undefined' &&\n\t'navigator' in window &&\n\t/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform);\n\ninterface LiveEditorState {\n\tfocusEditor: boolean;\n}\nexport interface LiveEditorProps extends BaseLiveEditorProps {}\n/**\n * A wrapper around the default LiveEditor from react-live\n * Fixes focus state problems where mdx-deck and react-live don't get along\n * maybe not needed when this PR is merged:\n * https://github.com/FormidableLabs/react-live/pull/77\n *\n * Passes all valid params down to the LiveEditor from react-live\n */\nexport class LiveEditor extends React.PureComponent<\n\tLiveEditorProps,\n\tLiveEditorState\n> {\n\tstate = { focusEditor: true };\n\n\tfocusEditor = () => {\n\t\tthis.setState({ focusEditor: true });\n\t};\n\tblurEditor = () => {\n\t\tthis.setState({ focusEditor: false });\n\t};\n\n\t/**\n\t * remove focus from editor when user presses one of:\n\t * - Escape\n\t * - CTRL + M (Windows and Linux)\n\t * - CTRL + SHIFT + M (Mac)\n\t * Mimicks Monaco edtor:\n\t * https://github.com/Microsoft/monaco-editor/wiki/Monaco-Editor-Accessibility-Guide#tab-trapping\n\t */\n\tblurOnKeyCombo: React.KeyboardEventHandler<HTMLDivElement> = event => {\n\t\tif (\n\t\t\tevent.key === 'Escape' ||\n\t\t\t(event.key === 'M' &&\n\t\t\t\tevent.ctrlKey &&\n\t\t\t\t(isMacLike ? event.shiftKey : true))\n\t\t) {\n\t\t\tthis.blurEditor();\n\t\t}\n\t};\n\n\trender() {\n\t\tconst { focusEditor } = this.state;\n\t\tconst { className, ...props } = this.props;\n\n\t\treturn (\n\t\t\t<div\n\t\t\t\tonFocus={this.focusEditor}\n\t\t\t\tonClick={this.focusEditor}\n\t\t\t\tonBlur={this.blurEditor}\n\t\t\t\tonKeyDown={this.blurOnKeyCombo}\n\t\t\t\tclassName={className}\n\t\t\t>\n\t\t\t\t<StyledBaseLiveEditor contentEditable={focusEditor} {...props as any} />\n\t\t\t</div>\n\t\t);\n\t}\n}\n\n// add extra spacing at the bottom to make sure errors don't obscure code\nconst StyledBaseLiveEditor = styled(BaseLiveEditor)`\n\theight: 100%;\n\tmax-height: 100vh;\n\toverflow: auto;\n\tfont-size: 0.7em;\n\twidth: 100%;\n\tpadding-bottom: 5rem !important;\n\t${props => props.theme.liveCode && props.theme.liveCode.editor};\n`;\n","import * as React from 'react';\nimport {\n\tLiveProvider,\n\tLiveError,\n\tLiveProviderProps,\n\tLivePreview,\n} from 'react-live';\nimport styled, { withTheme } from 'styled-components';\nimport { LiveEditor, LiveEditorProps } from './live-editor';\nimport { OmitRef } from '../types';\n\ninterface Props {\n\tcode?: string;\n\ttitle?: string;\n\tsize?: Size;\n\terrors?: boolean;\n\tproviderProps?: OmitRef<LiveProviderProps>;\n\teditorProps?: OmitRef<LiveEditorProps>;\n\tpreviewProps?: OmitRef<React.HTMLProps<HTMLDivElement>>;\n\terrorProps?: OmitRef<React.HTMLProps<HTMLDivElement>>;\n}\ntype Size = 'small' | 'medium' | 'large' | 'fullscreen';\n\n/**\n * A high level component to quickly add live coding abilities\n */\nconst LiveCodeBase: React.SFC<Props & { theme: any }> = ({\n\tcode,\n\tsize = 'medium',\n\terrors = true,\n\tproviderProps,\n\ttitle,\n\teditorProps,\n\tpreviewProps,\n\terrorProps,\n}) => {\n\treturn (\n\t\t<LiveProvider code={code} {...providerProps}>\n\t\t\t<LiveDeck size={size as Size}>\n\t\t\t\t{title && !(size === 'fullscreen') && <p>{title}</p>}\n\t\t\t\t<LiveContainer size={size as Size}>\n\t\t\t\t\t<StyledLivePreview {...previewProps as any} />\n\t\t\t\t\t<StyledLiveEditor {...editorProps as any} />\n\t\t\t\t\t{errors && <StyledLiveError {...errorProps as any} />}\n\t\t\t\t</LiveContainer>\n\t\t\t</LiveDeck>\n\t\t</LiveProvider>\n\t);\n};\n\nexport const LiveCode = withTheme(LiveCodeBase);\n\nconst LiveDeck = styled.div<{ size: Size }>`\n\tdisplay: flex;\n\tflex-direction: column;\n\tjustify-content: center;\n\talign-items: center;\n\tpadding: ${({ size }) => (size === 'fullscreen' ? '0' : '1em')};\n\t${({ size }) => {\n\t\tswitch (size) {\n\t\t\tcase 'small':\n\t\t\t\treturn 'width: 60vw; height: 70vh';\n\t\t\tcase 'medium':\n\t\t\t\treturn 'width: 80vw; height: 90vh';\n\t\t\tcase 'large':\n\t\t\tcase 'fullscreen':\n\t\t\t\treturn 'width: 100vw; height: 100vh;';\n\t\t}\n\t}};\n`;\n\n// prettier-ignore\nconst LiveContainer = styled.div<{ size: Size }>`\n\twidth: 100%;\n\theight: 100%;\n\tdisplay: flex;\n\tposition: relative;\n\t\n\t${({size}) => size !== 'fullscreen' &&\n\t\t`box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.5);\n\t\tborder-radius: 0.25rem;`\n\t}\n\t${props => props.theme.liveCode && props.theme.liveCode.container} \n`;\n\nconst StyledLivePreview = styled(LivePreview)`\n\twidth: 50%;\n\tbackground: white;\n\t${props => props.theme.liveCode && props.theme.liveCode.preview};\n`;\n\nconst StyledLiveEditor = styled(LiveEditor)`\n\twidth: 50%;\n`;\n\nconst StyledLiveError = styled(LiveError)`\n\tposition: absolute;\n\tbottom: 0;\n\twidth: 100%;\n\tpadding: 0.125em;\n\tbackground: #280000;\n\tborder: 2px solid #5c0000;\n\tcolor #ff8080;\n\tfont-family: monospace;\n\tfont-size: 0.75em;\n\theight: 5rem;\n\toverflow-y: auto;\n\tresize: vertical;\n\t${props => props.theme.liveCode && props.theme.liveCode.error} \n`;\n"],"names":["isMacLike","window","test","navigator","platform","LiveEditor","constructor","focusEditor","setState","event","key","ctrlKey","shiftKey","blurEditor","render","this","state","props","React","onFocus","onClick","onBlur","onKeyDown","blurOnKeyCombo","className","StyledBaseLiveEditor","contentEditable","styled","BaseLiveEditor","theme","liveCode","editor","LiveCode","withTheme","ref","LiveProvider","code","LiveDeck","size","title","LiveContainer","StyledLivePreview","previewProps","StyledLiveEditor","editorProps","errors","StyledLiveError","errorProps","div","container","LivePreview","preview","LiveError","error"],"mappings":"2WAOMA,EACa,oBAAXC,QACP,cAAeA,QACf,0BAA0BC,KAAKC,UAAUC,UAc7BC,cAAbC,2DAIS,CAAEC,aAAa,iCAGjBC,SAAS,CAAED,aAAa,kCAGxBC,SAAS,CAAED,aAAa,kCAW+BE,IAE7C,WAAdA,EAAMC,KACS,MAAdD,EAAMC,KACND,EAAME,WACLX,GAAYS,EAAMG,cAEfC,8GAIPC,wBACyBC,KAAKC,oBACGD,KAAKE,wKAGpCC,SACCC,QAASJ,KAAKR,YACda,QAASL,KAAKR,YACdc,OAAQN,KAAKF,WACbS,UAAWP,KAAKQ,eAChBC,UAAWA,GAEXN,EAACO,iBAAqBC,gBAAiBnB,YA5CXW,GAmD1BO,EAAuBE,EAAOC,EAAPD,YAO1BV,UAASA,EAAMY,MAAMC,UAAYb,EAAMY,MAAMC,SAASC,0pBChC5CC,EAAWC,WAxBiCC,+BAEjD,yCACE,wEAQRhB,EAACiB,iBAAaC,8BACblB,EAACmB,GAASC,KAAMA,GACdC,KAAoB,eAATD,IAA0BpB,WAAIqB,GAC1CrB,EAACsB,GAAcF,KAAMA,GACpBpB,EAACuB,mBAAsBC,IACvBxB,EAACyB,mBAAqBC,IACrBC,GAAU3B,EAAC4B,mBAAoBC,SAS/BV,EAAWV,EAAOqB,eAKXd,SAAuB,sBAAe,IAAM,gBACrDA,sBAEI,cACG,gCACH,eACG,gCACH,YACA,mBACG,kCAMLM,EAAgBb,EAAOqB,eAMzBd,SAAoB,6GAIrBjB,UAASA,EAAMY,MAAMC,UAAYb,EAAMY,MAAMC,SAASmB,YAGnDR,EAAoBd,EAAOuB,EAAPvB,YAGvBV,UAASA,EAAMY,MAAMC,UAAYb,EAAMY,MAAMC,SAASqB,UAGnDR,EAAmBhB,EAAOtB,EAAPsB,IAInBmB,EAAkBnB,EAAOyB,EAAPzB,YAarBV,UAASA,EAAMY,MAAMC,UAAYb,EAAMY,MAAMC,SAASuB"}