Skip to content

Instantly share code, notes, and snippets.

@davo
Last active Nov 27, 2019
Embed
What would you like to do?
FrameSpy - Refactor
import * as React from 'react'
import { addPropertyControls, ControlType, FrameProps, Frame } from 'framer'
import reactElementToJSXString from 'react-element-to-jsx-string'
import Highlight, { defaultProps } from 'prism-react-renderer'
import { themes } from './themes'
import Clipboard from 'react-clipboard.js'
// @steveruizok
// Define type of property
type Props = Partial<FrameProps> &
Partial<{
target: React.ReactNodeArray
theme: string
fontSize: number
lineHeight: number
tabStop: number
sortProps: boolean
showFunctions: boolean
showDefaultProps: boolean
useBooleanShorthandSyntax: boolean
useFragmentShortSyntax: boolean
}>
export const FrameSpy = (props: Props) => {
const {
target,
theme,
tabStop,
fontSize,
lineHeight,
sortProps,
showFunctions,
showDefaultProps,
useFragmentShortSyntax,
useBooleanShorthandSyntax,
...rest
} = props
const [node] = target
if (!node) {
return (
<DefaultContainer {...rest}>
<h1>🕵️‍♀️ FrameSpy</h1>
<p>Connect a Frame to spy on its JSX.</p>
</DefaultContainer>
)
}
const codeString = reactElementToJSXString(node, {
tabStop,
sortProps,
showFunctions,
showDefaultProps,
useFragmentShortSyntax,
useBooleanShorthandSyntax,
})
return (
<Frame {...rest} background={themes[theme].plain.backgroundColor}>
<div style={containerStyle}>
<Highlight {...defaultProps} code={codeString} theme={themes[theme]} language='jsx'>
{({ className, style, tokens, getLineProps, getTokenProps }) => (
<pre
className={className}
style={{
...style,
fontSize: `${fontSize}rem`,
lineHeight: `${lineHeight}rem`,
}}>
{tokens.map((line, i) => (
<div {...getLineProps({ line, key: i })}>
{line.map((token, key) => (
<span {...getTokenProps({ token, key })} />
))}
</div>
))}
</pre>
)}
</Highlight>
<Clipboard data-clipboard-text={codeString} style={clipboard}>
Copy to Clipboard
</Clipboard>
</div>
</Frame>
)
}
FrameSpy.defaultProps = {
height: 280,
width: 296,
target: [],
showDefaultProps: true,
sortProps: false,
showFunctions: false,
useBooleanShorthandSyntax: true,
useFragmentShortSyntax: true,
tabStop: 2,
fontSize: 1,
lineHeight: 1.5,
theme: 'dracula',
}
addPropertyControls(FrameSpy, {
target: { type: ControlType.ComponentInstance, title: 'Target' },
theme: {
type: ControlType.Enum,
options: Object.keys(themes),
title: 'Theme',
},
showDefaultProps: {
type: ControlType.Boolean,
title: 'Default Props',
defaultValue: false,
},
sortProps: {
type: ControlType.Boolean,
title: 'Sort Props',
defaultValue: false,
},
showFunctions: {
type: ControlType.Boolean,
title: 'Show Functions',
defaultValue: false,
},
useBooleanShorthandSyntax: {
type: ControlType.Boolean,
title: 'Boolean Shorthand',
defaultValue: true,
},
useFragmentShortSyntax: {
type: ControlType.Boolean,
title: 'Fragment Shorthand',
defaultValue: true,
},
fontSize: {
type: ControlType.Number,
title: 'Font Size',
defaultValue: 1,
min: 0.5,
max: 5,
unit: 'rem',
step: 0.1,
displayStepper: true,
},
lineHeight: {
type: ControlType.Number,
title: 'Line Height',
defaultValue: 1.5,
min: 0.5,
max: 5,
unit: 'rem',
step: 0.1,
displayStepper: true,
},
tabStop: {
type: ControlType.Number,
title: 'Tab Stop',
min: 2,
max: 8,
defaultValue: 2,
},
})
type DefaultContainerProps = Partial<FrameProps>
// A component for our default container
const DefaultContainer = (props: DefaultContainerProps) => {
const { children, style, ...rest } = props
return (
<Frame
{...rest}
style={{
...emptyState,
...style,
}}>
<>{children}</>
</Frame>
)
}
const emptyState: React.CSSProperties = {
color: '#8855FF',
background: 'rgba(136, 85, 255, 0.1)',
overflow: 'hidden',
padding: 16,
fontSize: 16,
lineHeight: 1.3,
textAlign: 'left',
}
const containerStyle: React.CSSProperties = {
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
overflow: 'scroll',
padding: '0 8px',
}
const clipboard: React.CSSProperties = {
cursor: 'pointer',
backgroundColor: 'none',
background: 'none',
border: 'none',
outline: 'none',
color: '#0099ff',
position: 'fixed',
top: '8px',
right: '12px',
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment