@govbr-ds/webcomponents
Version:
Biblioteca de Web Components baseado no GovBR-DS
1,980 lines (1,961 loc) • 119 kB
JavaScript
/*!
* Construído por SERPRO
* © https://serpro.gov.br/ - MIT License.
*/
import { p as r, H as a, h as o, c as i } from "./p-UEoE4lEZ.js";
var n = {};
/**
* (c) Iconify
*
* For the full copyright and license information, please view the license.txt
* files at https://github.com/iconify/iconify
*
* Licensed under MIT.
*
* @license MIT
* @version 3.0.1
*/ var t;
function requireIconifyIcon() {
if (t) return n;
t = 1;
/**
* Default values for dimensions
*/ const r = Object.freeze({
left: 0,
top: 0,
width: 16,
height: 16
});
/**
* Default values for transformations
*/ const a = Object.freeze({
rotate: 0,
vFlip: false,
hFlip: false
});
/**
* Default values for all optional IconifyIcon properties
*/ const o = Object.freeze({
...r,
...a
});
/**
* Default values for all properties used in ExtendedIconifyIcon
*/ const i = Object.freeze({
...o,
body: "",
hidden: false
});
/**
* Default icon customisations values
*/ const e = Object.freeze({
width: null,
height: null
});
const g = Object.freeze({
...e,
...a
});
/**
* Get rotation value
*/ function rotateFromString(r, a = 0) {
const o = r.replace(/^-?[0-9.]*/, "");
function cleanup(r) {
while (r < 0) r += 4;
return r % 4;
}
if (o === "") {
const a = parseInt(r);
return isNaN(a) ? 0 : cleanup(a);
} else if (o !== r) {
let a = 0;
switch (o) {
case "%":
a = 25;
break;
case "deg":
a = 90;
}
if (a) {
let i = parseFloat(r.slice(0, r.length - o.length));
if (isNaN(i)) return 0;
i = i / a;
return i % 1 === 0 ? cleanup(i) : 0;
}
}
return a;
}
const v = /[\s,]+/;
/**
* Apply "flip" string to icon customisations
*/ function flipFromString(r, a) {
a.split(v).forEach((a => {
const o = a.trim();
switch (o) {
case "horizontal":
r.hFlip = true;
break;
case "vertical":
r.vFlip = true;
break;
}
}));
}
const d = {
...g,
preserveAspectRatio: ""
};
/**
* Get customisations
*/ function getCustomisations(r) {
const a = {
...d
};
const attr = (a, o) => r.getAttribute(a) || o
// Dimensions
;
a.width = attr("width", null);
a.height = attr("height", null);
// Rotation
a.rotate = rotateFromString(attr("rotate", ""));
// Flip
flipFromString(a, attr("flip", ""));
// SVG attributes
a.preserveAspectRatio = attr("preserveAspectRatio", attr("preserveaspectratio", ""));
return a;
}
/**
* Check if customisations have been updated
*/ function haveCustomisationsChanged(r, a) {
for (const o in d) {
if (r[o] !== a[o]) {
return true;
}
}
return false;
}
/**
* Expression to test part of icon name.
*
* Used when loading icons from Iconify API due to project naming convension.
* Ignored when using custom icon sets - convension does not apply.
*/ const c = /^[a-z0-9]+(-[a-z0-9]+)*$/;
/**
* Convert string icon name to IconifyIconName object.
*/ const stringToIcon = (r, a, o, i = "") => {
const n = r.split(":");
if (r.slice(0, 1) === "@") {
if (n.length < 2 || n.length > 3) return null;
i = n.shift().slice(1);
}
if (n.length > 3 || !n.length) return null;
if (n.length > 1) {
const r = n.pop();
const o = n.pop();
const t = {
provider: n.length > 0 ? n[0] : i,
prefix: o,
name: r
};
return a && !validateIconName(t) ? null : t;
}
const t = n[0];
const e = t.split("-");
if (e.length > 1) {
const r = {
provider: i,
prefix: e.shift(),
name: e.join("-")
};
return a && !validateIconName(r) ? null : r;
}
if (o && i === "") {
const r = {
provider: i,
prefix: "",
name: t
};
return a && !validateIconName(r, o) ? null : r;
}
return null;
};
/**
* Check if icon is valid.
*
* This function is not part of stringToIcon because validation is not needed for most code.
*/ const validateIconName = (r, a) => {
if (!r) return false;
return !!((a && r.prefix === "" || !!r.prefix) && !!r.name);
};
/**
* Resolve icon set icons
*
* Returns parent icon for each icon
*/ function getIconsTree(r, a) {
const o = r.icons;
const i = r.aliases || Object.create(null);
const n = Object.create(null);
function resolve(r) {
if (o[r]) return n[r] = [];
if (!(r in n)) {
n[r] = null;
const a = i[r] && i[r].parent;
const o = a && resolve(a);
if (o) n[r] = [ a ].concat(o);
}
return n[r];
}
Object.keys(o).concat(Object.keys(i)).forEach(resolve);
return n;
}
/**
* Merge transformations
*/ function mergeIconTransformations(r, a) {
const o = {};
if (!r.hFlip !== !a.hFlip) o.hFlip = true;
if (!r.vFlip !== !a.vFlip) o.vFlip = true;
const i = ((r.rotate || 0) + (a.rotate || 0)) % 4;
if (i) o.rotate = i;
return o;
}
/**
* Merge icon and alias
*
* Can also be used to merge default values and icon
*/ function mergeIconData(r, o) {
const n = mergeIconTransformations(r, o);
for (const t in i) if (t in a) {
if (t in r && !(t in n)) n[t] = a[t];
} else if (t in o) n[t] = o[t]; else if (t in r) n[t] = r[t];
return n;
}
/**
* Get icon data, using prepared aliases tree
*/ function internalGetIconData(r, a, o) {
const i = r.icons;
const n = r.aliases || Object.create(null);
let t = {};
function parse(r) {
t = mergeIconData(i[r] || n[r], t);
}
parse(a);
o.forEach(parse);
return mergeIconData(r, t);
}
/**
* Extract icons from an icon set
*
* Returns list of icons that were found in icon set
*/ function parseIconSet(r, a) {
const o = [];
if (typeof r !== "object" || typeof r.icons !== "object") return o;
if (r.not_found instanceof Array) r.not_found.forEach((r => {
a(r, null);
o.push(r);
}));
const i = getIconsTree(r);
for (const n in i) {
const t = i[n];
if (t) {
a(n, internalGetIconData(r, n, t));
o.push(n);
}
}
return o;
}
/**
* Optional properties
*/ const b = {
provider: "",
aliases: {},
not_found: {},
...r
};
/**
* Check props
*/ function checkOptionalProps(r, a) {
for (const o in a) if (o in r && typeof r[o] !== typeof a[o]) return false;
return true;
}
/**
* Validate icon set, return it as IconifyJSON on success, null on failure
*
* Unlike validateIconSet(), this function is very basic.
* It does not throw exceptions, it does not check metadata, it does not fix stuff.
*/ function quicklyValidateIconSet(r) {
if (typeof r !== "object" || r === null) return null;
const a = r;
if (typeof a.prefix !== "string" || !r.icons || typeof r.icons !== "object") return null;
if (!checkOptionalProps(r, b)) return null;
const o = a.icons;
for (const r in o) {
const a = o[r];
if (!r || typeof a.body !== "string" || !checkOptionalProps(a, i)) return null;
}
const n = a.aliases || Object.create(null);
for (const r in n) {
const a = n[r];
const t = a.parent;
if (!r || typeof t !== "string" || !o[t] && !n[t] || !checkOptionalProps(a, i)) return null;
}
return a;
}
/**
* Storage by provider and prefix
*/ const u = Object.create(null);
/**
* Create new storage
*/ function newStorage(r, a) {
return {
provider: r,
prefix: a,
icons: Object.create(null),
missing: new Set
};
}
/**
* Get storage for provider and prefix
*/ function getStorage(r, a) {
const o = u[r] || (u[r] = Object.create(null));
return o[a] || (o[a] = newStorage(r, a));
}
/**
* Add icon set to storage
*
* Returns array of added icons
*/ function addIconSet(r, a) {
if (!quicklyValidateIconSet(a)) return [];
return parseIconSet(a, ((a, o) => {
if (o) r.icons[a] = o; else r.missing.add(a);
}));
}
/**
* Add icon to storage
*/ function addIconToStorage(r, a, o) {
try {
if (typeof o.body === "string") {
r.icons[a] = {
...o
};
return true;
}
} catch (r) {}
return false;
}
/**
* List available icons
*/ function listIcons$1(r, a) {
let o = [];
const i = typeof r === "string" ? [ r ] : Object.keys(u);
i.forEach((r => {
const i = typeof r === "string" && typeof a === "string" ? [ a ] : Object.keys(u[r] || {});
i.forEach((a => {
const i = getStorage(r, a);
o = o.concat(Object.keys(i.icons).map((o => (r !== "" ? "@" + r + ":" : "") + a + ":" + o)));
}));
}));
return o;
}
/**
* Allow storing icons without provider or prefix, making it possible to store icons like "home"
*/ let l = false;
function allowSimpleNames(r) {
if (typeof r === "boolean") l = r;
return l;
}
/**
* Get icon data
*
* Returns:
* - IconifyIcon on success, object directly from storage so don't modify it
* - null if icon is marked as missing (returned in `not_found` property from API, so don't bother sending API requests)
* - undefined if icon is missing in storage
*/ function getIconData(r) {
const a = typeof r === "string" ? stringToIcon(r, true, l) : r;
if (a) {
const r = getStorage(a.provider, a.prefix);
const o = a.name;
return r.icons[o] || (r.missing.has(o) ? null : void 0);
}
}
/**
* Add one icon
*/ function addIcon$1(r, a) {
const o = stringToIcon(r, true, l);
if (!o) return false;
const i = getStorage(o.provider, o.prefix);
if (a) return addIconToStorage(i, o.name, a); else {
i.missing.add(o.name);
return true;
}
}
/**
* Add icon set
*/ function addCollection$1(r, a) {
if (typeof r !== "object") return false;
if (typeof a !== "string") a = r.provider || "";
if (l && !a && !r.prefix) {
let a = false;
if (quicklyValidateIconSet(r)) {
r.prefix = "";
parseIconSet(r, ((r, o) => {
if (addIcon$1(r, o)) a = true;
}));
}
return a;
}
const o = r.prefix;
if (!validateIconName({
prefix: o,
name: "a"
})) return false;
const i = getStorage(a, o);
return !!addIconSet(i, r);
}
/**
* Check if icon data is available
*/ function iconLoaded$1(r) {
return !!getIconData(r);
}
/**
* Get full icon
*/ function getIcon$1(r) {
const a = getIconData(r);
return a ? {
...o,
...a
} : a;
}
/**
* Remove callback
*/ function removeCallback(r, a) {
r.forEach((r => {
const o = r.loaderCallbacks;
if (o) r.loaderCallbacks = o.filter((r => r.id !== a));
}));
}
/**
* Update all callbacks for provider and prefix
*/ function updateCallbacks(r) {
if (!r.pendingCallbacksFlag) {
r.pendingCallbacksFlag = true;
setTimeout((() => {
r.pendingCallbacksFlag = false;
const a = r.loaderCallbacks ? r.loaderCallbacks.slice(0) : [];
if (!a.length) return;
let o = false;
const i = r.provider;
const n = r.prefix;
a.forEach((a => {
const t = a.icons;
const e = t.pending.length;
t.pending = t.pending.filter((a => {
if (a.prefix !== n) return true;
const e = a.name;
if (r.icons[e]) t.loaded.push({
provider: i,
prefix: n,
name: e
}); else if (r.missing.has(e)) t.missing.push({
provider: i,
prefix: n,
name: e
}); else {
o = true;
return true;
}
return false;
}));
if (t.pending.length !== e) {
if (!o) removeCallback([ r ], a.id);
a.callback(t.loaded.slice(0), t.missing.slice(0), t.pending.slice(0), a.abort);
}
}));
}));
}
}
/**
* Unique id counter for callbacks
*/ let m = 0;
/**
* Add callback
*/ function storeCallback(r, a, o) {
const i = m++;
const n = removeCallback.bind(null, o, i);
if (!a.pending.length) return n;
const t = {
id: i,
icons: a,
callback: r,
abort: n
};
o.forEach((r => {
(r.loaderCallbacks || (r.loaderCallbacks = [])).push(t);
}));
return n;
}
/**
* Check if icons have been loaded
*/ function sortIcons(r) {
const a = {
loaded: [],
missing: [],
pending: []
};
const o = Object.create(null);
r.sort(((r, a) => {
if (r.provider !== a.provider) return r.provider.localeCompare(a.provider);
if (r.prefix !== a.prefix) return r.prefix.localeCompare(a.prefix);
return r.name.localeCompare(a.name);
}));
let i = {
provider: "",
prefix: "",
name: ""
};
r.forEach((r => {
if (i.name === r.name && i.prefix === r.prefix && i.provider === r.provider) return;
i = r;
const n = r.provider;
const t = r.prefix;
const e = r.name;
const g = o[n] || (o[n] = Object.create(null));
const v = g[t] || (g[t] = getStorage(n, t));
let d;
if (e in v.icons) d = a.loaded; else if (t === "" || v.missing.has(e)) d = a.missing; else d = a.pending;
const c = {
provider: n,
prefix: t,
name: e
};
d.push(c);
}));
return a;
}
/**
* Local storate types and entries
*/ const s = Object.create(null);
/**
* Set API module
*/ function setAPIModule(r, a) {
s[r] = a;
}
/**
* Get API module
*/ function getAPIModule(r) {
return s[r] || s[""];
}
/**
* Convert icons list from string/icon mix to icons and validate them
*/ function listToIcons(r, a = true, o = false) {
const i = [];
r.forEach((r => {
const n = typeof r === "string" ? stringToIcon(r, a, o) : r;
if (n) i.push(n);
}));
return i;
}
/**
* Create full API configuration from partial data
*/ function createAPIConfig(r) {
let a;
if (typeof r.resources === "string") a = [ r.resources ]; else {
a = r.resources;
if (!(a instanceof Array) || !a.length) return null;
}
const o = {
resources: a,
path: r.path || "/",
maxURL: r.maxURL || 500,
rotate: r.rotate || 750,
timeout: r.timeout || 5e3,
random: r.random === true,
index: r.index || 0,
dataAfterTimeout: r.dataAfterTimeout !== false
};
return o;
}
/**
* Local storage
*/ const k = Object.create(null);
/**
* Redundancy for API servers.
*
* API should have very high uptime because of implemented redundancy at server level, but
* sometimes bad things happen. On internet 100% uptime is not possible.
*
* There could be routing problems. Server might go down for whatever reason, but it takes
* few minutes to detect that downtime, so during those few minutes API might not be accessible.
*
* This script has some redundancy to mitigate possible network issues.
*
* If one host cannot be reached in 'rotate' (750 by default) ms, script will try to retrieve
* data from different host. Hosts have different configurations, pointing to different
* API servers hosted at different providers.
*/ const p = [ "https://api.simplesvg.com", "https://api.unisvg.com" ];
const f = [];
while (p.length > 0) if (p.length === 1) f.push(p.shift()); else if (Math.random() > .5) f.push(p.shift()); else f.push(p.pop());
k[""] = createAPIConfig({
resources: [ "https://api.iconify.design" ].concat(f)
});
/**
* Add custom config for provider
*/ function addAPIProvider$1(r, a) {
const o = createAPIConfig(a);
if (o === null) return false;
k[r] = o;
return true;
}
/**
* Get API configuration
*/ function getAPIConfig(r) {
return k[r];
}
/**
* List API providers
*/ function listAPIProviders() {
return Object.keys(k);
}
/**
* Default RedundancyConfig for API calls
*/ const w = {
resources: [],
index: 0,
timeout: 2e3,
rotate: 750,
random: false,
dataAfterTimeout: false
};
/**
* Send query
*/ function sendQuery(r, a, o, i) {
const n = r.resources.length;
const t = r.random ? Math.floor(Math.random() * n) : r.index;
let e;
if (r.random) {
let a = r.resources.slice(0);
e = [];
while (a.length > 1) {
const r = Math.floor(Math.random() * a.length);
e.push(a[r]);
a = a.slice(0, r).concat(a.slice(r + 1));
}
e = e.concat(a);
} else e = r.resources.slice(t).concat(r.resources.slice(0, t));
const g = Date.now();
let v = "pending";
let d = 0;
let c;
let b = null;
let u = [];
let l = [];
if (typeof i === "function") l.push(i);
/**
* Reset timer
*/ function resetTimer() {
if (b) {
clearTimeout(b);
b = null;
}
}
/**
* Abort everything
*/ function abort() {
if (v === "pending") v = "aborted";
resetTimer();
u.forEach((r => {
if (r.status === "pending") r.status = "aborted";
}));
u = [];
}
/**
* Add / replace callback to call when execution is complete.
* This can be used to abort pending query implementations when query is complete or aborted.
*/ function subscribe(r, a) {
if (a) l = [];
if (typeof r === "function") l.push(r);
}
/**
* Get query status
*/ function getQueryStatus() {
return {
startTime: g,
payload: a,
status: v,
queriesSent: d,
queriesPending: u.length,
subscribe,
abort
};
}
/**
* Fail query
*/ function failQuery() {
v = "failed";
l.forEach((r => {
r(void 0, c);
}));
}
/**
* Clear queue
*/ function clearQueue() {
u.forEach((r => {
if (r.status === "pending") r.status = "aborted";
}));
u = [];
}
/**
* Got response from module
*/ function moduleResponse(a, o, i) {
const n = o !== "success";
u = u.filter((r => r !== a));
switch (v) {
case "pending":
break;
case "failed":
if (n || !r.dataAfterTimeout) return;
break;
default:
return;
}
if (o === "abort") {
c = i;
failQuery();
return;
}
if (n) {
c = i;
if (!u.length) if (!e.length) failQuery(); else execNext();
return;
}
resetTimer();
clearQueue();
if (!r.random) {
const o = r.resources.indexOf(a.resource);
if (o !== -1 && o !== r.index) r.index = o;
}
v = "completed";
l.forEach((r => {
r(i);
}));
}
/**
* Execute next query
*/ function execNext() {
if (v !== "pending") return;
resetTimer();
const i = e.shift();
if (i === void 0) {
if (u.length) {
b = setTimeout((() => {
resetTimer();
if (v === "pending") {
clearQueue();
failQuery();
}
}), r.timeout);
return;
}
failQuery();
return;
}
const n = {
status: "pending",
resource: i,
callback: (r, a) => {
moduleResponse(n, r, a);
}
};
u.push(n);
d++;
b = setTimeout(execNext, r.rotate);
o(i, a, n.callback);
}
setTimeout(execNext);
return getQueryStatus;
}
/**
* Redundancy instance
*/ function initRedundancy(r) {
const a = {
...w,
...r
};
let o = [];
/**
* Remove aborted and completed queries
*/ function cleanup() {
o = o.filter((r => r().status === "pending"));
}
/**
* Send query
*/ function query(r, i, n) {
const t = sendQuery(a, r, i, ((r, a) => {
cleanup();
if (n) n(r, a);
}));
o.push(t);
return t;
}
/**
* Find instance
*/ function find(r) {
return o.find((a => r(a))) || null;
}
const i = {
query,
find,
setIndex: r => {
a.index = r;
},
getIndex: () => a.index,
cleanup
};
return i;
}
function emptyCallback$1() {}
const y = Object.create(null);
/**
* Get Redundancy instance for provider
*/ function getRedundancyCache(r) {
if (!y[r]) {
const a = getAPIConfig(r);
if (!a) return;
const o = initRedundancy(a);
const i = {
config: a,
redundancy: o
};
y[r] = i;
}
return y[r];
}
/**
* Send API query
*/ function sendAPIQuery(r, a, o) {
let i;
let n;
if (typeof r === "string") {
const a = getAPIModule(r);
if (!a) {
o(void 0, 424);
return emptyCallback$1;
}
n = a.send;
const t = getRedundancyCache(r);
if (t) i = t.redundancy;
} else {
const a = createAPIConfig(r);
if (a) {
i = initRedundancy(a);
const o = r.resources ? r.resources[0] : "";
const t = getAPIModule(o);
if (t) n = t.send;
}
}
if (!i || !n) {
o(void 0, 424);
return emptyCallback$1;
}
return i.query(a, n, o)().abort;
}
function emptyCallback() {}
/**
* Function called when new icons have been loaded
*/ function loadedNewIcons(r) {
if (!r.iconsLoaderFlag) {
r.iconsLoaderFlag = true;
setTimeout((() => {
r.iconsLoaderFlag = false;
updateCallbacks(r);
}));
}
}
/**
* Check icon names for API
*/ function checkIconNamesForAPI(r) {
const a = [];
const o = [];
r.forEach((r => {
(r.match(c) ? a : o).push(r);
}));
return {
valid: a,
invalid: o
};
}
/**
* Parse loader response
*/ function parseLoaderResponse(r, a, o) {
function checkMissing() {
const o = r.pendingIcons;
a.forEach((a => {
if (o) o.delete(a);
if (!r.icons[a]) r.missing.add(a);
}));
}
if (o && typeof o === "object") try {
const a = addIconSet(r, o);
if (!a.length) {
checkMissing();
return;
}
} catch (r) {
console.error(r);
}
checkMissing();
loadedNewIcons(r);
}
/**
* Handle response that can be async
*/ function parsePossiblyAsyncResponse(r, a) {
if (r instanceof Promise) r.then((r => {
a(r);
})).catch((() => {
a(null);
})); else a(r);
}
/**
* Load icons
*/ function loadNewIcons(r, a) {
if (!r.iconsToLoad) r.iconsToLoad = a; else r.iconsToLoad = r.iconsToLoad.concat(a).sort();
if (!r.iconsQueueFlag) {
r.iconsQueueFlag = true;
setTimeout((() => {
r.iconsQueueFlag = false;
const {provider: a, prefix: o} = r;
const i = r.iconsToLoad;
delete r.iconsToLoad;
if (!i || !i.length) return;
const n = r.loadIcon;
if (r.loadIcons && (i.length > 1 || !n)) {
parsePossiblyAsyncResponse(r.loadIcons(i, o, a), (a => {
parseLoaderResponse(r, i, a);
}));
return;
}
if (n) {
i.forEach((i => {
const t = n(i, o, a);
parsePossiblyAsyncResponse(t, (a => {
const n = a ? {
prefix: o,
icons: {
[i]: a
}
} : null;
parseLoaderResponse(r, [ i ], n);
}));
}));
return;
}
const {valid: t, invalid: e} = checkIconNamesForAPI(i);
if (e.length) parseLoaderResponse(r, e, null);
if (!t.length) return;
const g = o.match(c) ? getAPIModule(a) : null;
if (!g) {
parseLoaderResponse(r, t, null);
return;
}
const v = g.prepare(a, o, t);
v.forEach((o => {
sendAPIQuery(a, o, (a => {
parseLoaderResponse(r, o.icons, a);
}));
}));
}));
}
}
/**
* Load icons
*/ const loadIcons$1 = (r, a) => {
const o = listToIcons(r, true, allowSimpleNames());
const i = sortIcons(o);
if (!i.pending.length) {
let r = true;
if (a) setTimeout((() => {
if (r) a(i.loaded, i.missing, i.pending, emptyCallback);
}));
return () => {
r = false;
};
}
const n = Object.create(null);
const t = [];
let e, g;
i.pending.forEach((r => {
const {provider: a, prefix: o} = r;
if (o === g && a === e) return;
e = a;
g = o;
t.push(getStorage(a, o));
const i = n[a] || (n[a] = Object.create(null));
if (!i[o]) i[o] = [];
}));
i.pending.forEach((r => {
const {provider: a, prefix: o, name: i} = r;
const t = getStorage(a, o);
const e = t.pendingIcons || (t.pendingIcons = new Set);
if (!e.has(i)) {
e.add(i);
n[a][o].push(i);
}
}));
t.forEach((r => {
const a = n[r.provider][r.prefix];
if (a.length) loadNewIcons(r, a);
}));
return a ? storeCallback(a, i, t) : emptyCallback;
};
/**
* Load one icon using Promise
*/ const loadIcon$1 = r => new Promise(((a, i) => {
const n = typeof r === "string" ? stringToIcon(r, true) : r;
if (!n) {
i(r);
return;
}
loadIcons$1([ n || r ], (t => {
if (t.length && n) {
const r = getIconData(n);
if (r) {
a({
...o,
...r
});
return;
}
}
i(r);
}));
}));
/**
* Test icon string
*/ function testIconObject(r) {
try {
const a = typeof r === "string" ? JSON.parse(r) : r;
if (typeof a.body === "string") {
return {
...a
};
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (r) {
}
}
/**
* Parse icon value, load if needed
*/ function parseIconValue(r, a) {
if (typeof r === "object") {
const a = testIconObject(r);
return {
data: a,
value: r
};
}
if (typeof r !== "string") {
// Invalid value
return {
value: r
};
}
// Check for JSON
if (r.includes("{")) {
const a = testIconObject(r);
if (a) {
return {
data: a,
value: r
};
}
}
// Parse icon name
const o = stringToIcon(r, true, true);
if (!o) {
return {
value: r
};
}
// Valid icon name: check if data is available
const i = getIconData(o);
// Icon data exists or icon has no prefix. Do not load icon from API if icon has no prefix
if (i !== undefined || !o.prefix) {
return {
value: r,
name: o,
data: i
};
}
// Load icon
const n = loadIcons$1([ o ], (() => a(r, o, getIconData(o))));
return {
value: r,
name: o,
loading: n
};
}
// Check for Safari
let h = false;
try {
h = navigator.vendor.indexOf("Apple") === 0;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (r) {
}
/**
* Get render mode
*/ function getRenderMode(r, a) {
switch (a) {
// Force mode
case "svg":
case "bg":
case "mask":
return a;
}
// Check for animation, use 'style' for animated icons, unless browser is Safari
// (only <a>, which should be ignored or animations start with '<a')
if (a !== "style" && (h || r.indexOf("<a") === -1)) {
// Render <svg>
return "svg";
}
// Use background or mask
return r.indexOf("currentColor") === -1 ? "bg" : "mask";
}
/**
* Regular expressions for calculating dimensions
*/ const x = /(-?[0-9.]*[0-9]+[0-9.]*)/g;
const I = /^-?[0-9.]*[0-9]+[0-9.]*$/g;
function calculateSize$1(r, a, o) {
if (a === 1) return r;
o = o || 100;
if (typeof r === "number") return Math.ceil(r * a * o) / o;
if (typeof r !== "string") return r;
const i = r.split(x);
if (i === null || !i.length) return r;
const n = [];
let t = i.shift();
let e = I.test(t);
while (true) {
if (e) {
const r = parseFloat(t);
if (isNaN(r)) n.push(t); else n.push(Math.ceil(r * a * o) / o);
} else n.push(t);
t = i.shift();
if (t === void 0) return n.join("");
e = !e;
}
}
function splitSVGDefs(r, a = "defs") {
let o = "";
const i = r.indexOf("<" + a);
while (i >= 0) {
const n = r.indexOf(">", i);
const t = r.indexOf("</" + a);
if (n === -1 || t === -1) break;
const e = r.indexOf(">", t);
if (e === -1) break;
o += r.slice(n + 1, t).trim();
r = r.slice(0, i).trim() + r.slice(e + 1);
}
return {
defs: o,
content: r
};
}
/**
* Merge defs and content
*/ function mergeDefsAndContent(r, a) {
return r ? "<defs>" + r + "</defs>" + a : a;
}
/**
* Wrap SVG content, without wrapping definitions
*/ function wrapSVGContent(r, a, o) {
const i = splitSVGDefs(r);
return mergeDefsAndContent(i.defs, a + i.content + o);
}
/**
* Check if value should be unset. Allows multiple keywords
*/ const isUnsetKeyword = r => r === "unset" || r === "undefined" || r === "none"
/**
* Get SVG attributes and content from icon + customisations
*
* Does not generate style to make it compatible with frameworks that use objects for style, such as React.
* Instead, it generates 'inline' value. If true, rendering engine should add verticalAlign: -0.125em to icon.
*
* Customisations should be normalised by platform specific parser.
* Result should be converted to <svg> by platform specific parser.
* Use replaceIDs to generate unique IDs for body.
*/;
function iconToSVG(r, a) {
const i = {
...o,
...r
};
const n = {
...g,
...a
};
const t = {
left: i.left,
top: i.top,
width: i.width,
height: i.height
};
let e = i.body;
[ i, n ].forEach((r => {
const a = [];
const o = r.hFlip;
const i = r.vFlip;
let n = r.rotate;
if (o) if (i) n += 2; else {
a.push("translate(" + (t.width + t.left).toString() + " " + (0 - t.top).toString() + ")");
a.push("scale(-1 1)");
t.top = t.left = 0;
} else if (i) {
a.push("translate(" + (0 - t.left).toString() + " " + (t.height + t.top).toString() + ")");
a.push("scale(1 -1)");
t.top = t.left = 0;
}
let g;
if (n < 0) n -= Math.floor(n / 4) * 4;
n = n % 4;
switch (n) {
case 1:
g = t.height / 2 + t.top;
a.unshift("rotate(90 " + g.toString() + " " + g.toString() + ")");
break;
case 2:
a.unshift("rotate(180 " + (t.width / 2 + t.left).toString() + " " + (t.height / 2 + t.top).toString() + ")");
break;
case 3:
g = t.width / 2 + t.left;
a.unshift("rotate(-90 " + g.toString() + " " + g.toString() + ")");
break;
}
if (n % 2 === 1) {
if (t.left !== t.top) {
g = t.left;
t.left = t.top;
t.top = g;
}
if (t.width !== t.height) {
g = t.width;
t.width = t.height;
t.height = g;
}
}
if (a.length) e = wrapSVGContent(e, '<g transform="' + a.join(" ") + '">', "</g>");
}));
const v = n.width;
const d = n.height;
const c = t.width;
const b = t.height;
let u;
let l;
if (v === null) {
l = d === null ? "1em" : d === "auto" ? b : d;
u = calculateSize$1(l, c / b);
} else {
u = v === "auto" ? c : v;
l = d === null ? calculateSize$1(u, b / c) : d === "auto" ? b : d;
}
const m = {};
const setAttr = (r, a) => {
if (!isUnsetKeyword(a)) m[r] = a.toString();
};
setAttr("width", u);
setAttr("height", l);
const s = [ t.left, t.top, c, b ];
m.viewBox = s.join(" ");
return {
attributes: m,
viewBox: s,
body: e
};
}
/**
* Generate <svg>
*/ function iconToHTML$1(r, a) {
let o = r.indexOf("xlink:") === -1 ? "" : ' xmlns:xlink="http://www.w3.org/1999/xlink"';
for (const r in a) o += " " + r + '="' + a[r] + '"';
return '<svg xmlns="http://www.w3.org/2000/svg"' + o + ">" + r + "</svg>";
}
/**
* Encode SVG for use in url()
*
* Short alternative to encodeURIComponent() that encodes only stuff used in SVG, generating
* smaller code.
*/ function encodeSVGforURL(r) {
return r.replace(/"/g, "'").replace(/%/g, "%25").replace(/#/g, "%23").replace(/</g, "%3C").replace(/>/g, "%3E").replace(/\s+/g, " ");
}
/**
* Generate data: URL from SVG
*/ function svgToData(r) {
return "data:image/svg+xml," + encodeSVGforURL(r);
}
/**
* Generate url() from SVG
*/ function svgToURL$1(r) {
return 'url("' + svgToData(r) + '")';
}
const detectFetch = () => {
let r;
try {
r = fetch;
if (typeof r === "function") return r;
} catch (r) {}
};
/**
* Fetch function
*/ let S = detectFetch();
/**
* Set custom fetch() function
*/ function setFetch(r) {
S = r;
}
/**
* Get fetch() function. Used by Icon Finder Core
*/ function getFetch() {
return S;
}
/**
* Calculate maximum icons list length for prefix
*/ function calculateMaxLength(r, a) {
const o = getAPIConfig(r);
if (!o) return 0;
let i;
if (!o.maxURL) i = 0; else {
let r = 0;
o.resources.forEach((a => {
const o = a;
r = Math.max(r, o.length);
}));
const n = a + ".json?icons=";
i = o.maxURL - r - o.path.length - n.length;
}
return i;
}
/**
* Should query be aborted, based on last HTTP status
*/ function shouldAbort(r) {
return r === 404;
}
/**
* Prepare params
*/ const prepare = (r, a, o) => {
const i = [];
const n = calculateMaxLength(r, a);
const t = "icons";
let e = {
type: t,
provider: r,
prefix: a,
icons: []
};
let g = 0;
o.forEach(((o, v) => {
g += o.length + 1;
if (g >= n && v > 0) {
i.push(e);
e = {
type: t,
provider: r,
prefix: a,
icons: []
};
g = o.length;
}
e.icons.push(o);
}));
i.push(e);
return i;
};
/**
* Get path
*/ function getPath(r) {
if (typeof r === "string") {
const a = getAPIConfig(r);
if (a) return a.path;
}
return "/";
}
/**
* Load icons
*/ const send = (r, a, o) => {
if (!S) {
o("abort", 424);
return;
}
let i = getPath(a.provider);
switch (a.type) {
case "icons":
{
const r = a.prefix;
const o = a.icons;
const n = o.join(",");
const t = new URLSearchParams({
icons: n
});
i += r + ".json?" + t.toString();
break;
}
case "custom":
{
const r = a.uri;
i += r.slice(0, 1) === "/" ? r.slice(1) : r;
break;
}
default:
o("abort", 400);
return;
}
let n = 503;
S(r + i).then((r => {
const a = r.status;
if (a !== 200) {
setTimeout((() => {
o(shouldAbort(a) ? "abort" : "next", a);
}));
return;
}
n = 501;
return r.json();
})).then((r => {
if (typeof r !== "object" || r === null) {
setTimeout((() => {
if (r === 404) o("abort", r); else o("next", n);
}));
return;
}
setTimeout((() => {
o("success", r);
}));
})).catch((() => {
o("next", n);
}));
};
/**
* Export module
*/ const z = {
prepare,
send
};
/**
* Set custom loader for multiple icons
*/ function setCustomIconsLoader$1(r, a, o) {
getStorage(o || "", a).loadIcons = r;
}
/**
* Set custom loader for one icon
*/ function setCustomIconLoader$1(r, a, o) {
getStorage(o || "", a).loadIcon = r;
}
/**
* Attribute to add
*/ const C = "data-style";
/**
* Custom style to add to each node
*/ let P = "";
/**
* Set custom style to add to all components
*
* Affects only components rendered after function call
*/ function appendCustomStyle(r) {
P = r;
}
/**
* Add/update style node
*/ function updateStyle(r, a) {
// Get node, create if needed
let o = Array.from(r.childNodes).find((r => r.hasAttribute && r.hasAttribute(C)));
if (!o) {
o = document.createElement("style");
o.setAttribute(C, C);
r.appendChild(o);
}
// Update content
o.textContent = ":host{display:inline-block;vertical-align:" + (a ? "-0.125em" : "0") + "}span,svg{display:block;margin:auto}" + P;
}
// Core
/**
* Get functions and initialise stuff
*/ function exportFunctions() {
/**
* Initialise stuff
*/
// Set API module
setAPIModule("", z);
// Allow simple icon names
allowSimpleNames(true);
let r;
try {
r = window;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (r) {
}
if (r) {
// Load icons from global "IconifyPreload"
if (r.IconifyPreload !== void 0) {
const a = r.IconifyPreload;
const o = "Invalid IconifyPreload syntax.";
if (typeof a === "object" && a !== null) {
(a instanceof Array ? a : [ a ]).forEach((r => {
try {
if (
// Check if item is an object and not null/array
typeof r !== "object" || r === null || r instanceof Array ||
// Check for 'icons' and 'prefix'
typeof r.icons !== "object" || typeof r.prefix !== "string" ||
// Add icon set
!addCollection$1(r)) {
console.error(o);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (r) {
console.error(o);
}
}));
}
}
// Set API from global "IconifyProviders"
if (r.IconifyProviders !== void 0) {
const a = r.IconifyProviders;
if (typeof a === "object" && a !== null) {
for (const r in a) {
const o = "IconifyProviders[" + r + "] is invalid.";
try {
const i = a[r];
if (typeof i !== "object" || !i || i.resources === void 0) {
continue;
}
if (!addAPIProvider$1(r, i)) {
console.error(o);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (r) {
console.error(o);
}
}
}
}
}
const a = {
getAPIConfig,
setAPIModule,
sendAPIQuery,
setFetch,
getFetch,
listAPIProviders
};
return {
iconLoaded: iconLoaded$1,
getIcon: getIcon$1,
listIcons: listIcons$1,
addIcon: addIcon$1,
addCollection: addCollection$1,
calculateSize: calculateSize$1,
buildIcon: iconToSVG,
iconToHTML: iconToHTML$1,
svgToURL: svgToURL$1,
loadIcons: loadIcons$1,
loadIcon: loadIcon$1,
addAPIProvider: addAPIProvider$1,
setCustomIconLoader: setCustomIconLoader$1,
setCustomIconsLoader: setCustomIconsLoader$1,
appendCustomStyle,
_api: a
};
}
// List of properties to apply
const j = {
"background-color": "currentColor"
};
const A = {
"background-color": "transparent"
};
// Dynamically add common props to variables above
const T = {
image: "var(--svg)",
repeat: "no-repeat",
size: "100% 100%"
};
const O = {
"-webkit-mask": j,
mask: j,
background: A
};
for (const r in O) {
const a = O[r];
for (const o in T) {
a[r + "-" + o] = T[o];
}
}
/**
* Fix size: add 'px' to numbers
*/ function fixSize(r) {
return r ? r + (r.match(/^[-0-9.]+$/) ? "px" : "") : "inherit";
}
/**
* Render node as <span>
*/ function renderSPAN(r, a, o) {
const i = document.createElement("span");
// Body
let n = r.body;
if (n.indexOf("<a") !== -1) {
// Animated SVG: add something to fix timing bug
n += "\x3c!-- " + Date.now() + " --\x3e";
}
// Generate SVG as URL
const t = r.attributes;
const e = iconToHTML$1(n, {
...t,
width: a.width + "",
height: a.height + ""
});
const g = svgToURL$1(e);
// Generate style
const v = i.style;
const d = {
"--svg": g,
width: fixSize(t.width),
height: fixSize(t.height),
...o ? j : A
};
// Apply style
for (const r in d) {
v.setProperty(r, d[r]);
}
return i;
}
let L;
/**
* Attempt to create policy
*/ function createPolicy() {
try {
L = window.trustedTypes.createPolicy("iconify", {
createHTML: r => r
});
} catch (r) {
L = null;
}
}
/**
* Clean up value for innerHTML assignment
*
* This code doesn't actually clean up anything.
* It is intended be used with Iconify icon data, which has already been validated
*/ function cleanUpInnerHTML(r) {
if (L === void 0) createPolicy();
return L ? L.createHTML(r) : r;
}
/**
* Render node as <svg>
*/ function renderSVG(r) {
const a = document.createElement("span");
// Add style if needed
const o = r.attributes;
let i = "";
if (!o.width) {
i = "width: inherit;";
}
if (!o.height) {
i += "height: inherit;";
}
if (i) {
o.style = i;
}
// Generate SVG
const n = iconToHTML$1(r.body, o);
a.innerHTML = cleanUpInnerHTML(n);
return a.firstChild;
}
/**
* Find icon node
*/ function findIconElement(r) {
return Array.from(r.childNodes).find((r => {
const a = r.tagName && r.tagName.toUpperCase();
return a === "SPAN" || a === "SVG";
}));
}
/**
* Render icon
*/ function renderIcon(r, a) {
const i = a.icon.data;
const n = a.customisations;
// Render icon
const t = iconToSVG(i, n);
if (n.preserveAspectRatio) {
t.attributes["preserveAspectRatio"] = n.preserveAspectRatio;
}
const e = a.renderedMode;
let g;
switch (e) {
case "svg":
g = renderSVG(t);
break;
default:
g = renderSPAN(t, {
...o,
...i
}, e === "mask");
}
// Set element
const v = findIconElement(r);
if (v) {
// Replace old element
if (g.tagName === "SPAN" && v.tagName === g.tagName) {
// Swap style instead of whole node
v.setAttribute("style", g.getAttribute("style"));
} else {
r.replaceChild(g, v);
}
} else {
// Add new element
r.appendChild(g);
}
}
/**
* Set state to PendingState
*/ function setPendingState(r, a, o) {
const i = o && (o.rendered ? o : o.lastRender);
return {
rendered: false,
inline: a,
icon: r,
lastRender: i
};
}
/**
* Register 'iconify-icon' component, if it does not exist
*/ function defineIconifyIcon(r = "iconify-icon") {
// Check for custom elements registry and HTMLElement
let a;
let o;
try {
a = window.customElements;
o = window.HTMLElement;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (r) {
return;
}
// Make sure registry and HTMLElement exist
if (!a || !o) {
return;
}
// Check for duplicate
const i = a.get(r);
if (i) {
return i;
}
// All attributes
const n = [
// Icon
"icon",
// Mode
"mode", "inline", "noobserver",
// Customisations
"width", "height", "rotate", "flip" ];
/**
* Component class
*/ const t = class extends o {
// Root
_shadowRoot;
// Initialised
_initialised=false;
// Icon state
_state;
// Attributes check queued
_checkQueued=false;
// Connected
_connected=false;
// Observer
_observer=null;
_visible=true;
/**
* Constructor
*/
constructor() {
super();
// Attach shadow DOM
const r = this._shadowRoot = this.attachShadow({
mode: "open"
});
// Add style
const a = this.hasAttribute("inline");
updateStyle(r, a);
// Create empty state
this._state = setPendingState({
value: ""
}, a);
// Queue icon render
this._queueCheck();
}
/**
* Connected to DOM
*/ connectedCallback() {
this._connected = true;
this.startObserver();
}
/**
* Disconnected from DOM
*/ disconnectedCallback() {
this._connected = false;
this.stopObserver();
}
/**
* Observed attributes
*/ static get observedAttributes() {
return n.slice(0);
}
/**
* Observed properties that are different from attributes
*
* Experimental! Need to test with various frameworks that support it
*/
/*
static get properties() {
return {
inline: {
type: Boolean,
reflect: true,
},
// Not listing other attributes because they are strings or combination
// of string and another type. Cannot have multiple types
};
}
*/
/**
* Attribute has changed
*/ attributeChangedCallback(r) {
switch (r) {
case "inline":
{
// Update immediately: not affected by other attributes
const r = this.hasAttribute("inline");
const a = this._state;
if (r !== a.inline) {
// Update style if inline mode changed
a.inline = r;
updateStyle(this._shadowRoot, r);
}
break;
}
case "noobserver":
{
const r = this.hasAttribute("noobserver");
if (r) {
this.startObserver();
} else {
this.stopObserver();
}
break;
}
default:
// Queue check for other attributes
this._queueCheck();
}
}
/**
* Get/set icon
*/ get icon() {
const r = this.getAttribute("icon");
if (r && r.slice(0, 1) === "{") {
try {
return JSON.parse(r);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (r) {
}
}
return r;
}
set icon(r) {
if (typeof r === "object") {
r = JSON.stringify(r);
}
this.setAttribute("icon", r);
}
/**
* Get/set inline
*/ get inline() {
return this.hasAttribute("inline");
}
set inline(r) {
if (r) {
this.setAttribute("inline", "true");
} else {
this.removeAttribute("inline");
}
}
/**
* Get/set observer
*/ get observer() {
return this.hasAttribute("observer");
}
set observer(r) {
if (r) {
this.setAttribute("observer", "true");
} else {
this.removeAttribute("observer");
}
}
/**
* Restart animation
*/ restartAnimation() {
const r = this._state;
if (r.rendered) {
const a = this._shadowRoot;
if (r.renderedMode === "svg") {
// Update root node
try {
a.lastChild.setCurrentTime(0);
return;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (r) {
// Failed: setCurrentTime() is not supported
}
}
renderIcon(a, r);
}
}
/**
* Get status
*/ get status() {
const r = this._state;
return r.rendered ? "rendered" : r.icon.data === null ? "failed" : "loading";
}
/**
* Queue attributes re-check
*/ _queueCheck() {
if (!this._checkQueued) {
this._checkQueued = true;
setTimeout((() => {
this._check();
}));
}
}
/**
* Check for changes
*/ _check() {
if (!this._checkQueued) {
return;
}
this._checkQueued = false;
const r = this._state;
// Get icon
const a = this.getAttribute("icon");
if (a !== r.icon.value) {
this._iconChanged(a);
return;
}
// Ignore other attributes if icon is not rendered
if (!r.rendered || !this._visible) {
return;
}
// Check for mode and attribute changes
const o = this.getAttribute("mode");
const i = getCustomisations(this);
if (r.attrMode !== o || haveCustomisationsChanged(r.customisations, i) || !findIconElement(this._shadowRoot)) {
this._renderIcon(r.icon, i, o);
}
}
/**
* Icon value has changed