├── .babelrc
├── .gitignore
├── .npmignore
├── .prettierrc
├── LICENSE
├── README.md
├── docs
├── bundle.js
└── index.html
├── examples
├── CustomExample.js
├── SingleExample.js
├── SwatchesExample.js
├── index.js
└── styles.css
├── index.html
├── package.json
├── src
├── components
│ ├── ColorPicker.js
│ ├── Draggable.js
│ ├── Map.js
│ └── Slider.js
└── index.js
├── webpack.config.js
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["@babel/env", "@babel/react"],
3 | "plugins": ["@babel/plugin-proposal-export-default-from"]
4 | }
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | npm-debug.log
3 | /dist
4 | /lib
5 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | examples/
2 | src/
3 | docs/
4 | .babelrc
5 | Makefile
6 | webpack.config.js
7 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": false,
3 | "singleQuote": true,
4 | "trailingComma": "es5"
5 | }
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2016 Lionel T.
5 | Copyright (c) 2014 Nick Williams
6 | Copyright (c) 2014 George Czabania
7 |
8 | Permission is hereby granted, free of charge, to any person obtaining a copy
9 | of this software and associated documentation files (the "Software"), to deal
10 | in the Software without restriction, including without limitation the rights
11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | copies of the Software, and to permit persons to whom the Software is
13 | furnished to do so, subject to the following conditions:
14 |
15 | The above copyright notice and this permission notice shall be included in
16 | all copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | THE SOFTWARE.
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ColoReact
2 |
3 | A tiny **Color Picker** for **React** [ [Demo](https://elrumordelaluz.github.io/coloreact/) ]
4 |
5 |
6 | ### Install
7 |
8 | ```
9 | $ npm i --save coloreact
10 | ```
11 |
12 | ### How to use
13 |
14 | ```js
15 |
16 | import ColorPicker from 'coloreact';
17 |
18 | // ...
19 | return (
20 |
25 | );
26 | // ...
27 |
28 | ```
29 |
30 | ### Custom Parts
31 |
32 | It is possible to create your own _ColorPicker_ using `Map` and `Slider`s.
33 |
34 |
35 | ```js
36 | import { Map, Slider } from 'coloreact';
37 |
38 | // ...
39 | return (
40 |
41 |
48 |
54 |
55 | // ...
56 |
57 |
58 | ```
59 |
60 | ### Examples
61 |
62 | [Live examples](https://elrumordelaluz.github.io/coloreact/) |
63 | [Code](https://github.com/elrumordelaluz/coloreact/tree/master/examples)
64 |
65 | ```
66 | $ npm start
67 | # goto http://localhost:3040/
68 | ```
69 |
70 | ### License and Attribution
71 |
72 | The project start as a derivate of the awesome [react-simple-colorpicker](https://github.com/WickyNilliams/react-simple-colorpicker) which is based on [react-colorpicker](https://github.com/stayradiated/react-colorpicker). Licensed MIT.
73 |
74 | ### Docs
75 |
76 | coming soon
77 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ColoReact ~ Demo
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/examples/CustomExample.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { Slider, Map } from '../src'
3 | import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
4 | import { atomDark } from 'react-syntax-highlighter/dist/esm/styles/prism'
5 | import tinycolor from 'tinycolor2'
6 |
7 | class CustomExample extends Component {
8 | constructor(props) {
9 | super(props)
10 | this.state = {
11 | h: 155,
12 | s: 50,
13 | v: 50,
14 | mapActive: false,
15 | sliderActive: false,
16 | }
17 | this._sv = this._sv.bind(this)
18 | this._h = this._h.bind(this)
19 | this.resetActive = this.resetActive.bind(this)
20 | }
21 |
22 | _sv(s, v) {
23 | this.setState({ s, v, mapActive: true })
24 | }
25 |
26 | _h(h) {
27 | this.setState({ h, sliderActive: true })
28 | }
29 |
30 | resetActive() {
31 | this.setState({
32 | mapActive: false,
33 | sliderActive: false,
34 | })
35 | }
36 |
37 | getHue() {
38 | const color = tinycolor(`hsv(${this.state.h}, 100, 100)`)
39 | // return u.toRgbString([this.state.h, 100, 100]);
40 | return color.toRgbString()
41 | }
42 |
43 | render() {
44 | const color = tinycolor(
45 | `hsv(${this.state.h}, ${this.state.s}, ${this.state.v})`
46 | )
47 | const rgb = color.toRgbString()
48 | return (
49 |
50 |
Custom ColorPicker
51 |
59 |
86 |
114 |
115 |
116 | {`import { Map, Slider } from 'coloreact';
117 |
118 |
127 |
128 | `}
136 |
137 |
141 | Source
142 | {' '}
143 | |{' '}
144 |
148 | Edit
149 |
150 |
151 | )
152 | }
153 | }
154 |
155 | export default CustomExample
156 |
--------------------------------------------------------------------------------
/examples/SingleExample.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ColorPicker from '../src'
3 | import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
4 | import { atomDark } from 'react-syntax-highlighter/dist/esm/styles/prism'
5 |
6 | const SingleExample = () => {
7 | return (
8 |
9 |
Single ColorPicker
10 |
console.log('single-example color:', color.hex)}
19 | />
20 |
21 | {`import ColorPicker from 'coloreact';
22 | console.log(color.hex)} />`}
23 |
24 |
28 | Source
29 | {' '}
30 | |{' '}
31 |
35 | Edit
36 |
37 |
38 | )
39 | }
40 |
41 | export default SingleExample
42 |
--------------------------------------------------------------------------------
/examples/SwatchesExample.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import ColorPicker from '../src'
3 | import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
4 | import { atomDark } from 'react-syntax-highlighter/dist/esm/styles/prism'
5 |
6 | class SwatchesExample extends Component {
7 | constructor(props) {
8 | super(props)
9 | this.state = {
10 | swatches: [
11 | 'rgb(157, 41, 177)',
12 | '#673AB7',
13 | 'rgba(182, 73, 98, 1)',
14 | '#00BCD4',
15 | 'LightSeaGreen',
16 | 'rgb(76, 175, 80)',
17 | 'rgba(8, 136, 124, .7)',
18 | '#CDDC39',
19 | ],
20 | selected: 5,
21 | }
22 | this.selectSwatch = this.selectSwatch.bind(this)
23 | this.handleChange = this.handleChange.bind(this)
24 | }
25 |
26 | selectSwatch(selected) {
27 | this.setState({
28 | selected,
29 | })
30 | }
31 |
32 | handleChange(color) {
33 | const swatches = [...this.state.swatches]
34 | swatches[this.state.selected] = color.rgbString
35 | this.setState({
36 | swatches,
37 | })
38 | }
39 |
40 | render() {
41 | const actualColor = this.state.swatches[this.state.selected]
42 | return (
43 |
44 |
ColorPicker with Swatches
45 |
46 | {this.state.swatches.map((col, i) => (
47 | - this.selectSwatch(i)}
52 | />
53 | ))}
54 |
55 |
56 | {actualColor}
57 |
58 |
69 |
70 | {`import ColorPicker from 'coloreact';
71 | `}
75 |
76 |
80 | Source
81 | {' '}
82 | |{' '}
83 |
87 | Edit
88 |
89 |
90 | )
91 | }
92 | }
93 |
94 | export default SwatchesExample
95 |
--------------------------------------------------------------------------------
/examples/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import ReactDOM from 'react-dom';
3 | import Styles from './styles.css';
4 | import ColorPicker, { Slider, Map } from '../src';
5 |
6 | import SingleExample from './SingleExample';
7 | import SwatchesExample from './SwatchesExample';
8 | import CustomExample from './CustomExample';
9 |
10 | class App extends Component {
11 | constructor (props) {
12 | super(props);
13 | }
14 |
15 | render () {
16 | return (
17 |
28 | );
29 | }
30 | }
31 |
32 | ReactDOM.render(, document.querySelector('.container'));
33 |
--------------------------------------------------------------------------------
/examples/styles.css:
--------------------------------------------------------------------------------
1 | @import url(https://fonts.googleapis.com/css?family=Ubuntu+Mono);
2 |
3 | body {
4 | font-family: 'Ubuntu Mono', monospace;
5 | background-color: #f2f2f2;
6 | }
7 |
8 | pre,
9 | code {
10 | font-family: 'Ubuntu Mono', monospace;
11 | }
12 |
13 | pre {
14 | padding: .75rem 1rem !important;
15 | }
16 |
17 | pre code {
18 | line-height: 1.5;
19 | }
20 |
21 | .examples {
22 | margin-left: 10vw;
23 | margin-right: 10vw;
24 | }
25 |
26 | .examples-header {
27 | margin-bottom: 2.5em;
28 | }
29 |
30 | .example {
31 | padding: 1em 2em;
32 | border-radius: .3em;
33 | background-color: rgba(255,255,255,.5);
34 | margin-bottom: 2.5em;
35 | }
36 |
37 | .example h3 {
38 | text-align: center;;
39 | }
40 |
41 | .example__codeLink {
42 | display: inline-block;
43 | text-decoration: none;
44 | color: inherit;
45 | }
46 |
47 | .example__codeLink:hover {
48 | text-decoration: underline;
49 | }
50 |
51 | .main-title a {
52 | text-decoration: none;
53 | color: inherit;
54 | }
55 |
56 | .swatches {
57 | list-style: none;
58 | padding: 0;
59 | margin: 0;
60 | text-align: center;
61 | }
62 | .swatches li {
63 | cursor: pointer;
64 | display: inline-block;
65 | height: 2em;
66 | margin: 1px;
67 | border-width: 3px;
68 | border-style: solid;
69 | border-color: transparent;
70 | width: 2em;
71 | transition: box-shadow .3s;
72 | }
73 |
74 | .swatches li:hover {
75 | box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23);
76 | }
77 |
78 | .swatches li.selected {
79 | box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23);
80 | }
81 |
82 | .swatch-value {
83 | opacity: .5;
84 | display: block;
85 | text-align: center;
86 | padding: 1em;
87 | }
88 |
89 |
90 | @keyframes moveLeftRight {
91 | to {
92 | transform: translateX(50%);
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ColoReact ~ Demo
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "coloreact",
3 | "version": "0.3.2",
4 | "description": "A tiny Color Picker for React",
5 | "main": "lib/index.js",
6 | "scripts": {
7 | "prepublish": "npm run lib",
8 | "start": "webpack-dev-server --mode development --open",
9 | "lib": "NODE_ENV=production babel -d lib/ src/",
10 | "build": "webpack --mode production"
11 | },
12 | "keywords": [
13 | "color-picker",
14 | "react",
15 | "color"
16 | ],
17 | "author": "Lionel T (elrumordelaluz.com)",
18 | "license": "MIT",
19 | "repository": {
20 | "type": "git",
21 | "url": "https://github.com/elrumordelaluz/coloreact"
22 | },
23 | "devDependencies": {
24 | "@babel/cli": "7.6.2",
25 | "@babel/core": "7.6.2",
26 | "@babel/plugin-proposal-export-default-from": "7.5.2",
27 | "@babel/preset-env": "7.6.2",
28 | "@babel/preset-react": "7.0.0",
29 | "babel-loader": "8.0.6",
30 | "css-loader": "3.2.0",
31 | "mini-css-extract-plugin": "0.8.0",
32 | "prop-types": "15.7.2",
33 | "react": "16.10.1",
34 | "react-dom": "16.10.1",
35 | "react-syntax-highlighter": "11.0.2",
36 | "style-loader": "1.0.0",
37 | "webpack": "4.41.0",
38 | "webpack-cli": "3.3.9",
39 | "webpack-dev-server": "3.8.1"
40 | },
41 | "dependencies": {
42 | "hoist-non-react-statics": "3.3.0",
43 | "lodash.throttle": "4.1.1",
44 | "tinycolor2": "^1.3.0"
45 | },
46 | "peerDependencies": {
47 | "react": ">= 15.6.1"
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/components/ColorPicker.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import PropTypes from 'prop-types'
3 | import Slider from './Slider'
4 | import Map from './Map'
5 | import throttle from 'lodash.throttle'
6 | import tinycolor from 'tinycolor2'
7 |
8 | class ColorPicker extends Component {
9 | constructor(props) {
10 | super(props)
11 | const c = tinycolor(this.props.color).toHsv()
12 | this.state = {
13 | color: this.toPercentage(c),
14 | }
15 |
16 | this.throttle = throttle(function(fn, data) {
17 | fn(data)
18 | }, 100)
19 |
20 | this.handleSaturationValueChange = this.handleSaturationValueChange.bind(
21 | this
22 | )
23 | this.handleHueChange = this.handleHueChange.bind(this)
24 | this.handleAlphaChange = this.handleAlphaChange.bind(this)
25 | this.showLastValue = this.showLastValue.bind(this)
26 | }
27 |
28 | componentWillReceiveProps(nextProps) {
29 | if (!tinycolor.equals(nextProps.color, this.state.color)) {
30 | const c = tinycolor(nextProps.color).toHsv()
31 | this.setState({
32 | color: this.toPercentage(c),
33 | })
34 | }
35 | }
36 |
37 | toPercentage(hsv) {
38 | const { h, s, v, a } = hsv
39 | return {
40 | h,
41 | s: s * 100,
42 | v: v * 100,
43 | a,
44 | }
45 | }
46 |
47 | handleHueChange(h) {
48 | const { s, v, a } = this.state.color
49 | this.update({ h, s, v, a })
50 | }
51 |
52 | handleSaturationValueChange(s, v) {
53 | const { h, a } = this.state.color
54 | this.update({ h, s, v, a })
55 | }
56 |
57 | handleAlphaChange(a) {
58 | const { h, s, v } = this.state.color
59 | this.update({ h, s, v, a })
60 | }
61 |
62 | getAlpha() {
63 | return this.state.color.a === undefined ? 1 : this.state.color.a
64 | }
65 |
66 | getBackgroundHue() {
67 | return tinycolor({
68 | h: this.state.color.h,
69 | s: 100,
70 | v: 100,
71 | }).toRgbString()
72 | }
73 |
74 | getBackgroundGradient() {
75 | const { h, s, v } = this.state.color
76 | const opaque = tinycolor({
77 | h,
78 | s,
79 | v,
80 | a: 1,
81 | }).toRgbString()
82 | return `linear-gradient(to right, rgba(0,0,0,0) 0%, ${opaque} 100%)`
83 | }
84 |
85 | update(color) {
86 | this.setState({ color }, () => {
87 | this.throttle(this.props.onChange, this.output())
88 | })
89 | }
90 |
91 | output() {
92 | const c = tinycolor(this.state.color)
93 | return {
94 | hsl: c.toHsl(),
95 | hex: c.toHex(),
96 | hexString: c.toHexString(),
97 | rgb: c.toRgb(),
98 | rgbString: c.toRgbString(),
99 | }
100 | }
101 |
102 | showLastValue() {
103 | this.props.onComplete && this.props.onComplete(this.output())
104 | }
105 |
106 | render() {
107 | const { h, s, v, a } = this.state.color
108 | return (
109 |
113 |
142 |
143 | {this.props.opacity && (
144 |
170 | )}
171 |
172 |
189 |
190 | )
191 | }
192 | }
193 |
194 | ColorPicker.propTypes = {
195 | color: PropTypes.string.isRequired,
196 | onChange: PropTypes.func.isRequired,
197 | onComplete: PropTypes.func,
198 | }
199 |
200 | ColorPicker.defaultProps = {
201 | color: 'rgba(0,0,0,1)',
202 | }
203 |
204 | export default ColorPicker
205 |
--------------------------------------------------------------------------------
/src/components/Draggable.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import PropTypes from 'prop-types'
3 | import ReactDOM from 'react-dom'
4 | import hoistStatics from 'hoist-non-react-statics'
5 | import throttle from 'lodash.throttle'
6 |
7 | const noop = () => {}
8 | const getDocument = element => element.ownerDocument
9 | const clamp = (val, min, max) => Math.min(Math.max(val, min), max)
10 | const getDisplayName = WrappedComponent => {
11 | return WrappedComponent.displayName || WrappedComponent.name || 'Component'
12 | }
13 |
14 | export default function draggable(options = {}) {
15 | return function wrappedInDraggable(WrappedComponent) {
16 | class Draggable extends Component {
17 | constructor(props) {
18 | super(props)
19 |
20 | this.state = { active: false }
21 |
22 | this.throttle = throttle((fn, data) => fn(data), 30)
23 | this.getPercentageValue = this.getPercentageValue.bind(this)
24 | this.startUpdates = this.startUpdates.bind(this)
25 | this.handleUpdate = this.handleUpdate.bind(this)
26 | this.stopUpdates = this.stopUpdates.bind(this)
27 | this.getPosition = this.getPosition.bind(this)
28 | this.getScaledValue = this.getScaledValue.bind(this)
29 | this.updateBoundingRect = this.updateBoundingRect.bind(this)
30 | this.updatePosition = this.updatePosition.bind(this)
31 | }
32 |
33 | componentDidMount() {
34 | this.document = getDocument(ReactDOM.findDOMNode(this))
35 | const window = (this.window = this.document.defaultView)
36 |
37 | window.addEventListener('resize', this.updateBoundingRect)
38 | window.addEventListener('scroll', this.updateBoundingRect)
39 |
40 | this.updateBoundingRect()
41 | }
42 |
43 | componentWillUnmount() {
44 | const { window } = this
45 | window.removeEventListener('resize', this.updateBoundingRect)
46 | window.removeEventListener('scroll', this.updateBoundingRect)
47 | }
48 |
49 | startUpdates(e) {
50 | const { document } = this
51 | e.preventDefault()
52 |
53 | const rect = this.updateBoundingRect()
54 | document.addEventListener('mousemove', this.handleUpdate)
55 | document.addEventListener('touchmove', this.handleUpdate)
56 | document.addEventListener('mouseup', this.stopUpdates)
57 | document.addEventListener('touchend', this.stopUpdates)
58 |
59 | const { x, y } = this.getPosition(e)
60 | this.setState({ active: true })
61 | this.updatePosition({ x, y }, rect)
62 | // this.throttle(this.updatePosition, { x, y });
63 | }
64 |
65 | handleUpdate(e) {
66 | if (this.state.active) {
67 | e.preventDefault()
68 | const { x, y } = this.getPosition(e)
69 | this.updatePosition({ x, y })
70 | // this.throttle(this.updatePosition, { x, y });
71 | }
72 | }
73 |
74 | stopUpdates() {
75 | if (this.state.active) {
76 | const { document } = this
77 |
78 | document.removeEventListener('mousemove', this.handleUpdate)
79 | document.removeEventListener('touchmove', this.handleUpdate)
80 | document.removeEventListener('mouseup', this.stopUpdates)
81 | document.removeEventListener('touchend', this.stopUpdates)
82 |
83 | this.props.onComplete()
84 | this.setState({ active: false })
85 | }
86 | }
87 |
88 | updatePosition({ x: clientX, y: clientY }, rect = this.state.rect) {
89 | if (options.single) {
90 | const value = this.props.vertical
91 | ? (rect.bottom - clientY) / rect.height
92 | : (clientX - rect.left) / rect.width
93 | return this.props.onChange(this.getScaledValue(value))
94 | }
95 |
96 | const x = (clientX - rect.left) / rect.width
97 | const y = (rect.bottom - clientY) / rect.height
98 | return this.props.onChange(
99 | this.getScaledValue(x),
100 | this.getScaledValue(y)
101 | )
102 | }
103 |
104 | getPosition(e) {
105 | if (e.touches) {
106 | e = e.touches[0]
107 | }
108 |
109 | return {
110 | x: e.clientX,
111 | y: e.clientY,
112 | }
113 | }
114 |
115 | getPercentageValue(value) {
116 | return (value / this.props.max) * 100 + '%'
117 | }
118 |
119 | getScaledValue(value) {
120 | return clamp(value, 0, 1) * this.props.max
121 | }
122 |
123 | /**
124 | * Findout the bounding rect - update state to send the rect to WrappedComponent
125 | * @return {Object} Returns rect for additional logic
126 | */
127 | updateBoundingRect() {
128 | const rect = ReactDOM.findDOMNode(this).getBoundingClientRect()
129 | this.setState({ rect })
130 | return rect
131 | }
132 |
133 | render() {
134 | return (
135 |
141 | )
142 | }
143 | }
144 |
145 | Draggable.displayName = `draggable(${getDisplayName(WrappedComponent)})`
146 | Draggable.WrappedComponent = WrappedComponent
147 | Draggable.propTypes = {
148 | onChange: PropTypes.func.isRequired,
149 | onComplete: PropTypes.func,
150 | max: PropTypes.number,
151 | }
152 | Draggable.defaultProps = {
153 | onChange: noop,
154 | onComplete: noop,
155 | max: 1,
156 | }
157 |
158 | return hoistStatics(Draggable, WrappedComponent)
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/src/components/Map.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import draggable from './Draggable';
4 |
5 | class Map extends Component {
6 | getMapStyles () {
7 | const { map, mapActive } = Map.defaultStyles;
8 | return Object.assign({},
9 | map,
10 | this.props.style && this.props.style,
11 | this.props.active && mapActive
12 | );
13 | }
14 |
15 | getPointerStyles () {
16 | const { pointer, pointerDark, pointerLight } = Map.defaultStyles;
17 | return Object.assign({},
18 | pointer,
19 | this.props.pointerStyle && this.props.pointerStyle,
20 | {
21 | left: this.props.getPercentageValue(this.props.x),
22 | bottom: this.props.getPercentageValue(this.props.y)
23 | },
24 | );
25 | }
26 |
27 | getBgStyles () {
28 | const { bg } = Map.defaultStyles;
29 | const { backgroundColor } = this.props;
30 | return Object.assign({}, bg, { backgroundColor });
31 | }
32 |
33 | render () {
34 | const { bgOverlay } = Map.defaultStyles;
35 | return (
36 |
41 |
42 |
43 |
44 |
45 |
46 | { this.props.rect && (
47 |
48 | )}
49 |
50 | );
51 | }
52 | }
53 |
54 | Map.propTypes = {
55 | x: PropTypes.number.isRequired,
56 | y: PropTypes.number.isRequired,
57 | backgroundColor: PropTypes.string,
58 | className: PropTypes.string,
59 | };
60 |
61 | Map.defaultProps = {
62 | x: 0,
63 | y: 0,
64 | backgroundColor: 'transparent',
65 | className: 'Map',
66 | };
67 |
68 | Map.defaultStyles = {
69 | // Map
70 | map: {
71 | position: 'absolute',
72 | top: 0,
73 | bottom: 0,
74 | right: 0,
75 | left: 0,
76 | overflow: 'hidden',
77 | userSelect: 'none',
78 | },
79 | mapActive: {
80 | cursor: 'none',
81 | },
82 |
83 | // Pointer
84 | pointer: {
85 | position: 'absolute',
86 | width: 10,
87 | height: 10,
88 | marginLeft: -5,
89 | marginBottom: -5,
90 | borderRadius: '100%',
91 | border: '1px solid',
92 | willChange: 'auto',
93 | },
94 |
95 | // Background
96 | bg: {
97 | top: 0,
98 | left: 0,
99 | position: 'absolute',
100 | height: '100%',
101 | width: '100%',
102 | },
103 | bgOverlay: {
104 | display: 'block',
105 | position: 'absolute',
106 | top: 0,
107 | left: 0,
108 | bottom: 0,
109 | right: 0,
110 | background: `linear-gradient(to bottom, rgba(0,0,0,0) 0%,rgba(0,0,0,1) 100%),
111 | linear-gradient(to right, rgba(255,255,255,1) 0%,rgba(255,255,255,0) 100%)`,
112 | },
113 | };
114 |
115 | export default draggable()(Map);
116 |
--------------------------------------------------------------------------------
/src/components/Slider.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import draggable from './Draggable';
4 |
5 | class Slider extends Component {
6 | getPointerStyles() {
7 | const { pointer } = Slider.defaultStyles;
8 | const attr = this.props.vertical ? 'bottom' : 'left';
9 | return Object.assign({},
10 | pointer,
11 | this.props.pointerStyle && this.props.pointerStyle,
12 | {
13 | [attr]: this.props.getPercentageValue(this.props.value)
14 | },
15 | );
16 | }
17 |
18 | getSliderStyles () {
19 | const { slider, verticalSlider, horizontalSlider } = Slider.defaultStyles;
20 | return Object.assign({},
21 | slider,
22 | this.props.vertical && verticalSlider,
23 | !this.props.vertical && horizontalSlider,
24 | this.props.style && this.props.style,
25 | );
26 | }
27 |
28 | getTrackStyles () {
29 | const { track, horizontalTrack, verticalTrack, opacityTrack, hueTrack } = Slider.defaultStyles;
30 | const background = this.props.background;
31 | return Object.assign({},
32 | track,
33 | this.props.vertical && verticalTrack,
34 | !this.props.vertical && horizontalTrack,
35 | this.props.trackStyle && this.props.trackStyle,
36 | this.props.background && { background: this.props.background },
37 | );
38 | }
39 |
40 | render () {
41 | const { opacitySlider, opacitySlider__track }= Slider.defaultStyles;
42 | return (
43 |
48 |
49 |
50 |
51 | { this.props.rect && (
52 |
53 | )}
54 |
55 | );
56 | }
57 | }
58 |
59 | Slider.propTypes = {
60 | value: PropTypes.number.isRequired,
61 | background: PropTypes.string,
62 | };
63 |
64 | Slider.defaultProps = {
65 | value: 0,
66 | background: '',
67 | };
68 |
69 | Slider.defaultStyles = {
70 | // Slider
71 | slider: {
72 | position: 'absolute',
73 | userSelect: 'none',
74 | },
75 | horizontalSlider: {
76 | height: 8,
77 | left: 0,
78 | right: 0,
79 | height: 10,
80 | cursor: 'ew-resize',
81 | },
82 | verticalSlider: {
83 | top: 0,
84 | bottom: 0,
85 | width: 10,
86 | cursor: 'ns-resize',
87 | },
88 |
89 | // Track
90 | track: {
91 | background: '#efefef',
92 | position: 'absolute',
93 | },
94 | horizontalTrack: {
95 | height: '100%',
96 | left: 0,
97 | right: 0,
98 | },
99 | verticalTrack: {
100 | bottom: 0,
101 | top: 0,
102 | width: '100%',
103 | },
104 |
105 | // Pointer
106 | pointer: {
107 | position: 'absolute',
108 | bottom: '50%',
109 | left: '50%',
110 | width: 16,
111 | height: 16,
112 | marginLeft: -8,
113 | marginBottom: -8,
114 | background: '#efefef',
115 | willChange: 'auto',
116 | },
117 | };
118 |
119 | export default draggable({ single: true })(Slider);
120 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import ColorPicker from './components/ColorPicker';
2 | export Slider from './components/Slider';
3 | export Map from './components/Map';
4 |
5 | export default ColorPicker;
6 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const MiniCssExtractPlugin = require('mini-css-extract-plugin')
2 | const path = require('path')
3 |
4 | module.exports = {
5 | entry: {
6 | app: ['./examples/index.js'],
7 | },
8 | output: {
9 | path: path.join(__dirname, './docs'),
10 | publicPath: '/docs',
11 | filename: 'bundle.js',
12 | library: 'coloreact',
13 | libraryTarget: 'umd',
14 | },
15 | module: {
16 | rules: [
17 | {
18 | test: /\.js$/,
19 | exclude: /node_modules/,
20 | loader: 'babel-loader',
21 | },
22 | {
23 | test: /\.css$/,
24 | use: ['style-loader', 'css-loader'],
25 | },
26 | ],
27 | },
28 | resolve: {
29 | modules: [path.join(__dirname, 'src'), 'node_modules'],
30 | },
31 | plugins: [
32 | new MiniCssExtractPlugin({
33 | filename: '[name].css',
34 | }),
35 | ],
36 | optimization: {
37 | minimize: true,
38 | },
39 | devServer: {
40 | historyApiFallback: true,
41 | contentBase: './',
42 | },
43 | }
44 |
--------------------------------------------------------------------------------