diff --git a/.gitignore b/.gitignore index 582b19e..7e30ed6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ -.DS_Store node_modules -.sass-cache +package-lock.json +src/assets/svg-sprite-symbol/ +.tarima +.nvmrc +.ruby-version +.DS_Store diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..672f679 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,38 @@ +# Changelog + +## [Unreleased] + +## [0.1.0] [#1](../../pull/1) - 2020-02-18 +### Added +- HWB color model +- feColorMatrix’s values +- Default initial `#FFFFFF` color +- History navigation +- Random color button +- [`Simonwep/pickr`](https://github.com/Simonwep/pickr) color picker +- [`sindresorhus/copy-text-to-clipboard`](https://github.com/sindresorhus/copy-text-to-clipboard) +- Copied to clipboard feedback +- CSS Variables to update the UI +- Favicons and site.webmanifest + +### Changed +- Start using [`tacoss/tarima`](https://github.com/tacoss/tarima) for pre-processing + - [`postcss`](https://github.com/postcss/postcss), [`rollup`](https://github.com/rollup/rollup), [`buble`](https://github.com/bublejs/buble) +- Start using [`Qix-/color`](https://github.com/Qix-/color) for color conversion and manipulation +- Overall design + +### Removed +- Grunt, bower and [`noeldelgado/values.js`](https://github.com/noeldelgado/values.js) + +## 2014-09-16 +- [hsl support](10daf75e196ef6fb45dc78857a81309d2155cda6) + +## [1c53e9d](https://github.com/noeldelgado/yacc/commit/1c53e9d2426c8e4fcd5ef9a062fc9baaca8039a5) - 2014-03-04 +- hash based url +- disable HSL input + +## 2013-10-03 +- Initial release + +[Unreleased]: https://github.com/noeldelgado/yacc/compare/v0.1.0...HEAD +[0.1.0]: https://github.com/noeldelgado/yacc/releases/tag/v0.1.0 \ No newline at end of file diff --git a/Gruntfile.js b/Gruntfile.js deleted file mode 100644 index 9932e87..0000000 --- a/Gruntfile.js +++ /dev/null @@ -1,44 +0,0 @@ -module.exports = (grunt) => { - - grunt.initConfig({ - pkg: grunt.file.readJSON('package.json'), - - sass: { - dist: { - options: { - style: 'compact' - }, - files: { - 'source/stylesheets/project.css': 'source/sass/project.scss' - } - } - }, - - watch: { - css: { - files: ['source/sass/**/*.scss'], - tasks: ['sass'], - options: { - livereload: true - } - }, - js: { - files: ['source/javascripts/*.js'], - tasks: [], - options: { - livereload: true - } - }, - docs: { - files: ['index.html'], - tasks: [], - options: { - livereload: true - } - } - } - }); - - require('load-grunt-tasks')(grunt); - grunt.registerTask('default', ['watch']); -}; diff --git a/README.md b/README.md index b421bf0..5c6f9f8 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,29 @@ -## Color Converter +## yet another color converter -Convert HEX/RGB/HSL color formats. +Convert HEX/RGB/HSL/HWB color models plus feColorMatrix’s values -https://noeldelgado.github.io/color-converter/ +https://noeldelgado.github.io/yacc/ -This micro tool was built using [Values.js](https://github.com/noeldelgado/Values.js). +### Development +Start server on port 3000 with livereload watching files on the `src` folder + +```sh +npm install +npm start +``` + +#### SVG sprite +If you need to add a new `.svg` files to the svg sprite located after the `body` tag: + +- Place your `.svg`’s files on the `src/assets/svg` folder +- Make sure you have `svg-sprite` installed, e.i.: `npm i -g svg-sprite` +- Run npm script `npm run svg` + - That should generate a new file at `src/assets/svg-sprite-symbol/svg/sprite.symbol.svg` (ignored by `.gitignore`’s rule) +- Copy the contents of that file and replace the `svg` line after the `body` 🙈 + +### Build +To minify the `build/{js,css}/main.` files. Make sure you have `uglify` installed, e.i.: `npm i -g uglify` and then + +```sh +npm run build +``` diff --git a/bower.json b/bower.json deleted file mode 100644 index aad7a25..0000000 --- a/bower.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "color-converter", - "version": "0.0.1", - "homepage": "https://github.com/noeldelgado/color-converter", - "authors": [ - "Noel Delgado " - ], - "license": "MIT", - "private": true, - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "test", - "tests" - ], - "dependencies": { - "values.js": "~1.0.1", - "syringe.js": "~0.4.0" - } -} diff --git a/bower_components/syringe.js/.bower.json b/bower_components/syringe.js/.bower.json deleted file mode 100644 index 867cb65..0000000 --- a/bower_components/syringe.js/.bower.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "syringe.js", - "version": "0.4.0", - "main": "syringe.js", - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "tests", - "src", - "test", - "Gruntfile.js", - "LICENSE", - "package.json" - ], - "homepage": "https://github.com/noeldelgado/Syringe.js", - "authors": [ - "Noel Delgado " - ], - "description": "Inject additional CSS at runtime", - "keywords": [ - "syringe", - "injection", - "css" - ], - "license": "MIT", - "_release": "0.4.0", - "_resolution": { - "type": "version", - "tag": "v0.4.0", - "commit": "0ae31f290f5542cbec7970cbc5520833134463f5" - }, - "_source": "https://github.com/noeldelgado/Syringe.git", - "_target": "~0.4.0", - "_originalSource": "syringe.js", - "_direct": true -} \ No newline at end of file diff --git a/bower_components/syringe.js/README.md b/bower_components/syringe.js/README.md deleted file mode 100644 index f0f7047..0000000 --- a/bower_components/syringe.js/README.md +++ /dev/null @@ -1,224 +0,0 @@ -# Syringe -[![npm-image](https://img.shields.io/npm/v/syringe.js.svg?style=flat-square)](https://www.npmjs.com/package/syringe.js) -![bower-image](https://img.shields.io/bower/v/syringe.js.svg?style=flat-square) - -* Injects CSS at runtime -* Remove CSS added via Syringe -* Supports: - * @keyframes (auto-prefixed) - * @media at-rule - Media Queries - * @font-face at-rule - * @import at-rule - * Pseudo-elements and pseudo-classes - * Prefixed properties (explicit declaration) - * JSON format - -**Tested on:** IE8+, Chrome, Firefox, Safari and Opera. - - -## Installation - -**NPM** - -`npm install syringe.js --save` - -**Bower** - -`bower install syringe.js --save` - -**Browser** - -Just download [syringe.js](https://raw.githubusercontent.com/noeldelgado/Syringe.js/master/syringe.js) and add it to your env. - -## Usage -### Syringe.inject() -```js -var Syringe = require('syringe.js') - -var props = { - body: { - background: '#222', - color: 'rgba(255,255,255,0.9)' - }, - '.demo p': { - 'font-size': "6px", - fontFamily: "sans-serif" - } -}; - -Syringe.inject(props); -``` - -### Syringe.remove() -```js -Syringe.remove("header"); // single selector -Syringe.remove(["header", "body"]); // multiple selectors at once -``` - -### Syringe.removeAll() -```js -Syringe.removeAll() // remove all styles injected via Syringe -``` - -## More Examples - -### @keyframes -No need to declare the prefixed versions for `@keyframes`. Syringe will check which one is suported by the browser and inject that. - -If you want to prefix any other property, you need to specify which ones and which prefixes you want to be applied, more on how to do this below. -```js -var props = { - '@keyframes anim-test': { - from: { - color: 'red', - boxShadow: "0 0 20px red", - transform: 'translate3d(0, -20px, 0)' - }, - to: { - color: 'lime', - boxShadow: "0 0 20px lime", - transform: 'translate3d(0, 20px, -100px)' - } - }, - 'h1': { - animation: 'anim-test 2s ease 0s infinite alternate forwards' - } -}; - -Syringe.inject(props); -``` - -#### @keyframes (remove) -```js -Syringe.remove(["@keyframes anim-test"]); -``` - -### Prefixed Properties - -Non-support by default, however you can define what properties and which prefixes to apply, just extend `Syringe.config.prefixedProperties` before injection. - -Example: - -```js -Syringe.config.prefixedProperties = { - 'perspective' : ['webkit'], - 'transform-style': ['webkit', 'ms'], - 'animation' : ['webkit'], - 'transform' : ['webkit', 'moz', 'ms', 'o'] -}; -``` - -```js -var props = { - 'body': { - perspective: '1000px', - transformStyle: 'preserve-3d', - animation: 'animation-test 2s ease 0 0' - }, - 'h1': { - transform: 'translate3d(0, 0, -1000px)' - } -}; - -Syringe.inject(props); -``` - -That will inject: - -```css -body { - -webkit-perspective: 1000px; - perspective: 1000px; - -webkit-transform-style: preserve-3d; - -ms-transform-style: preserve-3d; - transform-style: preserve-3d; - -webkit-animation: animation-test 2s ease 0 0; - animation: animation-test 2s ease 0 0; -} -h1{ - -webkit-transform: translate3d(0, 0, -1000px); - -moz-transform: translate3d(0, 0, -1000px); - -ms-transform: translate3d(0, 0, -1000px); - -o-transform: translate3d(0, 0, -1000px); - transform: translate3d(0, 0, -1000px); -} - ``` - -### @media (Media Queries) -```js -var props = { - "@media screen" : { - "*" : { - fontFamily: "sans-serif" - } - }, - "@media all and (min-width: 500px)": { - "body": { - "background": "lime" - } - } -}; -Syringe.inject(props); -``` - -#### Media Queries (remove) -```js -Syringe.remove("@media screen"); -``` - -### @font-face -```js -var props = { - '@font-face' : { - 'font-family': '"Bitstream Vera Serif Bold"', - 'src': 'url("VeraSeBd.ttf")' - }, - 'body' : { - 'font-family': '"Bitstream Vera Serif Bold", serif' - } -}; -Syringe.inject(props); - -#### @font-face (remove) -```js -Syringe.remove("@font-face"); -``` - -### Pseudo-elements, pseudo-classes -```js -var props = { - 'a': { - color: "lime", - transition: 'color 400ms' - }, - 'a:hover': { - color: "red" - }, - 'a:after': { - display: 'inline-block', - content: '"[/]"', - marginLeft: "5px" - } -}; - -/* Strings support: - Note that on the pseudo-element example, - any expected 'String' should be double quoted -*/ -``` - -### @import -As the [spec](http://www.w3.org/TR/CSS2/cascade.html#at-import) says: -> ...any @import rules must precede all other rules (except the @charset rule, if present)... - -```js -var props = { - "@import": "url(style.css)" -}; -Syringe.inject(props); -``` - -#### @import (remove) -```js -Syringe.remove("@import url(style.css)"); -``` diff --git a/bower_components/syringe.js/bower.json b/bower_components/syringe.js/bower.json deleted file mode 100644 index 5252504..0000000 --- a/bower_components/syringe.js/bower.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "syringe.js", - "version": "0.4.0", - "main": "syringe.js", - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "tests", - "src", - "test", - "Gruntfile.js", - "LICENSE", - "package.json" - - ], - "homepage": "https://github.com/noeldelgado/Syringe.js", - "authors": [ - "Noel Delgado " - ], - "description": "Inject additional CSS at runtime", - "keywords": [ - "syringe", - "injection", - "css" - ], - "license": "MIT" -} diff --git a/bower_components/syringe.js/syringe.js b/bower_components/syringe.js/syringe.js deleted file mode 100644 index 9c84bf0..0000000 --- a/bower_components/syringe.js/syringe.js +++ /dev/null @@ -1,360 +0,0 @@ -/* syringe.js - * @version 0.4.0 - * https://github.com/noeldelgado/Syringe.js - * Licensed under the MIT lincese - */ -/* globals CSSRule */ -(function() { - - "use strict"; - - var Syringe = { - config : { - prefixedProperties : null - }, - - style : null, - sheet : null, - rules : null, - buffer : {}, - _level : 0, - - inject : function inject(options) { - if (this.style === null) { - Syringe._createStyleSheet(); - } - - // Reset variables for iteration - this._level = 0; - this.buffer.selectors = []; - this.buffer.blocks = []; - - // Handle rules to be injected - this._iterate(options); - - // Inject rules - return this._insertRules(); - }, - - removeAll : function removeAll() { - while (this.rules.length) { - if (this.sheet.deleteRule) { - this.sheet.deleteRule(this.rules.length - 1); - } else { - this.sheet.removeRule(this.rules.length - 1); - } - } - - // IE8 at-rule - if (this.sheet.imports) { - while(this.sheet.imports.length) { - this.sheet.removeImport(this.sheet.imports.length - 1); - } - } - - this._removeStyleSheet(); - }, - - remove : function remove(selector) { - var rules, rulesLength, selectorsLength, j; - - if (!selector) { - return false; - } - - rules = this.rules; - rulesLength = rules.length; - selectorsLength = selector.length; - - if (typeof selector === "string") { - while (rulesLength--) { - this._deleteRule(rules[rulesLength], rulesLength, selector); - } - } - - if (selector instanceof Array) { - while (rulesLength--) { - for (j = 0; j < selectorsLength; j++) { - this._deleteRule(rules[rulesLength], rulesLength, selector[j]); - } - } - } - - if (this.rules.length === 0) { - this._removeStyleSheet(); - } - }, - - _deleteRule : function _deleteRule(rule, index, selector) { - var isKeyframe, isAtRule, isMedia, isFontFace, selectorNoSpaces; - - if (rule) { - if (this.sheet.deleteRule) { - isKeyframe = this._re.keyframe.exec(selector); - isAtRule = this._re.atRule.exec(selector); - isMedia = this._re.media.exec(selector); - isFontFace = this._re.fontFace.exec(selector); - - if (rule.type === 1 && (rule.selectorText === selector)) { // CSSRule.STYLE_RULE - this.sheet.deleteRule(index); - } else if (rule.type === 3 && isAtRule) { // CSSRule.IMPORT_RULE - if (rule.href === isAtRule[1]) { - this.sheet.deleteRule(index); - } - } else if (rule.type === 4 && isMedia) { // CSSRule.MEDIA_RULE - selectorNoSpaces = selector.replace(/\s/g, ''); - if (rule.cssText.replace(/\s/g, '').substring(0, selectorNoSpaces.length) === selectorNoSpaces) { - this.sheet.deleteRule(index); - } - } else if (rule.type === 5 && isFontFace) { // CSSFontFaceRule - this.sheet.deleteRule(index); - } else if (rule.type === 7 && isKeyframe) { // CSSRule.KEYFRAMES_RULE - if (rule.name === isKeyframe[2]) { - this.sheet.deleteRule(index); - } - } - } else { - // IE-8 - if (rule.selectorText.toLowerCase() === selector) { - this.sheet.removeRule(index); - } else { - isAtRule = this._re.atRule.exec(selector); - if (isAtRule) { - if (this.sheet.imports) { - for (var i = 0; i< this.sheet.imports.length; i++) { - if (this.sheet.imports[i].href.indexOf(isAtRule[1]) > 0) { - this.sheet.removeImport(i); - } - } - } - } - } - } - } - }, - - _iterate : function iterate(obj) { - var selector, lastSelector, property; - - for (selector in obj) { - if (obj.hasOwnProperty(selector)) { - lastSelector = this.buffer.selectors.length - 1; - - if (typeof obj[selector] === "object") { - // Handle rule blocks - this._level++; - - if (this._level === 1) { - this.buffer.selectors.push(selector); - lastSelector = this.buffer.selectors.length - 1; - } else { - this._addToBlock(lastSelector, selector + "{"); - } - - if (this._isEmptyObject(obj[selector])) { - this._level--; - this.buffer.blocks[lastSelector] = ""; - } else { - this._iterate(obj[selector]); - - if (this._level > 1) { - this.buffer.blocks[lastSelector] += "}"; - } - - this._level--; - } - } else { - // handle declarations - property = selector; - - if (this._re.camelCase.test(selector) === true) { - property = this._toDash(selector); - } - - if (this.config.prefixedProperties) { - if (lastSelector < 0) { // empty ruleset, special case for @import rule - lastSelector = 0; - this.buffer.selectors.push(""); - } - this._addToBlock(lastSelector, this._getPrefixedDeclarations(property, obj[selector])); - } else { - this._addToBlock(lastSelector, this._getDeclaration(property, obj[selector])); - } - } - } - } - }, - - _insertRules : function _insertRules() { - var i, blocksLength, rulesLength, result, selector, block, isMedia, isKeyframe, keyframeName; - - blocksLength = this.buffer.blocks.length; - rulesLength = this.rules.length; - result = ""; - - for (i = 0; i < blocksLength; i++) { - selector = this.buffer.selectors[i]; - block = this.buffer.blocks[i]; - isMedia = this._re.media.exec(selector); - isKeyframe = this._re.keyframe.exec(selector); - keyframeName= ""; - - // @import at-rule - if (selector === "") { - result += block; - - if (this.sheet.insertRule) { - this.sheet.insertRule(block, rulesLength); - } else if (this.sheet.addImport) { // IE8- - this.sheet.addImport(this._re.atRule.exec(block)[1]); - } - - continue; - } - - // @keyframes - if (isKeyframe) { - keyframeName = " " + isKeyframe[2]; - if (!!window.CSSRule) { - if (CSSRule.KEYFRAMES_RULE) { - selector = "@keyframes" + keyframeName; - } else if (CSSRule.WEBKIT_KEYFRAMES_RULE) { - selector = "@-webkit-keyframes" + keyframeName; - } else if (CSSRule.MOZ_KEYFRAMES_RULE) { - selector = "@-moz-keyframes" + keyframeName; - } else { - selector = ""; - } - } else { - selector = ""; - } - } - - // media querie, IE8 validation - if (isMedia) { - if ((window.matchMedia === undefined && window.msMatchMedia === undefined) && - (window.styleMedia === undefined && window.media === undefined)) { - selector = ""; - } - } - - if (selector && block) { - if (this.sheet.insertRule) { - this.sheet.insertRule(selector + "{" + block + "}", rulesLength); - } else { - this.sheet.addRule(selector, block, 0); - } - } - - result += selector + "{" + block + "}"; - selector = block = isKeyframe = keyframeName = null; - } - - return result; - }, - - _addToBlock : function _addToBlock(index, value) { - if (this.buffer.blocks[index] === undefined) { - this.buffer.blocks[index] = ""; - } - - this.buffer.blocks[index] += value; - }, - - _getDeclaration : function _getDeclaration(property, value) { - var declaration; - - if (property === "@import") { - declaration = (property + " " + value); - } else { - declaration = (property + ":" + value); - } - - return declaration + ";"; - }, - - _getPrefixedDeclarations : function _getPrefixedDeclarations(property, value) { - var result, index, prefixedProps, prefixedPropsLength; - - if (this.config.prefixedProperties[property]) { - result = ""; - prefixedProps = this._getPrefixedSelector(property); - prefixedPropsLength = prefixedProps.length; - - for (index = 0; index < prefixedPropsLength; index++) { - result += this._getDeclaration(prefixedProps[index], value); - } - - return result; - } - - return this._getDeclaration(property, value); - }, - - _getPrefixedSelector : function _getPrefixedSelector(selector) { - var index, result, prefixes, prefixesLength; - - result = []; - prefixes = this.config.prefixedProperties[selector]; - prefixesLength = prefixes.length; - - for (index = 0; index < prefixesLength; index++) { - result.push('-' + prefixes[index] + '-' + selector); - } - - result.push(selector); - - return result; - }, - - _re : { - camelCase : new RegExp("[A-Z]\\w+"), - keyframe : new RegExp("@(.*)?keyframes (.*)"), - atRule : new RegExp("@import url\\((.*)\\)"), - media : new RegExp("@media"), - fontFace : new RegExp("@font-face") - }, - - _toDash : function _toDash(string) { - return string.replace(/([A-Z])/g, function(letter) { - return '-' + letter.toLowerCase(); - }); - }, - - _isEmptyObject : function _isEmptyObject(obj) { - for (var prop in obj) { - if (obj.hasOwnProperty(prop)) { - return false; - } - } - return true; - }, - - _removeStyleSheet : function _removeStyleSheet() { - // The complete style element must be deleted to - // update the style settings in Firefox and Opera - this.style.parentNode.removeChild(this.style); - this.style = null; - }, - - _createStyleSheet : function _createStyleSheet() { - this.style = document.createElement('style'); - this.style.setAttribute("type", "text/css"); - document.getElementsByTagName("head")[0].appendChild(this.style); - if (this.style.sheet === undefined) { - this.sheet = this.style.styleSheet; - } else { - this.sheet = this.style.sheet; - } - if (this.sheet.cssRules) { - this.rules = this.sheet.cssRules; - } else { - this.rules = this.sheet.rules; - } - } - }; - - if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { - module.exports = Syringe; - } else { window.Syringe = Syringe; } -})(); diff --git a/bower_components/values.js/.bower.json b/bower_components/values.js/.bower.json deleted file mode 100644 index 1a0e8ea..0000000 --- a/bower_components/values.js/.bower.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "values.js", - "version": "1.0.1", - "main": "index.js", - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "test", - "tests", - "gulpfile.js", - "package.json", - "bower.json" - ], - "homepage": "https://github.com/noeldelgado/Values.js", - "authors": [ - "Noel Delgado " - ], - "description": "JS libraryet the tints and shades of a color", - "moduleType": [ - "node" - ], - "keywords": [ - "tints", - "shades", - "color" - ], - "license": "MIT", - "_release": "1.0.1", - "_resolution": { - "type": "version", - "tag": "v1.0.1", - "commit": "d90882868e73f147b7fe2dc50284bbd00a75cd98" - }, - "_source": "git://github.com/noeldelgado/Values.js.git", - "_target": "~1.0.1", - "_originalSource": "values.js", - "_direct": true -} \ No newline at end of file diff --git a/bower_components/values.js/README.md b/bower_components/values.js/README.md deleted file mode 100644 index 43329fc..0000000 --- a/bower_components/values.js/README.md +++ /dev/null @@ -1,161 +0,0 @@ -## Values.js -The lightness or darkness of a color is called its value. -Tints are light values that are made by mixing a color with white, which increases lightness. -Shades are dark values that are made by mixing a color with black, which reduces lightness. - -http://noeldelgado.github.io/Values.js/ - -### Installation - -#### Node - -`npm install values.js` - -#### Bower - -`bower install values.js` - -### Usage -```js -// node -var Values = require('Values.js'); - -// browser - -``` -#### Example -```js -var color = new Values('#0099ff'); - -console.log(color.hex) // => "0099ff" -console.log(color.rgb) // => {r:0, g:153, b:255} -console.log(color.hsl) // => {h:204, s: 100, l: 50} - -console.log(color.hexString()) // => "#0099ff" -console.log(color.rgbString()) // => "rgb(0, 153, 255)" -console.log(color.hslString()) // => "hsl(204, 100%, 50%)" - -console.log(color.getBrightness()) // => 53 - -color.tints().forEach(function(tint) { - console.log(tint); // => [Value instance] -}); - -color.shades().forEach(function(shade) { - console.log(shade); // => [Value instance] -}); - -// tints, original color and shades -color.all().forEach(function(color) { - console.log(color); // => [Value instance] -}); -``` - -### Methods - -#### setColor -```js -/** -Sets the base color for which all operations are based. Updates the instance's properties. -@method setColor [Function] -@param color [String] A valid color format (#000, rgb(0,0,0), hsl(0,0%,0%)) -@return Values instance || Error [Object] -*/ -color.setColor('ff0'); -color.setColor('rgb(255,255,0)'); -color.setColor('hsl(60,100%,50%)'); -``` - -#### tint -```js -/** -Lightens the instance by mixing it with white as specified by @percentage. -@method tint [Function] -@param percentage [Number] {50} -@return new Values instance [Object] -*/ - -color.tint(); -color.tint(10); -color.tint(24); -``` - -#### shade -```js -/** -Darkens the instance color by mixing it with black as specified by @percentage. -@method shade [Function] -@param percentage [Number] {50} -@return new Values instance [Object] -*/ - -color.shade(); -color.shade(9); -color.shade(31); -``` - -#### tints -````js -/** -Generates the tints of the instance color as specified by @percentage. -@method tints [Function] -@param percentage [Number] {10} -@return Array of Values instances [Array] -*/ - -color.tints(20).forEach(function(tint) { - console.log(tint) -}) -```` - -#### shades -````js -/** -Generates the shades of the instance color as specified by @percentage. -@method shades [Function] -@param percentage [Number] {10} -@return Array of Values instances [Array] -*/ - -color.shades(20).forEach(function(shade) { - console.log(shade) -}) -```` - -#### all -```js -/** -Generates the tints and shades of the instance color as specified by @percentage. -@method all [Function] -@param percentage [Number] {10} -@return Array of Values instances [Array] -*/ - -color.all().forEach(function(color) { - console.log(color) -}) -``` - -### Values.Utils - -#### isHex(color) -```js -Values.Utils.isHEX('09c') => true -Values.Utils.isHEX('#09c') => true -Values.Utils.isHEX('#0099cc') => true -Values.Utils.isHEX('09cc') => false -``` - -#### isRGB(color) -```js -Values.Utils.isRGB('rgb(0,0,0)') => true -Values.Utils.isRGB('rgba(0,0,0,.0)') => true -Values.Utils.isRGB('0,0,0') => false -``` - -#### isHSL(color) -```js -Values.Utils.isHSL('hsl(198,58%,1%)') => true -Values.Utils.isHSL('hsla(360,10%,10%, 1)') => true -Values.Utils.isHSl('hsl(361,10%,10%)') => false -``` \ No newline at end of file diff --git a/bower_components/values.js/bower.json b/bower_components/values.js/bower.json deleted file mode 100644 index 6bcb2d2..0000000 --- a/bower_components/values.js/bower.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "values.js", - "version": "1.0.1", - "main": "index.js", - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "test", - "tests", - "gulpfile.js", - "package.json", - "bower.json" - ], - "homepage": "https://github.com/noeldelgado/Values.js", - "authors": [ - "Noel Delgado " - ], - "description": "JS libraryet the tints and shades of a color", - "moduleType": [ - "node" - ], - "keywords": [ - "tints", - "shades", - "color" - ], - "license": "MIT" -} diff --git a/bower_components/values.js/index.js b/bower_components/values.js/index.js deleted file mode 100644 index cb52704..0000000 --- a/bower_components/values.js/index.js +++ /dev/null @@ -1,319 +0,0 @@ -/** - * values.js - Get the tints and shades of a color - * @version v1.0.1 - * @link http://noeldelgado.github.io/Values.js/ - * @license MIT - */ - (function() { - var Utils = { - reHash : new RegExp("^#"), - reHEX : new RegExp("^(#)?([0-9a-fA-F]{3})([0-9a-fA-F]{3})?$"), - reRGB : new RegExp("rgba?\\s*\\((\\d+)\\,\\s*(\\d+)\\,\\s*(\\d+)(,\\s*((\\d+)?(\\.\\d+)?))?\\)","i"), - reHSL : new RegExp("hsla?\\((\\d+),\\s*([\\d.]+)%,\\s*([\\d.]+)%,?\\s*(?:0?(\\.\\d+)?|1(\\.0)?)?\\)","i"), - - isHEX : function isHEX(value) { - return this.reHEX.test(value); - }, - - isRGB : function isRGB(value) { - var rgb = value.match(this.reRGB); - - if (rgb) { - if ((rgb[1] <= 255) && (rgb[2] <= 255) && (rgb[3] <= 255)) { - return true; - } - } - - return false; - }, - - isHSL : function isHSL(value) { - var hsl = value.match(this.reHSL); - - if (hsl) { - if ((hsl[1] <= 360) && (hsl[2] <= 100) && (hsl[3] <= 100)) { - return true; - } - } - - return false; - }, - - HEXtoRGB : function HEXtoRGB(hex) { - hex = hex.replace('#', ''); - - if (hex.length === 3) { - var h1 = hex.charAt(0), h2 = hex.charAt(1), h3 = hex.charAt(2); - hex = h1 + h1 + h2 + h2 + h3 + h3; - } - var bw = parseInt(hex, 16); - - return {r: (bw >> 16) & 255, g: (bw >> 8) & 255, b: bw & 255}; - }, - - RGBtoHEX : function RGBtoHEX(r, g, b) { - return (0x1000000 + (r << 16) + (g << 8) + b).toString(16).slice(1); - }, - - RGBtoHSL : function RGBtoHSL(r, g, b) { - var min, max, h, s, l; - - r = (r / 255); - g = (g / 255); - b = (b / 255); - - max = Math.max(r, g, b); - min = Math.min(r, g, b); - l = ((max + min) / 2); - - if (max === min) { - h = s = 0; - } else { - var d = (max - min); - s = (l > 0.5) ? (d / (2 - max - min)) : (d / (max + min)); - - if (max === r) h = ((g - b) / d + (g < b ? 6 : 0)); - else if (max === g) h = ((b - r) / d + 2); - else if (max === b) h = ((r - g) / d + 4); - - h /= 6; - } - - return {h: Math.round(h * 360), s: Math.round(s * 100), l: Math.round(l * 100)}; - }, - - HUEtoRGB : function HUEtoRGB(v1, v2, vh) { - if (vh < 0) vh += 1; - if (vh > 1) vh -= 1; - - if ((6 * vh) < 1) return (v1 + (v2 - v1) * 6 * vh); - if ((2 * vh) < 1) return v2; - if ((3 * vh) < 2) return (v1 + (v2 - v1) * ((2/3) - vh) * 6); - return v1; - }, - - HSLtoRGB : function HSLtoRGB(h, s, l) { - var r, g, b; - - h /= 360; - s /= 100; - l /= 100; - - if (s == 0) r = g = b = l; - else { - var q = (l < 0.5) ? (l * (1 + s)) : (l + s - l * s); - var p = (2 * l - q); - r = this.HUEtoRGB(p, q, h + 1/3); - g = this.HUEtoRGB(p, q, h); - b = this.HUEtoRGB(p, q, h - 1/3); - } - - return {r: Math.round(r * 255), g: Math.round(g * 255), b: Math.round(b * 255)}; - }, - - mix : function mix(color1, color2, percentage) { - percentage = percentage || 50; - - var weight = (percentage / 100.0); - var w = (weight * 2 - 1); - var a = 0; - - var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; - var w2 = (1 - w1); - - var r = Math.round(color1.rgb.r * w1 + color2.rgb.r * w2); - var g = Math.round(color1.rgb.g * w1 + color2.rgb.g * w2); - var b = Math.round(color1.rgb.b * w1 + color2.rgb.b * w2); - - return new Values(Utils.RGBtoHEX(r,g,b)); - } - }; - - function Values(color) { - this.hex = ''; - this.hsl = {}; - this.rgb = {}; - - if (color) { - return this.setColor(color); - } - - return this; - } - - Values.Utils = Utils; - - /** - Sets the base color for which all operations are based. Updates the instance's properties. - @method setColor [Function] - @param color [String] A valid color format (#000, rgb(0,0,0), hsl(0,0%,0%)) - @return Values instance || Error [Object] - */ - Values.prototype.setColor = function(color) { - if (Utils.isHEX(color)) { - return this._setFromHexString(color); - } else if (Utils.isRGB(color)) { - return this._setFromRGBString(color); - } else if (Utils.isHSL(color)) { - return this._setFromHSLString(color); - } - - return new Error('Invalid Color Format'); - }; - - /** - Lightens the instance by mixing it with white as specified by @percentage. - @method tint [Function] - @param percentage [Number] {50} - @return new Values instance [Object] - */ - Values.prototype.tint = function tint(percentage) { - return Utils.mix({rgb:{r:255, g:255, b:255}}, this, percentage); - }; - - /** - Darkens the instance color by mixing it with black as specified by @percentage. - @method shade [Function] - @param percentage [Number] {50} - @return new Values instance [Object] - */ - Values.prototype.shade = function shade(percentage) { - return Utils.mix({rgb:{r:0, g:0, b:0}}, this, percentage); - }; - - /** - Generates the tints of the instance color as specified by @percentage. - @method tints [Function] - @param percentage [Number] {10} - @return Array of Values instances [Array] - */ - Values.prototype.tints = function tint(percentage) { - var i = percentage = (percentage || 10), tints = []; - - while (i <= 100) { - tints.push(this.tint(i)); - i += percentage; - } - - return tints; - }; - - /** - Generates the shades of the instance color as specified by @percentage. - @method shades [Function] - @param percentage [Number] {10} - @return Array of Values instances [Array] - */ - Values.prototype.shades = function tint(percentage) { - var i = percentage = (percentage || 10), shades = []; - - while (i <= 100) { - shades.push(this.shade(i)); - i += percentage; - } - - return shades; - }; - - /** - Generates the tints and shades of the instance color as specified by @percentage. - @method all [Function] - @param percentage [Number] {10} - @return Array of Values instances [Array] - */ - Values.prototype.all = function all(percentage) { - percentage = percentage; - - var tints = this.tints(percentage).reverse(); - var shades = this.shades(percentage); - tints.push(this); - - return tints.concat(shades); - }; - - /** - Calculates and returns the brightness of the instance base-color. - @return brightness [Number] - */ - Values.prototype.getBrightness = function getBrightness() { - var sum = (this.rgb.r + this.rgb.g + this.rgb.b); - return Math.round(sum / (255 * 3) * 100); - }; - - /** - Returns the instance color in hexadecimal string form. - @returns '#000000' [String] - */ - Values.prototype.hexString = function() { - return '#' + this.hex; - }; - - /** - Returns the instance color in rgb string form. - @returns 'rgb(0, 0, 0)' [String] - */ - Values.prototype.rgbString = function() { - return 'rgb(' + this.rgb.r + ', ' + this.rgb.g + ', ' + this.rgb.b + ')'; - }; - - /** - Returns the instance color in hsl string form. - @returns 'hsl(0, 0%, 0%)' [String] - */ - Values.prototype.hslString = function() { - return 'hsl(' + this.hsl.h + ', ' + this.hsl.s + '%, ' + this.hsl.l + '%)'; - }; - - /** - Updates the instance base-color properties from a valid hex string. - @method _setFromHexString [Function] - @param color [String] - */ - Values.prototype._setFromHexString = function _setFromHexString(color) { - this.hex = (Utils.reHash.test(color)) ? color.replace('#','') : color; - this.rgb = Utils.HEXtoRGB(color); - this.hsl = Utils.RGBtoHSL(this.rgb.r, this.rgb.g, this.rgb.b); - - return this - }; - - /** - Updates the instance base-color properties from a valid rgb string. - @method _setFromRGBString [Function] - @param color [String] - */ - Values.prototype._setFromRGBString = function _setFromRGBString(color) { - var rgb = color.replace(/[^\d,]/g, '').split(','), - r = parseInt(rgb[0], 10), - g = parseInt(rgb[1], 10), - b = parseInt(rgb[2], 10); - - this.rgb = {r: r, g: g, b: b}; - this.hex = Utils.RGBtoHEX(r, g, b); - this.hsl = Utils.RGBtoHSL(this.rgb.r, this.rgb.g, this.rgb.b); - - return this; - }; - - /** - Updates the instance base-color properties from a valid hsl string. - @method _setFromHSLString [Function] - @param color [String] - */ - Values.prototype._setFromHSLString = function _setFromHSLString(color) { - var hsl = color.match(Utils.reHSL), - h = Math.round(hsl[1]), - s = Math.round(hsl[2]), - l = Math.round(hsl[3]); - - this.hsl = {h: h, s: s, l: l}; - this.rgb = Utils.HSLtoRGB(h, s, l); - this.hex = Utils.RGBtoHEX(this.rgb.r, this.rgb.g, this.rgb.b); - - return this; - }; - - if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { - module.exports = Values; - } else window.Values = Values; -})(); \ No newline at end of file diff --git a/bower_components/values.js/test.js b/bower_components/values.js/test.js deleted file mode 100644 index 3740954..0000000 --- a/bower_components/values.js/test.js +++ /dev/null @@ -1,190 +0,0 @@ -"use strict" - -var assert = require('assert') -var Values = require('./') -var color = new Values('0099cc') - -describe('new instance setup', function() { - it('should instantiate correctly', function() { - var hex = color.hex - var rgb = color.rgb - var hsl = color.hsl - - assert.equal(color instanceof Values, true) - assert.equal(color.hex, '0099cc') - assert.equal(color.rgb.r, 0) - assert.equal(color.rgb.g, 153) - assert.equal(color.rgb.b, 204) - assert.equal(color.hsl.h, 195) - assert.equal(color.hsl.s, 100) - assert.equal(color.hsl.l, 40) - }) -}) - -describe('values.methods', function() { - describe('values.method.setColor', function() { - it('should update instance with setColor', function() { - color.setColor('rgb(0,255,255)') - - var hex = color.hex - var rgb = color.rgb - var hsl = color.hsl - - assert.equal(color.hex, '00ffff') - assert.equal(color.rgb.r, 0) - assert.equal(color.rgb.g, 255) - assert.equal(color.rgb.b, 255) - assert.equal(color.hsl.h, 180) - assert.equal(color.hsl.s, 100) - assert.equal(color.hsl.l, 50) - }) - }) - - describe('values.method.tint', function() { - it('should calculate independent tints', function() { - assert.equal(color.tint(10).hexString(), '#19ffff') - assert.equal(color.tint(20).hexString(), '#33ffff') - assert.equal(color.tint(30).hexString(), '#4dffff') - assert.equal(color.tint(10).rgbString(), 'rgb(25, 255, 255)') - assert.equal(color.tint(10).hslString(), 'hsl(180, 100%, 55%)') - }) - }) - - describe('values.method.shade', function() { - it('should calculate independent shades', function() { - assert.equal(color.shade(10).hexString(), '#00e6e6') - assert.equal(color.shade(20).hexString(), '#00cccc') - assert.equal(color.shade(30).hexString(), '#00b3b3') - assert.equal(color.shade(10).rgbString(), 'rgb(0, 230, 230)') - assert.equal(color.shade(10).hslString(), 'hsl(180, 100%, 45%)') - }) - }) - - describe('values.method.tints', function() { - it('should calculate tints', function() { - var tints = color.tints() - assert.equal(tints.length, 10) - assert.equal(tints[0].hex, '19ffff') - assert.equal(tints[2].hex, '4dffff') - assert.equal(tints[4].hex, '80ffff') - assert.equal(tints[6].hex, 'b3ffff') - assert.equal(tints[8].hex, 'e6ffff') - assert.equal(tints[9].hex, 'ffffff') - }) - }) - - describe('values.method.shades', function() { - it('should calculate shades', function() { - var shades = color.shades() - assert.equal(shades.length, 10) - assert.equal(shades[0].hex, '00e6e6') - assert.equal(shades[2].hex, '00b3b3') - assert.equal(shades[4].hex, '008080') - assert.equal(shades[6].hex, '004d4d') - assert.equal(shades[8].hex, '001919') - assert.equal(shades[9].hex, '000000') - }) - }) - - describe('values.method.all', function() { - it('should calculate all', function() { - var all = color.all() - assert.equal(all.length, 21) - assert.equal(all[0].hex, 'ffffff') - assert.equal(all[10].hex, color.hex) - assert.equal(all[20].hex, '000000') - }) - }) - - describe('values.method.getBrightness', function() { - it('should return the brightness', function() { - assert.equal(color.getBrightness(), 67) - }) - }) - - describe('values.method.hexString', function() { - it('should return the color in hex string form', function() { - assert.equal(new Values('0099cc').hexString(), '#0099cc') - }) - }) - - describe('values.method.rgbString', function() { - it('should return the color in reg string form', function() { - assert.equal(new Values('0099cc').rgbString(), 'rgb(0, 153, 204)') - }) - }) - - describe('values.method.hslString', function() { - it('should return the color in hsl string form', function() { - assert.equal(new Values('0099cc').hslString(), 'hsl(195, 100%, 40%)') - }) - }) -}) - -describe('values.utils', function() { - describe('color format validation', function() { - it('should support hex formats', function() { - assert.equal(Values.Utils.isHEX('#09c'), true) - assert.equal(Values.Utils.isHEX('09c'), true) - assert.equal(Values.Utils.isHEX('#0099cc'), true) - assert.equal(Values.Utils.isHEX('CCCCCC'), true) - assert.equal(Values.Utils.isHEX('09cc'), false) - assert.equal(Values.Utils.isHEX('#FFG'), false) - }) - - it('should support rgb color formats', function() { - assert.equal(Values.Utils.isRGB('rgba(255,0,0,1)'), true) - assert.equal(Values.Utils.isRGB('rgb(255,255,255)'), true) - assert.equal(Values.Utils.isRGB('rgba(100,0,240,0.5)'), true) - assert.equal(Values.Utils.isRGB('rgba(100,0,240,.5)'), true) - assert.equal(Values.Utils.isRGB('255,0,0'), false) - assert.equal(Values.Utils.isRGB('rgb(0,0,0)'), true) - assert.equal(Values.Utils.isRGB('rgb(255,10,0.5)'), false) - assert.equal(Values.Utils.isRGB('rgb(255,10.5, 0)'), false) - assert.equal(Values.Utils.isRGB('rgb(256,0,0)'), false) - assert.equal(Values.Utils.isRGB('rgb(0,256,0)'), false) - assert.equal(Values.Utils.isRGB('rgb(0,0,256)'), false) - assert.equal(Values.Utils.isRGB('RGB(0,0,255)'), true) - }) - - it('should support hsl color formats', function() { - assert.equal(Values.Utils.isHSL('hsl(198, 58%, 1%)'), true) - assert.equal(Values.Utils.isHSL('hsla(198, 58%, 1%, 1)'), true) - assert.equal(Values.Utils.isHSL('hsla(198, 58%, 1%, 0.1)'), true) - assert.equal(Values.Utils.isHSL('hsla(198, 58%, 1%, 1)'), true) - assert.equal(Values.Utils.isHSL('hsl(198, 58, 1%)'), false) - assert.equal(Values.Utils.isHSL('hsl(361, 58%, 1%)'), false) - assert.equal(Values.Utils.isHSL('hsl(360, 101%, 50%)'), false) - assert.equal(Values.Utils.isHSL('hsl(360, 100%, 100%)'), true) - assert.equal(Values.Utils.isHSL('HSL(360, 100%, 100%)'), true) - }) - }) - - describe('color format convertions', function() { - it('should convert from hex to rgb', function() { - var rgb = Values.Utils.HEXtoRGB('09f') - assert.equal(rgb.r, 0) - assert.equal(rgb.g, 153) - assert.equal(rgb.b, 255) - }) - - it('should convert from rgb to hex', function() { - var hex = Values.Utils.RGBtoHEX(0, 153, 255) - assert.equal(hex, '0099ff') - }) - - it('should convert from rgb to hsl', function() { - var hsl = Values.Utils.RGBtoHSL(0, 153, 255) - assert.equal(hsl.h, 204) - assert.equal(hsl.s, 100) - assert.equal(hsl.l, 50) - }) - - it('should convert from hsl to rgb', function() { - var rgb = Values.Utils.HSLtoRGB(204, 100, 50) - assert.equal(rgb.r, 0) - assert.equal(rgb.g, 153) - assert.equal(rgb.b, 255) - }) - }) -}) diff --git a/build/css/main.css b/build/css/main.css new file mode 100644 index 0000000..67bdd0b --- /dev/null +++ b/build/css/main.css @@ -0,0 +1,329 @@ +/*! Pickr 1.5.1 MIT | https://github.com/Simonwep/pickr */ +.pickr{position:relative;overflow:visible;-webkit-transform:translateY(0);transform:translateY(0)} +.pickr *{-webkit-box-sizing:border-box;box-sizing:border-box;outline:none;border:none;-webkit-appearance:none} +.pickr .pcr-button{position:relative;height:2em;width:2em;padding:.5em;cursor:pointer;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;border-radius:.15em;background:url('data:image/svg+xml;utf8, ') no-repeat 50%;background-size:0;-webkit-transition:all .3s;transition:all .3s} +.pickr .pcr-button:before{background:url('data:image/svg+xml;utf8, ');background-size:.5em;z-index:-1;z-index:auto} +.pickr .pcr-button:after,.pickr .pcr-button:before{position:absolute;content:"";top:0;left:0;width:100%;height:100%;border-radius:.15em} +.pickr .pcr-button:after{-webkit-transition:background .3s;transition:background .3s;background:currentColor} +.pickr .pcr-button.clear{background-size:70%} +.pickr .pcr-button.clear:before{opacity:0} +.pickr .pcr-button.clear:focus{-webkit-box-shadow:0 0 0 1px hsla(0, 0%, 100%, .85),0 0 0 3px currentColor;box-shadow:0 0 0 1px hsla(0, 0%, 100%, .85),0 0 0 3px currentColor} +.pickr .pcr-button.disabled{cursor:not-allowed} +.pcr-app *,.pickr *{-webkit-box-sizing:border-box;box-sizing:border-box;outline:none;border:none;-webkit-appearance:none} +.pcr-app button.pcr-active,.pcr-app button:focus,.pcr-app input.pcr-active,.pcr-app input:focus,.pickr button.pcr-active,.pickr button:focus,.pickr input.pcr-active,.pickr input:focus{-webkit-box-shadow:0 0 0 1px hsla(0, 0%, 100%, .85),0 0 0 3px currentColor;box-shadow:0 0 0 1px hsla(0, 0%, 100%, .85),0 0 0 3px currentColor} +.pcr-app .pcr-palette,.pcr-app .pcr-slider,.pickr .pcr-palette,.pickr .pcr-slider{-webkit-transition:-webkit-box-shadow .3s;transition:-webkit-box-shadow .3s;transition:box-shadow .3s;transition:box-shadow .3s, -webkit-box-shadow .3s} +.pcr-app .pcr-palette:focus,.pcr-app .pcr-slider:focus,.pickr .pcr-palette:focus,.pickr .pcr-slider:focus{-webkit-box-shadow:0 0 0 1px hsla(0, 0%, 100%, .85),0 0 0 3px rgba(0, 0, 0, .25);box-shadow:0 0 0 1px hsla(0, 0%, 100%, .85),0 0 0 3px rgba(0, 0, 0, .25)} +.pcr-app{position:fixed;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;z-index:10000;border-radius:.1em;background:#fff;opacity:0;visibility:hidden;-webkit-transition:opacity .3s,visibility 0s .3s;transition:opacity .3s,visibility 0s .3s;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;-webkit-box-shadow:0 .15em 1.5em 0 rgba(0, 0, 0, .1),0 0 1em 0 rgba(0, 0, 0, .03);box-shadow:0 .15em 1.5em 0 rgba(0, 0, 0, .1),0 0 1em 0 rgba(0, 0, 0, .03);left:0;top:0} +.pcr-app.visible{-webkit-transition:opacity .3s;transition:opacity .3s;visibility:visible;opacity:1} +.pcr-app .pcr-swatches{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-top:.75em} +.pcr-app .pcr-swatches.pcr-last{margin:0} +@supports (display:grid){.pcr-app .pcr-swatches{display:grid;-webkit-box-align:center;-ms-flex-align:center;align-items:center;grid-template-columns:repeat(auto-fit,1.75em)}} +.pcr-app .pcr-swatches>button{font-size:1em;position:relative;width:calc(1.75em - 5px);height:calc(1.75em - 5px);border-radius:.15em;cursor:pointer;margin:2.5px;-ms-flex-negative:0;flex-shrink:0;justify-self:center;-webkit-transition:all .15s;transition:all .15s;overflow:hidden;background:transparent;z-index:1} +.pcr-app .pcr-swatches>button:before{position:absolute;content:"";top:0;left:0;width:100%;height:100%;background:url('data:image/svg+xml;utf8, ');background-size:6px;border-radius:.15em;z-index:-1} +.pcr-app .pcr-swatches>button:after{content:"";position:absolute;top:0;left:0;width:100%;height:100%;background:currentColor;border:1px solid rgba(0, 0, 0, .05);border-radius:.15em;-webkit-box-sizing:border-box;box-sizing:border-box} +.pcr-app .pcr-swatches>button:hover{-webkit-filter:brightness(1.05);filter:url('data:image/svg+xml;charset=utf-8,#filter');filter:brightness(1.05)} +.pcr-app .pcr-interaction{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin:0 -.2em} +.pcr-app .pcr-interaction>*{margin:0 .2em} +.pcr-app .pcr-interaction input{letter-spacing:.07em;font-size:.75em;text-align:center;cursor:pointer;color:#75797e;background:#f1f3f4;border-radius:.15em;-webkit-transition:all .15s;transition:all .15s;padding:.45em .5em;margin-top:.75em} +.pcr-app .pcr-interaction input:hover{-webkit-filter:brightness(.975);filter:url('data:image/svg+xml;charset=utf-8,#filter');filter:brightness(.975)} +.pcr-app .pcr-interaction input:focus{-webkit-box-shadow:0 0 0 1px hsla(0, 0%, 100%, .85),0 0 0 3px rgba(66, 133, 244, .75);box-shadow:0 0 0 1px hsla(0, 0%, 100%, .85),0 0 0 3px rgba(66, 133, 244, .75)} +.pcr-app .pcr-interaction .pcr-result{color:#75797e;text-align:left;-webkit-box-flex:1;-ms-flex:1 1 8em;flex:1 1 8em;min-width:8em;-webkit-transition:all .2s;transition:all .2s;border-radius:.15em;background:#f1f3f4;cursor:text} +.pcr-app .pcr-interaction .pcr-result::-moz-selection{background:#4285f4;color:#fff} +.pcr-app .pcr-interaction .pcr-result::selection{background:#4285f4;color:#fff} +.pcr-app .pcr-interaction .pcr-type.active{color:#fff;background:#4285f4} +.pcr-app .pcr-interaction .pcr-cancel,.pcr-app .pcr-interaction .pcr-clear,.pcr-app .pcr-interaction .pcr-save{width:auto;color:#fff} +.pcr-app .pcr-interaction .pcr-cancel:hover,.pcr-app .pcr-interaction .pcr-clear:hover,.pcr-app .pcr-interaction .pcr-save:hover{-webkit-filter:brightness(.925);filter:url('data:image/svg+xml;charset=utf-8,#filter');filter:brightness(.925)} +.pcr-app .pcr-interaction .pcr-save{background:#4285f4} +.pcr-app .pcr-interaction .pcr-cancel,.pcr-app .pcr-interaction .pcr-clear{background:#f44250} +.pcr-app .pcr-interaction .pcr-cancel:focus,.pcr-app .pcr-interaction .pcr-clear:focus{-webkit-box-shadow:0 0 0 1px hsla(0, 0%, 100%, .85),0 0 0 3px rgba(244, 66, 80, .75);box-shadow:0 0 0 1px hsla(0, 0%, 100%, .85),0 0 0 3px rgba(244, 66, 80, .75)} +.pcr-app .pcr-selection .pcr-picker{position:absolute;height:18px;width:18px;border:2px solid #fff;border-radius:100%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none} +.pcr-app .pcr-selection .pcr-color-chooser,.pcr-app .pcr-selection .pcr-color-opacity,.pcr-app .pcr-selection .pcr-color-palette{position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;cursor:grab;cursor:-webkit-grab} +.pcr-app .pcr-selection .pcr-color-chooser:active,.pcr-app .pcr-selection .pcr-color-opacity:active,.pcr-app .pcr-selection .pcr-color-palette:active{cursor:grabbing;cursor:-webkit-grabbing} +.pcr-app[data-theme=nano]{width:14.25em;max-width:95vw} +.pcr-app[data-theme=nano] .pcr-swatches{margin-top:.6em;padding:0 .6em} +.pcr-app[data-theme=nano] .pcr-interaction{padding:0 .6em .6em} +.pcr-app[data-theme=nano] .pcr-selection{display:grid;grid-gap:.6em;grid-template-columns:1fr 4fr;grid-template-rows:5fr auto auto;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:10.5em;width:100%;align-self:flex-start} +.pcr-app[data-theme=nano] .pcr-selection .pcr-color-preview{grid-area:2/1/4/1;height:100%;width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;margin-left:.6em} +.pcr-app[data-theme=nano] .pcr-selection .pcr-color-preview .pcr-last-color{display:none} +.pcr-app[data-theme=nano] .pcr-selection .pcr-color-preview .pcr-current-color{position:relative;background:currentColor;width:2em;height:2em;border-radius:50em;overflow:hidden} +.pcr-app[data-theme=nano] .pcr-selection .pcr-color-preview .pcr-current-color:before{position:absolute;content:"";top:0;left:0;width:100%;height:100%;background:url('data:image/svg+xml;utf8, ');background-size:.5em;border-radius:.15em;z-index:-1} +.pcr-app[data-theme=nano] .pcr-selection .pcr-color-palette{grid-area:1/1/2/3;width:100%;height:100%;z-index:1} +.pcr-app[data-theme=nano] .pcr-selection .pcr-color-palette .pcr-palette{border-radius:.15em;width:100%;height:100%} +.pcr-app[data-theme=nano] .pcr-selection .pcr-color-palette .pcr-palette:before{position:absolute;content:"";top:0;left:0;width:100%;height:100%;background:url('data:image/svg+xml;utf8, ');background-size:.5em;border-radius:.15em;z-index:-1} +.pcr-app[data-theme=nano] .pcr-selection .pcr-color-chooser{grid-area:2/2/2/2} +.pcr-app[data-theme=nano] .pcr-selection .pcr-color-opacity{grid-area:3/2/3/2} +.pcr-app[data-theme=nano] .pcr-selection .pcr-color-chooser,.pcr-app[data-theme=nano] .pcr-selection .pcr-color-opacity{height:.5em;margin:0 .6em} +.pcr-app[data-theme=nano] .pcr-selection .pcr-color-chooser .pcr-picker,.pcr-app[data-theme=nano] .pcr-selection .pcr-color-opacity .pcr-picker{top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)} +.pcr-app[data-theme=nano] .pcr-selection .pcr-color-chooser .pcr-slider,.pcr-app[data-theme=nano] .pcr-selection .pcr-color-opacity .pcr-slider{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;border-radius:50em} +.pcr-app[data-theme=nano] .pcr-selection .pcr-color-chooser .pcr-slider{background:-webkit-gradient(linear,left top, right top,from(red),color-stop(#ff0),color-stop(#0f0),color-stop(#0ff),color-stop(#00f),color-stop(#f0f),to(red));background:linear-gradient(90deg,red,#ff0,#0f0,#0ff,#00f,#f0f,red)} +.pcr-app[data-theme=nano] .pcr-selection .pcr-color-opacity .pcr-slider{background:-webkit-gradient(linear,left top, right top,from(transparent),to(#000)),url('data:image/svg+xml;utf8, ');background:linear-gradient(90deg,transparent,#000),url('data:image/svg+xml;utf8, ');background-size:100%,.25em} +.github-corner{ + position:absolute; + top:0; + border:0; + right:0 +} +.github-corner .octo-arm, + .github-corner .octo-body{fill:var(--cc-main-color);-webkit-transition:fill var(--cc-transition-duration) var(--cc-transition-timing);transition:fill var(--cc-transition-duration) var(--cc-transition-timing);} +.github-corner:hover .octo-arm{-webkit-animation:octocat-wave 560ms ease-in-out;animation:octocat-wave 560ms ease-in-out;} +@media (max-width:500px){ +.github-corner:hover .octo-arm{-webkit-animation:none;animation:none;} +.github-corner .octo-arm{-webkit-animation:octocat-wave 560ms ease-in-out;animation:octocat-wave 560ms ease-in-out;}} +@-webkit-keyframes octocat-wave{ + 0%, 100%{ -webkit-transform:rotate(0); transform:rotate(0) } + 20%, 60%{ -webkit-transform:rotate(-25deg); transform:rotate(-25deg) } + 40%, 80%{ -webkit-transform:rotate(10deg); transform:rotate(10deg) } +} +@keyframes octocat-wave{ + 0%, 100%{ -webkit-transform:rotate(0); transform:rotate(0) } + 20%, 60%{ -webkit-transform:rotate(-25deg); transform:rotate(-25deg) } + 40%, 80%{ -webkit-transform:rotate(10deg); transform:rotate(10deg) } +} +.pcr-app[data-theme=nano] .pcr-selection .pcr-color-chooser{grid-area:2/1/2/3;} +.pcr-app[data-theme=nano] .pcr-swatches{margin:0;} +button{ + font-weight:inherit; + border:2px solid var(--cc-border-color); + background-color:var(--cc-text-color); + color:var(--cc-main-color); + -webkit-transition:all var(--cc-transition-duration) var(--cc-transition-timing); + transition:all var(--cc-transition-duration) var(--cc-transition-timing); + -webkit-transition-property:color, background-color, border-color, -webkit-box-shadow; + transition-property:color, background-color, border-color, -webkit-box-shadow; + transition-property:color, background-color, border-color, box-shadow; + transition-property:color, background-color, border-color, box-shadow, -webkit-box-shadow +} +button:focus{-webkit-box-shadow:var(--cc-border-color) 0 0 0 0.25em;box-shadow:var(--cc-border-color) 0 0 0 0.25em;} +button:active{background-color:var(--cc-border-color);-webkit-box-shadow:none;box-shadow:none;} +.cc-btn{ + border-radius:3px; + border:none; + padding:8px 16px; + padding:0.5rem 1rem +} +.cc-btn > *{display:inline-block;vertical-align:middle;} +button.cc-btn-icon{ + width:64px; + height:64px; + border-radius:50%; + padding:0 +} +button.cc-btn-icon.cc-btn-sm{width:48px;height:48px} +button.cc-btn-icon.cc-btn-sm > svg{display:block;margin:0 auto;} +:root{ + --cc-fsd:10 +} +.cc-color-item{ + display:-webkit-box; + display:-ms-flexbox; + display:flex +} +.cc-color-item.-hex{--cc-fsd:7;font-size:calc(100vw / var(--cc-fsd));} +@media (min-width: 500px){ +.cc-color-item.-hex{font-size:calc(100vw / (var(--cc-fsd) - 1));}} +@media (min-width: 1000px){ +.cc-color-item.-hex{font-size:calc(1000px / var(--cc-fsd));}} +.cc-color-item.-hex{margin:-0.1em 0 -0.2em;} +.cc-color-item.-rgb{--cc-fsd:12;font-size:calc(100vw / var(--cc-fsd));} +@media (min-width: 500px){ +.cc-color-item.-rgb{font-size:calc(100vw / (var(--cc-fsd) - 1));}} +@media (min-width: 1000px){ +.cc-color-item.-rgb{font-size:calc(1000px / var(--cc-fsd));}} +.cc-color-item.-hsl{--cc-fsd:13;font-size:calc(100vw / var(--cc-fsd));} +@media (min-width: 500px){ +.cc-color-item.-hsl{font-size:calc(100vw / (var(--cc-fsd) - 1));}} +@media (min-width: 1000px){ +.cc-color-item.-hsl{font-size:calc(1000px / var(--cc-fsd));}} +.cc-color-item.-hwb{--cc-fsd:13;font-size:calc(100vw / var(--cc-fsd));} +@media (min-width: 500px){ +.cc-color-item.-hwb{font-size:calc(100vw / (var(--cc-fsd) - 1));}} +@media (min-width: 1000px){ +.cc-color-item.-hwb{font-size:calc(1000px / var(--cc-fsd));}} +.cc-color-item__label{ + display:-webkit-box; + display:-ms-flexbox; + display:flex; + -webkit-box-align:center; + -ms-flex-align:center; + align-items:center; + font-size:12px; + font-size:0.75rem; + padding:0 8px 0 16px; + padding:0 0.5rem 0 1rem +} +.cc-color-item__label > span{width:10px;-webkit-writing-mode:vertical-lr;-ms-writing-mode:tb-lr;writing-mode:vertical-lr;-webkit-transform:rotate(180deg);transform:rotate(180deg);} +.cc-color-item__btn{ + display:-webkit-box; + display:-ms-flexbox; + display:flex; + -webkit-box-align:center; + -ms-flex-align:center; + align-items:center; + padding:0 8px 0 0; + padding:0 0.5rem 0 0; +} +.cc-input{ + border:none; + width:100%; + font-family:inherit; + font-size:inherit; + padding:0; + margin:0; + font-weight:900; + letter-spacing:-2px; + background:rgba(0, 0, 0, 0); + color:inherit; + outline:none; + text-overflow:ellipsis +} +.cc-input:invalid, + .cc-input[aria-invalid="true"]{-webkit-text-decoration:underline wavy red;text-decoration:underline wavy red;text-decoration-skip-ink:none;} +.cc-input::-webkit-input-placeholder{color:inherit;opacity:0.25;} +.cc-input::-moz-placeholder{color:inherit;opacity:0.25;} +.cc-input::-ms-input-placeholder{color:inherit;opacity:0.25;} +.cc-input::placeholder{color:inherit;opacity:0.25;} +.toast-wrapper{ + pointer-events:none; + position:fixed; + top:16px; + top:1rem; + left:16px; + left:1rem +} +.toast-wrapper.show > .toast{opacity:1;-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0);} +.toast{ + display:inline-block; + padding:12px 20px; + padding:0.75rem 1.25rem; + font-weight:400; + background:var(--cc-text-color); + color:var(--cc-main-color); + border-radius:3px; + opacity:0; + -webkit-transform:translate3d(-1rem, 0, 0); + transform:translate3d(-1rem, 0, 0); + -webkit-transition:all var(--cc-transition-duration) var(--cc-transition-timing); + transition:all var(--cc-transition-duration) var(--cc-transition-timing); + -webkit-transition-property:opacity, -webkit-transform; + transition-property:opacity, -webkit-transform; + transition-property:opacity, transform; + transition-property:opacity, transform, -webkit-transform; +} +.df{ display:-webkit-box; display:-ms-flexbox; display:flex } +.aic{ -webkit-box-align:center; -ms-flex-align:center; align-items:center } +.mr1{ margin-right:8px; margin-right:0.5rem } +.tdn{ text-decoration:none } +html, +body{ height:100%; } +body{ + line-height:1; + font-weight:800; + + color:var(--cc-text-color); + background-color:var(--cc-main-color); + + -webkit-transition:all var(--cc-transition-duration) var(--cc-transition-timing); + + transition:all var(--cc-transition-duration) var(--cc-transition-timing); + -webkit-transition-property:color, background-color; + transition-property:color, background-color +} +body::before, body::after{content:'';position:fixed;left:0;width:8px;width:0.5rem;height:50%;} +body::before{background:black;top:0;} +body::after{background:white;top:50%;} +::-moz-selection{ + background:var(--cc-text-color); + color:var(--cc-main-color); +} +::selection{ + background:var(--cc-text-color); + color:var(--cc-main-color); +} +.root{ + margin:auto 0; + padding:32px 0; + padding:2rem 0; +} +header{ + position:relative; + padding:0 16px; + padding:0 1rem; + font-style:italic; +} +.logo{ + width:16px; + height:16px; + display:inline-block; + border-radius:50%; + background-image:radial-gradient(circle at top center, #F00 50%, transparent 100%), radial-gradient(circle at bottom right, #0F0 50%, transparent 100%), radial-gradient(circle at bottom left, #00F 50%, transparent 100%); + background-blend-mode:lighten; + -webkit-box-shadow:0 0 0 1px var(--cc-border-color); + box-shadow:0 0 0 1px var(--cc-border-color); +} +.cc-extra-items{ + padding:16px 0 0 0; + padding:1rem 0 0 0; +} +footer{ + font-size:10px; + font-size:0.625rem; + padding:24px 16px 0 32px; + padding:1.5rem 1rem 0 2rem +} +footer a{-webkit-transition:opacity 300ms linear;transition:opacity 300ms linear} +footer a:hover{opacity:0.7;} +footer > .footer__info{position:relative;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;padding-left:32px;padding-left:2rem;margin-left:32px;margin-left:2rem} +footer > .footer__info::before{content:'';position:absolute;left:0;top:25%;bottom:25%;border-left-width:1px;border-left-style:dotted;} +.cc-by{ + font-size:10px; + font-size:0.625rem; + position:fixed; + bottom:16px; + bottom:1rem; + right:16px; + right:1rem; + font-size:12px; + font-size:0.75rem; +} +:root{ + --cc-main-color:#fff; + --cc-text-color:#000; + --cc-border-color:#e6e6e6; + + --cc-transition-timing:ease-out; + --cc-transition-duration:260ms; + + font-family:system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Droid Sans, Helvetica Neue; + font-size:16px; +} +*{ + -webkit-box-sizing:border-box; + box-sizing:border-box; + margin:0; + padding:0; +} +body{ + -webkit-user-select:none; + -moz-user-select:none; + -ms-user-select:none; + user-select:none; + -webkit-font-feature-settings:"kern" off; + font-feature-settings:"kern" off; + -webkit-font-kerning:none; + font-kerning:none; +} +a{ + display:-webkit-inline-box; + display:-ms-inline-flexbox; + display:inline-flex; + -webkit-box-align:center; + -ms-flex-align:center; + align-items:center; + color:inherit; +} +svg{ + fill:currentColor; +} +[disabled]{ + opacity:0.5; +} diff --git a/build/js/main.js b/build/js/main.js new file mode 100644 index 0000000..78f7af9 --- /dev/null +++ b/build/js/main.js @@ -0,0 +1,2633 @@ +(function () { + var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + function unwrapExports (x) { + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; + } + + function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; + } + + var colorName = { + "aliceblue": [240, 248, 255], + "antiquewhite": [250, 235, 215], + "aqua": [0, 255, 255], + "aquamarine": [127, 255, 212], + "azure": [240, 255, 255], + "beige": [245, 245, 220], + "bisque": [255, 228, 196], + "black": [0, 0, 0], + "blanchedalmond": [255, 235, 205], + "blue": [0, 0, 255], + "blueviolet": [138, 43, 226], + "brown": [165, 42, 42], + "burlywood": [222, 184, 135], + "cadetblue": [95, 158, 160], + "chartreuse": [127, 255, 0], + "chocolate": [210, 105, 30], + "coral": [255, 127, 80], + "cornflowerblue": [100, 149, 237], + "cornsilk": [255, 248, 220], + "crimson": [220, 20, 60], + "cyan": [0, 255, 255], + "darkblue": [0, 0, 139], + "darkcyan": [0, 139, 139], + "darkgoldenrod": [184, 134, 11], + "darkgray": [169, 169, 169], + "darkgreen": [0, 100, 0], + "darkgrey": [169, 169, 169], + "darkkhaki": [189, 183, 107], + "darkmagenta": [139, 0, 139], + "darkolivegreen": [85, 107, 47], + "darkorange": [255, 140, 0], + "darkorchid": [153, 50, 204], + "darkred": [139, 0, 0], + "darksalmon": [233, 150, 122], + "darkseagreen": [143, 188, 143], + "darkslateblue": [72, 61, 139], + "darkslategray": [47, 79, 79], + "darkslategrey": [47, 79, 79], + "darkturquoise": [0, 206, 209], + "darkviolet": [148, 0, 211], + "deeppink": [255, 20, 147], + "deepskyblue": [0, 191, 255], + "dimgray": [105, 105, 105], + "dimgrey": [105, 105, 105], + "dodgerblue": [30, 144, 255], + "firebrick": [178, 34, 34], + "floralwhite": [255, 250, 240], + "forestgreen": [34, 139, 34], + "fuchsia": [255, 0, 255], + "gainsboro": [220, 220, 220], + "ghostwhite": [248, 248, 255], + "gold": [255, 215, 0], + "goldenrod": [218, 165, 32], + "gray": [128, 128, 128], + "green": [0, 128, 0], + "greenyellow": [173, 255, 47], + "grey": [128, 128, 128], + "honeydew": [240, 255, 240], + "hotpink": [255, 105, 180], + "indianred": [205, 92, 92], + "indigo": [75, 0, 130], + "ivory": [255, 255, 240], + "khaki": [240, 230, 140], + "lavender": [230, 230, 250], + "lavenderblush": [255, 240, 245], + "lawngreen": [124, 252, 0], + "lemonchiffon": [255, 250, 205], + "lightblue": [173, 216, 230], + "lightcoral": [240, 128, 128], + "lightcyan": [224, 255, 255], + "lightgoldenrodyellow": [250, 250, 210], + "lightgray": [211, 211, 211], + "lightgreen": [144, 238, 144], + "lightgrey": [211, 211, 211], + "lightpink": [255, 182, 193], + "lightsalmon": [255, 160, 122], + "lightseagreen": [32, 178, 170], + "lightskyblue": [135, 206, 250], + "lightslategray": [119, 136, 153], + "lightslategrey": [119, 136, 153], + "lightsteelblue": [176, 196, 222], + "lightyellow": [255, 255, 224], + "lime": [0, 255, 0], + "limegreen": [50, 205, 50], + "linen": [250, 240, 230], + "magenta": [255, 0, 255], + "maroon": [128, 0, 0], + "mediumaquamarine": [102, 205, 170], + "mediumblue": [0, 0, 205], + "mediumorchid": [186, 85, 211], + "mediumpurple": [147, 112, 219], + "mediumseagreen": [60, 179, 113], + "mediumslateblue": [123, 104, 238], + "mediumspringgreen": [0, 250, 154], + "mediumturquoise": [72, 209, 204], + "mediumvioletred": [199, 21, 133], + "midnightblue": [25, 25, 112], + "mintcream": [245, 255, 250], + "mistyrose": [255, 228, 225], + "moccasin": [255, 228, 181], + "navajowhite": [255, 222, 173], + "navy": [0, 0, 128], + "oldlace": [253, 245, 230], + "olive": [128, 128, 0], + "olivedrab": [107, 142, 35], + "orange": [255, 165, 0], + "orangered": [255, 69, 0], + "orchid": [218, 112, 214], + "palegoldenrod": [238, 232, 170], + "palegreen": [152, 251, 152], + "paleturquoise": [175, 238, 238], + "palevioletred": [219, 112, 147], + "papayawhip": [255, 239, 213], + "peachpuff": [255, 218, 185], + "peru": [205, 133, 63], + "pink": [255, 192, 203], + "plum": [221, 160, 221], + "powderblue": [176, 224, 230], + "purple": [128, 0, 128], + "rebeccapurple": [102, 51, 153], + "red": [255, 0, 0], + "rosybrown": [188, 143, 143], + "royalblue": [65, 105, 225], + "saddlebrown": [139, 69, 19], + "salmon": [250, 128, 114], + "sandybrown": [244, 164, 96], + "seagreen": [46, 139, 87], + "seashell": [255, 245, 238], + "sienna": [160, 82, 45], + "silver": [192, 192, 192], + "skyblue": [135, 206, 235], + "slateblue": [106, 90, 205], + "slategray": [112, 128, 144], + "slategrey": [112, 128, 144], + "snow": [255, 250, 250], + "springgreen": [0, 255, 127], + "steelblue": [70, 130, 180], + "tan": [210, 180, 140], + "teal": [0, 128, 128], + "thistle": [216, 191, 216], + "tomato": [255, 99, 71], + "turquoise": [64, 224, 208], + "violet": [238, 130, 238], + "wheat": [245, 222, 179], + "white": [255, 255, 255], + "whitesmoke": [245, 245, 245], + "yellow": [255, 255, 0], + "yellowgreen": [154, 205, 50] + }; + + var isArrayish = function isArrayish(obj) { + if (!obj || typeof obj === 'string') { + return false; + } + + return obj instanceof Array || Array.isArray(obj) || + (obj.length >= 0 && (obj.splice instanceof Function || + (Object.getOwnPropertyDescriptor(obj, (obj.length - 1)) && obj.constructor.name !== 'String'))); + }; + + var simpleSwizzle = createCommonjsModule(function (module) { + + + + var concat = Array.prototype.concat; + var slice = Array.prototype.slice; + + var swizzle = module.exports = function swizzle(args) { + var results = []; + + for (var i = 0, len = args.length; i < len; i++) { + var arg = args[i]; + + if (isArrayish(arg)) { + // http://jsperf.com/javascript-array-concat-vs-push/98 + results = concat.call(results, slice.call(arg)); + } else { + results.push(arg); + } + } + + return results; + }; + + swizzle.wrap = function (fn) { + return function () { + return fn(swizzle(arguments)); + }; + }; + }); + + var colorString = createCommonjsModule(function (module) { + /* MIT license */ + + + + var reverseNames = {}; + + // create a list of reverse color names + for (var name in colorName) { + if (colorName.hasOwnProperty(name)) { + reverseNames[colorName[name]] = name; + } + } + + var cs = module.exports = { + to: {}, + get: {} + }; + + cs.get = function (string) { + var prefix = string.substring(0, 3).toLowerCase(); + var val; + var model; + switch (prefix) { + case 'hsl': + val = cs.get.hsl(string); + model = 'hsl'; + break; + case 'hwb': + val = cs.get.hwb(string); + model = 'hwb'; + break; + default: + val = cs.get.rgb(string); + model = 'rgb'; + break; + } + + if (!val) { + return null; + } + + return {model: model, value: val}; + }; + + cs.get.rgb = function (string) { + if (!string) { + return null; + } + + var abbr = /^#([a-f0-9]{3,4})$/i; + var hex = /^#([a-f0-9]{6})([a-f0-9]{2})?$/i; + var rgba = /^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/; + var per = /^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/; + var keyword = /(\D+)/; + + var rgb = [0, 0, 0, 1]; + var match; + var i; + var hexAlpha; + + if (match = string.match(hex)) { + hexAlpha = match[2]; + match = match[1]; + + for (i = 0; i < 3; i++) { + // https://jsperf.com/slice-vs-substr-vs-substring-methods-long-string/19 + var i2 = i * 2; + rgb[i] = parseInt(match.slice(i2, i2 + 2), 16); + } + + if (hexAlpha) { + rgb[3] = Math.round((parseInt(hexAlpha, 16) / 255) * 100) / 100; + } + } else if (match = string.match(abbr)) { + match = match[1]; + hexAlpha = match[3]; + + for (i = 0; i < 3; i++) { + rgb[i] = parseInt(match[i] + match[i], 16); + } + + if (hexAlpha) { + rgb[3] = Math.round((parseInt(hexAlpha + hexAlpha, 16) / 255) * 100) / 100; + } + } else if (match = string.match(rgba)) { + for (i = 0; i < 3; i++) { + rgb[i] = parseInt(match[i + 1], 0); + } + + if (match[4]) { + rgb[3] = parseFloat(match[4]); + } + } else if (match = string.match(per)) { + for (i = 0; i < 3; i++) { + rgb[i] = Math.round(parseFloat(match[i + 1]) * 2.55); + } + + if (match[4]) { + rgb[3] = parseFloat(match[4]); + } + } else if (match = string.match(keyword)) { + if (match[1] === 'transparent') { + return [0, 0, 0, 0]; + } + + rgb = colorName[match[1]]; + + if (!rgb) { + return null; + } + + rgb[3] = 1; + + return rgb; + } else { + return null; + } + + for (i = 0; i < 3; i++) { + rgb[i] = clamp(rgb[i], 0, 255); + } + rgb[3] = clamp(rgb[3], 0, 1); + + return rgb; + }; + + cs.get.hsl = function (string) { + if (!string) { + return null; + } + + var hsl = /^hsla?\(\s*([+-]?(?:\d*\.)?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/; + var match = string.match(hsl); + + if (match) { + var alpha = parseFloat(match[4]); + var h = (parseFloat(match[1]) + 360) % 360; + var s = clamp(parseFloat(match[2]), 0, 100); + var l = clamp(parseFloat(match[3]), 0, 100); + var a = clamp(isNaN(alpha) ? 1 : alpha, 0, 1); + + return [h, s, l, a]; + } + + return null; + }; + + cs.get.hwb = function (string) { + if (!string) { + return null; + } + + var hwb = /^hwb\(\s*([+-]?\d*[\.]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/; + var match = string.match(hwb); + + if (match) { + var alpha = parseFloat(match[4]); + var h = ((parseFloat(match[1]) % 360) + 360) % 360; + var w = clamp(parseFloat(match[2]), 0, 100); + var b = clamp(parseFloat(match[3]), 0, 100); + var a = clamp(isNaN(alpha) ? 1 : alpha, 0, 1); + return [h, w, b, a]; + } + + return null; + }; + + cs.to.hex = function () { + var rgba = simpleSwizzle(arguments); + + return ( + '#' + + hexDouble(rgba[0]) + + hexDouble(rgba[1]) + + hexDouble(rgba[2]) + + (rgba[3] < 1 + ? (hexDouble(Math.round(rgba[3] * 255))) + : '') + ); + }; + + cs.to.rgb = function () { + var rgba = simpleSwizzle(arguments); + + return rgba.length < 4 || rgba[3] === 1 + ? 'rgb(' + Math.round(rgba[0]) + ', ' + Math.round(rgba[1]) + ', ' + Math.round(rgba[2]) + ')' + : 'rgba(' + Math.round(rgba[0]) + ', ' + Math.round(rgba[1]) + ', ' + Math.round(rgba[2]) + ', ' + rgba[3] + ')'; + }; + + cs.to.rgb.percent = function () { + var rgba = simpleSwizzle(arguments); + + var r = Math.round(rgba[0] / 255 * 100); + var g = Math.round(rgba[1] / 255 * 100); + var b = Math.round(rgba[2] / 255 * 100); + + return rgba.length < 4 || rgba[3] === 1 + ? 'rgb(' + r + '%, ' + g + '%, ' + b + '%)' + : 'rgba(' + r + '%, ' + g + '%, ' + b + '%, ' + rgba[3] + ')'; + }; + + cs.to.hsl = function () { + var hsla = simpleSwizzle(arguments); + return hsla.length < 4 || hsla[3] === 1 + ? 'hsl(' + hsla[0] + ', ' + hsla[1] + '%, ' + hsla[2] + '%)' + : 'hsla(' + hsla[0] + ', ' + hsla[1] + '%, ' + hsla[2] + '%, ' + hsla[3] + ')'; + }; + + // hwb is a bit different than rgb(a) & hsl(a) since there is no alpha specific syntax + // (hwb have alpha optional & 1 is default value) + cs.to.hwb = function () { + var hwba = simpleSwizzle(arguments); + + var a = ''; + if (hwba.length >= 4 && hwba[3] !== 1) { + a = ', ' + hwba[3]; + } + + return 'hwb(' + hwba[0] + ', ' + hwba[1] + '%, ' + hwba[2] + '%' + a + ')'; + }; + + cs.to.keyword = function (rgb) { + return reverseNames[rgb.slice(0, 3)]; + }; + + // helpers + function clamp(num, min, max) { + return Math.min(Math.max(min, num), max); + } + + function hexDouble(num) { + var str = num.toString(16).toUpperCase(); + return (str.length < 2) ? '0' + str : str; + } + }); + var colorString_1 = colorString.to; + var colorString_2 = colorString.get; + + var conversions = createCommonjsModule(function (module) { + /* MIT license */ + + + // NOTE: conversions should only return primitive values (i.e. arrays, or + // values that give correct `typeof` results). + // do not use box values types (i.e. Number(), String(), etc.) + + var reverseKeywords = {}; + for (var key in colorName) { + if (colorName.hasOwnProperty(key)) { + reverseKeywords[colorName[key]] = key; + } + } + + var convert = module.exports = { + rgb: {channels: 3, labels: 'rgb'}, + hsl: {channels: 3, labels: 'hsl'}, + hsv: {channels: 3, labels: 'hsv'}, + hwb: {channels: 3, labels: 'hwb'}, + cmyk: {channels: 4, labels: 'cmyk'}, + xyz: {channels: 3, labels: 'xyz'}, + lab: {channels: 3, labels: 'lab'}, + lch: {channels: 3, labels: 'lch'}, + hex: {channels: 1, labels: ['hex']}, + keyword: {channels: 1, labels: ['keyword']}, + ansi16: {channels: 1, labels: ['ansi16']}, + ansi256: {channels: 1, labels: ['ansi256']}, + hcg: {channels: 3, labels: ['h', 'c', 'g']}, + apple: {channels: 3, labels: ['r16', 'g16', 'b16']}, + gray: {channels: 1, labels: ['gray']} + }; + + // hide .channels and .labels properties + for (var model in convert) { + if (convert.hasOwnProperty(model)) { + if (!('channels' in convert[model])) { + throw new Error('missing channels property: ' + model); + } + + if (!('labels' in convert[model])) { + throw new Error('missing channel labels property: ' + model); + } + + if (convert[model].labels.length !== convert[model].channels) { + throw new Error('channel and label counts mismatch: ' + model); + } + + var channels = convert[model].channels; + var labels = convert[model].labels; + delete convert[model].channels; + delete convert[model].labels; + Object.defineProperty(convert[model], 'channels', {value: channels}); + Object.defineProperty(convert[model], 'labels', {value: labels}); + } + } + + convert.rgb.hsl = function (rgb) { + var r = rgb[0] / 255; + var g = rgb[1] / 255; + var b = rgb[2] / 255; + var min = Math.min(r, g, b); + var max = Math.max(r, g, b); + var delta = max - min; + var h; + var s; + var l; + + if (max === min) { + h = 0; + } else if (r === max) { + h = (g - b) / delta; + } else if (g === max) { + h = 2 + (b - r) / delta; + } else if (b === max) { + h = 4 + (r - g) / delta; + } + + h = Math.min(h * 60, 360); + + if (h < 0) { + h += 360; + } + + l = (min + max) / 2; + + if (max === min) { + s = 0; + } else if (l <= 0.5) { + s = delta / (max + min); + } else { + s = delta / (2 - max - min); + } + + return [h, s * 100, l * 100]; + }; + + convert.rgb.hsv = function (rgb) { + var rdif; + var gdif; + var bdif; + var h; + var s; + + var r = rgb[0] / 255; + var g = rgb[1] / 255; + var b = rgb[2] / 255; + var v = Math.max(r, g, b); + var diff = v - Math.min(r, g, b); + var diffc = function (c) { + return (v - c) / 6 / diff + 1 / 2; + }; + + if (diff === 0) { + h = s = 0; + } else { + s = diff / v; + rdif = diffc(r); + gdif = diffc(g); + bdif = diffc(b); + + if (r === v) { + h = bdif - gdif; + } else if (g === v) { + h = (1 / 3) + rdif - bdif; + } else if (b === v) { + h = (2 / 3) + gdif - rdif; + } + if (h < 0) { + h += 1; + } else if (h > 1) { + h -= 1; + } + } + + return [ + h * 360, + s * 100, + v * 100 + ]; + }; + + convert.rgb.hwb = function (rgb) { + var r = rgb[0]; + var g = rgb[1]; + var b = rgb[2]; + var h = convert.rgb.hsl(rgb)[0]; + var w = 1 / 255 * Math.min(r, Math.min(g, b)); + + b = 1 - 1 / 255 * Math.max(r, Math.max(g, b)); + + return [h, w * 100, b * 100]; + }; + + convert.rgb.cmyk = function (rgb) { + var r = rgb[0] / 255; + var g = rgb[1] / 255; + var b = rgb[2] / 255; + var c; + var m; + var y; + var k; + + k = Math.min(1 - r, 1 - g, 1 - b); + c = (1 - r - k) / (1 - k) || 0; + m = (1 - g - k) / (1 - k) || 0; + y = (1 - b - k) / (1 - k) || 0; + + return [c * 100, m * 100, y * 100, k * 100]; + }; + + /** + * See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance + * */ + function comparativeDistance(x, y) { + return ( + Math.pow(x[0] - y[0], 2) + + Math.pow(x[1] - y[1], 2) + + Math.pow(x[2] - y[2], 2) + ); + } + + convert.rgb.keyword = function (rgb) { + var reversed = reverseKeywords[rgb]; + if (reversed) { + return reversed; + } + + var currentClosestDistance = Infinity; + var currentClosestKeyword; + + for (var keyword in colorName) { + if (colorName.hasOwnProperty(keyword)) { + var value = colorName[keyword]; + + // Compute comparative distance + var distance = comparativeDistance(rgb, value); + + // Check if its less, if so set as closest + if (distance < currentClosestDistance) { + currentClosestDistance = distance; + currentClosestKeyword = keyword; + } + } + } + + return currentClosestKeyword; + }; + + convert.keyword.rgb = function (keyword) { + return colorName[keyword]; + }; + + convert.rgb.xyz = function (rgb) { + var r = rgb[0] / 255; + var g = rgb[1] / 255; + var b = rgb[2] / 255; + + // assume sRGB + r = r > 0.04045 ? Math.pow(((r + 0.055) / 1.055), 2.4) : (r / 12.92); + g = g > 0.04045 ? Math.pow(((g + 0.055) / 1.055), 2.4) : (g / 12.92); + b = b > 0.04045 ? Math.pow(((b + 0.055) / 1.055), 2.4) : (b / 12.92); + + var x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805); + var y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722); + var z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505); + + return [x * 100, y * 100, z * 100]; + }; + + convert.rgb.lab = function (rgb) { + var xyz = convert.rgb.xyz(rgb); + var x = xyz[0]; + var y = xyz[1]; + var z = xyz[2]; + var l; + var a; + var b; + + x /= 95.047; + y /= 100; + z /= 108.883; + + x = x > 0.008856 ? Math.pow(x, 1 / 3) : (7.787 * x) + (16 / 116); + y = y > 0.008856 ? Math.pow(y, 1 / 3) : (7.787 * y) + (16 / 116); + z = z > 0.008856 ? Math.pow(z, 1 / 3) : (7.787 * z) + (16 / 116); + + l = (116 * y) - 16; + a = 500 * (x - y); + b = 200 * (y - z); + + return [l, a, b]; + }; + + convert.hsl.rgb = function (hsl) { + var h = hsl[0] / 360; + var s = hsl[1] / 100; + var l = hsl[2] / 100; + var t1; + var t2; + var t3; + var rgb; + var val; + + if (s === 0) { + val = l * 255; + return [val, val, val]; + } + + if (l < 0.5) { + t2 = l * (1 + s); + } else { + t2 = l + s - l * s; + } + + t1 = 2 * l - t2; + + rgb = [0, 0, 0]; + for (var i = 0; i < 3; i++) { + t3 = h + 1 / 3 * -(i - 1); + if (t3 < 0) { + t3++; + } + if (t3 > 1) { + t3--; + } + + if (6 * t3 < 1) { + val = t1 + (t2 - t1) * 6 * t3; + } else if (2 * t3 < 1) { + val = t2; + } else if (3 * t3 < 2) { + val = t1 + (t2 - t1) * (2 / 3 - t3) * 6; + } else { + val = t1; + } + + rgb[i] = val * 255; + } + + return rgb; + }; + + convert.hsl.hsv = function (hsl) { + var h = hsl[0]; + var s = hsl[1] / 100; + var l = hsl[2] / 100; + var smin = s; + var lmin = Math.max(l, 0.01); + var sv; + var v; + + l *= 2; + s *= (l <= 1) ? l : 2 - l; + smin *= lmin <= 1 ? lmin : 2 - lmin; + v = (l + s) / 2; + sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s); + + return [h, sv * 100, v * 100]; + }; + + convert.hsv.rgb = function (hsv) { + var h = hsv[0] / 60; + var s = hsv[1] / 100; + var v = hsv[2] / 100; + var hi = Math.floor(h) % 6; + + var f = h - Math.floor(h); + var p = 255 * v * (1 - s); + var q = 255 * v * (1 - (s * f)); + var t = 255 * v * (1 - (s * (1 - f))); + v *= 255; + + switch (hi) { + case 0: + return [v, t, p]; + case 1: + return [q, v, p]; + case 2: + return [p, v, t]; + case 3: + return [p, q, v]; + case 4: + return [t, p, v]; + case 5: + return [v, p, q]; + } + }; + + convert.hsv.hsl = function (hsv) { + var h = hsv[0]; + var s = hsv[1] / 100; + var v = hsv[2] / 100; + var vmin = Math.max(v, 0.01); + var lmin; + var sl; + var l; + + l = (2 - s) * v; + lmin = (2 - s) * vmin; + sl = s * vmin; + sl /= (lmin <= 1) ? lmin : 2 - lmin; + sl = sl || 0; + l /= 2; + + return [h, sl * 100, l * 100]; + }; + + // http://dev.w3.org/csswg/css-color/#hwb-to-rgb + convert.hwb.rgb = function (hwb) { + var h = hwb[0] / 360; + var wh = hwb[1] / 100; + var bl = hwb[2] / 100; + var ratio = wh + bl; + var i; + var v; + var f; + var n; + + // wh + bl cant be > 1 + if (ratio > 1) { + wh /= ratio; + bl /= ratio; + } + + i = Math.floor(6 * h); + v = 1 - bl; + f = 6 * h - i; + + if ((i & 0x01) !== 0) { + f = 1 - f; + } + + n = wh + f * (v - wh); // linear interpolation + + var r; + var g; + var b; + switch (i) { + default: + case 6: + case 0: r = v; g = n; b = wh; break; + case 1: r = n; g = v; b = wh; break; + case 2: r = wh; g = v; b = n; break; + case 3: r = wh; g = n; b = v; break; + case 4: r = n; g = wh; b = v; break; + case 5: r = v; g = wh; b = n; break; + } + + return [r * 255, g * 255, b * 255]; + }; + + convert.cmyk.rgb = function (cmyk) { + var c = cmyk[0] / 100; + var m = cmyk[1] / 100; + var y = cmyk[2] / 100; + var k = cmyk[3] / 100; + var r; + var g; + var b; + + r = 1 - Math.min(1, c * (1 - k) + k); + g = 1 - Math.min(1, m * (1 - k) + k); + b = 1 - Math.min(1, y * (1 - k) + k); + + return [r * 255, g * 255, b * 255]; + }; + + convert.xyz.rgb = function (xyz) { + var x = xyz[0] / 100; + var y = xyz[1] / 100; + var z = xyz[2] / 100; + var r; + var g; + var b; + + r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986); + g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415); + b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570); + + // assume sRGB + r = r > 0.0031308 + ? ((1.055 * Math.pow(r, 1.0 / 2.4)) - 0.055) + : r * 12.92; + + g = g > 0.0031308 + ? ((1.055 * Math.pow(g, 1.0 / 2.4)) - 0.055) + : g * 12.92; + + b = b > 0.0031308 + ? ((1.055 * Math.pow(b, 1.0 / 2.4)) - 0.055) + : b * 12.92; + + r = Math.min(Math.max(0, r), 1); + g = Math.min(Math.max(0, g), 1); + b = Math.min(Math.max(0, b), 1); + + return [r * 255, g * 255, b * 255]; + }; + + convert.xyz.lab = function (xyz) { + var x = xyz[0]; + var y = xyz[1]; + var z = xyz[2]; + var l; + var a; + var b; + + x /= 95.047; + y /= 100; + z /= 108.883; + + x = x > 0.008856 ? Math.pow(x, 1 / 3) : (7.787 * x) + (16 / 116); + y = y > 0.008856 ? Math.pow(y, 1 / 3) : (7.787 * y) + (16 / 116); + z = z > 0.008856 ? Math.pow(z, 1 / 3) : (7.787 * z) + (16 / 116); + + l = (116 * y) - 16; + a = 500 * (x - y); + b = 200 * (y - z); + + return [l, a, b]; + }; + + convert.lab.xyz = function (lab) { + var l = lab[0]; + var a = lab[1]; + var b = lab[2]; + var x; + var y; + var z; + + y = (l + 16) / 116; + x = a / 500 + y; + z = y - b / 200; + + var y2 = Math.pow(y, 3); + var x2 = Math.pow(x, 3); + var z2 = Math.pow(z, 3); + y = y2 > 0.008856 ? y2 : (y - 16 / 116) / 7.787; + x = x2 > 0.008856 ? x2 : (x - 16 / 116) / 7.787; + z = z2 > 0.008856 ? z2 : (z - 16 / 116) / 7.787; + + x *= 95.047; + y *= 100; + z *= 108.883; + + return [x, y, z]; + }; + + convert.lab.lch = function (lab) { + var l = lab[0]; + var a = lab[1]; + var b = lab[2]; + var hr; + var h; + var c; + + hr = Math.atan2(b, a); + h = hr * 360 / 2 / Math.PI; + + if (h < 0) { + h += 360; + } + + c = Math.sqrt(a * a + b * b); + + return [l, c, h]; + }; + + convert.lch.lab = function (lch) { + var l = lch[0]; + var c = lch[1]; + var h = lch[2]; + var a; + var b; + var hr; + + hr = h / 360 * 2 * Math.PI; + a = c * Math.cos(hr); + b = c * Math.sin(hr); + + return [l, a, b]; + }; + + convert.rgb.ansi16 = function (args) { + var r = args[0]; + var g = args[1]; + var b = args[2]; + var value = 1 in arguments ? arguments[1] : convert.rgb.hsv(args)[2]; // hsv -> ansi16 optimization + + value = Math.round(value / 50); + + if (value === 0) { + return 30; + } + + var ansi = 30 + + ((Math.round(b / 255) << 2) + | (Math.round(g / 255) << 1) + | Math.round(r / 255)); + + if (value === 2) { + ansi += 60; + } + + return ansi; + }; + + convert.hsv.ansi16 = function (args) { + // optimization here; we already know the value and don't need to get + // it converted for us. + return convert.rgb.ansi16(convert.hsv.rgb(args), args[2]); + }; + + convert.rgb.ansi256 = function (args) { + var r = args[0]; + var g = args[1]; + var b = args[2]; + + // we use the extended greyscale palette here, with the exception of + // black and white. normal palette only has 4 greyscale shades. + if (r === g && g === b) { + if (r < 8) { + return 16; + } + + if (r > 248) { + return 231; + } + + return Math.round(((r - 8) / 247) * 24) + 232; + } + + var ansi = 16 + + (36 * Math.round(r / 255 * 5)) + + (6 * Math.round(g / 255 * 5)) + + Math.round(b / 255 * 5); + + return ansi; + }; + + convert.ansi16.rgb = function (args) { + var color = args % 10; + + // handle greyscale + if (color === 0 || color === 7) { + if (args > 50) { + color += 3.5; + } + + color = color / 10.5 * 255; + + return [color, color, color]; + } + + var mult = (~~(args > 50) + 1) * 0.5; + var r = ((color & 1) * mult) * 255; + var g = (((color >> 1) & 1) * mult) * 255; + var b = (((color >> 2) & 1) * mult) * 255; + + return [r, g, b]; + }; + + convert.ansi256.rgb = function (args) { + // handle greyscale + if (args >= 232) { + var c = (args - 232) * 10 + 8; + return [c, c, c]; + } + + args -= 16; + + var rem; + var r = Math.floor(args / 36) / 5 * 255; + var g = Math.floor((rem = args % 36) / 6) / 5 * 255; + var b = (rem % 6) / 5 * 255; + + return [r, g, b]; + }; + + convert.rgb.hex = function (args) { + var integer = ((Math.round(args[0]) & 0xFF) << 16) + + ((Math.round(args[1]) & 0xFF) << 8) + + (Math.round(args[2]) & 0xFF); + + var string = integer.toString(16).toUpperCase(); + return '000000'.substring(string.length) + string; + }; + + convert.hex.rgb = function (args) { + var match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i); + if (!match) { + return [0, 0, 0]; + } + + var colorString = match[0]; + + if (match[0].length === 3) { + colorString = colorString.split('').map(function (char) { + return char + char; + }).join(''); + } + + var integer = parseInt(colorString, 16); + var r = (integer >> 16) & 0xFF; + var g = (integer >> 8) & 0xFF; + var b = integer & 0xFF; + + return [r, g, b]; + }; + + convert.rgb.hcg = function (rgb) { + var r = rgb[0] / 255; + var g = rgb[1] / 255; + var b = rgb[2] / 255; + var max = Math.max(Math.max(r, g), b); + var min = Math.min(Math.min(r, g), b); + var chroma = (max - min); + var grayscale; + var hue; + + if (chroma < 1) { + grayscale = min / (1 - chroma); + } else { + grayscale = 0; + } + + if (chroma <= 0) { + hue = 0; + } else + if (max === r) { + hue = ((g - b) / chroma) % 6; + } else + if (max === g) { + hue = 2 + (b - r) / chroma; + } else { + hue = 4 + (r - g) / chroma + 4; + } + + hue /= 6; + hue %= 1; + + return [hue * 360, chroma * 100, grayscale * 100]; + }; + + convert.hsl.hcg = function (hsl) { + var s = hsl[1] / 100; + var l = hsl[2] / 100; + var c = 1; + var f = 0; + + if (l < 0.5) { + c = 2.0 * s * l; + } else { + c = 2.0 * s * (1.0 - l); + } + + if (c < 1.0) { + f = (l - 0.5 * c) / (1.0 - c); + } + + return [hsl[0], c * 100, f * 100]; + }; + + convert.hsv.hcg = function (hsv) { + var s = hsv[1] / 100; + var v = hsv[2] / 100; + + var c = s * v; + var f = 0; + + if (c < 1.0) { + f = (v - c) / (1 - c); + } + + return [hsv[0], c * 100, f * 100]; + }; + + convert.hcg.rgb = function (hcg) { + var h = hcg[0] / 360; + var c = hcg[1] / 100; + var g = hcg[2] / 100; + + if (c === 0.0) { + return [g * 255, g * 255, g * 255]; + } + + var pure = [0, 0, 0]; + var hi = (h % 1) * 6; + var v = hi % 1; + var w = 1 - v; + var mg = 0; + + switch (Math.floor(hi)) { + case 0: + pure[0] = 1; pure[1] = v; pure[2] = 0; break; + case 1: + pure[0] = w; pure[1] = 1; pure[2] = 0; break; + case 2: + pure[0] = 0; pure[1] = 1; pure[2] = v; break; + case 3: + pure[0] = 0; pure[1] = w; pure[2] = 1; break; + case 4: + pure[0] = v; pure[1] = 0; pure[2] = 1; break; + default: + pure[0] = 1; pure[1] = 0; pure[2] = w; + } + + mg = (1.0 - c) * g; + + return [ + (c * pure[0] + mg) * 255, + (c * pure[1] + mg) * 255, + (c * pure[2] + mg) * 255 + ]; + }; + + convert.hcg.hsv = function (hcg) { + var c = hcg[1] / 100; + var g = hcg[2] / 100; + + var v = c + g * (1.0 - c); + var f = 0; + + if (v > 0.0) { + f = c / v; + } + + return [hcg[0], f * 100, v * 100]; + }; + + convert.hcg.hsl = function (hcg) { + var c = hcg[1] / 100; + var g = hcg[2] / 100; + + var l = g * (1.0 - c) + 0.5 * c; + var s = 0; + + if (l > 0.0 && l < 0.5) { + s = c / (2 * l); + } else + if (l >= 0.5 && l < 1.0) { + s = c / (2 * (1 - l)); + } + + return [hcg[0], s * 100, l * 100]; + }; + + convert.hcg.hwb = function (hcg) { + var c = hcg[1] / 100; + var g = hcg[2] / 100; + var v = c + g * (1.0 - c); + return [hcg[0], (v - c) * 100, (1 - v) * 100]; + }; + + convert.hwb.hcg = function (hwb) { + var w = hwb[1] / 100; + var b = hwb[2] / 100; + var v = 1 - b; + var c = v - w; + var g = 0; + + if (c < 1) { + g = (v - c) / (1 - c); + } + + return [hwb[0], c * 100, g * 100]; + }; + + convert.apple.rgb = function (apple) { + return [(apple[0] / 65535) * 255, (apple[1] / 65535) * 255, (apple[2] / 65535) * 255]; + }; + + convert.rgb.apple = function (rgb) { + return [(rgb[0] / 255) * 65535, (rgb[1] / 255) * 65535, (rgb[2] / 255) * 65535]; + }; + + convert.gray.rgb = function (args) { + return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255]; + }; + + convert.gray.hsl = convert.gray.hsv = function (args) { + return [0, 0, args[0]]; + }; + + convert.gray.hwb = function (gray) { + return [0, 100, gray[0]]; + }; + + convert.gray.cmyk = function (gray) { + return [0, 0, 0, gray[0]]; + }; + + convert.gray.lab = function (gray) { + return [gray[0], 0, 0]; + }; + + convert.gray.hex = function (gray) { + var val = Math.round(gray[0] / 100 * 255) & 0xFF; + var integer = (val << 16) + (val << 8) + val; + + var string = integer.toString(16).toUpperCase(); + return '000000'.substring(string.length) + string; + }; + + convert.rgb.gray = function (rgb) { + var val = (rgb[0] + rgb[1] + rgb[2]) / 3; + return [val / 255 * 100]; + }; + }); + var conversions_1 = conversions.rgb; + var conversions_2 = conversions.hsl; + var conversions_3 = conversions.hsv; + var conversions_4 = conversions.hwb; + var conversions_5 = conversions.cmyk; + var conversions_6 = conversions.xyz; + var conversions_7 = conversions.lab; + var conversions_8 = conversions.lch; + var conversions_9 = conversions.hex; + var conversions_10 = conversions.keyword; + var conversions_11 = conversions.ansi16; + var conversions_12 = conversions.ansi256; + var conversions_13 = conversions.hcg; + var conversions_14 = conversions.apple; + var conversions_15 = conversions.gray; + + /* + this function routes a model to all other models. + + all functions that are routed have a property `.conversion` attached + to the returned synthetic function. This property is an array + of strings, each with the steps in between the 'from' and 'to' + color models (inclusive). + + conversions that are not possible simply are not included. + */ + + function buildGraph() { + var graph = {}; + // https://jsperf.com/object-keys-vs-for-in-with-closure/3 + var models = Object.keys(conversions); + + for (var len = models.length, i = 0; i < len; i++) { + graph[models[i]] = { + // http://jsperf.com/1-vs-infinity + // micro-opt, but this is simple. + distance: -1, + parent: null + }; + } + + return graph; + } + + // https://en.wikipedia.org/wiki/Breadth-first_search + function deriveBFS(fromModel) { + var graph = buildGraph(); + var queue = [fromModel]; // unshift -> queue -> pop + + graph[fromModel].distance = 0; + + while (queue.length) { + var current = queue.pop(); + var adjacents = Object.keys(conversions[current]); + + for (var len = adjacents.length, i = 0; i < len; i++) { + var adjacent = adjacents[i]; + var node = graph[adjacent]; + + if (node.distance === -1) { + node.distance = graph[current].distance + 1; + node.parent = current; + queue.unshift(adjacent); + } + } + } + + return graph; + } + + function link(from, to) { + return function (args) { + return to(from(args)); + }; + } + + function wrapConversion(toModel, graph) { + var path = [graph[toModel].parent, toModel]; + var fn = conversions[graph[toModel].parent][toModel]; + + var cur = graph[toModel].parent; + while (graph[cur].parent) { + path.unshift(graph[cur].parent); + fn = link(conversions[graph[cur].parent][cur], fn); + cur = graph[cur].parent; + } + + fn.conversion = path; + return fn; + } + + var route = function (fromModel) { + var graph = deriveBFS(fromModel); + var conversion = {}; + + var models = Object.keys(graph); + for (var len = models.length, i = 0; i < len; i++) { + var toModel = models[i]; + var node = graph[toModel]; + + if (node.parent === null) { + // no possible conversion, or this node is the source model. + continue; + } + + conversion[toModel] = wrapConversion(toModel, graph); + } + + return conversion; + }; + + var convert = {}; + + var models = Object.keys(conversions); + + function wrapRaw(fn) { + var wrappedFn = function (args) { + if (args === undefined || args === null) { + return args; + } + + if (arguments.length > 1) { + args = Array.prototype.slice.call(arguments); + } + + return fn(args); + }; + + // preserve .conversion property if there is one + if ('conversion' in fn) { + wrappedFn.conversion = fn.conversion; + } + + return wrappedFn; + } + + function wrapRounded(fn) { + var wrappedFn = function (args) { + if (args === undefined || args === null) { + return args; + } + + if (arguments.length > 1) { + args = Array.prototype.slice.call(arguments); + } + + var result = fn(args); + + // we're assuming the result is an array here. + // see notice in conversions.js; don't use box types + // in conversion functions. + if (typeof result === 'object') { + for (var len = result.length, i = 0; i < len; i++) { + result[i] = Math.round(result[i]); + } + } + + return result; + }; + + // preserve .conversion property if there is one + if ('conversion' in fn) { + wrappedFn.conversion = fn.conversion; + } + + return wrappedFn; + } + + models.forEach(function (fromModel) { + convert[fromModel] = {}; + + Object.defineProperty(convert[fromModel], 'channels', {value: conversions[fromModel].channels}); + Object.defineProperty(convert[fromModel], 'labels', {value: conversions[fromModel].labels}); + + var routes = route(fromModel); + var routeModels = Object.keys(routes); + + routeModels.forEach(function (toModel) { + var fn = routes[toModel]; + + convert[fromModel][toModel] = wrapRounded(fn); + convert[fromModel][toModel].raw = wrapRaw(fn); + }); + }); + + var colorConvert = convert; + + var _slice = [].slice; + + var skippedModels = [ + // to be honest, I don't really feel like keyword belongs in color convert, but eh. + 'keyword', + + // gray conflicts with some method names, and has its own method defined. + 'gray', + + // shouldn't really be in color-convert either... + 'hex' + ]; + + var hashedModelKeys = {}; + Object.keys(colorConvert).forEach(function (model) { + hashedModelKeys[_slice.call(colorConvert[model].labels).sort().join('')] = model; + }); + + var limiters = {}; + + function Color(obj, model) { + if (!(this instanceof Color)) { + return new Color(obj, model); + } + + if (model && model in skippedModels) { + model = null; + } + + if (model && !(model in colorConvert)) { + throw new Error('Unknown model: ' + model); + } + + var i; + var channels; + + if (obj == null) { // eslint-disable-line no-eq-null,eqeqeq + this.model = 'rgb'; + this.color = [0, 0, 0]; + this.valpha = 1; + } else if (obj instanceof Color) { + this.model = obj.model; + this.color = obj.color.slice(); + this.valpha = obj.valpha; + } else if (typeof obj === 'string') { + var result = colorString.get(obj); + if (result === null) { + throw new Error('Unable to parse color from string: ' + obj); + } + + this.model = result.model; + channels = colorConvert[this.model].channels; + this.color = result.value.slice(0, channels); + this.valpha = typeof result.value[channels] === 'number' ? result.value[channels] : 1; + } else if (obj.length) { + this.model = model || 'rgb'; + channels = colorConvert[this.model].channels; + var newArr = _slice.call(obj, 0, channels); + this.color = zeroArray(newArr, channels); + this.valpha = typeof obj[channels] === 'number' ? obj[channels] : 1; + } else if (typeof obj === 'number') { + // this is always RGB - can be converted later on. + obj &= 0xFFFFFF; + this.model = 'rgb'; + this.color = [ + (obj >> 16) & 0xFF, + (obj >> 8) & 0xFF, + obj & 0xFF + ]; + this.valpha = 1; + } else { + this.valpha = 1; + + var keys = Object.keys(obj); + if ('alpha' in obj) { + keys.splice(keys.indexOf('alpha'), 1); + this.valpha = typeof obj.alpha === 'number' ? obj.alpha : 0; + } + + var hashedKeys = keys.sort().join(''); + if (!(hashedKeys in hashedModelKeys)) { + throw new Error('Unable to parse color from object: ' + JSON.stringify(obj)); + } + + this.model = hashedModelKeys[hashedKeys]; + + var labels = colorConvert[this.model].labels; + var color = []; + for (i = 0; i < labels.length; i++) { + color.push(obj[labels[i]]); + } + + this.color = zeroArray(color); + } + + // perform limitations (clamping, etc.) + if (limiters[this.model]) { + channels = colorConvert[this.model].channels; + for (i = 0; i < channels; i++) { + var limit = limiters[this.model][i]; + if (limit) { + this.color[i] = limit(this.color[i]); + } + } + } + + this.valpha = Math.max(0, Math.min(1, this.valpha)); + + if (Object.freeze) { + Object.freeze(this); + } + } + + Color.prototype = { + toString: function () { + return this.string(); + }, + + toJSON: function () { + return this[this.model](); + }, + + string: function (places) { + var self = this.model in colorString.to ? this : this.rgb(); + self = self.round(typeof places === 'number' ? places : 1); + var args = self.valpha === 1 ? self.color : self.color.concat(this.valpha); + return colorString.to[self.model](args); + }, + + percentString: function (places) { + var self = this.rgb().round(typeof places === 'number' ? places : 1); + var args = self.valpha === 1 ? self.color : self.color.concat(this.valpha); + return colorString.to.rgb.percent(args); + }, + + array: function () { + return this.valpha === 1 ? this.color.slice() : this.color.concat(this.valpha); + }, + + object: function () { + var result = {}; + var channels = colorConvert[this.model].channels; + var labels = colorConvert[this.model].labels; + + for (var i = 0; i < channels; i++) { + result[labels[i]] = this.color[i]; + } + + if (this.valpha !== 1) { + result.alpha = this.valpha; + } + + return result; + }, + + unitArray: function () { + var rgb = this.rgb().color; + rgb[0] /= 255; + rgb[1] /= 255; + rgb[2] /= 255; + + if (this.valpha !== 1) { + rgb.push(this.valpha); + } + + return rgb; + }, + + unitObject: function () { + var rgb = this.rgb().object(); + rgb.r /= 255; + rgb.g /= 255; + rgb.b /= 255; + + if (this.valpha !== 1) { + rgb.alpha = this.valpha; + } + + return rgb; + }, + + round: function (places) { + places = Math.max(places || 0, 0); + return new Color(this.color.map(roundToPlace(places)).concat(this.valpha), this.model); + }, + + alpha: function (val) { + if (arguments.length) { + return new Color(this.color.concat(Math.max(0, Math.min(1, val))), this.model); + } + + return this.valpha; + }, + + // rgb + red: getset('rgb', 0, maxfn(255)), + green: getset('rgb', 1, maxfn(255)), + blue: getset('rgb', 2, maxfn(255)), + + hue: getset(['hsl', 'hsv', 'hsl', 'hwb', 'hcg'], 0, function (val) { return ((val % 360) + 360) % 360; }), // eslint-disable-line brace-style + + saturationl: getset('hsl', 1, maxfn(100)), + lightness: getset('hsl', 2, maxfn(100)), + + saturationv: getset('hsv', 1, maxfn(100)), + value: getset('hsv', 2, maxfn(100)), + + chroma: getset('hcg', 1, maxfn(100)), + gray: getset('hcg', 2, maxfn(100)), + + white: getset('hwb', 1, maxfn(100)), + wblack: getset('hwb', 2, maxfn(100)), + + cyan: getset('cmyk', 0, maxfn(100)), + magenta: getset('cmyk', 1, maxfn(100)), + yellow: getset('cmyk', 2, maxfn(100)), + black: getset('cmyk', 3, maxfn(100)), + + x: getset('xyz', 0, maxfn(100)), + y: getset('xyz', 1, maxfn(100)), + z: getset('xyz', 2, maxfn(100)), + + l: getset('lab', 0, maxfn(100)), + a: getset('lab', 1), + b: getset('lab', 2), + + keyword: function (val) { + if (arguments.length) { + return new Color(val); + } + + return colorConvert[this.model].keyword(this.color); + }, + + hex: function (val) { + if (arguments.length) { + return new Color(val); + } + + return colorString.to.hex(this.rgb().round().color); + }, + + rgbNumber: function () { + var rgb = this.rgb().color; + return ((rgb[0] & 0xFF) << 16) | ((rgb[1] & 0xFF) << 8) | (rgb[2] & 0xFF); + }, + + luminosity: function () { + // http://www.w3.org/TR/WCAG20/#relativeluminancedef + var rgb = this.rgb().color; + + var lum = []; + for (var i = 0; i < rgb.length; i++) { + var chan = rgb[i] / 255; + lum[i] = (chan <= 0.03928) ? chan / 12.92 : Math.pow(((chan + 0.055) / 1.055), 2.4); + } + + return 0.2126 * lum[0] + 0.7152 * lum[1] + 0.0722 * lum[2]; + }, + + contrast: function (color2) { + // http://www.w3.org/TR/WCAG20/#contrast-ratiodef + var lum1 = this.luminosity(); + var lum2 = color2.luminosity(); + + if (lum1 > lum2) { + return (lum1 + 0.05) / (lum2 + 0.05); + } + + return (lum2 + 0.05) / (lum1 + 0.05); + }, + + level: function (color2) { + var contrastRatio = this.contrast(color2); + if (contrastRatio >= 7.1) { + return 'AAA'; + } + + return (contrastRatio >= 4.5) ? 'AA' : ''; + }, + + isDark: function () { + // YIQ equation from http://24ways.org/2010/calculating-color-contrast + var rgb = this.rgb().color; + var yiq = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000; + return yiq < 128; + }, + + isLight: function () { + return !this.isDark(); + }, + + negate: function () { + var rgb = this.rgb(); + for (var i = 0; i < 3; i++) { + rgb.color[i] = 255 - rgb.color[i]; + } + return rgb; + }, + + lighten: function (ratio) { + var hsl = this.hsl(); + hsl.color[2] += hsl.color[2] * ratio; + return hsl; + }, + + darken: function (ratio) { + var hsl = this.hsl(); + hsl.color[2] -= hsl.color[2] * ratio; + return hsl; + }, + + saturate: function (ratio) { + var hsl = this.hsl(); + hsl.color[1] += hsl.color[1] * ratio; + return hsl; + }, + + desaturate: function (ratio) { + var hsl = this.hsl(); + hsl.color[1] -= hsl.color[1] * ratio; + return hsl; + }, + + whiten: function (ratio) { + var hwb = this.hwb(); + hwb.color[1] += hwb.color[1] * ratio; + return hwb; + }, + + blacken: function (ratio) { + var hwb = this.hwb(); + hwb.color[2] += hwb.color[2] * ratio; + return hwb; + }, + + grayscale: function () { + // http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale + var rgb = this.rgb().color; + var val = rgb[0] * 0.3 + rgb[1] * 0.59 + rgb[2] * 0.11; + return Color.rgb(val, val, val); + }, + + fade: function (ratio) { + return this.alpha(this.valpha - (this.valpha * ratio)); + }, + + opaquer: function (ratio) { + return this.alpha(this.valpha + (this.valpha * ratio)); + }, + + rotate: function (degrees) { + var hsl = this.hsl(); + var hue = hsl.color[0]; + hue = (hue + degrees) % 360; + hue = hue < 0 ? 360 + hue : hue; + hsl.color[0] = hue; + return hsl; + }, + + mix: function (mixinColor, weight) { + // ported from sass implementation in C + // https://github.com/sass/libsass/blob/0e6b4a2850092356aa3ece07c6b249f0221caced/functions.cpp#L209 + if (!mixinColor || !mixinColor.rgb) { + throw new Error('Argument to "mix" was not a Color instance, but rather an instance of ' + typeof mixinColor); + } + var color1 = mixinColor.rgb(); + var color2 = this.rgb(); + var p = weight === undefined ? 0.5 : weight; + + var w = 2 * p - 1; + var a = color1.alpha() - color2.alpha(); + + var w1 = (((w * a === -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + return Color.rgb( + w1 * color1.red() + w2 * color2.red(), + w1 * color1.green() + w2 * color2.green(), + w1 * color1.blue() + w2 * color2.blue(), + color1.alpha() * p + color2.alpha() * (1 - p)); + } + }; + + // model conversion methods and static constructors + Object.keys(colorConvert).forEach(function (model) { + if (skippedModels.indexOf(model) !== -1) { + return; + } + + var channels = colorConvert[model].channels; + + // conversion methods + Color.prototype[model] = function () { + if (this.model === model) { + return new Color(this); + } + + if (arguments.length) { + return new Color(arguments, model); + } + + var newAlpha = typeof arguments[channels] === 'number' ? channels : this.valpha; + return new Color(assertArray(colorConvert[this.model][model].raw(this.color)).concat(newAlpha), model); + }; + + // 'static' construction methods + Color[model] = function (color) { + if (typeof color === 'number') { + color = zeroArray(_slice.call(arguments), channels); + } + return new Color(color, model); + }; + }); + + function roundTo(num, places) { + return Number(num.toFixed(places)); + } + + function roundToPlace(places) { + return function (num) { + return roundTo(num, places); + }; + } + + function getset(model, channel, modifier) { + model = Array.isArray(model) ? model : [model]; + + model.forEach(function (m) { + (limiters[m] || (limiters[m] = []))[channel] = modifier; + }); + + model = model[0]; + + return function (val) { + var result; + + if (arguments.length) { + if (modifier) { + val = modifier(val); + } + + result = this[model](); + result.color[channel] = val; + return result; + } + + result = this[model]().color[channel]; + if (modifier) { + result = modifier(result); + } + + return result; + }; + } + + function maxfn(max) { + return function (v) { + return Math.max(0, Math.min(max, v)); + }; + } + + function assertArray(val) { + return Array.isArray(val) ? val : [val]; + } + + function zeroArray(arr, length) { + for (var i = 0; i < length; i++) { + if (typeof arr[i] !== 'number') { + arr[i] = 0; + } + } + + return arr; + } + + var color = Color; + + var pickr_es5_min = createCommonjsModule(function (module, exports) { + /*! Pickr 1.5.1 MIT | https://github.com/Simonwep/pickr */ + !function(t,e){module.exports=e();}(window,(function(){return function(t){var e={};function r(n){if(e[n]){ return e[n].exports; }var o=e[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=t,r.c=e,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n});},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0});},r.t=function(t,e){if(1&e&&(t=r(t)),8&e){ return t; }if(4&e&&"object"==typeof t&&t&&t.__esModule){ return t; }var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t){ for(var o in t){ r.d(n,o,function(e){return t[e]}.bind(null,o)); } }return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=144)}([function(t,e,r){var n=r(3),o=r(15).f,i=r(11),a=r(17),c=r(43),u=r(75),s=r(79);t.exports=function(t,e){var r,l,f,p,v,h=t.target,d=t.global,g=t.stat;if(r=d?n:g?n[h]||c(h,{}):(n[h]||{}).prototype){ for(l in e){if(p=e[l],f=t.noTargetGet?(v=o(r,l))&&v.value:r[l],!s(d?l:h+(g?".":"#")+l,t.forced)&&void 0!==f){if(typeof p==typeof f){ continue; }u(p,f);}(t.sham||f&&f.sham)&&i(p,"sham",!0),a(r,l,p,t);} }};},function(t,e){t.exports=function(t){try{return !!t()}catch(t){return !0}};},function(t,e,r){var n=r(3),o=r(44),i=r(4),a=r(45),c=r(50),u=r(80),s=o("wks"),l=n.Symbol,f=u?l:l&&l.withoutSetter||a;t.exports=function(t){return i(s,t)||(c&&i(l,t)?s[t]=l[t]:s[t]=f("Symbol."+t)),s[t]};},function(t,e,r){(function(e){var r=function(t){return t&&t.Math==Math&&t};t.exports=r("object"==typeof globalThis&&globalThis)||r("object"==typeof window&&window)||r("object"==typeof self&&self)||r("object"==typeof e&&e)||Function("return this")();}).call(this,r(105));},function(t,e){var r={}.hasOwnProperty;t.exports=function(t,e){return r.call(t,e)};},function(t,e,r){var n=r(7);t.exports=function(t){if(!n(t)){ throw TypeError(String(t)+" is not an object"); }return t};},function(t,e,r){var n=r(1);t.exports=!n((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]}));},function(t,e){t.exports=function(t){return "object"==typeof t?null!==t:"function"==typeof t};},function(t,e,r){var n=r(18),o=Math.min;t.exports=function(t){return t>0?o(n(t),9007199254740991):0};},function(t,e,r){var n=r(21),o=r(10);t.exports=function(t){return n(o(t))};},function(t,e){t.exports=function(t){if(null==t){ throw TypeError("Can't call method on "+t); }return t};},function(t,e,r){var n=r(6),o=r(12),i=r(20);t.exports=n?function(t,e,r){return o.f(t,e,i(1,r))}:function(t,e,r){return t[e]=r,t};},function(t,e,r){var n=r(6),o=r(71),i=r(5),a=r(22),c=Object.defineProperty;e.f=n?c:function(t,e,r){if(i(t),e=a(e,!0),i(r),o){ try{return c(t,e,r)}catch(t){} }if("get"in r||"set"in r){ throw TypeError("Accessors not supported"); }return "value"in r&&(t[e]=r.value),t};},function(t,e,r){var n=r(10);t.exports=function(t){return Object(n(t))};},function(t,e,r){var n=r(6),o=r(1),i=r(4),a=Object.defineProperty,c={},u=function(t){throw t};t.exports=function(t,e){if(i(c,t)){ return c[t]; }e||(e={});var r=[][t],s=!!i(e,"ACCESSORS")&&e.ACCESSORS,l=i(e,0)?e[0]:u,f=i(e,1)?e[1]:void 0;return c[t]=!!r&&!o((function(){if(s&&!n){ return !0; }var t={length:-1};s?a(t,1,{enumerable:!0,get:u}):t[1]=1,r.call(t,l,f);}))};},function(t,e,r){var n=r(6),o=r(42),i=r(20),a=r(9),c=r(22),u=r(4),s=r(71),l=Object.getOwnPropertyDescriptor;e.f=n?l:function(t,e){if(t=a(t),e=c(e,!0),s){ try{return l(t,e)}catch(t){} }if(u(t,e)){ return i(!o.f.call(t,e),t[e]) }};},function(t,e){var r={}.toString;t.exports=function(t){return r.call(t).slice(8,-1)};},function(t,e,r){var n=r(3),o=r(11),i=r(4),a=r(43),c=r(73),u=r(30),s=u.get,l=u.enforce,f=String(String).split("String");(t.exports=function(t,e,r,c){var u=!!c&&!!c.unsafe,s=!!c&&!!c.enumerable,p=!!c&&!!c.noTargetGet;"function"==typeof r&&("string"!=typeof e||i(r,"name")||o(r,"name",e),l(r).source=f.join("string"==typeof e?e:"")),t!==n?(u?!p&&t[e]&&(s=!0):delete t[e],s?t[e]=r:o(t,e,r)):s?t[e]=r:a(e,r);})(Function.prototype,"toString",(function(){return "function"==typeof this&&s(this).source||c(this)}));},function(t,e){var r=Math.ceil,n=Math.floor;t.exports=function(t){return isNaN(t=+t)?0:(t>0?n:r)(t)};},function(t,e,r){var n=r(83),o=r(21),i=r(13),a=r(8),c=r(53),u=[].push,s=function(t){var e=1==t,r=2==t,s=3==t,l=4==t,f=6==t,p=5==t||f;return function(v,h,d,g){for(var y,b,m=i(v),x=o(m),S=n(h,d,3),w=a(x.length),_=0,A=g||c,O=e?A(v,w):r?A(v,0):void 0;w>_;_++){ if((p||_ in x)&&(b=S(y=x[_],_,m),t)){ if(e){ O[_]=b; }else if(b){ switch(t){case 3:return !0;case 5:return y;case 6:return _;case 2:u.call(O,y);} }else if(l){ return !1; } } }return f?-1:s||l?l:O}};t.exports={forEach:s(0),map:s(1),filter:s(2),some:s(3),every:s(4),find:s(5),findIndex:s(6)};},function(t,e){t.exports=function(t,e){return {enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}};},function(t,e,r){var n=r(1),o=r(16),i="".split;t.exports=n((function(){return !Object("z").propertyIsEnumerable(0)}))?function(t){return "String"==o(t)?i.call(t,""):Object(t)}:Object;},function(t,e,r){var n=r(7);t.exports=function(t,e){if(!n(t)){ return t; }var r,o;if(e&&"function"==typeof(r=t.toString)&&!n(o=r.call(t))){ return o; }if("function"==typeof(r=t.valueOf)&&!n(o=r.call(t))){ return o; }if(!e&&"function"==typeof(r=t.toString)&&!n(o=r.call(t))){ return o; }throw TypeError("Can't convert object to primitive value")};},function(t,e){t.exports=!1;},function(t,e,r){var n=r(22),o=r(12),i=r(20);t.exports=function(t,e,r){var a=n(e);a in t?o.f(t,a,i(0,r)):t[a]=r;};},function(t,e,r){var n=r(1),o=r(2),i=r(84),a=o("species");t.exports=function(t){return i>=51||!n((function(){var e=[];return (e.constructor={})[a]=function(){return {foo:1}},1!==e[t](Boolean).foo}))};},function(t,e,r){var n=r(1);t.exports=function(t,e){var r=[][t];return !!r&&n((function(){r.call(null,e||function(){throw 1},1);}))};},function(t,e){t.exports={};},function(t,e,r){var n=r(61),o=r(17),i=r(119);n||o(Object.prototype,"toString",i,{unsafe:!0});},function(t,e,r){var n=r(0),o=r(40);n({target:"RegExp",proto:!0,forced:/./.exec!==o},{exec:o});},function(t,e,r){var n,o,i,a=r(106),c=r(3),u=r(7),s=r(11),l=r(4),f=r(31),p=r(32),v=c.WeakMap;if(a){var h=new v,d=h.get,g=h.has,y=h.set;n=function(t,e){return y.call(h,t,e),e},o=function(t){return d.call(h,t)||{}},i=function(t){return g.call(h,t)};}else{var b=f("state");p[b]=!0,n=function(t,e){return s(t,b,e),e},o=function(t){return l(t,b)?t[b]:{}},i=function(t){return l(t,b)};}t.exports={set:n,get:o,has:i,enforce:function(t){return i(t)?o(t):n(t,{})},getterFor:function(t){return function(e){var r;if(!u(e)||(r=o(e)).type!==t){ throw TypeError("Incompatible receiver, "+t+" required"); }return r}}};},function(t,e,r){var n=r(44),o=r(45),i=n("keys");t.exports=function(t){return i[t]||(i[t]=o(t))};},function(t,e){t.exports={};},function(t,e,r){var n=r(77),o=r(3),i=function(t){return "function"==typeof t?t:void 0};t.exports=function(t,e){return arguments.length<2?i(n[t])||i(o[t]):n[t]&&n[t][e]||o[t]&&o[t][e]};},function(t,e,r){var n=r(78),o=r(48).concat("length","prototype");e.f=Object.getOwnPropertyNames||function(t){return n(t,o)};},function(t,e,r){var n=r(16);t.exports=Array.isArray||function(t){return "Array"==n(t)};},function(t,e,r){var n,o=r(5),i=r(107),a=r(48),c=r(32),u=r(108),s=r(72),l=r(31),f=l("IE_PROTO"),p=function(){},v=function(t){return " - - + diff --git a/package.json b/package.json index 77cb7ee..80342ee 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,92 @@ { - "name": "color-converter", - "version": "0.0.1", + "private": true, + "name": "yacc", + "version": "0.1.0", + "scripts": { + "start": "npm run watch", + "watch": "tarima watch src", + "build": "npm run min-css && npm run min-js", + "min-css": "uglify -s build/css/main.css -o build/css/main.css -c", + "min-js": "uglify -s build/js/main.js -o build/js/main.js", + "svg": "svg-sprite -s --symbol-dest=svg-sprite-symbol --symbol-prefix=.svg- --ss=sprite.svg --si --sx --shape-id-generator=svg-%s --dest=src/assets src/assets/svg/*.svg" + }, + "author": "", + "license": "MIT", + "dependencies": { + "@simonwep/pickr": "^1.5.1", + "color": "^3.1.2", + "copy-text-to-clipboard": "^2.1.1" + }, "devDependencies": { - "grunt": "^1.0.1", - "grunt-contrib-sass": "^1.0.0", - "grunt-contrib-watch": "^1.0.0", - "load-grunt-tasks": "^3.5.2" + "postcss": "6.0.23", + "postcss-cssnext": "^3.1.0", + "postcss-discard-comments": "^4.0.2", + "postcss-import": "9.0.0", + "rollup": "^1.31.0", + "rollup-plugin-buble": "^0.19.8", + "rollup-plugin-commonjs": "^10.1.0", + "rollup-plugin-node-resolve": "^5.2.0", + "tarima": "^4.6.3" + }, + "tarima": { + "bundle": [ + "**/bundles/**" + ], + "filter": [ + "**/bundles/**" + ], + "cwd": ".", + "public": "./", + "from": [ + "src" + ], + "output": "build", + "watching": [ + "index.html" + ], + "ignoreFiles": [ + ".gitignore" + ], + "rename": [ + "**/bundles/**:{basedir/1/bundles/}/{fname}" + ], + "bundleOptions": { + "extensions": { + "js": "es6", + "css": "post" + }, + "postcss": { + "plugins": [ + "postcss-import", + "postcss-cssnext", + "postcss-discard-comments" + ], + "postcss-import": { + "path": [ + "src/css/lib" + ] + }, + "postcss-cssnext": { + "features": { + "customProperties": false, + "calc": false + } + } + }, + "rollup": { + "plugins": [ + "rollup-plugin-node-resolve", + "rollup-plugin-commonjs", + "rollup-plugin-buble" + ], + "rollup-plugin-node-resolve": { + "mainFields": [ + "module", + "jsnext:main", + "browser" + ] + } + } + } } } diff --git a/public/images/android-chrome-192x192.png b/public/images/android-chrome-192x192.png new file mode 100755 index 0000000..30ea267 Binary files /dev/null and b/public/images/android-chrome-192x192.png differ diff --git a/public/images/android-chrome-512x512.png b/public/images/android-chrome-512x512.png new file mode 100755 index 0000000..46f1362 Binary files /dev/null and b/public/images/android-chrome-512x512.png differ diff --git a/public/images/apple-touch-icon.png b/public/images/apple-touch-icon.png new file mode 100755 index 0000000..1f821e2 Binary files /dev/null and b/public/images/apple-touch-icon.png differ diff --git a/public/images/favicon-16x16.png b/public/images/favicon-16x16.png new file mode 100755 index 0000000..8911610 Binary files /dev/null and b/public/images/favicon-16x16.png differ diff --git a/public/images/favicon-32x32.png b/public/images/favicon-32x32.png new file mode 100755 index 0000000..148c5f2 Binary files /dev/null and b/public/images/favicon-32x32.png differ diff --git a/public/images/favicon.ico b/public/images/favicon.ico new file mode 100755 index 0000000..16ad2e7 Binary files /dev/null and b/public/images/favicon.ico differ diff --git a/public/site.webmanifest b/public/site.webmanifest new file mode 100755 index 0000000..50e8d81 --- /dev/null +++ b/public/site.webmanifest @@ -0,0 +1,20 @@ +{ + "name":"Yet another color converter", + "short_name":"YACC", + "icons":[ + { + "src":"/public/images/android-chrome-192x192.png", + "type":"image/png", + "sizes":"192x192" + }, + { + "src":"/public/images/android-chrome-512x512.png", + "type":"image/png", + "sizes":"512x512" + } + ], + "start_url": "/#FFFFFF", + "background_color":"#ffffff", + "display":"standalone", + "theme_color":"#ffffff" +} diff --git a/source/javascripts/script.js b/source/javascripts/script.js deleted file mode 100644 index 47bfa71..0000000 --- a/source/javascripts/script.js +++ /dev/null @@ -1,154 +0,0 @@ -(function(global) { - - "use strict"; - - // instance of Values.js - global.Color = new Values('rgb(255, 0, 0)'); - - var colorFormats = { - UI: { - hex: document.querySelector('.js-hex'), - rgb: document.querySelector('.js-rgb'), - hsl: document.querySelector('.js-hsl'), - wrapper: document.querySelector('.main-container--inner'), - links: document.querySelectorAll('.footer a'), - body: document.body - }, - - init: function init () { - this.UI._links = [].slice.call(this.UI.links, 0); - this.hash = global.location.hash; - this.bindEvents(); - - if (Values.Utils.isHEX(this.hash)) { - this.UI.hex.value = this.hash; - this.updateFromHex(this.hash); - } else global.location.hash = ''; - - return this; - }, - - bindEvents: function bindEvents () { - addEvent(this.UI.hex, "keyup", this.hexKeyUpEvent); - addEvent(this.UI.rgb, "keyup", this.rgbKeyUpEvent); - addEvent(this.UI.hsl, "keyup", this.hslKeyUpEvent); - - return this; - }, - - - hexKeyUpEvent: function hexKeyUpEvent () { - if (Values.Utils.isHEX(this.value)) { - colorFormats.updateFromHex(this.value); - - return true; - } - - colorFormats.UI.rgb.value = ''; - colorFormats.UI.hsl.value = ''; - return false; - }, - - rgbKeyUpEvent: function rgbKeyUpEvent () { - if (Values.Utils.isRGB(this.value)) { - colorFormats.updateFromRGB(this.value); - - return true; - } - - colorFormats.UI.hex.value = ''; - colorFormats.UI.hsl.value = ''; - - return false; - }, - - hslKeyUpEvent: function hslKeyUpEvent () { - if (Values.Utils.isHSL(this.value)) { - colorFormats.updateFromHSL(this.value); - - return this; - } - - colorFormats.UI.hex.value = ''; - colorFormats.UI.rgb.value = ''; - - return false; - }, - - updateFromHex: function updateFromHex (value) { - Color.setColor(value); - this.updateUIColors(); - this.UI.rgb.value = Color.rgbString(); - this.UI.hsl.value = Color.hslString(); - this.updateHash(Color.hex); - }, - - updateFromRGB: function updateFromRGB (value) { - Color.setColor(value); - this.updateUIColors(); - this.UI.hex.value = Color.hexString(); - this.UI.hsl.value = Color.hslString(); - this.updateHash(Color.hex); - }, - - updateFromHSL: function updateFromHSL (value) { - Color.setColor(value); - this.updateUIColors(); - this.UI.hex.value = Color.hexString(); - this.UI.rgb.value = Color.rgbString(); - this.updateHash(Color.hex); - }, - - updateHash: function updateHash (value) { - this.hash = value; - global.location.hash = this.hash; - }, - - updateUIColors: function updateUIColors () { - var isLight, bgClr, txtClr, borderClr; - - isLight = (Color.getBrightness() > 50); - bgClr = Color.hexString(); - txtClr = isLight ? Color.shade(50) : Color.tint(50); - borderClr = isLight ? Color.shade(10) : Color.tint(10); - - this.UI.body.style.backgroundColor = bgClr; - this.UI.body.style.color = txtClr.hexString(); - this.UI.wrapper.style.borderBottomColor = borderClr.hexString(); - - this.UI._links.forEach(function(el) { - el.style.color = txtClr.hex; - }); - - if (Syringe.rules) { - Syringe.remove('::selection'); - } - - Syringe.inject({ - '::selection': { - background: isLight ? 'rgba(0,0,0,.1)' : 'rgba(255,255,255,.2)' - } - }); - - bgClr = txtClr = null; - - return this; - } - }; - - var addEvent = function addEvent (obj, type, fn) { - if (obj.addEventListener) { - obj.addEventListener(type, fn, false); - } - else if (obj.attachEvent) { - obj['e' + type + fn] = fn; - obj[type + fn] = function() { - obj['e' + type + fn](window.event); - }; - obj.attachEvent("on" + type, obj[type + fn]); - } - }; - - // init the thing - colorFormats.init(); -})(window); diff --git a/source/sass/_normalize.scss b/source/sass/_normalize.scss deleted file mode 100644 index 57b5d26..0000000 --- a/source/sass/_normalize.scss +++ /dev/null @@ -1,375 +0,0 @@ -/*! normalize.css v2.0.1 | MIT License | git.io/normalize */ - -/* ========================================================================== - HTML5 display definitions - ========================================================================== */ - -/* - * Corrects `block` display not defined in IE 8/9. - */ - -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -nav, -section, -summary { - display: block; -} - -/* - * Corrects `inline-block` display not defined in IE 8/9. - */ - -audio, -canvas, -video { - display: inline-block; -} - -/* - * Prevents modern browsers from displaying `audio` without controls. - * Remove excess height in iOS 5 devices. - */ - -audio:not([controls]) { - display: none; - height: 0; -} - -/* - * Addresses styling for `hidden` attribute not present in IE 8/9. - */ - -[hidden] { - display: none; -} - -/* ========================================================================== - Base - ========================================================================== */ - -/* - * 1. Sets default font family to sans-serif. - * 2. Prevents iOS text size adjust after orientation change, without disabling - * user zoom. - */ - -html { - font-family: sans-serif; /* 1 */ - -webkit-text-size-adjust: 100%; /* 2 */ - -ms-text-size-adjust: 100%; /* 2 */ -} - -/* - * Removes default margin. - */ - -body { - margin: 0; -} - -/* ========================================================================== - Links - ========================================================================== */ - -/* - * Addresses `outline` inconsistency between Chrome and other browsers. - */ - -a:focus { - outline: thin dotted; -} - -/* - * Improves readability when focused and also mouse hovered in all browsers. - */ - -a:active, -a:hover { - outline: 0; -} - -/* ========================================================================== - Typography - ========================================================================== */ - -/* - * Addresses `h1` font sizes within `section` and `article` in Firefox 4+, - * Safari 5, and Chrome. - */ - -h1 { - font-size: 2em; -} - -/* - * Addresses styling not present in IE 8/9, Safari 5, and Chrome. - */ - -abbr[title] { - border-bottom: 1px dotted; -} - -/* - * Addresses style set to `bolder` in Firefox 4+, Safari 5, and Chrome. - */ - -b, -strong { - font-weight: bold; -} - -/* - * Addresses styling not present in Safari 5 and Chrome. - */ - -dfn { - font-style: italic; -} - -/* - * Addresses styling not present in IE 8/9. - */ - -mark { - background: #ff0; - color: #000; -} - - -/* - * Corrects font family set oddly in Safari 5 and Chrome. - */ - -code, -kbd, -pre, -samp { - font-family: monospace, serif; - font-size: 1em; -} - -/* - * Improves readability of pre-formatted text in all browsers. - */ - -pre { - white-space: pre; - white-space: pre-wrap; - word-wrap: break-word; -} - -/* - * Sets consistent quote types. - */ - -q { - quotes: "\201C" "\201D" "\2018" "\2019"; -} - -/* - * Addresses inconsistent and variable font size in all browsers. - */ - -small { - font-size: 80%; -} - -/* - * Prevents `sub` and `sup` affecting `line-height` in all browsers. - */ - -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} - -sup { - top: -0.5em; -} - -sub { - bottom: -0.25em; -} - -/* ========================================================================== - Embedded content - ========================================================================== */ - -/* - * Removes border when inside `a` element in IE 8/9. - */ - -img { - border: 0; -} - -/* - * Corrects overflow displayed oddly in IE 9. - */ - -svg:not(:root) { - overflow: hidden; -} - -/* ========================================================================== - Figures - ========================================================================== */ - -/* - * Addresses margin not present in IE 8/9 and Safari 5. - */ - -figure { - margin: 0; -} - -/* ========================================================================== - Forms - ========================================================================== */ - -/* - * Define consistent border, margin, and padding. - */ - -fieldset { - border: 1px solid #c0c0c0; - margin: 0 2px; - padding: 0.35em 0.625em 0.75em; -} - -/* - * 1. Corrects color not being inherited in IE 8/9. - * 2. Remove padding so people aren't caught out if they zero out fieldsets. - */ - -legend { - border: 0; /* 1 */ - padding: 0; /* 2 */ -} - -/* - * 1. Corrects font family not being inherited in all browsers. - * 2. Corrects font size not being inherited in all browsers. - * 3. Addresses margins set differently in Firefox 4+, Safari 5, and Chrome - */ - -button, -input, -select, -textarea { - font-family: inherit; /* 1 */ - font-size: 100%; /* 2 */ - margin: 0; /* 3 */ -} - -/* - * Addresses Firefox 4+ setting `line-height` on `input` using `!important` in - * the UA stylesheet. - */ - -button, -input { - line-height: normal; -} - -/* - * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` - * and `video` controls. - * 2. Corrects inability to style clickable `input` types in iOS. - * 3. Improves usability and consistency of cursor style between image-type - * `input` and others. - */ - -button, -html input[type="button"], /* 1 */ -input[type="reset"], -input[type="submit"] { - -webkit-appearance: button; /* 2 */ - cursor: pointer; /* 3 */ -} - -/* - * Re-set default cursor for disabled elements. - */ - -button[disabled], -input[disabled] { - cursor: default; -} - -/* - * 1. Addresses box sizing set to `content-box` in IE 8/9. - * 2. Removes excess padding in IE 8/9. - */ - -input[type="checkbox"], -input[type="radio"] { - box-sizing: border-box; /* 1 */ - padding: 0; /* 2 */ -} - -/* - * 1. Addresses `appearance` set to `searchfield` in Safari 5 and Chrome. - * 2. Addresses `box-sizing` set to `border-box` in Safari 5 and Chrome - * (include `-moz` to future-proof). - */ - -input[type="search"] { - -webkit-appearance: textfield; /* 1 */ - -moz-box-sizing: content-box; - -webkit-box-sizing: content-box; /* 2 */ - box-sizing: content-box; -} - -/* - * Removes inner padding and search cancel button in Safari 5 and Chrome - * on OS X. - */ - -input[type="search"]::-webkit-search-cancel-button, -input[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; -} - -/* - * Removes inner padding and border in Firefox 4+. - */ - -button::-moz-focus-inner, -input::-moz-focus-inner { - border: 0; - padding: 0; -} - -/* - * 1. Removes default vertical scrollbar in IE 8/9. - * 2. Improves readability and alignment in all browsers. - */ - -textarea { - overflow: auto; /* 1 */ - vertical-align: top; /* 2 */ -} - -/* ========================================================================== - Tables - ========================================================================== */ - -/* - * Remove most spacing between table cells. - */ - -table { - border-collapse: collapse; - border-spacing: 0; -} diff --git a/source/sass/project.scss b/source/sass/project.scss deleted file mode 100644 index c43c835..0000000 --- a/source/sass/project.scss +++ /dev/null @@ -1,96 +0,0 @@ -@import 'normalize', url(//fonts.googleapis.com/css?family=Lato:100,400); - -* { - box-sizing: border-box; -} - -html, -body { - height: 100%; -} - -body { - font-family: 'Lato', sans-serif; - font-size: 12px; - color: #999; - transform: translateZ(0); - transition: color 400ms ease-in-out, background-color 400ms ease-in-out; -} - -a { - text-decoration: none; - color: #ccc; - transition: opacity 400ms; - - &:hover {opacity: .7} -} - -.main-content { - display: table; - max-width: 500px; - height: 100%; - vertical-align: middle; - margin: 0 auto; -} - -.main-container--inner { - display: table-cell; - vertical-align: middle; - border-bottom-color: rgba(0,0,0,.25); -} - -input { - display: block; - border: none; - border-bottom-width: 1px; - border-bottom-style: solid; - border-bottom-color: inherit; - width: 100%; - font-size: 45px; - line-height: 1.5em; - font-weight: 100; - background: rgba(0, 0, 0, 0); - color: inherit; - text-align: center; - outline: none; - transition: border-color 400ms ease-in-out; - - &::-webkit-input-placeholder { - color: inherit; - } -} - -.footer { - position: absolute; - bottom: 15px; - right: 20px; - font-size: 9px; - text-transform: uppercase; - color: inherit; - - p { - margin: 0 5px; - display: inline-block; - } -} - -@media all and (max-width: 500px) { - body { - padding: 0 20px; - } - - input { - font-size: 30px; - font-weight: 400; - } - - .footer { - width: 100%; - text-align: center; - right: 0; - p { - display: block; - margin: 0; - } - } -} diff --git a/source/stylesheets/project.css b/source/stylesheets/project.css deleted file mode 100644 index a56a1b6..0000000 --- a/source/stylesheets/project.css +++ /dev/null @@ -1,138 +0,0 @@ -/*! normalize.css v2.0.1 | MIT License | git.io/normalize */ -/* ========================================================================== HTML5 display definitions ========================================================================== */ -/* Corrects `block` display not defined in IE 8/9. */ -@import url(//fonts.googleapis.com/css?family=Lato:100,400); -article, aside, details, figcaption, figure, footer, header, hgroup, nav, section, summary { display: block; } - -/* Corrects `inline-block` display not defined in IE 8/9. */ -audio, canvas, video { display: inline-block; } - -/* Prevents modern browsers from displaying `audio` without controls. Remove excess height in iOS 5 devices. */ -audio:not([controls]) { display: none; height: 0; } - -/* Addresses styling for `hidden` attribute not present in IE 8/9. */ -[hidden] { display: none; } - -/* ========================================================================== Base ========================================================================== */ -/* 1. Sets default font family to sans-serif. 2. Prevents iOS text size adjust after orientation change, without disabling user zoom. */ -html { font-family: sans-serif; /* 1 */ -webkit-text-size-adjust: 100%; /* 2 */ -ms-text-size-adjust: 100%; /* 2 */ } - -/* Removes default margin. */ -body { margin: 0; } - -/* ========================================================================== Links ========================================================================== */ -/* Addresses `outline` inconsistency between Chrome and other browsers. */ -a:focus { outline: thin dotted; } - -/* Improves readability when focused and also mouse hovered in all browsers. */ -a:active, a:hover { outline: 0; } - -/* ========================================================================== Typography ========================================================================== */ -/* Addresses `h1` font sizes within `section` and `article` in Firefox 4+, Safari 5, and Chrome. */ -h1 { font-size: 2em; } - -/* Addresses styling not present in IE 8/9, Safari 5, and Chrome. */ -abbr[title] { border-bottom: 1px dotted; } - -/* Addresses style set to `bolder` in Firefox 4+, Safari 5, and Chrome. */ -b, strong { font-weight: bold; } - -/* Addresses styling not present in Safari 5 and Chrome. */ -dfn { font-style: italic; } - -/* Addresses styling not present in IE 8/9. */ -mark { background: #ff0; color: #000; } - -/* Corrects font family set oddly in Safari 5 and Chrome. */ -code, kbd, pre, samp { font-family: monospace, serif; font-size: 1em; } - -/* Improves readability of pre-formatted text in all browsers. */ -pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; } - -/* Sets consistent quote types. */ -q { quotes: "\201C" "\201D" "\2018" "\2019"; } - -/* Addresses inconsistent and variable font size in all browsers. */ -small { font-size: 80%; } - -/* Prevents `sub` and `sup` affecting `line-height` in all browsers. */ -sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } - -sup { top: -0.5em; } - -sub { bottom: -0.25em; } - -/* ========================================================================== Embedded content ========================================================================== */ -/* Removes border when inside `a` element in IE 8/9. */ -img { border: 0; } - -/* Corrects overflow displayed oddly in IE 9. */ -svg:not(:root) { overflow: hidden; } - -/* ========================================================================== Figures ========================================================================== */ -/* Addresses margin not present in IE 8/9 and Safari 5. */ -figure { margin: 0; } - -/* ========================================================================== Forms ========================================================================== */ -/* Define consistent border, margin, and padding. */ -fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; } - -/* 1. Corrects color not being inherited in IE 8/9. 2. Remove padding so people aren't caught out if they zero out fieldsets. */ -legend { border: 0; /* 1 */ padding: 0; /* 2 */ } - -/* 1. Corrects font family not being inherited in all browsers. 2. Corrects font size not being inherited in all browsers. 3. Addresses margins set differently in Firefox 4+, Safari 5, and Chrome */ -button, input, select, textarea { font-family: inherit; /* 1 */ font-size: 100%; /* 2 */ margin: 0; /* 3 */ } - -/* Addresses Firefox 4+ setting `line-height` on `input` using `!important` in the UA stylesheet. */ -button, input { line-height: normal; } - -/* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` and `video` controls. 2. Corrects inability to style clickable `input` types in iOS. 3. Improves usability and consistency of cursor style between image-type `input` and others. */ -button, html input[type="button"], input[type="reset"], input[type="submit"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ } - -/* Re-set default cursor for disabled elements. */ -button[disabled], input[disabled] { cursor: default; } - -/* 1. Addresses box sizing set to `content-box` in IE 8/9. 2. Removes excess padding in IE 8/9. */ -input[type="checkbox"], input[type="radio"] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ } - -/* 1. Addresses `appearance` set to `searchfield` in Safari 5 and Chrome. 2. Addresses `box-sizing` set to `border-box` in Safari 5 and Chrome (include `-moz` to future-proof). */ -input[type="search"] { -webkit-appearance: textfield; /* 1 */ -moz-box-sizing: content-box; -webkit-box-sizing: content-box; /* 2 */ box-sizing: content-box; } - -/* Removes inner padding and search cancel button in Safari 5 and Chrome on OS X. */ -input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; } - -/* Removes inner padding and border in Firefox 4+. */ -button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; } - -/* 1. Removes default vertical scrollbar in IE 8/9. 2. Improves readability and alignment in all browsers. */ -textarea { overflow: auto; /* 1 */ vertical-align: top; /* 2 */ } - -/* ========================================================================== Tables ========================================================================== */ -/* Remove most spacing between table cells. */ -table { border-collapse: collapse; border-spacing: 0; } - -* { box-sizing: border-box; } - -html, body { height: 100%; } - -body { font-family: 'Lato', sans-serif; font-size: 12px; color: #999; transform: translateZ(0); transition: color 400ms ease-in-out, background-color 400ms ease-in-out; } - -a { text-decoration: none; color: #ccc; transition: opacity 400ms; } -a:hover { opacity: .7; } - -.main-content { display: table; max-width: 500px; height: 100%; vertical-align: middle; margin: 0 auto; } - -.main-container--inner { display: table-cell; vertical-align: middle; border-bottom-color: rgba(0, 0, 0, 0.25); } - -input { display: block; border: none; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: inherit; width: 100%; font-size: 45px; line-height: 1.5em; font-weight: 100; background: transparent; color: inherit; text-align: center; outline: none; transition: border-color 400ms ease-in-out; } -input::-webkit-input-placeholder { color: inherit; } - -.footer { position: absolute; bottom: 15px; right: 20px; font-size: 9px; text-transform: uppercase; color: inherit; } -.footer p { margin: 0 5px; display: inline-block; } - -@media all and (max-width: 500px) { body { padding: 0 20px; } - input { font-size: 30px; font-weight: 400; } - .footer { width: 100%; text-align: center; right: 0; } - .footer p { display: block; margin: 0; } } - -/*# sourceMappingURL=project.css.map */ diff --git a/source/stylesheets/project.css.map b/source/stylesheets/project.css.map deleted file mode 100644 index b87462b..0000000 --- a/source/stylesheets/project.css.map +++ /dev/null @@ -1,7 +0,0 @@ -{ -"version": 3, -"mappings": ";;;AAAqB,2DAAmD;ACUxE,0FAUQ,GACJ,OAAO,EAAE,KAAK;;;AAOlB,oBAEM,GACF,OAAO,EAAE,YAAY;;;AAQzB,qBAAsB,GAClB,OAAO,EAAE,IAAI,EACb,MAAM,EAAE,CAAC;;;AAOb,QAAS,GACL,OAAO,EAAE,IAAI;;;;AAajB,IAAK,GACD,WAAW,EAAE,UAAU,UACvB,wBAAwB,EAAE,IAAI,UAC9B,oBAAoB,EAAE,IAAI;;;AAO9B,IAAK,GACD,MAAM,EAAE,CAAC;;;;AAWb,OAAQ,GACJ,OAAO,EAAE,WAAW;;;AAOxB,iBACQ,GACJ,OAAO,EAAE,CAAC;;;;AAYd,EAAG,GACC,SAAS,EAAE,GAAG;;;AAOlB,WAAY,GACR,aAAa,EAAE,UAAU;;;AAO7B,SACO,GACH,WAAW,EAAE,IAAI;;;AAOrB,GAAI,GACA,UAAU,EAAE,MAAM;;;AAOtB,IAAK,GACD,UAAU,EAAE,IAAI,EAChB,KAAK,EAAE,IAAI;;;AAQf,oBAGK,GACD,WAAW,EAAE,gBAAgB,EAC7B,SAAS,EAAE,GAAG;;;AAOlB,GAAI,GACA,WAAW,EAAE,GAAG,EAChB,WAAW,EAAE,QAAQ,EACrB,SAAS,EAAE,UAAU;;;AAOzB,CAAE,GACE,MAAM,EAAE,+BAA+B;;;AAO3C,KAAM,GACF,SAAS,EAAE,GAAG;;;AAOlB,QACI,GACA,SAAS,EAAE,GAAG,EACd,WAAW,EAAE,CAAC,EACd,QAAQ,EAAE,QAAQ,EAClB,cAAc,EAAE,QAAQ;;AAG5B,GAAI,GACA,GAAG,EAAE,MAAM;;AAGf,GAAI,GACA,MAAM,EAAE,OAAO;;;;AAWnB,GAAI,GACA,MAAM,EAAE,CAAC;;;AAOb,cAAe,GACX,QAAQ,EAAE,MAAM;;;;AAWpB,MAAO,GACH,MAAM,EAAE,CAAC;;;;AAWb,QAAS,GACL,MAAM,EAAE,iBAAiB,EACzB,MAAM,EAAE,KAAK,EACb,OAAO,EAAE,qBAAqB;;;AAQlC,MAAO,GACH,MAAM,EAAE,CAAC,UACT,OAAO,EAAE,CAAC;;;AASd,+BAGS,GACL,WAAW,EAAE,OAAO,UACpB,SAAS,EAAE,IAAI,UACf,MAAM,EAAE,CAAC;;;AAQb,aACM,GACF,WAAW,EAAE,MAAM;;;AAWvB,4EAGqB,GACjB,kBAAkB,EAAE,MAAM,UAC1B,MAAM,EAAE,OAAO;;;AAOnB,iCACgB,GACZ,MAAM,EAAE,OAAO;;;AAQnB,2CACoB,GAChB,UAAU,EAAE,UAAU,UACtB,OAAO,EAAE,CAAC;;;AASd,oBAAqB,GACjB,kBAAkB,EAAE,SAAS,UAC7B,eAAe,EAAE,WAAW,EAC5B,kBAAkB,EAAE,WAAW,UAC/B,UAAU,EAAE,WAAW;;;AAQ3B,mGACgD,GAC5C,kBAAkB,EAAE,IAAI;;;AAO5B,iDACwB,GACpB,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,CAAC;;;AAQd,QAAS,GACL,QAAQ,EAAE,IAAI,UACd,cAAc,EAAE,GAAG;;;;AAWvB,KAAM,GACF,eAAe,EAAE,QAAQ,EACzB,cAAc,EAAE,CAAC;;ADnXrB,CAAE,GACA,UAAU,EAAE,UAAU;;AAGxB,UACK,GACH,MAAM,EAAE,IAAI;;AAGd,IAAK,GACH,WAAW,EAAE,kBAAkB,EAC/B,SAAS,EAAE,IAAI,EACf,KAAK,EAAE,IAAI,EACX,SAAS,EAAE,aAAa,EACxB,UAAU,EAAE,2DAA2D;;AAGzE,CAAE,GACA,eAAe,EAAE,IAAI,EACrB,KAAK,EAAE,IAAI,EACX,UAAU,EAAE,aAAa;AAEzB,OAAQ,GAAC,OAAO,EAAE,EAAE;;AAGtB,aAAc,GACZ,OAAO,EAAE,KAAK,EACd,SAAS,EAAE,KAAK,EAChB,MAAM,EAAE,IAAI,EACZ,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM;;AAGhB,sBAAuB,GACrB,OAAO,EAAE,UAAU,EACnB,cAAc,EAAE,MAAM,EACtB,mBAAmB,EAAE,mBAAe;;AAGtC,KAAM,GACJ,OAAO,EAAE,KAAK,EACd,MAAM,EAAE,IAAI,EACZ,mBAAmB,EAAE,GAAG,EACxB,mBAAmB,EAAE,KAAK,EAC1B,mBAAmB,EAAE,OAAO,EAC5B,KAAK,EAAE,IAAI,EACX,SAAS,EAAE,IAAI,EACf,WAAW,EAAE,KAAK,EAClB,WAAW,EAAE,GAAG,EAChB,UAAU,EAAE,WAAgB,EAC5B,KAAK,EAAE,OAAO,EACd,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,IAAI,EACb,UAAU,EAAE,8BAA8B;AAE1C,gCAA6B,GAC3B,KAAK,EAAE,OAAO;;AAIlB,OAAQ,GACN,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,IAAI,EACZ,KAAK,EAAE,IAAI,EACX,SAAS,EAAE,GAAG,EACd,cAAc,EAAE,SAAS,EACzB,KAAK,EAAE,OAAO;AAEd,SAAE,GACA,MAAM,EAAE,KAAK,EACb,OAAO,EAAE,YAAY;;AAIzB,iCAAkC,GAChC,IAAK,GACH,OAAO,EAAE,MAAM;EAGjB,KAAM,GACJ,SAAS,EAAE,IAAI,EACf,WAAW,EAAE,GAAG;EAGlB,OAAQ,GACN,KAAK,EAAE,IAAI,EACX,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,CAAC;EACR,SAAE,GACA,OAAO,EAAE,KAAK,EACd,MAAM,EAAE,CAAC", -"sources": ["../sass/project.scss","../sass/_normalize.scss"], -"names": [], -"file": "project.css" -} diff --git a/src/assets/svg/colorize-24px.svg b/src/assets/svg/colorize-24px.svg new file mode 100644 index 0000000..56e6eb0 --- /dev/null +++ b/src/assets/svg/colorize-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svg/file_copy-outlined-24px.svg b/src/assets/svg/file_copy-outlined-24px.svg new file mode 100644 index 0000000..1d9dd09 --- /dev/null +++ b/src/assets/svg/file_copy-outlined-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svg/shuffle-round-24px.svg b/src/assets/svg/shuffle-round-24px.svg new file mode 100644 index 0000000..72b8334 --- /dev/null +++ b/src/assets/svg/shuffle-round-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/css/bundles/main.css b/src/css/bundles/main.css new file mode 100644 index 0000000..0bbc9ee --- /dev/null +++ b/src/css/bundles/main.css @@ -0,0 +1,51 @@ +/** +--- +$bundle: true +--- +*/ +@import '@simonwep/pickr/dist/themes/nano.min.css'; +@import '../lib/vendor-overrides/github-corners'; +@import '../lib/vendor-overrides/pickr'; +@import '../lib/components/buttons'; +@import '../lib/components/color-item'; +@import '../lib/components/inputs'; +@import '../lib/components/toast'; +@import '../lib/utils'; +@import '../lib/style'; + +:root { + --cc-main-color: #fff; + --cc-text-color: #000; + --cc-border-color: #e6e6e6; + + --cc-transition-timing: ease-out; + --cc-transition-duration: 260ms; + + font-family: system-ui; + font-size: 16px; +} + +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +body { + user-select: none; + font-kerning: none; +} + +a { + display: inline-flex; + align-items: center; + color: inherit; +} + +svg { + fill: currentColor; +} + +[disabled] { + opacity: 0.5; +} diff --git a/src/css/lib/components/buttons.css b/src/css/lib/components/buttons.css new file mode 100644 index 0000000..72c09c6 --- /dev/null +++ b/src/css/lib/components/buttons.css @@ -0,0 +1,45 @@ +button { + font-weight: inherit; + border: 2px solid var(--cc-border-color); + background-color: var(--cc-text-color); + color: var(--cc-main-color); + transition: all var(--cc-transition-duration) var(--cc-transition-timing); + transition-property: color, background-color, border-color, box-shadow; + + &:focus { + box-shadow: var(--cc-border-color) 0 0 0 0.25em; + } + + &:active { + background-color: var(--cc-border-color); + box-shadow: none; + } +} + +.cc-btn { + border-radius: 3px; + border: none; + padding: 0.5rem 1rem; + + & > * { + display: inline-block; + vertical-align: middle; + } +} + +button.cc-btn-icon { + width: 64px; + height: 64px; + border-radius: 50%; + padding: 0; + + &.cc-btn-sm { + width: 48px; + height: 48px; + + & > svg { + display: block; + margin: 0 auto; + } + } +} diff --git a/src/css/lib/components/color-item.css b/src/css/lib/components/color-item.css new file mode 100644 index 0000000..3da18cd --- /dev/null +++ b/src/css/lib/components/color-item.css @@ -0,0 +1,58 @@ +:root { + --cc-fsd: 10; + --cc-color-item-input-font-size: { + font-size: calc(100vw / var(--cc-fsd)); + + @media (min-width: 500px) { + font-size: calc(100vw / (var(--cc-fsd) - 1)); + } + + @media (min-width: 1000px) { + font-size: calc(1000px / var(--cc-fsd)); + } + } +} + +.cc-color-item { + display: flex; + + &.-hex { + --cc-fsd: 7; + @apply --cc-color-item-input-font-size; + margin: -0.1em 0 -0.2em; + } + + &.-rgb { + --cc-fsd: 12; + @apply --cc-color-item-input-font-size; + } + + &.-hsl { + --cc-fsd: 13; + @apply --cc-color-item-input-font-size; + } + + &.-hwb { + --cc-fsd: 13; + @apply --cc-color-item-input-font-size; + } +} + +.cc-color-item__label { + display: flex; + align-items: center; + font-size: 0.75rem; + padding: 0 0.5rem 0 1rem; + + & > span { + width: 10px; + writing-mode: vertical-lr; + transform: rotate(180deg); + } +} + +.cc-color-item__btn { + display: flex; + align-items: center; + padding: 0 0.5rem 0 0; +} diff --git a/src/css/lib/components/inputs.css b/src/css/lib/components/inputs.css new file mode 100644 index 0000000..3d5c512 --- /dev/null +++ b/src/css/lib/components/inputs.css @@ -0,0 +1,25 @@ +.cc-input { + border: none; + width: 100%; + font-family: inherit; + font-size: inherit; + padding: 0; + margin: 0; + font-weight: 900; + letter-spacing: -2px; + background: rgba(0, 0, 0, 0); + color: inherit; + outline: none; + text-overflow: ellipsis; + + &:invalid, + &[aria-invalid="true"] { + text-decoration: underline wavy red; + text-decoration-skip-ink: none; + } + + &::placeholder { + color: inherit; + opacity: 0.25; + } +} diff --git a/src/css/lib/components/toast.css b/src/css/lib/components/toast.css new file mode 100644 index 0000000..e74e1e4 --- /dev/null +++ b/src/css/lib/components/toast.css @@ -0,0 +1,24 @@ +.toast-wrapper { + pointer-events: none; + position: fixed; + top: 1rem; + left: 1rem; + + &.show > .toast { + opacity: 1; + transform: translate3d(0, 0, 0); + } +} + +.toast { + display: inline-block; + padding: 0.75rem 1.25rem; + font-weight: 400; + background: var(--cc-text-color); + color: var(--cc-main-color); + border-radius: 3px; + opacity: 0; + transform: translate3d(-1rem, 0, 0); + transition: all var(--cc-transition-duration) var(--cc-transition-timing); + transition-property: opacity, transform; +} diff --git a/src/css/lib/style.css b/src/css/lib/style.css new file mode 100644 index 0000000..0b00db8 --- /dev/null +++ b/src/css/lib/style.css @@ -0,0 +1,102 @@ +html, +body { height: 100%; } + +body { + line-height: 1; + font-weight: 800; + + color: var(--cc-text-color); + background-color: var(--cc-main-color); + + transition: all var(--cc-transition-duration) var(--cc-transition-timing); + transition-property: color, background-color; + + &::before, &::after { + content: ''; + position: fixed; + left: 0; + width: 0.5rem; + height: 50%; + } + + &::before { + background: black; + top: 0; + } + + &::after { + background: white; + top: 50%; + } +} + +::selection { + background: var(--cc-text-color); + color: var(--cc-main-color); +} + +.root { + margin: auto 0; + padding: 2rem 0; +} + +header { + position: relative; + padding: 0 1rem; + font-style: italic; +} + +.logo { + width: 16px; + height: 16px; + display: inline-block; + border-radius: 50%; + background-image: + radial-gradient(circle at top center, #F00 50%, transparent 100%), + radial-gradient(circle at bottom right, #0F0 50%, transparent 100%), + radial-gradient(circle at bottom left, #00F 50%, transparent 100%) + ; + background-blend-mode: lighten; + box-shadow: 0 0 0 1px var(--cc-border-color); +} + +.cc-extra-items { + padding: 1rem 0 0 0; +} + +footer { + font-size: 0.625rem; + padding: 1.5rem 1rem 0 2rem; + + & a { + transition: opacity 300ms linear; + &:hover { opacity: 0.7; } + } + + & > .footer__info { + position: relative; + flex-direction: column; + justify-content: center; + padding-left: 2rem; + margin-left: 2rem; + + &::before { + content: ''; + position: absolute; + left: 0; + top: 25%; + bottom: 25%; + border-left-width: 1px; + border-left-style: dotted; + } + } +} + +.cc-by { + font-size: 0.625rem; + position: fixed; + bottom: 1rem; + right: 1rem; + font-size: 0.75rem; +} + diff --git a/src/css/lib/utils.css b/src/css/lib/utils.css new file mode 100644 index 0000000..53fe0db --- /dev/null +++ b/src/css/lib/utils.css @@ -0,0 +1,5 @@ + +.df { display: flex } +.aic { align-items: center } +.mr1 { margin-right: 0.5rem } +.tdn { text-decoration: none } diff --git a/src/css/lib/vendor-overrides/github-corners.css b/src/css/lib/vendor-overrides/github-corners.css new file mode 100644 index 0000000..8551086 --- /dev/null +++ b/src/css/lib/vendor-overrides/github-corners.css @@ -0,0 +1,31 @@ +/** + * https://github.com/tholman/github-corners + */ +.github-corner { + position: absolute; + top: 0; + border: 0; + right: 0; + + & .octo-arm, + & .octo-body { + fill: var(--cc-main-color); + transition: fill var(--cc-transition-duration) var(--cc-transition-timing); + } + + &:hover .octo-arm { + animation: octocat-wave 560ms ease-in-out; + } + + @media (max-width:500px){ + &:hover .octo-arm { animation: none; } + & .octo-arm { animation: octocat-wave 560ms ease-in-out; } + } +} + + +@keyframes octocat-wave { + 0%, 100% { transform:rotate(0) } + 20%, 60% { transform:rotate(-25deg) } + 40%, 80% { transform:rotate(10deg) } +} diff --git a/src/css/lib/vendor-overrides/pickr.css b/src/css/lib/vendor-overrides/pickr.css new file mode 100644 index 0000000..c915511 --- /dev/null +++ b/src/css/lib/vendor-overrides/pickr.css @@ -0,0 +1,12 @@ +/** + * https://github.com/Simonwep/pickr + */ +.pcr-app[data-theme=nano] { + & .pcr-selection .pcr-color-chooser { + grid-area: 2/1/2/3; + } + + & .pcr-swatches { + margin: 0; + } +} diff --git a/src/js/bundles/main.js b/src/js/bundles/main.js new file mode 100644 index 0000000..e93ae5b --- /dev/null +++ b/src/js/bundles/main.js @@ -0,0 +1,21 @@ +/** +--- +$bundle: true +--- +*/ +import Color from 'color'; +import App from '~/src/js/lib/app.js'; + +const data = { color: document.location.hash }; + +try { + Color(data.color) +} +catch (err) { + data.color = '#FFFFFF'; +} + +const app = new App(data); +app.run(); + +// window.app = app; diff --git a/src/js/lib/app.js b/src/js/lib/app.js new file mode 100644 index 0000000..fd0f0bf --- /dev/null +++ b/src/js/lib/app.js @@ -0,0 +1,270 @@ +const { log } = console; + +import Color from 'color'; +import Pickr from '@simonwep/pickr/dist/pickr.es5.min'; +import Copy from 'copy-text-to-clipboard'; +import Input from '~/src/js/lib/components/input.js'; +import Toast from '~/src/js/lib/components/toast.js'; +import CS from '~/src/js/lib/vendor/character-shuffling.js'; +import { $, $$, autoBind, getRandomHex } from '~/src/js/lib/utils' +window.Color = Color; + +const internals = {}; +/** + * Checks if a string is a valid color format for `color` library + * @param {string} color + * @return {boolean} + */ +internals.validateColor = (color) => { + try { + Color(color); + return true; + } + catch (err) { + return false; + } +}; + +/** + * Application main handler + */ +export default class App { + /** + * @return {Object} default class properties + */ + static get initialtProps() { + return { + config: {}, + /** + * Color’s instance reference + * @typeof {Color} + */ + color: null, + /** + * Pickr’s instance reference + * @typeof {Pickr} + */ + pickr: null, + /** + * Node elements collection reference + */ + ui: {} + } + } + + /** + * @return {Object} default configuraton values + */ + static get defaultConfig() { + return { + color: '#FFFFFF', + title: document.title + } + } + + /** + * @param {Object} config override default config + * @param {string} [config.color='#FFF'] + */ + constructor(config) { + const app = this; + + Object.assign(app, app.constructor.initialtProps); + Object.assign(app.config, app.constructor.defaultConfig, config); + + app.ui = { + randomBtn: $('[data-random]'), + copyToClipboardButtons: $$('[data-js-copy-to-clipboard-btn]'), + colorPickerButton: $('[data-js-colorpicker-btn]'), + fcmInput: $('[data-js-fecolormatrix-input]'), + + hexInput: new Input({ + el: $('[data-js-hex-input]'), + validate: internals.validateColor + }), + rgbInput: new Input({ + el: $('[data-js-rgb-input]'), + validate: internals.validateColor + }), + hslInput: new Input({ + el: $('[data-js-hsl-input]'), + validate: internals.validateColor + }), + hwbInput: new Input({ + el: $('[data-js-hwb-input]'), + validate: internals.validateColor + }), + + toast: new Toast({ + el: $('.toast-wrapper') + }) + }; + + app.pickr = new Pickr({ + el: app.ui.colorPickerButton, + useAsButton: true, + default: app.config.color, + theme: 'nano', + position: 'right', + components: { + hue: true + } + }); + } + + /** + * Boot the app: + * - enable inputs and buttons + * - bind events and update the history entry + * @public + * @return {App} + */ + run() { + const app = this; + const color = app.config.color; + + app.ui.hexInput.enable(); + app.ui.rgbInput.enable(); + app.ui.hslInput.enable(); + app.ui.hwbInput.enable(); + app.ui.colorPickerButton.removeAttribute('disabled'); + app.ui.copyToClipboardButtons.forEach(b => b.removeAttribute('disabled')); + + app._bindEvents()._updateUI(color, { + preventHistoryUpdate: true + }); + history.replaceState({ color }, null, `/${color}`); + + return app; + } + + /** + * Register event listeners + * @private + * @return {App} + */ + _bindEvents() { + const app = this; + + autoBind([ + [ app.ui.randomBtn, 'click', '_randomClickHandler' ], + [ app.ui.copyToClipboardButtons, 'click', '_copyColorToClipboardHandler' ], + [ app.ui.hexInput.element, 'isValid', '_isInputValidHandler' ], + [ app.ui.rgbInput.element, 'isValid', '_isInputValidHandler' ], + [ app.ui.hslInput.element, 'isValid', '_isInputValidHandler' ], + [ app.ui.hwbInput.element, 'isValid', '_isInputValidHandler' ], + [ window, 'popstate', '_popStateHandler' ] + ], app); + + app.pickr.on('changestop', instance => { + app._updateUI(instance.getColor().toHEXA().toString()); + }); + + return app; + } + + /** + * Handles copyToClipboardButtons’ click event + * @private + * @return undefined + */ + _copyColorToClipboardHandler(ev) { + const [ property, selector ] = ev.currentTarget.dataset.copy.split(':'); + const value = $(selector)[property]; + + if (Copy(value)) { + this.ui.toast.show(`${value} copied`); + } + } + + /** + * Handles app.ui.randomBtn’s click event + * @private + * @return undefined + */ + _randomClickHandler() { + this._updateUI(getRandomHex()); + } + + /** + * Handles Input’s isValid custom event + * @private + * @return undefined + */ + _isInputValidHandler(ev) { + this._updateUI(ev.detail.text(), { + preventElementUpdate: ev.target + }); + } + + /** + * Handles popstate event + * @private + * @return undefined + */ + _popStateHandler(ev) { + if (!ev.state || !ev.state.color) return; + + this._updateUI(ev.state.color, { + preventHistoryUpdate: true + }); + } + + /** + * Updates the UI with passed color param. + * Sets new app.color instance with to get color space conversions + * Creates a new history state if + * @param {string} [color='#000'] + * @param {Object} [params={}] + * @property {boolean=} preventHistoryUpdate + * @property {HTMLInputElement=} preventElementUpdate do not update this element + * @private + */ + _updateUI(color = '#000', params = {}) { + const app = this; + const { preventHistoryUpdate, preventElementUpdate } = params; + + app.color = Color(color); + + let hex = app.color.hex(); + let rgb = app.color.rgb().string(); + let hsl = app.color.hsl().round().string(); + let hwb = app.color.hwb().round().string(); + let [ r, g, b] = app.color.unitArray(); + + let isLight = app.color.isLight(); + let textColor = app.color.mix(Color(isLight ? '#000' : '#fff'), 0.8); + let borderColor = app.color.mix(Color(isLight ? '#000' : '#fff'), 0.2); + + app.pickr.setColor(hex); + + if (preventElementUpdate !== app.ui.hexInput.element) { + app.ui.hexInput.setValue(hex); + } + + if (preventElementUpdate !== app.ui.rgbInput.element) { + app.ui.rgbInput.setValue(rgb); + } + + if (preventElementUpdate !== app.ui.hslInput.element) { + app.ui.hslInput.setValue(hsl); + } + + if (preventElementUpdate !== app.ui.hwbInput.element) { + app.ui.hwbInput.setValue(hwb); + } + + app.ui.fcmInput.value = `${r.toFixed(2)}\t0\t0\t0\t0\n0\t${g.toFixed(2)}\t0\t0\t0\n0\t0\t${b.toFixed(2)}\t0\t0\n0\t0\t0\t1\t0`; + + document.documentElement.style.setProperty('--cc-main-color', hsl); + document.documentElement.style.setProperty('--cc-text-color', textColor.toString()); + document.documentElement.style.setProperty('--cc-border-color', borderColor.toString()); + + if (!preventHistoryUpdate) { + history.pushState({ color: hex }, null, `/${hex}`); + document.title = `${app.config.title} - ${hex}`; + } + + return app; + } +} diff --git a/src/js/lib/components/input.js b/src/js/lib/components/input.js new file mode 100644 index 0000000..a16e285 --- /dev/null +++ b/src/js/lib/components/input.js @@ -0,0 +1,117 @@ +const { log } = console; + +// import CS from '~/src/js/lib/vendor/character-shuffling.js'; +import { autoBind } from '~/src/js/lib/utils'; + +const internals = { + rs: (string) => string.replace(/\s/g,'') +}; + +export default class Input { + static get defaultProps() { + return { + config: {}, + latestValidValue: '' + } + } + + static get defaultConfig() { + return { + el: null, + validate: () => true + } + } + + constructor(config) { + const input = this; + + Object.assign(input, input.constructor.defaultProps); + Object.assign(input.config, input.constructor.defaultConfig, config); + + input._bindEvents(); + } + + enable() { + this.config.el.removeAttribute('disabled'); + return this; + } + + get element() { + return this.config.el; + } + + get value() { + return this.element.value; + } + + set value(value) { + this.config.element.value = value; + } + + setValue(value) { + const input = this; + + input.element.value = value; + input.latestValidValue = value; + + return input; + } + + /* + shuffle(text, params = {}) { + let options = { + times: 2, + chars: '123456789', + }; + Object.assign(options, params); + + new CS(this.element, options).shuffle({ text }); + } + */ + + _bindEvents() { + const input = this; + + input.events = {}; + input.events.isValid = new CustomEvent('isValid', { + bubbles: true, + testData: 100, + detail: { + el: input.element, + text: () => input.element.value + } + }); + + autoBind([ + [ input.config.el, 'input', '_inputHandler' ] + ], input); + + return input; + } + + _inputHandler(ev) { + const input = this; + + if (input.config.validate) { + if (input.config.validate(input.element.value)) { + input.element.setAttribute('aria-invalid', 'false'); + if (internals.rs(input.latestValidValue) !== internals.rs(input.element.value)) { + input.latestValidValue = input.element.value; + input.element.dispatchEvent(input.events.isValid); + } + return input; + } + + input.element.setAttribute('aria-invalid', 'true'); + + return input; + } + + // if (this.el.validity.valid) { + // if (rs(this.latestValidValue) !== rs(this.el.value)) { + // this.latestValidValue = this.el.value; + // this.el.dispatchEvent(this.events.isValid); + // } + // } + } +} diff --git a/src/js/lib/components/toast.js b/src/js/lib/components/toast.js new file mode 100644 index 0000000..14e52ba --- /dev/null +++ b/src/js/lib/components/toast.js @@ -0,0 +1,43 @@ +const { log } = console; + +export default class Toast { + static get defaultProps() { + return { + config: {}, + item: null, + _timeout: null + } + } + + static get defaultConfig() { + return { + el: null, + duration: 2500 + } + } + + constructor(config) { + const toast = this; + + Object.assign(toast, toast.constructor.defaultProps); + Object.assign(toast.config, toast.constructor.defaultConfig, config); + + toast.item = toast.config.el.querySelector('.toast'); + } + + show(text) { + const toast = this; + + toast.item.innerHTML = text; + + toast.config.el.classList.add('show'); + + if (toast._timeout) clearTimeout(toast._timeout); + toast._timeout = setTimeout(() => { + clearTimeout(toast._timeout); + toast.config.el.classList.remove('show'); + }, toast.config.duration); + + return toast; + } +} diff --git a/src/js/lib/utils/index.js b/src/js/lib/utils/index.js new file mode 100644 index 0000000..4b7f301 --- /dev/null +++ b/src/js/lib/utils/index.js @@ -0,0 +1,28 @@ +export const $ = document.querySelector.bind(document); +export const $$ = document.querySelectorAll.bind(document); + +/** + * Returns a random hexadecimal color code without the hash. + * @property getRandomHexColor {Function} + * @return 000000 {String} + */ +export function getRandomHex() { + return `#${Math.random().toString(16).slice(2, 8)}`; +} + +/** + * @usage + * autoBind([ + * [ , <'eventname'>, + * ], ) + */ +export function autoBind(arr, ctx) { + const listen = (node, ev, handler) => node.addEventListener(ev, handler, false); + arr.forEach(rule => { + ctx[rule[2]] = ctx[rule[2]].bind(ctx); + if (rule[0].length) { + return rule[0].forEach(ev => listen(ev, rule[1], ctx[rule[2]])); + } + return listen(rule[0], rule[1], ctx[rule[2]]); + }); +} diff --git a/src/js/lib/vendor/character-shuffling.js b/src/js/lib/vendor/character-shuffling.js new file mode 100644 index 0000000..bfff2fc --- /dev/null +++ b/src/js/lib/vendor/character-shuffling.js @@ -0,0 +1,107 @@ +/* character-shuffling + * https://github.com/noeldelgado/character-shuffling + * MIT License + */ +(function(root, factory) { 'use strict'; + if (typeof exports === 'object') { + module.exports = factory(); + } else { + root.CharacterShuffling = factory(root); + } +}(this, function factory() { 'use strict'; + CharacterShuffling.version = '1.0.0'; + + /* @constructor CharacterShuffling [Function] + * @param element [NodeElement] Node to shuffle its text contents. + * @param config [Object] Options to be merged with the defaults. + * config.chars [String] The characters you want to be used for the random selection on every update. + * config.times [Number] How many times should the letters be changed. (10) + * config.text [String] Text to transition to. (this.element.textContent) + * config.callback [Function] Function to be call once the shuffling is complete. + */ + function CharacterShuffling(element, config) { + if (typeof element === 'undefined') { + throw new Error('CharacterShuffling [constructor]: "element" param is required'); + } + + this.element = element; + + var defaults = { + chars : "abcdefghijklmnopqrstuvwxyz" + + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + + "0123456789" + + ",.?/\\(^)![]{}*&^%$#'\"", + times : 10, + text : this.element.textContent, + callback : null + }; + this.options = _merge(defaults, config); + } + + /* Starts the shuffle animation. + * @method shuffle [Function] + * @argument options [Object] (same options as constructor.config) + */ + CharacterShuffling.prototype.shuffle = function shuffle(options) { + if (options) { + _merge(this.options, options); + } + + this._start = -this.get('times'); + this._charsLen = this.get('chars').length; + this._textLen = this.get('text').length; + + requestAnimationFrame(this._shuffle.bind(this)); + return this; + }; + + /* Returns the current value of an option if matched with the argument passed. + * @method get [Function] + * @return this.options[propertyName] || undefined + */ + CharacterShuffling.prototype.get = function get(propertyName) { + return this.options[propertyName]; + }; + + CharacterShuffling.prototype.set = function set(propertyName, value) { + this.options[propertyName] = value; + }; + + /* Updates element.textContent value with new a random generated string. + * @method _shuffle [Function] + */ + CharacterShuffling.prototype._shuffle = function _shuffle() { + var i, arr = this.get('text').split(''); + + if (this._start > this._textLen) { + if (typeof this.get('callback') === 'function') { + this.get('callback').call(this); + } + return; + } + + for (i = Math.max(this._start,0); i < this._textLen; i++) { + if (i < (this._start + this.get('times'))) { + if (arr[i] !== ' ') { + arr[i] = this.get('chars')[Math.floor(Math.random() * this._charsLen)]; + } + continue; + } + arr[i] = ''; + } + + this._start++; + this.element.value = arr.join(''); + // this.element.textContent = arr.join(""); + requestAnimationFrame(this._shuffle.bind(this)); + }; + + function _merge(a, b) { + for (var propertyName in b) { + a[propertyName] = b[propertyName]; + } + return a; + } + + return CharacterShuffling; +}));