@damian-buho/support-ukraine 1.8.3 → 2.0.1
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/README.md +92 -28
- package/dist/ar.js +1 -1
- package/dist/ar.js.map +1 -1
- package/dist/banner.d.ts +6 -0
- package/dist/de.js +1 -1
- package/dist/de.js.map +1 -1
- package/dist/en.js +1 -1
- package/dist/en.js.map +1 -1
- package/dist/es.js +1 -1
- package/dist/es.js.map +1 -1
- package/dist/fr.js +1 -1
- package/dist/fr.js.map +1 -1
- package/dist/hi.js +1 -1
- package/dist/hi.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/it.js +1 -1
- package/dist/it.js.map +1 -1
- package/dist/ja.js +1 -1
- package/dist/ja.js.map +1 -1
- package/dist/ko.js +1 -1
- package/dist/ko.js.map +1 -1
- package/dist/nl.js +1 -1
- package/dist/nl.js.map +1 -1
- package/dist/pl.js +1 -1
- package/dist/pl.js.map +1 -1
- package/dist/pt.js +1 -1
- package/dist/pt.js.map +1 -1
- package/dist/sv.js +1 -1
- package/dist/sv.js.map +1 -1
- package/dist/th.js +1 -1
- package/dist/th.js.map +1 -1
- package/dist/types.d.ts +10 -3
- package/dist/uk.js +1 -1
- package/dist/uk.js.map +1 -1
- package/dist/zh.js +1 -1
- package/dist/zh.js.map +1 -1
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ SPDX-License-Identifier: MIT
|
|
|
20
20
|
[](https://api.reuse.software/info/github.com/damian-buho/support-ukraine)
|
|
21
21
|
|
|
22
22
|
- Browser library that adds a Ukraine-support charity banner to any website.
|
|
23
|
-
- Shows randomly selected Ukrainian charity localized to the visitor's language and
|
|
23
|
+
- Shows randomly selected Ukrainian charity localized to the visitor's language and respects RTL scripts.
|
|
24
24
|
- You can choose kinds of charities.
|
|
25
25
|
- Inspired by [hejny/Ukraine](https://github.com/hejny/Ukraine).
|
|
26
26
|
|
|
@@ -28,11 +28,11 @@ SPDX-License-Identifier: MIT
|
|
|
28
28
|
|
|
29
29
|
[Demo / Play with settings](https://damian-buho.github.io/support-ukraine/dev.html)
|
|
30
30
|
|
|
31
|
-

|
|
32
32
|
|
|
33
|
-

|
|
34
34
|
|
|
35
|
-

|
|
36
36
|
|
|
37
37
|
## Install
|
|
38
38
|
|
|
@@ -46,9 +46,9 @@ npm install @damian-buho/support-ukraine
|
|
|
46
46
|
|
|
47
47
|
```html
|
|
48
48
|
<script type="module">
|
|
49
|
-
|
|
49
|
+
import { supportUkraineBlock } from 'https://cdn.jsdelivr.net/npm/@damian-buho/support-ukraine@2/+esm'
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
await supportUkraineBlock()
|
|
52
52
|
</script>
|
|
53
53
|
```
|
|
54
54
|
|
|
@@ -56,28 +56,28 @@ For optimal Core Web Vitals, avoid the chained locale fetch by loading a pre-loc
|
|
|
56
56
|
|
|
57
57
|
```html
|
|
58
58
|
<script type="module">
|
|
59
|
-
|
|
59
|
+
import { supportUkraineBlock } from 'https://cdn.jsdelivr.net/npm/@damian-buho/support-ukraine@2/dist/es.js'
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
await supportUkraineBlock()
|
|
62
62
|
</script>
|
|
63
63
|
```
|
|
64
64
|
|
|
65
65
|
## Usage
|
|
66
66
|
|
|
67
67
|
```ts
|
|
68
|
-
import {supportUkraineBlock} from '@damian-buho/support-ukraine'
|
|
68
|
+
import { supportUkraineBlock } from '@damian-buho/support-ukraine'
|
|
69
69
|
|
|
70
70
|
// Auto-detect locale from navigator.language
|
|
71
71
|
await supportUkraineBlock()
|
|
72
72
|
|
|
73
73
|
// Force a specific locale
|
|
74
|
-
await supportUkraineBlock({locale: 'es'})
|
|
74
|
+
await supportUkraineBlock({ locale: 'es' })
|
|
75
75
|
```
|
|
76
76
|
|
|
77
77
|
For optimal Core Web Vitals, let your server or router decide the language and load only the needed build — no second network request:
|
|
78
78
|
|
|
79
79
|
```ts
|
|
80
|
-
import {supportUkraineBlock} from '@damian-buho/support-ukraine/es'
|
|
80
|
+
import { supportUkraineBlock } from '@damian-buho/support-ukraine/es'
|
|
81
81
|
|
|
82
82
|
await supportUkraineBlock()
|
|
83
83
|
```
|
|
@@ -90,11 +90,28 @@ language tag and load the matching bundle:
|
|
|
90
90
|
```html
|
|
91
91
|
<script type="module">
|
|
92
92
|
const base = navigator.language.split('-')[0]
|
|
93
|
-
const supported = [
|
|
93
|
+
const supported = [
|
|
94
|
+
'ar',
|
|
95
|
+
'de',
|
|
96
|
+
'en',
|
|
97
|
+
'es',
|
|
98
|
+
'fr',
|
|
99
|
+
'hi',
|
|
100
|
+
'it',
|
|
101
|
+
'ja',
|
|
102
|
+
'ko',
|
|
103
|
+
'nl',
|
|
104
|
+
'pl',
|
|
105
|
+
'pt',
|
|
106
|
+
'sv',
|
|
107
|
+
'th',
|
|
108
|
+
'uk',
|
|
109
|
+
'zh'
|
|
110
|
+
]
|
|
94
111
|
const locale = supported.includes(base) ? base : 'en'
|
|
95
112
|
|
|
96
113
|
const { supportUkraineBlock } = await import(
|
|
97
|
-
`https://cdn.jsdelivr.net/npm/@damian-buho/support-ukraine@
|
|
114
|
+
`https://cdn.jsdelivr.net/npm/@damian-buho/support-ukraine@2/dist/${locale}.js`
|
|
98
115
|
)
|
|
99
116
|
|
|
100
117
|
await supportUkraineBlock()
|
|
@@ -128,23 +145,55 @@ The entire block is a clickable link to the charity's donation page.
|
|
|
128
145
|
|
|
129
146
|
## Options
|
|
130
147
|
|
|
131
|
-
| Option | Type | Default | Description
|
|
132
|
-
|
|
133
|
-
| `element` | `HTMLElement` | `document.body` | Target mount element for the banner
|
|
148
|
+
| Option | Type | Default | Description |
|
|
149
|
+
| ------------- | ----------------------------------- | ----------------- | ----------------------------------------------------------------------------------------------------------------- |
|
|
150
|
+
| `element` | `HTMLElement` | `document.body` | Target mount element for the banner |
|
|
134
151
|
| `mode` | `'shift' \| 'overlap' \| 'replace'` | `'shift'` | `'shift'` pushes page content down, `'overlap'` floats on top, `'replace'` swaps a same-class placeholder element |
|
|
135
|
-
| `fontSize` | `string` | `'87.5%'` | Banner font size; `%` anchors to the widget's own 16px host box, ignoring document root scaling
|
|
136
|
-
| `charities` | `Charity[]` | _(built-in)_ | Custom charity list; replaces the built-in database
|
|
137
|
-
| `tags` | `CharityTag[]` | _(all)_ | Filter charities by category: `'military'`, `'humanitarian'`, `'animals'`
|
|
138
|
-
| `
|
|
139
|
-
| `
|
|
140
|
-
| `
|
|
152
|
+
| `fontSize` | `string` | `'87.5%'` | Banner font size; `%` anchors to the widget's own 16px host box, ignoring document root scaling |
|
|
153
|
+
| `charities` | `Charity[]` | _(built-in)_ | Custom charity list; replaces the built-in database |
|
|
154
|
+
| `tags` | `CharityTag[]` | _(all)_ | Filter charities by category: `'military'`, `'humanitarian'`, `'animals'` |
|
|
155
|
+
| `exclude` | `string[]` | _(none)_ | Exclude charities by id; unknown ids are ignored |
|
|
156
|
+
| `dontRepeat` | `boolean` | `true` | Avoid repeating charities; seen ids stay in session memory by default |
|
|
157
|
+
| `persistSeen` | `boolean` | `false` | Persist seen charity ids in `localStorage` across visits (needs visitor consent) |
|
|
158
|
+
| `isInConsole` | `boolean` | `true` | Log the selected charity to the dev console |
|
|
159
|
+
| `showRefreshButton` | `boolean` | `false` | Show a refresh button that loads the next random charity |
|
|
160
|
+
| `autoRefreshInterval` | `number` | `0` | Auto-refresh interval in milliseconds; `0` disables automatic refresh |
|
|
161
|
+
| `showRefreshAnimation` | `boolean` | `false` | Show a fade animation when the charity changes (respects `prefers-reduced-motion`) |
|
|
162
|
+
| `locale` | `string` | _(auto-detected)_ | Override the auto-detected BCP 47 language tag |
|
|
141
163
|
|
|
142
164
|
### Filtering by category
|
|
143
165
|
|
|
144
166
|
Show only military charities:
|
|
145
167
|
|
|
146
168
|
```ts
|
|
147
|
-
await supportUkraineBlock({tags: ['military']})
|
|
169
|
+
await supportUkraineBlock({ tags: ['military'] })
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Excluding charities
|
|
173
|
+
|
|
174
|
+
Hide specific charities by id (unknown ids are ignored):
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
await supportUkraineBlock({ exclude: ['united24'] })
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Localized charity URLs
|
|
181
|
+
|
|
182
|
+
Charities carry per-language donation URLs via a `urls` map (base language code → URL, `en` required).
|
|
183
|
+
The banner follows the visitor’s language and falls back to `en`:
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
await supportUkraineBlock({
|
|
187
|
+
charities: [
|
|
188
|
+
{
|
|
189
|
+
id: 'hospitallers',
|
|
190
|
+
name: 'Hospitallers',
|
|
191
|
+
tagline: '…',
|
|
192
|
+
urls: { en: 'https://www.hospitallers.org.uk', de: 'https://www.hospitallers.org.uk/de' },
|
|
193
|
+
tags: ['humanitarian']
|
|
194
|
+
}
|
|
195
|
+
]
|
|
196
|
+
})
|
|
148
197
|
```
|
|
149
198
|
|
|
150
199
|
### Replace mode (no layout shift)
|
|
@@ -155,11 +204,15 @@ page content:
|
|
|
155
204
|
```html
|
|
156
205
|
<!-- Static HTML: renders nothing until JS runs. Mirror the host box (font-size 16px,
|
|
157
206
|
min-height 2.5em = the banner's reserved height) so swap-in causes zero shift. -->
|
|
158
|
-
<section
|
|
207
|
+
<section
|
|
208
|
+
aria-label="Support Ukraine banner"
|
|
209
|
+
class="support-ukraine-block"
|
|
210
|
+
style="font-size:16px;min-height:2.5em"
|
|
211
|
+
></section>
|
|
159
212
|
```
|
|
160
213
|
|
|
161
214
|
```ts
|
|
162
|
-
await supportUkraineBlock({mode: 'replace'})
|
|
215
|
+
await supportUkraineBlock({ mode: 'replace' })
|
|
163
216
|
```
|
|
164
217
|
|
|
165
218
|
The banner finds the first element with class `support-ukraine-block` inside the mount element and replaces it in place.
|
|
@@ -171,7 +224,18 @@ placeholder already reserves the exact space the banner needs.
|
|
|
171
224
|
Allow the same charity to appear on every page load:
|
|
172
225
|
|
|
173
226
|
```ts
|
|
174
|
-
await supportUkraineBlock({dontRepeat: false})
|
|
227
|
+
await supportUkraineBlock({ dontRepeat: false })
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Persisting seen charities
|
|
231
|
+
|
|
232
|
+
By default the repeat prevention above keeps seen charity ids in session memory only — nothing is
|
|
233
|
+
written to the visitor’s device. Set `persistSeen` to remember them in `localStorage` across visits.
|
|
234
|
+
Storing data on a visitor’s device needs their consent under the GDPR/ePrivacy rules, so only enable
|
|
235
|
+
this after the site owner has obtained it:
|
|
236
|
+
|
|
237
|
+
```ts
|
|
238
|
+
await supportUkraineBlock({ persistSeen: true })
|
|
175
239
|
```
|
|
176
240
|
|
|
177
241
|
## Locale support
|
|
@@ -179,7 +243,7 @@ await supportUkraineBlock({dontRepeat: false})
|
|
|
179
243
|
The banner is translated to the visitor's language automatically. The following locales are supported:
|
|
180
244
|
|
|
181
245
|
| Language | Code | RTL |
|
|
182
|
-
|
|
246
|
+
| ---------- | ---- | ------------------ |
|
|
183
247
|
| Arabic | `ar` | Yes |
|
|
184
248
|
| Chinese | `zh` | |
|
|
185
249
|
| Dutch | `nl` | |
|
|
@@ -226,4 +290,4 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and guidelines.
|
|
|
226
290
|
|
|
227
291
|
## License
|
|
228
292
|
|
|
229
|
-
MIT
|
|
293
|
+
[MIT](LICENSE)
|
package/dist/ar.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var G={supportUkraine:"\u0627\u062F\u0639\u0645 \u0623\u0648\u0643\u0631\u0627\u0646\u064A\u0627 \u0628\u0640",regionLabel:"\u0644\u0627\u0641\u062A\u0629 \u062F\u0639\u0645 \u0623\u0648\u0643\u0631\u0627\u0646\u064A\u0627",more:"\u0627\u0644\u0645\u0632\u064A\u062F\u2026",donate:"\u062A\u0628\u0631\u0639",refresh:"\u0625\u0638\u0647\u0627\u0631 \u0627\u0644\u062C\u0647\u0629 \u0627\u0644\u062A\u0627\u0644\u064A\u0629",opensInNewTab:"(\u064A\u064F\u0641\u062A\u062D \u0641\u064A \u062A\u0628\u0648\u064A\u0628 \u062C\u062F\u064A\u062F)",charities:{united24:{tagline:"\u0627\u0644\u0645\u0646\u0635\u0629 \u0627\u0644\u0631\u0633\u0645\u064A\u0629 \u0644\u062C\u0645\u0639 \u0627\u0644\u062A\u0628\u0631\u0639\u0627\u062A \u0641\u064A \u0623\u0648\u0643\u0631\u0627\u0646\u064A\u0627"},"come-back-alive":{tagline:"\u062F\u0639\u0645 \u0627\u0644\u0642\u0648\u0627\u062A \u0627\u0644\u0645\u0633\u0644\u062D\u0629 \u0627\u0644\u0623\u0648\u0643\u0631\u0627\u0646\u064A\u0629 \u0645\u0646\u0630 2014"},"razom-for-ukraine":{tagline:"\u0627\u0644\u0627\u0633\u062A\u062C\u0627\u0628\u0629 \u0627\u0644\u0637\u0648\u0627\u0631\u0626 \u0648\u0627\u0644\u0645\u0633\u0627\u0639\u062F\u0629 \u0627\u0644\u0625\u0646\u0633\u0627\u0646\u064A\u0629"},"ukrainian-red-cross":{tagline:"\u0627\u0644\u0645\u0633\u0627\u0639\u062F\u0629 \u0627\u0644\u0625\u0646\u0633\u0627\u0646\u064A\u0629 \u0641\u064A \u0645\u0646\u0627\u0637\u0642 \u0627\u0644\u0646\u0632\u0627\u0639"},"nova-ukraine":{tagline:"\u0627\u0644\u0645\u0633\u0627\u0639\u062F\u0629 \u0627\u0644\u0625\u0646\u0633\u0627\u0646\u064A\u0629 \u0648\u0627\u0644\u0645\u0646\u0627\u0635\u0631\u0629"},"voices-of-children":{tagline:"\u0627\u0644\u062F\u0639\u0645 \u0627\u0644\u0646\u0641\u0633\u064A \u0644\u0644\u0623\u0637\u0641\u0627\u0644 \u0627\u0644\u0645\u062A\u0623\u062B\u0631\u064A\u0646 \u0628\u0627\u0644\u062D\u0631\u0628"},"prytula-foundation":{tagline:"\u062A\u0642\u0646\u064A\u0627\u062A \u0627\u0644\u062F\u0641\u0627\u0639 \u0648\u0627\u0644\u0645\u0639\u062F\u0627\u062A \u0644\u0623\u0648\u0643\u0631\u0627\u0646\u064A\u0627"},"medical-hilfe":{tagline:"\u0627\u0644\u0645\u0633\u062A\u0644\u0632\u0645\u0627\u062A \u0627\u0644\u0637\u0628\u064A\u0629 \u0644\u0644\u0645\u0633\u062A\u0634\u0641\u064A\u0627\u062A \u0627\u0644\u0623\u0648\u0643\u0631\u0627\u0646\u064A\u0629"},"army-of-drones":{tagline:"\u0637\u0627\u0626\u0631\u0627\u062A \u0627\u0633\u062A\u0637\u0644\u0627\u0639 \u0645\u0633\u064A\u0651\u0631\u0629 \u0644\u0644\u062C\u0628\u0647\u0629"},"world-central-kitchen":{tagline:"\u0648\u062C\u0628\u0627\u062A \u0637\u0627\u0632\u062C\u0629 \u0644\u0644\u0633\u0643\u0627\u0646 \u0641\u064A \u0645\u0646\u0627\u0637\u0642 \u0627\u0644\u0646\u0632\u0627\u0639"},"cats-of-kyiv":{tagline:"\u0645\u0644\u062C\u0623 \u0644\u0644\u0642\u0637\u0648\u0637 \u064A\u0646\u0642\u0630 \u0648\u064A\u0623\u0648\u064A \u0627\u0644\u0642\u0637\u0648\u0637 \u0641\u064A \u0643\u064A\u064A\u0641"},uanimals:{tagline:"\u0645\u0646\u0638\u0645\u0629 \u0625\u0646\u0642\u0627\u0630 \u0627\u0644\u062D\u064A\u0648\u0627\u0646\u0627\u062A \u0648\u0627\u0644\u0645\u0646\u0627\u0635\u0631\u0629 \u0641\u064A \u0623\u0648\u0643\u0631\u0627\u0646\u064A\u0627"},hospitallers:{tagline:"\u0645\u062A\u0637\u0648\u0639\u0648 \u0627\u0644\u0625\u0633\u0639\u0627\u0641 \u0627\u0644\u0623\u0648\u0643\u0631\u0627\u0646\u064A\u0648\u0646 \u064A\u0642\u062F\u0651\u0645\u0648\u0646 \u0627\u0644\u0625\u0633\u0639\u0627\u0641\u0627\u062A \u0627\u0644\u0623\u0648\u0644\u064A\u0629 \u0648\u0627\u0644\u0625\u062E\u0644\u0627\u0621"},"sternenko-fund":{tagline:"\u062A\u0632\u0648\u064A\u062F \u0637\u0627\u0626\u0631\u0627\u062A FPV \u0644\u0644\u0642\u0648\u0627\u062A \u0627\u0644\u062F\u0641\u0627\u0639\u064A\u0629 \u0627\u0644\u0623\u0648\u0643\u0631\u0627\u0646\u064A\u0629"},"life-robots-ukraine":{tagline:"\u0631\u0648\u0628\u0648\u062A\u0627\u062A \u0644\u0625\u0632\u0627\u0644\u0629 \u0627\u0644\u0623\u0644\u063A\u0627\u0645 \u0641\u064A \u0623\u0648\u0643\u0631\u0627\u0646\u064A\u0627"},"sirius-shelter":{tagline:"\u0623\u0643\u0628\u0631 \u0645\u0644\u062C\u0623 \u0644\u0644\u062D\u064A\u0648\u0627\u0646\u0627\u062A \u0641\u064A \u0623\u0648\u0643\u0631\u0627\u0646\u064A\u0627 \u0644\u0644\u0643\u0644\u0627\u0628 \u0648\u0627\u0644\u0642\u0637\u0637"}}};var V=["military","humanitarian","animals"];function m(e,t){if(!e)throw new Error(t)}function C(e,t){m(typeof e=="string",`${t} must be a string`),m(e.length>0,`${t} must not be empty`)}function ie(e,t){C(e,t);try{new URL(e)}catch{throw new Error(`${t} must be a valid URL`)}}function se(e){return m(V.includes(e),`Invalid tag: ${String(e)}. Must be one of: ${V.join(", ")}`),e}function K(e){m(e!==null&&typeof e=="object","Charity must be an object");let t=e;return C(t.id,"id"),C(t.name,"name"),C(t.tagline,"tagline"),ie(t.url,"url"),m(Array.isArray(t.tags),"tags must be an array"),m(t.tags.length>0,"tags must not be empty"),{id:t.id,name:t.name,tagline:t.tagline,url:t.url,tags:t.tags.map(n=>se(n))}}var le={parse:K},A={parse(e){return m(Array.isArray(e),"Charities must be an array"),e.map(t=>K(t))}};var q=[{id:"united24",name:"United24",tagline:"Official fundraising platform of Ukraine",url:"https://u24.gov.ua",tags:["humanitarian"]},{id:"come-back-alive",name:"Come Back Alive",tagline:"Supporting the Ukrainian Armed Forces since 2014",url:"https://www.comebackalive.in.ua",tags:["military"]},{id:"razom-for-ukraine",name:"Razom for Ukraine",tagline:"Emergency response and humanitarian aid",url:"https://www.razomforukraine.org",tags:["humanitarian"]},{id:"ukrainian-red-cross",name:"Ukrainian Red Cross",tagline:"Humanitarian assistance in conflict zones",url:"https://redcross.org.ua/en/",tags:["humanitarian"]},{id:"nova-ukraine",name:"Nova Ukraine",tagline:"Humanitarian aid and advocacy",url:"https://novaukraine.org",tags:["humanitarian"]},{id:"voices-of-children",name:"Voices of Children",tagline:"Psychological support for children affected by war",url:"https://voices.org.ua/en/",tags:["humanitarian"]},{id:"prytula-foundation",name:"Prytula Foundation",tagline:"Defence technology and equipment for Ukraine",url:"https://prytulafoundation.org/en",tags:["military"]},{id:"army-of-drones",name:"Army of Drones",tagline:"Reconnaissance drones for the frontline",url:"https://armyofdrones.com",tags:["military"]},{id:"world-central-kitchen",name:"World Central Kitchen",tagline:"Fresh meals for people in conflict zones",url:"https://wck.org/relief/activation-chefs-for-ukraine/",tags:["humanitarian"]},{id:"cats-of-kyiv",name:"Cats of Kyiv",tagline:"Cat shelter rescuing and rehoming cats in Kyiv",url:"https://cats.kiev.ua",tags:["animals"]},{id:"uanimals",name:"UAnimals",tagline:"Animal rescue and advocacy organization in Ukraine",url:"https://uanimals.org",tags:["animals"]},{id:"hospitallers",name:"Hospitallers",tagline:"Ukrainian voluntary paramedics providing first aid and evacuation",url:"https://www.hospitallers.org.uk",tags:["humanitarian"]},{id:"sternenko-fund",name:"Sternenko Fund",tagline:"FPV drone supply for Ukrainian defence forces",url:"https://www.sternenkofund.org",tags:["military"]},{id:"life-robots-ukraine",name:"Life Robots Ukraine",tagline:"Robots for demining Ukraine",url:"https://liferobots.com.ua",tags:["humanitarian"]},{id:"sirius-shelter",name:"Sirius",tagline:"Ukraine's largest animal shelter for dogs and cats",url:"https://dogcat.com.ua",tags:["animals"]},{id:"dignitas",name:"Dignitas",tagline:"Technology and support for Ukrainian defenders and veterans",url:"https://dignitas.fund",tags:["military"]},{id:"leleka",name:"Leleka Foundation",tagline:"Tactical medical supplies for Ukraine's frontline medics",url:"https://leleka.care/en",tags:["humanitarian"]},{id:"superhumans",name:"Superhumans Center",tagline:"Prosthetics, surgery, and rehabilitation for war survivors",url:"https://superhumans.com/en/",tags:["humanitarian"]}];var W=":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(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)}";var Q=A.parse(q),o="support-ukraine-block",Z="support-ukraine-seen",ce="\u27F3",Y=`${o}__visually-hidden`,ue={count:0};function pe(){try{let e=localStorage.getItem(Z);return e?new Set(JSON.parse(e)):new Set}catch{return new Set}}function de(e){try{localStorage.setItem(Z,JSON.stringify([...e]))}catch{}}function J(e){let t=pe();e(t),de(t)}function ee(e){if(e.length===0)throw new Error("randomItem: cannot pick from an empty array");return e[Math.floor(Math.random()*e.length)]}function X(e,t,n){let a=n?e.filter(i=>i.url!==n):e;a.length===0&&(a=e),t&&J(i=>{let k=a.filter(g=>!i.has(g.url));k.length>0?a=k:i.clear()});let l=ee(a);return t&&J(i=>{i.add(l.url)}),l}function me(e){let t=`${o}-styles`;if(e.querySelector(`#${t}`))return;let n=e.ownerDocument.createElement("style");n.id=t,n.textContent=W,e.append(n)}function te(e,t){return e.map(n=>{let a=t.charities[n.id];return a?.tagline?{...n,tagline:a.tagline}:n})}function ne(e){return(e.split("-",1)[0]??"").toLowerCase()==="ar"}function ke(){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 I(e,t){if(t.utmEnabled===!1||ke())return e;let n=t.utmSource??globalThis.window?.location?.hostname??"";if(!n)return e;let a=t.utmMedium??"support-ukraine-banner",l=t.utmCampaign??"";try{let i=new URL(e);return i.searchParams.set("utm_source",n),i.searchParams.set("utm_medium",a),l&&i.searchParams.set("utm_campaign",l),i.href}catch{return e}}function fe(e,t){return`\u{1F1FA}\u{1F1E6} ${t.supportUkraine} ${e.name}: ${e.tagline}`}function re(e,t,n={}){let{mode:a="shift",fontSize:l="87.5%",charities:i,tags:k,dontRepeat:g=!0,isInConsole:R=!0,showRefreshButton:oe=!1,autoRefreshInterval:z=0,showRefreshAnimation:ae=!1}=n,S=te(i??Q,t),h=k&&k.length>0?S.filter(r=>r.tags.some(f=>k.includes(f))):S;h.length===0&&(h=S);let d=X(h,g),B=d.url,p=document.createElement("div"),F=p.attachShadow({mode:"open"});me(F);let s=document.createElement("section");s.className=`${o} ${o}--${a}`,s.lang=e,s.setAttribute("aria-label",t.regionLabel),ne(e)&&s.setAttribute("dir","rtl");let c=document.createElement("a");c.className=`${o}__link`,c.href=I(d.url,n),c.target="_blank",c.rel="noopener noreferrer",c.style.fontSize=l;let M=++ue.count,D=`${o}-link-new-tab-${M}`,b=document.createElement("span");b.id=D,b.className=Y,b.textContent=t.opensInNewTab,c.setAttribute("aria-describedby",D);let y=document.createElement("span");y.className=`${o}__flag`,y.textContent="\u{1F1FA}\u{1F1E6} ",y.setAttribute("aria-hidden","true");let v=document.createElement("span");v.className=`${o}__prefix`,v.textContent=`${t.supportUkraine} `;let T=document.createElement("span");T.className=`${o}__info`;let x=document.createElement("span");x.className=`${o}__name`,x.textContent=d.name;let E=document.createElement("span");E.className=`${o}__colon`,E.textContent=": ";let _=document.createElement("span");_.className=`${o}__tagline`,_.textContent=d.tagline,T.append(x,E,_),c.append(y,v,T),s.append(c);let u=document.createElement("a");u.className=`${o}__more`,u.href=I("https://damian-buho.github.io/support-ukraine/",n),u.target="_blank",u.rel="noopener noreferrer",u.style.fontSize=l;let H=`${o}-more-new-tab-${M}`,w=document.createElement("span");w.id=H,w.className=Y,w.textContent=t.opensInNewTab,u.setAttribute("aria-describedby",H);let L=document.createElement("span");L.className=`${o}__more-text`,L.textContent=t.more;let $=document.createElement("span");$.className=`${o}__more-ellipsis`,$.textContent="\u2026",u.append(L,$),s.append(u),s.append(b,w);function O(r){c.href=I(r.url,n),x.textContent=r.name,_.textContent=r.tagline,R&&console.info("[support-ukraine] banner",`${r.name}: ${r.tagline}`,r.url)}function P(){let r=X(h,g,B);B=r.url,ae?(s.classList.add(`${o}--refreshing`),setTimeout(()=>{O(r),s.classList.remove(`${o}--refreshing`)},200)):O(r)}if(oe){let r=document.createElement("button");r.className=`${o}__refresh`,r.type="button",r.textContent="",r.style.fontSize=l,r.setAttribute("aria-label",t.refresh),r.addEventListener("click",P);let f=document.createElement("span");f.textContent=ce,f.setAttribute("aria-hidden","true"),r.append(f),s.insertBefore(r,u)}F.append(s);let N=n.element??document.body;if(a==="replace"){let r=N.querySelector(`.${o}`);r?r.replaceWith(p):N.prepend(p)}else N.prepend(p);R&&console.info("[support-ukraine] banner",`${d.name}: ${d.tagline}`,d.url),p.dataset.supportUkraine="",p.classList.add(`${o}--processed`);let U;z>0&&(U=setInterval(P,z));let j=p;return j.destroy=()=>{U!==void 0&&clearInterval(U),p.remove()},j}var ge="ar";function Le(e={}){return Promise.resolve(re(ge,G,e))}export{Q as DEFAULT_CHARITIES,A as charitiesSchema,le as charitySchema,fe as formatBannerText,ne as isRTL,te as mergeCharities,ee as randomItem,Le as supportUkraineBlock};
|
|
1
|
+
var Y={supportUkraine:"\u0627\u062F\u0639\u0645 \u0623\u0648\u0643\u0631\u0627\u0646\u064A\u0627 \u0628\u0640",regionLabel:"\u0644\u0627\u0641\u062A\u0629 \u062F\u0639\u0645 \u0623\u0648\u0643\u0631\u0627\u0646\u064A\u0627",more:"\u0627\u0644\u0645\u0632\u064A\u062F\u2026",donate:"\u062A\u0628\u0631\u0639",refresh:"\u0625\u0638\u0647\u0627\u0631 \u0627\u0644\u062C\u0647\u0629 \u0627\u0644\u062A\u0627\u0644\u064A\u0629",opensInNewTab:"(\u064A\u064F\u0641\u062A\u062D \u0641\u064A \u062A\u0628\u0648\u064A\u0628 \u062C\u062F\u064A\u062F)",charities:{united24:{tagline:"\u0627\u0644\u0645\u0646\u0635\u0629 \u0627\u0644\u0631\u0633\u0645\u064A\u0629 \u0644\u062C\u0645\u0639 \u0627\u0644\u062A\u0628\u0631\u0639\u0627\u062A \u0641\u064A \u0623\u0648\u0643\u0631\u0627\u0646\u064A\u0627"},"come-back-alive":{tagline:"\u062F\u0639\u0645 \u0627\u0644\u0642\u0648\u0627\u062A \u0627\u0644\u0645\u0633\u0644\u062D\u0629 \u0627\u0644\u0623\u0648\u0643\u0631\u0627\u0646\u064A\u0629 \u0645\u0646\u0630 2014"},"razom-for-ukraine":{tagline:"\u0627\u0644\u0627\u0633\u062A\u062C\u0627\u0628\u0629 \u0627\u0644\u0637\u0648\u0627\u0631\u0626 \u0648\u0627\u0644\u0645\u0633\u0627\u0639\u062F\u0629 \u0627\u0644\u0625\u0646\u0633\u0627\u0646\u064A\u0629"},"ukrainian-red-cross":{tagline:"\u0627\u0644\u0645\u0633\u0627\u0639\u062F\u0629 \u0627\u0644\u0625\u0646\u0633\u0627\u0646\u064A\u0629 \u0641\u064A \u0645\u0646\u0627\u0637\u0642 \u0627\u0644\u0646\u0632\u0627\u0639"},"nova-ukraine":{tagline:"\u0627\u0644\u0645\u0633\u0627\u0639\u062F\u0629 \u0627\u0644\u0625\u0646\u0633\u0627\u0646\u064A\u0629 \u0648\u0627\u0644\u0645\u0646\u0627\u0635\u0631\u0629"},"voices-of-children":{tagline:"\u0627\u0644\u062F\u0639\u0645 \u0627\u0644\u0646\u0641\u0633\u064A \u0644\u0644\u0623\u0637\u0641\u0627\u0644 \u0627\u0644\u0645\u062A\u0623\u062B\u0631\u064A\u0646 \u0628\u0627\u0644\u062D\u0631\u0628"},"prytula-foundation":{tagline:"\u062A\u0642\u0646\u064A\u0627\u062A \u0627\u0644\u062F\u0641\u0627\u0639 \u0648\u0627\u0644\u0645\u0639\u062F\u0627\u062A \u0644\u0623\u0648\u0643\u0631\u0627\u0646\u064A\u0627"},"medical-hilfe":{tagline:"\u0627\u0644\u0645\u0633\u062A\u0644\u0632\u0645\u0627\u062A \u0627\u0644\u0637\u0628\u064A\u0629 \u0644\u0644\u0645\u0633\u062A\u0634\u0641\u064A\u0627\u062A \u0627\u0644\u0623\u0648\u0643\u0631\u0627\u0646\u064A\u0629"},"army-of-drones":{tagline:"\u0637\u0627\u0626\u0631\u0627\u062A \u0627\u0633\u062A\u0637\u0644\u0627\u0639 \u0645\u0633\u064A\u0651\u0631\u0629 \u0644\u0644\u062C\u0628\u0647\u0629"},"world-central-kitchen":{tagline:"\u0648\u062C\u0628\u0627\u062A \u0637\u0627\u0632\u062C\u0629 \u0644\u0644\u0633\u0643\u0627\u0646 \u0641\u064A \u0645\u0646\u0627\u0637\u0642 \u0627\u0644\u0646\u0632\u0627\u0639"},"cats-of-kyiv":{tagline:"\u0645\u0644\u062C\u0623 \u0644\u0644\u0642\u0637\u0648\u0637 \u064A\u0646\u0642\u0630 \u0648\u064A\u0623\u0648\u064A \u0627\u0644\u0642\u0637\u0648\u0637 \u0641\u064A \u0643\u064A\u064A\u0641"},uanimals:{tagline:"\u0645\u0646\u0638\u0645\u0629 \u0625\u0646\u0642\u0627\u0630 \u0627\u0644\u062D\u064A\u0648\u0627\u0646\u0627\u062A \u0648\u0627\u0644\u0645\u0646\u0627\u0635\u0631\u0629 \u0641\u064A \u0623\u0648\u0643\u0631\u0627\u0646\u064A\u0627"},hospitallers:{tagline:"\u0645\u062A\u0637\u0648\u0639\u0648 \u0627\u0644\u0625\u0633\u0639\u0627\u0641 \u0627\u0644\u0623\u0648\u0643\u0631\u0627\u0646\u064A\u0648\u0646 \u064A\u0642\u062F\u0651\u0645\u0648\u0646 \u0627\u0644\u0625\u0633\u0639\u0627\u0641\u0627\u062A \u0627\u0644\u0623\u0648\u0644\u064A\u0629 \u0648\u0627\u0644\u0625\u062E\u0644\u0627\u0621"},"sternenko-fund":{tagline:"\u062A\u0632\u0648\u064A\u062F \u0637\u0627\u0626\u0631\u0627\u062A FPV \u0644\u0644\u0642\u0648\u0627\u062A \u0627\u0644\u062F\u0641\u0627\u0639\u064A\u0629 \u0627\u0644\u0623\u0648\u0643\u0631\u0627\u0646\u064A\u0629"},"life-robots-ukraine":{tagline:"\u0631\u0648\u0628\u0648\u062A\u0627\u062A \u0644\u0625\u0632\u0627\u0644\u0629 \u0627\u0644\u0623\u0644\u063A\u0627\u0645 \u0641\u064A \u0623\u0648\u0643\u0631\u0627\u0646\u064A\u0627"},"sirius-shelter":{tagline:"\u0623\u0643\u0628\u0631 \u0645\u0644\u062C\u0623 \u0644\u0644\u062D\u064A\u0648\u0627\u0646\u0627\u062A \u0641\u064A \u0623\u0648\u0643\u0631\u0627\u0646\u064A\u0627 \u0644\u0644\u0643\u0644\u0627\u0628 \u0648\u0627\u0644\u0642\u0637\u0637"}}};var J=["military","humanitarian","animals"];function p(e,t){if(!e)throw new Error(t)}function E(e,t){p(typeof e=="string",`${t} must be a string`),p(e.length>0,`${t} must not be empty`)}function de(e,t){E(e,t);try{new URL(e)}catch{throw new Error(`${t} must be a valid URL`)}}function me(e){return p(J.includes(e),`Invalid tag: ${String(e)}. Must be one of: ${J.join(", ")}`),e}function he(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[a,i]of t)de(i,`urls.${a}`),n[a.toLowerCase()]=i;return p(typeof n.en=="string",'urls must include an "en" entry'),n}function X(e){p(e!==null&&typeof e=="object","Charity must be an object");let t=e;return E(t.id,"id"),E(t.name,"name"),E(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:he(t.urls),tags:t.tags.map(n=>me(n))}}var fe={parse:X},L={parse(e){return p(Array.isArray(e),"Charities must be an array"),e.map(t=>X(t))}};var Q=[{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 Z=":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 oe=L.parse(Q),r="support-ukraine-block",re="support-ukraine-seen",ge="\u27F3",ee=`${r}__visually-hidden`,be={count:0},B=new Set;function _e(e){if(!e)return new Set(B);try{let t=localStorage.getItem(re);return t?new Set(JSON.parse(t)):new Set}catch{return new Set}}function ye(e,t){if(!t){B.clear();for(let n of e)B.add(n);return}try{localStorage.setItem(re,JSON.stringify([...e]))}catch{}}function te(e,t){let n=_e(t);e(n),ye(n,t)}function ae(e){if(e.length===0)throw new Error("randomItem: cannot pick from an empty array");return e[Math.floor(Math.random()*e.length)]}function ne(e,t,n,a,i,u){let s=i?e.filter(l=>l.id!==i):e;if(u&&s.length>1){let l=s.filter(f=>j(f,a)!==u);l.length>0&&(s=l)}s.length===0&&(s=e),t&&te(l=>{let f=s.filter(x=>!l.has(x.id));f.length>0?s=f:l.clear()},n);let g=ae(s);return t&&te(l=>{l.add(g.id)},n),g}function xe(e){let t=`${r}-styles`;if(e.querySelector(`#${t}`))return;let n=e.ownerDocument.createElement("style");n.id=t,n.textContent=Z,e.append(n)}function ie(e,t){return e.map(n=>{let a=t.charities[n.id];return a?.tagline?{...n,tagline:a.tagline}:n})}function j(e,t){let n=(t.split("-",1)[0]??"").toLowerCase();return e.urls[n]??e.urls.en}function se(e){return(e.split("-",1)[0]??"").toLowerCase()==="ar"}function we(){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 M(e,t){if(t.utmEnabled===!1||we())return e;let n=t.utmSource??globalThis.window?.location?.hostname??"";if(!n)return e;let a=t.utmMedium??"support-ukraine-banner",i=t.utmCampaign??"";try{let u=new URL(e);return u.searchParams.set("utm_source",n),u.searchParams.set("utm_medium",a),i&&u.searchParams.set("utm_campaign",i),u.href}catch{return e}}function ve(e,t){return`\u{1F1FA}\u{1F1E6} ${t.supportUkraine} ${e.name}: ${e.tagline}`}function le(e,t,n={}){let{mode:a="shift",fontSize:i="87.5%",charities:u,tags:s,exclude:g,dontRepeat:l=!0,persistSeen:f=!1,isInConsole:x=!0,showRefreshButton:ce=!1,autoRefreshInterval:H=0,showRefreshAnimation:ue=!1}=n,pe=u?L.parse(u):oe,$=ie(pe,t),b=s&&s.length>0?$.filter(o=>o.tags.some(h=>s.includes(h))):$;if(g&&g.length>0){let o=new Set(g),h=b.filter(ke=>!o.has(ke.id));h.length>0&&(b=h)}b.length===0&&(b=$);let _=ne(b,l,f,e),D=_,y=j(_,e),m=document.createElement("div"),O=m.attachShadow({mode:"open"});xe(O);let c=document.createElement("section");c.className=`${r} ${r}--${a}`,c.lang=e,c.setAttribute("aria-label",t.regionLabel),se(e)&&c.setAttribute("dir","rtl");let k=document.createElement("a");k.className=`${r}__link`,k.href=M(y,n),k.target="_blank",k.rel="noopener noreferrer",k.style.fontSize=i;let P=++be.count,G=`${r}-link-new-tab-${P}`,w=document.createElement("span");w.id=G,w.className=ee,w.textContent=t.opensInNewTab,k.setAttribute("aria-describedby",G);let v=document.createElement("span");v.className=`${r}__flag`,v.textContent="\u{1F1FA}\u{1F1E6} ",v.setAttribute("aria-hidden","true");let U=document.createElement("span");U.className=`${r}__prefix`,U.textContent=`${t.supportUkraine} `;let N=document.createElement("span");N.className=`${r}__info`;let C=document.createElement("span");C.className=`${r}__name`,C.textContent=_.name;let A=document.createElement("span");A.className=`${r}__colon`,A.textContent=": ";let S=document.createElement("span");S.className=`${r}__tagline`,S.textContent=_.tagline,N.append(C,A,S),k.append(v,U,N),c.append(k);let d=document.createElement("a");d.className=`${r}__more`,d.href=M("https://damian-buho.github.io/support-ukraine/",n),d.target="_blank",d.rel="noopener noreferrer",d.style.fontSize=i;let V=`${r}-more-new-tab-${P}`,T=document.createElement("span");T.id=V,T.className=ee,T.textContent=t.opensInNewTab,d.setAttribute("aria-describedby",V);let R=document.createElement("span");R.className=`${r}__more-text`,R.textContent=t.more;let I=document.createElement("span");I.className=`${r}__more-ellipsis`,I.textContent="\u2026",d.append(R,I),c.append(d),c.append(w,T);function K(o){D=o,y=j(o,e),k.href=M(y,n),C.textContent=o.name,S.textContent=o.tagline,x&&console.info("[support-ukraine] banner",`${o.name}: ${o.tagline}`,y)}function q(){let o=ne(b,l,f,e,D.id,y);ue?(c.classList.add(`${r}--refreshing`),setTimeout(()=>{K(o),c.classList.remove(`${r}--refreshing`)},200)):K(o)}if(ce){let o=document.createElement("button");o.className=`${r}__refresh`,o.type="button",o.textContent="",o.style.fontSize=i,o.setAttribute("aria-label",t.refresh),o.addEventListener("click",q);let h=document.createElement("span");h.textContent=ge,h.setAttribute("aria-hidden","true"),o.append(h),c.insertBefore(o,d)}O.append(c);let z=n.element??document.body;if(a==="replace"){let o=z.querySelector(`.${r}`);o?o.replaceWith(m):z.prepend(m)}else z.prepend(m);x&&console.info("[support-ukraine] banner",`${_.name}: ${_.tagline}`,y),m.dataset.supportUkraine="",m.classList.add(`${r}--processed`);let F;H>0&&(F=setInterval(q,H));let W=m;return W.destroy=()=>{F!==void 0&&clearInterval(F),m.remove()},W}var Ce="ar";function ze(e={}){return Promise.resolve(le(Ce,Y,e))}export{oe as DEFAULT_CHARITIES,L as charitiesSchema,fe as charitySchema,ve as formatBannerText,se as isRTL,ie as mergeCharities,ae as randomItem,ze as supportUkraineBlock};
|
|
2
2
|
//# sourceMappingURL=ar.js.map
|
package/dist/ar.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/locales/ar.yaml","../src/types.ts","../src/charities.yaml","../src/styles.scss","../src/banner.ts","../src/entries/ar.ts"],"sourcesContent":["export default {\"supportUkraine\":\"ادعم أوكرانيا بـ\",\"regionLabel\":\"لافتة دعم أوكرانيا\",\"more\":\"المزيد…\",\"donate\":\"تبرع\",\"refresh\":\"إظهار الجهة التالية\",\"opensInNewTab\":\"(يُفتح في تبويب جديد)\",\"charities\":{\"united24\":{\"tagline\":\"المنصة الرسمية لجمع التبرعات في أوكرانيا\"},\"come-back-alive\":{\"tagline\":\"دعم القوات المسلحة الأوكرانية منذ 2014\"},\"razom-for-ukraine\":{\"tagline\":\"الاستجابة الطوارئ والمساعدة الإنسانية\"},\"ukrainian-red-cross\":{\"tagline\":\"المساعدة الإنسانية في مناطق النزاع\"},\"nova-ukraine\":{\"tagline\":\"المساعدة الإنسانية والمناصرة\"},\"voices-of-children\":{\"tagline\":\"الدعم النفسي للأطفال المتأثرين بالحرب\"},\"prytula-foundation\":{\"tagline\":\"تقنيات الدفاع والمعدات لأوكرانيا\"},\"medical-hilfe\":{\"tagline\":\"المستلزمات الطبية للمستشفيات الأوكرانية\"},\"army-of-drones\":{\"tagline\":\"طائرات استطلاع مسيّرة للجبهة\"},\"world-central-kitchen\":{\"tagline\":\"وجبات طازجة للسكان في مناطق النزاع\"},\"cats-of-kyiv\":{\"tagline\":\"ملجأ للقطوط ينقذ ويأوي القطوط في كييف\"},\"uanimals\":{\"tagline\":\"منظمة إنقاذ الحيوانات والمناصرة في أوكرانيا\"},\"hospitallers\":{\"tagline\":\"متطوعو الإسعاف الأوكرانيون يقدّمون الإسعافات الأولية والإخلاء\"},\"sternenko-fund\":{\"tagline\":\"تزويد طائرات FPV للقوات الدفاعية الأوكرانية\"},\"life-robots-ukraine\":{\"tagline\":\"روبوتات لإزالة الألغام في أوكرانيا\"},\"sirius-shelter\":{\"tagline\":\"أكبر ملجأ للحيوانات في أوكرانيا للكلاب والقطط\"}}}","// SPDX-FileCopyrightText: 2026 Damián Búho <damian.buho@proton.me>\n//\n// SPDX-License-Identifier: MIT\n\n/**\nCategory tag for a charity.\n*/\nexport const VALID_TAGS = ['military', 'humanitarian', 'animals'] as const\nexport type CharityTag = (typeof VALID_TAGS)[number]\n\nfunction assert(condition: unknown, message: string): asserts condition {\n if (!condition) throw new Error(message)\n}\n\nfunction assertNonEmptyString(value: unknown, field: string): void {\n assert(typeof value === 'string', `${field} must be a string`)\n assert(value.length > 0, `${field} must not be empty`)\n}\n\nfunction assertUrl(value: unknown, field: string): void {\n assertNonEmptyString(value, field)\n try {\n new URL(value)\n } catch {\n throw new Error(`${field} must be a valid URL`)\n }\n}\n\nfunction parseCharityTag(value: unknown): CharityTag {\n assert(\n VALID_TAGS.includes(value as CharityTag),\n `Invalid tag: ${String(value)}. Must be one of: ${VALID_TAGS.join(', ')}`\n )\n return value as CharityTag\n}\n\n/**\nA charity foundation that can appear in the banner.\n*/\nexport interface Charity {\n id: string\n name: string\n tagline: string\n url: string\n tags: CharityTag[]\n}\n\nfunction parseCharity(value: unknown): Charity {\n assert(value !== null && typeof value === 'object', 'Charity must be an object')\n const record = value as Record<string, unknown>\n assertNonEmptyString(record.id, 'id')\n assertNonEmptyString(record.name, 'name')\n assertNonEmptyString(record.tagline, 'tagline')\n assertUrl(record.url, 'url')\n assert(Array.isArray(record.tags), 'tags must be an array')\n assert(record.tags.length > 0, 'tags must not be empty')\n return {\n id: record.id,\n name: record.name,\n tagline: record.tagline,\n url: record.url,\n tags: record.tags.map(tag => parseCharityTag(tag))\n }\n}\n\nexport const charitySchema = {\n parse: parseCharity\n}\n\nexport const charitiesSchema = {\n parse(value: unknown): Charity[] {\n assert(Array.isArray(value), 'Charities must be an array')\n return value.map(item => parseCharity(item))\n }\n}\n\n/**\nTranslated UI strings and charity taglines for a single locale.\n*/\nexport interface LocaleMessages {\n /**\n Banner prefix, e.g. \"Support Ukraine\".\n */\n supportUkraine: string\n /**\n 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 Avoid repeating charities across page loads using localStorage.\n */\n dontRepeat?: boolean\n /**\n Log a message to the dev console.\n */\n isInConsole?: boolean\n /**\n Show a refresh button that loads the next random charity.\n */\n showRefreshButton?: boolean\n /**\n Auto-refresh interval in milliseconds. 0 = off (default). Set e.g. 15000 for 15 seconds.\n */\n autoRefreshInterval?: number\n /**\n Show a fade animation when the charity changes (respects prefers-reduced-motion).\n */\n showRefreshAnimation?: boolean\n /**\n * Override the auto-detected locale (BCP 47 language tag).\n * If omitted the locale is detected from `navigator.language`.\n */\n locale?: string\n /**\n * 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\",\"url\":\"https://u24.gov.ua\",\"tags\":[\"humanitarian\"]},{\"id\":\"come-back-alive\",\"name\":\"Come Back Alive\",\"tagline\":\"Supporting the Ukrainian Armed Forces since 2014\",\"url\":\"https://www.comebackalive.in.ua\",\"tags\":[\"military\"]},{\"id\":\"razom-for-ukraine\",\"name\":\"Razom for Ukraine\",\"tagline\":\"Emergency response and humanitarian aid\",\"url\":\"https://www.razomforukraine.org\",\"tags\":[\"humanitarian\"]},{\"id\":\"ukrainian-red-cross\",\"name\":\"Ukrainian Red Cross\",\"tagline\":\"Humanitarian assistance in conflict zones\",\"url\":\"https://redcross.org.ua/en/\",\"tags\":[\"humanitarian\"]},{\"id\":\"nova-ukraine\",\"name\":\"Nova Ukraine\",\"tagline\":\"Humanitarian aid and advocacy\",\"url\":\"https://novaukraine.org\",\"tags\":[\"humanitarian\"]},{\"id\":\"voices-of-children\",\"name\":\"Voices of Children\",\"tagline\":\"Psychological support for children affected by war\",\"url\":\"https://voices.org.ua/en/\",\"tags\":[\"humanitarian\"]},{\"id\":\"prytula-foundation\",\"name\":\"Prytula Foundation\",\"tagline\":\"Defence technology and equipment for Ukraine\",\"url\":\"https://prytulafoundation.org/en\",\"tags\":[\"military\"]},{\"id\":\"army-of-drones\",\"name\":\"Army of Drones\",\"tagline\":\"Reconnaissance drones for the frontline\",\"url\":\"https://armyofdrones.com\",\"tags\":[\"military\"]},{\"id\":\"world-central-kitchen\",\"name\":\"World Central Kitchen\",\"tagline\":\"Fresh meals for people in conflict zones\",\"url\":\"https://wck.org/relief/activation-chefs-for-ukraine/\",\"tags\":[\"humanitarian\"]},{\"id\":\"cats-of-kyiv\",\"name\":\"Cats of Kyiv\",\"tagline\":\"Cat shelter rescuing and rehoming cats in Kyiv\",\"url\":\"https://cats.kiev.ua\",\"tags\":[\"animals\"]},{\"id\":\"uanimals\",\"name\":\"UAnimals\",\"tagline\":\"Animal rescue and advocacy organization in Ukraine\",\"url\":\"https://uanimals.org\",\"tags\":[\"animals\"]},{\"id\":\"hospitallers\",\"name\":\"Hospitallers\",\"tagline\":\"Ukrainian voluntary paramedics providing first aid and evacuation\",\"url\":\"https://www.hospitallers.org.uk\",\"tags\":[\"humanitarian\"]},{\"id\":\"sternenko-fund\",\"name\":\"Sternenko Fund\",\"tagline\":\"FPV drone supply for Ukrainian defence forces\",\"url\":\"https://www.sternenkofund.org\",\"tags\":[\"military\"]},{\"id\":\"life-robots-ukraine\",\"name\":\"Life Robots Ukraine\",\"tagline\":\"Robots for demining Ukraine\",\"url\":\"https://liferobots.com.ua\",\"tags\":[\"humanitarian\"]},{\"id\":\"sirius-shelter\",\"name\":\"Sirius\",\"tagline\":\"Ukraine's largest animal shelter for dogs and cats\",\"url\":\"https://dogcat.com.ua\",\"tags\":[\"animals\"]},{\"id\":\"dignitas\",\"name\":\"Dignitas\",\"tagline\":\"Technology and support for Ukrainian defenders and veterans\",\"url\":\"https://dignitas.fund\",\"tags\":[\"military\"]},{\"id\":\"leleka\",\"name\":\"Leleka Foundation\",\"tagline\":\"Tactical medical supplies for Ukraine's frontline medics\",\"url\":\"https://leleka.care/en\",\"tags\":[\"humanitarian\"]},{\"id\":\"superhumans\",\"name\":\"Superhumans Center\",\"tagline\":\"Prosthetics, surgery, and rehabilitation for war survivors\",\"url\":\"https://superhumans.com/en/\",\"tags\":[\"humanitarian\"]}]","export default \":host{display:block;margin:0;padding:0;border:none;font-size:16px;width:100%;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(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)}\"","// 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\nfunction readSeen(): Set<string> {\n try {\n const raw = localStorage.getItem(STORAGE_KEY)\n return raw ? new Set(JSON.parse(raw) as string[]) : new Set()\n } catch {\n return new Set()\n }\n}\n\nfunction writeSeen(seen: Set<string>): void {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify([...seen]))\n } catch {\n // localStorage unavailable — degrade silently\n }\n}\n\nfunction updateSeen(mutate: (seen: Set<string>) => void): void {\n const seen = readSeen()\n mutate(seen)\n writeSeen(seen)\n}\n\n/**\n * Pick a random item from an array.\n *\n * @internal\n */\nexport function randomItem<T>(items: T[]): T {\n if (items.length === 0) {\n throw new Error('randomItem: cannot pick from an empty array')\n }\n return items[Math.floor(Math.random() * items.length)]!\n}\n\nfunction pickCharity(\n candidates: Charity[],\n shouldAvoidRepeat: boolean,\n excludeUrl?: string\n): Charity {\n let pool = excludeUrl ? candidates.filter(c => c.url !== excludeUrl) : candidates\n if (pool.length === 0) pool = candidates\n\n if (shouldAvoidRepeat) {\n updateSeen(seen => {\n const unseen = pool.filter(c => !seen.has(c.url))\n if (unseen.length > 0) {\n pool = unseen\n } else {\n seen.clear()\n }\n })\n }\n\n const charity = randomItem(pool)\n\n if (shouldAvoidRepeat) {\n updateSeen(seen => {\n seen.add(charity.url)\n })\n }\n\n return charity\n}\n\nfunction injectShadowStyles(shadowRoot: ShadowRoot): void {\n const id = `${CSS_PREFIX}-styles`\n if (shadowRoot.querySelector(`#${id}`)) {\n return\n }\n\n const style = shadowRoot.ownerDocument.createElement('style')\n style.id = id\n style.textContent = styles\n shadowRoot.append(style)\n}\n\n/**\n * Merge base charities with locale-specific translations.\n */\nexport function mergeCharities(base: readonly Charity[], locale: LocaleMessages): Charity[] {\n return base.map(charity => {\n const translated = locale.charities[charity.id]\n return translated?.tagline ? { ...charity, tagline: translated.tagline } : charity\n })\n}\n\nexport function isRTL(lang: string): boolean {\n const base = (lang.split('-', 1)[0] ?? '').toLowerCase()\n return base === 'ar'\n}\n\nexport function 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/**\n * Mount the banner with already-resolved `lang` and `messages`.\n * Shared by the auto-detect build (`src/index.ts`) and the per-locale builds (`src/entries/*.ts`).\n */\nexport function mountBanner(\n lang: string,\n messages: LocaleMessages,\n options: SupportUkraineBlockOptions = {}\n): HTMLElement & { destroy: () => void } {\n const {\n mode = 'shift',\n fontSize = '87.5%',\n charities,\n tags,\n dontRepeat = true,\n isInConsole = true,\n showRefreshButton = false,\n autoRefreshInterval = 0,\n showRefreshAnimation = false\n } = options\n\n const baseCharities = charities ?? DEFAULT_CHARITIES\n const localizedCharities = mergeCharities(baseCharities, messages)\n\n let candidates =\n tags && tags.length > 0\n ? localizedCharities.filter(charity => charity.tags.some(t => tags.includes(t)))\n : localizedCharities\n\n if (candidates.length === 0) {\n candidates = localizedCharities\n }\n\n const charity = pickCharity(candidates, dontRepeat)\n let currentCharityUrl = charity.url\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(charity.url, 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 link.href = buildUtmUrl(next.url, options)\n name.textContent = next.name\n tagline.textContent = next.tagline\n if (isInConsole) {\n console.info('[support-ukraine] banner', `${next.name}: ${next.tagline}`, next.url)\n }\n }\n\n function updateCharity(): void {\n const next = pickCharity(candidates, dontRepeat, currentCharityUrl)\n currentCharityUrl = next.url\n if (showRefreshAnimation) {\n banner.classList.add(`${CSS_PREFIX}--refreshing`)\n setTimeout(() => {\n applyNext(next)\n banner.classList.remove(`${CSS_PREFIX}--refreshing`)\n }, 200)\n } else {\n applyNext(next)\n }\n }\n\n if (showRefreshButton) {\n const refreshButton = document.createElement('button')\n refreshButton.className = `${CSS_PREFIX}__refresh`\n refreshButton.type = 'button'\n refreshButton.textContent = ''\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('[support-ukraine] banner', `${charity.name}: ${charity.tagline}`, charity.url)\n }\n\n host.dataset.supportUkraine = ''\n host.classList.add(`${CSS_PREFIX}--processed`)\n\n let intervalId: ReturnType<typeof setInterval> | undefined\n if (autoRefreshInterval > 0) {\n intervalId = setInterval(updateCharity, autoRefreshInterval)\n }\n\n const instance = host as HTMLElement & { destroy: () => void }\n instance.destroy = () => {\n if (intervalId !== undefined) {\n clearInterval(intervalId)\n }\n host.remove()\n }\n\n return instance\n}\n","// SPDX-FileCopyrightText: 2026 Damián Búho <damian.buho@proton.me>\n//\n// SPDX-License-Identifier: MIT\n\nimport messages from '../locales/ar.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 = 'ar'\n\n/**\n * Localized `supportUkraineBlock` with `ar` baked in.\n *\n * This build is self-contained — the locale messages are bundled inline, so\n * no second network request is needed. For optimal Core Web Vitals, load\n * only the locale you need:\n *\n * ```ts\n * import { supportUkraineBlock } from '@damian-buho/support-ukraine/ar'\n * await supportUkraineBlock()\n * ```\n *\n * The `locale` option is ignored in this build (the bundle is already\n * localized). Use the auto-detect build (`@damian-buho/support-ukraine`)\n * if you need runtime locale switching.\n */\nexport function supportUkraineBlock(\n options: SupportUkraineBlockOptions = {}\n): Promise<HTMLElement> {\n return Promise.resolve(mountBanner(LANG, messages as unknown as LocaleMessages, options))\n}\n"],"mappings":"AAAA,IAAOA,EAAQ,CAAC,eAAiB,yFAAmB,YAAc,qGAAqB,KAAO,6CAAU,OAAS,2BAAO,QAAU,2GAAsB,cAAgB,wGAAwB,UAAY,CAAC,SAAW,CAAC,QAAU,yNAA0C,EAAE,kBAAkB,CAAC,QAAU,yLAAwC,EAAE,oBAAoB,CAAC,QAAU,iNAAuC,EAAE,sBAAsB,CAAC,QAAU,0LAAoC,EAAE,eAAe,CAAC,QAAU,gKAA8B,EAAE,qBAAqB,CAAC,QAAU,4MAAuC,EAAE,qBAAqB,CAAC,QAAU,mLAAkC,EAAE,gBAAgB,CAAC,QAAU,6NAAyC,EAAE,iBAAiB,CAAC,QAAU,2JAA8B,EAAE,wBAAwB,CAAC,QAAU,qLAAoC,EAAE,eAAe,CAAC,QAAU,kMAAuC,EAAE,SAAW,CAAC,QAAU,2OAA6C,EAAE,aAAe,CAAC,QAAU,kVAA+D,EAAE,iBAAiB,CAAC,QAAU,4NAA6C,EAAE,sBAAsB,CAAC,QAAU,0LAAoC,EAAE,iBAAiB,CAAC,QAAU,kPAA+C,CAAC,CAAC,ECOlzC,IAAMC,EAAa,CAAC,WAAY,eAAgB,SAAS,EAGhE,SAASC,EAAOC,EAAoBC,EAAoC,CACtE,GAAI,CAACD,EAAW,MAAM,IAAI,MAAMC,CAAO,CACzC,CAEA,SAASC,EAAqBC,EAAgBC,EAAqB,CACjEL,EAAO,OAAOI,GAAU,SAAU,GAAGC,CAAK,mBAAmB,EAC7DL,EAAOI,EAAM,OAAS,EAAG,GAAGC,CAAK,oBAAoB,CACvD,CAEA,SAASC,GAAUF,EAAgBC,EAAqB,CACtDF,EAAqBC,EAAOC,CAAK,EACjC,GAAI,CACF,IAAI,IAAID,CAAK,CACf,MAAQ,CACN,MAAM,IAAI,MAAM,GAAGC,CAAK,sBAAsB,CAChD,CACF,CAEA,SAASE,GAAgBH,EAA4B,CACnD,OAAAJ,EACED,EAAW,SAASK,CAAmB,EACvC,gBAAgB,OAAOA,CAAK,CAAC,qBAAqBL,EAAW,KAAK,IAAI,CAAC,EACzE,EACOK,CACT,CAaA,SAASI,EAAaJ,EAAyB,CAC7CJ,EAAOI,IAAU,MAAQ,OAAOA,GAAU,SAAU,2BAA2B,EAC/E,IAAMK,EAASL,EACf,OAAAD,EAAqBM,EAAO,GAAI,IAAI,EACpCN,EAAqBM,EAAO,KAAM,MAAM,EACxCN,EAAqBM,EAAO,QAAS,SAAS,EAC9CH,GAAUG,EAAO,IAAK,KAAK,EAC3BT,EAAO,MAAM,QAAQS,EAAO,IAAI,EAAG,uBAAuB,EAC1DT,EAAOS,EAAO,KAAK,OAAS,EAAG,wBAAwB,EAChD,CACL,GAAIA,EAAO,GACX,KAAMA,EAAO,KACb,QAASA,EAAO,QAChB,IAAKA,EAAO,IACZ,KAAMA,EAAO,KAAK,IAAIC,GAAOH,GAAgBG,CAAG,CAAC,CACnD,CACF,CAEO,IAAMC,GAAgB,CAC3B,MAAOH,CACT,EAEaI,EAAkB,CAC7B,MAAMR,EAA2B,CAC/B,OAAAJ,EAAO,MAAM,QAAQI,CAAK,EAAG,4BAA4B,EAClDA,EAAM,IAAIS,GAAQL,EAAaK,CAAI,CAAC,CAC7C,CACF,EC1EA,IAAOC,EAAQ,CAAC,CAAC,GAAK,WAAW,KAAO,WAAW,QAAU,2CAA2C,IAAM,qBAAqB,KAAO,CAAC,cAAc,CAAC,EAAE,CAAC,GAAK,kBAAkB,KAAO,kBAAkB,QAAU,mDAAmD,IAAM,kCAAkC,KAAO,CAAC,UAAU,CAAC,EAAE,CAAC,GAAK,oBAAoB,KAAO,oBAAoB,QAAU,0CAA0C,IAAM,kCAAkC,KAAO,CAAC,cAAc,CAAC,EAAE,CAAC,GAAK,sBAAsB,KAAO,sBAAsB,QAAU,4CAA4C,IAAM,8BAA8B,KAAO,CAAC,cAAc,CAAC,EAAE,CAAC,GAAK,eAAe,KAAO,eAAe,QAAU,gCAAgC,IAAM,0BAA0B,KAAO,CAAC,cAAc,CAAC,EAAE,CAAC,GAAK,qBAAqB,KAAO,qBAAqB,QAAU,qDAAqD,IAAM,4BAA4B,KAAO,CAAC,cAAc,CAAC,EAAE,CAAC,GAAK,qBAAqB,KAAO,qBAAqB,QAAU,+CAA+C,IAAM,mCAAmC,KAAO,CAAC,UAAU,CAAC,EAAE,CAAC,GAAK,iBAAiB,KAAO,iBAAiB,QAAU,0CAA0C,IAAM,2BAA2B,KAAO,CAAC,UAAU,CAAC,EAAE,CAAC,GAAK,wBAAwB,KAAO,wBAAwB,QAAU,2CAA2C,IAAM,uDAAuD,KAAO,CAAC,cAAc,CAAC,EAAE,CAAC,GAAK,eAAe,KAAO,eAAe,QAAU,iDAAiD,IAAM,uBAAuB,KAAO,CAAC,SAAS,CAAC,EAAE,CAAC,GAAK,WAAW,KAAO,WAAW,QAAU,qDAAqD,IAAM,uBAAuB,KAAO,CAAC,SAAS,CAAC,EAAE,CAAC,GAAK,eAAe,KAAO,eAAe,QAAU,oEAAoE,IAAM,kCAAkC,KAAO,CAAC,cAAc,CAAC,EAAE,CAAC,GAAK,iBAAiB,KAAO,iBAAiB,QAAU,gDAAgD,IAAM,gCAAgC,KAAO,CAAC,UAAU,CAAC,EAAE,CAAC,GAAK,sBAAsB,KAAO,sBAAsB,QAAU,8BAA8B,IAAM,4BAA4B,KAAO,CAAC,cAAc,CAAC,EAAE,CAAC,GAAK,iBAAiB,KAAO,SAAS,QAAU,qDAAqD,IAAM,wBAAwB,KAAO,CAAC,SAAS,CAAC,EAAE,CAAC,GAAK,WAAW,KAAO,WAAW,QAAU,8DAA8D,IAAM,wBAAwB,KAAO,CAAC,UAAU,CAAC,EAAE,CAAC,GAAK,SAAS,KAAO,oBAAoB,QAAU,2DAA2D,IAAM,yBAAyB,KAAO,CAAC,cAAc,CAAC,EAAE,CAAC,GAAK,cAAc,KAAO,qBAAqB,QAAU,6DAA6D,IAAM,8BAA8B,KAAO,CAAC,cAAc,CAAC,CAAC,ECA/5F,IAAOC,EAAQ,qrKCeR,IAAMC,EAA+BC,EAAgB,MAAMC,CAAY,EAExEC,EAAa,wBACbC,EAAc,uBACdC,GAAgB,SAChBC,EAAwB,GAAGH,CAAU,oBACrCI,GAAc,CAAE,MAAO,CAAE,EAE/B,SAASC,IAAwB,CAC/B,GAAI,CACF,IAAMC,EAAM,aAAa,QAAQL,CAAW,EAC5C,OAAOK,EAAM,IAAI,IAAI,KAAK,MAAMA,CAAG,CAAa,EAAI,IAAI,GAC1D,MAAQ,CACN,OAAO,IAAI,GACb,CACF,CAEA,SAASC,GAAUC,EAAyB,CAC1C,GAAI,CACF,aAAa,QAAQP,EAAa,KAAK,UAAU,CAAC,GAAGO,CAAI,CAAC,CAAC,CAC7D,MAAQ,CAER,CACF,CAEA,SAASC,EAAWC,EAA2C,CAC7D,IAAMF,EAAOH,GAAS,EACtBK,EAAOF,CAAI,EACXD,GAAUC,CAAI,CAChB,CAOO,SAASG,GAAcC,EAAe,CAC3C,GAAIA,EAAM,SAAW,EACnB,MAAM,IAAI,MAAM,6CAA6C,EAE/D,OAAOA,EAAM,KAAK,MAAM,KAAK,OAAO,EAAIA,EAAM,MAAM,CAAC,CACvD,CAEA,SAASC,EACPC,EACAC,EACAC,EACS,CACT,IAAIC,EAAOD,EAAaF,EAAW,OAAOI,GAAKA,EAAE,MAAQF,CAAU,EAAIF,EACnEG,EAAK,SAAW,IAAGA,EAAOH,GAE1BC,GACFN,EAAWD,GAAQ,CACjB,IAAMW,EAASF,EAAK,OAAOC,GAAK,CAACV,EAAK,IAAIU,EAAE,GAAG,CAAC,EAC5CC,EAAO,OAAS,EAClBF,EAAOE,EAEPX,EAAK,MAAM,CAEf,CAAC,EAGH,IAAMY,EAAUT,GAAWM,CAAI,EAE/B,OAAIF,GACFN,EAAWD,GAAQ,CACjBA,EAAK,IAAIY,EAAQ,GAAG,CACtB,CAAC,EAGIA,CACT,CAEA,SAASC,GAAmBC,EAA8B,CACxD,IAAMC,EAAK,GAAGvB,CAAU,UACxB,GAAIsB,EAAW,cAAc,IAAIC,CAAE,EAAE,EACnC,OAGF,IAAMC,EAAQF,EAAW,cAAc,cAAc,OAAO,EAC5DE,EAAM,GAAKD,EACXC,EAAM,YAAcC,EACpBH,EAAW,OAAOE,CAAK,CACzB,CAKO,SAASE,GAAeC,EAA0BC,EAAmC,CAC1F,OAAOD,EAAK,IAAIP,GAAW,CACzB,IAAMS,EAAaD,EAAO,UAAUR,EAAQ,EAAE,EAC9C,OAAOS,GAAY,QAAU,CAAE,GAAGT,EAAS,QAASS,EAAW,OAAQ,EAAIT,CAC7E,CAAC,CACH,CAEO,SAASU,GAAMC,EAAuB,CAE3C,OADcA,EAAK,MAAM,IAAK,CAAC,EAAE,CAAC,GAAK,IAAI,YAAY,IACvC,IAClB,CAEO,SAASC,IAA+B,CAC7C,GAAI,OAAO,UAAc,IAAa,MAAO,GAC7C,IAAMC,EAAM,UAAU,WACtB,GAAIA,IAAQ,KAAOA,IAAQ,MAAO,MAAO,GACzC,IAAMC,EAAM,WAAW,OACvB,GAAIA,EAAK,CACP,IAAMC,EAAUD,EAA2C,WAG3D,GAFIC,IAAW,KAAOA,IAAW,OAClB,UAAmD,eACpD,IAAK,MAAO,EAC5B,CACA,MAAO,EACT,CAEO,SAASC,EAAYC,EAAiBC,EAA6C,CAGxF,GADIA,EAAQ,aAAe,IACvBN,GAAoB,EAAG,OAAOK,EAElC,IAAME,EAASD,EAAQ,WAAa,WAAW,QAAQ,UAAU,UAAY,GAC7E,GAAI,CAACC,EAAQ,OAAOF,EAEpB,IAAMG,EAASF,EAAQ,WAAa,yBAC9BG,EAAWH,EAAQ,aAAe,GAExC,GAAI,CACF,IAAMI,EAAM,IAAI,IAAIL,CAAO,EAC3B,OAAAK,EAAI,aAAa,IAAI,aAAcH,CAAM,EACzCG,EAAI,aAAa,IAAI,aAAcF,CAAM,EACrCC,GAAUC,EAAI,aAAa,IAAI,eAAgBD,CAAQ,EACpDC,EAAI,IACb,MAAQ,CACN,OAAOL,CACT,CACF,CAEO,SAASM,GAAiBvB,EAAkBwB,EAAkC,CACnF,MAAO,sBAAsBA,EAAS,cAAc,IAAIxB,EAAQ,IAAI,KAAKA,EAAQ,OAAO,EAC1F,CAMO,SAASyB,GACdd,EACAa,EACAN,EAAsC,CAAC,EACA,CACvC,GAAM,CACJ,KAAAQ,EAAO,QACP,SAAAC,EAAW,QACX,UAAAC,EACA,KAAAC,EACA,WAAAC,EAAa,GACb,YAAAC,EAAc,GACd,kBAAAC,GAAoB,GACpB,oBAAAC,EAAsB,EACtB,qBAAAC,GAAuB,EACzB,EAAIhB,EAGEiB,EAAqB7B,GADLsB,GAAanD,EACsB+C,CAAQ,EAE7D9B,EACFmC,GAAQA,EAAK,OAAS,EAClBM,EAAmB,OAAOnC,GAAWA,EAAQ,KAAK,KAAKoC,GAAKP,EAAK,SAASO,CAAC,CAAC,CAAC,EAC7ED,EAEFzC,EAAW,SAAW,IACxBA,EAAayC,GAGf,IAAMnC,EAAUP,EAAYC,EAAYoC,CAAU,EAC9CO,EAAoBrC,EAAQ,IAE1BsC,EAAO,SAAS,cAAc,KAAK,EAEnCC,EAASD,EAAK,aAAa,CAAE,KAAM,MAAO,CAAC,EACjDrC,GAAmBsC,CAAM,EAEzB,IAAMC,EAAS,SAAS,cAAc,SAAS,EAC/CA,EAAO,UAAY,GAAG5D,CAAU,IAAIA,CAAU,KAAK8C,CAAI,GACvDc,EAAO,KAAO7B,EACd6B,EAAO,aAAa,aAAchB,EAAS,WAAW,EAElDd,GAAMC,CAAI,GACZ6B,EAAO,aAAa,MAAO,KAAK,EAGlC,IAAMC,EAAO,SAAS,cAAc,GAAG,EACvCA,EAAK,UAAY,GAAG7D,CAAU,SAC9B6D,EAAK,KAAOzB,EAAYhB,EAAQ,IAAKkB,CAAO,EAC5CuB,EAAK,OAAS,SACdA,EAAK,IAAM,sBACXA,EAAK,MAAM,SAAWd,EAEtB,IAAMe,EAAiB,EAAE1D,GAAY,MAC/B2D,EAAe,GAAG/D,CAAU,iBAAiB8D,CAAc,GAC3DE,EAAiB,SAAS,cAAc,MAAM,EACpDA,EAAe,GAAKD,EACpBC,EAAe,UAAY7D,EAC3B6D,EAAe,YAAcpB,EAAS,cACtCiB,EAAK,aAAa,mBAAoBE,CAAY,EAElD,IAAME,EAAO,SAAS,cAAc,MAAM,EAC1CA,EAAK,UAAY,GAAGjE,CAAU,SAC9BiE,EAAK,YAAc,sBACnBA,EAAK,aAAa,cAAe,MAAM,EAEvC,IAAMC,EAAS,SAAS,cAAc,MAAM,EAC5CA,EAAO,UAAY,GAAGlE,CAAU,WAChCkE,EAAO,YAAc,GAAGtB,EAAS,cAAc,IAE/C,IAAMuB,EAAO,SAAS,cAAc,MAAM,EAC1CA,EAAK,UAAY,GAAGnE,CAAU,SAE9B,IAAMoE,EAAO,SAAS,cAAc,MAAM,EAC1CA,EAAK,UAAY,GAAGpE,CAAU,SAC9BoE,EAAK,YAAchD,EAAQ,KAE3B,IAAMiD,EAAQ,SAAS,cAAc,MAAM,EAC3CA,EAAM,UAAY,GAAGrE,CAAU,UAC/BqE,EAAM,YAAc,KAEpB,IAAMC,EAAU,SAAS,cAAc,MAAM,EAC7CA,EAAQ,UAAY,GAAGtE,CAAU,YACjCsE,EAAQ,YAAclD,EAAQ,QAE9B+C,EAAK,OAAOC,EAAMC,EAAOC,CAAO,EAEhCT,EAAK,OAAOI,EAAMC,EAAQC,CAAI,EAC9BP,EAAO,OAAOC,CAAI,EAElB,IAAMU,EAAW,SAAS,cAAc,GAAG,EAC3CA,EAAS,UAAY,GAAGvE,CAAU,SAClCuE,EAAS,KAAOnC,EAAY,iDAAkDE,CAAO,EACrFiC,EAAS,OAAS,SAClBA,EAAS,IAAM,sBACfA,EAAS,MAAM,SAAWxB,EAE1B,IAAMyB,EAAe,GAAGxE,CAAU,iBAAiB8D,CAAc,GAC3DW,EAAiB,SAAS,cAAc,MAAM,EACpDA,EAAe,GAAKD,EACpBC,EAAe,UAAYtE,EAC3BsE,EAAe,YAAc7B,EAAS,cACtC2B,EAAS,aAAa,mBAAoBC,CAAY,EAEtD,IAAME,EAAW,SAAS,cAAc,MAAM,EAC9CA,EAAS,UAAY,GAAG1E,CAAU,cAClC0E,EAAS,YAAc9B,EAAS,KAEhC,IAAM+B,EAAe,SAAS,cAAc,MAAM,EAClDA,EAAa,UAAY,GAAG3E,CAAU,kBACtC2E,EAAa,YAAc,SAE3BJ,EAAS,OAAOG,EAAUC,CAAY,EACtCf,EAAO,OAAOW,CAAQ,EACtBX,EAAO,OAAOI,EAAgBS,CAAc,EAE5C,SAASG,EAAUC,EAAqB,CACtChB,EAAK,KAAOzB,EAAYyC,EAAK,IAAKvC,CAAO,EACzC8B,EAAK,YAAcS,EAAK,KACxBP,EAAQ,YAAcO,EAAK,QACvB1B,GACF,QAAQ,KAAK,2BAA4B,GAAG0B,EAAK,IAAI,KAAKA,EAAK,OAAO,GAAIA,EAAK,GAAG,CAEtF,CAEA,SAASC,GAAsB,CAC7B,IAAMD,EAAOhE,EAAYC,EAAYoC,EAAYO,CAAiB,EAClEA,EAAoBoB,EAAK,IACrBvB,IACFM,EAAO,UAAU,IAAI,GAAG5D,CAAU,cAAc,EAChD,WAAW,IAAM,CACf4E,EAAUC,CAAI,EACdjB,EAAO,UAAU,OAAO,GAAG5D,CAAU,cAAc,CACrD,EAAG,GAAG,GAEN4E,EAAUC,CAAI,CAElB,CAEA,GAAIzB,GAAmB,CACrB,IAAM2B,EAAgB,SAAS,cAAc,QAAQ,EACrDA,EAAc,UAAY,GAAG/E,CAAU,YACvC+E,EAAc,KAAO,SACrBA,EAAc,YAAc,GAC5BA,EAAc,MAAM,SAAWhC,EAC/BgC,EAAc,aAAa,aAAcnC,EAAS,OAAO,EACzDmC,EAAc,iBAAiB,QAASD,CAAa,EACrD,IAAME,EAAe,SAAS,cAAc,MAAM,EAClDA,EAAa,YAAc9E,GAC3B8E,EAAa,aAAa,cAAe,MAAM,EAC/CD,EAAc,OAAOC,CAAY,EAEjCpB,EAAO,aAAamB,EAAeR,CAAQ,CAC7C,CAEAZ,EAAO,OAAOC,CAAM,EAEpB,IAAMqB,EAAQ3C,EAAQ,SAAW,SAAS,KAE1C,GAAIQ,IAAS,UAAW,CACtB,IAAMoC,EAAcD,EAAM,cAA2B,IAAIjF,CAAU,EAAE,EACjEkF,EACFA,EAAY,YAAYxB,CAAI,EAE5BuB,EAAM,QAAQvB,CAAI,CAEtB,MACEuB,EAAM,QAAQvB,CAAI,EAGhBP,GACF,QAAQ,KAAK,2BAA4B,GAAG/B,EAAQ,IAAI,KAAKA,EAAQ,OAAO,GAAIA,EAAQ,GAAG,EAG7FsC,EAAK,QAAQ,eAAiB,GAC9BA,EAAK,UAAU,IAAI,GAAG1D,CAAU,aAAa,EAE7C,IAAImF,EACA9B,EAAsB,IACxB8B,EAAa,YAAYL,EAAezB,CAAmB,GAG7D,IAAM+B,EAAW1B,EACjB,OAAA0B,EAAS,QAAU,IAAM,CACnBD,IAAe,QACjB,cAAcA,CAAU,EAE1BzB,EAAK,OAAO,CACd,EAEO0B,CACT,CC3UA,IAAMC,GAAO,KAkBN,SAASC,GACdC,EAAsC,CAAC,EACjB,CACtB,OAAO,QAAQ,QAAQC,GAAYH,GAAMI,EAAuCF,CAAO,CAAC,CAC1F","names":["ar_default","VALID_TAGS","assert","condition","message","assertNonEmptyString","value","field","assertUrl","parseCharityTag","parseCharity","record","tag","charitySchema","charitiesSchema","item","charities_default","styles_default","DEFAULT_CHARITIES","charitiesSchema","charities_default","CSS_PREFIX","STORAGE_KEY","REFRESH_GLYPH","VISUALLY_HIDDEN_CLASS","bannerState","readSeen","raw","writeSeen","seen","updateSeen","mutate","randomItem","items","pickCharity","candidates","shouldAvoidRepeat","excludeUrl","pool","c","unseen","charity","injectShadowStyles","shadowRoot","id","style","styles_default","mergeCharities","base","locale","translated","isRTL","lang","isDoNotTrackEnabled","dnt","win","dntWin","buildUtmUrl","baseUrl","options","source","medium","campaign","url","formatBannerText","messages","mountBanner","mode","fontSize","charities","tags","dontRepeat","isInConsole","showRefreshButton","autoRefreshInterval","showRefreshAnimation","localizedCharities","t","currentCharityUrl","host","shadow","banner","link","instanceSuffix","linkNewTabId","linkNewTabHint","flag","prefix","info","name","colon","tagline","moreLink","moreNewTabId","moreNewTabHint","moreText","moreEllipsis","applyNext","next","updateCharity","refreshButton","refreshGlyph","mount","placeholder","intervalId","instance","LANG","supportUkraineBlock","options","mountBanner","ar_default"]}
|
|
1
|
+
{"version":3,"sources":["../src/locales/ar.yaml","../src/types.ts","../src/charities.yaml","../src/styles.scss","../src/banner.ts","../src/entries/ar.ts"],"sourcesContent":["export default {\"supportUkraine\":\"ادعم أوكرانيا بـ\",\"regionLabel\":\"لافتة دعم أوكرانيا\",\"more\":\"المزيد…\",\"donate\":\"تبرع\",\"refresh\":\"إظهار الجهة التالية\",\"opensInNewTab\":\"(يُفتح في تبويب جديد)\",\"charities\":{\"united24\":{\"tagline\":\"المنصة الرسمية لجمع التبرعات في أوكرانيا\"},\"come-back-alive\":{\"tagline\":\"دعم القوات المسلحة الأوكرانية منذ 2014\"},\"razom-for-ukraine\":{\"tagline\":\"الاستجابة الطوارئ والمساعدة الإنسانية\"},\"ukrainian-red-cross\":{\"tagline\":\"المساعدة الإنسانية في مناطق النزاع\"},\"nova-ukraine\":{\"tagline\":\"المساعدة الإنسانية والمناصرة\"},\"voices-of-children\":{\"tagline\":\"الدعم النفسي للأطفال المتأثرين بالحرب\"},\"prytula-foundation\":{\"tagline\":\"تقنيات الدفاع والمعدات لأوكرانيا\"},\"medical-hilfe\":{\"tagline\":\"المستلزمات الطبية للمستشفيات الأوكرانية\"},\"army-of-drones\":{\"tagline\":\"طائرات استطلاع مسيّرة للجبهة\"},\"world-central-kitchen\":{\"tagline\":\"وجبات طازجة للسكان في مناطق النزاع\"},\"cats-of-kyiv\":{\"tagline\":\"ملجأ للقطوط ينقذ ويأوي القطوط في كييف\"},\"uanimals\":{\"tagline\":\"منظمة إنقاذ الحيوانات والمناصرة في أوكرانيا\"},\"hospitallers\":{\"tagline\":\"متطوعو الإسعاف الأوكرانيون يقدّمون الإسعافات الأولية والإخلاء\"},\"sternenko-fund\":{\"tagline\":\"تزويد طائرات FPV للقوات الدفاعية الأوكرانية\"},\"life-robots-ukraine\":{\"tagline\":\"روبوتات لإزالة الألغام في أوكرانيا\"},\"sirius-shelter\":{\"tagline\":\"أكبر ملجأ للحيوانات في أوكرانيا للكلاب والقطط\"}}}","// 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 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/**\n * Pick a random item from an array.\n *\n * @internal\n */\nexport function randomItem<T>(items: T[]): T {\n if (items.length === 0) {\n throw new Error('randomItem: cannot pick from an empty array')\n }\n return items[Math.floor(Math.random() * items.length)]!\n}\n\nfunction pickCharity(\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/**\n * Merge base charities with locale-specific translations.\n */\nexport function mergeCharities(base: readonly Charity[], locale: LocaleMessages): Charity[] {\n return base.map(charity => {\n const translated = locale.charities[charity.id]\n return translated?.tagline ? { ...charity, tagline: translated.tagline } : charity\n })\n}\n\n/**\n * Resolve the donation URL for a charity in the given banner language.\n * Falls 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/**\n * Mount the banner with already-resolved `lang` and `messages`.\n * Shared by the auto-detect build (`src/index.ts`) and the per-locale builds (`src/entries/*.ts`).\n */\nexport function mountBanner(\n lang: string,\n messages: LocaleMessages,\n options: SupportUkraineBlockOptions = {}\n): HTMLElement & { destroy: () => void } {\n const {\n mode = 'shift',\n fontSize = '87.5%',\n charities,\n tags,\n exclude,\n dontRepeat = true,\n persistSeen = false,\n isInConsole = true,\n showRefreshButton = false,\n autoRefreshInterval = 0,\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 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 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/ar.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 = 'ar'\n\n/**\n * Localized `supportUkraineBlock` with `ar` baked in.\n *\n * This build is self-contained — the locale messages are bundled inline, so\n * no second network request is needed. For optimal Core Web Vitals, load\n * only the locale you need:\n *\n * ```ts\n * import { supportUkraineBlock } from '@damian-buho/support-ukraine/ar'\n * await supportUkraineBlock()\n * ```\n *\n * The `locale` option is ignored in this build (the bundle is already\n * localized). Use the auto-detect build (`@damian-buho/support-ukraine`)\n * if you need runtime locale switching.\n */\nexport function supportUkraineBlock(\n options: SupportUkraineBlockOptions = {}\n): Promise<HTMLElement> {\n return Promise.resolve(mountBanner(LANG, messages as unknown as LocaleMessages, options))\n}\n"],"mappings":"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","names":["ar_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","c","withoutUrl","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","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","refreshButton","refreshGlyph","REFRESH_GLYPH","mount","placeholder","intervalId","instance","LANG","supportUkraineBlock","options","mountBanner","ar_default"]}
|
package/dist/banner.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type Charity, type LocaleMessages, type SupportUkraineBlockOptions } from './types.js';
|
|
2
2
|
export type { Charity, CharityTag, SupportUkraineBlockOptions, LocaleMessages } from './types.js';
|
|
3
3
|
export declare const DEFAULT_CHARITIES: Charity[];
|
|
4
|
+
export declare function resetMemorySeen(): void;
|
|
4
5
|
/**
|
|
5
6
|
* Pick a random item from an array.
|
|
6
7
|
*
|
|
@@ -11,6 +12,11 @@ export declare function randomItem<T>(items: T[]): T;
|
|
|
11
12
|
* Merge base charities with locale-specific translations.
|
|
12
13
|
*/
|
|
13
14
|
export declare function mergeCharities(base: readonly Charity[], locale: LocaleMessages): Charity[];
|
|
15
|
+
/**
|
|
16
|
+
* Resolve the donation URL for a charity in the given banner language.
|
|
17
|
+
* Falls back to English.
|
|
18
|
+
*/
|
|
19
|
+
export declare function charityUrlFor(charity: Charity, lang: string): string;
|
|
14
20
|
export declare function isRTL(lang: string): boolean;
|
|
15
21
|
export declare function isDoNotTrackEnabled(): boolean;
|
|
16
22
|
export declare function buildUtmUrl(baseUrl: string, options: SupportUkraineBlockOptions): string;
|