@damian-buho/support-ukraine 1.7.0 → 1.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ar.js +1 -1
- package/dist/ar.js.map +1 -1
- package/dist/de.js +1 -1
- package/dist/de.js.map +1 -1
- package/dist/en.js +1 -1
- package/dist/en.js.map +1 -1
- package/dist/es.js +1 -1
- package/dist/es.js.map +1 -1
- package/dist/fr.js +1 -1
- package/dist/fr.js.map +1 -1
- package/dist/hi.js +1 -1
- package/dist/hi.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/it.js +1 -1
- package/dist/it.js.map +1 -1
- package/dist/ja.js +1 -1
- package/dist/ja.js.map +1 -1
- package/dist/ko.js +1 -1
- package/dist/ko.js.map +1 -1
- package/dist/nl.js +1 -1
- package/dist/nl.js.map +1 -1
- package/dist/pl.js +1 -1
- package/dist/pl.js.map +1 -1
- package/dist/pt.js +1 -1
- package/dist/pt.js.map +1 -1
- package/dist/sv.js +1 -1
- package/dist/sv.js.map +1 -1
- package/dist/th.js +1 -1
- package/dist/th.js.map +1 -1
- package/dist/uk.js +1 -1
- package/dist/uk.js.map +1 -1
- package/dist/zh.js +1 -1
- package/dist/zh.js.map +1 -1
- package/package.json +5 -5
package/dist/en.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var D={supportUkraine:"Support Ukraine with",more:"more\u2026",donate:"Donate",refresh:"Show next charity",opensInNewTab:"(opens in a new tab)",charities:{united24:{tagline:"Official fundraising platform of Ukraine"},"come-back-alive":{tagline:"Supporting the Ukrainian Armed Forces since 2014"},"razom-for-ukraine":{tagline:"Emergency response and humanitarian aid"},"ukrainian-red-cross":{tagline:"Humanitarian assistance in conflict zones"},"nova-ukraine":{tagline:"Humanitarian aid and advocacy"},"voices-of-children":{tagline:"Psychological support for children affected by war"},"prytula-foundation":{tagline:"Defence technology and equipment for Ukraine"},"army-of-drones":{tagline:"Reconnaissance drones for the frontline"},"world-central-kitchen":{tagline:"Fresh meals for people in conflict zones"},"cats-of-kyiv":{tagline:"Cat shelter rescuing and rehoming cats in Kyiv"},uanimals:{tagline:"Animal rescue and advocacy organization in Ukraine"},hospitallers:{tagline:"Ukrainian voluntary paramedics providing first aid and evacuation"},"sternenko-fund":{tagline:"FPV drone supply for Ukrainian defence forces"},"life-robots-ukraine":{tagline:"Robots for demining Ukraine"},"sirius-shelter":{tagline:"Ukraine's largest animal shelter for dogs and cats"}}};var O=["military","humanitarian","animals"];function u(e,t){if(!e)throw new Error(t)}function x(e,t){u(typeof e=="string",`${t} must be a string`),u(e.length>0,`${t} must not be empty`)}function ne(e,t){x(e,t);try{new URL(e)}catch{throw new Error(`${t} must be a valid URL`)}}function ae(e){return u(O.includes(e),`Invalid tag: ${String(e)}. Must be one of: ${O.join(", ")}`),e}function j(e){u(e!==null&&typeof e=="object","Charity must be an object");let t=e;return x(t.id,"id"),x(t.name,"name"),x(t.tagline,"tagline"),ne(t.url,"url"),u(Array.isArray(t.tags),"tags must be an array"),u(t.tags.length>0,"tags must not be empty"),{id:t.id,name:t.name,tagline:t.tagline,url:t.url,tags:t.tags.map(a=>ae(a))}}var oe={parse:j},L={parse(e){return u(Array.isArray(e),"Charities must be an array"),e.map(t=>j(t))}};var P=[{id:"united24",name:"United24",tagline:"Official fundraising platform of Ukraine",url:"https://u24.gov.ua",tags:["humanitarian"]},{id:"come-back-alive",name:"Come Back Alive",tagline:"Supporting the Ukrainian Armed Forces since 2014",url:"https://www.comebackalive.in.ua",tags:["military"]},{id:"razom-for-ukraine",name:"Razom for Ukraine",tagline:"Emergency response and humanitarian aid",url:"https://www.razomforukraine.org",tags:["humanitarian"]},{id:"ukrainian-red-cross",name:"Ukrainian Red Cross",tagline:"Humanitarian assistance in conflict zones",url:"https://redcross.org.ua/en/",tags:["humanitarian"]},{id:"nova-ukraine",name:"Nova Ukraine",tagline:"Humanitarian aid and advocacy",url:"https://novaukraine.org",tags:["humanitarian"]},{id:"voices-of-children",name:"Voices of Children",tagline:"Psychological support for children affected by war",url:"https://voices.org.ua/en/",tags:["humanitarian"]},{id:"prytula-foundation",name:"Prytula Foundation",tagline:"Defence technology and equipment for Ukraine",url:"https://prytulafoundation.org/en",tags:["military"]},{id:"army-of-drones",name:"Army of Drones",tagline:"Reconnaissance drones for the frontline",url:"https://armyofdrones.com",tags:["military"]},{id:"world-central-kitchen",name:"World Central Kitchen",tagline:"Fresh meals for people in conflict zones",url:"https://wck.org/relief/activation-chefs-for-ukraine/",tags:["humanitarian"]},{id:"cats-of-kyiv",name:"Cats of Kyiv",tagline:"Cat shelter rescuing and rehoming cats in Kyiv",url:"https://cats.kiev.ua",tags:["animals"]},{id:"uanimals",name:"UAnimals",tagline:"Animal rescue and advocacy organization in Ukraine",url:"https://uanimals.org",tags:["animals"]},{id:"hospitallers",name:"Hospitallers",tagline:"Ukrainian voluntary paramedics providing first aid and evacuation",url:"https://www.hospitallers.org.uk",tags:["humanitarian"]},{id:"sternenko-fund",name:"Sternenko Fund",tagline:"FPV drone supply for Ukrainian defence forces",url:"https://www.sternenkofund.org",tags:["military"]},{id:"life-robots-ukraine",name:"Life Robots Ukraine",tagline:"Robots for demining Ukraine",url:"https://liferobots.com.ua",tags:["humanitarian"]},{id:"sirius-shelter",name:"Sirius",tagline:"Ukraine's largest animal shelter for dogs and cats",url:"https://dogcat.com.ua",tags:["animals"]},{id:"dignitas",name:"Dignitas",tagline:"Technology and support for Ukrainian defenders and veterans",url:"https://dignitas.fund",tags:["military"]},{id:"leleka",name:"Leleka Foundation",tagline:"Tactical medical supplies for Ukraine's frontline medics",url:"https://leleka.care/en",tags:["humanitarian"]},{id:"superhumans",name:"Superhumans Center",tagline:"Prosthetics, surgery, and rehabilitation for war survivors",url:"https://superhumans.com/en/",tags:["humanitarian"]}];var V=":host{display:block;margin:0;padding:0;border:none;font-size:16px;width:100%;min-height:2.5em;line-height:1.4;box-sizing:border-box;z-index:2147483647}.support-ukraine-block__visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}header.support-ukraine-block{margin:0;padding:0;border:none;border-radius:0;width:100%;min-height:2.5em;display:flex;align-items:center;justify-content:center;font-family:system-ui,-apple-system,sans-serif;text-decoration:none;box-sizing:border-box;line-height:1.4;overflow:visible;background:#0057b7 none}@media(prefers-color-scheme: dark){header.support-ukraine-block{background-color:gold}}header.support-ukraine-block--shift,header.support-ukraine-block--replace{position:relative}header.support-ukraine-block--overlap{position:fixed;top:0;left:0}header.support-ukraine-block--refreshing .support-ukraine-block__link{opacity:0}header.support-ukraine-block .support-ukraine-block__link{display:inline-flex;align-items:center;flex-wrap:wrap;gap:0 .25em;text-decoration:none;flex:1;height:100%;justify-content:flex-start;text-align:left;padding:.5em 1em;box-sizing:border-box;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}@media(prefers-reduced-motion: no-preference){header.support-ukraine-block .support-ukraine-block__link{transition:opacity .2s ease-in-out}}@media(prefers-color-scheme: dark){header.support-ukraine-block .support-ukraine-block__link{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}header.support-ukraine-block .support-ukraine-block__link:hover{opacity:.9}header.support-ukraine-block .support-ukraine-block__link:focus-visible{outline:2px solid #fff;outline-offset:-2px}header.support-ukraine-block .support-ukraine-block__flag{white-space:nowrap}header.support-ukraine-block .support-ukraine-block__prefix,header.support-ukraine-block .support-ukraine-block__info,header.support-ukraine-block .support-ukraine-block__colon,header.support-ukraine-block .support-ukraine-block__tagline{min-width:0}header.support-ukraine-block .support-ukraine-block__more{display:inline-flex;align-items:center;text-decoration:none;padding:.5em 1em;box-sizing:border-box;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4);white-space:nowrap;opacity:.8}@media(prefers-color-scheme: dark){header.support-ukraine-block .support-ukraine-block__more{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}header.support-ukraine-block .support-ukraine-block__more:hover{opacity:1}header.support-ukraine-block .support-ukraine-block__more:focus-visible{outline:2px solid #fff;outline-offset:-2px}header.support-ukraine-block .support-ukraine-block__more-ellipsis{display:none}header.support-ukraine-block .support-ukraine-block__refresh{display:inline-flex;align-items:center;background:none;border:none;text-decoration:none;padding:.5em .5em .5em 1em;box-sizing:border-box;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4);white-space:nowrap;opacity:.8;cursor:pointer;font-size:inherit;line-height:1}@media(prefers-color-scheme: dark){header.support-ukraine-block .support-ukraine-block__refresh{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}header.support-ukraine-block .support-ukraine-block__refresh:hover{opacity:1}header.support-ukraine-block .support-ukraine-block__refresh:focus-visible{outline:2px solid #fff;outline-offset:-2px}header.support-ukraine-block .support-ukraine-block__name{font-weight:bold}@media(max-width: 58rem){header.support-ukraine-block .support-ukraine-block__prefix,header.support-ukraine-block .support-ukraine-block__name,header.support-ukraine-block .support-ukraine-block__colon,header.support-ukraine-block .support-ukraine-block__more,header.support-ukraine-block .support-ukraine-block__refresh{display:none}}@media(max-width: 35rem){header.support-ukraine-block .support-ukraine-block__name,header.support-ukraine-block .support-ukraine-block__colon{display:initial}header.support-ukraine-block .support-ukraine-block__tagline{display:none}}[dir=rtl] header.support-ukraine-block .support-ukraine-block__link{text-align:right;justify-content:flex-end}[dir=rtl] header.support-ukraine-block .support-ukraine-block__more{text-align:right}[dir=rtl] header.support-ukraine-block .support-ukraine-block__refresh{text-align:right}:host-context([data-theme=dark]) header.support-ukraine-block{background-color:gold}:host-context([data-theme=dark]) header.support-ukraine-block .support-ukraine-block__link{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=dark]) header.support-ukraine-block .support-ukraine-block__more{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=dark]) header.support-ukraine-block .support-ukraine-block__refresh{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=light]) header.support-ukraine-block{background-color:#0057b7}:host-context([data-theme=light]) header.support-ukraine-block .support-ukraine-block__link{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}:host-context([data-theme=light]) header.support-ukraine-block .support-ukraine-block__more{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}:host-context([data-theme=light]) header.support-ukraine-block .support-ukraine-block__refresh{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}";var Y=L.parse(P),n="support-ukraine-block",J="support-ukraine-seen",ie="\u27F3",G=`${n}__visually-hidden`;function se(){try{let e=localStorage.getItem(J);return e?new Set(JSON.parse(e)):new Set}catch{return new Set}}function le(e){try{localStorage.setItem(J,JSON.stringify([...e]))}catch{}}function K(e){let t=se();e(t),le(t)}function W(e){if(e.length===0)throw new Error("randomItem: cannot pick from an empty array");return e[Math.floor(Math.random()*e.length)]}function q(e,t){let a=e;t&&K(p=>{let m=a.filter(h=>!p.has(h.url));m.length>0?a=m:p.clear()});let l=W(a);return t&&K(p=>{p.add(l.url)}),l}function pe(e){let t=`${n}-styles`;if(e.querySelector(`#${t}`))return;let a=e.ownerDocument.createElement("style");a.id=t,a.textContent=V,e.append(a)}function X(e,t){return e.map(a=>{let l=t.charities[a.id];return l?.tagline?{...a,tagline:l.tagline}:a})}function Q(e){return(e.split("-",1)[0]??"").toLowerCase()==="ar"}function ce(e,t){return`\u{1F1FA}\u{1F1E6} ${t.supportUkraine} ${e.name}: ${e.tagline}`}function Z(e,t,a={}){let{mode:l="shift",fontSize:p="87.5%",charities:m,tags:h,dontRepeat:A=!0,isInConsole:I=!0,showRefreshButton:ee=!1,autoRefreshInterval:N=0,showRefreshAnimation:te=!1}=a,_=X(m??Y,t),k=h&&h.length>0?_.filter(r=>r.tags.some(re=>h.includes(re))):_;k.length===0&&(k=_);let d=q(k,A),c=document.createElement("div"),R=c.attachShadow({mode:"open"});pe(R);let o=document.createElement("header");o.className=`${n} ${n}--${l}`,o.lang=e,Q(e)&&o.setAttribute("dir","rtl");let i=document.createElement("a");i.className=`${n}__link`,i.href=d.url,i.target="_blank",i.rel="noopener noreferrer",i.style.fontSize=p;let z=`${n}-link-new-tab`,f=document.createElement("span");f.id=z,f.className=G,f.textContent=t.opensInNewTab,i.setAttribute("aria-describedby",z);let w=document.createElement("span");w.className=`${n}__flag`,w.textContent="\u{1F1FA}\u{1F1E6} ";let C=document.createElement("span");C.className=`${n}__prefix`,C.textContent=`${t.supportUkraine} `;let v=document.createElement("span");v.className=`${n}__info`;let g=document.createElement("span");g.className=`${n}__name`,g.textContent=d.name;let S=document.createElement("span");S.className=`${n}__colon`,S.textContent=": ";let b=document.createElement("span");b.className=`${n}__tagline`,b.textContent=d.tagline,v.append(g,S,b),i.append(w,C,v),o.append(i);let s=document.createElement("a");s.className=`${n}__more`,s.href="https://damian-buho.github.io/support-ukraine/",s.target="_blank",s.rel="noopener noreferrer",s.style.fontSize=p;let F=`${n}-more-new-tab`,y=document.createElement("span");y.id=F,y.className=G,y.textContent=t.opensInNewTab,s.setAttribute("aria-describedby",F);let U=document.createElement("span");U.className=`${n}__more-text`,U.textContent=t.more;let E=document.createElement("span");E.className=`${n}__more-ellipsis`,E.textContent="\u2026",s.append(U,E),o.append(s),o.append(f,y);function B(r){i.href=r.url,g.textContent=r.name,b.textContent=r.tagline,I&&console.info("[support-ukraine] banner",`${r.name}: ${r.tagline}`,r.url)}function H(){let r=q(k,A);te?(o.classList.add(`${n}--refreshing`),setTimeout(()=>{B(r),o.classList.remove(`${n}--refreshing`)},200)):B(r)}if(ee){let r=document.createElement("button");r.className=`${n}__refresh`,r.type="button",r.textContent=ie,r.style.fontSize=p,r.setAttribute("aria-label",t.refresh),r.addEventListener("click",H),o.insertBefore(r,s)}R.append(o);let T=a.element??document.body;if(l==="replace"){let r=T.querySelector(`.${n}`);r?r.replaceWith(c):T.prepend(c)}else T.prepend(c);I&&console.info("[support-ukraine] banner",`${d.name}: ${d.tagline}`,d.url),c.dataset.supportUkraine="",c.classList.add(`${n}--processed`);let $;N>0&&($=setInterval(H,N));let M=c;return M.destroy=()=>{$!==void 0&&clearInterval($),c.remove()},M}var ue="en";function Ce(e={}){return Promise.resolve(Z(ue,D,e))}export{Y as DEFAULT_CHARITIES,L as charitiesSchema,oe as charitySchema,ce as formatBannerText,Q as isRTL,X as mergeCharities,W as randomItem,Ce as supportUkraineBlock};
|
|
1
|
+
var D={supportUkraine:"Support Ukraine with",more:"more\u2026",donate:"Donate",refresh:"Show next charity",opensInNewTab:"(opens in a new tab)",charities:{united24:{tagline:"Official fundraising platform of Ukraine"},"come-back-alive":{tagline:"Supporting the Ukrainian Armed Forces since 2014"},"razom-for-ukraine":{tagline:"Emergency response and humanitarian aid"},"ukrainian-red-cross":{tagline:"Humanitarian assistance in conflict zones"},"nova-ukraine":{tagline:"Humanitarian aid and advocacy"},"voices-of-children":{tagline:"Psychological support for children affected by war"},"prytula-foundation":{tagline:"Defence technology and equipment for Ukraine"},"army-of-drones":{tagline:"Reconnaissance drones for the frontline"},"world-central-kitchen":{tagline:"Fresh meals for people in conflict zones"},"cats-of-kyiv":{tagline:"Cat shelter rescuing and rehoming cats in Kyiv"},uanimals:{tagline:"Animal rescue and advocacy organization in Ukraine"},hospitallers:{tagline:"Ukrainian voluntary paramedics providing first aid and evacuation"},"sternenko-fund":{tagline:"FPV drone supply for Ukrainian defence forces"},"life-robots-ukraine":{tagline:"Robots for demining Ukraine"},"sirius-shelter":{tagline:"Ukraine's largest animal shelter for dogs and cats"}}};var O=["military","humanitarian","animals"];function u(e,t){if(!e)throw new Error(t)}function x(e,t){u(typeof e=="string",`${t} must be a string`),u(e.length>0,`${t} must not be empty`)}function ne(e,t){x(e,t);try{new URL(e)}catch{throw new Error(`${t} must be a valid URL`)}}function ae(e){return u(O.includes(e),`Invalid tag: ${String(e)}. Must be one of: ${O.join(", ")}`),e}function j(e){u(e!==null&&typeof e=="object","Charity must be an object");let t=e;return x(t.id,"id"),x(t.name,"name"),x(t.tagline,"tagline"),ne(t.url,"url"),u(Array.isArray(t.tags),"tags must be an array"),u(t.tags.length>0,"tags must not be empty"),{id:t.id,name:t.name,tagline:t.tagline,url:t.url,tags:t.tags.map(a=>ae(a))}}var oe={parse:j},L={parse(e){return u(Array.isArray(e),"Charities must be an array"),e.map(t=>j(t))}};var P=[{id:"united24",name:"United24",tagline:"Official fundraising platform of Ukraine",url:"https://u24.gov.ua",tags:["humanitarian"]},{id:"come-back-alive",name:"Come Back Alive",tagline:"Supporting the Ukrainian Armed Forces since 2014",url:"https://www.comebackalive.in.ua",tags:["military"]},{id:"razom-for-ukraine",name:"Razom for Ukraine",tagline:"Emergency response and humanitarian aid",url:"https://www.razomforukraine.org",tags:["humanitarian"]},{id:"ukrainian-red-cross",name:"Ukrainian Red Cross",tagline:"Humanitarian assistance in conflict zones",url:"https://redcross.org.ua/en/",tags:["humanitarian"]},{id:"nova-ukraine",name:"Nova Ukraine",tagline:"Humanitarian aid and advocacy",url:"https://novaukraine.org",tags:["humanitarian"]},{id:"voices-of-children",name:"Voices of Children",tagline:"Psychological support for children affected by war",url:"https://voices.org.ua/en/",tags:["humanitarian"]},{id:"prytula-foundation",name:"Prytula Foundation",tagline:"Defence technology and equipment for Ukraine",url:"https://prytulafoundation.org/en",tags:["military"]},{id:"army-of-drones",name:"Army of Drones",tagline:"Reconnaissance drones for the frontline",url:"https://armyofdrones.com",tags:["military"]},{id:"world-central-kitchen",name:"World Central Kitchen",tagline:"Fresh meals for people in conflict zones",url:"https://wck.org/relief/activation-chefs-for-ukraine/",tags:["humanitarian"]},{id:"cats-of-kyiv",name:"Cats of Kyiv",tagline:"Cat shelter rescuing and rehoming cats in Kyiv",url:"https://cats.kiev.ua",tags:["animals"]},{id:"uanimals",name:"UAnimals",tagline:"Animal rescue and advocacy organization in Ukraine",url:"https://uanimals.org",tags:["animals"]},{id:"hospitallers",name:"Hospitallers",tagline:"Ukrainian voluntary paramedics providing first aid and evacuation",url:"https://www.hospitallers.org.uk",tags:["humanitarian"]},{id:"sternenko-fund",name:"Sternenko Fund",tagline:"FPV drone supply for Ukrainian defence forces",url:"https://www.sternenkofund.org",tags:["military"]},{id:"life-robots-ukraine",name:"Life Robots Ukraine",tagline:"Robots for demining Ukraine",url:"https://liferobots.com.ua",tags:["humanitarian"]},{id:"sirius-shelter",name:"Sirius",tagline:"Ukraine's largest animal shelter for dogs and cats",url:"https://dogcat.com.ua",tags:["animals"]},{id:"dignitas",name:"Dignitas",tagline:"Technology and support for Ukrainian defenders and veterans",url:"https://dignitas.fund",tags:["military"]},{id:"leleka",name:"Leleka Foundation",tagline:"Tactical medical supplies for Ukraine's frontline medics",url:"https://leleka.care/en",tags:["humanitarian"]},{id:"superhumans",name:"Superhumans Center",tagline:"Prosthetics, surgery, and rehabilitation for war survivors",url:"https://superhumans.com/en/",tags:["humanitarian"]}];var V=":host{display:block;margin:0;padding:0;border:none;font-size:16px;width:100%;min-height:2.5em;line-height:1.4;box-sizing:border-box;z-index:2147483647}.support-ukraine-block__visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}header.support-ukraine-block{margin:0;padding:0;border:none;border-radius:0;width:100%;min-height:2.5em;display:flex;align-items:center;justify-content:center;font-family:system-ui,-apple-system,sans-serif;text-decoration:none;box-sizing:border-box;line-height:1.4;overflow:visible;background:#0057b7 none}@media(prefers-color-scheme: dark){header.support-ukraine-block{background-color:gold}}header.support-ukraine-block--shift,header.support-ukraine-block--replace{position:relative}header.support-ukraine-block--overlap{position:fixed;top:0;left:0;z-index:2147483647}header.support-ukraine-block--refreshing .support-ukraine-block__link{opacity:0}header.support-ukraine-block .support-ukraine-block__link{display:inline-flex;align-items:center;flex-wrap:wrap;gap:0 .25em;text-decoration:none;flex:1;height:100%;justify-content:flex-start;text-align:left;padding:.5em 1em;box-sizing:border-box;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}@media(prefers-reduced-motion: no-preference){header.support-ukraine-block .support-ukraine-block__link{transition:opacity .2s ease-in-out}}@media(prefers-color-scheme: dark){header.support-ukraine-block .support-ukraine-block__link{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}header.support-ukraine-block .support-ukraine-block__link:hover{opacity:.9}header.support-ukraine-block .support-ukraine-block__link:focus-visible{outline:2px solid #fff;outline-offset:-2px}header.support-ukraine-block .support-ukraine-block__flag{white-space:nowrap}header.support-ukraine-block .support-ukraine-block__prefix,header.support-ukraine-block .support-ukraine-block__info,header.support-ukraine-block .support-ukraine-block__colon,header.support-ukraine-block .support-ukraine-block__tagline{min-width:0}header.support-ukraine-block .support-ukraine-block__more{display:inline-flex;align-items:center;text-decoration:none;padding:.5em 1em;box-sizing:border-box;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4);white-space:nowrap;opacity:.8}@media(prefers-color-scheme: dark){header.support-ukraine-block .support-ukraine-block__more{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}header.support-ukraine-block .support-ukraine-block__more:hover{opacity:1}header.support-ukraine-block .support-ukraine-block__more:focus-visible{outline:2px solid #fff;outline-offset:-2px}header.support-ukraine-block .support-ukraine-block__more-ellipsis{display:none}header.support-ukraine-block .support-ukraine-block__refresh{display:inline-flex;align-items:center;background:none;border:none;text-decoration:none;padding:.5em .5em .5em 1em;box-sizing:border-box;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4);white-space:nowrap;opacity:.8;cursor:pointer;font-size:inherit;line-height:1}@media(prefers-color-scheme: dark){header.support-ukraine-block .support-ukraine-block__refresh{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}header.support-ukraine-block .support-ukraine-block__refresh:hover{opacity:1}header.support-ukraine-block .support-ukraine-block__refresh:focus-visible{outline:2px solid #fff;outline-offset:-2px}header.support-ukraine-block .support-ukraine-block__name{font-weight:bold}@media(max-width: 58rem){header.support-ukraine-block .support-ukraine-block__prefix,header.support-ukraine-block .support-ukraine-block__name,header.support-ukraine-block .support-ukraine-block__colon,header.support-ukraine-block .support-ukraine-block__more,header.support-ukraine-block .support-ukraine-block__refresh{display:none}}@media(max-width: 35rem){header.support-ukraine-block .support-ukraine-block__name,header.support-ukraine-block .support-ukraine-block__colon{display:initial}header.support-ukraine-block .support-ukraine-block__tagline{display:none}}[dir=rtl] header.support-ukraine-block .support-ukraine-block__link{text-align:right;justify-content:flex-end}[dir=rtl] header.support-ukraine-block .support-ukraine-block__more{text-align:right}[dir=rtl] header.support-ukraine-block .support-ukraine-block__refresh{text-align:right}:host-context([data-theme=dark]) header.support-ukraine-block{background-color:gold}:host-context([data-theme=dark]) header.support-ukraine-block .support-ukraine-block__link{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=dark]) header.support-ukraine-block .support-ukraine-block__more{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=dark]) header.support-ukraine-block .support-ukraine-block__refresh{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=light]) header.support-ukraine-block{background-color:#0057b7}:host-context([data-theme=light]) header.support-ukraine-block .support-ukraine-block__link{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}:host-context([data-theme=light]) header.support-ukraine-block .support-ukraine-block__more{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}:host-context([data-theme=light]) header.support-ukraine-block .support-ukraine-block__refresh{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}";var Y=L.parse(P),n="support-ukraine-block",J="support-ukraine-seen",ie="\u27F3",G=`${n}__visually-hidden`;function se(){try{let e=localStorage.getItem(J);return e?new Set(JSON.parse(e)):new Set}catch{return new Set}}function le(e){try{localStorage.setItem(J,JSON.stringify([...e]))}catch{}}function K(e){let t=se();e(t),le(t)}function W(e){if(e.length===0)throw new Error("randomItem: cannot pick from an empty array");return e[Math.floor(Math.random()*e.length)]}function q(e,t){let a=e;t&&K(p=>{let m=a.filter(h=>!p.has(h.url));m.length>0?a=m:p.clear()});let l=W(a);return t&&K(p=>{p.add(l.url)}),l}function pe(e){let t=`${n}-styles`;if(e.querySelector(`#${t}`))return;let a=e.ownerDocument.createElement("style");a.id=t,a.textContent=V,e.append(a)}function X(e,t){return e.map(a=>{let l=t.charities[a.id];return l?.tagline?{...a,tagline:l.tagline}:a})}function Q(e){return(e.split("-",1)[0]??"").toLowerCase()==="ar"}function ce(e,t){return`\u{1F1FA}\u{1F1E6} ${t.supportUkraine} ${e.name}: ${e.tagline}`}function Z(e,t,a={}){let{mode:l="shift",fontSize:p="87.5%",charities:m,tags:h,dontRepeat:A=!0,isInConsole:I=!0,showRefreshButton:ee=!1,autoRefreshInterval:N=0,showRefreshAnimation:te=!1}=a,_=X(m??Y,t),k=h&&h.length>0?_.filter(r=>r.tags.some(re=>h.includes(re))):_;k.length===0&&(k=_);let d=q(k,A),c=document.createElement("div"),R=c.attachShadow({mode:"open"});pe(R);let o=document.createElement("header");o.className=`${n} ${n}--${l}`,o.lang=e,Q(e)&&o.setAttribute("dir","rtl");let i=document.createElement("a");i.className=`${n}__link`,i.href=d.url,i.target="_blank",i.rel="noopener noreferrer",i.style.fontSize=p;let z=`${n}-link-new-tab`,f=document.createElement("span");f.id=z,f.className=G,f.textContent=t.opensInNewTab,i.setAttribute("aria-describedby",z);let w=document.createElement("span");w.className=`${n}__flag`,w.textContent="\u{1F1FA}\u{1F1E6} ";let C=document.createElement("span");C.className=`${n}__prefix`,C.textContent=`${t.supportUkraine} `;let v=document.createElement("span");v.className=`${n}__info`;let g=document.createElement("span");g.className=`${n}__name`,g.textContent=d.name;let S=document.createElement("span");S.className=`${n}__colon`,S.textContent=": ";let b=document.createElement("span");b.className=`${n}__tagline`,b.textContent=d.tagline,v.append(g,S,b),i.append(w,C,v),o.append(i);let s=document.createElement("a");s.className=`${n}__more`,s.href="https://damian-buho.github.io/support-ukraine/",s.target="_blank",s.rel="noopener noreferrer",s.style.fontSize=p;let F=`${n}-more-new-tab`,y=document.createElement("span");y.id=F,y.className=G,y.textContent=t.opensInNewTab,s.setAttribute("aria-describedby",F);let U=document.createElement("span");U.className=`${n}__more-text`,U.textContent=t.more;let E=document.createElement("span");E.className=`${n}__more-ellipsis`,E.textContent="\u2026",s.append(U,E),o.append(s),o.append(f,y);function B(r){i.href=r.url,g.textContent=r.name,b.textContent=r.tagline,I&&console.info("[support-ukraine] banner",`${r.name}: ${r.tagline}`,r.url)}function H(){let r=q(k,A);te?(o.classList.add(`${n}--refreshing`),setTimeout(()=>{B(r),o.classList.remove(`${n}--refreshing`)},200)):B(r)}if(ee){let r=document.createElement("button");r.className=`${n}__refresh`,r.type="button",r.textContent=ie,r.style.fontSize=p,r.setAttribute("aria-label",t.refresh),r.addEventListener("click",H),o.insertBefore(r,s)}R.append(o);let T=a.element??document.body;if(l==="replace"){let r=T.querySelector(`.${n}`);r?r.replaceWith(c):T.prepend(c)}else T.prepend(c);I&&console.info("[support-ukraine] banner",`${d.name}: ${d.tagline}`,d.url),c.dataset.supportUkraine="",c.classList.add(`${n}--processed`);let $;N>0&&($=setInterval(H,N));let M=c;return M.destroy=()=>{$!==void 0&&clearInterval($),c.remove()},M}var ue="en";function Ce(e={}){return Promise.resolve(Z(ue,D,e))}export{Y as DEFAULT_CHARITIES,L as charitiesSchema,oe as charitySchema,ce as formatBannerText,Q as isRTL,X as mergeCharities,W as randomItem,Ce as supportUkraineBlock};
|
|
2
2
|
//# sourceMappingURL=en.js.map
|
package/dist/en.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/locales/en.yaml","../src/types.ts","../src/charities.yaml","../src/styles.scss","../src/banner.ts","../src/entries/en.ts"],"sourcesContent":["export default {\"supportUkraine\":\"Support Ukraine with\",\"more\":\"more…\",\"donate\":\"Donate\",\"refresh\":\"Show next charity\",\"opensInNewTab\":\"(opens in a new tab)\",\"charities\":{\"united24\":{\"tagline\":\"Official fundraising platform of Ukraine\"},\"come-back-alive\":{\"tagline\":\"Supporting the Ukrainian Armed Forces since 2014\"},\"razom-for-ukraine\":{\"tagline\":\"Emergency response and humanitarian aid\"},\"ukrainian-red-cross\":{\"tagline\":\"Humanitarian assistance in conflict zones\"},\"nova-ukraine\":{\"tagline\":\"Humanitarian aid and advocacy\"},\"voices-of-children\":{\"tagline\":\"Psychological support for children affected by war\"},\"prytula-foundation\":{\"tagline\":\"Defence technology and equipment for Ukraine\"},\"army-of-drones\":{\"tagline\":\"Reconnaissance drones for the frontline\"},\"world-central-kitchen\":{\"tagline\":\"Fresh meals for people in conflict zones\"},\"cats-of-kyiv\":{\"tagline\":\"Cat shelter rescuing and rehoming cats in Kyiv\"},\"uanimals\":{\"tagline\":\"Animal rescue and advocacy organization in Ukraine\"},\"hospitallers\":{\"tagline\":\"Ukrainian voluntary paramedics providing first aid and evacuation\"},\"sternenko-fund\":{\"tagline\":\"FPV drone supply for Ukrainian defence forces\"},\"life-robots-ukraine\":{\"tagline\":\"Robots for demining Ukraine\"},\"sirius-shelter\":{\"tagline\":\"Ukraine's largest animal shelter for dogs and cats\"}}}","// SPDX-FileCopyrightText: 2026 Damián Búho <damian.buho@proton.me>\n//\n// SPDX-License-Identifier: MIT\n\n/**\nCategory tag for a charity.\n*/\nexport const VALID_TAGS = ['military', 'humanitarian', 'animals'] as const\nexport type CharityTag = (typeof VALID_TAGS)[number]\n\nfunction assert(condition: unknown, message: string): asserts condition {\n if (!condition) throw new Error(message)\n}\n\nfunction assertNonEmptyString(value: unknown, field: string): void {\n assert(typeof value === 'string', `${field} must be a string`)\n assert(value.length > 0, `${field} must not be empty`)\n}\n\nfunction assertUrl(value: unknown, field: string): void {\n assertNonEmptyString(value, field)\n try {\n new URL(value)\n } catch {\n throw new Error(`${field} must be a valid URL`)\n }\n}\n\nfunction parseCharityTag(value: unknown): CharityTag {\n assert(\n VALID_TAGS.includes(value as CharityTag),\n `Invalid tag: ${String(value)}. Must be one of: ${VALID_TAGS.join(', ')}`\n )\n return value as CharityTag\n}\n\n/**\nA charity foundation that can appear in the banner.\n*/\nexport interface Charity {\n id: string\n name: string\n tagline: string\n url: string\n tags: CharityTag[]\n}\n\nfunction parseCharity(value: unknown): Charity {\n assert(value !== null && typeof value === 'object', 'Charity must be an object')\n const record = value as Record<string, unknown>\n assertNonEmptyString(record.id, 'id')\n assertNonEmptyString(record.name, 'name')\n assertNonEmptyString(record.tagline, 'tagline')\n assertUrl(record.url, 'url')\n assert(Array.isArray(record.tags), 'tags must be an array')\n assert(record.tags.length > 0, 'tags must not be empty')\n return {\n id: record.id,\n name: record.name,\n tagline: record.tagline,\n url: record.url,\n tags: record.tags.map(tag => parseCharityTag(tag))\n }\n}\n\nexport const charitySchema = {\n parse: parseCharity\n}\n\nexport const charitiesSchema = {\n parse(value: unknown): Charity[] {\n assert(Array.isArray(value), 'Charities must be an array')\n return value.map(item => parseCharity(item))\n }\n}\n\n/**\nTranslated UI strings and charity taglines for a single locale.\n*/\nexport interface LocaleMessages {\n /**\n Banner prefix, e.g. \"Support Ukraine\".\n */\n supportUkraine: string\n /**\n \"More…\" link text.\n */\n more: string\n /**\n Card donate button text, e.g. \"Donate\".\n */\n donate: string\n /**\n Refresh button aria-label, e.g. \"Show next charity\".\n */\n refresh: string\n /**\n Text appended to external links for screen readers, e.g. \"(opens in a new tab)\".\n */\n opensInNewTab: string\n /**\n Translated taglines keyed by charity id. Missing keys fall back to EN.\n */\n charities: Record<string, { tagline: string }>\n}\n\nexport interface SupportUkraineBlockOptions {\n /**\n Target mount element. If omitted the banner is prepended to document.body.\n */\n element?: HTMLElement\n /**\n Positioning mode: 'shift' pushes content down, 'overlap' floats on top, 'replace' swaps a same-class placeholder.\n */\n mode?: 'shift' | 'overlap' | 'replace'\n /**\n Font size (default '87.5%'). Percentages resolve against the widget's fixed 16px host box, so document root scaling is ignored; rem would inherit it.\n */\n fontSize?: string\n /**\n * Custom charity list. If omitted the built-in defaults are used.\n */\n charities?: Charity[]\n /**\n * Category tags to filter by. If omitted all charities are shown.\n */\n tags?: CharityTag[]\n /**\n Avoid repeating charities across page loads using localStorage.\n */\n dontRepeat?: boolean\n /**\n Log a message to the dev console.\n */\n isInConsole?: boolean\n /**\n Show a refresh button that loads the next random charity.\n */\n showRefreshButton?: boolean\n /**\n Auto-refresh interval in milliseconds. 0 = off (default). Set e.g. 15000 for 15 seconds.\n */\n autoRefreshInterval?: number\n /**\n Show a fade animation when the charity changes (respects prefers-reduced-motion).\n */\n showRefreshAnimation?: boolean\n /**\n * Override the auto-detected locale (BCP 47 language tag).\n * If omitted the locale is detected from `navigator.language`.\n */\n locale?: string\n}\n","export default [{\"id\":\"united24\",\"name\":\"United24\",\"tagline\":\"Official fundraising platform of Ukraine\",\"url\":\"https://u24.gov.ua\",\"tags\":[\"humanitarian\"]},{\"id\":\"come-back-alive\",\"name\":\"Come Back Alive\",\"tagline\":\"Supporting the Ukrainian Armed Forces since 2014\",\"url\":\"https://www.comebackalive.in.ua\",\"tags\":[\"military\"]},{\"id\":\"razom-for-ukraine\",\"name\":\"Razom for Ukraine\",\"tagline\":\"Emergency response and humanitarian aid\",\"url\":\"https://www.razomforukraine.org\",\"tags\":[\"humanitarian\"]},{\"id\":\"ukrainian-red-cross\",\"name\":\"Ukrainian Red Cross\",\"tagline\":\"Humanitarian assistance in conflict zones\",\"url\":\"https://redcross.org.ua/en/\",\"tags\":[\"humanitarian\"]},{\"id\":\"nova-ukraine\",\"name\":\"Nova Ukraine\",\"tagline\":\"Humanitarian aid and advocacy\",\"url\":\"https://novaukraine.org\",\"tags\":[\"humanitarian\"]},{\"id\":\"voices-of-children\",\"name\":\"Voices of Children\",\"tagline\":\"Psychological support for children affected by war\",\"url\":\"https://voices.org.ua/en/\",\"tags\":[\"humanitarian\"]},{\"id\":\"prytula-foundation\",\"name\":\"Prytula Foundation\",\"tagline\":\"Defence technology and equipment for Ukraine\",\"url\":\"https://prytulafoundation.org/en\",\"tags\":[\"military\"]},{\"id\":\"army-of-drones\",\"name\":\"Army of Drones\",\"tagline\":\"Reconnaissance drones for the frontline\",\"url\":\"https://armyofdrones.com\",\"tags\":[\"military\"]},{\"id\":\"world-central-kitchen\",\"name\":\"World Central Kitchen\",\"tagline\":\"Fresh meals for people in conflict zones\",\"url\":\"https://wck.org/relief/activation-chefs-for-ukraine/\",\"tags\":[\"humanitarian\"]},{\"id\":\"cats-of-kyiv\",\"name\":\"Cats of Kyiv\",\"tagline\":\"Cat shelter rescuing and rehoming cats in Kyiv\",\"url\":\"https://cats.kiev.ua\",\"tags\":[\"animals\"]},{\"id\":\"uanimals\",\"name\":\"UAnimals\",\"tagline\":\"Animal rescue and advocacy organization in Ukraine\",\"url\":\"https://uanimals.org\",\"tags\":[\"animals\"]},{\"id\":\"hospitallers\",\"name\":\"Hospitallers\",\"tagline\":\"Ukrainian voluntary paramedics providing first aid and evacuation\",\"url\":\"https://www.hospitallers.org.uk\",\"tags\":[\"humanitarian\"]},{\"id\":\"sternenko-fund\",\"name\":\"Sternenko Fund\",\"tagline\":\"FPV drone supply for Ukrainian defence forces\",\"url\":\"https://www.sternenkofund.org\",\"tags\":[\"military\"]},{\"id\":\"life-robots-ukraine\",\"name\":\"Life Robots Ukraine\",\"tagline\":\"Robots for demining Ukraine\",\"url\":\"https://liferobots.com.ua\",\"tags\":[\"humanitarian\"]},{\"id\":\"sirius-shelter\",\"name\":\"Sirius\",\"tagline\":\"Ukraine's largest animal shelter for dogs and cats\",\"url\":\"https://dogcat.com.ua\",\"tags\":[\"animals\"]},{\"id\":\"dignitas\",\"name\":\"Dignitas\",\"tagline\":\"Technology and support for Ukrainian defenders and veterans\",\"url\":\"https://dignitas.fund\",\"tags\":[\"military\"]},{\"id\":\"leleka\",\"name\":\"Leleka Foundation\",\"tagline\":\"Tactical medical supplies for Ukraine's frontline medics\",\"url\":\"https://leleka.care/en\",\"tags\":[\"humanitarian\"]},{\"id\":\"superhumans\",\"name\":\"Superhumans Center\",\"tagline\":\"Prosthetics, surgery, and rehabilitation for war survivors\",\"url\":\"https://superhumans.com/en/\",\"tags\":[\"humanitarian\"]}]","export default \":host{display:block;margin:0;padding:0;border:none;font-size:16px;width:100%;min-height:2.5em;line-height:1.4;box-sizing:border-box;z-index:2147483647}.support-ukraine-block__visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}header.support-ukraine-block{margin:0;padding:0;border:none;border-radius:0;width:100%;min-height:2.5em;display:flex;align-items:center;justify-content:center;font-family:system-ui,-apple-system,sans-serif;text-decoration:none;box-sizing:border-box;line-height:1.4;overflow:visible;background:#0057b7 none}@media(prefers-color-scheme: dark){header.support-ukraine-block{background-color:gold}}header.support-ukraine-block--shift,header.support-ukraine-block--replace{position:relative}header.support-ukraine-block--overlap{position:fixed;top:0;left:0}header.support-ukraine-block--refreshing .support-ukraine-block__link{opacity:0}header.support-ukraine-block .support-ukraine-block__link{display:inline-flex;align-items:center;flex-wrap:wrap;gap:0 .25em;text-decoration:none;flex:1;height:100%;justify-content:flex-start;text-align:left;padding:.5em 1em;box-sizing:border-box;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}@media(prefers-reduced-motion: no-preference){header.support-ukraine-block .support-ukraine-block__link{transition:opacity .2s ease-in-out}}@media(prefers-color-scheme: dark){header.support-ukraine-block .support-ukraine-block__link{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}header.support-ukraine-block .support-ukraine-block__link:hover{opacity:.9}header.support-ukraine-block .support-ukraine-block__link:focus-visible{outline:2px solid #fff;outline-offset:-2px}header.support-ukraine-block .support-ukraine-block__flag{white-space:nowrap}header.support-ukraine-block .support-ukraine-block__prefix,header.support-ukraine-block .support-ukraine-block__info,header.support-ukraine-block .support-ukraine-block__colon,header.support-ukraine-block .support-ukraine-block__tagline{min-width:0}header.support-ukraine-block .support-ukraine-block__more{display:inline-flex;align-items:center;text-decoration:none;padding:.5em 1em;box-sizing:border-box;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4);white-space:nowrap;opacity:.8}@media(prefers-color-scheme: dark){header.support-ukraine-block .support-ukraine-block__more{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}header.support-ukraine-block .support-ukraine-block__more:hover{opacity:1}header.support-ukraine-block .support-ukraine-block__more:focus-visible{outline:2px solid #fff;outline-offset:-2px}header.support-ukraine-block .support-ukraine-block__more-ellipsis{display:none}header.support-ukraine-block .support-ukraine-block__refresh{display:inline-flex;align-items:center;background:none;border:none;text-decoration:none;padding:.5em .5em .5em 1em;box-sizing:border-box;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4);white-space:nowrap;opacity:.8;cursor:pointer;font-size:inherit;line-height:1}@media(prefers-color-scheme: dark){header.support-ukraine-block .support-ukraine-block__refresh{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}header.support-ukraine-block .support-ukraine-block__refresh:hover{opacity:1}header.support-ukraine-block .support-ukraine-block__refresh:focus-visible{outline:2px solid #fff;outline-offset:-2px}header.support-ukraine-block .support-ukraine-block__name{font-weight:bold}@media(max-width: 58rem){header.support-ukraine-block .support-ukraine-block__prefix,header.support-ukraine-block .support-ukraine-block__name,header.support-ukraine-block .support-ukraine-block__colon,header.support-ukraine-block .support-ukraine-block__more,header.support-ukraine-block .support-ukraine-block__refresh{display:none}}@media(max-width: 35rem){header.support-ukraine-block .support-ukraine-block__name,header.support-ukraine-block .support-ukraine-block__colon{display:initial}header.support-ukraine-block .support-ukraine-block__tagline{display:none}}[dir=rtl] header.support-ukraine-block .support-ukraine-block__link{text-align:right;justify-content:flex-end}[dir=rtl] header.support-ukraine-block .support-ukraine-block__more{text-align:right}[dir=rtl] header.support-ukraine-block .support-ukraine-block__refresh{text-align:right}:host-context([data-theme=dark]) header.support-ukraine-block{background-color:gold}:host-context([data-theme=dark]) header.support-ukraine-block .support-ukraine-block__link{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=dark]) header.support-ukraine-block .support-ukraine-block__more{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=dark]) header.support-ukraine-block .support-ukraine-block__refresh{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=light]) header.support-ukraine-block{background-color:#0057b7}:host-context([data-theme=light]) header.support-ukraine-block .support-ukraine-block__link{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}:host-context([data-theme=light]) header.support-ukraine-block .support-ukraine-block__more{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}:host-context([data-theme=light]) header.support-ukraine-block .support-ukraine-block__refresh{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}\"","// SPDX-FileCopyrightText: 2026 Damián Búho <damian.buho@proton.me>\n//\n// SPDX-License-Identifier: MIT\n\nimport {\n charitiesSchema,\n type Charity,\n type LocaleMessages,\n type SupportUkraineBlockOptions\n} from './types.js'\nimport rawCharities from './charities.yaml'\nimport styles from './styles.scss'\n\nexport type { Charity, CharityTag, SupportUkraineBlockOptions, LocaleMessages } from './types.js'\n\nexport const DEFAULT_CHARITIES: Charity[] = charitiesSchema.parse(rawCharities)\n\nconst CSS_PREFIX = 'support-ukraine-block'\nconst STORAGE_KEY = 'support-ukraine-seen'\nconst REFRESH_GLYPH = '\\u{27F3}'\nconst VISUALLY_HIDDEN_CLASS = `${CSS_PREFIX}__visually-hidden`\n\nfunction readSeen(): Set<string> {\n try {\n const raw = localStorage.getItem(STORAGE_KEY)\n return raw ? new Set(JSON.parse(raw) as string[]) : new Set()\n } catch {\n return new Set()\n }\n}\n\nfunction writeSeen(seen: Set<string>): void {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify([...seen]))\n } catch {\n // localStorage unavailable — degrade silently\n }\n}\n\nfunction updateSeen(mutate: (seen: Set<string>) => void): void {\n const seen = readSeen()\n mutate(seen)\n writeSeen(seen)\n}\n\n/**\n * Pick a random item from an array.\n *\n * @internal\n */\nexport function randomItem<T>(items: T[]): T {\n if (items.length === 0) {\n throw new Error('randomItem: cannot pick from an empty array')\n }\n return items[Math.floor(Math.random() * items.length)]!\n}\n\nfunction pickCharity(candidates: Charity[], shouldAvoidRepeat: boolean): Charity {\n let pool = candidates\n\n if (shouldAvoidRepeat) {\n updateSeen(seen => {\n const unseen = pool.filter(c => !seen.has(c.url))\n if (unseen.length > 0) {\n pool = unseen\n } else {\n seen.clear()\n }\n })\n }\n\n const charity = randomItem(pool)\n\n if (shouldAvoidRepeat) {\n updateSeen(seen => {\n seen.add(charity.url)\n })\n }\n\n return charity\n}\n\nfunction injectShadowStyles(shadowRoot: ShadowRoot): void {\n const id = `${CSS_PREFIX}-styles`\n if (shadowRoot.querySelector(`#${id}`)) {\n return\n }\n\n const style = shadowRoot.ownerDocument.createElement('style')\n style.id = id\n style.textContent = styles\n shadowRoot.append(style)\n}\n\n/**\n * Merge base charities with locale-specific translations.\n */\nexport function mergeCharities(base: readonly Charity[], locale: LocaleMessages): Charity[] {\n return base.map(charity => {\n const translated = locale.charities[charity.id]\n if (translated?.tagline) {\n return { ...charity, tagline: translated.tagline }\n }\n return charity\n })\n}\n\nexport function isRTL(lang: string): boolean {\n const base = (lang.split('-', 1)[0] ?? '').toLowerCase()\n return base === 'ar'\n}\n\nexport function formatBannerText(charity: Charity, messages: LocaleMessages): string {\n return `\\u{1F1FA}\\u{1F1E6} ${messages.supportUkraine} ${charity.name}: ${charity.tagline}`\n}\n\n/**\n * Mount the banner with already-resolved `lang` and `messages`.\n * Shared by the auto-detect build (`src/index.ts`) and the per-locale builds (`src/entries/*.ts`).\n */\nexport function mountBanner(\n lang: string,\n messages: LocaleMessages,\n options: SupportUkraineBlockOptions = {}\n): HTMLElement & { destroy: () => void } {\n const {\n mode = 'shift',\n fontSize = '87.5%',\n charities,\n tags,\n dontRepeat = true,\n isInConsole = true,\n showRefreshButton = false,\n autoRefreshInterval = 0,\n showRefreshAnimation = false\n } = options\n\n const baseCharities = charities ?? DEFAULT_CHARITIES\n const localizedCharities = mergeCharities(baseCharities, messages)\n\n let candidates =\n tags && tags.length > 0\n ? localizedCharities.filter(charity => charity.tags.some(t => tags.includes(t)))\n : localizedCharities\n\n if (candidates.length === 0) {\n candidates = localizedCharities\n }\n\n const charity = pickCharity(candidates, dontRepeat)\n\n const host = document.createElement('div')\n\n const shadow = host.attachShadow({ mode: 'open' })\n injectShadowStyles(shadow)\n\n const banner = document.createElement('header')\n banner.className = `${CSS_PREFIX} ${CSS_PREFIX}--${mode}`\n banner.lang = lang\n\n if (isRTL(lang)) {\n banner.setAttribute('dir', 'rtl')\n }\n\n const link = document.createElement('a')\n link.className = `${CSS_PREFIX}__link`\n link.href = charity.url\n link.target = '_blank'\n link.rel = 'noopener noreferrer'\n link.style.fontSize = fontSize\n\n const linkNewTabId = `${CSS_PREFIX}-link-new-tab`\n const linkNewTabHint = document.createElement('span')\n linkNewTabHint.id = linkNewTabId\n linkNewTabHint.className = VISUALLY_HIDDEN_CLASS\n linkNewTabHint.textContent = messages.opensInNewTab\n link.setAttribute('aria-describedby', linkNewTabId)\n\n const flag = document.createElement('span')\n flag.className = `${CSS_PREFIX}__flag`\n flag.textContent = `\\u{1F1FA}\\u{1F1E6} `\n\n const prefix = document.createElement('span')\n prefix.className = `${CSS_PREFIX}__prefix`\n prefix.textContent = `${messages.supportUkraine} `\n\n const info = document.createElement('span')\n info.className = `${CSS_PREFIX}__info`\n\n const name = document.createElement('span')\n name.className = `${CSS_PREFIX}__name`\n name.textContent = charity.name\n\n const colon = document.createElement('span')\n colon.className = `${CSS_PREFIX}__colon`\n colon.textContent = ': '\n\n const tagline = document.createElement('span')\n tagline.className = `${CSS_PREFIX}__tagline`\n tagline.textContent = charity.tagline\n\n info.append(name, colon, tagline)\n\n link.append(flag, prefix, info)\n banner.append(link)\n\n const moreLink = document.createElement('a')\n moreLink.className = `${CSS_PREFIX}__more`\n moreLink.href = 'https://damian-buho.github.io/support-ukraine/'\n moreLink.target = '_blank'\n moreLink.rel = 'noopener noreferrer'\n moreLink.style.fontSize = fontSize\n\n const moreNewTabId = `${CSS_PREFIX}-more-new-tab`\n const moreNewTabHint = document.createElement('span')\n moreNewTabHint.id = moreNewTabId\n moreNewTabHint.className = VISUALLY_HIDDEN_CLASS\n moreNewTabHint.textContent = messages.opensInNewTab\n moreLink.setAttribute('aria-describedby', moreNewTabId)\n\n const moreText = document.createElement('span')\n moreText.className = `${CSS_PREFIX}__more-text`\n moreText.textContent = messages.more\n\n const moreEllipsis = document.createElement('span')\n moreEllipsis.className = `${CSS_PREFIX}__more-ellipsis`\n moreEllipsis.textContent = '\\u{2026}'\n\n moreLink.append(moreText, moreEllipsis)\n banner.append(moreLink)\n banner.append(linkNewTabHint, moreNewTabHint)\n\n function applyNext(next: Charity): void {\n link.href = next.url\n name.textContent = next.name\n tagline.textContent = next.tagline\n if (isInConsole) {\n console.info('[support-ukraine] banner', `${next.name}: ${next.tagline}`, next.url)\n }\n }\n\n function updateCharity(): void {\n const next = pickCharity(candidates, dontRepeat)\n if (showRefreshAnimation) {\n banner.classList.add(`${CSS_PREFIX}--refreshing`)\n setTimeout(() => {\n applyNext(next)\n banner.classList.remove(`${CSS_PREFIX}--refreshing`)\n }, 200)\n } else {\n applyNext(next)\n }\n }\n\n if (showRefreshButton) {\n const refreshButton = document.createElement('button')\n refreshButton.className = `${CSS_PREFIX}__refresh`\n refreshButton.type = 'button'\n refreshButton.textContent = REFRESH_GLYPH\n refreshButton.style.fontSize = fontSize\n refreshButton.setAttribute('aria-label', messages.refresh)\n refreshButton.addEventListener('click', updateCharity)\n // eslint-disable-next-line unicorn/prefer-modern-dom-apis\n banner.insertBefore(refreshButton, moreLink)\n }\n\n shadow.append(banner)\n\n const mount = options.element ?? document.body\n\n if (mode === 'replace') {\n const placeholder = mount.querySelector<HTMLElement>(`.${CSS_PREFIX}`)\n if (placeholder) {\n placeholder.replaceWith(host)\n } else {\n mount.prepend(host)\n }\n } else {\n mount.prepend(host)\n }\n\n if (isInConsole) {\n console.info('[support-ukraine] banner', `${charity.name}: ${charity.tagline}`, charity.url)\n }\n\n host.dataset.supportUkraine = ''\n host.classList.add(`${CSS_PREFIX}--processed`)\n\n let intervalId: ReturnType<typeof setInterval> | undefined\n if (autoRefreshInterval > 0) {\n intervalId = setInterval(updateCharity, autoRefreshInterval)\n }\n\n const instance = host as HTMLElement & { destroy: () => void }\n instance.destroy = () => {\n if (intervalId !== undefined) {\n clearInterval(intervalId)\n }\n host.remove()\n }\n\n return instance\n}\n","// SPDX-FileCopyrightText: 2026 Damián Búho <damian.buho@proton.me>\n//\n// SPDX-License-Identifier: MIT\n\nimport messages from '../locales/en.yaml'\nimport { mountBanner } from '../banner.js'\nimport type { LocaleMessages, SupportUkraineBlockOptions } from '../types.js'\n\nexport type { Charity, CharityTag, SupportUkraineBlockOptions } from '../types.js'\nexport { charitySchema, charitiesSchema } from '../types.js'\nexport {\n DEFAULT_CHARITIES,\n mergeCharities,\n isRTL,\n formatBannerText,\n randomItem\n} from '../banner.js'\nexport type { SupportedLocale } from '../locales/index.js'\n\nconst LANG = 'en'\n\n/**\n * Localized `supportUkraineBlock` with `en` baked in.\n *\n * This build is self-contained — the locale messages are bundled inline, so\n * no second network request is needed. For optimal Core Web Vitals, load\n * only the locale you need:\n *\n * ```ts\n * import { supportUkraineBlock } from '@damian-buho/support-ukraine/en'\n * await supportUkraineBlock()\n * ```\n *\n * The `locale` option is ignored in this build (the bundle is already\n * localized). Use the auto-detect build (`@damian-buho/support-ukraine`)\n * if you need runtime locale switching.\n */\nexport function supportUkraineBlock(\n options: SupportUkraineBlockOptions = {}\n): Promise<HTMLElement> {\n return Promise.resolve(mountBanner(LANG, messages as unknown as LocaleMessages, options))\n}\n"],"mappings":"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","names":["en_default","VALID_TAGS","assert","condition","message","assertNonEmptyString","value","field","assertUrl","parseCharityTag","parseCharity","record","tag","charitySchema","charitiesSchema","item","charities_default","styles_default","DEFAULT_CHARITIES","charitiesSchema","charities_default","CSS_PREFIX","STORAGE_KEY","REFRESH_GLYPH","VISUALLY_HIDDEN_CLASS","readSeen","raw","writeSeen","seen","updateSeen","mutate","randomItem","items","pickCharity","candidates","shouldAvoidRepeat","pool","unseen","c","charity","injectShadowStyles","shadowRoot","id","style","styles_default","mergeCharities","base","locale","translated","isRTL","lang","formatBannerText","messages","mountBanner","options","mode","fontSize","charities","tags","dontRepeat","isInConsole","showRefreshButton","autoRefreshInterval","showRefreshAnimation","localizedCharities","t","host","shadow","banner","link","linkNewTabId","linkNewTabHint","flag","prefix","info","name","colon","tagline","moreLink","moreNewTabId","moreNewTabHint","moreText","moreEllipsis","applyNext","next","updateCharity","refreshButton","mount","placeholder","intervalId","instance","LANG","supportUkraineBlock","options","mountBanner","en_default"]}
|
|
1
|
+
{"version":3,"sources":["../src/locales/en.yaml","../src/types.ts","../src/charities.yaml","../src/styles.scss","../src/banner.ts","../src/entries/en.ts"],"sourcesContent":["export default {\"supportUkraine\":\"Support Ukraine with\",\"more\":\"more…\",\"donate\":\"Donate\",\"refresh\":\"Show next charity\",\"opensInNewTab\":\"(opens in a new tab)\",\"charities\":{\"united24\":{\"tagline\":\"Official fundraising platform of Ukraine\"},\"come-back-alive\":{\"tagline\":\"Supporting the Ukrainian Armed Forces since 2014\"},\"razom-for-ukraine\":{\"tagline\":\"Emergency response and humanitarian aid\"},\"ukrainian-red-cross\":{\"tagline\":\"Humanitarian assistance in conflict zones\"},\"nova-ukraine\":{\"tagline\":\"Humanitarian aid and advocacy\"},\"voices-of-children\":{\"tagline\":\"Psychological support for children affected by war\"},\"prytula-foundation\":{\"tagline\":\"Defence technology and equipment for Ukraine\"},\"army-of-drones\":{\"tagline\":\"Reconnaissance drones for the frontline\"},\"world-central-kitchen\":{\"tagline\":\"Fresh meals for people in conflict zones\"},\"cats-of-kyiv\":{\"tagline\":\"Cat shelter rescuing and rehoming cats in Kyiv\"},\"uanimals\":{\"tagline\":\"Animal rescue and advocacy organization in Ukraine\"},\"hospitallers\":{\"tagline\":\"Ukrainian voluntary paramedics providing first aid and evacuation\"},\"sternenko-fund\":{\"tagline\":\"FPV drone supply for Ukrainian defence forces\"},\"life-robots-ukraine\":{\"tagline\":\"Robots for demining Ukraine\"},\"sirius-shelter\":{\"tagline\":\"Ukraine's largest animal shelter for dogs and cats\"}}}","// SPDX-FileCopyrightText: 2026 Damián Búho <damian.buho@proton.me>\n//\n// SPDX-License-Identifier: MIT\n\n/**\nCategory tag for a charity.\n*/\nexport const VALID_TAGS = ['military', 'humanitarian', 'animals'] as const\nexport type CharityTag = (typeof VALID_TAGS)[number]\n\nfunction assert(condition: unknown, message: string): asserts condition {\n if (!condition) throw new Error(message)\n}\n\nfunction assertNonEmptyString(value: unknown, field: string): void {\n assert(typeof value === 'string', `${field} must be a string`)\n assert(value.length > 0, `${field} must not be empty`)\n}\n\nfunction assertUrl(value: unknown, field: string): void {\n assertNonEmptyString(value, field)\n try {\n new URL(value)\n } catch {\n throw new Error(`${field} must be a valid URL`)\n }\n}\n\nfunction parseCharityTag(value: unknown): CharityTag {\n assert(\n VALID_TAGS.includes(value as CharityTag),\n `Invalid tag: ${String(value)}. Must be one of: ${VALID_TAGS.join(', ')}`\n )\n return value as CharityTag\n}\n\n/**\nA charity foundation that can appear in the banner.\n*/\nexport interface Charity {\n id: string\n name: string\n tagline: string\n url: string\n tags: CharityTag[]\n}\n\nfunction parseCharity(value: unknown): Charity {\n assert(value !== null && typeof value === 'object', 'Charity must be an object')\n const record = value as Record<string, unknown>\n assertNonEmptyString(record.id, 'id')\n assertNonEmptyString(record.name, 'name')\n assertNonEmptyString(record.tagline, 'tagline')\n assertUrl(record.url, 'url')\n assert(Array.isArray(record.tags), 'tags must be an array')\n assert(record.tags.length > 0, 'tags must not be empty')\n return {\n id: record.id,\n name: record.name,\n tagline: record.tagline,\n url: record.url,\n tags: record.tags.map(tag => parseCharityTag(tag))\n }\n}\n\nexport const charitySchema = {\n parse: parseCharity\n}\n\nexport const charitiesSchema = {\n parse(value: unknown): Charity[] {\n assert(Array.isArray(value), 'Charities must be an array')\n return value.map(item => parseCharity(item))\n }\n}\n\n/**\nTranslated UI strings and charity taglines for a single locale.\n*/\nexport interface LocaleMessages {\n /**\n Banner prefix, e.g. \"Support Ukraine\".\n */\n supportUkraine: string\n /**\n \"More…\" link text.\n */\n more: string\n /**\n Card donate button text, e.g. \"Donate\".\n */\n donate: string\n /**\n Refresh button aria-label, e.g. \"Show next charity\".\n */\n refresh: string\n /**\n Text appended to external links for screen readers, e.g. \"(opens in a new tab)\".\n */\n opensInNewTab: string\n /**\n Translated taglines keyed by charity id. Missing keys fall back to EN.\n */\n charities: Record<string, { tagline: string }>\n}\n\nexport interface SupportUkraineBlockOptions {\n /**\n Target mount element. If omitted the banner is prepended to document.body.\n */\n element?: HTMLElement\n /**\n Positioning mode: 'shift' pushes content down, 'overlap' floats on top, 'replace' swaps a same-class placeholder.\n */\n mode?: 'shift' | 'overlap' | 'replace'\n /**\n Font size (default '87.5%'). Percentages resolve against the widget's fixed 16px host box, so document root scaling is ignored; rem would inherit it.\n */\n fontSize?: string\n /**\n * Custom charity list. If omitted the built-in defaults are used.\n */\n charities?: Charity[]\n /**\n * Category tags to filter by. If omitted all charities are shown.\n */\n tags?: CharityTag[]\n /**\n Avoid repeating charities across page loads using localStorage.\n */\n dontRepeat?: boolean\n /**\n Log a message to the dev console.\n */\n isInConsole?: boolean\n /**\n Show a refresh button that loads the next random charity.\n */\n showRefreshButton?: boolean\n /**\n Auto-refresh interval in milliseconds. 0 = off (default). Set e.g. 15000 for 15 seconds.\n */\n autoRefreshInterval?: number\n /**\n Show a fade animation when the charity changes (respects prefers-reduced-motion).\n */\n showRefreshAnimation?: boolean\n /**\n * Override the auto-detected locale (BCP 47 language tag).\n * If omitted the locale is detected from `navigator.language`.\n */\n locale?: string\n}\n","export default [{\"id\":\"united24\",\"name\":\"United24\",\"tagline\":\"Official fundraising platform of Ukraine\",\"url\":\"https://u24.gov.ua\",\"tags\":[\"humanitarian\"]},{\"id\":\"come-back-alive\",\"name\":\"Come Back Alive\",\"tagline\":\"Supporting the Ukrainian Armed Forces since 2014\",\"url\":\"https://www.comebackalive.in.ua\",\"tags\":[\"military\"]},{\"id\":\"razom-for-ukraine\",\"name\":\"Razom for Ukraine\",\"tagline\":\"Emergency response and humanitarian aid\",\"url\":\"https://www.razomforukraine.org\",\"tags\":[\"humanitarian\"]},{\"id\":\"ukrainian-red-cross\",\"name\":\"Ukrainian Red Cross\",\"tagline\":\"Humanitarian assistance in conflict zones\",\"url\":\"https://redcross.org.ua/en/\",\"tags\":[\"humanitarian\"]},{\"id\":\"nova-ukraine\",\"name\":\"Nova Ukraine\",\"tagline\":\"Humanitarian aid and advocacy\",\"url\":\"https://novaukraine.org\",\"tags\":[\"humanitarian\"]},{\"id\":\"voices-of-children\",\"name\":\"Voices of Children\",\"tagline\":\"Psychological support for children affected by war\",\"url\":\"https://voices.org.ua/en/\",\"tags\":[\"humanitarian\"]},{\"id\":\"prytula-foundation\",\"name\":\"Prytula Foundation\",\"tagline\":\"Defence technology and equipment for Ukraine\",\"url\":\"https://prytulafoundation.org/en\",\"tags\":[\"military\"]},{\"id\":\"army-of-drones\",\"name\":\"Army of Drones\",\"tagline\":\"Reconnaissance drones for the frontline\",\"url\":\"https://armyofdrones.com\",\"tags\":[\"military\"]},{\"id\":\"world-central-kitchen\",\"name\":\"World Central Kitchen\",\"tagline\":\"Fresh meals for people in conflict zones\",\"url\":\"https://wck.org/relief/activation-chefs-for-ukraine/\",\"tags\":[\"humanitarian\"]},{\"id\":\"cats-of-kyiv\",\"name\":\"Cats of Kyiv\",\"tagline\":\"Cat shelter rescuing and rehoming cats in Kyiv\",\"url\":\"https://cats.kiev.ua\",\"tags\":[\"animals\"]},{\"id\":\"uanimals\",\"name\":\"UAnimals\",\"tagline\":\"Animal rescue and advocacy organization in Ukraine\",\"url\":\"https://uanimals.org\",\"tags\":[\"animals\"]},{\"id\":\"hospitallers\",\"name\":\"Hospitallers\",\"tagline\":\"Ukrainian voluntary paramedics providing first aid and evacuation\",\"url\":\"https://www.hospitallers.org.uk\",\"tags\":[\"humanitarian\"]},{\"id\":\"sternenko-fund\",\"name\":\"Sternenko Fund\",\"tagline\":\"FPV drone supply for Ukrainian defence forces\",\"url\":\"https://www.sternenkofund.org\",\"tags\":[\"military\"]},{\"id\":\"life-robots-ukraine\",\"name\":\"Life Robots Ukraine\",\"tagline\":\"Robots for demining Ukraine\",\"url\":\"https://liferobots.com.ua\",\"tags\":[\"humanitarian\"]},{\"id\":\"sirius-shelter\",\"name\":\"Sirius\",\"tagline\":\"Ukraine's largest animal shelter for dogs and cats\",\"url\":\"https://dogcat.com.ua\",\"tags\":[\"animals\"]},{\"id\":\"dignitas\",\"name\":\"Dignitas\",\"tagline\":\"Technology and support for Ukrainian defenders and veterans\",\"url\":\"https://dignitas.fund\",\"tags\":[\"military\"]},{\"id\":\"leleka\",\"name\":\"Leleka Foundation\",\"tagline\":\"Tactical medical supplies for Ukraine's frontline medics\",\"url\":\"https://leleka.care/en\",\"tags\":[\"humanitarian\"]},{\"id\":\"superhumans\",\"name\":\"Superhumans Center\",\"tagline\":\"Prosthetics, surgery, and rehabilitation for war survivors\",\"url\":\"https://superhumans.com/en/\",\"tags\":[\"humanitarian\"]}]","export default \":host{display:block;margin:0;padding:0;border:none;font-size:16px;width:100%;min-height:2.5em;line-height:1.4;box-sizing:border-box;z-index:2147483647}.support-ukraine-block__visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}header.support-ukraine-block{margin:0;padding:0;border:none;border-radius:0;width:100%;min-height:2.5em;display:flex;align-items:center;justify-content:center;font-family:system-ui,-apple-system,sans-serif;text-decoration:none;box-sizing:border-box;line-height:1.4;overflow:visible;background:#0057b7 none}@media(prefers-color-scheme: dark){header.support-ukraine-block{background-color:gold}}header.support-ukraine-block--shift,header.support-ukraine-block--replace{position:relative}header.support-ukraine-block--overlap{position:fixed;top:0;left:0;z-index:2147483647}header.support-ukraine-block--refreshing .support-ukraine-block__link{opacity:0}header.support-ukraine-block .support-ukraine-block__link{display:inline-flex;align-items:center;flex-wrap:wrap;gap:0 .25em;text-decoration:none;flex:1;height:100%;justify-content:flex-start;text-align:left;padding:.5em 1em;box-sizing:border-box;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}@media(prefers-reduced-motion: no-preference){header.support-ukraine-block .support-ukraine-block__link{transition:opacity .2s ease-in-out}}@media(prefers-color-scheme: dark){header.support-ukraine-block .support-ukraine-block__link{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}header.support-ukraine-block .support-ukraine-block__link:hover{opacity:.9}header.support-ukraine-block .support-ukraine-block__link:focus-visible{outline:2px solid #fff;outline-offset:-2px}header.support-ukraine-block .support-ukraine-block__flag{white-space:nowrap}header.support-ukraine-block .support-ukraine-block__prefix,header.support-ukraine-block .support-ukraine-block__info,header.support-ukraine-block .support-ukraine-block__colon,header.support-ukraine-block .support-ukraine-block__tagline{min-width:0}header.support-ukraine-block .support-ukraine-block__more{display:inline-flex;align-items:center;text-decoration:none;padding:.5em 1em;box-sizing:border-box;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4);white-space:nowrap;opacity:.8}@media(prefers-color-scheme: dark){header.support-ukraine-block .support-ukraine-block__more{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}header.support-ukraine-block .support-ukraine-block__more:hover{opacity:1}header.support-ukraine-block .support-ukraine-block__more:focus-visible{outline:2px solid #fff;outline-offset:-2px}header.support-ukraine-block .support-ukraine-block__more-ellipsis{display:none}header.support-ukraine-block .support-ukraine-block__refresh{display:inline-flex;align-items:center;background:none;border:none;text-decoration:none;padding:.5em .5em .5em 1em;box-sizing:border-box;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4);white-space:nowrap;opacity:.8;cursor:pointer;font-size:inherit;line-height:1}@media(prefers-color-scheme: dark){header.support-ukraine-block .support-ukraine-block__refresh{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}header.support-ukraine-block .support-ukraine-block__refresh:hover{opacity:1}header.support-ukraine-block .support-ukraine-block__refresh:focus-visible{outline:2px solid #fff;outline-offset:-2px}header.support-ukraine-block .support-ukraine-block__name{font-weight:bold}@media(max-width: 58rem){header.support-ukraine-block .support-ukraine-block__prefix,header.support-ukraine-block .support-ukraine-block__name,header.support-ukraine-block .support-ukraine-block__colon,header.support-ukraine-block .support-ukraine-block__more,header.support-ukraine-block .support-ukraine-block__refresh{display:none}}@media(max-width: 35rem){header.support-ukraine-block .support-ukraine-block__name,header.support-ukraine-block .support-ukraine-block__colon{display:initial}header.support-ukraine-block .support-ukraine-block__tagline{display:none}}[dir=rtl] header.support-ukraine-block .support-ukraine-block__link{text-align:right;justify-content:flex-end}[dir=rtl] header.support-ukraine-block .support-ukraine-block__more{text-align:right}[dir=rtl] header.support-ukraine-block .support-ukraine-block__refresh{text-align:right}:host-context([data-theme=dark]) header.support-ukraine-block{background-color:gold}:host-context([data-theme=dark]) header.support-ukraine-block .support-ukraine-block__link{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=dark]) header.support-ukraine-block .support-ukraine-block__more{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=dark]) header.support-ukraine-block .support-ukraine-block__refresh{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=light]) header.support-ukraine-block{background-color:#0057b7}:host-context([data-theme=light]) header.support-ukraine-block .support-ukraine-block__link{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}:host-context([data-theme=light]) header.support-ukraine-block .support-ukraine-block__more{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}:host-context([data-theme=light]) header.support-ukraine-block .support-ukraine-block__refresh{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}\"","// SPDX-FileCopyrightText: 2026 Damián Búho <damian.buho@proton.me>\n//\n// SPDX-License-Identifier: MIT\n\nimport {\n charitiesSchema,\n type Charity,\n type LocaleMessages,\n type SupportUkraineBlockOptions\n} from './types.js'\nimport rawCharities from './charities.yaml'\nimport styles from './styles.scss'\n\nexport type { Charity, CharityTag, SupportUkraineBlockOptions, LocaleMessages } from './types.js'\n\nexport const DEFAULT_CHARITIES: Charity[] = charitiesSchema.parse(rawCharities)\n\nconst CSS_PREFIX = 'support-ukraine-block'\nconst STORAGE_KEY = 'support-ukraine-seen'\nconst REFRESH_GLYPH = '\\u{27F3}'\nconst VISUALLY_HIDDEN_CLASS = `${CSS_PREFIX}__visually-hidden`\n\nfunction readSeen(): Set<string> {\n try {\n const raw = localStorage.getItem(STORAGE_KEY)\n return raw ? new Set(JSON.parse(raw) as string[]) : new Set()\n } catch {\n return new Set()\n }\n}\n\nfunction writeSeen(seen: Set<string>): void {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify([...seen]))\n } catch {\n // localStorage unavailable — degrade silently\n }\n}\n\nfunction updateSeen(mutate: (seen: Set<string>) => void): void {\n const seen = readSeen()\n mutate(seen)\n writeSeen(seen)\n}\n\n/**\n * Pick a random item from an array.\n *\n * @internal\n */\nexport function randomItem<T>(items: T[]): T {\n if (items.length === 0) {\n throw new Error('randomItem: cannot pick from an empty array')\n }\n return items[Math.floor(Math.random() * items.length)]!\n}\n\nfunction pickCharity(candidates: Charity[], shouldAvoidRepeat: boolean): Charity {\n let pool = candidates\n\n if (shouldAvoidRepeat) {\n updateSeen(seen => {\n const unseen = pool.filter(c => !seen.has(c.url))\n if (unseen.length > 0) {\n pool = unseen\n } else {\n seen.clear()\n }\n })\n }\n\n const charity = randomItem(pool)\n\n if (shouldAvoidRepeat) {\n updateSeen(seen => {\n seen.add(charity.url)\n })\n }\n\n return charity\n}\n\nfunction injectShadowStyles(shadowRoot: ShadowRoot): void {\n const id = `${CSS_PREFIX}-styles`\n if (shadowRoot.querySelector(`#${id}`)) {\n return\n }\n\n const style = shadowRoot.ownerDocument.createElement('style')\n style.id = id\n style.textContent = styles\n shadowRoot.append(style)\n}\n\n/**\n * Merge base charities with locale-specific translations.\n */\nexport function mergeCharities(base: readonly Charity[], locale: LocaleMessages): Charity[] {\n return base.map(charity => {\n const translated = locale.charities[charity.id]\n if (translated?.tagline) {\n return { ...charity, tagline: translated.tagline }\n }\n return charity\n })\n}\n\nexport function isRTL(lang: string): boolean {\n const base = (lang.split('-', 1)[0] ?? '').toLowerCase()\n return base === 'ar'\n}\n\nexport function formatBannerText(charity: Charity, messages: LocaleMessages): string {\n return `\\u{1F1FA}\\u{1F1E6} ${messages.supportUkraine} ${charity.name}: ${charity.tagline}`\n}\n\n/**\n * Mount the banner with already-resolved `lang` and `messages`.\n * Shared by the auto-detect build (`src/index.ts`) and the per-locale builds (`src/entries/*.ts`).\n */\nexport function mountBanner(\n lang: string,\n messages: LocaleMessages,\n options: SupportUkraineBlockOptions = {}\n): HTMLElement & { destroy: () => void } {\n const {\n mode = 'shift',\n fontSize = '87.5%',\n charities,\n tags,\n dontRepeat = true,\n isInConsole = true,\n showRefreshButton = false,\n autoRefreshInterval = 0,\n showRefreshAnimation = false\n } = options\n\n const baseCharities = charities ?? DEFAULT_CHARITIES\n const localizedCharities = mergeCharities(baseCharities, messages)\n\n let candidates =\n tags && tags.length > 0\n ? localizedCharities.filter(charity => charity.tags.some(t => tags.includes(t)))\n : localizedCharities\n\n if (candidates.length === 0) {\n candidates = localizedCharities\n }\n\n const charity = pickCharity(candidates, dontRepeat)\n\n const host = document.createElement('div')\n\n const shadow = host.attachShadow({ mode: 'open' })\n injectShadowStyles(shadow)\n\n const banner = document.createElement('header')\n banner.className = `${CSS_PREFIX} ${CSS_PREFIX}--${mode}`\n banner.lang = lang\n\n if (isRTL(lang)) {\n banner.setAttribute('dir', 'rtl')\n }\n\n const link = document.createElement('a')\n link.className = `${CSS_PREFIX}__link`\n link.href = charity.url\n link.target = '_blank'\n link.rel = 'noopener noreferrer'\n link.style.fontSize = fontSize\n\n const linkNewTabId = `${CSS_PREFIX}-link-new-tab`\n const linkNewTabHint = document.createElement('span')\n linkNewTabHint.id = linkNewTabId\n linkNewTabHint.className = VISUALLY_HIDDEN_CLASS\n linkNewTabHint.textContent = messages.opensInNewTab\n link.setAttribute('aria-describedby', linkNewTabId)\n\n const flag = document.createElement('span')\n flag.className = `${CSS_PREFIX}__flag`\n flag.textContent = `\\u{1F1FA}\\u{1F1E6} `\n\n const prefix = document.createElement('span')\n prefix.className = `${CSS_PREFIX}__prefix`\n prefix.textContent = `${messages.supportUkraine} `\n\n const info = document.createElement('span')\n info.className = `${CSS_PREFIX}__info`\n\n const name = document.createElement('span')\n name.className = `${CSS_PREFIX}__name`\n name.textContent = charity.name\n\n const colon = document.createElement('span')\n colon.className = `${CSS_PREFIX}__colon`\n colon.textContent = ': '\n\n const tagline = document.createElement('span')\n tagline.className = `${CSS_PREFIX}__tagline`\n tagline.textContent = charity.tagline\n\n info.append(name, colon, tagline)\n\n link.append(flag, prefix, info)\n banner.append(link)\n\n const moreLink = document.createElement('a')\n moreLink.className = `${CSS_PREFIX}__more`\n moreLink.href = 'https://damian-buho.github.io/support-ukraine/'\n moreLink.target = '_blank'\n moreLink.rel = 'noopener noreferrer'\n moreLink.style.fontSize = fontSize\n\n const moreNewTabId = `${CSS_PREFIX}-more-new-tab`\n const moreNewTabHint = document.createElement('span')\n moreNewTabHint.id = moreNewTabId\n moreNewTabHint.className = VISUALLY_HIDDEN_CLASS\n moreNewTabHint.textContent = messages.opensInNewTab\n moreLink.setAttribute('aria-describedby', moreNewTabId)\n\n const moreText = document.createElement('span')\n moreText.className = `${CSS_PREFIX}__more-text`\n moreText.textContent = messages.more\n\n const moreEllipsis = document.createElement('span')\n moreEllipsis.className = `${CSS_PREFIX}__more-ellipsis`\n moreEllipsis.textContent = '\\u{2026}'\n\n moreLink.append(moreText, moreEllipsis)\n banner.append(moreLink)\n banner.append(linkNewTabHint, moreNewTabHint)\n\n function applyNext(next: Charity): void {\n link.href = next.url\n name.textContent = next.name\n tagline.textContent = next.tagline\n if (isInConsole) {\n console.info('[support-ukraine] banner', `${next.name}: ${next.tagline}`, next.url)\n }\n }\n\n function updateCharity(): void {\n const next = pickCharity(candidates, dontRepeat)\n if (showRefreshAnimation) {\n banner.classList.add(`${CSS_PREFIX}--refreshing`)\n setTimeout(() => {\n applyNext(next)\n banner.classList.remove(`${CSS_PREFIX}--refreshing`)\n }, 200)\n } else {\n applyNext(next)\n }\n }\n\n if (showRefreshButton) {\n const refreshButton = document.createElement('button')\n refreshButton.className = `${CSS_PREFIX}__refresh`\n refreshButton.type = 'button'\n refreshButton.textContent = REFRESH_GLYPH\n refreshButton.style.fontSize = fontSize\n refreshButton.setAttribute('aria-label', messages.refresh)\n refreshButton.addEventListener('click', updateCharity)\n // eslint-disable-next-line unicorn/prefer-modern-dom-apis\n banner.insertBefore(refreshButton, moreLink)\n }\n\n shadow.append(banner)\n\n const mount = options.element ?? document.body\n\n if (mode === 'replace') {\n const placeholder = mount.querySelector<HTMLElement>(`.${CSS_PREFIX}`)\n if (placeholder) {\n placeholder.replaceWith(host)\n } else {\n mount.prepend(host)\n }\n } else {\n mount.prepend(host)\n }\n\n if (isInConsole) {\n console.info('[support-ukraine] banner', `${charity.name}: ${charity.tagline}`, charity.url)\n }\n\n host.dataset.supportUkraine = ''\n host.classList.add(`${CSS_PREFIX}--processed`)\n\n let intervalId: ReturnType<typeof setInterval> | undefined\n if (autoRefreshInterval > 0) {\n intervalId = setInterval(updateCharity, autoRefreshInterval)\n }\n\n const instance = host as HTMLElement & { destroy: () => void }\n instance.destroy = () => {\n if (intervalId !== undefined) {\n clearInterval(intervalId)\n }\n host.remove()\n }\n\n return instance\n}\n","// SPDX-FileCopyrightText: 2026 Damián Búho <damian.buho@proton.me>\n//\n// SPDX-License-Identifier: MIT\n\nimport messages from '../locales/en.yaml'\nimport { mountBanner } from '../banner.js'\nimport type { LocaleMessages, SupportUkraineBlockOptions } from '../types.js'\n\nexport type { Charity, CharityTag, SupportUkraineBlockOptions } from '../types.js'\nexport { charitySchema, charitiesSchema } from '../types.js'\nexport {\n DEFAULT_CHARITIES,\n mergeCharities,\n isRTL,\n formatBannerText,\n randomItem\n} from '../banner.js'\nexport type { SupportedLocale } from '../locales/index.js'\n\nconst LANG = 'en'\n\n/**\n * Localized `supportUkraineBlock` with `en` baked in.\n *\n * This build is self-contained — the locale messages are bundled inline, so\n * no second network request is needed. For optimal Core Web Vitals, load\n * only the locale you need:\n *\n * ```ts\n * import { supportUkraineBlock } from '@damian-buho/support-ukraine/en'\n * await supportUkraineBlock()\n * ```\n *\n * The `locale` option is ignored in this build (the bundle is already\n * localized). Use the auto-detect build (`@damian-buho/support-ukraine`)\n * if you need runtime locale switching.\n */\nexport function supportUkraineBlock(\n options: SupportUkraineBlockOptions = {}\n): Promise<HTMLElement> {\n return Promise.resolve(mountBanner(LANG, messages as unknown as LocaleMessages, options))\n}\n"],"mappings":"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","names":["en_default","VALID_TAGS","assert","condition","message","assertNonEmptyString","value","field","assertUrl","parseCharityTag","parseCharity","record","tag","charitySchema","charitiesSchema","item","charities_default","styles_default","DEFAULT_CHARITIES","charitiesSchema","charities_default","CSS_PREFIX","STORAGE_KEY","REFRESH_GLYPH","VISUALLY_HIDDEN_CLASS","readSeen","raw","writeSeen","seen","updateSeen","mutate","randomItem","items","pickCharity","candidates","shouldAvoidRepeat","pool","unseen","c","charity","injectShadowStyles","shadowRoot","id","style","styles_default","mergeCharities","base","locale","translated","isRTL","lang","formatBannerText","messages","mountBanner","options","mode","fontSize","charities","tags","dontRepeat","isInConsole","showRefreshButton","autoRefreshInterval","showRefreshAnimation","localizedCharities","t","host","shadow","banner","link","linkNewTabId","linkNewTabHint","flag","prefix","info","name","colon","tagline","moreLink","moreNewTabId","moreNewTabHint","moreText","moreEllipsis","applyNext","next","updateCharity","refreshButton","mount","placeholder","intervalId","instance","LANG","supportUkraineBlock","options","mountBanner","en_default"]}
|
package/dist/es.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var D={supportUkraine:"Apoya a Ucrania con",more:"m\xE1s\u2026",donate:"Donar",refresh:"Mostrar siguiente charity",opensInNewTab:"(se abre en una nueva pesta\xF1a)",charities:{united24:{tagline:"Plataforma oficial de recaudaci\xF3n de Ucrania"},"come-back-alive":{tagline:"Apoyando a las fuerzas armadas ucranianas desde 2014"},"razom-for-ukraine":{tagline:"Respuesta de emergencia y ayuda humanitaria"},"ukrainian-red-cross":{tagline:"Asistencia humanitaria en zonas de conflicto"},"nova-ukraine":{tagline:"Ayuda humanitaria y defensa de derechos"},"voices-of-children":{tagline:"Apoyo psicol\xF3gico para ni\xF1os afectados por la guerra"},"prytula-foundation":{tagline:"Tecnolog\xEDa de defensa y equipamiento para Ucrania"},"medical-hilfe":{tagline:"Suministros m\xE9dicos para hospitales ucranianos"},"army-of-drones":{tagline:"Drones de reconocimiento para el frente"},"world-central-kitchen":{tagline:"Comidas frescas para personas en zonas de conflicto"},"cats-of-kyiv":{tagline:"Refugio que rescata y reubicia gatos en Kyiv"},uanimals:{tagline:"Organizaci\xF3n de rescate animal y defensa de derechos en Ucrania"},hospitallers:{tagline:"Param\xE9dicos voluntarios ucranianos que prestan primeros auxilios y evacuaci\xF3n"},"sternenko-fund":{tagline:"Suministro de drones FPV para las fuerzas de defensa ucranianas"},"life-robots-ukraine":{tagline:"Robots para la desminaci\xF3n de Ucrania"},"sirius-shelter":{tagline:"El mayor refugio de animales de Ucrania para perros y gatos"}}};var O=["military","humanitarian","animals"];function u(e,t){if(!e)throw new Error(t)}function x(e,t){u(typeof e=="string",`${t} must be a string`),u(e.length>0,`${t} must not be empty`)}function re(e,t){x(e,t);try{new URL(e)}catch{throw new Error(`${t} must be a valid URL`)}}function ne(e){return u(O.includes(e),`Invalid tag: ${String(e)}. Must be one of: ${O.join(", ")}`),e}function j(e){u(e!==null&&typeof e=="object","Charity must be an object");let t=e;return x(t.id,"id"),x(t.name,"name"),x(t.tagline,"tagline"),re(t.url,"url"),u(Array.isArray(t.tags),"tags must be an array"),u(t.tags.length>0,"tags must not be empty"),{id:t.id,name:t.name,tagline:t.tagline,url:t.url,tags:t.tags.map(n=>ne(n))}}var oe={parse:j},L={parse(e){return u(Array.isArray(e),"Charities must be an array"),e.map(t=>j(t))}};var P=[{id:"united24",name:"United24",tagline:"Official fundraising platform of Ukraine",url:"https://u24.gov.ua",tags:["humanitarian"]},{id:"come-back-alive",name:"Come Back Alive",tagline:"Supporting the Ukrainian Armed Forces since 2014",url:"https://www.comebackalive.in.ua",tags:["military"]},{id:"razom-for-ukraine",name:"Razom for Ukraine",tagline:"Emergency response and humanitarian aid",url:"https://www.razomforukraine.org",tags:["humanitarian"]},{id:"ukrainian-red-cross",name:"Ukrainian Red Cross",tagline:"Humanitarian assistance in conflict zones",url:"https://redcross.org.ua/en/",tags:["humanitarian"]},{id:"nova-ukraine",name:"Nova Ukraine",tagline:"Humanitarian aid and advocacy",url:"https://novaukraine.org",tags:["humanitarian"]},{id:"voices-of-children",name:"Voices of Children",tagline:"Psychological support for children affected by war",url:"https://voices.org.ua/en/",tags:["humanitarian"]},{id:"prytula-foundation",name:"Prytula Foundation",tagline:"Defence technology and equipment for Ukraine",url:"https://prytulafoundation.org/en",tags:["military"]},{id:"army-of-drones",name:"Army of Drones",tagline:"Reconnaissance drones for the frontline",url:"https://armyofdrones.com",tags:["military"]},{id:"world-central-kitchen",name:"World Central Kitchen",tagline:"Fresh meals for people in conflict zones",url:"https://wck.org/relief/activation-chefs-for-ukraine/",tags:["humanitarian"]},{id:"cats-of-kyiv",name:"Cats of Kyiv",tagline:"Cat shelter rescuing and rehoming cats in Kyiv",url:"https://cats.kiev.ua",tags:["animals"]},{id:"uanimals",name:"UAnimals",tagline:"Animal rescue and advocacy organization in Ukraine",url:"https://uanimals.org",tags:["animals"]},{id:"hospitallers",name:"Hospitallers",tagline:"Ukrainian voluntary paramedics providing first aid and evacuation",url:"https://www.hospitallers.org.uk",tags:["humanitarian"]},{id:"sternenko-fund",name:"Sternenko Fund",tagline:"FPV drone supply for Ukrainian defence forces",url:"https://www.sternenkofund.org",tags:["military"]},{id:"life-robots-ukraine",name:"Life Robots Ukraine",tagline:"Robots for demining Ukraine",url:"https://liferobots.com.ua",tags:["humanitarian"]},{id:"sirius-shelter",name:"Sirius",tagline:"Ukraine's largest animal shelter for dogs and cats",url:"https://dogcat.com.ua",tags:["animals"]},{id:"dignitas",name:"Dignitas",tagline:"Technology and support for Ukrainian defenders and veterans",url:"https://dignitas.fund",tags:["military"]},{id:"leleka",name:"Leleka Foundation",tagline:"Tactical medical supplies for Ukraine's frontline medics",url:"https://leleka.care/en",tags:["humanitarian"]},{id:"superhumans",name:"Superhumans Center",tagline:"Prosthetics, surgery, and rehabilitation for war survivors",url:"https://superhumans.com/en/",tags:["humanitarian"]}];var q=":host{display:block;margin:0;padding:0;border:none;font-size:16px;width:100%;min-height:2.5em;line-height:1.4;box-sizing:border-box;z-index:2147483647}.support-ukraine-block__visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}header.support-ukraine-block{margin:0;padding:0;border:none;border-radius:0;width:100%;min-height:2.5em;display:flex;align-items:center;justify-content:center;font-family:system-ui,-apple-system,sans-serif;text-decoration:none;box-sizing:border-box;line-height:1.4;overflow:visible;background:#0057b7 none}@media(prefers-color-scheme: dark){header.support-ukraine-block{background-color:gold}}header.support-ukraine-block--shift,header.support-ukraine-block--replace{position:relative}header.support-ukraine-block--overlap{position:fixed;top:0;left:0}header.support-ukraine-block--refreshing .support-ukraine-block__link{opacity:0}header.support-ukraine-block .support-ukraine-block__link{display:inline-flex;align-items:center;flex-wrap:wrap;gap:0 .25em;text-decoration:none;flex:1;height:100%;justify-content:flex-start;text-align:left;padding:.5em 1em;box-sizing:border-box;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}@media(prefers-reduced-motion: no-preference){header.support-ukraine-block .support-ukraine-block__link{transition:opacity .2s ease-in-out}}@media(prefers-color-scheme: dark){header.support-ukraine-block .support-ukraine-block__link{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}header.support-ukraine-block .support-ukraine-block__link:hover{opacity:.9}header.support-ukraine-block .support-ukraine-block__link:focus-visible{outline:2px solid #fff;outline-offset:-2px}header.support-ukraine-block .support-ukraine-block__flag{white-space:nowrap}header.support-ukraine-block .support-ukraine-block__prefix,header.support-ukraine-block .support-ukraine-block__info,header.support-ukraine-block .support-ukraine-block__colon,header.support-ukraine-block .support-ukraine-block__tagline{min-width:0}header.support-ukraine-block .support-ukraine-block__more{display:inline-flex;align-items:center;text-decoration:none;padding:.5em 1em;box-sizing:border-box;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4);white-space:nowrap;opacity:.8}@media(prefers-color-scheme: dark){header.support-ukraine-block .support-ukraine-block__more{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}header.support-ukraine-block .support-ukraine-block__more:hover{opacity:1}header.support-ukraine-block .support-ukraine-block__more:focus-visible{outline:2px solid #fff;outline-offset:-2px}header.support-ukraine-block .support-ukraine-block__more-ellipsis{display:none}header.support-ukraine-block .support-ukraine-block__refresh{display:inline-flex;align-items:center;background:none;border:none;text-decoration:none;padding:.5em .5em .5em 1em;box-sizing:border-box;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4);white-space:nowrap;opacity:.8;cursor:pointer;font-size:inherit;line-height:1}@media(prefers-color-scheme: dark){header.support-ukraine-block .support-ukraine-block__refresh{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}header.support-ukraine-block .support-ukraine-block__refresh:hover{opacity:1}header.support-ukraine-block .support-ukraine-block__refresh:focus-visible{outline:2px solid #fff;outline-offset:-2px}header.support-ukraine-block .support-ukraine-block__name{font-weight:bold}@media(max-width: 58rem){header.support-ukraine-block .support-ukraine-block__prefix,header.support-ukraine-block .support-ukraine-block__name,header.support-ukraine-block .support-ukraine-block__colon,header.support-ukraine-block .support-ukraine-block__more,header.support-ukraine-block .support-ukraine-block__refresh{display:none}}@media(max-width: 35rem){header.support-ukraine-block .support-ukraine-block__name,header.support-ukraine-block .support-ukraine-block__colon{display:initial}header.support-ukraine-block .support-ukraine-block__tagline{display:none}}[dir=rtl] header.support-ukraine-block .support-ukraine-block__link{text-align:right;justify-content:flex-end}[dir=rtl] header.support-ukraine-block .support-ukraine-block__more{text-align:right}[dir=rtl] header.support-ukraine-block .support-ukraine-block__refresh{text-align:right}:host-context([data-theme=dark]) header.support-ukraine-block{background-color:gold}:host-context([data-theme=dark]) header.support-ukraine-block .support-ukraine-block__link{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=dark]) header.support-ukraine-block .support-ukraine-block__more{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=dark]) header.support-ukraine-block .support-ukraine-block__refresh{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=light]) header.support-ukraine-block{background-color:#0057b7}:host-context([data-theme=light]) header.support-ukraine-block .support-ukraine-block__link{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}:host-context([data-theme=light]) header.support-ukraine-block .support-ukraine-block__more{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}:host-context([data-theme=light]) header.support-ukraine-block .support-ukraine-block__refresh{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}";var Y=L.parse(P),r="support-ukraine-block",J="support-ukraine-seen",ie="\u27F3",V=`${r}__visually-hidden`;function se(){try{let e=localStorage.getItem(J);return e?new Set(JSON.parse(e)):new Set}catch{return new Set}}function le(e){try{localStorage.setItem(J,JSON.stringify([...e]))}catch{}}function G(e){let t=se();e(t),le(t)}function W(e){if(e.length===0)throw new Error("randomItem: cannot pick from an empty array");return e[Math.floor(Math.random()*e.length)]}function K(e,t){let n=e;t&&G(p=>{let h=n.filter(m=>!p.has(m.url));h.length>0?n=h:p.clear()});let l=W(n);return t&&G(p=>{p.add(l.url)}),l}function pe(e){let t=`${r}-styles`;if(e.querySelector(`#${t}`))return;let n=e.ownerDocument.createElement("style");n.id=t,n.textContent=q,e.append(n)}function X(e,t){return e.map(n=>{let l=t.charities[n.id];return l?.tagline?{...n,tagline:l.tagline}:n})}function Q(e){return(e.split("-",1)[0]??"").toLowerCase()==="ar"}function ce(e,t){return`\u{1F1FA}\u{1F1E6} ${t.supportUkraine} ${e.name}: ${e.tagline}`}function Z(e,t,n={}){let{mode:l="shift",fontSize:p="87.5%",charities:h,tags:m,dontRepeat:A=!0,isInConsole:I=!0,showRefreshButton:ee=!1,autoRefreshInterval:N=0,showRefreshAnimation:te=!1}=n,_=X(h??Y,t),k=m&&m.length>0?_.filter(a=>a.tags.some(ae=>m.includes(ae))):_;k.length===0&&(k=_);let d=K(k,A),c=document.createElement("div"),R=c.attachShadow({mode:"open"});pe(R);let o=document.createElement("header");o.className=`${r} ${r}--${l}`,o.lang=e,Q(e)&&o.setAttribute("dir","rtl");let i=document.createElement("a");i.className=`${r}__link`,i.href=d.url,i.target="_blank",i.rel="noopener noreferrer",i.style.fontSize=p;let z=`${r}-link-new-tab`,f=document.createElement("span");f.id=z,f.className=V,f.textContent=t.opensInNewTab,i.setAttribute("aria-describedby",z);let w=document.createElement("span");w.className=`${r}__flag`,w.textContent="\u{1F1FA}\u{1F1E6} ";let C=document.createElement("span");C.className=`${r}__prefix`,C.textContent=`${t.supportUkraine} `;let v=document.createElement("span");v.className=`${r}__info`;let g=document.createElement("span");g.className=`${r}__name`,g.textContent=d.name;let S=document.createElement("span");S.className=`${r}__colon`,S.textContent=": ";let b=document.createElement("span");b.className=`${r}__tagline`,b.textContent=d.tagline,v.append(g,S,b),i.append(w,C,v),o.append(i);let s=document.createElement("a");s.className=`${r}__more`,s.href="https://damian-buho.github.io/support-ukraine/",s.target="_blank",s.rel="noopener noreferrer",s.style.fontSize=p;let F=`${r}-more-new-tab`,y=document.createElement("span");y.id=F,y.className=V,y.textContent=t.opensInNewTab,s.setAttribute("aria-describedby",F);let T=document.createElement("span");T.className=`${r}__more-text`,T.textContent=t.more;let E=document.createElement("span");E.className=`${r}__more-ellipsis`,E.textContent="\u2026",s.append(T,E),o.append(s),o.append(f,y);function B(a){i.href=a.url,g.textContent=a.name,b.textContent=a.tagline,I&&console.info("[support-ukraine] banner",`${a.name}: ${a.tagline}`,a.url)}function M(){let a=K(k,A);te?(o.classList.add(`${r}--refreshing`),setTimeout(()=>{B(a),o.classList.remove(`${r}--refreshing`)},200)):B(a)}if(ee){let a=document.createElement("button");a.className=`${r}__refresh`,a.type="button",a.textContent=ie,a.style.fontSize=p,a.setAttribute("aria-label",t.refresh),a.addEventListener("click",M),o.insertBefore(a,s)}R.append(o);let U=n.element??document.body;if(l==="replace"){let a=U.querySelector(`.${r}`);a?a.replaceWith(c):U.prepend(c)}else U.prepend(c);I&&console.info("[support-ukraine] banner",`${d.name}: ${d.tagline}`,d.url),c.dataset.supportUkraine="",c.classList.add(`${r}--processed`);let $;N>0&&($=setInterval(M,N));let H=c;return H.destroy=()=>{$!==void 0&&clearInterval($),c.remove()},H}var ue="es";function Ce(e={}){return Promise.resolve(Z(ue,D,e))}export{Y as DEFAULT_CHARITIES,L as charitiesSchema,oe as charitySchema,ce as formatBannerText,Q as isRTL,X as mergeCharities,W as randomItem,Ce as supportUkraineBlock};
|
|
1
|
+
var D={supportUkraine:"Apoya a Ucrania con",more:"m\xE1s\u2026",donate:"Donar",refresh:"Mostrar siguiente charity",opensInNewTab:"(se abre en una nueva pesta\xF1a)",charities:{united24:{tagline:"Plataforma oficial de recaudaci\xF3n de Ucrania"},"come-back-alive":{tagline:"Apoyando a las fuerzas armadas ucranianas desde 2014"},"razom-for-ukraine":{tagline:"Respuesta de emergencia y ayuda humanitaria"},"ukrainian-red-cross":{tagline:"Asistencia humanitaria en zonas de conflicto"},"nova-ukraine":{tagline:"Ayuda humanitaria y defensa de derechos"},"voices-of-children":{tagline:"Apoyo psicol\xF3gico para ni\xF1os afectados por la guerra"},"prytula-foundation":{tagline:"Tecnolog\xEDa de defensa y equipamiento para Ucrania"},"medical-hilfe":{tagline:"Suministros m\xE9dicos para hospitales ucranianos"},"army-of-drones":{tagline:"Drones de reconocimiento para el frente"},"world-central-kitchen":{tagline:"Comidas frescas para personas en zonas de conflicto"},"cats-of-kyiv":{tagline:"Refugio que rescata y reubicia gatos en Kyiv"},uanimals:{tagline:"Organizaci\xF3n de rescate animal y defensa de derechos en Ucrania"},hospitallers:{tagline:"Param\xE9dicos voluntarios ucranianos que prestan primeros auxilios y evacuaci\xF3n"},"sternenko-fund":{tagline:"Suministro de drones FPV para las fuerzas de defensa ucranianas"},"life-robots-ukraine":{tagline:"Robots para la desminaci\xF3n de Ucrania"},"sirius-shelter":{tagline:"El mayor refugio de animales de Ucrania para perros y gatos"}}};var O=["military","humanitarian","animals"];function u(e,t){if(!e)throw new Error(t)}function x(e,t){u(typeof e=="string",`${t} must be a string`),u(e.length>0,`${t} must not be empty`)}function re(e,t){x(e,t);try{new URL(e)}catch{throw new Error(`${t} must be a valid URL`)}}function ne(e){return u(O.includes(e),`Invalid tag: ${String(e)}. Must be one of: ${O.join(", ")}`),e}function j(e){u(e!==null&&typeof e=="object","Charity must be an object");let t=e;return x(t.id,"id"),x(t.name,"name"),x(t.tagline,"tagline"),re(t.url,"url"),u(Array.isArray(t.tags),"tags must be an array"),u(t.tags.length>0,"tags must not be empty"),{id:t.id,name:t.name,tagline:t.tagline,url:t.url,tags:t.tags.map(n=>ne(n))}}var oe={parse:j},L={parse(e){return u(Array.isArray(e),"Charities must be an array"),e.map(t=>j(t))}};var P=[{id:"united24",name:"United24",tagline:"Official fundraising platform of Ukraine",url:"https://u24.gov.ua",tags:["humanitarian"]},{id:"come-back-alive",name:"Come Back Alive",tagline:"Supporting the Ukrainian Armed Forces since 2014",url:"https://www.comebackalive.in.ua",tags:["military"]},{id:"razom-for-ukraine",name:"Razom for Ukraine",tagline:"Emergency response and humanitarian aid",url:"https://www.razomforukraine.org",tags:["humanitarian"]},{id:"ukrainian-red-cross",name:"Ukrainian Red Cross",tagline:"Humanitarian assistance in conflict zones",url:"https://redcross.org.ua/en/",tags:["humanitarian"]},{id:"nova-ukraine",name:"Nova Ukraine",tagline:"Humanitarian aid and advocacy",url:"https://novaukraine.org",tags:["humanitarian"]},{id:"voices-of-children",name:"Voices of Children",tagline:"Psychological support for children affected by war",url:"https://voices.org.ua/en/",tags:["humanitarian"]},{id:"prytula-foundation",name:"Prytula Foundation",tagline:"Defence technology and equipment for Ukraine",url:"https://prytulafoundation.org/en",tags:["military"]},{id:"army-of-drones",name:"Army of Drones",tagline:"Reconnaissance drones for the frontline",url:"https://armyofdrones.com",tags:["military"]},{id:"world-central-kitchen",name:"World Central Kitchen",tagline:"Fresh meals for people in conflict zones",url:"https://wck.org/relief/activation-chefs-for-ukraine/",tags:["humanitarian"]},{id:"cats-of-kyiv",name:"Cats of Kyiv",tagline:"Cat shelter rescuing and rehoming cats in Kyiv",url:"https://cats.kiev.ua",tags:["animals"]},{id:"uanimals",name:"UAnimals",tagline:"Animal rescue and advocacy organization in Ukraine",url:"https://uanimals.org",tags:["animals"]},{id:"hospitallers",name:"Hospitallers",tagline:"Ukrainian voluntary paramedics providing first aid and evacuation",url:"https://www.hospitallers.org.uk",tags:["humanitarian"]},{id:"sternenko-fund",name:"Sternenko Fund",tagline:"FPV drone supply for Ukrainian defence forces",url:"https://www.sternenkofund.org",tags:["military"]},{id:"life-robots-ukraine",name:"Life Robots Ukraine",tagline:"Robots for demining Ukraine",url:"https://liferobots.com.ua",tags:["humanitarian"]},{id:"sirius-shelter",name:"Sirius",tagline:"Ukraine's largest animal shelter for dogs and cats",url:"https://dogcat.com.ua",tags:["animals"]},{id:"dignitas",name:"Dignitas",tagline:"Technology and support for Ukrainian defenders and veterans",url:"https://dignitas.fund",tags:["military"]},{id:"leleka",name:"Leleka Foundation",tagline:"Tactical medical supplies for Ukraine's frontline medics",url:"https://leleka.care/en",tags:["humanitarian"]},{id:"superhumans",name:"Superhumans Center",tagline:"Prosthetics, surgery, and rehabilitation for war survivors",url:"https://superhumans.com/en/",tags:["humanitarian"]}];var q=":host{display:block;margin:0;padding:0;border:none;font-size:16px;width:100%;min-height:2.5em;line-height:1.4;box-sizing:border-box;z-index:2147483647}.support-ukraine-block__visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}header.support-ukraine-block{margin:0;padding:0;border:none;border-radius:0;width:100%;min-height:2.5em;display:flex;align-items:center;justify-content:center;font-family:system-ui,-apple-system,sans-serif;text-decoration:none;box-sizing:border-box;line-height:1.4;overflow:visible;background:#0057b7 none}@media(prefers-color-scheme: dark){header.support-ukraine-block{background-color:gold}}header.support-ukraine-block--shift,header.support-ukraine-block--replace{position:relative}header.support-ukraine-block--overlap{position:fixed;top:0;left:0;z-index:2147483647}header.support-ukraine-block--refreshing .support-ukraine-block__link{opacity:0}header.support-ukraine-block .support-ukraine-block__link{display:inline-flex;align-items:center;flex-wrap:wrap;gap:0 .25em;text-decoration:none;flex:1;height:100%;justify-content:flex-start;text-align:left;padding:.5em 1em;box-sizing:border-box;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}@media(prefers-reduced-motion: no-preference){header.support-ukraine-block .support-ukraine-block__link{transition:opacity .2s ease-in-out}}@media(prefers-color-scheme: dark){header.support-ukraine-block .support-ukraine-block__link{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}header.support-ukraine-block .support-ukraine-block__link:hover{opacity:.9}header.support-ukraine-block .support-ukraine-block__link:focus-visible{outline:2px solid #fff;outline-offset:-2px}header.support-ukraine-block .support-ukraine-block__flag{white-space:nowrap}header.support-ukraine-block .support-ukraine-block__prefix,header.support-ukraine-block .support-ukraine-block__info,header.support-ukraine-block .support-ukraine-block__colon,header.support-ukraine-block .support-ukraine-block__tagline{min-width:0}header.support-ukraine-block .support-ukraine-block__more{display:inline-flex;align-items:center;text-decoration:none;padding:.5em 1em;box-sizing:border-box;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4);white-space:nowrap;opacity:.8}@media(prefers-color-scheme: dark){header.support-ukraine-block .support-ukraine-block__more{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}header.support-ukraine-block .support-ukraine-block__more:hover{opacity:1}header.support-ukraine-block .support-ukraine-block__more:focus-visible{outline:2px solid #fff;outline-offset:-2px}header.support-ukraine-block .support-ukraine-block__more-ellipsis{display:none}header.support-ukraine-block .support-ukraine-block__refresh{display:inline-flex;align-items:center;background:none;border:none;text-decoration:none;padding:.5em .5em .5em 1em;box-sizing:border-box;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4);white-space:nowrap;opacity:.8;cursor:pointer;font-size:inherit;line-height:1}@media(prefers-color-scheme: dark){header.support-ukraine-block .support-ukraine-block__refresh{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}header.support-ukraine-block .support-ukraine-block__refresh:hover{opacity:1}header.support-ukraine-block .support-ukraine-block__refresh:focus-visible{outline:2px solid #fff;outline-offset:-2px}header.support-ukraine-block .support-ukraine-block__name{font-weight:bold}@media(max-width: 58rem){header.support-ukraine-block .support-ukraine-block__prefix,header.support-ukraine-block .support-ukraine-block__name,header.support-ukraine-block .support-ukraine-block__colon,header.support-ukraine-block .support-ukraine-block__more,header.support-ukraine-block .support-ukraine-block__refresh{display:none}}@media(max-width: 35rem){header.support-ukraine-block .support-ukraine-block__name,header.support-ukraine-block .support-ukraine-block__colon{display:initial}header.support-ukraine-block .support-ukraine-block__tagline{display:none}}[dir=rtl] header.support-ukraine-block .support-ukraine-block__link{text-align:right;justify-content:flex-end}[dir=rtl] header.support-ukraine-block .support-ukraine-block__more{text-align:right}[dir=rtl] header.support-ukraine-block .support-ukraine-block__refresh{text-align:right}:host-context([data-theme=dark]) header.support-ukraine-block{background-color:gold}:host-context([data-theme=dark]) header.support-ukraine-block .support-ukraine-block__link{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=dark]) header.support-ukraine-block .support-ukraine-block__more{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=dark]) header.support-ukraine-block .support-ukraine-block__refresh{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=light]) header.support-ukraine-block{background-color:#0057b7}:host-context([data-theme=light]) header.support-ukraine-block .support-ukraine-block__link{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}:host-context([data-theme=light]) header.support-ukraine-block .support-ukraine-block__more{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}:host-context([data-theme=light]) header.support-ukraine-block .support-ukraine-block__refresh{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}";var Y=L.parse(P),r="support-ukraine-block",J="support-ukraine-seen",ie="\u27F3",V=`${r}__visually-hidden`;function se(){try{let e=localStorage.getItem(J);return e?new Set(JSON.parse(e)):new Set}catch{return new Set}}function le(e){try{localStorage.setItem(J,JSON.stringify([...e]))}catch{}}function G(e){let t=se();e(t),le(t)}function W(e){if(e.length===0)throw new Error("randomItem: cannot pick from an empty array");return e[Math.floor(Math.random()*e.length)]}function K(e,t){let n=e;t&&G(p=>{let h=n.filter(m=>!p.has(m.url));h.length>0?n=h:p.clear()});let l=W(n);return t&&G(p=>{p.add(l.url)}),l}function pe(e){let t=`${r}-styles`;if(e.querySelector(`#${t}`))return;let n=e.ownerDocument.createElement("style");n.id=t,n.textContent=q,e.append(n)}function X(e,t){return e.map(n=>{let l=t.charities[n.id];return l?.tagline?{...n,tagline:l.tagline}:n})}function Q(e){return(e.split("-",1)[0]??"").toLowerCase()==="ar"}function ce(e,t){return`\u{1F1FA}\u{1F1E6} ${t.supportUkraine} ${e.name}: ${e.tagline}`}function Z(e,t,n={}){let{mode:l="shift",fontSize:p="87.5%",charities:h,tags:m,dontRepeat:A=!0,isInConsole:I=!0,showRefreshButton:ee=!1,autoRefreshInterval:N=0,showRefreshAnimation:te=!1}=n,_=X(h??Y,t),k=m&&m.length>0?_.filter(a=>a.tags.some(ae=>m.includes(ae))):_;k.length===0&&(k=_);let d=K(k,A),c=document.createElement("div"),z=c.attachShadow({mode:"open"});pe(z);let o=document.createElement("header");o.className=`${r} ${r}--${l}`,o.lang=e,Q(e)&&o.setAttribute("dir","rtl");let i=document.createElement("a");i.className=`${r}__link`,i.href=d.url,i.target="_blank",i.rel="noopener noreferrer",i.style.fontSize=p;let R=`${r}-link-new-tab`,f=document.createElement("span");f.id=R,f.className=V,f.textContent=t.opensInNewTab,i.setAttribute("aria-describedby",R);let w=document.createElement("span");w.className=`${r}__flag`,w.textContent="\u{1F1FA}\u{1F1E6} ";let C=document.createElement("span");C.className=`${r}__prefix`,C.textContent=`${t.supportUkraine} `;let v=document.createElement("span");v.className=`${r}__info`;let g=document.createElement("span");g.className=`${r}__name`,g.textContent=d.name;let S=document.createElement("span");S.className=`${r}__colon`,S.textContent=": ";let b=document.createElement("span");b.className=`${r}__tagline`,b.textContent=d.tagline,v.append(g,S,b),i.append(w,C,v),o.append(i);let s=document.createElement("a");s.className=`${r}__more`,s.href="https://damian-buho.github.io/support-ukraine/",s.target="_blank",s.rel="noopener noreferrer",s.style.fontSize=p;let F=`${r}-more-new-tab`,y=document.createElement("span");y.id=F,y.className=V,y.textContent=t.opensInNewTab,s.setAttribute("aria-describedby",F);let T=document.createElement("span");T.className=`${r}__more-text`,T.textContent=t.more;let E=document.createElement("span");E.className=`${r}__more-ellipsis`,E.textContent="\u2026",s.append(T,E),o.append(s),o.append(f,y);function B(a){i.href=a.url,g.textContent=a.name,b.textContent=a.tagline,I&&console.info("[support-ukraine] banner",`${a.name}: ${a.tagline}`,a.url)}function M(){let a=K(k,A);te?(o.classList.add(`${r}--refreshing`),setTimeout(()=>{B(a),o.classList.remove(`${r}--refreshing`)},200)):B(a)}if(ee){let a=document.createElement("button");a.className=`${r}__refresh`,a.type="button",a.textContent=ie,a.style.fontSize=p,a.setAttribute("aria-label",t.refresh),a.addEventListener("click",M),o.insertBefore(a,s)}z.append(o);let U=n.element??document.body;if(l==="replace"){let a=U.querySelector(`.${r}`);a?a.replaceWith(c):U.prepend(c)}else U.prepend(c);I&&console.info("[support-ukraine] banner",`${d.name}: ${d.tagline}`,d.url),c.dataset.supportUkraine="",c.classList.add(`${r}--processed`);let $;N>0&&($=setInterval(M,N));let H=c;return H.destroy=()=>{$!==void 0&&clearInterval($),c.remove()},H}var ue="es";function Ce(e={}){return Promise.resolve(Z(ue,D,e))}export{Y as DEFAULT_CHARITIES,L as charitiesSchema,oe as charitySchema,ce as formatBannerText,Q as isRTL,X as mergeCharities,W as randomItem,Ce as supportUkraineBlock};
|
|
2
2
|
//# sourceMappingURL=es.js.map
|
package/dist/es.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/locales/es.yaml","../src/types.ts","../src/charities.yaml","../src/styles.scss","../src/banner.ts","../src/entries/es.ts"],"sourcesContent":["export default {\"supportUkraine\":\"Apoya a Ucrania con\",\"more\":\"más…\",\"donate\":\"Donar\",\"refresh\":\"Mostrar siguiente charity\",\"opensInNewTab\":\"(se abre en una nueva pestaña)\",\"charities\":{\"united24\":{\"tagline\":\"Plataforma oficial de recaudación de Ucrania\"},\"come-back-alive\":{\"tagline\":\"Apoyando a las fuerzas armadas ucranianas desde 2014\"},\"razom-for-ukraine\":{\"tagline\":\"Respuesta de emergencia y ayuda humanitaria\"},\"ukrainian-red-cross\":{\"tagline\":\"Asistencia humanitaria en zonas de conflicto\"},\"nova-ukraine\":{\"tagline\":\"Ayuda humanitaria y defensa de derechos\"},\"voices-of-children\":{\"tagline\":\"Apoyo psicológico para niños afectados por la guerra\"},\"prytula-foundation\":{\"tagline\":\"Tecnología de defensa y equipamiento para Ucrania\"},\"medical-hilfe\":{\"tagline\":\"Suministros médicos para hospitales ucranianos\"},\"army-of-drones\":{\"tagline\":\"Drones de reconocimiento para el frente\"},\"world-central-kitchen\":{\"tagline\":\"Comidas frescas para personas en zonas de conflicto\"},\"cats-of-kyiv\":{\"tagline\":\"Refugio que rescata y reubicia gatos en Kyiv\"},\"uanimals\":{\"tagline\":\"Organización de rescate animal y defensa de derechos en Ucrania\"},\"hospitallers\":{\"tagline\":\"Paramédicos voluntarios ucranianos que prestan primeros auxilios y evacuación\"},\"sternenko-fund\":{\"tagline\":\"Suministro de drones FPV para las fuerzas de defensa ucranianas\"},\"life-robots-ukraine\":{\"tagline\":\"Robots para la desminación de Ucrania\"},\"sirius-shelter\":{\"tagline\":\"El mayor refugio de animales de Ucrania para perros y gatos\"}}}","// SPDX-FileCopyrightText: 2026 Damián Búho <damian.buho@proton.me>\n//\n// SPDX-License-Identifier: MIT\n\n/**\nCategory tag for a charity.\n*/\nexport const VALID_TAGS = ['military', 'humanitarian', 'animals'] as const\nexport type CharityTag = (typeof VALID_TAGS)[number]\n\nfunction assert(condition: unknown, message: string): asserts condition {\n if (!condition) throw new Error(message)\n}\n\nfunction assertNonEmptyString(value: unknown, field: string): void {\n assert(typeof value === 'string', `${field} must be a string`)\n assert(value.length > 0, `${field} must not be empty`)\n}\n\nfunction assertUrl(value: unknown, field: string): void {\n assertNonEmptyString(value, field)\n try {\n new URL(value)\n } catch {\n throw new Error(`${field} must be a valid URL`)\n }\n}\n\nfunction parseCharityTag(value: unknown): CharityTag {\n assert(\n VALID_TAGS.includes(value as CharityTag),\n `Invalid tag: ${String(value)}. Must be one of: ${VALID_TAGS.join(', ')}`\n )\n return value as CharityTag\n}\n\n/**\nA charity foundation that can appear in the banner.\n*/\nexport interface Charity {\n id: string\n name: string\n tagline: string\n url: string\n tags: CharityTag[]\n}\n\nfunction parseCharity(value: unknown): Charity {\n assert(value !== null && typeof value === 'object', 'Charity must be an object')\n const record = value as Record<string, unknown>\n assertNonEmptyString(record.id, 'id')\n assertNonEmptyString(record.name, 'name')\n assertNonEmptyString(record.tagline, 'tagline')\n assertUrl(record.url, 'url')\n assert(Array.isArray(record.tags), 'tags must be an array')\n assert(record.tags.length > 0, 'tags must not be empty')\n return {\n id: record.id,\n name: record.name,\n tagline: record.tagline,\n url: record.url,\n tags: record.tags.map(tag => parseCharityTag(tag))\n }\n}\n\nexport const charitySchema = {\n parse: parseCharity\n}\n\nexport const charitiesSchema = {\n parse(value: unknown): Charity[] {\n assert(Array.isArray(value), 'Charities must be an array')\n return value.map(item => parseCharity(item))\n }\n}\n\n/**\nTranslated UI strings and charity taglines for a single locale.\n*/\nexport interface LocaleMessages {\n /**\n Banner prefix, e.g. \"Support Ukraine\".\n */\n supportUkraine: string\n /**\n \"More…\" link text.\n */\n more: string\n /**\n Card donate button text, e.g. \"Donate\".\n */\n donate: string\n /**\n Refresh button aria-label, e.g. \"Show next charity\".\n */\n refresh: string\n /**\n Text appended to external links for screen readers, e.g. \"(opens in a new tab)\".\n */\n opensInNewTab: string\n /**\n Translated taglines keyed by charity id. Missing keys fall back to EN.\n */\n charities: Record<string, { tagline: string }>\n}\n\nexport interface SupportUkraineBlockOptions {\n /**\n Target mount element. If omitted the banner is prepended to document.body.\n */\n element?: HTMLElement\n /**\n Positioning mode: 'shift' pushes content down, 'overlap' floats on top, 'replace' swaps a same-class placeholder.\n */\n mode?: 'shift' | 'overlap' | 'replace'\n /**\n Font size (default '87.5%'). Percentages resolve against the widget's fixed 16px host box, so document root scaling is ignored; rem would inherit it.\n */\n fontSize?: string\n /**\n * Custom charity list. If omitted the built-in defaults are used.\n */\n charities?: Charity[]\n /**\n * Category tags to filter by. If omitted all charities are shown.\n */\n tags?: CharityTag[]\n /**\n Avoid repeating charities across page loads using localStorage.\n */\n dontRepeat?: boolean\n /**\n Log a message to the dev console.\n */\n isInConsole?: boolean\n /**\n Show a refresh button that loads the next random charity.\n */\n showRefreshButton?: boolean\n /**\n Auto-refresh interval in milliseconds. 0 = off (default). Set e.g. 15000 for 15 seconds.\n */\n autoRefreshInterval?: number\n /**\n Show a fade animation when the charity changes (respects prefers-reduced-motion).\n */\n showRefreshAnimation?: boolean\n /**\n * Override the auto-detected locale (BCP 47 language tag).\n * If omitted the locale is detected from `navigator.language`.\n */\n locale?: string\n}\n","export default [{\"id\":\"united24\",\"name\":\"United24\",\"tagline\":\"Official fundraising platform of Ukraine\",\"url\":\"https://u24.gov.ua\",\"tags\":[\"humanitarian\"]},{\"id\":\"come-back-alive\",\"name\":\"Come Back Alive\",\"tagline\":\"Supporting the Ukrainian Armed Forces since 2014\",\"url\":\"https://www.comebackalive.in.ua\",\"tags\":[\"military\"]},{\"id\":\"razom-for-ukraine\",\"name\":\"Razom for Ukraine\",\"tagline\":\"Emergency response and humanitarian aid\",\"url\":\"https://www.razomforukraine.org\",\"tags\":[\"humanitarian\"]},{\"id\":\"ukrainian-red-cross\",\"name\":\"Ukrainian Red Cross\",\"tagline\":\"Humanitarian assistance in conflict zones\",\"url\":\"https://redcross.org.ua/en/\",\"tags\":[\"humanitarian\"]},{\"id\":\"nova-ukraine\",\"name\":\"Nova Ukraine\",\"tagline\":\"Humanitarian aid and advocacy\",\"url\":\"https://novaukraine.org\",\"tags\":[\"humanitarian\"]},{\"id\":\"voices-of-children\",\"name\":\"Voices of Children\",\"tagline\":\"Psychological support for children affected by war\",\"url\":\"https://voices.org.ua/en/\",\"tags\":[\"humanitarian\"]},{\"id\":\"prytula-foundation\",\"name\":\"Prytula Foundation\",\"tagline\":\"Defence technology and equipment for Ukraine\",\"url\":\"https://prytulafoundation.org/en\",\"tags\":[\"military\"]},{\"id\":\"army-of-drones\",\"name\":\"Army of Drones\",\"tagline\":\"Reconnaissance drones for the frontline\",\"url\":\"https://armyofdrones.com\",\"tags\":[\"military\"]},{\"id\":\"world-central-kitchen\",\"name\":\"World Central Kitchen\",\"tagline\":\"Fresh meals for people in conflict zones\",\"url\":\"https://wck.org/relief/activation-chefs-for-ukraine/\",\"tags\":[\"humanitarian\"]},{\"id\":\"cats-of-kyiv\",\"name\":\"Cats of Kyiv\",\"tagline\":\"Cat shelter rescuing and rehoming cats in Kyiv\",\"url\":\"https://cats.kiev.ua\",\"tags\":[\"animals\"]},{\"id\":\"uanimals\",\"name\":\"UAnimals\",\"tagline\":\"Animal rescue and advocacy organization in Ukraine\",\"url\":\"https://uanimals.org\",\"tags\":[\"animals\"]},{\"id\":\"hospitallers\",\"name\":\"Hospitallers\",\"tagline\":\"Ukrainian voluntary paramedics providing first aid and evacuation\",\"url\":\"https://www.hospitallers.org.uk\",\"tags\":[\"humanitarian\"]},{\"id\":\"sternenko-fund\",\"name\":\"Sternenko Fund\",\"tagline\":\"FPV drone supply for Ukrainian defence forces\",\"url\":\"https://www.sternenkofund.org\",\"tags\":[\"military\"]},{\"id\":\"life-robots-ukraine\",\"name\":\"Life Robots Ukraine\",\"tagline\":\"Robots for demining Ukraine\",\"url\":\"https://liferobots.com.ua\",\"tags\":[\"humanitarian\"]},{\"id\":\"sirius-shelter\",\"name\":\"Sirius\",\"tagline\":\"Ukraine's largest animal shelter for dogs and cats\",\"url\":\"https://dogcat.com.ua\",\"tags\":[\"animals\"]},{\"id\":\"dignitas\",\"name\":\"Dignitas\",\"tagline\":\"Technology and support for Ukrainian defenders and veterans\",\"url\":\"https://dignitas.fund\",\"tags\":[\"military\"]},{\"id\":\"leleka\",\"name\":\"Leleka Foundation\",\"tagline\":\"Tactical medical supplies for Ukraine's frontline medics\",\"url\":\"https://leleka.care/en\",\"tags\":[\"humanitarian\"]},{\"id\":\"superhumans\",\"name\":\"Superhumans Center\",\"tagline\":\"Prosthetics, surgery, and rehabilitation for war survivors\",\"url\":\"https://superhumans.com/en/\",\"tags\":[\"humanitarian\"]}]","export default \":host{display:block;margin:0;padding:0;border:none;font-size:16px;width:100%;min-height:2.5em;line-height:1.4;box-sizing:border-box;z-index:2147483647}.support-ukraine-block__visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}header.support-ukraine-block{margin:0;padding:0;border:none;border-radius:0;width:100%;min-height:2.5em;display:flex;align-items:center;justify-content:center;font-family:system-ui,-apple-system,sans-serif;text-decoration:none;box-sizing:border-box;line-height:1.4;overflow:visible;background:#0057b7 none}@media(prefers-color-scheme: dark){header.support-ukraine-block{background-color:gold}}header.support-ukraine-block--shift,header.support-ukraine-block--replace{position:relative}header.support-ukraine-block--overlap{position:fixed;top:0;left:0}header.support-ukraine-block--refreshing .support-ukraine-block__link{opacity:0}header.support-ukraine-block .support-ukraine-block__link{display:inline-flex;align-items:center;flex-wrap:wrap;gap:0 .25em;text-decoration:none;flex:1;height:100%;justify-content:flex-start;text-align:left;padding:.5em 1em;box-sizing:border-box;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}@media(prefers-reduced-motion: no-preference){header.support-ukraine-block .support-ukraine-block__link{transition:opacity .2s ease-in-out}}@media(prefers-color-scheme: dark){header.support-ukraine-block .support-ukraine-block__link{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}header.support-ukraine-block .support-ukraine-block__link:hover{opacity:.9}header.support-ukraine-block .support-ukraine-block__link:focus-visible{outline:2px solid #fff;outline-offset:-2px}header.support-ukraine-block .support-ukraine-block__flag{white-space:nowrap}header.support-ukraine-block .support-ukraine-block__prefix,header.support-ukraine-block .support-ukraine-block__info,header.support-ukraine-block .support-ukraine-block__colon,header.support-ukraine-block .support-ukraine-block__tagline{min-width:0}header.support-ukraine-block .support-ukraine-block__more{display:inline-flex;align-items:center;text-decoration:none;padding:.5em 1em;box-sizing:border-box;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4);white-space:nowrap;opacity:.8}@media(prefers-color-scheme: dark){header.support-ukraine-block .support-ukraine-block__more{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}header.support-ukraine-block .support-ukraine-block__more:hover{opacity:1}header.support-ukraine-block .support-ukraine-block__more:focus-visible{outline:2px solid #fff;outline-offset:-2px}header.support-ukraine-block .support-ukraine-block__more-ellipsis{display:none}header.support-ukraine-block .support-ukraine-block__refresh{display:inline-flex;align-items:center;background:none;border:none;text-decoration:none;padding:.5em .5em .5em 1em;box-sizing:border-box;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4);white-space:nowrap;opacity:.8;cursor:pointer;font-size:inherit;line-height:1}@media(prefers-color-scheme: dark){header.support-ukraine-block .support-ukraine-block__refresh{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}header.support-ukraine-block .support-ukraine-block__refresh:hover{opacity:1}header.support-ukraine-block .support-ukraine-block__refresh:focus-visible{outline:2px solid #fff;outline-offset:-2px}header.support-ukraine-block .support-ukraine-block__name{font-weight:bold}@media(max-width: 58rem){header.support-ukraine-block .support-ukraine-block__prefix,header.support-ukraine-block .support-ukraine-block__name,header.support-ukraine-block .support-ukraine-block__colon,header.support-ukraine-block .support-ukraine-block__more,header.support-ukraine-block .support-ukraine-block__refresh{display:none}}@media(max-width: 35rem){header.support-ukraine-block .support-ukraine-block__name,header.support-ukraine-block .support-ukraine-block__colon{display:initial}header.support-ukraine-block .support-ukraine-block__tagline{display:none}}[dir=rtl] header.support-ukraine-block .support-ukraine-block__link{text-align:right;justify-content:flex-end}[dir=rtl] header.support-ukraine-block .support-ukraine-block__more{text-align:right}[dir=rtl] header.support-ukraine-block .support-ukraine-block__refresh{text-align:right}:host-context([data-theme=dark]) header.support-ukraine-block{background-color:gold}:host-context([data-theme=dark]) header.support-ukraine-block .support-ukraine-block__link{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=dark]) header.support-ukraine-block .support-ukraine-block__more{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=dark]) header.support-ukraine-block .support-ukraine-block__refresh{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=light]) header.support-ukraine-block{background-color:#0057b7}:host-context([data-theme=light]) header.support-ukraine-block .support-ukraine-block__link{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}:host-context([data-theme=light]) header.support-ukraine-block .support-ukraine-block__more{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}:host-context([data-theme=light]) header.support-ukraine-block .support-ukraine-block__refresh{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}\"","// SPDX-FileCopyrightText: 2026 Damián Búho <damian.buho@proton.me>\n//\n// SPDX-License-Identifier: MIT\n\nimport {\n charitiesSchema,\n type Charity,\n type LocaleMessages,\n type SupportUkraineBlockOptions\n} from './types.js'\nimport rawCharities from './charities.yaml'\nimport styles from './styles.scss'\n\nexport type { Charity, CharityTag, SupportUkraineBlockOptions, LocaleMessages } from './types.js'\n\nexport const DEFAULT_CHARITIES: Charity[] = charitiesSchema.parse(rawCharities)\n\nconst CSS_PREFIX = 'support-ukraine-block'\nconst STORAGE_KEY = 'support-ukraine-seen'\nconst REFRESH_GLYPH = '\\u{27F3}'\nconst VISUALLY_HIDDEN_CLASS = `${CSS_PREFIX}__visually-hidden`\n\nfunction readSeen(): Set<string> {\n try {\n const raw = localStorage.getItem(STORAGE_KEY)\n return raw ? new Set(JSON.parse(raw) as string[]) : new Set()\n } catch {\n return new Set()\n }\n}\n\nfunction writeSeen(seen: Set<string>): void {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify([...seen]))\n } catch {\n // localStorage unavailable — degrade silently\n }\n}\n\nfunction updateSeen(mutate: (seen: Set<string>) => void): void {\n const seen = readSeen()\n mutate(seen)\n writeSeen(seen)\n}\n\n/**\n * Pick a random item from an array.\n *\n * @internal\n */\nexport function randomItem<T>(items: T[]): T {\n if (items.length === 0) {\n throw new Error('randomItem: cannot pick from an empty array')\n }\n return items[Math.floor(Math.random() * items.length)]!\n}\n\nfunction pickCharity(candidates: Charity[], shouldAvoidRepeat: boolean): Charity {\n let pool = candidates\n\n if (shouldAvoidRepeat) {\n updateSeen(seen => {\n const unseen = pool.filter(c => !seen.has(c.url))\n if (unseen.length > 0) {\n pool = unseen\n } else {\n seen.clear()\n }\n })\n }\n\n const charity = randomItem(pool)\n\n if (shouldAvoidRepeat) {\n updateSeen(seen => {\n seen.add(charity.url)\n })\n }\n\n return charity\n}\n\nfunction injectShadowStyles(shadowRoot: ShadowRoot): void {\n const id = `${CSS_PREFIX}-styles`\n if (shadowRoot.querySelector(`#${id}`)) {\n return\n }\n\n const style = shadowRoot.ownerDocument.createElement('style')\n style.id = id\n style.textContent = styles\n shadowRoot.append(style)\n}\n\n/**\n * Merge base charities with locale-specific translations.\n */\nexport function mergeCharities(base: readonly Charity[], locale: LocaleMessages): Charity[] {\n return base.map(charity => {\n const translated = locale.charities[charity.id]\n if (translated?.tagline) {\n return { ...charity, tagline: translated.tagline }\n }\n return charity\n })\n}\n\nexport function isRTL(lang: string): boolean {\n const base = (lang.split('-', 1)[0] ?? '').toLowerCase()\n return base === 'ar'\n}\n\nexport function formatBannerText(charity: Charity, messages: LocaleMessages): string {\n return `\\u{1F1FA}\\u{1F1E6} ${messages.supportUkraine} ${charity.name}: ${charity.tagline}`\n}\n\n/**\n * Mount the banner with already-resolved `lang` and `messages`.\n * Shared by the auto-detect build (`src/index.ts`) and the per-locale builds (`src/entries/*.ts`).\n */\nexport function mountBanner(\n lang: string,\n messages: LocaleMessages,\n options: SupportUkraineBlockOptions = {}\n): HTMLElement & { destroy: () => void } {\n const {\n mode = 'shift',\n fontSize = '87.5%',\n charities,\n tags,\n dontRepeat = true,\n isInConsole = true,\n showRefreshButton = false,\n autoRefreshInterval = 0,\n showRefreshAnimation = false\n } = options\n\n const baseCharities = charities ?? DEFAULT_CHARITIES\n const localizedCharities = mergeCharities(baseCharities, messages)\n\n let candidates =\n tags && tags.length > 0\n ? localizedCharities.filter(charity => charity.tags.some(t => tags.includes(t)))\n : localizedCharities\n\n if (candidates.length === 0) {\n candidates = localizedCharities\n }\n\n const charity = pickCharity(candidates, dontRepeat)\n\n const host = document.createElement('div')\n\n const shadow = host.attachShadow({ mode: 'open' })\n injectShadowStyles(shadow)\n\n const banner = document.createElement('header')\n banner.className = `${CSS_PREFIX} ${CSS_PREFIX}--${mode}`\n banner.lang = lang\n\n if (isRTL(lang)) {\n banner.setAttribute('dir', 'rtl')\n }\n\n const link = document.createElement('a')\n link.className = `${CSS_PREFIX}__link`\n link.href = charity.url\n link.target = '_blank'\n link.rel = 'noopener noreferrer'\n link.style.fontSize = fontSize\n\n const linkNewTabId = `${CSS_PREFIX}-link-new-tab`\n const linkNewTabHint = document.createElement('span')\n linkNewTabHint.id = linkNewTabId\n linkNewTabHint.className = VISUALLY_HIDDEN_CLASS\n linkNewTabHint.textContent = messages.opensInNewTab\n link.setAttribute('aria-describedby', linkNewTabId)\n\n const flag = document.createElement('span')\n flag.className = `${CSS_PREFIX}__flag`\n flag.textContent = `\\u{1F1FA}\\u{1F1E6} `\n\n const prefix = document.createElement('span')\n prefix.className = `${CSS_PREFIX}__prefix`\n prefix.textContent = `${messages.supportUkraine} `\n\n const info = document.createElement('span')\n info.className = `${CSS_PREFIX}__info`\n\n const name = document.createElement('span')\n name.className = `${CSS_PREFIX}__name`\n name.textContent = charity.name\n\n const colon = document.createElement('span')\n colon.className = `${CSS_PREFIX}__colon`\n colon.textContent = ': '\n\n const tagline = document.createElement('span')\n tagline.className = `${CSS_PREFIX}__tagline`\n tagline.textContent = charity.tagline\n\n info.append(name, colon, tagline)\n\n link.append(flag, prefix, info)\n banner.append(link)\n\n const moreLink = document.createElement('a')\n moreLink.className = `${CSS_PREFIX}__more`\n moreLink.href = 'https://damian-buho.github.io/support-ukraine/'\n moreLink.target = '_blank'\n moreLink.rel = 'noopener noreferrer'\n moreLink.style.fontSize = fontSize\n\n const moreNewTabId = `${CSS_PREFIX}-more-new-tab`\n const moreNewTabHint = document.createElement('span')\n moreNewTabHint.id = moreNewTabId\n moreNewTabHint.className = VISUALLY_HIDDEN_CLASS\n moreNewTabHint.textContent = messages.opensInNewTab\n moreLink.setAttribute('aria-describedby', moreNewTabId)\n\n const moreText = document.createElement('span')\n moreText.className = `${CSS_PREFIX}__more-text`\n moreText.textContent = messages.more\n\n const moreEllipsis = document.createElement('span')\n moreEllipsis.className = `${CSS_PREFIX}__more-ellipsis`\n moreEllipsis.textContent = '\\u{2026}'\n\n moreLink.append(moreText, moreEllipsis)\n banner.append(moreLink)\n banner.append(linkNewTabHint, moreNewTabHint)\n\n function applyNext(next: Charity): void {\n link.href = next.url\n name.textContent = next.name\n tagline.textContent = next.tagline\n if (isInConsole) {\n console.info('[support-ukraine] banner', `${next.name}: ${next.tagline}`, next.url)\n }\n }\n\n function updateCharity(): void {\n const next = pickCharity(candidates, dontRepeat)\n if (showRefreshAnimation) {\n banner.classList.add(`${CSS_PREFIX}--refreshing`)\n setTimeout(() => {\n applyNext(next)\n banner.classList.remove(`${CSS_PREFIX}--refreshing`)\n }, 200)\n } else {\n applyNext(next)\n }\n }\n\n if (showRefreshButton) {\n const refreshButton = document.createElement('button')\n refreshButton.className = `${CSS_PREFIX}__refresh`\n refreshButton.type = 'button'\n refreshButton.textContent = REFRESH_GLYPH\n refreshButton.style.fontSize = fontSize\n refreshButton.setAttribute('aria-label', messages.refresh)\n refreshButton.addEventListener('click', updateCharity)\n // eslint-disable-next-line unicorn/prefer-modern-dom-apis\n banner.insertBefore(refreshButton, moreLink)\n }\n\n shadow.append(banner)\n\n const mount = options.element ?? document.body\n\n if (mode === 'replace') {\n const placeholder = mount.querySelector<HTMLElement>(`.${CSS_PREFIX}`)\n if (placeholder) {\n placeholder.replaceWith(host)\n } else {\n mount.prepend(host)\n }\n } else {\n mount.prepend(host)\n }\n\n if (isInConsole) {\n console.info('[support-ukraine] banner', `${charity.name}: ${charity.tagline}`, charity.url)\n }\n\n host.dataset.supportUkraine = ''\n host.classList.add(`${CSS_PREFIX}--processed`)\n\n let intervalId: ReturnType<typeof setInterval> | undefined\n if (autoRefreshInterval > 0) {\n intervalId = setInterval(updateCharity, autoRefreshInterval)\n }\n\n const instance = host as HTMLElement & { destroy: () => void }\n instance.destroy = () => {\n if (intervalId !== undefined) {\n clearInterval(intervalId)\n }\n host.remove()\n }\n\n return instance\n}\n","// SPDX-FileCopyrightText: 2026 Damián Búho <damian.buho@proton.me>\n//\n// SPDX-License-Identifier: MIT\n\nimport messages from '../locales/es.yaml'\nimport { mountBanner } from '../banner.js'\nimport type { LocaleMessages, SupportUkraineBlockOptions } from '../types.js'\n\nexport type { Charity, CharityTag, SupportUkraineBlockOptions } from '../types.js'\nexport { charitySchema, charitiesSchema } from '../types.js'\nexport {\n DEFAULT_CHARITIES,\n mergeCharities,\n isRTL,\n formatBannerText,\n randomItem\n} from '../banner.js'\nexport type { SupportedLocale } from '../locales/index.js'\n\nconst LANG = 'es'\n\n/**\n * Localized `supportUkraineBlock` with `es` baked in.\n *\n * This build is self-contained — the locale messages are bundled inline, so\n * no second network request is needed. For optimal Core Web Vitals, load\n * only the locale you need:\n *\n * ```ts\n * import { supportUkraineBlock } from '@damian-buho/support-ukraine/es'\n * await supportUkraineBlock()\n * ```\n *\n * The `locale` option is ignored in this build (the bundle is already\n * localized). Use the auto-detect build (`@damian-buho/support-ukraine`)\n * if you need runtime locale switching.\n */\nexport function supportUkraineBlock(\n options: SupportUkraineBlockOptions = {}\n): Promise<HTMLElement> {\n return Promise.resolve(mountBanner(LANG, messages as unknown as LocaleMessages, options))\n}\n"],"mappings":"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","names":["es_default","VALID_TAGS","assert","condition","message","assertNonEmptyString","value","field","assertUrl","parseCharityTag","parseCharity","record","tag","charitySchema","charitiesSchema","item","charities_default","styles_default","DEFAULT_CHARITIES","charitiesSchema","charities_default","CSS_PREFIX","STORAGE_KEY","REFRESH_GLYPH","VISUALLY_HIDDEN_CLASS","readSeen","raw","writeSeen","seen","updateSeen","mutate","randomItem","items","pickCharity","candidates","shouldAvoidRepeat","pool","unseen","c","charity","injectShadowStyles","shadowRoot","id","style","styles_default","mergeCharities","base","locale","translated","isRTL","lang","formatBannerText","messages","mountBanner","options","mode","fontSize","charities","tags","dontRepeat","isInConsole","showRefreshButton","autoRefreshInterval","showRefreshAnimation","localizedCharities","t","host","shadow","banner","link","linkNewTabId","linkNewTabHint","flag","prefix","info","name","colon","tagline","moreLink","moreNewTabId","moreNewTabHint","moreText","moreEllipsis","applyNext","next","updateCharity","refreshButton","mount","placeholder","intervalId","instance","LANG","supportUkraineBlock","options","mountBanner","es_default"]}
|
|
1
|
+
{"version":3,"sources":["../src/locales/es.yaml","../src/types.ts","../src/charities.yaml","../src/styles.scss","../src/banner.ts","../src/entries/es.ts"],"sourcesContent":["export default {\"supportUkraine\":\"Apoya a Ucrania con\",\"more\":\"más…\",\"donate\":\"Donar\",\"refresh\":\"Mostrar siguiente charity\",\"opensInNewTab\":\"(se abre en una nueva pestaña)\",\"charities\":{\"united24\":{\"tagline\":\"Plataforma oficial de recaudación de Ucrania\"},\"come-back-alive\":{\"tagline\":\"Apoyando a las fuerzas armadas ucranianas desde 2014\"},\"razom-for-ukraine\":{\"tagline\":\"Respuesta de emergencia y ayuda humanitaria\"},\"ukrainian-red-cross\":{\"tagline\":\"Asistencia humanitaria en zonas de conflicto\"},\"nova-ukraine\":{\"tagline\":\"Ayuda humanitaria y defensa de derechos\"},\"voices-of-children\":{\"tagline\":\"Apoyo psicológico para niños afectados por la guerra\"},\"prytula-foundation\":{\"tagline\":\"Tecnología de defensa y equipamiento para Ucrania\"},\"medical-hilfe\":{\"tagline\":\"Suministros médicos para hospitales ucranianos\"},\"army-of-drones\":{\"tagline\":\"Drones de reconocimiento para el frente\"},\"world-central-kitchen\":{\"tagline\":\"Comidas frescas para personas en zonas de conflicto\"},\"cats-of-kyiv\":{\"tagline\":\"Refugio que rescata y reubicia gatos en Kyiv\"},\"uanimals\":{\"tagline\":\"Organización de rescate animal y defensa de derechos en Ucrania\"},\"hospitallers\":{\"tagline\":\"Paramédicos voluntarios ucranianos que prestan primeros auxilios y evacuación\"},\"sternenko-fund\":{\"tagline\":\"Suministro de drones FPV para las fuerzas de defensa ucranianas\"},\"life-robots-ukraine\":{\"tagline\":\"Robots para la desminación de Ucrania\"},\"sirius-shelter\":{\"tagline\":\"El mayor refugio de animales de Ucrania para perros y gatos\"}}}","// SPDX-FileCopyrightText: 2026 Damián Búho <damian.buho@proton.me>\n//\n// SPDX-License-Identifier: MIT\n\n/**\nCategory tag for a charity.\n*/\nexport const VALID_TAGS = ['military', 'humanitarian', 'animals'] as const\nexport type CharityTag = (typeof VALID_TAGS)[number]\n\nfunction assert(condition: unknown, message: string): asserts condition {\n if (!condition) throw new Error(message)\n}\n\nfunction assertNonEmptyString(value: unknown, field: string): void {\n assert(typeof value === 'string', `${field} must be a string`)\n assert(value.length > 0, `${field} must not be empty`)\n}\n\nfunction assertUrl(value: unknown, field: string): void {\n assertNonEmptyString(value, field)\n try {\n new URL(value)\n } catch {\n throw new Error(`${field} must be a valid URL`)\n }\n}\n\nfunction parseCharityTag(value: unknown): CharityTag {\n assert(\n VALID_TAGS.includes(value as CharityTag),\n `Invalid tag: ${String(value)}. Must be one of: ${VALID_TAGS.join(', ')}`\n )\n return value as CharityTag\n}\n\n/**\nA charity foundation that can appear in the banner.\n*/\nexport interface Charity {\n id: string\n name: string\n tagline: string\n url: string\n tags: CharityTag[]\n}\n\nfunction parseCharity(value: unknown): Charity {\n assert(value !== null && typeof value === 'object', 'Charity must be an object')\n const record = value as Record<string, unknown>\n assertNonEmptyString(record.id, 'id')\n assertNonEmptyString(record.name, 'name')\n assertNonEmptyString(record.tagline, 'tagline')\n assertUrl(record.url, 'url')\n assert(Array.isArray(record.tags), 'tags must be an array')\n assert(record.tags.length > 0, 'tags must not be empty')\n return {\n id: record.id,\n name: record.name,\n tagline: record.tagline,\n url: record.url,\n tags: record.tags.map(tag => parseCharityTag(tag))\n }\n}\n\nexport const charitySchema = {\n parse: parseCharity\n}\n\nexport const charitiesSchema = {\n parse(value: unknown): Charity[] {\n assert(Array.isArray(value), 'Charities must be an array')\n return value.map(item => parseCharity(item))\n }\n}\n\n/**\nTranslated UI strings and charity taglines for a single locale.\n*/\nexport interface LocaleMessages {\n /**\n Banner prefix, e.g. \"Support Ukraine\".\n */\n supportUkraine: string\n /**\n \"More…\" link text.\n */\n more: string\n /**\n Card donate button text, e.g. \"Donate\".\n */\n donate: string\n /**\n Refresh button aria-label, e.g. \"Show next charity\".\n */\n refresh: string\n /**\n Text appended to external links for screen readers, e.g. \"(opens in a new tab)\".\n */\n opensInNewTab: string\n /**\n Translated taglines keyed by charity id. Missing keys fall back to EN.\n */\n charities: Record<string, { tagline: string }>\n}\n\nexport interface SupportUkraineBlockOptions {\n /**\n Target mount element. If omitted the banner is prepended to document.body.\n */\n element?: HTMLElement\n /**\n Positioning mode: 'shift' pushes content down, 'overlap' floats on top, 'replace' swaps a same-class placeholder.\n */\n mode?: 'shift' | 'overlap' | 'replace'\n /**\n Font size (default '87.5%'). Percentages resolve against the widget's fixed 16px host box, so document root scaling is ignored; rem would inherit it.\n */\n fontSize?: string\n /**\n * Custom charity list. If omitted the built-in defaults are used.\n */\n charities?: Charity[]\n /**\n * Category tags to filter by. If omitted all charities are shown.\n */\n tags?: CharityTag[]\n /**\n Avoid repeating charities across page loads using localStorage.\n */\n dontRepeat?: boolean\n /**\n Log a message to the dev console.\n */\n isInConsole?: boolean\n /**\n Show a refresh button that loads the next random charity.\n */\n showRefreshButton?: boolean\n /**\n Auto-refresh interval in milliseconds. 0 = off (default). Set e.g. 15000 for 15 seconds.\n */\n autoRefreshInterval?: number\n /**\n Show a fade animation when the charity changes (respects prefers-reduced-motion).\n */\n showRefreshAnimation?: boolean\n /**\n * Override the auto-detected locale (BCP 47 language tag).\n * If omitted the locale is detected from `navigator.language`.\n */\n locale?: string\n}\n","export default [{\"id\":\"united24\",\"name\":\"United24\",\"tagline\":\"Official fundraising platform of Ukraine\",\"url\":\"https://u24.gov.ua\",\"tags\":[\"humanitarian\"]},{\"id\":\"come-back-alive\",\"name\":\"Come Back Alive\",\"tagline\":\"Supporting the Ukrainian Armed Forces since 2014\",\"url\":\"https://www.comebackalive.in.ua\",\"tags\":[\"military\"]},{\"id\":\"razom-for-ukraine\",\"name\":\"Razom for Ukraine\",\"tagline\":\"Emergency response and humanitarian aid\",\"url\":\"https://www.razomforukraine.org\",\"tags\":[\"humanitarian\"]},{\"id\":\"ukrainian-red-cross\",\"name\":\"Ukrainian Red Cross\",\"tagline\":\"Humanitarian assistance in conflict zones\",\"url\":\"https://redcross.org.ua/en/\",\"tags\":[\"humanitarian\"]},{\"id\":\"nova-ukraine\",\"name\":\"Nova Ukraine\",\"tagline\":\"Humanitarian aid and advocacy\",\"url\":\"https://novaukraine.org\",\"tags\":[\"humanitarian\"]},{\"id\":\"voices-of-children\",\"name\":\"Voices of Children\",\"tagline\":\"Psychological support for children affected by war\",\"url\":\"https://voices.org.ua/en/\",\"tags\":[\"humanitarian\"]},{\"id\":\"prytula-foundation\",\"name\":\"Prytula Foundation\",\"tagline\":\"Defence technology and equipment for Ukraine\",\"url\":\"https://prytulafoundation.org/en\",\"tags\":[\"military\"]},{\"id\":\"army-of-drones\",\"name\":\"Army of Drones\",\"tagline\":\"Reconnaissance drones for the frontline\",\"url\":\"https://armyofdrones.com\",\"tags\":[\"military\"]},{\"id\":\"world-central-kitchen\",\"name\":\"World Central Kitchen\",\"tagline\":\"Fresh meals for people in conflict zones\",\"url\":\"https://wck.org/relief/activation-chefs-for-ukraine/\",\"tags\":[\"humanitarian\"]},{\"id\":\"cats-of-kyiv\",\"name\":\"Cats of Kyiv\",\"tagline\":\"Cat shelter rescuing and rehoming cats in Kyiv\",\"url\":\"https://cats.kiev.ua\",\"tags\":[\"animals\"]},{\"id\":\"uanimals\",\"name\":\"UAnimals\",\"tagline\":\"Animal rescue and advocacy organization in Ukraine\",\"url\":\"https://uanimals.org\",\"tags\":[\"animals\"]},{\"id\":\"hospitallers\",\"name\":\"Hospitallers\",\"tagline\":\"Ukrainian voluntary paramedics providing first aid and evacuation\",\"url\":\"https://www.hospitallers.org.uk\",\"tags\":[\"humanitarian\"]},{\"id\":\"sternenko-fund\",\"name\":\"Sternenko Fund\",\"tagline\":\"FPV drone supply for Ukrainian defence forces\",\"url\":\"https://www.sternenkofund.org\",\"tags\":[\"military\"]},{\"id\":\"life-robots-ukraine\",\"name\":\"Life Robots Ukraine\",\"tagline\":\"Robots for demining Ukraine\",\"url\":\"https://liferobots.com.ua\",\"tags\":[\"humanitarian\"]},{\"id\":\"sirius-shelter\",\"name\":\"Sirius\",\"tagline\":\"Ukraine's largest animal shelter for dogs and cats\",\"url\":\"https://dogcat.com.ua\",\"tags\":[\"animals\"]},{\"id\":\"dignitas\",\"name\":\"Dignitas\",\"tagline\":\"Technology and support for Ukrainian defenders and veterans\",\"url\":\"https://dignitas.fund\",\"tags\":[\"military\"]},{\"id\":\"leleka\",\"name\":\"Leleka Foundation\",\"tagline\":\"Tactical medical supplies for Ukraine's frontline medics\",\"url\":\"https://leleka.care/en\",\"tags\":[\"humanitarian\"]},{\"id\":\"superhumans\",\"name\":\"Superhumans Center\",\"tagline\":\"Prosthetics, surgery, and rehabilitation for war survivors\",\"url\":\"https://superhumans.com/en/\",\"tags\":[\"humanitarian\"]}]","export default \":host{display:block;margin:0;padding:0;border:none;font-size:16px;width:100%;min-height:2.5em;line-height:1.4;box-sizing:border-box;z-index:2147483647}.support-ukraine-block__visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}header.support-ukraine-block{margin:0;padding:0;border:none;border-radius:0;width:100%;min-height:2.5em;display:flex;align-items:center;justify-content:center;font-family:system-ui,-apple-system,sans-serif;text-decoration:none;box-sizing:border-box;line-height:1.4;overflow:visible;background:#0057b7 none}@media(prefers-color-scheme: dark){header.support-ukraine-block{background-color:gold}}header.support-ukraine-block--shift,header.support-ukraine-block--replace{position:relative}header.support-ukraine-block--overlap{position:fixed;top:0;left:0;z-index:2147483647}header.support-ukraine-block--refreshing .support-ukraine-block__link{opacity:0}header.support-ukraine-block .support-ukraine-block__link{display:inline-flex;align-items:center;flex-wrap:wrap;gap:0 .25em;text-decoration:none;flex:1;height:100%;justify-content:flex-start;text-align:left;padding:.5em 1em;box-sizing:border-box;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}@media(prefers-reduced-motion: no-preference){header.support-ukraine-block .support-ukraine-block__link{transition:opacity .2s ease-in-out}}@media(prefers-color-scheme: dark){header.support-ukraine-block .support-ukraine-block__link{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}header.support-ukraine-block .support-ukraine-block__link:hover{opacity:.9}header.support-ukraine-block .support-ukraine-block__link:focus-visible{outline:2px solid #fff;outline-offset:-2px}header.support-ukraine-block .support-ukraine-block__flag{white-space:nowrap}header.support-ukraine-block .support-ukraine-block__prefix,header.support-ukraine-block .support-ukraine-block__info,header.support-ukraine-block .support-ukraine-block__colon,header.support-ukraine-block .support-ukraine-block__tagline{min-width:0}header.support-ukraine-block .support-ukraine-block__more{display:inline-flex;align-items:center;text-decoration:none;padding:.5em 1em;box-sizing:border-box;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4);white-space:nowrap;opacity:.8}@media(prefers-color-scheme: dark){header.support-ukraine-block .support-ukraine-block__more{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}header.support-ukraine-block .support-ukraine-block__more:hover{opacity:1}header.support-ukraine-block .support-ukraine-block__more:focus-visible{outline:2px solid #fff;outline-offset:-2px}header.support-ukraine-block .support-ukraine-block__more-ellipsis{display:none}header.support-ukraine-block .support-ukraine-block__refresh{display:inline-flex;align-items:center;background:none;border:none;text-decoration:none;padding:.5em .5em .5em 1em;box-sizing:border-box;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4);white-space:nowrap;opacity:.8;cursor:pointer;font-size:inherit;line-height:1}@media(prefers-color-scheme: dark){header.support-ukraine-block .support-ukraine-block__refresh{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}header.support-ukraine-block .support-ukraine-block__refresh:hover{opacity:1}header.support-ukraine-block .support-ukraine-block__refresh:focus-visible{outline:2px solid #fff;outline-offset:-2px}header.support-ukraine-block .support-ukraine-block__name{font-weight:bold}@media(max-width: 58rem){header.support-ukraine-block .support-ukraine-block__prefix,header.support-ukraine-block .support-ukraine-block__name,header.support-ukraine-block .support-ukraine-block__colon,header.support-ukraine-block .support-ukraine-block__more,header.support-ukraine-block .support-ukraine-block__refresh{display:none}}@media(max-width: 35rem){header.support-ukraine-block .support-ukraine-block__name,header.support-ukraine-block .support-ukraine-block__colon{display:initial}header.support-ukraine-block .support-ukraine-block__tagline{display:none}}[dir=rtl] header.support-ukraine-block .support-ukraine-block__link{text-align:right;justify-content:flex-end}[dir=rtl] header.support-ukraine-block .support-ukraine-block__more{text-align:right}[dir=rtl] header.support-ukraine-block .support-ukraine-block__refresh{text-align:right}:host-context([data-theme=dark]) header.support-ukraine-block{background-color:gold}:host-context([data-theme=dark]) header.support-ukraine-block .support-ukraine-block__link{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=dark]) header.support-ukraine-block .support-ukraine-block__more{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=dark]) header.support-ukraine-block .support-ukraine-block__refresh{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=light]) header.support-ukraine-block{background-color:#0057b7}:host-context([data-theme=light]) header.support-ukraine-block .support-ukraine-block__link{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}:host-context([data-theme=light]) header.support-ukraine-block .support-ukraine-block__more{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}:host-context([data-theme=light]) header.support-ukraine-block .support-ukraine-block__refresh{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}\"","// SPDX-FileCopyrightText: 2026 Damián Búho <damian.buho@proton.me>\n//\n// SPDX-License-Identifier: MIT\n\nimport {\n charitiesSchema,\n type Charity,\n type LocaleMessages,\n type SupportUkraineBlockOptions\n} from './types.js'\nimport rawCharities from './charities.yaml'\nimport styles from './styles.scss'\n\nexport type { Charity, CharityTag, SupportUkraineBlockOptions, LocaleMessages } from './types.js'\n\nexport const DEFAULT_CHARITIES: Charity[] = charitiesSchema.parse(rawCharities)\n\nconst CSS_PREFIX = 'support-ukraine-block'\nconst STORAGE_KEY = 'support-ukraine-seen'\nconst REFRESH_GLYPH = '\\u{27F3}'\nconst VISUALLY_HIDDEN_CLASS = `${CSS_PREFIX}__visually-hidden`\n\nfunction readSeen(): Set<string> {\n try {\n const raw = localStorage.getItem(STORAGE_KEY)\n return raw ? new Set(JSON.parse(raw) as string[]) : new Set()\n } catch {\n return new Set()\n }\n}\n\nfunction writeSeen(seen: Set<string>): void {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify([...seen]))\n } catch {\n // localStorage unavailable — degrade silently\n }\n}\n\nfunction updateSeen(mutate: (seen: Set<string>) => void): void {\n const seen = readSeen()\n mutate(seen)\n writeSeen(seen)\n}\n\n/**\n * Pick a random item from an array.\n *\n * @internal\n */\nexport function randomItem<T>(items: T[]): T {\n if (items.length === 0) {\n throw new Error('randomItem: cannot pick from an empty array')\n }\n return items[Math.floor(Math.random() * items.length)]!\n}\n\nfunction pickCharity(candidates: Charity[], shouldAvoidRepeat: boolean): Charity {\n let pool = candidates\n\n if (shouldAvoidRepeat) {\n updateSeen(seen => {\n const unseen = pool.filter(c => !seen.has(c.url))\n if (unseen.length > 0) {\n pool = unseen\n } else {\n seen.clear()\n }\n })\n }\n\n const charity = randomItem(pool)\n\n if (shouldAvoidRepeat) {\n updateSeen(seen => {\n seen.add(charity.url)\n })\n }\n\n return charity\n}\n\nfunction injectShadowStyles(shadowRoot: ShadowRoot): void {\n const id = `${CSS_PREFIX}-styles`\n if (shadowRoot.querySelector(`#${id}`)) {\n return\n }\n\n const style = shadowRoot.ownerDocument.createElement('style')\n style.id = id\n style.textContent = styles\n shadowRoot.append(style)\n}\n\n/**\n * Merge base charities with locale-specific translations.\n */\nexport function mergeCharities(base: readonly Charity[], locale: LocaleMessages): Charity[] {\n return base.map(charity => {\n const translated = locale.charities[charity.id]\n if (translated?.tagline) {\n return { ...charity, tagline: translated.tagline }\n }\n return charity\n })\n}\n\nexport function isRTL(lang: string): boolean {\n const base = (lang.split('-', 1)[0] ?? '').toLowerCase()\n return base === 'ar'\n}\n\nexport function formatBannerText(charity: Charity, messages: LocaleMessages): string {\n return `\\u{1F1FA}\\u{1F1E6} ${messages.supportUkraine} ${charity.name}: ${charity.tagline}`\n}\n\n/**\n * Mount the banner with already-resolved `lang` and `messages`.\n * Shared by the auto-detect build (`src/index.ts`) and the per-locale builds (`src/entries/*.ts`).\n */\nexport function mountBanner(\n lang: string,\n messages: LocaleMessages,\n options: SupportUkraineBlockOptions = {}\n): HTMLElement & { destroy: () => void } {\n const {\n mode = 'shift',\n fontSize = '87.5%',\n charities,\n tags,\n dontRepeat = true,\n isInConsole = true,\n showRefreshButton = false,\n autoRefreshInterval = 0,\n showRefreshAnimation = false\n } = options\n\n const baseCharities = charities ?? DEFAULT_CHARITIES\n const localizedCharities = mergeCharities(baseCharities, messages)\n\n let candidates =\n tags && tags.length > 0\n ? localizedCharities.filter(charity => charity.tags.some(t => tags.includes(t)))\n : localizedCharities\n\n if (candidates.length === 0) {\n candidates = localizedCharities\n }\n\n const charity = pickCharity(candidates, dontRepeat)\n\n const host = document.createElement('div')\n\n const shadow = host.attachShadow({ mode: 'open' })\n injectShadowStyles(shadow)\n\n const banner = document.createElement('header')\n banner.className = `${CSS_PREFIX} ${CSS_PREFIX}--${mode}`\n banner.lang = lang\n\n if (isRTL(lang)) {\n banner.setAttribute('dir', 'rtl')\n }\n\n const link = document.createElement('a')\n link.className = `${CSS_PREFIX}__link`\n link.href = charity.url\n link.target = '_blank'\n link.rel = 'noopener noreferrer'\n link.style.fontSize = fontSize\n\n const linkNewTabId = `${CSS_PREFIX}-link-new-tab`\n const linkNewTabHint = document.createElement('span')\n linkNewTabHint.id = linkNewTabId\n linkNewTabHint.className = VISUALLY_HIDDEN_CLASS\n linkNewTabHint.textContent = messages.opensInNewTab\n link.setAttribute('aria-describedby', linkNewTabId)\n\n const flag = document.createElement('span')\n flag.className = `${CSS_PREFIX}__flag`\n flag.textContent = `\\u{1F1FA}\\u{1F1E6} `\n\n const prefix = document.createElement('span')\n prefix.className = `${CSS_PREFIX}__prefix`\n prefix.textContent = `${messages.supportUkraine} `\n\n const info = document.createElement('span')\n info.className = `${CSS_PREFIX}__info`\n\n const name = document.createElement('span')\n name.className = `${CSS_PREFIX}__name`\n name.textContent = charity.name\n\n const colon = document.createElement('span')\n colon.className = `${CSS_PREFIX}__colon`\n colon.textContent = ': '\n\n const tagline = document.createElement('span')\n tagline.className = `${CSS_PREFIX}__tagline`\n tagline.textContent = charity.tagline\n\n info.append(name, colon, tagline)\n\n link.append(flag, prefix, info)\n banner.append(link)\n\n const moreLink = document.createElement('a')\n moreLink.className = `${CSS_PREFIX}__more`\n moreLink.href = 'https://damian-buho.github.io/support-ukraine/'\n moreLink.target = '_blank'\n moreLink.rel = 'noopener noreferrer'\n moreLink.style.fontSize = fontSize\n\n const moreNewTabId = `${CSS_PREFIX}-more-new-tab`\n const moreNewTabHint = document.createElement('span')\n moreNewTabHint.id = moreNewTabId\n moreNewTabHint.className = VISUALLY_HIDDEN_CLASS\n moreNewTabHint.textContent = messages.opensInNewTab\n moreLink.setAttribute('aria-describedby', moreNewTabId)\n\n const moreText = document.createElement('span')\n moreText.className = `${CSS_PREFIX}__more-text`\n moreText.textContent = messages.more\n\n const moreEllipsis = document.createElement('span')\n moreEllipsis.className = `${CSS_PREFIX}__more-ellipsis`\n moreEllipsis.textContent = '\\u{2026}'\n\n moreLink.append(moreText, moreEllipsis)\n banner.append(moreLink)\n banner.append(linkNewTabHint, moreNewTabHint)\n\n function applyNext(next: Charity): void {\n link.href = next.url\n name.textContent = next.name\n tagline.textContent = next.tagline\n if (isInConsole) {\n console.info('[support-ukraine] banner', `${next.name}: ${next.tagline}`, next.url)\n }\n }\n\n function updateCharity(): void {\n const next = pickCharity(candidates, dontRepeat)\n if (showRefreshAnimation) {\n banner.classList.add(`${CSS_PREFIX}--refreshing`)\n setTimeout(() => {\n applyNext(next)\n banner.classList.remove(`${CSS_PREFIX}--refreshing`)\n }, 200)\n } else {\n applyNext(next)\n }\n }\n\n if (showRefreshButton) {\n const refreshButton = document.createElement('button')\n refreshButton.className = `${CSS_PREFIX}__refresh`\n refreshButton.type = 'button'\n refreshButton.textContent = REFRESH_GLYPH\n refreshButton.style.fontSize = fontSize\n refreshButton.setAttribute('aria-label', messages.refresh)\n refreshButton.addEventListener('click', updateCharity)\n // eslint-disable-next-line unicorn/prefer-modern-dom-apis\n banner.insertBefore(refreshButton, moreLink)\n }\n\n shadow.append(banner)\n\n const mount = options.element ?? document.body\n\n if (mode === 'replace') {\n const placeholder = mount.querySelector<HTMLElement>(`.${CSS_PREFIX}`)\n if (placeholder) {\n placeholder.replaceWith(host)\n } else {\n mount.prepend(host)\n }\n } else {\n mount.prepend(host)\n }\n\n if (isInConsole) {\n console.info('[support-ukraine] banner', `${charity.name}: ${charity.tagline}`, charity.url)\n }\n\n host.dataset.supportUkraine = ''\n host.classList.add(`${CSS_PREFIX}--processed`)\n\n let intervalId: ReturnType<typeof setInterval> | undefined\n if (autoRefreshInterval > 0) {\n intervalId = setInterval(updateCharity, autoRefreshInterval)\n }\n\n const instance = host as HTMLElement & { destroy: () => void }\n instance.destroy = () => {\n if (intervalId !== undefined) {\n clearInterval(intervalId)\n }\n host.remove()\n }\n\n return instance\n}\n","// SPDX-FileCopyrightText: 2026 Damián Búho <damian.buho@proton.me>\n//\n// SPDX-License-Identifier: MIT\n\nimport messages from '../locales/es.yaml'\nimport { mountBanner } from '../banner.js'\nimport type { LocaleMessages, SupportUkraineBlockOptions } from '../types.js'\n\nexport type { Charity, CharityTag, SupportUkraineBlockOptions } from '../types.js'\nexport { charitySchema, charitiesSchema } from '../types.js'\nexport {\n DEFAULT_CHARITIES,\n mergeCharities,\n isRTL,\n formatBannerText,\n randomItem\n} from '../banner.js'\nexport type { SupportedLocale } from '../locales/index.js'\n\nconst LANG = 'es'\n\n/**\n * Localized `supportUkraineBlock` with `es` baked in.\n *\n * This build is self-contained — the locale messages are bundled inline, so\n * no second network request is needed. For optimal Core Web Vitals, load\n * only the locale you need:\n *\n * ```ts\n * import { supportUkraineBlock } from '@damian-buho/support-ukraine/es'\n * await supportUkraineBlock()\n * ```\n *\n * The `locale` option is ignored in this build (the bundle is already\n * localized). Use the auto-detect build (`@damian-buho/support-ukraine`)\n * if you need runtime locale switching.\n */\nexport function supportUkraineBlock(\n options: SupportUkraineBlockOptions = {}\n): Promise<HTMLElement> {\n return Promise.resolve(mountBanner(LANG, messages as unknown as LocaleMessages, options))\n}\n"],"mappings":"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","names":["es_default","VALID_TAGS","assert","condition","message","assertNonEmptyString","value","field","assertUrl","parseCharityTag","parseCharity","record","tag","charitySchema","charitiesSchema","item","charities_default","styles_default","DEFAULT_CHARITIES","charitiesSchema","charities_default","CSS_PREFIX","STORAGE_KEY","REFRESH_GLYPH","VISUALLY_HIDDEN_CLASS","readSeen","raw","writeSeen","seen","updateSeen","mutate","randomItem","items","pickCharity","candidates","shouldAvoidRepeat","pool","unseen","c","charity","injectShadowStyles","shadowRoot","id","style","styles_default","mergeCharities","base","locale","translated","isRTL","lang","formatBannerText","messages","mountBanner","options","mode","fontSize","charities","tags","dontRepeat","isInConsole","showRefreshButton","autoRefreshInterval","showRefreshAnimation","localizedCharities","t","host","shadow","banner","link","linkNewTabId","linkNewTabHint","flag","prefix","info","name","colon","tagline","moreLink","moreNewTabId","moreNewTabHint","moreText","moreEllipsis","applyNext","next","updateCharity","refreshButton","mount","placeholder","intervalId","instance","LANG","supportUkraineBlock","options","mountBanner","es_default"]}
|