UNPKG

@iobroker/adapter-react-v5

Version:

React components to develop ioBroker interfaces with react.

222 lines 9.29 kB
/** * Copyright 2018-2024 Denis Haev (bluefox) <dogafox@gmail.com> * * Licensed under the Creative Commons Attribution-NonCommercial License, Version 4.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://creativecommons.org/licenses/by-nc/4.0/legalcode.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import React, { Component } from 'react'; import { ChromePicker } from 'react-color'; import { TextField, Menu, IconButton, Button, Box } from '@mui/material'; import { Delete as IconDelete, Close as IconClose } from '@mui/icons-material'; import { I18n } from '../i18n'; const styles = { color: { width: 36, height: 14, borderRadius: 2, }, delButton: { marginTop: 16, }, swatch: { mt: '16px', p: '5px', backgroundColor: 'background.paper', borderRadius: '1px', boxShadow: '0 0 0 1px rgba(0,0,0,.1)', display: 'inline-block', cursor: 'pointer', verticalAlign: 'middle', }, swatchDisabled: { opacity: 0.5, cursor: 'default', }, popover: { '& .MuiPaper-root': { textAlign: 'right', backgroundColor: '#00000000', boxShadow: 'none', }, }, popoverList: { padding: 0, }, closeButton: (theme) => ({ backgroundColor: `${theme.palette.background.paper} !important`, borderRadius: '0 0 25% 25%', '&:hover': { backgroundColor: `${theme.palette.secondary.main} !important`, }, }), cover: { position: 'fixed', top: 0, right: 0, bottom: 0, left: 0, }, textDense: { mt: 0, mb: 0, }, picker: (theme) => ({ background: `${theme.palette.background.paper} !important`, }), iconButton: { width: 16, height: 16, }, button: { width: 32, height: 32, minWidth: 32, minHeight: 32, }, }; /** * A color picker component. */ export class ColorPicker extends Component { /** * Constructor for the color picker. * * @param props The properties. */ constructor(props) { super(props); this.state = { displayColorPicker: false, color: this.props.value || this.props.color || '', anchorEl: null, }; } handleClick = (e) => { this.setState({ displayColorPicker: !this.state.displayColorPicker, anchorEl: this.state.displayColorPicker ? null : e.currentTarget, }); }; handleClose = () => { this.setState({ displayColorPicker: false, anchorEl: null }); }; /** * Convert the given color to hex ('#rrggbb') or rgba ('rgba(r,g,b,a)') format. * * @param color The color to convert. * @param isHex If true, the color will be converted to hex format. * @returns the hex or rgba representation of the given color. */ static getColor(color, isHex) { if (color && typeof color === 'object') { const oColor = color; if (oColor.rgb) { if (isHex) { return `#${oColor.rgb.r.toString(16).padStart(2, '0')}${oColor.rgb.g.toString(16).padStart(2, '0')}${oColor.rgb.b.toString(16).padStart(2, '0')}`; } return `rgba(${oColor.rgb.r},${oColor.rgb.g},${oColor.rgb.b},${oColor.rgb.a})`; } const rColor = color; if (isHex) { return `#${rColor.r.toString(16).padStart(2, '0')}${rColor.g.toString(16).padStart(2, '0')}${rColor.b.toString(16).padStart(2, '0')}`; } return `rgba(${rColor.r},${rColor.g},${rColor.b},${rColor.a})`; } if (typeof color === 'string') { return isHex ? ColorPicker.rgb2hex(color || '') : color || ''; } return ''; } /** * Convert rgb() or rgba() format to hex format #rrggbb. * * @param rgb The color in rgb() or rgba() format. if not in this format, the color will be returned as is. */ static rgb2hex(rgb) { const m = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i); if (m) { const r = parseInt(m[1], 10).toString(16).padStart(2, '0'); const g = parseInt(m[2], 10).toString(16).padStart(2, '0'); const b = parseInt(m[3], 10).toString(16).padStart(2, '0'); return m?.length === 4 ? `#${r}${g}${b}` : rgb; } return rgb; } handleChange = (color) => { this.setState({ color }, () => this.props.onChange && this.props.onChange(ColorPicker.getColor(color))); }; /** * If the props are updated from outside, they should override the state * * @param _prevProps The previous properties. * @param prevState The previous state. */ componentDidUpdate(_prevProps, prevState) { const color = ColorPicker.getColor(this.props.color || this.props.value || ''); if (color !== prevState.color) { this.setState({ color }); } } renderCustomPalette() { if (!this.props.customPalette) { return null; } return (React.createElement("div", { style: { width: '100%', display: 'flex', flexWrap: 'wrap' } }, this.props.customPalette.map(color => (React.createElement(Button, { style: styles.button, key: color, onClick: () => { this.handleChange(color); setTimeout(() => this.handleClose(), 300); } }, React.createElement("div", { style: { ...styles.iconButton, background: color } })))))); } render() { const style = { ...(this.props.style || {}) }; style.position = 'relative'; const { color } = this.state; return (React.createElement(Box, { component: "div", style: style, sx: this.props.sx || undefined, className: this.props.className || '' }, this.props.noInputField ? null : (React.createElement(TextField, { disabled: this.props.disabled, variant: "standard", id: "ar_color_picker_name", label: this.props.label || this.props.name, value: color || '', margin: "dense", sx: { '&.MuiFormControl-root': styles.textDense, width: color ? 'calc(100% - 80px)' : 'calc(100% - 56px)', mr: color ? undefined : 1, }, onChange: e => this.handleChange(e.target.value) })), !this.props.noInputField && color ? (React.createElement(IconButton, { disabled: this.props.disabled, onClick: () => this.handleChange(''), size: "small", style: this.props.label || this.props.name ? styles.delButton : undefined }, React.createElement(IconDelete, null))) : null, React.createElement(Box, { component: "div", onClick: e => !this.props.disabled && this.handleClick(e), title: I18n.t('ra_Select color'), sx: { ...styles.swatch, ...(this.props.disabled ? styles.swatchDisabled : undefined), background: color ? undefined : 'transparent', border: color ? undefined : '1px dashed #ccc', boxSizing: 'border-box', marginTop: this.props.noInputField || !(this.props.label || this.props.name) ? 0 : undefined, } }, React.createElement("div", { style: { ...styles.color, background: ColorPicker.getColor(color), width: this.props.noInputField ? this.props.barWidth || 16 : this.props.barWidth || 36, } })), this.state.displayColorPicker && !this.props.disabled ? (React.createElement(Menu, { sx: { ...styles.popover, '&. MuiMenu-list': styles.popoverList, }, anchorEl: this.state.anchorEl, open: !0, onClose: () => this.handleClose() }, React.createElement(ChromePicker, { color: this.state.color || undefined, onChangeComplete: (_color) => this.handleChange(_color.rgb), styles: { default: { picker: { backgroundColor: this.props.theme?.palette.background.paper || '#888', }, }, } }), color && this.props.noInputField ? (React.createElement(IconButton, { sx: styles.closeButton, onClick: () => this.handleChange('') }, React.createElement(IconDelete, null))) : null, React.createElement(IconButton, { sx: styles.closeButton, onClick: () => this.handleClose() }, React.createElement(IconClose, null)), this.renderCustomPalette())) : null)); } } //# sourceMappingURL=ColorPicker.js.map