UNPKG

solid-circle-flags

Version:

A Solid component with a collection of 300+ minimal circular SVG country flags.

308 lines (303 loc) 6.04 kB
// src/countries.ts var countryToCountryMap = { ac: "sh-ac", bq: "bq-bo", bv: "no", "cn-hk": "hk", cp: "fr-cp", dg: "io", ea: "es-ce", eu: "european_union", fx: "fr", hm: "au", ic: "es-cn", sh: "sh-hl", sj: "no", su: "soviet_union", ta: "sh-ta", uk: "gb", um: "us", "us-as": "as", "us-gu": "gu", "us-mp": "mp", "us-pr": "pr", "us-um": "us", "us-vi": "vi" }; // src/languages.ts var languageToCountryMap = { aa: "et-af", ab: "ge-ab", af: "za", ak: "gh", am: "et", an: "es-ar", as: "in-as", av: "ru-da", ay: "bo", az: "az", ba: "ru-ba", be: "by", bg: "bg", bi: "vu", bm: "ml", bn: "bd", bo: "tibet", br: "fr-bre", bs: "ba", ca: "es-ct", ce: "ru-ce", ceb: "ph", ch: "gu", chm: "ru", ckb: "iq-kr", co: "fr-20r", cs: "cz", cv: "ru-cu", cy: "gb-wls", da: "dk", de: "de", dv: "mv", dz: "bt", ee: "gh", el: "gr", en: "us", es: "es", et: "ee", eu: "es-pv", fa: "ir", fi: "fi", fil: "ph", fj: "fj", fo: "fo", fr: "fr", fy: "nl-fr", ga: "ie", gd: "gb-sct", gl: "es-ga", gn: "py", gu: "in-gj", gv: "im", ha: "ng", haw: "us-hi", he: "il", hi: "in", hmn: "hmong", ho: "pg", hr: "hr", ht: "ht", hu: "hu", hy: "am", id: "id", ig: "ng", ilo: "ph", is: "is", it: "it", ja: "jp", jv: "id-jt", ka: "ge", kg: "cd", ki: "ke", kk: "kz", kl: "gl", km: "kh", kn: "in-ka", ko: "kr", kr: "ng", kri: "sl", ks: "in", ku: "iq-kr", kv: "ru-ko", kw: "gb-con", ky: "kg", lb: "lu", lg: "ug", ln: "cd", lo: "la", lt: "lt", lu: "cd", lus: "in-mz", lv: "lv", mg: "mg", mh: "mh", mi: "maori", mk: "mk", ml: "malayali", mn: "mn", mni: "in-mn", mrj: "ru", ms: "my", mt: "mt", my: "mm", na: "nr", nb: "no", nd: "zw", ne: "np", nl: "nl", nn: "no", no: "no", nr: "za", ny: "mw", oc: "occitania", om: "et", or: "in-or", os: "ru", oto: "mx", pa: "in", pap: "cw", pl: "pl", pms: "it-21", ps: "af", "pt-br": "br", pt: "pt", qu: "pe", rm: "ch-gr", rn: "bi", ro: "ro", ru: "ru", rw: "rw", sc: "it-82", sd: "pk-sd", se: "no", sg: "cf", si: "lk", sk: "sk", sl: "si", sm: "ws", sn: "zw", so: "so", sq: "al", sr: "rs", ss: "sz", st: "ls", su: "id-jb", sv: "se", sw: "tz", ta: "in-tn", te: "in-tg", tg: "tj", th: "th", ti: "er", tk: "tm", tl: "ph", tn: "bw", to: "to", tr: "tr", tt: "ru-ta", ty: "pf", udm: "ru-ud", ug: "cn-xj", uk: "ua", ur: "pk", uz: "uz", vi: "vn", xh: "za", yo: "yorubaland", yua: "mx", zh: "cn", zu: "za" }; // src/components/FallbackSvg.tsx function FallbackSvg(props) { const maskId = "circular-graphic-fallback-mask"; return <svg xmlns="http://www.w3.org/2000/svg" width={props.width} height={props.height} viewBox="0 0 512 512" aria-label="Loading" role="img" ><mask id={maskId}><circle cx="256" cy="256" r="256" fill="#fff" /></mask><g mask={`url(#${maskId})`}><path fill="#eee" d="M0 0h512v512H0z" /><circle cx="253" cy="380" r="32" fill="#acabb1" /><path fill="#acabb1" d="M322.4 135.5c-15.6-13.6-37.4-20.3-65.5-20.3-27.9 0-49.9 7.2-66 21.4a74.9 74.9 0 0 0-24.3 55.4h-.2v12.8H224l.1-9a35.2 35.2 0 0 1 9.3-24.8c5.8-6.1 13.7-9 23.5-9 20.7 0 31 11 31 33.4 0 7.4-2 14.5-6 21.1a124.2 124.2 0 0 1-23.9 26 90.4 90.4 0 0 0-24.8 32.3c-4.5 11-6.8 26.7-6.8 45.2h51l.8-13.1a54 54 0 0 1 17.3-33.9l16.2-15.2a131.4 131.4 0 0 0 26.4-33.2 69.5 69.5 0 0 0 7.6-31.8c-.1-24.7-7.8-43.7-23.3-57.3z" /></g></svg>; } // src/components/CircularGraphic.tsx import { createSignal } from "solid-js"; var DEFAULT_CDN_URLS = { country: "https://circle-flags.zeljko.me/flags/", language: "https://circle-flags.zeljko.me/flags/language/" }; var ENV_CDN_URL = import.meta.env.VITE_PUBLIC_CIRCLE_FLAGS_CDN_URL?.trim() || ""; function CircularGraphic(props) { const { code, type, cdn, label, width, height, alt, src, onError, ...restProps } = props; const [imgError, setImgError] = createSignal(false); const getCdnUrl = () => { const rawCdn = props.cdn?.trim() || ENV_CDN_URL || DEFAULT_CDN_URLS[props.type]; return rawCdn.replace(/\/+$/, "") + "/"; }; const getCleanCode = () => { return props.code.replace(/^\/+/, ""); }; const getSourceUrl = () => { return `${getCdnUrl()}${getCleanCode()}.svg`; }; const getAriaLabel = () => { return props.label || `${props.type} ${getCleanCode()} flag`; }; const handleError = () => { setImgError(true); }; return <>{!imgError() ? <img src={getSourceUrl()} width={props.width} height={props.height} alt={getAriaLabel()} onError={handleError} {...restProps} /> : <FallbackSvg width={props.width} height={props.height} />}</>; } // src/index.tsx function CircleFlag(props) { const { countryCode, width, height, cdn, label, ...imgProps } = props; const mappedCountryCode = countryToCountryMap[countryCode]; if (mappedCountryCode !== void 0) { return <CircularGraphic code={mappedCountryCode} type="country" width={width} height={height} cdn={cdn} label={label} {...imgProps} />; } else { return <CircularGraphic code={countryCode} type="country" width={width} height={height} cdn={cdn} label={label} {...imgProps} />; } } function CircleFlagLanguage(props) { const { languageCode, width, height, cdn, label, ...imgProps } = props; const mappedCountryCode = languageToCountryMap[languageCode]; if (mappedCountryCode !== void 0) { return <CircleFlag countryCode={mappedCountryCode} width={width} height={height} cdn={cdn} label={label} {...imgProps} />; } else { return <CircularGraphic code={languageCode} type="language" width={width} height={height} cdn={cdn} label={label} {...imgProps} />; } } export { CircleFlag, CircleFlagLanguage };