react-tinted
Version:
A react wrapper for the Tinted color harmony wheel
347 lines (300 loc) • 10.2 kB
JavaScript
import React, { useContext, useRef, useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import chroma from 'chroma-js';
import { TintedWheel as TintedWheel$1, TintedPalette as TintedPalette$1 } from 'tinted';
export { colorModes } from 'tinted';
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
function _arrayWithHoles(arr) {
if (Array.isArray(arr)) return arr;
}
function _iterableToArrayLimit(arr, i) {
if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
var _arr = [];
var _n = true;
var _d = false;
var _e = undefined;
try {
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"] != null) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) {
arr2[i] = arr[i];
}
return arr2;
}
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _slicedToArray(arr, i) {
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
}
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
return target;
}
function _objectWithoutProperties(source, excluded) {
if (source == null) return {};
var target = _objectWithoutPropertiesLoose(source, excluded);
var key, i;
if (Object.getOwnPropertySymbols) {
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
for (i = 0; i < sourceSymbolKeys.length; i++) {
key = sourceSymbolKeys[i];
if (excluded.indexOf(key) >= 0) continue;
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
target[key] = source[key];
}
}
return target;
}
function createCommonjsModule(fn, basedir, module) {
return module = {
path: basedir,
exports: {},
require: function (path, base) {
return commonjsRequire(path, (base === undefined || base === null) ? module.path : base);
}
}, fn(module, module.exports), module.exports;
}
function commonjsRequire () {
throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs');
}
var classnames = createCommonjsModule(function (module) {
/*!
Copyright (c) 2017 Jed Watson.
Licensed under the MIT License (MIT), see
http://jedwatson.github.io/classnames
*/
/* global define */
(function () {
var hasOwn = {}.hasOwnProperty;
function classNames () {
var classes = [];
for (var i = 0; i < arguments.length; i++) {
var arg = arguments[i];
if (!arg) continue;
var argType = typeof arg;
if (argType === 'string' || argType === 'number') {
classes.push(arg);
} else if (Array.isArray(arg) && arg.length) {
var inner = classNames.apply(null, arg);
if (inner) {
classes.push(inner);
}
} else if (argType === 'object') {
for (var key in arg) {
if (hasOwn.call(arg, key) && arg[key]) {
classes.push(key);
}
}
}
}
return classes.join(' ');
}
if ( module.exports) {
classNames.default = classNames;
module.exports = classNames;
} else {
window.classNames = classNames;
}
}());
});
var WheelContext = /*#__PURE__*/React.createContext(null);
function useWheel() {
return useContext(WheelContext);
}
function TintedWheel(props) {
var children = props.children,
className = props.className,
colorCount = props.colorCount,
customColors = props.customColors,
radius = props.radius,
markerWidth = props.markerWidth,
markerOutlineWidth = props.markerOutlineWidth,
margin = props.margin,
defaultSlice = props.defaultSlice,
initRoot = props.initRoot,
mode = props.mode,
colorWheelImage = props.colorWheelImage,
onColorsChanged = props.onColorsChanged,
rest = _objectWithoutProperties(props, ["children", "className", "colorCount", "customColors", "radius", "markerWidth", "markerOutlineWidth", "margin", "defaultSlice", "initRoot", "mode", "colorWheelImage", "onColorsChanged"]);
var rootElRef = useRef();
var _useState = useState(null),
_useState2 = _slicedToArray(_useState, 2),
wheel = _useState2[0],
setWheel = _useState2[1];
useEffect(function () {
var defaultMargin = markerWidth / 2 + markerOutlineWidth;
var finalMargin = typeof margin === 'number' ? margin : defaultMargin;
var wheel = new TintedWheel$1({
container: rootElRef.current,
radius: radius,
markerWidth: markerWidth,
markerOutlineWidth: markerOutlineWidth,
margin: finalMargin,
defaultSlice: defaultSlice,
initRoot: initRoot,
initMode: mode,
colorWheelImage: colorWheelImage
});
setWheel(wheel);
}, []);
useEffect(function () {
if (!wheel) return;
wheel.setMode(mode);
}, [wheel, mode]);
useEffect(function () {
if (!wheel || !onColorsChanged) return;
wheel.dispatch.on('update-end.reactWheel', function () {
var colorData = wheel._getVisibleMarkers().data();
var hexColors = colorData.map(function (d) {
return chroma(d.color).hex();
});
onColorsChanged(hexColors, mode, wheel);
});
return function () {
wheel.dispatch.on('update-end.reactWheel', null);
};
}, [wheel, onColorsChanged]);
useEffect(function () {
if (!wheel) return;
var userData = customColors || colorCount;
wheel.bindData(userData);
}, [wheel, colorCount, customColors]);
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("svg", _extends({}, rest, {
ref: rootElRef,
className: classnames('tinted-wheel', className)
})), /*#__PURE__*/React.createElement(WheelContext.Provider, {
value: wheel
}, children));
}
TintedWheel.propTypes = {
colorCount: PropTypes.number,
customColors: PropTypes.array,
radius: PropTypes.number,
markerWidth: PropTypes.number,
markerOutlineWidth: PropTypes.number,
margin: PropTypes.number,
defaultSlice: PropTypes.number,
initRoot: PropTypes.string,
mode: PropTypes.oneOf(Object.values(TintedWheel$1.MODES)),
colorWheelImage: PropTypes.string,
onColorsChanged: PropTypes.func
};
TintedWheel.defaultProps = {
colorCount: 5,
radius: 100,
markerWidth: 25,
markerOutlineWidth: 1,
defaultSlice: 20,
initRoot: 'red',
mode: TintedWheel$1.MODES.ANALOGOUS,
colorWheelImage: 'https://zposten.github.io/tinted/wheel.png'
};
function TintedPalette(props) {
var children = props.children,
className = props.className,
rest = _objectWithoutProperties(props, ["children", "className"]);
var wheel = useWheel();
var rootElRef = useRef();
var paletteRef = useRef();
var _useState = useState([]),
_useState2 = _slicedToArray(_useState, 2),
hexColors = _useState2[0],
setHexColors = _useState2[1];
useEffect(function () {
if (!wheel) return;
var palette = new TintedPalette$1({
container: rootElRef.current,
colorWheel: wheel
});
wheel.dispatch.on('bind-data.reactPalette', function (data) {
palette.render(data, wheel);
});
wheel.dispatch.on('markers-updated.reactPalette', function () {
palette.onColorValuesChanged(wheel.currentMode);
});
wheel.dispatch.on('update-end.reactPalette', function () {
var colorData = wheel._getVisibleMarkers().data();
var hexColors = colorData.map(function (d) {
return chroma(d.color).hex();
});
setHexColors(hexColors);
});
return function () {
wheel.dispatch.on('bind-data.reactPalette', null);
wheel.dispatch.on('markers-updated.reactPalette', null);
wheel.dispatch.on('update-end.reactPalette', null);
};
}, [wheel]);
useEffect(function () {
if (wheel) return;
paletteRef.current;
}); // Throw an error if multiple child elements are passed
React.Children.only(children);
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", _extends({}, rest, {
ref: rootElRef,
className: classnames('tinted-palette', className)
})), children && /*#__PURE__*/React.createElement("div", {
className: "tinted-palette-for-each-color"
}, // Duplicate the children once for each color
hexColors.map(function (hexColor, i) {
var order = markerDistance(i);
var clonedChild = /*#__PURE__*/React.cloneElement(children, {
hexColor: hexColor,
order: order
});
return /*#__PURE__*/React.createElement(React.Fragment, {
key: "".concat(hexColor, "-").concat(i)
}, clonedChild);
})));
} // Stolen from tinted/src/util.js
function markerDistance(i) {
return Math.ceil(i / 2) * Math.pow(-1, i + 1);
}
export { TintedPalette, TintedWheel, useWheel };
//# sourceMappingURL=index.js.map