diff --git a/package-lock.json b/package-lock.json index c9398675..50af876d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1034,11 +1034,6 @@ "@hapi/hoek": "^8.3.0" } }, - "@icons/material": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz", - "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==" - }, "@jest/console": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", @@ -1492,6 +1487,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/@types/nanoid/-/nanoid-2.1.0.tgz", "integrity": "sha512-xdkn/oRTA0GSNPLIKZgHWqDTWZsVrieKomxJBOQUK9YDD+zfSgmwD5t4WJYra5S7XyhTw7tfvwznW+pFexaepQ==", + "dev": true, "requires": { "@types/node": "*" } @@ -9400,11 +9396,6 @@ "object-visit": "^1.0.0" } }, - "material-colors": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz", - "integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==" - }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -12135,19 +12126,6 @@ "whatwg-fetch": "^3.0.0" } }, - "react-color": { - "version": "2.17.3", - "resolved": "https://registry.npmjs.org/react-color/-/react-color-2.17.3.tgz", - "integrity": "sha512-1dtO8LqAVotPIChlmo6kLtFS1FP89ll8/OiA8EcFRDR+ntcK+0ukJgByuIQHRtzvigf26dV5HklnxDIvhON9VQ==", - "requires": { - "@icons/material": "^0.2.4", - "lodash": "^4.17.11", - "material-colors": "^1.2.1", - "prop-types": "^15.5.10", - "reactcss": "^1.2.0", - "tinycolor2": "^1.4.1" - } - }, "react-dev-utils": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-10.0.0.tgz", @@ -12369,14 +12347,6 @@ "workbox-webpack-plugin": "4.3.1" } }, - "reactcss": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz", - "integrity": "sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==", - "requires": { - "lodash": "^4.0.1" - } - }, "read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", @@ -14459,11 +14429,6 @@ "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=" }, - "tinycolor2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz", - "integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g=" - }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", diff --git a/package.json b/package.json index 432faa66..26ac9ca0 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,6 @@ "dependencies": { "nanoid": "^2.1.9", "react": "16.12.0", - "react-color": "^2.17.3", "react-dom": "16.12.0", "react-scripts": "3.3.0", "roughjs": "3.1.0" diff --git a/src/components/ColorPicker.css b/src/components/ColorPicker.css new file mode 100644 index 00000000..febd7bfd --- /dev/null +++ b/src/components/ColorPicker.css @@ -0,0 +1,89 @@ +.color-picker { + width: 205px; + background: rgb(255, 255, 255); + border: 0px solid rgba(0, 0, 0, 0.25); + box-shadow: rgba(0, 0, 0, 0.25) 0px 1px 4px; + border-radius: 4px; + position: relative; +} + +.color-picker-triangle-shadow { + width: 0px; + height: 0px; + border-style: solid; + border-width: 0px 9px 10px; + border-color: transparent transparent rgba(0, 0, 0, 0.1); + position: absolute; + top: -11px; + left: 12px; +} + +.color-picker-triangle { + width: 0px; + height: 0px; + border-style: solid; + border-width: 0px 9px 10px; + border-color: transparent transparent rgb(255, 255, 255); + position: absolute; + top: -10px; + left: 12px; +} + +.color-picker-content { + padding: 15px 9px 9px 15px; +} + +.color-picker-swatch { + height: 30px; + width: 30px; + cursor: pointer; + position: relative; + outline: none; + float: left; + border-radius: 4px; + margin: 0px 6px 6px 0px; +} + +.color-picker-swatch:focus { + /* Note: in the original react-color it uses the color of the element, + but it's too annoying to set from JavaScript without a css lib... */ + box-shadow: 0 0 4px rgba(0, 0, 0, 0.3); +} + +.color-picker-transparent { + border-radius: 4px; + box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 0px 1px inset; + position: absolute; + top: 0px; + right: 0px; + bottom: 0px; + left: 0px; + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMUlEQVQ4T2NkYGAQYcAP3uCTZhw1gGGYhAGBZIA/nYDCgBDAm9BGDWAAJyRCgLaBCAAgXwixzAS0pgAAAABJRU5ErkJggg==") + left center; +} + +.color-picker-hash { + background: rgb(240, 240, 240); + height: 30px; + width: 30px; + border-radius: 4px 0px 0px 4px; + float: left; + color: rgb(152, 161, 164); + display: flex; + align-items: center; + justify-content: center; +} + +.color-picker-input { + width: 100px; + font-size: 14px; + color: rgb(102, 102, 102); + border: 0px; + outline: none; + height: 28px; + box-shadow: rgb(240, 240, 240) 0px 0px 0px 1px inset; + box-sizing: content-box; + border-radius: 0px 4px 4px 0px; + float: left; + padding-left: 8px; +} diff --git a/src/components/ColorPicker.tsx b/src/components/ColorPicker.tsx index 3090ed39..bb7276d0 100644 --- a/src/components/ColorPicker.tsx +++ b/src/components/ColorPicker.tsx @@ -1,11 +1,66 @@ -import React, { lazy } from "react"; +import React from "react"; import { Popover } from "./Popover"; -const TwitterPicker = lazy(() => - import( - /* webpackPrefetch: true */ "react-color/lib/components/twitter/Twitter" - ) -); +import "./ColorPicker.css"; + +// This is a narrow reimplementation of the awesome react-color Twitter component +// https://github.com/casesandberg/react-color/blob/master/src/components/twitter/Twitter.js + +const Picker = function({ + colors, + color, + onChange +}: { + colors: string[]; + color: string | undefined; + onChange: (color: string) => void; +}) { + const [innerValue, setInnerValue] = React.useState(color); + React.useEffect(() => { + setInnerValue(color); + }, [color]); + return ( +
+
+
+
+ {colors.map(color => ( +
{ + onChange(color); + }} + title={color} + tabIndex={0} + style={{ backgroundColor: color }} + > + {color === "transparent" ? ( +
+ ) : ( + undefined + )} +
+ ))} +
#
+
+ { + const value = e.target.value; + if (value.match(/^([0-9a-f]{3}|[0-9a-f]{6}|transparent)$/)) { + onChange(value === "transparent" ? "transparent" : "#" + value); + } + setInnerValue(value); + }} + value={(innerValue || "").replace(/^#/, "")} + /> +
+
+
+
+ ); +}; export function ColorPicker({ type, @@ -27,12 +82,11 @@ export function ColorPicker({ {isActive ? ( setActive(false)}> - { - onChange(changedColor.hex); + onChange(changedColor); }} /> @@ -74,7 +128,7 @@ const colors = { "#FF9DA7", "#9C755F", "#BAB0AB", - "#FFFFFF" + "transparent" ], elementStroke: [ "#324E6B", diff --git a/src/renderer/renderElement.ts b/src/renderer/renderElement.ts index 75e4bf05..d468d33d 100644 --- a/src/renderer/renderElement.ts +++ b/src/renderer/renderElement.ts @@ -22,7 +22,10 @@ export function renderElement( element.shape = withCustomMathRandom(element.seed, () => { return generator.rectangle(0, 0, element.width, element.height, { stroke: element.strokeColor, - fill: element.backgroundColor, + fill: + element.backgroundColor === "transparent" + ? undefined + : element.backgroundColor, fillStyle: element.fillStyle, strokeWidth: element.strokeWidth, roughness: element.roughness @@ -55,7 +58,10 @@ export function renderElement( ], { stroke: element.strokeColor, - fill: element.backgroundColor, + fill: + element.backgroundColor === "transparent" + ? undefined + : element.backgroundColor, fillStyle: element.fillStyle, strokeWidth: element.strokeWidth, roughness: element.roughness @@ -77,7 +83,10 @@ export function renderElement( element.height, { stroke: element.strokeColor, - fill: element.backgroundColor, + fill: + element.backgroundColor === "transparent" + ? undefined + : element.backgroundColor, fillStyle: element.fillStyle, strokeWidth: element.strokeWidth, roughness: element.roughness