Mike Fix 5 years ago
parent 4ec70a2bf6
commit cdaee55f0d

@ -7,6 +7,10 @@ import { Controlled as CodeMirror } from 'react-codemirror2'
import SpinnerWrapper from './SpinnerWrapper' import SpinnerWrapper from './SpinnerWrapper'
import WindowControls from './WindowControls' import WindowControls from './WindowControls'
import Popout from './Popout'
import Button from './Button'
import ColorPicker from './ColorPicker'
import { import {
COLORS, COLORS,
LANGUAGES, LANGUAGES,
@ -17,6 +21,93 @@ import {
THEMES_HASH THEMES_HASH
} from '../lib/constants' } from '../lib/constants'
function ModifierButton(props) {
const [selected, setOpen] = React.useState(props.selected)
return (
<Button
flex={0}
padding="0"
center
margin="0 8px 0 0"
style={{ borderBottom: `1px solid ${selected ? 'white' : 'transparent'}` }}
onClick={() => setOpen(s => !s)}
>
{props.children}
</Button>
)
}
function SeletionEditor(props) {
const [open, setOpen] = React.useState(false)
const [color, setColor] = React.useState(COLORS.PRIMARY)
return (
<Popout
hidden={false}
pointerLeft="62px"
style={{
zIndex: 100,
top: props.pos.top,
left: props.pos.left
}}
>
<div className="colorizer">
<div className="modifier">
<ModifierButton flex={0}>
<b>B</b>
</ModifierButton>
<ModifierButton flex={0}>
<i>I</i>
</ModifierButton>
<ModifierButton flex={0}>
<u>U</u>
</ModifierButton>
<button className="color-square" onClick={() => setOpen(o => !o)} />
</div>
{open && (
<div className="color-picker-container">
<ColorPicker color={color} disableAlpha={true} onChange={d => setColor(d.hex)} />
</div>
)}
</div>
<style jsx>
{`
.modifier {
padding: 0px 8px;
display: flex;
}
.colorizer b {
font-weight: bold;
}
.colorizer i {
font-style: italic;
}
.colorizer :global(button) {
border-bottom: 1px solid white;
min-width: 24px;
}
.color-square {
cursor: pointer;
appearance: none;
outline: none;
border: none;
border-radius: 3px;
padding: 12px;
margin: 4px 0 4px auto;
background: ${color};
box-shadow: ${`inset 0px 0px 0px ${open ? 2 : 1}px ${COLORS.SECONDARY}`};
}
.color-picker-container {
width: 218px;
border-top: 2px solid ${COLORS.SECONDARY};
}
`}
</style>
</Popout>
)
}
const Watermark = dynamic(() => import('./svg/Watermark'), { const Watermark = dynamic(() => import('./svg/Watermark'), {
loading: () => null loading: () => null
}) })
@ -29,6 +120,7 @@ class Carbon extends React.PureComponent {
static defaultProps = { static defaultProps = {
onChange: () => {} onChange: () => {}
} }
state = {}
handleLanguageChange = debounce( handleLanguageChange = debounce(
(newCode, language) => { (newCode, language) => {
@ -94,8 +186,38 @@ class Carbon extends React.PureComponent {
const light = themeConfig && themeConfig.light const light = themeConfig && themeConfig.light
/* eslint-disable jsx-a11y/no-static-element-interactions */
const content = ( const content = (
<div className="container"> <div
className="container"
onMouseUp={() => {
if (this.currentSelection) {
// let x = this.props.editorRef.current.editor.doc.markText(
// this.currentSelection.from,
// this.currentSelection.to,
// {
// css: 'font-weight: bold'
// }
// )
const modifierOpenAt = this.props.editorRef.current.editor.charCoords(
this.currentSelection.from,
'local'
)
const modifierOpenAtEnd = this.props.editorRef.current.editor.charCoords(
this.currentSelection.to,
'local'
)
// TODO find a better more consistent way to measure
const top = modifierOpenAt.bottom + parseInt(config.paddingVertical) + 45
const left = (modifierOpenAt.left + modifierOpenAtEnd.right) / 2
this.setState({ modifierOpenAt: { ...modifierOpenAt, top, left } })
this.currentSelection = null
} else {
this.setState({ modifierOpenAt: null })
}
}}
>
{config.windowControls ? ( {config.windowControls ? (
<WindowControls <WindowControls
theme={config.windowTheme} theme={config.windowTheme}
@ -110,6 +232,31 @@ class Carbon extends React.PureComponent {
options={options} options={options}
onBeforeChange={this.onBeforeChange} onBeforeChange={this.onBeforeChange}
onGutterClick={this.props.onGutterClick} onGutterClick={this.props.onGutterClick}
onSelection={(ed, data) => {
const selection = data.ranges[0]
if (
selection.head.line === selection.anchor.line &&
selection.head.ch === selection.anchor.ch
) {
return
}
if (
selection.head.line + selection.head.ch >
selection.anchor.line + selection.anchor.ch
) {
this.currentSelection = {
from: selection.anchor,
to: selection.head
}
} else {
this.currentSelection = {
from: selection.head,
to: selection.anchor
}
}
}}
/> />
{config.watermark && <Watermark light={light} />} {config.watermark && <Watermark light={light} />}
<div className="container-bg"> <div className="container-bg">
@ -234,6 +381,7 @@ class Carbon extends React.PureComponent {
<SpinnerWrapper loading={this.props.loading}>{content}</SpinnerWrapper> <SpinnerWrapper loading={this.props.loading}>{content}</SpinnerWrapper>
<div className="twitter-png-fix" /> <div className="twitter-png-fix" />
</div> </div>
{this.state.modifierOpenAt && <SeletionEditor pos={this.state.modifierOpenAt} />}
<style jsx> <style jsx>
{` {`
.section, .section,

@ -9,13 +9,14 @@ const pickerStyle = {
margin: '0 auto 1px' margin: '0 auto 1px'
} }
const ColorPicker = ({ onChange = () => {}, color, presets, style }) => ( const ColorPicker = ({ onChange = () => {}, color, presets, style, disableAlpha }) => (
<React.Fragment> <React.Fragment>
<SketchPicker <SketchPicker
styles={{ picker: style || pickerStyle }} styles={{ picker: style || pickerStyle }}
color={color} color={color}
onChangeComplete={onChange} onChangeComplete={onChange}
presetColors={presets} presetColors={presets}
disableAlpha={disableAlpha}
/> />
<style jsx> <style jsx>
{` {`

Loading…
Cancel
Save