@iobroker/adapter-react-v5
Version:
React components to develop ioBroker interfaces with react.
126 lines • 4.79 kB
JavaScript
import React, { Component } from 'react';
import { Box } from '@mui/material';
import { IconNoIcon } from '../icons/IconNoIcon';
function getElementFromSource(src) {
const svgContainer = document.createElement('div');
svgContainer.innerHTML = src;
const svg = svgContainer.firstElementChild;
if (svg?.remove) {
svg.remove();
}
else if (svg) {
svgContainer.removeChild(svg);
}
svgContainer.remove();
return svg;
}
function serializeAttrs(map) {
const ret = {};
if (!map) {
return ret;
}
for (let prop, i = 0; i < map.length; i++) {
const key = map[i].name;
if (key === 'class') {
prop = 'className';
}
else if (!key.startsWith('data-')) {
prop = key.replace(/[-|:]([a-z])/g, g => g[1].toUpperCase());
}
else {
prop = key;
}
ret[prop] = map[i].value;
}
return ret;
}
/**
* A component for displaying an image.
*/
export class Image extends Component {
svg;
static REMOTE_SERVER = window.location.hostname.includes('iobroker.in');
static REMOTE_PREFIX = window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/') + 1);
constructor(props) {
super(props);
this.state = {
svg: !!this.props.src?.startsWith('data:'),
created: true,
color: this.props.color || '',
src: this.props.src || '',
imgError: false,
showError: !!this.props.showError,
};
this.svg = this.state.svg && this.state.src ? this.getSvgFromData(this.state.src) : null;
}
static getDerivedStateFromProps(props, state) {
const newState = {};
let changed = false;
if (props && state && props.src !== state.src) {
newState.src = props.src;
newState.svg = props.src?.startsWith('data:');
newState.created = false;
changed = true;
}
if (props && state && props.color !== state.color) {
newState.color = props.color;
newState.created = false;
changed = true;
}
if (props && state && props.showError !== state.showError) {
newState.showError = props.showError;
changed = true;
}
return changed ? newState : null;
}
getSvgFromData(src) {
const len = 'data:image/svg+xml;base64,';
if (!src.startsWith(len)) {
return null;
}
src = src.substring(len.length);
try {
src = atob(src);
const svg = getElementFromSource(src);
const inner = svg.innerHTML;
const svgProps = serializeAttrs(svg.attributes);
svg.remove();
return (React.createElement(Box, { component: "svg", sx: this.props.sx, className: this.props.className, style: this.state.color ? { color: this.state.color } : undefined, ...svgProps, dangerouslySetInnerHTML: { __html: inner } }));
}
catch {
// ignore
}
return null;
}
render() {
if (this.state.svg) {
if (!this.state.created) {
setTimeout(() => {
this.svg = this.state.src ? this.getSvgFromData(this.state.src) : null;
this.setState({ created: true });
}, 50);
}
return this.svg;
}
if (this.state.src) {
if (this.state.imgError || !this.state.src) {
return React.createElement(IconNoIcon, { className: this.props.className });
}
if (Image.REMOTE_SERVER &&
!this.state.src.startsWith('http://') &&
!this.state.src.startsWith('https://')) {
let src = (this.props.imagePrefix || '') + this.state.src;
if (src.startsWith('./')) {
src = Image.REMOTE_PREFIX + src.substring(2);
}
else if (!src.startsWith('/')) {
src = Image.REMOTE_PREFIX + src;
}
return (React.createElement(Box, { component: "img", sx: this.props.sx, className: this.props.className, src: `https://remote-files.iobroker.in${src}`, alt: "", onError: () => this.props.showError ? this.setState({ imgError: true }) : this.setState({ src: '' }) }));
}
return (React.createElement(Box, { component: "img", sx: this.props.sx, className: this.props.className, src: (this.props.imagePrefix || '') + this.state.src, alt: "", onError: () => this.props.showError ? this.setState({ imgError: true }) : this.setState({ src: '' }) }));
}
return null;
}
}
//# sourceMappingURL=Image.js.map