chayns-components
Version:
A set of beautiful React components for developing chayns® applications.
429 lines (423 loc) • 15.9 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.default = void 0;
var _clsx = _interopRequireDefault(require("clsx"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _react = _interopRequireWildcard(require("react"));
var _Bubble = _interopRequireDefault(require("../../react-chayns-bubble/component/Bubble"));
var _color = require("../../utils/color");
var _is = require("../../utils/is");
var _ColorArea = _interopRequireDefault(require("./colorArea/ColorArea"));
var _ColorInput = _interopRequireDefault(require("./colorInput/ColorInput"));
require("./ColorPicker.css");
var _HueSlider = _interopRequireDefault(require("./hueSlider/HueSlider"));
var _TransparencySlider = _interopRequireDefault(require("./transparencySlider/TransparencySlider"));
var _isDescendant = _interopRequireDefault(require("../../utils/isDescendant"));
var _ColorSelection = _interopRequireDefault(require("./colorSelection/ColorSelection"));
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
/**
* @component
*/
const getHsvColor = color => {
if ((0, _is.isString)(color)) {
// HEX(A)
return (0, _color.hexStringToHsv)(color);
}
if (color.r !== undefined) {
// RGB(A) (0-255)
return (0, _color.rgbToHsv)(color);
}
if (color.h !== undefined) {
// HSV(A)
return color;
}
return {
h: 0,
s: 0,
v: 0,
a: 1
};
};
/**
* Lets a user choose a color for text, shapes, marking tools, and other
* elements.
*/
const ColorPicker = /*#__PURE__*/(0, _react.forwardRef)((_ref, reference) => {
let {
defaultColorModel,
transparency = false,
onChangeEnd,
input = false,
color,
onBlur,
inline = false,
children,
removeParentSpace = false,
parent,
onChange,
style,
className,
bubblePosition = _Bubble.default.position.BOTTOM_CENTER,
bubbleClassName,
bubbleStyle,
showAllColorModels = false,
customColorsArray,
showCustomColors = false,
showGlobalColors = false,
onCreateCustomColor,
onRemoveCustomColor
} = _ref;
// references
const bubbleRef = (0, _react.useRef)(null);
const bubbleContentRef = (0, _react.useRef)(null);
const linkRef = (0, _react.useRef)(null);
const childrenRef = (0, _react.useRef)(null);
// state
const [colorState, setColor] = (0, _react.useState)(getHsvColor(color));
const [coordinates, setCoordinates] = (0, _react.useState)({
x: 0,
y: 0
});
const [colorModel, setColorModel] = (0, _react.useState)(defaultColorModel !== null && defaultColorModel !== void 0 ? defaultColorModel : transparency ? ColorPicker.colorModels.RGB : ColorPicker.colorModels.HEX);
const [customColorsState, setCustomColorsState] = (0, _react.useState)(customColorsArray ? customColorsArray.map(c => getHsvColor(c)) : []);
(0, _react.useEffect)(() => {
if (customColorsArray) {
setCustomColorsState(customColorsArray.map(c => getHsvColor(c)));
} else {
setCustomColorsState([]);
}
}, [customColorsArray]);
// effects (lifecycle methods)
(0, _react.useEffect)(() => {
setColor(getHsvColor(color));
}, [color]);
const closeBubble = (0, _react.useCallback)(async event => {
// Hide bubble and remove event listeners if click was outside of the bubble
if (event.type === 'blur' || !(event.target === bubbleContentRef.current || (0, _isDescendant.default)(bubbleContentRef.current, event.target))) {
document.removeEventListener('click', closeBubble);
window.removeEventListener('blur', closeBubble);
if (bubbleRef.current) {
bubbleRef.current.hide();
}
if (onBlur) {
onBlur(color);
}
if (chayns.env.isApp || chayns.env.isMyChaynsApp) {
chayns.allowRefreshScroll();
}
}
}, [color, onBlur]);
const openBubble = (0, _react.useCallback)(async () => {
if (inline) {
return;
}
const ref = children ? childrenRef : linkRef;
const rect = ref.current.getBoundingClientRect();
let newX = rect.left + rect.width / 2;
let newY = rect.bottom + (chayns.env.isApp ? (await chayns.getWindowMetrics()).pageYOffset : 0);
if (removeParentSpace) {
const parentRect = (parent || document.getElementsByClassName('tapp')[0] || document.body).getBoundingClientRect();
newX -= parentRect.left;
newY -= parentRect.top;
}
setCoordinates({
x: newX,
y: newY
});
bubbleRef.current.show();
// Add event listeners to hide the bubble
document.addEventListener('click', closeBubble, {
capture: true
});
// window.addEventListener('blur', closeBubble);
if (chayns.env.isApp || chayns.env.isMyChaynsApp) {
chayns.disallowRefreshScroll();
}
}, [inline, children, removeParentSpace, closeBubble, parent]);
const onChangeCallback = (0, _react.useCallback)(newColor => {
setColor(newColor);
if (onChange) {
onChange(newColor);
}
}, [setColor, onChange]);
const onCreateCustomColorCallback = (0, _react.useCallback)(newColor => {
if (onCreateCustomColor) {
onCreateCustomColor(newColor);
}
}, [onCreateCustomColor]);
const onRemoveCustomColorCallback = (0, _react.useCallback)(newColor => {
if (onRemoveCustomColor) {
onRemoveCustomColor(newColor);
}
}, [onRemoveCustomColor]);
const onColorModelToggle = (0, _react.useCallback)(() => {
setColorModel((colorModel + 1) % Object.keys(ColorPicker.colorModels).length);
}, [setColorModel, colorModel]);
const rgb255 = (0, _color.hsvToRgb)(colorState);
(0, _react.useImperativeHandle)(reference, () => ({
show: openBubble
}));
if (inline) {
return /*#__PURE__*/_react.default.createElement("div", {
className: (0, _clsx.default)('cc__color-picker', className),
style: {
width: '322px',
...style
},
onClick: openBubble,
key: "div",
ref: childrenRef
}, /*#__PURE__*/_react.default.createElement("div", {
ref: bubbleContentRef,
className: "cc__color-picker__bubble-content"
}, /*#__PURE__*/_react.default.createElement(_ColorArea.default, {
color: colorState,
onChange: onChangeCallback,
onChangeEnd: onChangeEnd
}), /*#__PURE__*/_react.default.createElement("div", {
style: {
padding: '0 11px'
}
}, /*#__PURE__*/_react.default.createElement("div", {
style: {
display: 'flex',
flexDirection: 'row'
}
}, /*#__PURE__*/_react.default.createElement("div", {
style: {},
className: transparency ? 'cc__color-picker__slider-container__with-transparency' : 'cc__color-picker__slider-container__without-transparency'
}, /*#__PURE__*/_react.default.createElement(_HueSlider.default, {
color: colorState,
onChange: onChangeCallback,
onChangeEnd: onChangeEnd,
showTooltip: false
}), transparency && /*#__PURE__*/_react.default.createElement(_TransparencySlider.default, {
color: colorState,
onChange: onChangeCallback,
onChangeEnd: onChangeEnd
})), transparency && /*#__PURE__*/_react.default.createElement("div", {
className: "cc__color-picker__color-square",
style: {
backgroundColor: (0, _color.hsvToHexString)(colorState)
}
}))), /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_ColorSelection.default, {
customColorsArray: customColorsState,
showCustomColors: showCustomColors,
showGlobalColors: showGlobalColors,
color: colorState,
onChange: c => {
onChangeCallback(c);
onChangeEnd === null || onChangeEnd === void 0 ? void 0 : onChangeEnd(c);
},
onCreateCustomColor: onCreateCustomColorCallback,
onRemoveCustomColor: onRemoveCustomColorCallback
}), input && /*#__PURE__*/_react.default.createElement(_ColorInput.default, {
color: colorState,
onChange: onChangeCallback,
onChangeEnd: onChangeEnd,
onModelToggle: onColorModelToggle,
colorModel: colorModel,
transparency: transparency,
showAllColorModels: showAllColorModels
}))));
}
return [/*#__PURE__*/_react.default.createElement("div", {
className: (0, _clsx.default)('cc__color-picker', className),
style: style,
onClick: openBubble,
key: "div",
ref: childrenRef
}, children || [/*#__PURE__*/_react.default.createElement("div", {
key: "circle",
className: "cc__color-picker__color-circle",
style: {
backgroundColor: (0, _color.rgbToRgbString)(rgb255, true)
}
}), /*#__PURE__*/_react.default.createElement("div", {
key: "link",
className: "cc__color-picker__color-link chayns__color--headline chayns__border-color--headline",
ref: linkRef
}, colorModel === ColorPicker.colorModels.RGB ? (0, _color.rgbToRgbString)(rgb255, transparency) : (0, _color.rgbToHexString)(rgb255, transparency))]), /*#__PURE__*/_react.default.createElement(_Bubble.default, {
ref: bubbleRef,
coordinates: coordinates,
position: bubblePosition,
parent: parent,
className: bubbleClassName,
style: {
width: '322px',
...bubbleStyle
},
key: "bubble"
}, /*#__PURE__*/_react.default.createElement("div", {
ref: bubbleContentRef,
className: "cc__color-picker__bubble-content"
}, /*#__PURE__*/_react.default.createElement(_ColorArea.default, {
color: colorState,
onChange: onChangeCallback,
onChangeEnd: onChangeEnd
}), /*#__PURE__*/_react.default.createElement("div", {
style: {
padding: '0 11px'
}
}, /*#__PURE__*/_react.default.createElement("div", {
style: {
display: 'flex',
flexDirection: 'row'
}
}, /*#__PURE__*/_react.default.createElement("div", {
style: {},
className: transparency ? 'cc__color-picker__slider-container__with-transparency' : 'cc__color-picker__slider-container__without-transparency'
}, /*#__PURE__*/_react.default.createElement(_HueSlider.default, {
color: colorState,
onChange: onChangeCallback,
onChangeEnd: onChangeEnd,
showTooltip: false
}), transparency && /*#__PURE__*/_react.default.createElement(_TransparencySlider.default, {
color: colorState,
onChange: onChangeCallback,
onChangeEnd: onChangeEnd
})), transparency && /*#__PURE__*/_react.default.createElement("div", {
className: "cc__color-picker__color-square",
style: {
backgroundColor: (0, _color.hsvToHexString)(colorState)
}
}))), /*#__PURE__*/_react.default.createElement("div", {
style: {
marginBottom: '5px'
}
}, /*#__PURE__*/_react.default.createElement(_ColorSelection.default, {
customColorsArray: customColorsState,
showCustomColors: showCustomColors,
showGlobalColors: showGlobalColors,
color: colorState,
onChange: c => {
onChangeCallback(c);
onChangeEnd === null || onChangeEnd === void 0 ? void 0 : onChangeEnd(c);
},
onCreateCustomColor: onCreateCustomColorCallback,
onRemoveCustomColor: onRemoveCustomColorCallback
}), input && /*#__PURE__*/_react.default.createElement(_ColorInput.default, {
color: colorState,
onChange: onChangeCallback,
onChangeEnd: onChangeEnd,
onModelToggle: onColorModelToggle,
colorModel: colorModel,
transparency: transparency,
showAllColorModels: showAllColorModels
}))))];
});
const colorPropType = _propTypes.default.oneOfType([_propTypes.default.string.isRequired, _propTypes.default.shape({
r: _propTypes.default.number.isRequired,
g: _propTypes.default.number.isRequired,
b: _propTypes.default.number.isRequired,
a: _propTypes.default.number
}).isRequired, _propTypes.default.shape({
h: _propTypes.default.number.isRequired,
s: _propTypes.default.number.isRequired,
v: _propTypes.default.number.isRequired,
a: _propTypes.default.number
}).isRequired]);
ColorPicker.propTypes = {
/**
* Display the color picker without a bubble.
*/
inline: _propTypes.default.bool,
/**
* The current color. Either a HEX-string, an HSV(A)- or RGB(A)-object.
*/
color: colorPropType.isRequired,
/**
* The bubble position. The possible values are listed under the
* `Bubble`-component.
*/
bubblePosition: _propTypes.default.number,
/**
* Will be called when changing the color.
*/
onChange: _propTypes.default.func,
/**
* Will be called after the color was changed.
*/
onChangeEnd: _propTypes.default.func,
/**
* Will be called when the picker loses focus.
*/
onBlur: _propTypes.default.func,
/**
* Wether the picker should show a transparency slider.
*/
transparency: _propTypes.default.bool,
/**
* The parent node the bubble should be rendered into.
*/
parent: typeof Element !== 'undefined' ? _propTypes.default.instanceOf(Element) : () => {},
/**
* The classname that will be set on the children wrapper.
*/
className: _propTypes.default.string,
/**
* A React style object that will be assigned to the children wrapper
* element.
*/
style: _propTypes.default.objectOf(_propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string])),
/**
* A classname string that will be applied to the Bubble component.
*/
bubbleClassName: _propTypes.default.string,
/**
* A React style object that will be applied to the Bubble component.
*/
bubbleStyle: _propTypes.default.objectOf(_propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string])),
/**
* Displays an input to type in the color.
*/
input: _propTypes.default.bool,
/**
* The color model that is used by default.
*/
defaultColorModel: _propTypes.default.number,
/**
* Children // TODO
*/
children: _propTypes.default.node,
/**
* Removes space from the parent to the page borders from the tooltip
* position. This is only needed if the parent is padded from the page and
* has a relative positioning.
*/
removeParentSpace: _propTypes.default.bool,
/**
* Shows all color models
*/
showAllColorModels: _propTypes.default.bool,
/**
* An array of custom selectable colors
*/
customColorsArray: _propTypes.default.arrayOf(colorPropType),
/**
* Shows custom colors
*/
showCustomColors: _propTypes.default.bool,
/**
* Shows global colors
*/
showGlobalColors: _propTypes.default.bool,
/**
* Will be called when a custom color is added
*/
onCreateCustomColor: _propTypes.default.func,
/**
* Will be called when a custom color is removed
*/
onRemoveCustomColor: _propTypes.default.func
};
ColorPicker.colorModels = {
HEX: 0,
RGB: 1
};
ColorPicker.displayName = 'ColorPicker';
var _default = ColorPicker;
exports.default = _default;
//# sourceMappingURL=ColorPicker.js.map