46 lines
1.1 KiB
React
46 lines
1.1 KiB
React
import { useEffect, useState } from 'react';
|
|
import { api } from '../api.js';
|
|
|
|
const ICONS_BASE = '/api/icons-files/';
|
|
|
|
let _cache = null;
|
|
let _promise = null;
|
|
|
|
function getIcons() {
|
|
if (_cache) return Promise.resolve(_cache);
|
|
if (!_promise) {
|
|
_promise = api.get('/icons')
|
|
.then(rows => { _cache = {}; rows.forEach(r => { _cache[r.name] = r.filename; }); return _cache; })
|
|
.catch(() => { _cache = {}; return _cache; });
|
|
}
|
|
return _promise;
|
|
}
|
|
|
|
export default function PageIcon({ name, size = 40, style }) {
|
|
const [filename, setFilename] = useState(() => _cache?.[name] ?? null);
|
|
|
|
useEffect(() => {
|
|
if (_cache) { setFilename(_cache[name] ?? null); return; }
|
|
getIcons().then(m => setFilename(m[name] ?? null));
|
|
}, [name]);
|
|
|
|
if (!filename) return null;
|
|
return (
|
|
<img
|
|
src={`${ICONS_BASE}${filename}`}
|
|
width={size}
|
|
height={size}
|
|
alt=""
|
|
aria-hidden="true"
|
|
style={{
|
|
display: 'inline',
|
|
verticalAlign: 'middle',
|
|
marginRight: 10,
|
|
objectFit: 'contain',
|
|
opacity: 0.85,
|
|
...style,
|
|
}}
|
|
/>
|
|
);
|
|
}
|