mirror of https://github.com/sgoudham/carbon.git
Background image settings (#169)
* Implement drag-n-drop image for backgrounds - Closes #122 * In progress * Add background-size, background-position settings * Add ReactCrop * Remove old bg sizing sliders * Add resize observer * Fix typo * Disable select on sliders * onAspectRatioChange hook * Rename to backgroundColor * Fix state issues * Add backgroundMode toggle * Rename ColorPicker * Add upload-image margin * Minor font-size change * Fix buildmain
parent
77af47b59e
commit
cbc6824b83
@ -0,0 +1,208 @@
|
||||
import React from 'react'
|
||||
import enhanceWithClickOutside from 'react-click-outside'
|
||||
import { SketchPicker } from 'react-color'
|
||||
import WindowPointer from './WindowPointer'
|
||||
import ImagePicker from './ImagePicker'
|
||||
import { COLORS } from '../lib/constants'
|
||||
import { parseRGBA, capitalizeFirstLetter } from '../lib/util'
|
||||
|
||||
class BackgroundSelect extends React.Component {
|
||||
constructor() {
|
||||
super()
|
||||
this.state = { isVisible: false, selectedTab: 'color' }
|
||||
this.toggle = this.toggle.bind(this)
|
||||
this.selectTab = this.selectTab.bind(this)
|
||||
this.handlePickColor = this.handlePickColor.bind(this)
|
||||
}
|
||||
|
||||
toggle() {
|
||||
this.setState({ isVisible: !this.state.isVisible })
|
||||
}
|
||||
|
||||
selectTab(name) {
|
||||
if (this.props.config.backgroundMode !== name) {
|
||||
this.props.onChange({ backgroundMode: name })
|
||||
}
|
||||
}
|
||||
|
||||
handleClickOutside() {
|
||||
this.setState({ isVisible: false })
|
||||
}
|
||||
|
||||
handlePickColor(color) {
|
||||
this.props.onChange({ backgroundColor: parseRGBA(color.rgb) })
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="bg-select-container">
|
||||
<div className="bg-select-display">
|
||||
<div className="bg-select-label">
|
||||
<span>BG</span>
|
||||
</div>
|
||||
<div className="bg-color-container" onClick={this.toggle}>
|
||||
<div className="bg-color-alpha" />
|
||||
<div className="bg-color" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-select-pickers" hidden={!this.state.isVisible}>
|
||||
<WindowPointer fromLeft="15px" />
|
||||
<div className="picker-tabs">
|
||||
{['color', 'image'].map((tab, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className={`picker-tab ${this.props.config.backgroundMode === tab ? 'active' : ''}`}
|
||||
onClick={this.selectTab.bind(null, tab)}
|
||||
>
|
||||
{capitalizeFirstLetter(tab)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="picker-tabs-contents">
|
||||
<div style={this.props.config.backgroundMode === 'color' ? {} : { display: 'none' }}>
|
||||
<SketchPicker
|
||||
color={this.props.config.backgroundColor}
|
||||
onChangeComplete={this.handlePickColor}
|
||||
/>
|
||||
</div>
|
||||
<div style={this.props.config.backgroundMode === 'image' ? {} : { display: 'none' }}>
|
||||
<ImagePicker
|
||||
onChange={this.props.onChange}
|
||||
imageDataURL={this.props.config.backgroundImage}
|
||||
aspectRatio={this.props.config.aspectRatio}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<style jsx>{`
|
||||
.bg-select-container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.bg-select-display {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
width: 72px;
|
||||
border: 0.5px solid ${COLORS.SECONDARY};
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.bg-select-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
height: 100%;
|
||||
padding: 0 8px;
|
||||
border-right: 0.5px solid ${COLORS.SECONDARY};
|
||||
}
|
||||
|
||||
.bg-color-container {
|
||||
position: relative;
|
||||
width: 34px;
|
||||
margin-bottom: 1px;
|
||||
background: #fff;
|
||||
border-radius: 0px 2px 2px 0px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.bg-color {
|
||||
border-radius: 0px 2px 2px 0px;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
${this.props.config.backgroundMode === 'image'
|
||||
? `background: url(${this.props.config.backgroundImage});
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;`
|
||||
: `background: ${this.props.config.backgroundColor || config.backgroundColor};
|
||||
background-size: auto;
|
||||
background-repeat: repeat;`};
|
||||
}
|
||||
|
||||
.bg-color-alpha {
|
||||
border-radius: 0px 2px 2px 0px;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMUlEQVQ4T2NkYGAQYcAP3uCTZhw1gGGYhAGBZIA/nYDCgBDAm9BGDWAAJyRCgLaBCAAgXwixzAS0pgAAAABJRU5ErkJggg==)
|
||||
left center;
|
||||
}
|
||||
|
||||
.picker-tabs {
|
||||
display: flex;
|
||||
border-bottom: 1px solid ${COLORS.SECONDARY};
|
||||
}
|
||||
|
||||
.picker-tab {
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
background: rgba(255, 255, 255, 0.165);
|
||||
width: 50%;
|
||||
text-align: center;
|
||||
padding: 8px 0;
|
||||
border-right: 1px solid ${COLORS.SECONDARY};
|
||||
}
|
||||
|
||||
.picker-tab:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.picker-tab.active {
|
||||
background: none;
|
||||
}
|
||||
|
||||
.bg-select-pickers {
|
||||
position: absolute;
|
||||
width: 222px;
|
||||
margin-left: 36px;
|
||||
margin-top: 4px;
|
||||
border: 0.5px solid ${COLORS.SECONDARY};
|
||||
border-radius: 3px;
|
||||
background: #1a1a1a;
|
||||
}
|
||||
|
||||
/* react-color overrides */
|
||||
.bg-select-pickers :global(.sketch-picker) {
|
||||
background: #1a1a1a !important;
|
||||
padding: 8px 8px 0 !important;
|
||||
margin: 0 auto 1px !important;
|
||||
}
|
||||
|
||||
.bg-select-pickers :global(.sketch-picker > div:nth-child(3) > div > div > span) {
|
||||
color: ${COLORS.SECONDARY} !important;
|
||||
}
|
||||
|
||||
/* TODO remove once base64 url issue fixed in react-color */
|
||||
/* prettier-ignore */
|
||||
.bg-select-pickers :global(.sketch-picker > div:nth-child(2) > div:nth-child(1) > div:nth-child(2) > div > div:nth-child(1) > div),
|
||||
.bg-select-pickers :global(.sketch-picker > div:nth-child(2) > div:nth-child(2) > div:nth-child(1)) {
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMUlEQVQ4T2NkYGAQYcAP3uCTZhw1gGGYhAGBZIA/nYDCgBDAm9BGDWAAJyRCgLaBCAAgXwixzAS0pgAAAABJRU5ErkJggg==)
|
||||
left center !important;
|
||||
}
|
||||
|
||||
.bg-select-pickers :global(.sketch-picker > div:nth-child(3) > div > div > input) {
|
||||
width: 100% !important;
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
border-radius: 2px;
|
||||
background: rgba(255, 255, 255, 0.165);
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
/* prettier-ignore */
|
||||
.bg-select-pickers :global(.sketch-picker > div:nth-child(2) > div:nth-child(1) > div:nth-child(2), .sketch-picker > div:nth-child(2) > div:nth-child(2)) {
|
||||
background: #fff;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default enhanceWithClickOutside(BackgroundSelect)
|
@ -1,141 +0,0 @@
|
||||
import React from 'react'
|
||||
import enhanceWithClickOutside from 'react-click-outside'
|
||||
import { SketchPicker } from 'react-color'
|
||||
import WindowPointer from './WindowPointer'
|
||||
import { COLORS } from '../lib/constants'
|
||||
import { parseRGBA } from '../lib/util'
|
||||
|
||||
class ColorPicker extends React.Component {
|
||||
constructor() {
|
||||
super()
|
||||
this.state = { isVisible: false }
|
||||
this.toggle = this.toggle.bind(this)
|
||||
this.handlePickColor = this.handlePickColor.bind(this)
|
||||
}
|
||||
|
||||
toggle() {
|
||||
this.setState({ isVisible: !this.state.isVisible })
|
||||
}
|
||||
|
||||
handleClickOutside() {
|
||||
this.setState({ isVisible: false })
|
||||
}
|
||||
|
||||
handlePickColor(color) {
|
||||
this.props.onChange(parseRGBA(color.rgb))
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="colorpicker-container">
|
||||
<div className="colorpicker-display">
|
||||
<div className="colorpicker-label">
|
||||
<span>BG</span>
|
||||
</div>
|
||||
<div className="bg-color-container" onClick={this.toggle}>
|
||||
<div className="bg-color-alpha" />
|
||||
<div className="bg-color" style={{ background: this.props.bg }} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="colorpicker-picker" hidden={!this.state.isVisible}>
|
||||
<WindowPointer fromLeft="15px" />
|
||||
<SketchPicker color={this.props.bg} onChangeComplete={this.handlePickColor} />
|
||||
</div>
|
||||
<style jsx>{`
|
||||
.colorpicker-container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.colorpicker-display {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
width: 72px;
|
||||
border: 0.5px solid ${COLORS.SECONDARY};
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.colorpicker-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
height: 100%;
|
||||
padding: 0 8px;
|
||||
border-right: 0.5px solid ${COLORS.SECONDARY};
|
||||
}
|
||||
|
||||
.bg-color-container {
|
||||
position: relative;
|
||||
width: 34px;
|
||||
margin-bottom: 1px;
|
||||
background: #fff;
|
||||
border-radius: 0px 2px 2px 0px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.bg-color {
|
||||
border-radius: 0px 2px 2px 0px;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
.bg-color-alpha {
|
||||
border-radius: 0px 2px 2px 0px;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMUlEQVQ4T2NkYGAQYcAP3uCTZhw1gGGYhAGBZIA/nYDCgBDAm9BGDWAAJyRCgLaBCAAgXwixzAS0pgAAAABJRU5ErkJggg==)
|
||||
left center;
|
||||
}
|
||||
|
||||
.colorpicker-picker {
|
||||
position: absolute;
|
||||
margin-left: 36px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
/* react-color overrides */
|
||||
.colorpicker-picker :global(.sketch-picker) {
|
||||
border: 0.5px solid ${COLORS.SECONDARY} !important;
|
||||
border-radius: 3px !important;
|
||||
background: #1a1a1a !important;
|
||||
}
|
||||
|
||||
.colorpicker-picker > :global(.sketch-picker > div:nth-child(3) > div > div > span) {
|
||||
color: ${COLORS.SECONDARY} !important;
|
||||
}
|
||||
|
||||
/* TODO remove once base64 url issue fixed in react-color */
|
||||
/* prettier-ignore */
|
||||
.colorpicker-picker > :global(.sketch-picker > div:nth-child(2) > div:nth-child(1) > div:nth-child(2) > div > div:nth-child(1) > div),
|
||||
.colorpicker-picker > :global(.sketch-picker > div:nth-child(2) > div:nth-child(2) > div:nth-child(1)) {
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMUlEQVQ4T2NkYGAQYcAP3uCTZhw1gGGYhAGBZIA/nYDCgBDAm9BGDWAAJyRCgLaBCAAgXwixzAS0pgAAAABJRU5ErkJggg==)
|
||||
left center !important;
|
||||
}
|
||||
|
||||
.colorpicker-picker > :global(.sketch-picker > div:nth-child(3) > div > div > input) {
|
||||
width: 100% !important;
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
border-radius: 2px;
|
||||
background: rgba(255, 255, 255, 0.165);
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
/* prettier-ignore */
|
||||
.colorpicker-picker :global(.sketch-picker > div:nth-child(2) > div:nth-child(1) > div:nth-child(2), .sketch-picker > div:nth-child(2) > div:nth-child(2)) {
|
||||
background: #fff;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default enhanceWithClickOutside(ColorPicker)
|
@ -0,0 +1,188 @@
|
||||
import React from 'react'
|
||||
import ReactCrop, { makeAspectCrop } from 'react-image-crop'
|
||||
import Slider from './Slider'
|
||||
import { COLORS } from '../lib/constants'
|
||||
|
||||
const getCroppedImg = (imageDataURL, pixelCrop) => {
|
||||
const canvas = document.createElement('canvas')
|
||||
canvas.width = pixelCrop.width
|
||||
canvas.height = pixelCrop.height
|
||||
const ctx = canvas.getContext('2d')
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const image = new Image()
|
||||
image.src = imageDataURL
|
||||
image.onload = () => {
|
||||
ctx.drawImage(
|
||||
image,
|
||||
pixelCrop.x,
|
||||
pixelCrop.y,
|
||||
pixelCrop.width,
|
||||
pixelCrop.height,
|
||||
0,
|
||||
0,
|
||||
pixelCrop.width,
|
||||
pixelCrop.height
|
||||
)
|
||||
|
||||
resolve(canvas.toDataURL('image/jpeg'))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const INITIAL_STATE = { crop: null, imageAspectRatio: null, pixelCrop: null }
|
||||
|
||||
export default class extends React.Component {
|
||||
constructor() {
|
||||
super()
|
||||
this.state = INITIAL_STATE
|
||||
this.selectImage = this.selectImage.bind(this)
|
||||
this.removeImage = this.removeImage.bind(this)
|
||||
this.onImageLoaded = this.onImageLoaded.bind(this)
|
||||
this.onCropChange = this.onCropChange.bind(this)
|
||||
this.onDragEnd = this.onDragEnd.bind(this)
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this.state.crop && this.props.aspectRatio != nextProps.aspectRatio) {
|
||||
// update crop for editor container aspect-ratio change
|
||||
this.setState({
|
||||
crop: makeAspectCrop(
|
||||
{
|
||||
...this.state.crop,
|
||||
aspect: nextProps.aspectRatio
|
||||
},
|
||||
this.state.imageAspectRatio
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
selectImage(e) {
|
||||
const file = e.target.files[0]
|
||||
|
||||
const reader = new FileReader()
|
||||
reader.onload = e =>
|
||||
this.props.onChange({ backgroundImage: e.target.result, backgroundImageSelection: null })
|
||||
reader.readAsDataURL(file)
|
||||
}
|
||||
|
||||
removeImage() {
|
||||
this.setState(INITIAL_STATE, () => {
|
||||
this.props.onChange({
|
||||
backgroundMode: 'color',
|
||||
backgroundImage: null,
|
||||
backgroundImageSelection: null
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
onImageLoaded(image) {
|
||||
const imageAspectRatio = image.width / image.height
|
||||
const initialCrop = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 100,
|
||||
aspect: this.props.aspectRatio
|
||||
}
|
||||
|
||||
this.setState({
|
||||
imageAspectRatio,
|
||||
crop: makeAspectCrop(initialCrop, imageAspectRatio)
|
||||
})
|
||||
}
|
||||
|
||||
onCropChange(crop, pixelCrop) {
|
||||
this.setState({
|
||||
crop: { ...crop, aspect: this.props.aspectRatio },
|
||||
pixelCrop
|
||||
})
|
||||
}
|
||||
|
||||
async onDragEnd() {
|
||||
if (this.state.pixelCrop) {
|
||||
const croppedImg = await getCroppedImg(this.props.imageDataURL, this.state.pixelCrop)
|
||||
this.props.onChange({ backgroundImageSelection: croppedImg })
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let content = (
|
||||
<div className="upload-image">
|
||||
<span>Click the button below to upload a background image</span>
|
||||
<input type="file" accept="image/x-png,image/jpeg,image/jpg" onChange={this.selectImage} />
|
||||
<style jsx>{`
|
||||
.upload-image {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
span {
|
||||
display: block;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
|
||||
if (this.props.imageDataURL) {
|
||||
content = (
|
||||
<div className="settings-container">
|
||||
<div className="image-container">
|
||||
<div className="label">
|
||||
<span>Background image</span>
|
||||
<a href="#" onClick={this.removeImage}>
|
||||
×
|
||||
</a>
|
||||
</div>
|
||||
<ReactCrop
|
||||
src={this.props.imageDataURL}
|
||||
onImageLoaded={this.onImageLoaded}
|
||||
crop={this.state.crop}
|
||||
onChange={this.onCropChange}
|
||||
onDragEnd={this.onDragEnd}
|
||||
minHeight={10}
|
||||
minWidth={10}
|
||||
keepSelection
|
||||
/>
|
||||
</div>
|
||||
<style jsx>{`
|
||||
.settings-container img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.label {
|
||||
user-select: none;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
:global(.ReactCrop__image) {
|
||||
user-select: none;
|
||||
user-drag: none;
|
||||
}
|
||||
|
||||
.image-container {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.image-container .label {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="image-picker-container">{content}</div>
|
||||
<style jsx>{`
|
||||
.image-picker-container {
|
||||
font-size: 12px;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,163 @@
|
||||
.ReactCrop {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
cursor: crosshair;
|
||||
overflow: hidden;
|
||||
max-width: 100%;
|
||||
background-color: #000; }
|
||||
.ReactCrop:focus {
|
||||
outline: none; }
|
||||
.ReactCrop--disabled {
|
||||
cursor: inherit; }
|
||||
.ReactCrop__image {
|
||||
display: block;
|
||||
max-width: 100%; }
|
||||
.ReactCrop--crop-invisible .ReactCrop__image {
|
||||
opacity: 0.5; }
|
||||
.ReactCrop__crop-selection {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
transform: translate3d(0, 0, 0);
|
||||
box-sizing: border-box;
|
||||
cursor: move;
|
||||
box-shadow: 0 0 0 9999em rgba(0, 0, 0, 0.5);
|
||||
border: 1px solid;
|
||||
border-image-source: url("data:image/gif;base64,R0lGODlhCgAKAJECAAAAAP///////wAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OEI5RDc5MTFDNkE2MTFFM0JCMDZEODI2QTI4MzJBOTIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OEI5RDc5MTBDNkE2MTFFM0JCMDZEODI2QTI4MzJBOTIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuZGlkOjAyODAxMTc0MDcyMDY4MTE4MDgzQzNDMjA5MzREQ0ZDIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjAyODAxMTc0MDcyMDY4MTE4MDgzQzNDMjA5MzREQ0ZDIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+Af/+/fz7+vn49/b19PPy8fDv7u3s6+rp6Ofm5eTj4uHg397d3Nva2djX1tXU09LR0M/OzczLysnIx8bFxMPCwcC/vr28u7q5uLe2tbSzsrGwr66trKuqqainpqWko6KhoJ+enZybmpmYl5aVlJOSkZCPjo2Mi4qJiIeGhYSDgoGAf359fHt6eXh3dnV0c3JxcG9ubWxramloZ2ZlZGNiYWBfXl1cW1pZWFdWVVRTUlFQT05NTEtKSUhHRkVEQ0JBQD8+PTw7Ojk4NzY1NDMyMTAvLi0sKyopKCcmJSQjIiEgHx4dHBsaGRgXFhUUExIREA8ODQwLCgkIBwYFBAMCAQAAIfkEBQoAAgAsAAAAAAoACgAAAhWEERkn7W3ei7KlagMWF/dKgYeyGAUAIfkEBQoAAgAsAAAAAAoACgAAAg+UYwLJ7RnQm7QmsCyVKhUAIfkEBQoAAgAsAAAAAAoACgAAAhCUYgLJHdiinNSAVfOEKoUCACH5BAUKAAIALAAAAAAKAAoAAAIRVISAdusPo3RAzYtjaMIaUQAAIfkEBQoAAgAsAAAAAAoACgAAAg+MDiem7Q8bSLFaG5il6xQAIfkEBQoAAgAsAAAAAAoACgAAAg+UYRLJ7QnQm7SmsCyVKhUAIfkEBQoAAgAsAAAAAAoACgAAAhCUYBLJDdiinNSEVfOEKoECACH5BAUKAAIALAAAAAAKAAoAAAIRFISBdusPo3RBzYsjaMIaUQAAOw==");
|
||||
border-image-slice: 1;
|
||||
border-image-repeat: repeat; }
|
||||
.ReactCrop--disabled .ReactCrop__crop-selection {
|
||||
cursor: inherit; }
|
||||
.ReactCrop__drag-handle {
|
||||
position: absolute;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
border: 1px solid rgba(255, 255, 255, 0.7);
|
||||
box-sizing: border-box;
|
||||
outline: 1px solid transparent; }
|
||||
.ReactCrop .ord-nw {
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin-top: -5px;
|
||||
margin-left: -5px;
|
||||
cursor: nw-resize; }
|
||||
.ReactCrop .ord-n {
|
||||
top: 0;
|
||||
left: 50%;
|
||||
margin-top: -5px;
|
||||
margin-left: -5px;
|
||||
cursor: n-resize; }
|
||||
.ReactCrop .ord-ne {
|
||||
top: 0;
|
||||
right: 0;
|
||||
margin-top: -5px;
|
||||
margin-right: -5px;
|
||||
cursor: ne-resize; }
|
||||
.ReactCrop .ord-e {
|
||||
top: 50%;
|
||||
right: 0;
|
||||
margin-top: -5px;
|
||||
margin-right: -5px;
|
||||
cursor: e-resize; }
|
||||
.ReactCrop .ord-se {
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
margin-bottom: -5px;
|
||||
margin-right: -5px;
|
||||
cursor: se-resize; }
|
||||
.ReactCrop .ord-s {
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
margin-bottom: -5px;
|
||||
margin-left: -5px;
|
||||
cursor: s-resize; }
|
||||
.ReactCrop .ord-sw {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
margin-bottom: -5px;
|
||||
margin-left: -5px;
|
||||
cursor: sw-resize; }
|
||||
.ReactCrop .ord-w {
|
||||
top: 50%;
|
||||
left: 0;
|
||||
margin-top: -5px;
|
||||
margin-left: -5px;
|
||||
cursor: w-resize; }
|
||||
.ReactCrop__disabled .ReactCrop__drag-handle {
|
||||
cursor: inherit; }
|
||||
.ReactCrop__drag-bar {
|
||||
position: absolute; }
|
||||
.ReactCrop__drag-bar.ord-n {
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 6px;
|
||||
margin-top: -3px; }
|
||||
.ReactCrop__drag-bar.ord-e {
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 6px;
|
||||
height: 100%;
|
||||
margin-right: -3px; }
|
||||
.ReactCrop__drag-bar.ord-s {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 6px;
|
||||
margin-bottom: -3px; }
|
||||
.ReactCrop__drag-bar.ord-w {
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 6px;
|
||||
height: 100%;
|
||||
margin-left: -3px; }
|
||||
.ReactCrop--new-crop .ReactCrop__drag-bar,
|
||||
.ReactCrop--new-crop .ReactCrop__drag-handle,
|
||||
.ReactCrop--fixed-aspect .ReactCrop__drag-bar {
|
||||
display: none; }
|
||||
.ReactCrop--fixed-aspect .ReactCrop__drag-handle.ord-n,
|
||||
.ReactCrop--fixed-aspect .ReactCrop__drag-handle.ord-e,
|
||||
.ReactCrop--fixed-aspect .ReactCrop__drag-handle.ord-s,
|
||||
.ReactCrop--fixed-aspect .ReactCrop__drag-handle.ord-w {
|
||||
display: none; }
|
||||
@media (max-width: 768px) {
|
||||
.ReactCrop__drag-handle {
|
||||
width: 17px;
|
||||
height: 17px; }
|
||||
.ReactCrop .ord-nw {
|
||||
margin-top: -9px;
|
||||
margin-left: -9px; }
|
||||
.ReactCrop .ord-n {
|
||||
margin-top: -9px;
|
||||
margin-left: -9px; }
|
||||
.ReactCrop .ord-ne {
|
||||
margin-top: -9px;
|
||||
margin-right: -9px; }
|
||||
.ReactCrop .ord-e {
|
||||
margin-top: -9px;
|
||||
margin-right: -9px; }
|
||||
.ReactCrop .ord-se {
|
||||
margin-bottom: -9px;
|
||||
margin-right: -9px; }
|
||||
.ReactCrop .ord-s {
|
||||
margin-bottom: -9px;
|
||||
margin-left: -9px; }
|
||||
.ReactCrop .ord-sw {
|
||||
margin-bottom: -9px;
|
||||
margin-left: -9px; }
|
||||
.ReactCrop .ord-w {
|
||||
margin-top: -9px;
|
||||
margin-left: -9px; }
|
||||
.ReactCrop__drag-bar.ord-n {
|
||||
height: 14px;
|
||||
margin-top: -7px; }
|
||||
.ReactCrop__drag-bar.ord-e {
|
||||
width: 14px;
|
||||
margin-right: -7px; }
|
||||
.ReactCrop__drag-bar.ord-s {
|
||||
height: 14px;
|
||||
margin-bottom: -7px; }
|
||||
.ReactCrop__drag-bar.ord-w {
|
||||
width: 14px;
|
||||
margin-left: -7px; } }
|
Loading…
Reference in New Issue