@damian-buho/support-ukraine 2.1.1 → 2.2.0

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/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\",\"regionLabel\":\"Banner de apoyo a Ucrania\",\"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 /**\n Donation URLs keyed by base language code. `en` is required and is the fallback.\n */\n urls: Record<string, string> & { en: string }\n tags: CharityTag[]\n}\n\nfunction parseLocalizedUrls(value: unknown): Record<string, string> & { en: string } {\n assert(value !== null && typeof value === 'object', 'urls must be an object')\n const entries = Object.entries(value as Record<string, unknown>)\n assert(entries.length > 0, 'urls must not be empty')\n const result: Record<string, string> = {}\n for (const [key, entry] of entries) {\n assertUrl(entry, `urls.${key}`)\n result[key.toLowerCase()] = entry as string\n }\n assert(typeof result.en === 'string', 'urls must include an \"en\" entry')\n return result as Record<string, string> & { en: string }\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 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 urls: parseLocalizedUrls(record.urls),\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 Accessible name for the banner landmark, e.g. \"Support Ukraine banner\".\n */\n regionLabel: 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 Charity ids to exclude from rotation. Unknown ids are ignored.\n */\n exclude?: string[]\n // Avoid repeating charities. Seen ids stay in session memory unless persistSeen is set.\n dontRepeat?: boolean\n // Persist the seen-charity list in localStorage. Default false (session memory only).\n persistSeen?: 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 the next random charity after the visitor clicks the banner link.\n The banner rotates once the page loses focus (the donation opens in a new tab),\n with a short delayed fallback, so the swap never flashes in front of the visitor.\n Enabled by default so a returning visitor sees a fresh charity instead of the one just opened.\n */\n refreshOnClick?: boolean\n /**\n Fallback delay in milliseconds before the banner rotates after a click\n when the page never loses focus (pop-up blocker, background tab). Default 2000.\n */\n refreshOnClickDelay?: 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 Enable UTM parameters on charity links. Enabled by default.\n */\n utmEnabled?: boolean\n /**\n UTM source parameter. Defaults to the current domain (window.location.hostname).\n */\n utmSource?: string\n /**\n UTM medium parameter. Defaults to 'support-ukraine-banner'.\n */\n utmMedium?: string\n /**\n UTM campaign parameter. Empty by default.\n */\n utmCampaign?: string\n}\n","export default [{\"id\":\"united24\",\"name\":\"United24\",\"tagline\":\"Official fundraising platform of Ukraine\",\"urls\":{\"en\":\"https://u24.gov.ua/en\",\"uk\":\"https://u24.gov.ua/uk\"},\"tags\":[\"humanitarian\"]},{\"id\":\"come-back-alive\",\"name\":\"Come Back Alive\",\"tagline\":\"Supporting the Ukrainian Armed Forces since 2014\",\"urls\":{\"en\":\"https://savelife.in.ua/en/\",\"uk\":\"https://savelife.in.ua/\"},\"tags\":[\"military\"]},{\"id\":\"razom-for-ukraine\",\"name\":\"Razom for Ukraine\",\"tagline\":\"Emergency response and humanitarian aid\",\"urls\":{\"en\":\"https://www.razomforukraine.org\",\"uk\":\"https://www.razomforukraine.org/ua/\"},\"tags\":[\"humanitarian\"]},{\"id\":\"ukrainian-red-cross\",\"name\":\"Ukrainian Red Cross\",\"tagline\":\"Humanitarian assistance in conflict zones\",\"urls\":{\"en\":\"https://redcross.org.ua/en/\",\"uk\":\"https://redcross.org.ua/\"},\"tags\":[\"humanitarian\"]},{\"id\":\"nova-ukraine\",\"name\":\"Nova Ukraine\",\"tagline\":\"Humanitarian aid and advocacy\",\"urls\":{\"en\":\"https://novaukraine.org\",\"uk\":\"https://novaukraine.org.ua/\"},\"tags\":[\"humanitarian\"]},{\"id\":\"voices-of-children\",\"name\":\"Voices of Children\",\"tagline\":\"Psychological support for children affected by war\",\"urls\":{\"en\":\"https://voices.org.ua/en/\",\"uk\":\"https://voices.org.ua/\"},\"tags\":[\"humanitarian\"]},{\"id\":\"prytula-foundation\",\"name\":\"Prytula Foundation\",\"tagline\":\"Defence technology and equipment for Ukraine\",\"urls\":{\"en\":\"https://prytulafoundation.org/en\",\"uk\":\"https://prytulafoundation.org/\"},\"tags\":[\"military\"]},{\"id\":\"world-central-kitchen\",\"name\":\"World Central Kitchen\",\"tagline\":\"Fresh meals for people in conflict zones\",\"urls\":{\"en\":\"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\",\"urls\":{\"en\":\"https://cats.kiev.ua\"},\"tags\":[\"animals\"]},{\"id\":\"uanimals\",\"name\":\"UAnimals\",\"tagline\":\"Animal rescue and advocacy organization in Ukraine\",\"urls\":{\"en\":\"https://uanimals.org/en/\",\"uk\":\"https://uanimals.org/\"},\"tags\":[\"animals\"]},{\"id\":\"hospitallers\",\"name\":\"Hospitallers\",\"tagline\":\"Ukrainian voluntary paramedics providing first aid and evacuation\",\"urls\":{\"en\":\"https://www.hospitallers.org.uk\",\"de\":\"https://www.hospitallers.org.uk/de\",\"es\":\"https://www.hospitallers.org.uk/es\",\"fr\":\"https://www.hospitallers.org.uk/fr\",\"it\":\"https://www.hospitallers.org.uk/it\",\"nl\":\"https://www.hospitallers.org.uk/nl\",\"pl\":\"https://www.hospitallers.org.uk/pl\",\"cs\":\"https://www.hospitallers.org.uk/cs\",\"sv\":\"https://www.hospitallers.org.uk/sv\"},\"tags\":[\"humanitarian\"]},{\"id\":\"sternenko-fund\",\"name\":\"Sternenko Fund\",\"tagline\":\"FPV drone supply for Ukrainian defence forces\",\"urls\":{\"en\":\"https://www.sternenkofund.org/en\",\"uk\":\"https://www.sternenkofund.org/\"},\"tags\":[\"military\"]},{\"id\":\"life-robots-ukraine\",\"name\":\"Life Robots Ukraine\",\"tagline\":\"Robots for demining Ukraine\",\"urls\":{\"en\":\"https://liferobots.com.ua/en\",\"uk\":\"https://liferobots.com.ua/\",\"de\":\"https://liferobots.com.ua/de\",\"es\":\"https://liferobots.com.ua/es\",\"fr\":\"https://liferobots.com.ua/fr\",\"ja\":\"https://liferobots.com.ua/ja\",\"ko\":\"https://liferobots.com.ua/ko\",\"nl\":\"https://liferobots.com.ua/nl\",\"pl\":\"https://liferobots.com.ua/pl\",\"he\":\"https://liferobots.com.ua/he\",\"lt\":\"https://liferobots.com.ua/lt\",\"lv\":\"https://liferobots.com.ua/lv\",\"no\":\"https://liferobots.com.ua/no\",\"ro\":\"https://liferobots.com.ua/ro\",\"ru\":\"https://liferobots.com.ua/ru\"},\"tags\":[\"humanitarian\"]},{\"id\":\"sirius-shelter\",\"name\":\"Sirius\",\"tagline\":\"Ukraine's largest animal shelter for dogs and cats\",\"urls\":{\"en\":\"https://dogcat.com.ua/en\",\"uk\":\"https://dogcat.com.ua/\"},\"tags\":[\"animals\"]},{\"id\":\"dignitas\",\"name\":\"Dignitas\",\"tagline\":\"Technology and support for Ukrainian defenders and veterans\",\"urls\":{\"en\":\"https://dignitas.fund/\",\"uk\":\"https://dignitas.fund/uk/\"},\"tags\":[\"military\"]},{\"id\":\"leleka\",\"name\":\"Leleka Foundation\",\"tagline\":\"Tactical medical supplies for Ukraine's frontline medics\",\"urls\":{\"en\":\"https://leleka.care/en\",\"uk\":\"https://leleka.care/ua\"},\"tags\":[\"humanitarian\"]},{\"id\":\"superhumans\",\"name\":\"Superhumans Center\",\"tagline\":\"Prosthetics, surgery, and rehabilitation for war survivors\",\"urls\":{\"en\":\"https://superhumans.com/en/\",\"uk\":\"https://superhumans.com/\"},\"tags\":[\"humanitarian\"]},{\"id\":\"nikopol-chance\",\"name\":\"Nikopol Chance\",\"tagline\":\"Dog shelter rescuing and rehoming strays in frontline Nikopol\",\"urls\":{\"en\":\"https://nikopolchance.com\"},\"tags\":[\"animals\"]}]","export default \":host{display:block;margin:0;padding:0;border:none;font-size:16px;width:100%;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}section.support-ukraine-block{margin:0;padding:0;border:none;border-radius:0;width:100%;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){section.support-ukraine-block{background-color:gold}}section.support-ukraine-block--shift,section.support-ukraine-block--replace{position:relative}section.support-ukraine-block--overlap{position:fixed;top:0;left:0;z-index:2147483647}section.support-ukraine-block--refreshing .support-ukraine-block__link{opacity:0}section.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){section.support-ukraine-block .support-ukraine-block__link{transition:opacity .2s ease-in-out}}@media(prefers-color-scheme: dark){section.support-ukraine-block .support-ukraine-block__link{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}section.support-ukraine-block .support-ukraine-block__link:hover{opacity:.9}section.support-ukraine-block .support-ukraine-block__link:focus-visible{outline:2px solid #fff;outline-offset:-2px}section.support-ukraine-block .support-ukraine-block__flag{white-space:nowrap}section.support-ukraine-block .support-ukraine-block__prefix,section.support-ukraine-block .support-ukraine-block__info,section.support-ukraine-block .support-ukraine-block__colon,section.support-ukraine-block .support-ukraine-block__tagline{min-width:0}section.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){section.support-ukraine-block .support-ukraine-block__more{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}section.support-ukraine-block .support-ukraine-block__more:hover{opacity:1}section.support-ukraine-block .support-ukraine-block__more:focus-visible{outline:2px solid #fff;outline-offset:-2px}section.support-ukraine-block .support-ukraine-block__more-ellipsis{display:none}section.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){section.support-ukraine-block .support-ukraine-block__refresh{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}section.support-ukraine-block .support-ukraine-block__refresh:hover{opacity:1}section.support-ukraine-block .support-ukraine-block__refresh:focus-visible{outline:2px solid #fff;outline-offset:-2px}section.support-ukraine-block .support-ukraine-block__name{font-weight:bold}@media(prefers-contrast: more){section.support-ukraine-block{background-color:#003580}section.support-ukraine-block .support-ukraine-block__link,section.support-ukraine-block .support-ukraine-block__more,section.support-ukraine-block .support-ukraine-block__refresh{opacity:1;text-shadow:none}section.support-ukraine-block .support-ukraine-block__link:hover,section.support-ukraine-block .support-ukraine-block__more:hover,section.support-ukraine-block .support-ukraine-block__refresh:hover{opacity:1}}@media(prefers-contrast: more)and (prefers-color-scheme: dark){section.support-ukraine-block{background-color:gold}section.support-ukraine-block .support-ukraine-block__link,section.support-ukraine-block .support-ukraine-block__more,section.support-ukraine-block .support-ukraine-block__refresh{opacity:1;text-shadow:none}}@media(forced-colors: active){section.support-ukraine-block .support-ukraine-block__link:focus-visible,section.support-ukraine-block .support-ukraine-block__more:focus-visible,section.support-ukraine-block .support-ukraine-block__refresh:focus-visible{outline:2px solid Highlight}}@media(max-width: 58rem){section.support-ukraine-block .support-ukraine-block__prefix,section.support-ukraine-block .support-ukraine-block__name,section.support-ukraine-block .support-ukraine-block__colon,section.support-ukraine-block .support-ukraine-block__more,section.support-ukraine-block .support-ukraine-block__refresh{display:none}}@media(max-width: 35rem){section.support-ukraine-block .support-ukraine-block__name{display:initial}section.support-ukraine-block .support-ukraine-block__tagline{display:none}}[dir=rtl] section.support-ukraine-block .support-ukraine-block__link{text-align:right;justify-content:flex-end}[dir=rtl] section.support-ukraine-block .support-ukraine-block__more{text-align:right}[dir=rtl] section.support-ukraine-block .support-ukraine-block__refresh{text-align:right}:host-context([data-theme=dark]) section.support-ukraine-block{background-color:gold}:host-context([data-theme=dark]) section.support-ukraine-block .support-ukraine-block__link{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=dark]) section.support-ukraine-block .support-ukraine-block__more{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=dark]) section.support-ukraine-block .support-ukraine-block__refresh{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=light]) section.support-ukraine-block{background-color:#0057b7}:host-context([data-theme=light]) section.support-ukraine-block .support-ukraine-block__link{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}:host-context([data-theme=light]) section.support-ukraine-block .support-ukraine-block__more{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}:host-context([data-theme=light]) section.support-ukraine-block .support-ukraine-block__refresh{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}@media(prefers-contrast: more){:host-context([data-theme=light]) section.support-ukraine-block{background-color:#003580}:host-context([data-theme=light]) section.support-ukraine-block .support-ukraine-block__link,:host-context([data-theme=light]) section.support-ukraine-block .support-ukraine-block__more,:host-context([data-theme=light]) section.support-ukraine-block .support-ukraine-block__refresh,:host-context([data-theme=dark]) section.support-ukraine-block .support-ukraine-block__link,:host-context([data-theme=dark]) section.support-ukraine-block .support-ukraine-block__more,:host-context([data-theme=dark]) section.support-ukraine-block .support-ukraine-block__refresh{opacity:1;text-shadow:none}}\"","// 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`\nconst bannerState = { count: 0 } // Suffix for hint ids so repeated banners stay unique.\n\nconst memorySeen = new Set<string>() // Session-only seen ids, used when persistSeen is false.\n\n// @internal — test helper resetting the session-only seen set.\nexport function resetMemorySeen(): void {\n memorySeen.clear()\n}\n\nfunction readSeen(shouldPersist: boolean): Set<string> {\n if (!shouldPersist) return new Set(memorySeen)\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>, shouldPersist: boolean): void {\n if (!shouldPersist) {\n memorySeen.clear()\n for (const id of seen) memorySeen.add(id)\n return\n }\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, shouldPersist: boolean): void {\n const seen = readSeen(shouldPersist)\n mutate(seen)\n writeSeen(seen, shouldPersist)\n}\n\n/**\nPick 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(\n candidates: Charity[],\n shouldAvoidRepeat: boolean,\n shouldPersist: boolean,\n lang: string,\n excludeId?: string,\n excludeUrl?: string\n): Charity {\n let pool = excludeId ? candidates.filter(c => c.id !== excludeId) : candidates\n if (excludeUrl && pool.length > 1) {\n const withoutUrl = pool.filter(c => charityUrlFor(c, lang) !== excludeUrl)\n if (withoutUrl.length > 0) pool = withoutUrl\n }\n if (pool.length === 0) pool = candidates\n\n if (shouldAvoidRepeat) {\n updateSeen(seen => {\n const unseen = pool.filter(c => !seen.has(c.id))\n if (unseen.length > 0) {\n pool = unseen\n } else {\n seen.clear()\n }\n }, shouldPersist)\n }\n\n const charity = randomItem(pool)\n\n if (shouldAvoidRepeat) {\n updateSeen(seen => {\n seen.add(charity.id)\n }, shouldPersist)\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/**\nMerge 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 return translated?.tagline ? { ...charity, tagline: translated.tagline } : charity\n })\n}\n\n/**\nResolve the donation URL for a charity in the given banner language.\nFalls back to English.\n*/\nexport function charityUrlFor(charity: Charity, lang: string): string {\n const base = (lang.split('-', 1)[0] ?? '').toLowerCase()\n return charity.urls[base] ?? charity.urls.en\n}\n\nexport function isRTL(lang: string): boolean {\n const base = (lang.split('-', 1)[0] ?? '').toLowerCase()\n return base === 'ar'\n}\n\nexport function isDoNotTrackEnabled(): boolean {\n if (typeof navigator === 'undefined') return false\n const dnt = navigator.doNotTrack\n if (dnt === '1' || dnt === 'yes') return true\n const win = globalThis.window\n if (win) {\n const dntWin = (win as unknown as { doNotTrack?: string }).doNotTrack\n if (dntWin === '1' || dntWin === 'yes') return true\n const msDnt = (navigator as unknown as { msDoNotTrack?: string }).msDoNotTrack\n if (msDnt === '1') return true\n }\n return false\n}\n\nexport function buildUtmUrl(baseUrl: string, options: SupportUkraineBlockOptions): string {\n // Default utmEnabled to true if not explicitly set to false\n if (options.utmEnabled === false) return baseUrl\n if (isDoNotTrackEnabled()) return baseUrl\n\n const source = options.utmSource ?? globalThis.window?.location?.hostname ?? ''\n if (!source) return baseUrl\n\n const medium = options.utmMedium ?? 'support-ukraine-banner'\n const campaign = options.utmCampaign ?? ''\n\n try {\n const url = new URL(baseUrl)\n url.searchParams.set('utm_source', source)\n url.searchParams.set('utm_medium', medium)\n if (campaign) url.searchParams.set('utm_campaign', campaign)\n return url.href\n } catch {\n return baseUrl\n }\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/**\nMount the banner with already-resolved `lang` and `messages`.\nShared 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 exclude,\n dontRepeat = true,\n persistSeen = false,\n isInConsole = true,\n showRefreshButton = false,\n autoRefreshInterval = 0,\n refreshOnClick = true,\n refreshOnClickDelay = 2000,\n showRefreshAnimation = false\n } = options\n\n const baseCharities = charities ? charitiesSchema.parse(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 (exclude && exclude.length > 0) {\n const excluded = new Set(exclude)\n const kept = candidates.filter(charity => !excluded.has(charity.id))\n if (kept.length > 0) candidates = kept\n }\n\n if (candidates.length === 0) {\n candidates = localizedCharities\n }\n\n const charity = pickCharity(candidates, dontRepeat, persistSeen, lang)\n let currentCharity = charity\n let currentCharityUrl = charityUrlFor(charity, lang)\n\n const host = document.createElement('div')\n\n const shadow = host.attachShadow({ mode: 'open' })\n injectShadowStyles(shadow)\n\n const banner = document.createElement('section')\n banner.className = `${CSS_PREFIX} ${CSS_PREFIX}--${mode}`\n banner.lang = lang\n banner.setAttribute('aria-label', messages.regionLabel)\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 = buildUtmUrl(currentCharityUrl, options)\n link.target = '_blank'\n link.rel = 'noopener noreferrer'\n link.style.fontSize = fontSize\n\n const instanceSuffix = ++bannerState.count // Unique per mount for hint ids.\n const linkNewTabId = `${CSS_PREFIX}-link-new-tab-${instanceSuffix}`\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 flag.setAttribute('aria-hidden', 'true') // Flag duplicates \"Ukraine\" in link text.\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 = buildUtmUrl('https://damian-buho.github.io/support-ukraine/', options)\n moreLink.target = '_blank'\n moreLink.rel = 'noopener noreferrer'\n moreLink.style.fontSize = fontSize\n\n const moreNewTabId = `${CSS_PREFIX}-more-new-tab-${instanceSuffix}`\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 currentCharity = next\n currentCharityUrl = charityUrlFor(next, lang)\n link.href = buildUtmUrl(currentCharityUrl, options)\n name.textContent = next.name\n tagline.textContent = next.tagline\n if (isInConsole) {\n console.info('[support-ukraine] banner', `${next.name}: ${next.tagline}`, currentCharityUrl)\n }\n }\n\n function updateCharity(): void {\n const next = pickCharity(\n candidates,\n dontRepeat,\n persistSeen,\n lang,\n currentCharity.id,\n currentCharityUrl\n )\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 let clickRefreshTimer: ReturnType<typeof setTimeout> | undefined\n function cancelClickRefresh(): void {\n if (clickRefreshTimer !== undefined) {\n clearTimeout(clickRefreshTimer)\n clickRefreshTimer = undefined\n }\n document.removeEventListener('visibilitychange', handlePageHidden)\n globalThis.window?.removeEventListener?.('blur', handleWindowBlur)\n }\n function handlePageHidden(): void {\n if (!document.hidden) return\n cancelClickRefresh()\n updateCharity()\n }\n function handleWindowBlur(): void {\n cancelClickRefresh()\n updateCharity()\n }\n function scheduleClickRefresh(): void {\n if (clickRefreshTimer !== undefined) return\n document.addEventListener('visibilitychange', handlePageHidden)\n globalThis.window?.addEventListener?.('blur', handleWindowBlur)\n clickRefreshTimer = setTimeout(() => {\n cancelClickRefresh()\n updateCharity()\n }, refreshOnClickDelay)\n }\n\n if (refreshOnClick) {\n link.addEventListener('click', scheduleClickRefresh)\n }\n\n if (showRefreshButton) {\n const refreshButton = document.createElement('button')\n refreshButton.className = `${CSS_PREFIX}__refresh`\n refreshButton.type = 'button'\n refreshButton.textContent = ''\n refreshButton.style.fontSize = fontSize\n refreshButton.setAttribute('aria-label', messages.refresh)\n refreshButton.addEventListener('click', updateCharity)\n const refreshGlyph = document.createElement('span')\n refreshGlyph.textContent = REFRESH_GLYPH\n refreshGlyph.setAttribute('aria-hidden', 'true') // Name comes from aria-label.\n refreshButton.append(refreshGlyph)\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(\n '[support-ukraine] banner',\n `${charity.name}: ${charity.tagline}`,\n currentCharityUrl\n )\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 cancelClickRefresh()\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/**\nLocalized `supportUkraineBlock` with `es` baked in.\n\nThis build is self-contained — the locale messages are bundled inline, so\nno second network request is needed. For optimal Core Web Vitals, load\nonly the locale you need:\n\n```ts\nimport { supportUkraineBlock } from '@damian-buho/support-ukraine/es'\nawait supportUkraineBlock()\n```\n\nThe `locale` option is ignored in this build (the bundle is already\nlocalized). Use the auto-detect build (`@damian-buho/support-ukraine`)\nif 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","parseLocalizedUrls","entries","result","key","entry","parseCharity","record","tag","charitySchema","charitiesSchema","item","charities_default","styles_default","DEFAULT_CHARITIES","charitiesSchema","charities_default","CSS_PREFIX","STORAGE_KEY","REFRESH_GLYPH","VISUALLY_HIDDEN_CLASS","bannerState","memorySeen","readSeen","shouldPersist","memorySeen","raw","STORAGE_KEY","writeSeen","seen","id","updateSeen","mutate","randomItem","items","pickCharity","candidates","shouldAvoidRepeat","lang","excludeId","excludeUrl","pool","withoutUrl","c","charityUrlFor","unseen","charity","injectShadowStyles","shadowRoot","CSS_PREFIX","style","styles_default","mergeCharities","base","locale","translated","isRTL","isDoNotTrackEnabled","dnt","win","dntWin","buildUtmUrl","baseUrl","options","source","medium","campaign","url","formatBannerText","messages","mountBanner","mode","fontSize","charities","tags","exclude","dontRepeat","persistSeen","isInConsole","showRefreshButton","autoRefreshInterval","refreshOnClick","refreshOnClickDelay","showRefreshAnimation","baseCharities","charitiesSchema","DEFAULT_CHARITIES","localizedCharities","t","excluded","kept","currentCharity","currentCharityUrl","host","shadow","banner","link","instanceSuffix","bannerState","linkNewTabId","linkNewTabHint","VISUALLY_HIDDEN_CLASS","flag","prefix","info","name","colon","tagline","moreLink","moreNewTabId","moreNewTabHint","moreText","moreEllipsis","applyNext","next","updateCharity","clickRefreshTimer","cancelClickRefresh","handlePageHidden","handleWindowBlur","scheduleClickRefresh","refreshButton","refreshGlyph","REFRESH_GLYPH","mount","placeholder","intervalId","instance","LANG","supportUkraineBlock","options","mountBanner","es_default"]}
1
+ {"version":3,"sources":["../src/locales/es.yaml","../src/types.ts","../src/language.ts","../src/charities.yaml","../src/styles.scss","../src/banner.ts","../src/entries/es.ts"],"sourcesContent":["export default {\"supportUkraine\":\"Apoya a Ucrania con\",\"regionLabel\":\"Banner de apoyo a Ucrania\",\"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 /**\n Donation URLs keyed by base language code. `en` is required and is the fallback.\n */\n urls: Record<string, string> & { en: string }\n tags: CharityTag[]\n}\n\nfunction parseLocalizedUrls(value: unknown): Record<string, string> & { en: string } {\n assert(value !== null && typeof value === 'object', 'urls must be an object')\n const entries = Object.entries(value as Record<string, unknown>)\n assert(entries.length > 0, 'urls must not be empty')\n const result: Record<string, string> = {}\n for (const [key, entry] of entries) {\n assertUrl(entry, `urls.${key}`)\n result[key.toLowerCase()] = entry as string\n }\n assert(typeof result.en === 'string', 'urls must include an \"en\" entry')\n return result as Record<string, string> & { en: string }\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 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 urls: parseLocalizedUrls(record.urls),\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 Accessible name for the banner landmark, e.g. \"Support Ukraine banner\".\n */\n regionLabel: 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 Charity ids to exclude from rotation. Unknown ids are ignored.\n */\n exclude?: string[]\n // Avoid repeating charities. Seen ids stay in session memory unless persistSeen is set.\n dontRepeat?: boolean\n // Persist the seen-charity list in localStorage. Default false (session memory only).\n persistSeen?: 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 the next random charity after the visitor clicks the banner link.\n The banner rotates once the page loses focus (the donation opens in a new tab),\n with a short delayed fallback, so the swap never flashes in front of the visitor.\n Enabled by default so a returning visitor sees a fresh charity instead of the one just opened.\n */\n refreshOnClick?: boolean\n /**\n Fallback delay in milliseconds before the banner rotates after a click\n when the page never loses focus (pop-up blocker, background tab). Default 2000.\n */\n refreshOnClickDelay?: 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 Enable UTM parameters on charity links. Enabled by default.\n */\n utmEnabled?: boolean\n /**\n UTM source parameter. Defaults to the current domain (window.location.hostname).\n */\n utmSource?: string\n /**\n UTM medium parameter. Defaults to 'support-ukraine-banner'.\n */\n utmMedium?: string\n /**\n UTM campaign parameter. Empty by default.\n */\n utmCampaign?: string\n}\n","// SPDX-FileCopyrightText: 2026 Damián Búho <damian.buho@proton.me>\n//\n// SPDX-License-Identifier: MIT\n\n// Extracts the base language subtag of a BCP 47 tag, e.g. `es` from `es-MX`.\nexport function baseLanguage(tag: string): string {\n const dash = tag.indexOf('-')\n return (dash === -1 ? tag : tag.slice(0, dash)).toLowerCase()\n}\n","export default [{\"id\":\"united24\",\"name\":\"United24\",\"tagline\":\"Official fundraising platform of Ukraine\",\"urls\":{\"en\":\"https://u24.gov.ua/en\",\"uk\":\"https://u24.gov.ua/uk\"},\"tags\":[\"humanitarian\"]},{\"id\":\"come-back-alive\",\"name\":\"Come Back Alive\",\"tagline\":\"Supporting the Ukrainian Armed Forces since 2014\",\"urls\":{\"en\":\"https://savelife.in.ua/en/\",\"uk\":\"https://savelife.in.ua/\"},\"tags\":[\"military\"]},{\"id\":\"razom-for-ukraine\",\"name\":\"Razom for Ukraine\",\"tagline\":\"Emergency response and humanitarian aid\",\"urls\":{\"en\":\"https://www.razomforukraine.org\",\"uk\":\"https://www.razomforukraine.org/ua/\"},\"tags\":[\"humanitarian\"]},{\"id\":\"ukrainian-red-cross\",\"name\":\"Ukrainian Red Cross\",\"tagline\":\"Humanitarian assistance in conflict zones\",\"urls\":{\"en\":\"https://redcross.org.ua/en/\",\"uk\":\"https://redcross.org.ua/\"},\"tags\":[\"humanitarian\"]},{\"id\":\"nova-ukraine\",\"name\":\"Nova Ukraine\",\"tagline\":\"Humanitarian aid and advocacy\",\"urls\":{\"en\":\"https://novaukraine.org\",\"uk\":\"https://novaukraine.org.ua/\"},\"tags\":[\"humanitarian\"]},{\"id\":\"voices-of-children\",\"name\":\"Voices of Children\",\"tagline\":\"Psychological support for children affected by war\",\"urls\":{\"en\":\"https://voices.org.ua/en/\",\"uk\":\"https://voices.org.ua/\"},\"tags\":[\"humanitarian\"]},{\"id\":\"prytula-foundation\",\"name\":\"Prytula Foundation\",\"tagline\":\"Defence technology and equipment for Ukraine\",\"urls\":{\"en\":\"https://prytulafoundation.org/en\",\"uk\":\"https://prytulafoundation.org/\"},\"tags\":[\"military\"]},{\"id\":\"world-central-kitchen\",\"name\":\"World Central Kitchen\",\"tagline\":\"Fresh meals for people in conflict zones\",\"urls\":{\"en\":\"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\",\"urls\":{\"en\":\"https://cats.kiev.ua\"},\"tags\":[\"animals\"]},{\"id\":\"uanimals\",\"name\":\"UAnimals\",\"tagline\":\"Animal rescue and advocacy organization in Ukraine\",\"urls\":{\"en\":\"https://uanimals.org/en/\",\"uk\":\"https://uanimals.org/\"},\"tags\":[\"animals\"]},{\"id\":\"hospitallers\",\"name\":\"Hospitallers\",\"tagline\":\"Ukrainian voluntary paramedics providing first aid and evacuation\",\"urls\":{\"en\":\"https://www.hospitallers.org.uk\",\"de\":\"https://www.hospitallers.org.uk/de\",\"es\":\"https://www.hospitallers.org.uk/es\",\"fr\":\"https://www.hospitallers.org.uk/fr\",\"it\":\"https://www.hospitallers.org.uk/it\",\"nl\":\"https://www.hospitallers.org.uk/nl\",\"pl\":\"https://www.hospitallers.org.uk/pl\",\"cs\":\"https://www.hospitallers.org.uk/cs\",\"sv\":\"https://www.hospitallers.org.uk/sv\"},\"tags\":[\"humanitarian\"]},{\"id\":\"sternenko-fund\",\"name\":\"Sternenko Fund\",\"tagline\":\"FPV drone supply for Ukrainian defence forces\",\"urls\":{\"en\":\"https://www.sternenkofund.org/en\",\"uk\":\"https://www.sternenkofund.org/\"},\"tags\":[\"military\"]},{\"id\":\"life-robots-ukraine\",\"name\":\"Life Robots Ukraine\",\"tagline\":\"Robots for demining Ukraine\",\"urls\":{\"en\":\"https://liferobots.com.ua/en\",\"uk\":\"https://liferobots.com.ua/\",\"de\":\"https://liferobots.com.ua/de\",\"es\":\"https://liferobots.com.ua/es\",\"fr\":\"https://liferobots.com.ua/fr\",\"ja\":\"https://liferobots.com.ua/ja\",\"ko\":\"https://liferobots.com.ua/ko\",\"nl\":\"https://liferobots.com.ua/nl\",\"pl\":\"https://liferobots.com.ua/pl\",\"he\":\"https://liferobots.com.ua/he\",\"lt\":\"https://liferobots.com.ua/lt\",\"lv\":\"https://liferobots.com.ua/lv\",\"no\":\"https://liferobots.com.ua/no\",\"ro\":\"https://liferobots.com.ua/ro\",\"ru\":\"https://liferobots.com.ua/ru\"},\"tags\":[\"humanitarian\"]},{\"id\":\"sirius-shelter\",\"name\":\"Sirius\",\"tagline\":\"Ukraine's largest animal shelter for dogs and cats\",\"urls\":{\"en\":\"https://dogcat.com.ua/en\",\"uk\":\"https://dogcat.com.ua/\"},\"tags\":[\"animals\"]},{\"id\":\"dignitas\",\"name\":\"Dignitas\",\"tagline\":\"Technology and support for Ukrainian defenders and veterans\",\"urls\":{\"en\":\"https://dignitas.fund/\",\"uk\":\"https://dignitas.fund/uk/\"},\"tags\":[\"military\"]},{\"id\":\"leleka\",\"name\":\"Leleka Foundation\",\"tagline\":\"Tactical medical supplies for Ukraine's frontline medics\",\"urls\":{\"en\":\"https://leleka.care/en\",\"uk\":\"https://leleka.care/ua\"},\"tags\":[\"humanitarian\"]},{\"id\":\"superhumans\",\"name\":\"Superhumans Center\",\"tagline\":\"Prosthetics, surgery, and rehabilitation for war survivors\",\"urls\":{\"en\":\"https://superhumans.com/en/\",\"uk\":\"https://superhumans.com/\"},\"tags\":[\"humanitarian\"]},{\"id\":\"nikopol-chance\",\"name\":\"Nikopol Chance\",\"tagline\":\"Dog shelter rescuing and rehoming strays in frontline Nikopol\",\"urls\":{\"en\":\"https://nikopolchance.com\"},\"tags\":[\"animals\"]},{\"id\":\"dzygaspaw\",\"name\":\"Dzyga’s Paw\",\"tagline\":\"Lifesaving tech for Ukrainian defenders\",\"urls\":{\"en\":\"https://dzygaspaw.com\",\"uk\":\"https://dzygaspaw.com/uk\",\"de\":\"https://dzygaspaw.com/de\"},\"tags\":[\"military\"]}]","export default \":host{display:block;margin:0;padding:0;border:none;font-size:16px;width:100%;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}section.support-ukraine-block{margin:0;padding:0;border:none;border-radius:0;width:100%;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){section.support-ukraine-block{background-color:gold}}section.support-ukraine-block--shift,section.support-ukraine-block--replace{position:relative}section.support-ukraine-block--overlap{position:fixed;top:0;left:0;z-index:2147483647}section.support-ukraine-block--refreshing .support-ukraine-block__link{opacity:0}section.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){section.support-ukraine-block .support-ukraine-block__link{transition:opacity .2s ease-in-out}}@media(prefers-color-scheme: dark){section.support-ukraine-block .support-ukraine-block__link{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}section.support-ukraine-block .support-ukraine-block__link:hover{opacity:.9}section.support-ukraine-block .support-ukraine-block__link:focus-visible{outline:2px solid #fff;outline-offset:-2px}section.support-ukraine-block .support-ukraine-block__flag{white-space:nowrap}section.support-ukraine-block .support-ukraine-block__prefix,section.support-ukraine-block .support-ukraine-block__info,section.support-ukraine-block .support-ukraine-block__colon,section.support-ukraine-block .support-ukraine-block__tagline{min-width:0}section.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){section.support-ukraine-block .support-ukraine-block__more{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}section.support-ukraine-block .support-ukraine-block__more:hover{opacity:1}section.support-ukraine-block .support-ukraine-block__more:focus-visible{outline:2px solid #fff;outline-offset:-2px}section.support-ukraine-block .support-ukraine-block__more-ellipsis{display:none}section.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){section.support-ukraine-block .support-ukraine-block__refresh{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}section.support-ukraine-block .support-ukraine-block__refresh:hover{opacity:1}section.support-ukraine-block .support-ukraine-block__refresh:focus-visible{outline:2px solid #fff;outline-offset:-2px}section.support-ukraine-block .support-ukraine-block__name{font-weight:bold}@media(prefers-contrast: more){section.support-ukraine-block{background-color:#003580}section.support-ukraine-block .support-ukraine-block__link,section.support-ukraine-block .support-ukraine-block__more,section.support-ukraine-block .support-ukraine-block__refresh{opacity:1;text-shadow:none}section.support-ukraine-block .support-ukraine-block__link:hover,section.support-ukraine-block .support-ukraine-block__more:hover,section.support-ukraine-block .support-ukraine-block__refresh:hover{opacity:1}}@media(prefers-contrast: more)and (prefers-color-scheme: dark){section.support-ukraine-block{background-color:gold}section.support-ukraine-block .support-ukraine-block__link,section.support-ukraine-block .support-ukraine-block__more,section.support-ukraine-block .support-ukraine-block__refresh{opacity:1;text-shadow:none}}@media(forced-colors: active){section.support-ukraine-block .support-ukraine-block__link:focus-visible,section.support-ukraine-block .support-ukraine-block__more:focus-visible,section.support-ukraine-block .support-ukraine-block__refresh:focus-visible{outline:2px solid Highlight}}@media(max-width: 58rem){section.support-ukraine-block .support-ukraine-block__prefix,section.support-ukraine-block .support-ukraine-block__name,section.support-ukraine-block .support-ukraine-block__colon,section.support-ukraine-block .support-ukraine-block__more,section.support-ukraine-block .support-ukraine-block__refresh{display:none}}@media(max-width: 35rem){section.support-ukraine-block .support-ukraine-block__name{display:initial}section.support-ukraine-block .support-ukraine-block__tagline{display:none}}[dir=rtl] section.support-ukraine-block .support-ukraine-block__link{text-align:right;justify-content:flex-end}[dir=rtl] section.support-ukraine-block .support-ukraine-block__more{text-align:right}[dir=rtl] section.support-ukraine-block .support-ukraine-block__refresh{text-align:right}:host-context([data-theme=dark]) section.support-ukraine-block{background-color:gold}:host-context([data-theme=dark]) section.support-ukraine-block .support-ukraine-block__link{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=dark]) section.support-ukraine-block .support-ukraine-block__more{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=dark]) section.support-ukraine-block .support-ukraine-block__refresh{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=light]) section.support-ukraine-block{background-color:#0057b7}:host-context([data-theme=light]) section.support-ukraine-block .support-ukraine-block__link{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}:host-context([data-theme=light]) section.support-ukraine-block .support-ukraine-block__more{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}:host-context([data-theme=light]) section.support-ukraine-block .support-ukraine-block__refresh{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}@media(prefers-contrast: more){:host-context([data-theme=light]) section.support-ukraine-block{background-color:#003580}:host-context([data-theme=light]) section.support-ukraine-block .support-ukraine-block__link,:host-context([data-theme=light]) section.support-ukraine-block .support-ukraine-block__more,:host-context([data-theme=light]) section.support-ukraine-block .support-ukraine-block__refresh,:host-context([data-theme=dark]) section.support-ukraine-block .support-ukraine-block__link,:host-context([data-theme=dark]) section.support-ukraine-block .support-ukraine-block__more,:host-context([data-theme=dark]) section.support-ukraine-block .support-ukraine-block__refresh{opacity:1;text-shadow:none}}\"","// 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 { baseLanguage } from './language.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`\nconst bannerState = { count: 0 } // Suffix for hint ids so repeated banners stay unique.\n\nconst memorySeen = new Set<string>() // Session-only seen ids, used when persistSeen is false.\n\n// @internal — test helper resetting the session-only seen set.\nexport function resetMemorySeen(): void {\n memorySeen.clear()\n}\n\nfunction readSeen(shouldPersist: boolean): Set<string> {\n if (!shouldPersist) return new Set(memorySeen)\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>, shouldPersist: boolean): void {\n if (!shouldPersist) {\n memorySeen.clear()\n for (const id of seen) memorySeen.add(id)\n return\n }\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, shouldPersist: boolean): void {\n const seen = readSeen(shouldPersist)\n mutate(seen)\n writeSeen(seen, shouldPersist)\n}\n\n/**\nPick a random item from an array.\n\n@internal\n*/\nexport function randomItem<T>(items: T[]): T {\n const item = items[Math.floor(Math.random() * items.length)]\n if (item === undefined) throw new Error('randomItem: cannot pick from an empty array')\n return item\n}\n\nfunction pickCharity(\n candidates: Charity[],\n shouldAvoidRepeat: boolean,\n shouldPersist: boolean,\n lang: string,\n excludeId?: string,\n excludedUrls: ReadonlySet<string> = new Set<string>()\n): Charity {\n let pool = excludeId ? candidates.filter(c => c.id !== excludeId) : candidates\n const withoutUrl = pool.filter(c => !excludedUrls.has(charityUrlFor(c, lang)))\n if (withoutUrl.length > 0) pool = withoutUrl\n if (pool.length === 0) pool = candidates\n\n if (shouldAvoidRepeat) {\n updateSeen(seen => {\n const unseen = pool.filter(c => !seen.has(c.id))\n if (unseen.length > 0) {\n pool = unseen\n } else {\n seen.clear()\n }\n }, shouldPersist)\n }\n\n const charity = randomItem(pool)\n\n if (shouldAvoidRepeat) {\n updateSeen(seen => {\n seen.add(charity.id)\n }, shouldPersist)\n }\n\n return charity\n}\n\n// @internal — exported so the test can prove the injection stays idempotent.\nexport function 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/**\nMerge 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 return translated?.tagline ? { ...charity, tagline: translated.tagline } : charity\n })\n}\n\n/**\nResolve the donation URL for a charity in the given banner language.\nFalls back to English.\n*/\nexport function charityUrlFor(charity: Charity, lang: string): string {\n const base = baseLanguage(lang)\n return charity.urls[base] ?? charity.urls.en\n}\n\nexport function isRTL(lang: string): boolean {\n return baseLanguage(lang) === 'ar'\n}\n\nexport function isDoNotTrackEnabled(): boolean {\n if (typeof navigator === 'undefined') return false\n const dnt = navigator.doNotTrack\n if (dnt === '1' || dnt === 'yes') return true\n const win = globalThis.window\n if (win) {\n const dntWin = (win as unknown as { doNotTrack?: string }).doNotTrack\n if (dntWin === '1' || dntWin === 'yes') return true\n const msDnt = (navigator as unknown as { msDoNotTrack?: string }).msDoNotTrack\n if (msDnt === '1') return true\n }\n return false\n}\n\nexport function buildUtmUrl(baseUrl: string, options: SupportUkraineBlockOptions): string {\n // Default utmEnabled to true if not explicitly set to false\n if (options.utmEnabled === false) return baseUrl\n if (isDoNotTrackEnabled()) return baseUrl\n\n const source = options.utmSource ?? globalThis.window?.location?.hostname ?? ''\n if (!source) return baseUrl\n\n const medium = options.utmMedium ?? 'support-ukraine-banner'\n const campaign = options.utmCampaign ?? ''\n\n try {\n const url = new URL(baseUrl)\n url.searchParams.set('utm_source', source)\n url.searchParams.set('utm_medium', medium)\n if (campaign) url.searchParams.set('utm_campaign', campaign)\n return url.href\n } catch {\n return baseUrl\n }\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/**\nMount the banner with already-resolved `lang` and `messages`.\nShared 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 exclude,\n dontRepeat = true,\n persistSeen = false,\n isInConsole = true,\n showRefreshButton = false,\n autoRefreshInterval = 0,\n refreshOnClick = true,\n refreshOnClickDelay = 2000,\n showRefreshAnimation = false\n } = options\n\n const baseCharities = charities ? charitiesSchema.parse(charities) : DEFAULT_CHARITIES\n const localizedCharities = mergeCharities(baseCharities, messages)\n\n let candidates = tags\n ? localizedCharities.filter(charity => charity.tags.some(t => tags.includes(t)))\n : localizedCharities\n\n const excluded = new Set(exclude)\n const kept = candidates.filter(charity => !excluded.has(charity.id))\n if (kept.length > 0) candidates = kept\n\n if (candidates.length === 0) {\n candidates = localizedCharities\n }\n\n const charity = pickCharity(candidates, dontRepeat, persistSeen, lang)\n let currentCharity = charity\n let currentCharityUrl = charityUrlFor(charity, lang)\n\n const host = document.createElement('div')\n\n const shadow = host.attachShadow({ mode: 'open' })\n injectShadowStyles(shadow)\n\n const banner = document.createElement('section')\n banner.className = `${CSS_PREFIX} ${CSS_PREFIX}--${mode}`\n banner.lang = lang\n banner.setAttribute('aria-label', messages.regionLabel)\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 = buildUtmUrl(currentCharityUrl, options)\n link.target = '_blank'\n link.rel = 'noopener noreferrer'\n link.style.fontSize = fontSize\n\n const instanceSuffix = ++bannerState.count // Unique per mount for hint ids.\n const linkNewTabId = `${CSS_PREFIX}-link-new-tab-${instanceSuffix}`\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 flag.setAttribute('aria-hidden', 'true') // Flag duplicates \"Ukraine\" in link text.\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 = buildUtmUrl('https://damian-buho.github.io/support-ukraine/', options)\n moreLink.target = '_blank'\n moreLink.rel = 'noopener noreferrer'\n moreLink.style.fontSize = fontSize\n\n const moreNewTabId = `${CSS_PREFIX}-more-new-tab-${instanceSuffix}`\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 currentCharity = next\n currentCharityUrl = charityUrlFor(next, lang)\n link.href = buildUtmUrl(currentCharityUrl, options)\n name.textContent = next.name\n tagline.textContent = next.tagline\n if (isInConsole) {\n console.info('[support-ukraine] banner', `${next.name}: ${next.tagline}`, currentCharityUrl)\n }\n }\n\n function updateCharity(): void {\n const next = pickCharity(\n candidates,\n dontRepeat,\n persistSeen,\n lang,\n currentCharity.id,\n new Set([currentCharityUrl])\n )\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 let clickRefreshTimer: ReturnType<typeof setTimeout> | undefined\n function cancelClickRefresh(): void {\n clearTimeout(clickRefreshTimer)\n clickRefreshTimer = undefined\n document.removeEventListener('visibilitychange', handlePageHidden)\n globalThis.window?.removeEventListener?.('blur', handleWindowBlur)\n }\n function handlePageHidden(): void {\n if (!document.hidden) return\n cancelClickRefresh()\n updateCharity()\n }\n function handleWindowBlur(): void {\n cancelClickRefresh()\n updateCharity()\n }\n function scheduleClickRefresh(): void {\n if (clickRefreshTimer !== undefined) return\n document.addEventListener('visibilitychange', handlePageHidden)\n globalThis.window?.addEventListener?.('blur', handleWindowBlur)\n clickRefreshTimer = setTimeout(() => {\n cancelClickRefresh()\n updateCharity()\n }, refreshOnClickDelay)\n }\n\n if (refreshOnClick) {\n link.addEventListener('click', scheduleClickRefresh)\n }\n\n if (showRefreshButton) {\n const refreshButton = document.createElement('button')\n refreshButton.className = `${CSS_PREFIX}__refresh`\n refreshButton.type = 'button'\n refreshButton.style.fontSize = fontSize\n refreshButton.setAttribute('aria-label', messages.refresh)\n refreshButton.addEventListener('click', updateCharity)\n const refreshGlyph = document.createElement('span')\n refreshGlyph.textContent = REFRESH_GLYPH\n refreshGlyph.setAttribute('aria-hidden', 'true') // Name comes from aria-label.\n refreshButton.append(refreshGlyph)\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(\n '[support-ukraine] banner',\n `${charity.name}: ${charity.tagline}`,\n currentCharityUrl\n )\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 cancelClickRefresh()\n clearInterval(intervalId)\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/**\nLocalized `supportUkraineBlock` with `es` baked in.\n\nThis build is self-contained — the locale messages are bundled inline, so\nno second network request is needed. For optimal Core Web Vitals, load\nonly the locale you need:\n\n```ts\nimport { supportUkraineBlock } from '@damian-buho/support-ukraine/es'\nawait supportUkraineBlock()\n```\n\nThe `locale` option is ignored in this build (the bundle is already\nlocalized). Use the auto-detect build (`@damian-buho/support-ukraine`)\nif 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","parseLocalizedUrls","entries","result","key","entry","parseCharity","record","tag","charitySchema","charitiesSchema","item","baseLanguage","tag","dash","charities_default","styles_default","DEFAULT_CHARITIES","charitiesSchema","charities_default","CSS_PREFIX","STORAGE_KEY","REFRESH_GLYPH","VISUALLY_HIDDEN_CLASS","bannerState","memorySeen","readSeen","shouldPersist","memorySeen","raw","STORAGE_KEY","writeSeen","seen","id","updateSeen","mutate","randomItem","items","item","pickCharity","candidates","shouldAvoidRepeat","lang","excludeId","excludedUrls","pool","c","withoutUrl","charityUrlFor","unseen","charity","injectShadowStyles","shadowRoot","CSS_PREFIX","style","styles_default","mergeCharities","base","locale","translated","baseLanguage","isRTL","isDoNotTrackEnabled","dnt","win","dntWin","buildUtmUrl","baseUrl","options","source","medium","campaign","url","formatBannerText","messages","mountBanner","mode","fontSize","charities","tags","exclude","dontRepeat","persistSeen","isInConsole","showRefreshButton","autoRefreshInterval","refreshOnClick","refreshOnClickDelay","showRefreshAnimation","baseCharities","charitiesSchema","DEFAULT_CHARITIES","localizedCharities","t","excluded","kept","currentCharity","currentCharityUrl","host","shadow","banner","link","instanceSuffix","bannerState","linkNewTabId","linkNewTabHint","VISUALLY_HIDDEN_CLASS","flag","prefix","info","name","colon","tagline","moreLink","moreNewTabId","moreNewTabHint","moreText","moreEllipsis","applyNext","next","updateCharity","clickRefreshTimer","cancelClickRefresh","handlePageHidden","handleWindowBlur","scheduleClickRefresh","refreshButton","refreshGlyph","REFRESH_GLYPH","mount","placeholder","intervalId","instance","LANG","supportUkraineBlock","options","mountBanner","es_default"]}
package/dist/fr.js CHANGED
@@ -1,2 +1,2 @@
1
- var Z={supportUkraine:"Soutenir l'Ukraine avec",regionLabel:"Banni\xE8re de soutien \xE0 l'Ukraine",more:"plus\u2026",donate:"Faire un don",refresh:"Afficher la charity suivante",opensInNewTab:"(s\\u0201ouvre dans un nouvel onglet)",charities:{united24:{tagline:"Plateforme officielle de collecte de fonds de l'Ukraine"},"come-back-alive":{tagline:"Soutenir les forces arm\xE9es ukrainiennes depuis 2014"},"razom-for-ukraine":{tagline:"Intervention d'urgence et aide humanitaire"},"ukrainian-red-cross":{tagline:"Assistance humanitaire en zones de conflit"},"nova-ukraine":{tagline:"Aide humanitaire et d\xE9fense des droits"},"voices-of-children":{tagline:"Soutien psychologique pour les enfants victimes de la guerre"},"prytula-foundation":{tagline:"Technologies de d\xE9fense et \xE9quipements pour l'Ukraine"},"medical-hilfe":{tagline:"Fournitures m\xE9dicales pour les h\xF4pitaux ukrainiens"},"army-of-drones":{tagline:"Drones de reconnaissance pour le front"},"world-central-kitchen":{tagline:"Repas frais pour les personnes en zones de conflit"},"cats-of-kyiv":{tagline:"Refuge pour chats qui secourt et reloge des chats \xE0 Kyiv"},uanimals:{tagline:"Organisation de sauvetage animal et de d\xE9fense des droits en Ukraine"},hospitallers:{tagline:"Param\xE9dics b\xE9n\xE9voles ukrainiens assurant les premiers secours et l'\xE9vacuation"},"sternenko-fund":{tagline:"Fourniture de drones FPV pour les forces de d\xE9fense ukrainiennes"},"life-robots-ukraine":{tagline:"Des robots pour le d\xE9minage de l'Ukraine"},"sirius-shelter":{tagline:"Le plus grand refuge animal d'Ukraine pour les chiens et les chats"}}};var ee=["military","humanitarian","animals"];function k(e,t){if(!e)throw new Error(t)}function $(e,t){k(typeof e=="string",`${t} must be a string`),k(e.length>0,`${t} must not be empty`)}function _e(e,t){$(e,t);try{new URL(e)}catch{throw new Error(`${t} must be a valid URL`)}}function xe(e){return k(ee.includes(e),`Invalid tag: ${String(e)}. Must be one of: ${ee.join(", ")}`),e}function we(e){k(e!==null&&typeof e=="object","urls must be an object");let t=Object.entries(e);k(t.length>0,"urls must not be empty");let n={};for(let[i,a]of t)_e(a,`urls.${i}`),n[i.toLowerCase()]=a;return k(typeof n.en=="string",'urls must include an "en" entry'),n}function te(e){k(e!==null&&typeof e=="object","Charity must be an object");let t=e;return $(t.id,"id"),$(t.name,"name"),$(t.tagline,"tagline"),k(Array.isArray(t.tags),"tags must be an array"),k(t.tags.length>0,"tags must not be empty"),{id:t.id,name:t.name,tagline:t.tagline,urls:we(t.urls),tags:t.tags.map(n=>xe(n))}}var ve={parse:te},N={parse(e){return k(Array.isArray(e),"Charities must be an array"),e.map(t=>te(t))}};var ne=[{id:"united24",name:"United24",tagline:"Official fundraising platform of Ukraine",urls:{en:"https://u24.gov.ua/en",uk:"https://u24.gov.ua/uk"},tags:["humanitarian"]},{id:"come-back-alive",name:"Come Back Alive",tagline:"Supporting the Ukrainian Armed Forces since 2014",urls:{en:"https://savelife.in.ua/en/",uk:"https://savelife.in.ua/"},tags:["military"]},{id:"razom-for-ukraine",name:"Razom for Ukraine",tagline:"Emergency response and humanitarian aid",urls:{en:"https://www.razomforukraine.org",uk:"https://www.razomforukraine.org/ua/"},tags:["humanitarian"]},{id:"ukrainian-red-cross",name:"Ukrainian Red Cross",tagline:"Humanitarian assistance in conflict zones",urls:{en:"https://redcross.org.ua/en/",uk:"https://redcross.org.ua/"},tags:["humanitarian"]},{id:"nova-ukraine",name:"Nova Ukraine",tagline:"Humanitarian aid and advocacy",urls:{en:"https://novaukraine.org",uk:"https://novaukraine.org.ua/"},tags:["humanitarian"]},{id:"voices-of-children",name:"Voices of Children",tagline:"Psychological support for children affected by war",urls:{en:"https://voices.org.ua/en/",uk:"https://voices.org.ua/"},tags:["humanitarian"]},{id:"prytula-foundation",name:"Prytula Foundation",tagline:"Defence technology and equipment for Ukraine",urls:{en:"https://prytulafoundation.org/en",uk:"https://prytulafoundation.org/"},tags:["military"]},{id:"world-central-kitchen",name:"World Central Kitchen",tagline:"Fresh meals for people in conflict zones",urls:{en:"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",urls:{en:"https://cats.kiev.ua"},tags:["animals"]},{id:"uanimals",name:"UAnimals",tagline:"Animal rescue and advocacy organization in Ukraine",urls:{en:"https://uanimals.org/en/",uk:"https://uanimals.org/"},tags:["animals"]},{id:"hospitallers",name:"Hospitallers",tagline:"Ukrainian voluntary paramedics providing first aid and evacuation",urls:{en:"https://www.hospitallers.org.uk",de:"https://www.hospitallers.org.uk/de",es:"https://www.hospitallers.org.uk/es",fr:"https://www.hospitallers.org.uk/fr",it:"https://www.hospitallers.org.uk/it",nl:"https://www.hospitallers.org.uk/nl",pl:"https://www.hospitallers.org.uk/pl",cs:"https://www.hospitallers.org.uk/cs",sv:"https://www.hospitallers.org.uk/sv"},tags:["humanitarian"]},{id:"sternenko-fund",name:"Sternenko Fund",tagline:"FPV drone supply for Ukrainian defence forces",urls:{en:"https://www.sternenkofund.org/en",uk:"https://www.sternenkofund.org/"},tags:["military"]},{id:"life-robots-ukraine",name:"Life Robots Ukraine",tagline:"Robots for demining Ukraine",urls:{en:"https://liferobots.com.ua/en",uk:"https://liferobots.com.ua/",de:"https://liferobots.com.ua/de",es:"https://liferobots.com.ua/es",fr:"https://liferobots.com.ua/fr",ja:"https://liferobots.com.ua/ja",ko:"https://liferobots.com.ua/ko",nl:"https://liferobots.com.ua/nl",pl:"https://liferobots.com.ua/pl",he:"https://liferobots.com.ua/he",lt:"https://liferobots.com.ua/lt",lv:"https://liferobots.com.ua/lv",no:"https://liferobots.com.ua/no",ro:"https://liferobots.com.ua/ro",ru:"https://liferobots.com.ua/ru"},tags:["humanitarian"]},{id:"sirius-shelter",name:"Sirius",tagline:"Ukraine's largest animal shelter for dogs and cats",urls:{en:"https://dogcat.com.ua/en",uk:"https://dogcat.com.ua/"},tags:["animals"]},{id:"dignitas",name:"Dignitas",tagline:"Technology and support for Ukrainian defenders and veterans",urls:{en:"https://dignitas.fund/",uk:"https://dignitas.fund/uk/"},tags:["military"]},{id:"leleka",name:"Leleka Foundation",tagline:"Tactical medical supplies for Ukraine's frontline medics",urls:{en:"https://leleka.care/en",uk:"https://leleka.care/ua"},tags:["humanitarian"]},{id:"superhumans",name:"Superhumans Center",tagline:"Prosthetics, surgery, and rehabilitation for war survivors",urls:{en:"https://superhumans.com/en/",uk:"https://superhumans.com/"},tags:["humanitarian"]},{id:"nikopol-chance",name:"Nikopol Chance",tagline:"Dog shelter rescuing and rehoming strays in frontline Nikopol",urls:{en:"https://nikopolchance.com"},tags:["animals"]}];var re=":host{display:block;margin:0;padding:0;border:none;font-size:16px;width:100%;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}section.support-ukraine-block{margin:0;padding:0;border:none;border-radius:0;width:100%;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){section.support-ukraine-block{background-color:gold}}section.support-ukraine-block--shift,section.support-ukraine-block--replace{position:relative}section.support-ukraine-block--overlap{position:fixed;top:0;left:0;z-index:2147483647}section.support-ukraine-block--refreshing .support-ukraine-block__link{opacity:0}section.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){section.support-ukraine-block .support-ukraine-block__link{transition:opacity .2s ease-in-out}}@media(prefers-color-scheme: dark){section.support-ukraine-block .support-ukraine-block__link{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}section.support-ukraine-block .support-ukraine-block__link:hover{opacity:.9}section.support-ukraine-block .support-ukraine-block__link:focus-visible{outline:2px solid #fff;outline-offset:-2px}section.support-ukraine-block .support-ukraine-block__flag{white-space:nowrap}section.support-ukraine-block .support-ukraine-block__prefix,section.support-ukraine-block .support-ukraine-block__info,section.support-ukraine-block .support-ukraine-block__colon,section.support-ukraine-block .support-ukraine-block__tagline{min-width:0}section.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){section.support-ukraine-block .support-ukraine-block__more{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}section.support-ukraine-block .support-ukraine-block__more:hover{opacity:1}section.support-ukraine-block .support-ukraine-block__more:focus-visible{outline:2px solid #fff;outline-offset:-2px}section.support-ukraine-block .support-ukraine-block__more-ellipsis{display:none}section.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){section.support-ukraine-block .support-ukraine-block__refresh{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}section.support-ukraine-block .support-ukraine-block__refresh:hover{opacity:1}section.support-ukraine-block .support-ukraine-block__refresh:focus-visible{outline:2px solid #fff;outline-offset:-2px}section.support-ukraine-block .support-ukraine-block__name{font-weight:bold}@media(prefers-contrast: more){section.support-ukraine-block{background-color:#003580}section.support-ukraine-block .support-ukraine-block__link,section.support-ukraine-block .support-ukraine-block__more,section.support-ukraine-block .support-ukraine-block__refresh{opacity:1;text-shadow:none}section.support-ukraine-block .support-ukraine-block__link:hover,section.support-ukraine-block .support-ukraine-block__more:hover,section.support-ukraine-block .support-ukraine-block__refresh:hover{opacity:1}}@media(prefers-contrast: more)and (prefers-color-scheme: dark){section.support-ukraine-block{background-color:gold}section.support-ukraine-block .support-ukraine-block__link,section.support-ukraine-block .support-ukraine-block__more,section.support-ukraine-block .support-ukraine-block__refresh{opacity:1;text-shadow:none}}@media(forced-colors: active){section.support-ukraine-block .support-ukraine-block__link:focus-visible,section.support-ukraine-block .support-ukraine-block__more:focus-visible,section.support-ukraine-block .support-ukraine-block__refresh:focus-visible{outline:2px solid Highlight}}@media(max-width: 58rem){section.support-ukraine-block .support-ukraine-block__prefix,section.support-ukraine-block .support-ukraine-block__name,section.support-ukraine-block .support-ukraine-block__colon,section.support-ukraine-block .support-ukraine-block__more,section.support-ukraine-block .support-ukraine-block__refresh{display:none}}@media(max-width: 35rem){section.support-ukraine-block .support-ukraine-block__name{display:initial}section.support-ukraine-block .support-ukraine-block__tagline{display:none}}[dir=rtl] section.support-ukraine-block .support-ukraine-block__link{text-align:right;justify-content:flex-end}[dir=rtl] section.support-ukraine-block .support-ukraine-block__more{text-align:right}[dir=rtl] section.support-ukraine-block .support-ukraine-block__refresh{text-align:right}:host-context([data-theme=dark]) section.support-ukraine-block{background-color:gold}:host-context([data-theme=dark]) section.support-ukraine-block .support-ukraine-block__link{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=dark]) section.support-ukraine-block .support-ukraine-block__more{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=dark]) section.support-ukraine-block .support-ukraine-block__refresh{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=light]) section.support-ukraine-block{background-color:#0057b7}:host-context([data-theme=light]) section.support-ukraine-block .support-ukraine-block__link{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}:host-context([data-theme=light]) section.support-ukraine-block .support-ukraine-block__more{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}:host-context([data-theme=light]) section.support-ukraine-block .support-ukraine-block__refresh{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}@media(prefers-contrast: more){:host-context([data-theme=light]) section.support-ukraine-block{background-color:#003580}:host-context([data-theme=light]) section.support-ukraine-block .support-ukraine-block__link,:host-context([data-theme=light]) section.support-ukraine-block .support-ukraine-block__more,:host-context([data-theme=light]) section.support-ukraine-block .support-ukraine-block__refresh,:host-context([data-theme=dark]) section.support-ukraine-block .support-ukraine-block__link,:host-context([data-theme=dark]) section.support-ukraine-block .support-ukraine-block__more,:host-context([data-theme=dark]) section.support-ukraine-block .support-ukraine-block__refresh{opacity:1;text-shadow:none}}";var se=N.parse(ne),o="support-ukraine-block",le="support-ukraine-seen",Ce="\u27F3",oe=`${o}__visually-hidden`,Se={count:0},H=new Set;function Te(e){if(!e)return new Set(H);try{let t=localStorage.getItem(le);return t?new Set(JSON.parse(t)):new Set}catch{return new Set}}function Ee(e,t){if(!t){H.clear();for(let n of e)H.add(n);return}try{localStorage.setItem(le,JSON.stringify([...e]))}catch{}}function ie(e,t){let n=Te(t);e(n),Ee(n,t)}function ue(e){if(e.length===0)throw new Error("randomItem: cannot pick from an empty array");return e[Math.floor(Math.random()*e.length)]}function ae(e,t,n,i,a,c){let s=a?e.filter(l=>l.id!==a):e;if(c&&s.length>1){let l=s.filter(f=>j(f,i)!==c);l.length>0&&(s=l)}s.length===0&&(s=e),t&&ie(l=>{let f=s.filter(v=>!l.has(v.id));f.length>0?s=f:l.clear()},n);let g=ue(s);return t&&ie(l=>{l.add(g.id)},n),g}function Le(e){let t=`${o}-styles`;if(e.querySelector(`#${t}`))return;let n=e.ownerDocument.createElement("style");n.id=t,n.textContent=re,e.append(n)}function ce(e,t){return e.map(n=>{let i=t.charities[n.id];return i?.tagline?{...n,tagline:i.tagline}:n})}function j(e,t){let n=(t.split("-",1)[0]??"").toLowerCase();return e.urls[n]??e.urls.en}function pe(e){return(e.split("-",1)[0]??"").toLowerCase()==="ar"}function Ue(){if(typeof navigator>"u")return!1;let e=navigator.doNotTrack;if(e==="1"||e==="yes")return!0;let t=globalThis.window;if(t){let n=t.doNotTrack;if(n==="1"||n==="yes"||navigator.msDoNotTrack==="1")return!0}return!1}function O(e,t){if(t.utmEnabled===!1||Ue())return e;let n=t.utmSource??globalThis.window?.location?.hostname??"";if(!n)return e;let i=t.utmMedium??"support-ukraine-banner",a=t.utmCampaign??"";try{let c=new URL(e);return c.searchParams.set("utm_source",n),c.searchParams.set("utm_medium",i),a&&c.searchParams.set("utm_campaign",a),c.href}catch{return e}}function $e(e,t){return`\u{1F1FA}\u{1F1E6} ${t.supportUkraine} ${e.name}: ${e.tagline}`}function ke(e,t,n={}){let{mode:i="shift",fontSize:a="87.5%",charities:c,tags:s,exclude:g,dontRepeat:l=!0,persistSeen:f=!1,isInConsole:v=!0,showRefreshButton:de=!1,autoRefreshInterval:P=0,refreshOnClick:me=!0,refreshOnClickDelay:he=2e3,showRefreshAnimation:fe=!1}=n,ge=c?N.parse(c):se,R=ce(ge,t),b=s&&s.length>0?R.filter(r=>r.tags.some(h=>s.includes(h))):R;if(g&&g.length>0){let r=new Set(g),h=b.filter(ye=>!r.has(ye.id));h.length>0&&(b=h)}b.length===0&&(b=R);let y=ae(b,l,f,e),q=y,_=j(y,e),m=document.createElement("div"),G=m.attachShadow({mode:"open"});Le(G);let u=document.createElement("section");u.className=`${o} ${o}--${i}`,u.lang=e,u.setAttribute("aria-label",t.regionLabel),pe(e)&&u.setAttribute("dir","rtl");let p=document.createElement("a");p.className=`${o}__link`,p.href=O(_,n),p.target="_blank",p.rel="noopener noreferrer",p.style.fontSize=a;let V=++Se.count,K=`${o}-link-new-tab-${V}`,C=document.createElement("span");C.id=K,C.className=oe,C.textContent=t.opensInNewTab,p.setAttribute("aria-describedby",K);let S=document.createElement("span");S.className=`${o}__flag`,S.textContent="\u{1F1FA}\u{1F1E6} ",S.setAttribute("aria-hidden","true");let A=document.createElement("span");A.className=`${o}__prefix`,A.textContent=`${t.supportUkraine} `;let I=document.createElement("span");I.className=`${o}__info`;let T=document.createElement("span");T.className=`${o}__name`,T.textContent=y.name;let z=document.createElement("span");z.className=`${o}__colon`,z.textContent=": ";let E=document.createElement("span");E.className=`${o}__tagline`,E.textContent=y.tagline,I.append(T,z,E),p.append(S,A,I),u.append(p);let d=document.createElement("a");d.className=`${o}__more`,d.href=O("https://damian-buho.github.io/support-ukraine/",n),d.target="_blank",d.rel="noopener noreferrer",d.style.fontSize=a;let W=`${o}-more-new-tab-${V}`,L=document.createElement("span");L.id=W,L.className=oe,L.textContent=t.opensInNewTab,d.setAttribute("aria-describedby",W);let F=document.createElement("span");F.className=`${o}__more-text`,F.textContent=t.more;let B=document.createElement("span");B.className=`${o}__more-ellipsis`,B.textContent="\u2026",d.append(F,B),u.append(d),u.append(C,L);function Y(r){q=r,_=j(r,e),p.href=O(_,n),T.textContent=r.name,E.textContent=r.tagline,v&&console.info("[support-ukraine] banner",`${r.name}: ${r.tagline}`,_)}function x(){let r=ae(b,l,f,e,q.id,_);fe?(u.classList.add(`${o}--refreshing`),setTimeout(()=>{Y(r),u.classList.remove(`${o}--refreshing`)},200)):Y(r)}let w;function U(){w!==void 0&&(clearTimeout(w),w=void 0),document.removeEventListener("visibilitychange",J),globalThis.window?.removeEventListener?.("blur",X)}function J(){document.hidden&&(U(),x())}function X(){U(),x()}function be(){w===void 0&&(document.addEventListener("visibilitychange",J),globalThis.window?.addEventListener?.("blur",X),w=setTimeout(()=>{U(),x()},he))}if(me&&p.addEventListener("click",be),de){let r=document.createElement("button");r.className=`${o}__refresh`,r.type="button",r.textContent="",r.style.fontSize=a,r.setAttribute("aria-label",t.refresh),r.addEventListener("click",x);let h=document.createElement("span");h.textContent=Ce,h.setAttribute("aria-hidden","true"),r.append(h),u.insertBefore(r,d)}G.append(u);let D=n.element??document.body;if(i==="replace"){let r=D.querySelector(`.${o}`);r?r.replaceWith(m):D.prepend(m)}else D.prepend(m);v&&console.info("[support-ukraine] banner",`${y.name}: ${y.tagline}`,_),m.dataset.supportUkraine="",m.classList.add(`${o}--processed`);let M;P>0&&(M=setInterval(x,P));let Q=m;return Q.destroy=()=>{U(),M!==void 0&&clearInterval(M),m.remove()},Q}var Ne="fr";function je(e={}){return Promise.resolve(ke(Ne,Z,e))}export{se as DEFAULT_CHARITIES,N as charitiesSchema,ve as charitySchema,$e as formatBannerText,pe as isRTL,ce as mergeCharities,ue as randomItem,je as supportUkraineBlock};
1
+ var ne={supportUkraine:"Soutenir l'Ukraine avec",regionLabel:"Banni\xE8re de soutien \xE0 l'Ukraine",more:"plus\u2026",donate:"Faire un don",refresh:"Afficher la charity suivante",opensInNewTab:"(s\\u0201ouvre dans un nouvel onglet)",charities:{united24:{tagline:"Plateforme officielle de collecte de fonds de l'Ukraine"},"come-back-alive":{tagline:"Soutenir les forces arm\xE9es ukrainiennes depuis 2014"},"razom-for-ukraine":{tagline:"Intervention d'urgence et aide humanitaire"},"ukrainian-red-cross":{tagline:"Assistance humanitaire en zones de conflit"},"nova-ukraine":{tagline:"Aide humanitaire et d\xE9fense des droits"},"voices-of-children":{tagline:"Soutien psychologique pour les enfants victimes de la guerre"},"prytula-foundation":{tagline:"Technologies de d\xE9fense et \xE9quipements pour l'Ukraine"},"medical-hilfe":{tagline:"Fournitures m\xE9dicales pour les h\xF4pitaux ukrainiens"},"army-of-drones":{tagline:"Drones de reconnaissance pour le front"},"world-central-kitchen":{tagline:"Repas frais pour les personnes en zones de conflit"},"cats-of-kyiv":{tagline:"Refuge pour chats qui secourt et reloge des chats \xE0 Kyiv"},uanimals:{tagline:"Organisation de sauvetage animal et de d\xE9fense des droits en Ukraine"},hospitallers:{tagline:"Param\xE9dics b\xE9n\xE9voles ukrainiens assurant les premiers secours et l'\xE9vacuation"},"sternenko-fund":{tagline:"Fourniture de drones FPV pour les forces de d\xE9fense ukrainiennes"},"life-robots-ukraine":{tagline:"Des robots pour le d\xE9minage de l'Ukraine"},"sirius-shelter":{tagline:"Le plus grand refuge animal d'Ukraine pour les chiens et les chats"}}};var re=["military","humanitarian","animals"];function p(e,t){if(!e)throw new Error(t)}function $(e,t){p(typeof e=="string",`${t} must be a string`),p(e.length>0,`${t} must not be empty`)}function we(e,t){$(e,t);try{new URL(e)}catch{throw new Error(`${t} must be a valid URL`)}}function ve(e){return p(re.includes(e),`Invalid tag: ${String(e)}. Must be one of: ${re.join(", ")}`),e}function Ce(e){p(e!==null&&typeof e=="object","urls must be an object");let t=Object.entries(e);p(t.length>0,"urls must not be empty");let n={};for(let[i,a]of t)we(a,`urls.${i}`),n[i.toLowerCase()]=a;return p(typeof n.en=="string",'urls must include an "en" entry'),n}function oe(e){p(e!==null&&typeof e=="object","Charity must be an object");let t=e;return $(t.id,"id"),$(t.name,"name"),$(t.tagline,"tagline"),p(Array.isArray(t.tags),"tags must be an array"),p(t.tags.length>0,"tags must not be empty"),{id:t.id,name:t.name,tagline:t.tagline,urls:Ce(t.urls),tags:t.tags.map(n=>ve(n))}}var Se={parse:oe},N={parse(e){return p(Array.isArray(e),"Charities must be an array"),e.map(t=>oe(t))}};function O(e){let t=e.indexOf("-");return(t===-1?e:e.slice(0,t)).toLowerCase()}var ie=[{id:"united24",name:"United24",tagline:"Official fundraising platform of Ukraine",urls:{en:"https://u24.gov.ua/en",uk:"https://u24.gov.ua/uk"},tags:["humanitarian"]},{id:"come-back-alive",name:"Come Back Alive",tagline:"Supporting the Ukrainian Armed Forces since 2014",urls:{en:"https://savelife.in.ua/en/",uk:"https://savelife.in.ua/"},tags:["military"]},{id:"razom-for-ukraine",name:"Razom for Ukraine",tagline:"Emergency response and humanitarian aid",urls:{en:"https://www.razomforukraine.org",uk:"https://www.razomforukraine.org/ua/"},tags:["humanitarian"]},{id:"ukrainian-red-cross",name:"Ukrainian Red Cross",tagline:"Humanitarian assistance in conflict zones",urls:{en:"https://redcross.org.ua/en/",uk:"https://redcross.org.ua/"},tags:["humanitarian"]},{id:"nova-ukraine",name:"Nova Ukraine",tagline:"Humanitarian aid and advocacy",urls:{en:"https://novaukraine.org",uk:"https://novaukraine.org.ua/"},tags:["humanitarian"]},{id:"voices-of-children",name:"Voices of Children",tagline:"Psychological support for children affected by war",urls:{en:"https://voices.org.ua/en/",uk:"https://voices.org.ua/"},tags:["humanitarian"]},{id:"prytula-foundation",name:"Prytula Foundation",tagline:"Defence technology and equipment for Ukraine",urls:{en:"https://prytulafoundation.org/en",uk:"https://prytulafoundation.org/"},tags:["military"]},{id:"world-central-kitchen",name:"World Central Kitchen",tagline:"Fresh meals for people in conflict zones",urls:{en:"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",urls:{en:"https://cats.kiev.ua"},tags:["animals"]},{id:"uanimals",name:"UAnimals",tagline:"Animal rescue and advocacy organization in Ukraine",urls:{en:"https://uanimals.org/en/",uk:"https://uanimals.org/"},tags:["animals"]},{id:"hospitallers",name:"Hospitallers",tagline:"Ukrainian voluntary paramedics providing first aid and evacuation",urls:{en:"https://www.hospitallers.org.uk",de:"https://www.hospitallers.org.uk/de",es:"https://www.hospitallers.org.uk/es",fr:"https://www.hospitallers.org.uk/fr",it:"https://www.hospitallers.org.uk/it",nl:"https://www.hospitallers.org.uk/nl",pl:"https://www.hospitallers.org.uk/pl",cs:"https://www.hospitallers.org.uk/cs",sv:"https://www.hospitallers.org.uk/sv"},tags:["humanitarian"]},{id:"sternenko-fund",name:"Sternenko Fund",tagline:"FPV drone supply for Ukrainian defence forces",urls:{en:"https://www.sternenkofund.org/en",uk:"https://www.sternenkofund.org/"},tags:["military"]},{id:"life-robots-ukraine",name:"Life Robots Ukraine",tagline:"Robots for demining Ukraine",urls:{en:"https://liferobots.com.ua/en",uk:"https://liferobots.com.ua/",de:"https://liferobots.com.ua/de",es:"https://liferobots.com.ua/es",fr:"https://liferobots.com.ua/fr",ja:"https://liferobots.com.ua/ja",ko:"https://liferobots.com.ua/ko",nl:"https://liferobots.com.ua/nl",pl:"https://liferobots.com.ua/pl",he:"https://liferobots.com.ua/he",lt:"https://liferobots.com.ua/lt",lv:"https://liferobots.com.ua/lv",no:"https://liferobots.com.ua/no",ro:"https://liferobots.com.ua/ro",ru:"https://liferobots.com.ua/ru"},tags:["humanitarian"]},{id:"sirius-shelter",name:"Sirius",tagline:"Ukraine's largest animal shelter for dogs and cats",urls:{en:"https://dogcat.com.ua/en",uk:"https://dogcat.com.ua/"},tags:["animals"]},{id:"dignitas",name:"Dignitas",tagline:"Technology and support for Ukrainian defenders and veterans",urls:{en:"https://dignitas.fund/",uk:"https://dignitas.fund/uk/"},tags:["military"]},{id:"leleka",name:"Leleka Foundation",tagline:"Tactical medical supplies for Ukraine's frontline medics",urls:{en:"https://leleka.care/en",uk:"https://leleka.care/ua"},tags:["humanitarian"]},{id:"superhumans",name:"Superhumans Center",tagline:"Prosthetics, surgery, and rehabilitation for war survivors",urls:{en:"https://superhumans.com/en/",uk:"https://superhumans.com/"},tags:["humanitarian"]},{id:"nikopol-chance",name:"Nikopol Chance",tagline:"Dog shelter rescuing and rehoming strays in frontline Nikopol",urls:{en:"https://nikopolchance.com"},tags:["animals"]},{id:"dzygaspaw",name:"Dzyga\u2019s Paw",tagline:"Lifesaving tech for Ukrainian defenders",urls:{en:"https://dzygaspaw.com",uk:"https://dzygaspaw.com/uk",de:"https://dzygaspaw.com/de"},tags:["military"]}];var ae=":host{display:block;margin:0;padding:0;border:none;font-size:16px;width:100%;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}section.support-ukraine-block{margin:0;padding:0;border:none;border-radius:0;width:100%;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){section.support-ukraine-block{background-color:gold}}section.support-ukraine-block--shift,section.support-ukraine-block--replace{position:relative}section.support-ukraine-block--overlap{position:fixed;top:0;left:0;z-index:2147483647}section.support-ukraine-block--refreshing .support-ukraine-block__link{opacity:0}section.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){section.support-ukraine-block .support-ukraine-block__link{transition:opacity .2s ease-in-out}}@media(prefers-color-scheme: dark){section.support-ukraine-block .support-ukraine-block__link{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}section.support-ukraine-block .support-ukraine-block__link:hover{opacity:.9}section.support-ukraine-block .support-ukraine-block__link:focus-visible{outline:2px solid #fff;outline-offset:-2px}section.support-ukraine-block .support-ukraine-block__flag{white-space:nowrap}section.support-ukraine-block .support-ukraine-block__prefix,section.support-ukraine-block .support-ukraine-block__info,section.support-ukraine-block .support-ukraine-block__colon,section.support-ukraine-block .support-ukraine-block__tagline{min-width:0}section.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){section.support-ukraine-block .support-ukraine-block__more{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}section.support-ukraine-block .support-ukraine-block__more:hover{opacity:1}section.support-ukraine-block .support-ukraine-block__more:focus-visible{outline:2px solid #fff;outline-offset:-2px}section.support-ukraine-block .support-ukraine-block__more-ellipsis{display:none}section.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){section.support-ukraine-block .support-ukraine-block__refresh{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}}section.support-ukraine-block .support-ukraine-block__refresh:hover{opacity:1}section.support-ukraine-block .support-ukraine-block__refresh:focus-visible{outline:2px solid #fff;outline-offset:-2px}section.support-ukraine-block .support-ukraine-block__name{font-weight:bold}@media(prefers-contrast: more){section.support-ukraine-block{background-color:#003580}section.support-ukraine-block .support-ukraine-block__link,section.support-ukraine-block .support-ukraine-block__more,section.support-ukraine-block .support-ukraine-block__refresh{opacity:1;text-shadow:none}section.support-ukraine-block .support-ukraine-block__link:hover,section.support-ukraine-block .support-ukraine-block__more:hover,section.support-ukraine-block .support-ukraine-block__refresh:hover{opacity:1}}@media(prefers-contrast: more)and (prefers-color-scheme: dark){section.support-ukraine-block{background-color:gold}section.support-ukraine-block .support-ukraine-block__link,section.support-ukraine-block .support-ukraine-block__more,section.support-ukraine-block .support-ukraine-block__refresh{opacity:1;text-shadow:none}}@media(forced-colors: active){section.support-ukraine-block .support-ukraine-block__link:focus-visible,section.support-ukraine-block .support-ukraine-block__more:focus-visible,section.support-ukraine-block .support-ukraine-block__refresh:focus-visible{outline:2px solid Highlight}}@media(max-width: 58rem){section.support-ukraine-block .support-ukraine-block__prefix,section.support-ukraine-block .support-ukraine-block__name,section.support-ukraine-block .support-ukraine-block__colon,section.support-ukraine-block .support-ukraine-block__more,section.support-ukraine-block .support-ukraine-block__refresh{display:none}}@media(max-width: 35rem){section.support-ukraine-block .support-ukraine-block__name{display:initial}section.support-ukraine-block .support-ukraine-block__tagline{display:none}}[dir=rtl] section.support-ukraine-block .support-ukraine-block__link{text-align:right;justify-content:flex-end}[dir=rtl] section.support-ukraine-block .support-ukraine-block__more{text-align:right}[dir=rtl] section.support-ukraine-block .support-ukraine-block__refresh{text-align:right}:host-context([data-theme=dark]) section.support-ukraine-block{background-color:gold}:host-context([data-theme=dark]) section.support-ukraine-block .support-ukraine-block__link{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=dark]) section.support-ukraine-block .support-ukraine-block__more{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=dark]) section.support-ukraine-block .support-ukraine-block__refresh{color:#000;text-shadow:0 1px 2px rgba(255,255,255,.4)}:host-context([data-theme=light]) section.support-ukraine-block{background-color:#0057b7}:host-context([data-theme=light]) section.support-ukraine-block .support-ukraine-block__link{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}:host-context([data-theme=light]) section.support-ukraine-block .support-ukraine-block__more{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}:host-context([data-theme=light]) section.support-ukraine-block .support-ukraine-block__refresh{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}@media(prefers-contrast: more){:host-context([data-theme=light]) section.support-ukraine-block{background-color:#003580}:host-context([data-theme=light]) section.support-ukraine-block .support-ukraine-block__link,:host-context([data-theme=light]) section.support-ukraine-block .support-ukraine-block__more,:host-context([data-theme=light]) section.support-ukraine-block .support-ukraine-block__refresh,:host-context([data-theme=dark]) section.support-ukraine-block .support-ukraine-block__link,:host-context([data-theme=dark]) section.support-ukraine-block .support-ukraine-block__more,:host-context([data-theme=dark]) section.support-ukraine-block .support-ukraine-block__refresh{opacity:1;text-shadow:none}}";var ce=N.parse(ie),o="support-ukraine-block",pe="support-ukraine-seen",Te="\u27F3",se=`${o}__visually-hidden`,Le={count:0},j=new Set;function Ee(e){if(!e)return new Set(j);try{let t=localStorage.getItem(pe);return t?new Set(JSON.parse(t)):new Set}catch{return new Set}}function Ue(e,t){if(!t){j.clear();for(let n of e)j.add(n);return}try{localStorage.setItem(pe,JSON.stringify([...e]))}catch{}}function le(e,t){let n=Ee(t);e(n),Ue(n,t)}function ke(e){let t=e[Math.floor(Math.random()*e.length)];if(t===void 0)throw new Error("randomItem: cannot pick from an empty array");return t}function ue(e,t,n,i,a,k=new Set){let u=a?e.filter(s=>s.id!==a):e,w=u.filter(s=>!k.has(P(s,i)));w.length>0&&(u=w),u.length===0&&(u=e),t&&le(s=>{let y=u.filter(R=>!s.has(R.id));y.length>0?u=y:s.clear()},n);let b=ke(u);return t&&le(s=>{s.add(b.id)},n),b}function $e(e){let t=`${o}-styles`;if(e.querySelector(`#${t}`))return;let n=e.ownerDocument.createElement("style");n.id=t,n.textContent=ae,e.append(n)}function de(e,t){return e.map(n=>{let i=t.charities[n.id];return i?.tagline?{...n,tagline:i.tagline}:n})}function P(e,t){let n=O(t);return e.urls[n]??e.urls.en}function me(e){return O(e)==="ar"}function Ne(){if(typeof navigator>"u")return!1;let e=navigator.doNotTrack;if(e==="1"||e==="yes")return!0;let t=globalThis.window;if(t){let n=t.doNotTrack;if(n==="1"||n==="yes"||navigator.msDoNotTrack==="1")return!0}return!1}function H(e,t){if(t.utmEnabled===!1||Ne())return e;let n=t.utmSource??globalThis.window?.location?.hostname??"";if(!n)return e;let i=t.utmMedium??"support-ukraine-banner",a=t.utmCampaign??"";try{let k=new URL(e);return k.searchParams.set("utm_source",n),k.searchParams.set("utm_medium",i),a&&k.searchParams.set("utm_campaign",a),k.href}catch{return e}}function Re(e,t){return`\u{1F1FA}\u{1F1E6} ${t.supportUkraine} ${e.name}: ${e.tagline}`}function he(e,t,n={}){let{mode:i="shift",fontSize:a="87.5%",charities:k,tags:u,exclude:w,dontRepeat:b=!0,persistSeen:s=!1,isInConsole:y=!0,showRefreshButton:R=!1,autoRefreshInterval:q=0,refreshOnClick:fe=!0,refreshOnClickDelay:ge=2e3,showRefreshAnimation:be=!1}=n,ye=k?N.parse(k):ce,A=de(ye,t),h=u?A.filter(r=>r.tags.some(x=>u.includes(x))):A,_e=new Set(w),G=h.filter(r=>!_e.has(r.id));G.length>0&&(h=G),h.length===0&&(h=A);let f=ue(h,b,s,e),V=f,g=P(f,e),m=document.createElement("div"),K=m.attachShadow({mode:"open"});$e(K);let l=document.createElement("section");l.className=`${o} ${o}--${i}`,l.lang=e,l.setAttribute("aria-label",t.regionLabel),me(e)&&l.setAttribute("dir","rtl");let c=document.createElement("a");c.className=`${o}__link`,c.href=H(g,n),c.target="_blank",c.rel="noopener noreferrer",c.style.fontSize=a;let W=++Le.count,Y=`${o}-link-new-tab-${W}`,v=document.createElement("span");v.id=Y,v.className=se,v.textContent=t.opensInNewTab,c.setAttribute("aria-describedby",Y);let C=document.createElement("span");C.className=`${o}__flag`,C.textContent="\u{1F1FA}\u{1F1E6} ",C.setAttribute("aria-hidden","true");let z=document.createElement("span");z.className=`${o}__prefix`,z.textContent=`${t.supportUkraine} `;let I=document.createElement("span");I.className=`${o}__info`;let S=document.createElement("span");S.className=`${o}__name`,S.textContent=f.name;let F=document.createElement("span");F.className=`${o}__colon`,F.textContent=": ";let T=document.createElement("span");T.className=`${o}__tagline`,T.textContent=f.tagline,I.append(S,F,T),c.append(C,z,I),l.append(c);let d=document.createElement("a");d.className=`${o}__more`,d.href=H("https://damian-buho.github.io/support-ukraine/",n),d.target="_blank",d.rel="noopener noreferrer",d.style.fontSize=a;let J=`${o}-more-new-tab-${W}`,L=document.createElement("span");L.id=J,L.className=se,L.textContent=t.opensInNewTab,d.setAttribute("aria-describedby",J);let B=document.createElement("span");B.className=`${o}__more-text`,B.textContent=t.more;let D=document.createElement("span");D.className=`${o}__more-ellipsis`,D.textContent="\u2026",d.append(B,D),l.append(d),l.append(v,L);function X(r){V=r,g=P(r,e),c.href=H(g,n),S.textContent=r.name,T.textContent=r.tagline,y&&console.info("[support-ukraine] banner",`${r.name}: ${r.tagline}`,g)}function _(){let r=ue(h,b,s,e,V.id,new Set([g]));be?(l.classList.add(`${o}--refreshing`),setTimeout(()=>{X(r),l.classList.remove(`${o}--refreshing`)},200)):X(r)}let E;function U(){clearTimeout(E),E=void 0,document.removeEventListener("visibilitychange",Q),globalThis.window?.removeEventListener?.("blur",Z)}function Q(){document.hidden&&(U(),_())}function Z(){U(),_()}function xe(){E===void 0&&(document.addEventListener("visibilitychange",Q),globalThis.window?.addEventListener?.("blur",Z),E=setTimeout(()=>{U(),_()},ge))}if(fe&&c.addEventListener("click",xe),R){let r=document.createElement("button");r.className=`${o}__refresh`,r.type="button",r.style.fontSize=a,r.setAttribute("aria-label",t.refresh),r.addEventListener("click",_);let x=document.createElement("span");x.textContent=Te,x.setAttribute("aria-hidden","true"),r.append(x),l.insertBefore(r,d)}K.append(l);let M=n.element??document.body;if(i==="replace"){let r=M.querySelector(`.${o}`);r?r.replaceWith(m):M.prepend(m)}else M.prepend(m);y&&console.info("[support-ukraine] banner",`${f.name}: ${f.tagline}`,g),m.dataset.supportUkraine="",m.classList.add(`${o}--processed`);let ee;q>0&&(ee=setInterval(_,q));let te=m;return te.destroy=()=>{U(),clearInterval(ee),m.remove()},te}var Ae="fr";function Ve(e={}){return Promise.resolve(he(Ae,ne,e))}export{ce as DEFAULT_CHARITIES,N as charitiesSchema,Se as charitySchema,Re as formatBannerText,me as isRTL,de as mergeCharities,ke as randomItem,Ve as supportUkraineBlock};
2
2
  //# sourceMappingURL=fr.js.map