|
|
@ -1,11 +1,11 @@
|
|
|
|
import React from 'react'
|
|
|
|
import React from 'react'
|
|
|
|
import enhanceWithClickOutside from 'react-click-outside'
|
|
|
|
|
|
|
|
import { withRouter } from 'next/router'
|
|
|
|
import { withRouter } from 'next/router'
|
|
|
|
|
|
|
|
|
|
|
|
import { COLORS, EXPORT_SIZES } from '../lib/constants'
|
|
|
|
import { COLORS, EXPORT_SIZES } from '../lib/constants'
|
|
|
|
import Button from './Button'
|
|
|
|
import Button from './Button'
|
|
|
|
|
|
|
|
import Input from './Input'
|
|
|
|
import CopyButton from './CopyButton'
|
|
|
|
import CopyButton from './CopyButton'
|
|
|
|
import WindowPointer from './WindowPointer'
|
|
|
|
import Popout from './Popout'
|
|
|
|
|
|
|
|
|
|
|
|
import { toggle } from '../lib/util'
|
|
|
|
import { toggle } from '../lib/util'
|
|
|
|
|
|
|
|
|
|
|
@ -20,53 +20,35 @@ const toIFrame = url =>
|
|
|
|
const CopyEmbed = withRouter(
|
|
|
|
const CopyEmbed = withRouter(
|
|
|
|
React.memo(
|
|
|
|
React.memo(
|
|
|
|
({ router: { asPath } }) => (
|
|
|
|
({ router: { asPath } }) => (
|
|
|
|
<React.Fragment>
|
|
|
|
<CopyButton text={toIFrame(asPath)}>
|
|
|
|
<CopyButton text={toIFrame(asPath)}>
|
|
|
|
{({ copied }) => (
|
|
|
|
{({ copied }) => (
|
|
|
|
<Button
|
|
|
|
<button className="copy-button">{copied ? 'Copied!' : 'Copy Embed'}</button>
|
|
|
|
center
|
|
|
|
)}
|
|
|
|
title={copied ? 'Copied!' : 'Copy Embed'}
|
|
|
|
</CopyButton>
|
|
|
|
color={COLORS.PURPLE}
|
|
|
|
<style jsx>
|
|
|
|
padding="12px 16px"
|
|
|
|
{`
|
|
|
|
flex="1 0 68px"
|
|
|
|
.copy-button {
|
|
|
|
/>
|
|
|
|
display: flex;
|
|
|
|
)}
|
|
|
|
flex: 1;
|
|
|
|
</CopyButton>
|
|
|
|
flex-basis: 68px;
|
|
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
padding: 12px 16px;
|
|
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
|
|
user-select: none;
|
|
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
|
|
outline: none;
|
|
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
|
|
background: inherit;
|
|
|
|
|
|
|
|
color: ${COLORS.PURPLE};
|
|
|
|
|
|
|
|
border-right: 1px solid ${COLORS.PURPLE};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.copy-button:hover {
|
|
|
|
|
|
|
|
opacity: 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
`}
|
|
|
|
|
|
|
|
</style>
|
|
|
|
|
|
|
|
</React.Fragment>
|
|
|
|
|
|
|
|
),
|
|
|
|
),
|
|
|
|
(prevProps, nextProps) => prevProps.router.asPath === nextProps.router.asPath
|
|
|
|
(prevProps, nextProps) => prevProps.router.asPath === nextProps.router.asPath
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const popoutStyle = { width: '280px', right: 0 }
|
|
|
|
|
|
|
|
|
|
|
|
class ExportMenu extends React.PureComponent {
|
|
|
|
class ExportMenu extends React.PureComponent {
|
|
|
|
state = {
|
|
|
|
state = {
|
|
|
|
isVisible: false
|
|
|
|
isVisible: false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
toggle = () => this.setState(toggle('isVisible'))
|
|
|
|
toggle = e => {
|
|
|
|
|
|
|
|
e.stopPropagation()
|
|
|
|
handleClickOutside = () => this.setState({ isVisible: false })
|
|
|
|
this.setState(toggle('isVisible'))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
handleInputChange = e => this.props.onChange(e.target.name, e.target.value)
|
|
|
|
handleInputChange = ({ target: { name, value } }) => this.props.onChange(name, value)
|
|
|
|
|
|
|
|
|
|
|
|
handleExportSizeChange = selectedSize => () => this.props.onChange('exportSize', selectedSize)
|
|
|
|
handleExportSizeChange = selectedSize => () => this.props.onChange('exportSize', selectedSize)
|
|
|
|
|
|
|
|
|
|
|
@ -77,180 +59,120 @@ class ExportMenu extends React.PureComponent {
|
|
|
|
const { isVisible } = this.state
|
|
|
|
const { isVisible } = this.state
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
return (
|
|
|
|
<div className="export-menu-container" id="export-menu">
|
|
|
|
<div className="export-menu-container">
|
|
|
|
<Button
|
|
|
|
<div className="flex">
|
|
|
|
selected={isVisible}
|
|
|
|
<Button
|
|
|
|
className="exportButton"
|
|
|
|
border
|
|
|
|
onClick={this.toggle}
|
|
|
|
large
|
|
|
|
title="Export"
|
|
|
|
title="Export"
|
|
|
|
color={COLORS.PURPLE}
|
|
|
|
color={COLORS.PURPLE}
|
|
|
|
/>
|
|
|
|
padding="0 16px"
|
|
|
|
<div className="export-menu" hidden={!isVisible}>
|
|
|
|
selected={isVisible}
|
|
|
|
<WindowPointer fromRight="28px" color={COLORS.PURPLE} />
|
|
|
|
onClick={this.toggle}
|
|
|
|
<div className="export-option filename-option">
|
|
|
|
/>
|
|
|
|
<span>File name</span>
|
|
|
|
</div>
|
|
|
|
<input
|
|
|
|
<Popout
|
|
|
|
|
|
|
|
hidden={!isVisible}
|
|
|
|
|
|
|
|
borderColor={COLORS.PURPLE}
|
|
|
|
|
|
|
|
onClickOutside={this.toggle}
|
|
|
|
|
|
|
|
pointerRight="28px"
|
|
|
|
|
|
|
|
style={popoutStyle}
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<div className="export-row">
|
|
|
|
|
|
|
|
<span className="filename">File name</span>
|
|
|
|
|
|
|
|
<Input
|
|
|
|
title="filename"
|
|
|
|
title="filename"
|
|
|
|
placeholder="carbon"
|
|
|
|
placeholder="carbon"
|
|
|
|
value={filename}
|
|
|
|
value={filename}
|
|
|
|
name="filename"
|
|
|
|
name="filename"
|
|
|
|
onChange={this.handleInputChange}
|
|
|
|
onChange={this.handleInputChange}
|
|
|
|
|
|
|
|
color={COLORS.PURPLE}
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className="export-option">
|
|
|
|
<div className="export-row">
|
|
|
|
<div className="size-container">
|
|
|
|
<span>Size</span>
|
|
|
|
<span>Size</span>
|
|
|
|
<div className="flex">
|
|
|
|
<div>
|
|
|
|
{EXPORT_SIZES.map(({ name }, i) => (
|
|
|
|
{EXPORT_SIZES.map(({ name }) => (
|
|
|
|
<Button
|
|
|
|
<button
|
|
|
|
center
|
|
|
|
key={name}
|
|
|
|
key={name}
|
|
|
|
onClick={this.handleExportSizeChange(name)}
|
|
|
|
title={name}
|
|
|
|
className={`size-button ${exportSize === name ? 'selected' : ''}`}
|
|
|
|
hoverColor={COLORS.PURPLE}
|
|
|
|
>
|
|
|
|
margin={i === EXPORT_SIZES.length - 1 ? 0 : '0 10px 0 0'}
|
|
|
|
{name}
|
|
|
|
color={exportSize === name ? COLORS.PURPLE : COLORS.DARK_PURPLE}
|
|
|
|
</button>
|
|
|
|
onClick={this.handleExportSizeChange(name)}
|
|
|
|
))}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className="export-option">
|
|
|
|
<div className="export-row">
|
|
|
|
<button className="open-button" onClick={this.handleExport('open')}>
|
|
|
|
<Button center title="Open" color={COLORS.PURPLE} onClick={this.handleExport('open')} />
|
|
|
|
Open
|
|
|
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
<CopyEmbed />
|
|
|
|
<CopyEmbed />
|
|
|
|
<div className="save-container">
|
|
|
|
<div className="save-container">
|
|
|
|
<span>Save as</span>
|
|
|
|
<span>Save as</span>
|
|
|
|
<div>
|
|
|
|
<div>
|
|
|
|
<button onClick={this.handleExport('png')} className="save-button" id="export-png">
|
|
|
|
<Button
|
|
|
|
PNG
|
|
|
|
center
|
|
|
|
</button>
|
|
|
|
title="PNG"
|
|
|
|
<button onClick={this.handleExport('svg')} className="save-button" id="export-svg">
|
|
|
|
margin="0 8px 0 0"
|
|
|
|
SVG
|
|
|
|
hoverColor={COLORS.PURPLE}
|
|
|
|
</button>
|
|
|
|
color={COLORS.DARK_PURPLE}
|
|
|
|
|
|
|
|
onClick={this.handleExport('png')}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
<Button
|
|
|
|
|
|
|
|
center
|
|
|
|
|
|
|
|
title="SVG"
|
|
|
|
|
|
|
|
hoverColor={COLORS.PURPLE}
|
|
|
|
|
|
|
|
color={COLORS.DARK_PURPLE}
|
|
|
|
|
|
|
|
onClick={this.handleExport('svg')}
|
|
|
|
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</Popout>
|
|
|
|
<style jsx>
|
|
|
|
<style jsx>
|
|
|
|
{`
|
|
|
|
{`
|
|
|
|
button {
|
|
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
user-select: none;
|
|
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
|
|
background: inherit;
|
|
|
|
|
|
|
|
outline: none;
|
|
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
|
|
color: ${COLORS.PURPLE};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
button:hover {
|
|
|
|
|
|
|
|
opacity: 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
input {
|
|
|
|
|
|
|
|
padding: 8px 16px;
|
|
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
|
|
color: ${COLORS.PURPLE};
|
|
|
|
|
|
|
|
background: transparent;
|
|
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
|
|
outline: none;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
input::placeholder {
|
|
|
|
|
|
|
|
color: ${COLORS.PURPLE};
|
|
|
|
|
|
|
|
opacity: 0.4;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.export-menu-container {
|
|
|
|
.export-menu-container {
|
|
|
|
position: relative;
|
|
|
|
position: relative;
|
|
|
|
color: ${COLORS.PURPLE};
|
|
|
|
color: ${COLORS.PURPLE};
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.export-menu {
|
|
|
|
.flex {
|
|
|
|
box-sizing: content-box;
|
|
|
|
display: flex;
|
|
|
|
position: absolute;
|
|
|
|
height: 100%;
|
|
|
|
margin-top: 10px;
|
|
|
|
|
|
|
|
width: 280px;
|
|
|
|
|
|
|
|
border-radius: 3px;
|
|
|
|
|
|
|
|
border: 2px solid ${COLORS.PURPLE};
|
|
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
|
|
background-color: ${COLORS.BLACK};
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.filename-option {
|
|
|
|
.export-row {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: space-between;
|
|
|
|
justify-content: space-between;
|
|
|
|
padding: 0 16px;
|
|
|
|
padding: 8px 16px;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.filename-option input {
|
|
|
|
|
|
|
|
padding: 8px 0;
|
|
|
|
|
|
|
|
width: 60%;
|
|
|
|
|
|
|
|
text-align: right;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.export-option {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
border-bottom: 1px solid ${COLORS.PURPLE};
|
|
|
|
border-bottom: 1px solid ${COLORS.PURPLE};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.export-option:last-child {
|
|
|
|
.export-row > :global(button) {
|
|
|
|
border-bottom: none;
|
|
|
|
border-right: 1px solid ${COLORS.PURPLE};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.size-container {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
|
|
padding: 8px 16px;
|
|
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.size-container > div {
|
|
|
|
.export-row:last-child {
|
|
|
|
display: flex;
|
|
|
|
border-bottom: none;
|
|
|
|
|
|
|
|
padding: 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.size-button {
|
|
|
|
.filename {
|
|
|
|
line-height: 0;
|
|
|
|
flex-basis: 72px;
|
|
|
|
opacity: 0.4;
|
|
|
|
|
|
|
|
margin-right: 10px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
.size-button:last-child {
|
|
|
|
|
|
|
|
margin-right: 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
.size-button.selected {
|
|
|
|
|
|
|
|
opacity: 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.open-button,
|
|
|
|
|
|
|
|
.save-container {
|
|
|
|
.save-container {
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
flex: 1;
|
|
|
|
flex: 1;
|
|
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
justify-content: center;
|
|
|
|
justify-content: center;
|
|
|
|
align-items: center;
|
|
|
|
align-items: center;
|
|
|
|
padding: 12px 16px;
|
|
|
|
padding: 12px 16px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.open-button {
|
|
|
|
|
|
|
|
border-right: 1px solid ${COLORS.PURPLE};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.save-container {
|
|
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
.save-container > span {
|
|
|
|
|
|
|
|
margin-bottom: 6px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
.save-container > div {
|
|
|
|
.save-container > div {
|
|
|
|
|
|
|
|
margin-top: 6px;
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
}
|
|
|
|
flex: 1;
|
|
|
|
|
|
|
|
|
|
|
|
.save-button {
|
|
|
|
|
|
|
|
opacity: 0.4;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
.save-button:first-child {
|
|
|
|
|
|
|
|
margin-right: 8px;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`}
|
|
|
|
`}
|
|
|
|
</style>
|
|
|
|
</style>
|
|
|
@ -259,4 +181,4 @@ class ExportMenu extends React.PureComponent {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export default enhanceWithClickOutside(ExportMenu)
|
|
|
|
export default ExportMenu
|
|
|
|