UNPKG

@iobroker/adapter-react-v5

Version:

React components to develop ioBroker interfaces with react.

126 lines 4.79 kB
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