polite-media 0.5.0 → 0.6.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/CHANGELOG.md CHANGED
@@ -3,6 +3,98 @@
3
3
  Notable changes, newest first. Versions follow [semver](https://semver.org); while
4
4
  this is `0.x`, a minor bump may still break things and will say so here.
5
5
 
6
+ ## 0.6.1 (2026-10-11)
7
+
8
+ ### Fixed
9
+
10
+ - **The reveal failsafe could not run on the compositor.** Its animation lasted `0s`, which
11
+ Chromium will not composite, so every image marked for a reveal carried a main-thread animation
12
+ and Lighthouse listed it under "Avoid non-composited animations". It now lasts `1ms`, and a
13
+ stray image still arrives unfaded once `--polite-failsafe` has passed.
14
+
15
+ ### Documentation
16
+
17
+ - **The wrapper recipe in "Composing your own animation" uses a `1ms` failsafe**, for the same
18
+ reason. Its `0s` gave a copied rule the same Lighthouse warning.
19
+
20
+ ## 0.6.0 (2026-10-07)
21
+
22
+ ### Breaking
23
+
24
+ - **`data-polite-active` is on `<html>` only while a registered video may play.** It used to stay
25
+ for as long as any video was registered, so under reduced motion, on Save-Data or a 2g connection,
26
+ or with `atOnce` at `0`, the README's recipe showed a pause control with nothing to stop. It now
27
+ follows those gates on every reconcile, and a user pause keeps it, since the control is then what
28
+ resumes. CSS that used the attribute to mean "a video is registered" needs another hook.
29
+
30
+ - **A revealed poster is hidden with `opacity`, so its `alt` stays in the accessibility tree.**
31
+ `video.css` hid it with `visibility: hidden`, which removes it from the tree, while the README
32
+ tells you to put the meaning in the poster's `alt` and hide the video. It now sets
33
+ `opacity: 0 !important` and `pointer-events: none` on the poster image, inside a `<picture>` too,
34
+ after the same `--polite-fade` delay. `!important` because image.css's failsafe animation would
35
+ otherwise keep a marked poster that nothing manages opaque. A rule of yours that changes the
36
+ poster's opacity after the reveal now needs `!important` as well, and a test that waited for the
37
+ poster with Playwright's `toBeHidden()` must wait for computed opacity `0`, since Playwright
38
+ counts an element at opacity 0 as visible.
39
+
40
+ - **`smallViewport` defaults to `'(max-width: 767.98px)'`**, from `'(max-width: 767px)'`. Beside a
41
+ `(min-width: 768px)` the old default left every width between 767px and 768px, which page zoom
42
+ produces, matching neither, so arbitration treated those viewports as large. The gap is now
43
+ 0.02px. Range syntax would close it fully, but Safari before 16.4 never matches it. Pass
44
+ `smallViewport` yourself to keep the old value.
45
+
46
+ ### Added
47
+
48
+ - **A warning when a registered video is not decorative.** The markup contract asks for
49
+ `tabindex="-1" aria-hidden="true"` on the video, and nothing checked it. `register()` now warns
50
+ once per page, naming the video, when its `tabindex` attribute is not `-1` or no
51
+ `aria-hidden="true"` sits on the video or a box around it.
52
+
53
+ - **A warning when `--polite-fade` is not a CSS time.** A value such as `0.6` computes to `0s`
54
+ rather than to the stylesheet's default, so it silently removed the image fade. The first video
55
+ box and the first fading image that see such a value are named once per page. The browser parses
56
+ the value, so `calc(0.3s * 2)` passes, and a bare `0` stays quiet because it gives the cut it
57
+ looks like.
58
+
59
+ - **`register(video, { until, prefetchWhileGated: true })`** lets a gated video download while it
60
+ waits, so a splash buys it load time. A gate used to hold the fetch as well as playback, and that
61
+ stays the default, since a page may rely on a consent dialog holding the bytes too. The download
62
+ still waits for `startWhen`, reduced motion, Save-Data and a user pause, and starts once the video
63
+ is on screen or within `prefetchMargin`. A host can end its splash on the video's own
64
+ `canplaythrough`, which fires while the gate still holds; the README shows the recipe.
65
+
66
+ ### Fixed
67
+
68
+ - **`warm()` with `sources` fetched the candidate for the full viewport width.** A `<source>`
69
+ without its own `sizes` is selected as if it said `100vw`, and `sizes` went on the `<img>` alone,
70
+ so a desktop warm could fetch a file several times the size the destination then picked. Every
71
+ `<source>` now carries the `sizes` it was passed.
72
+
73
+ - **A video buffered ahead through `prefetchMargin` started playing off screen when its first source
74
+ could not be decoded.** The source fallback revealed and played whatever came next, whether or not
75
+ anything had asked the video to play. It now moves to the next source and waits.
76
+
77
+ - **A lazy image still faded in under reduced motion.** `image.css`'s reduced-motion rule lost on
78
+ specificity to the rule that sets the fade, so the README's promise that reduced motion overrides
79
+ `--polite-fade` held only for eager images that opted in. Lazy images now arrive at once there.
80
+
81
+ - **A paused page still buffered videos within `prefetchMargin`.** The prefetch observer fetched
82
+ without asking whether the visitor had paused. It now waits, and resuming starts the fetch.
83
+
84
+ ### Documentation
85
+
86
+ - **`register()` and `pauseAll()` carry their documentation in the published types.** Their doc
87
+ comments sat above other functions, so an editor hovering either showed nothing.
88
+
89
+ - **An `until` gate does not protect LCP**, and the README no longer says it does. The video's
90
+ first frame is an LCP candidate whenever it paints; only `startWhen: 'interaction'` keeps it out.
91
+ The poster-`load` gate example is gone for the same reason.
92
+ - **A gate that never settles holds its video for good.** The README shows racing it against a
93
+ timeout of your own.
94
+ - **The wrapper recipe in "Composing your own animation" gates only on images that will load.**
95
+ Lazy images in a horizontal scroller may never be fetched, so a wrapper waiting on all of them
96
+ waits for its failsafe.
97
+
6
98
  ## 0.5.0 (2026-09-12)
7
99
 
8
100
  ### Breaking
package/README.md CHANGED
@@ -166,9 +166,12 @@ console names any image in that state, so widen the selector or drop the
166
166
  attribute. An eager image is never hidden; give the attribute the value `eager`
167
167
  to opt one into the fade anyway.
168
168
 
169
- `data-polite-active` is on `<html>` for as long as at least one video is
170
- registered. A pause control is markup on every page, but it must not offer to
171
- stop something that was never registered, and nothing else lets CSS answer that:
169
+ `data-polite-active` is on `<html>` while a registered video may play. It is
170
+ absent when nothing is registered, under reduced motion, on Save-Data or a 2g
171
+ connection, and where `atOnce` is `0` for the viewport; a user pause keeps it,
172
+ since the control is then what resumes. A pause control is markup on every page,
173
+ but it must not offer to stop something that cannot move, and CSS alone cannot
174
+ see most of those reasons:
172
175
 
173
176
  ```css
174
177
  [data-polite-pause-control] {
@@ -197,7 +200,7 @@ you have to add yourself:
197
200
  .card.is-visible:has(img[data-polite-reveal]:not([data-polite-ready])) {
198
201
  opacity: 0;
199
202
  /* yours, not the library's: see below */
200
- animation: your-failsafe 0s linear 5s forwards;
203
+ animation: your-failsafe 1ms linear 5s forwards;
201
204
  }
202
205
  ```
203
206
 
@@ -205,7 +208,17 @@ you have to add yourself:
205
208
  `image.css` is CSS-only and reveals **the image**, not a wrapper around it. So a
206
209
  bundle that never arrives leaves your wrapper hidden for good even though the
207
210
  library's own failsafe fired. Give any rule of yours that hides on
208
- `:not([data-polite-ready])` its own failsafe on the same delay.
211
+ `:not([data-polite-ready])` its own failsafe on the same delay, and give it a
212
+ length: Chromium runs no animation of `0s` on the compositor, and Lighthouse
213
+ lists every such element as non-composited.
214
+
215
+ **Gate a wrapper only on images that will load.** The `:has()` above waits on
216
+ every marked image inside the card, and lazy loading may never fetch some of
217
+ them. Measured in Chromium, in a 412px-wide horizontal scroller of nine lazy
218
+ images, only the first three loaded, and three in the middle never did, even
219
+ after scrolling past them. A card holding that scroller waits for your failsafe
220
+ and then appears unfaded. Gate it on the images in view when it appears, such as
221
+ the first, or leave scrollers out of the rule.
209
222
 
210
223
  One limit worth knowing: a skipped `content-visibility: auto` subtree runs no
211
224
  animations, so neither failsafe fires there until the section is scrolled into
@@ -249,14 +262,18 @@ it could have mattered.
249
262
  6. The video carries `tabindex="-1" aria-hidden="true"`. It is decorative, and
250
263
  without this it lands in the tab order: measured in Firefox, twelve background
251
264
  videos sat ahead of the pause button, so a keyboard user reached it on the
252
- thirteenth Tab.
265
+ thirteenth Tab. The console says so once per page when a registered video
266
+ lacks either; `aria-hidden` on a box around it counts too. Anything the
267
+ picture means goes in the poster's `alt`: the reveal hides the poster with
268
+ `opacity`, not `visibility`, so it stays in the accessibility tree while the
269
+ video plays.
253
270
 
254
271
  ## API
255
272
 
256
273
  ```js
257
274
  // polite-media/video
258
- register(video, { until, observe, startWhen }); // manage a video
259
- registerAll(target?, { until, startWhen }); // every [data-polite-media] video by default
275
+ register(video, { until, observe, startWhen, prefetchWhileGated }); // manage a video
276
+ registerAll(target?, { until, startWhen, prefetchWhileGated }); // every [data-polite-media] video by default
260
277
  unregister(video); // stop managing it, release everything
261
278
  unregisterAll(); // tear down the whole page
262
279
  configure({ ... }); // before the first register, or it throws
@@ -309,7 +326,13 @@ rather than guessed.
309
326
  | option | default | reach for it when |
310
327
  | --------------- | ---------------------------- | ---------------------------------------------------------- |
311
328
  | `atOnce` | `{ small: 1, large: 'all' }` | a feed wants one at a time everywhere, or phones want none |
312
- | `smallViewport` | `'(max-width: 767px)'` | your breakpoint is not ours |
329
+ | `smallViewport` | `'(max-width: 767.98px)'` | your breakpoint is not ours |
330
+
331
+ The `smallViewport` default meets a `(min-width: 768px)` with a 0.02px gap rather
332
+ than a whole pixel, so a fractional width from page zoom lands on one side. Pair
333
+ your own queries the same way. Range syntax, `(width < 768px)`, would close the
334
+ gap entirely, but Safari before 16.4 never matches it, so phones there would
335
+ count as large and play every visible video at once.
313
336
 
314
337
  **When may it begin?**
315
338
 
@@ -338,30 +361,70 @@ effect on the next pass.
338
361
  callers: a `2` would otherwise fall through to the single-slot branch and quietly
339
362
  mean `1`.
340
363
 
341
- **A malformed `smallViewport` cannot be detected.** An invalid media query does
342
- not throw and does not normalise to anything recognisable; Chromium echoes the
343
- text straight back and never matches. So `smallViewport: '(max-width: 767)'`,
364
+ **A malformed `smallViewport` is not checked for you.** An invalid media query
365
+ does not throw and does not normalise to anything recognisable; Chromium echoes
366
+ the text straight back and never matches. So `smallViewport: '(max-width: 767)'`,
344
367
  missing its unit, means arbitration silently never engages and phones behave like
345
- desktops. Check that value by eye.
368
+ desktops. Check it in the console on both sides of your breakpoint:
369
+ `matchMedia(query).matches` should be `true` below it and `false` above. A
370
+ malformed query is `false` on both.
346
371
 
347
372
  ### Per-video gates
348
373
 
349
374
  `register(video, { until: promise })` holds a video back until the promise
350
- settles: for a splash screen, a consent dialog, or protecting your LCP. A hero at
351
- scroll-top is reported visible in the observer's very first batch, so without
352
- this it starts before whatever the page is waiting on has finished.
375
+ settles: for a splash screen or a consent dialog. A hero at scroll-top is
376
+ reported visible in the observer's very first batch, so without this it starts
377
+ before whatever the page is waiting on has finished.
378
+
379
+ **A gate delays the video; it does not keep it out of Largest Contentful Paint.**
380
+ The first frame is an LCP candidate like any image, whenever it paints: measured
381
+ in Chromium on a real hero gated behind a splash, the video's first frame
382
+ replaced the poster as the LCP element just after the gate opened. Only
383
+ [`startWhen: 'interaction'`](#startwhen) keeps a video out of LCP.
384
+
385
+ The gate opens when the promise settles, fulfilled or rejected, and not
386
+ otherwise: one that never settles holds the video on its poster for the life of
387
+ the page. If whatever resolves it might never run, race it against a timeout of
388
+ your own:
353
389
 
354
390
  ```js
355
- // If the poster is your LCP element, gate the video on it having loaded.
356
- register(video, {
357
- until: new Promise((done) => {
358
- const poster = document.querySelector('img.hero-poster');
359
- if (!poster || poster.complete) done();
360
- else poster.addEventListener('load', () => done(), { once: true });
361
- }),
362
- });
391
+ const timeout = (ms) => new Promise((done) => setTimeout(done, ms));
392
+
393
+ register(video, { until: Promise.race([splashDone, timeout(15000)]) });
394
+ ```
395
+
396
+ **A splash can buy the video load time.** A gate holds the download as well as
397
+ playback, so a hero behind a five-second splash only starts fetching once the
398
+ splash ends. `prefetchWhileGated: true` lets it download while it waits: only
399
+ playback waits for the gate, while `startWhen`, reduced motion, Save-Data and a
400
+ pause still hold the fetch. The browser fires `canplaythrough` once it can play
401
+ through, which a splash can end on, with a floor and a cap of its own:
402
+
403
+ ```js
404
+ const wait = (ms) => new Promise((done) => setTimeout(done, ms));
405
+ let endSplash;
406
+ const splashDone = new Promise((done) => (endSplash = done));
407
+
408
+ register(hero, { until: splashDone, prefetchWhileGated: true });
409
+
410
+ // Nothing downloads where nothing will play (reduced motion, Save-Data,
411
+ // atOnce: 0), or while the visitor has paused.
412
+ const root = document.documentElement;
413
+ const buffered =
414
+ root.hasAttribute('data-polite-active') && !root.hasAttribute('data-polite-paused')
415
+ ? new Promise((done) => hero.addEventListener('canplaythrough', done, { once: true }))
416
+ : Promise.resolve();
417
+
418
+ // At least 1.5s of splash, at most 4.5s, and in between until the hero can play through.
419
+ await Promise.race([Promise.all([buffered, wait(1500)]), wait(4500)]);
420
+ hideSplash();
421
+ endSplash();
363
422
  ```
364
423
 
424
+ Keep the cap. Whether iOS Safari buffers under `preload="auto"` before anything
425
+ calls `play()` is untested, and the cap is what ends the splash if the event
426
+ never comes.
427
+
365
428
  `register(video, { observe: box })` observes a wrapper instead of the video, for
366
429
  when the video is `inset: 0` inside the element that carries the layout.
367
430
 
@@ -562,7 +625,9 @@ Two things that surprise people:
562
625
  that is invalid at computed-value time falls back to the property's initial
563
626
  value, and the `var()` fallback only applies when the property is undefined.
564
627
  Harmless on video, which cuts anyway; on images it silently removes the 350ms
565
- fade.
628
+ fade. The console names the first image or video box where it is set to
629
+ something that is not a time. A bare `0` is left alone, since the cut it gives
630
+ is what it looks like it asks for.
566
631
 
567
632
  Reduced motion overrides you either way: the stylesheet sets `transition: none`
568
633
  there, so a fade you asked for never runs for someone who asked not to see one.
@@ -585,6 +650,11 @@ warmOnIntent('a[data-hero]', (link) => ({
585
650
  }));
586
651
  ```
587
652
 
653
+ Give a format through `sources` with its `type`, as above, rather than as a bare `srcset`: a
654
+ browser that cannot decode AVIF then skips it and warms the fallback, instead of fetching a file it
655
+ cannot show. `sizes` goes on every `<source>` and on the image, since a `<source>` without its own
656
+ is chosen as if it said `100vw`.
657
+
588
658
  **Nothing in this package parses a media query**, which is the point: the
589
659
  candidates are assembled as a detached `<picture>` and the browser picks, running
590
660
  the same algorithm it will run on the destination. Hand-rolling that selection
@@ -633,6 +703,24 @@ document.addEventListener('astro:page-load', () => registerAll('[data-polite-med
633
703
  registered twice. Videos that did not survive need no cleanup: the coordinator
634
704
  drops any entry whose element has left the document on its next pass.
635
705
 
706
+ ## Astro
707
+
708
+ This is developed against Astro projects, and the same three things come up.
709
+
710
+ **Import each stylesheet from the component that emits its attribute.** A build folds every
711
+ component's CSS into one file, so a stylesheet imported anywhere covers everywhere, while a dev
712
+ server serves it per component and does not. Import `image.css` from some other component and the
713
+ fade works in the build and is missing in dev, on exactly the pages that do not render whichever
714
+ component happened to import it. The console says so when the stylesheet never arrives.
715
+
716
+ **Put the `<script>` in the component that renders the media**, not in the layout. Astro bundles a
717
+ component's script once per page, so a page that never renders that component never downloads the
718
+ coordinator.
719
+
720
+ **A strict CSP needs nothing from this package.** It writes attributes and never an inline `style`,
721
+ which the end-to-end suite asserts on every demo, so `style-src` needs no `'unsafe-inline'` on its
722
+ account.
723
+
636
724
  ## What it does
637
725
 
638
726
  - Reveals on a genuinely presented frame, never on `playing`.
@@ -52,8 +52,13 @@ export interface ConfigureOptions {
52
52
  */
53
53
  prefetchMargin?: string;
54
54
  /**
55
- * Which viewports count as small. Configurable because 767px is one project's
55
+ * Which viewports count as small. Configurable because 768px is one project's
56
56
  * breakpoint, not a fact about phones.
57
+ *
58
+ * The default stops at 767.98px, leaving 0.02px beside a `(min-width: 768px)`
59
+ * rather than the whole pixel a zoomed page's fractional width can fall into.
60
+ * Range syntax would close the gap, but Safari before 16.4 never matches it, so
61
+ * phones there would count as large.
57
62
  */
58
63
  smallViewport?: string;
59
64
  /**
@@ -158,6 +163,9 @@ export interface RegisterOptions {
158
163
  * at scroll-top is reported visible in the observer's very first batch, so
159
164
  * without a gate it starts before whatever the page is waiting on (a splash
160
165
  * screen, a consent dialog) has finished.
166
+ *
167
+ * Settling, fulfilled or rejected, is the only release: a promise that never
168
+ * settles holds the video on its poster for the life of the page.
161
169
  */
162
170
  until?: Promise<unknown>;
163
171
  /**
@@ -173,8 +181,30 @@ export interface RegisterOptions {
173
181
  * the same rule buys nothing.
174
182
  */
175
183
  startWhen?: StartWhen;
184
+ /**
185
+ * Let the video download while `until` holds it, so a splash buys it load time.
186
+ * Only playback waits for the gate; the download still waits for `startWhen`,
187
+ * Save-Data, reduced motion and a user pause, and starts once the video is on
188
+ * screen or within `prefetchMargin`.
189
+ *
190
+ * Opt-in, because a gate holding the fetch too is what `until` has always
191
+ * done, and a page gating a video behind a consent dialog may rely on it.
192
+ */
193
+ prefetchWhileGated?: boolean;
176
194
  }
177
195
  export declare function reconcile(): void;
196
+ /**
197
+ * Starts managing a video: reveals it on its first genuinely painted frame,
198
+ * plays it only while it is visible, falls through its `<source>` list when one
199
+ * cannot be decoded, and stops it when a gate closes.
200
+ *
201
+ * The video and its poster must already share a box carrying `data-polite-media`
202
+ * in the authored markup, and the video should be `muted loop playsinline
203
+ * preload="none"`. Calling this twice on the same element is a no-op.
204
+ *
205
+ * @param video the element to manage
206
+ * @param options see {@link RegisterOptions}
207
+ */
178
208
  export declare function register(video: HTMLVideoElement, options?: RegisterOptions): void;
179
209
  /** Anything that names one or more videos. See {@link Target}. */
180
210
  export type VideoTarget = Target<HTMLVideoElement>;
@@ -199,6 +229,22 @@ export declare function registerAll(target?: VideoTarget, options?: Omit<Registe
199
229
  * was the last one. Safe to call for a video that was never registered.
200
230
  */
201
231
  export declare function unregister(video: HTMLVideoElement): void;
232
+ /**
233
+ * Stops every managed video and keeps them stopped.
234
+ *
235
+ * WCAG 2.2.2 applies to content that moves automatically, runs for more than
236
+ * five seconds, and sits alongside other content -- which a looping background
237
+ * video does. Honouring `prefers-reduced-motion` is necessary but, per the W3C
238
+ * understanding document, is not listed as satisfying the criterion, so a
239
+ * mechanism the user can actually operate has to exist.
240
+ *
241
+ * The host supplies the button and its styling; the library ships no markup and
242
+ * no CSS for it. A `<button>` carrying `data-polite-pause-control` toggles this.
243
+ *
244
+ * It has to be a real `<button>`. The binding is a delegated `click`, and a
245
+ * browser only synthesises that from Enter and Space for a native button, so a
246
+ * `div[role="button"][tabindex="0"]` responds to a mouse and not to a keyboard.
247
+ */
202
248
  export declare function pauseAll(): void;
203
249
  /** Lets playback resume, undoing {@link pauseAll}. */
204
250
  export declare function resumeAll(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"coordinator.d.ts","sourceRoot":"","sources":["../src/coordinator.ts"],"names":[],"mappings":"AAWA,OAAO,EAAkB,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3D;;;;;;;;GAQG;AAEH;;;;;GAKG;AACH,MAAM,MAAM,MAAM,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAEnC;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,aAAa,GAAG,aAAa,CAAC;AAElE;;;;;;;;GAQG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;;;;;;;;;;OAgBG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACnD;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;;;;;;;;;;;OAaG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AA4ED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAcvD;AAwDD,MAAM,WAAW,eAAe;IAC9B;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IACzB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAkjBD,wBAAgB,SAAS,IAAI,IAAI,CAsFhC;AAiPD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,gBAAgB,EAAE,OAAO,GAAE,eAAoB,GAAG,IAAI,CA6DrF;AAED,kEAAkE;AAClE,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;AAEnD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CACzB,MAAM,GAAE,WAAyC,EACjD,OAAO,GAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAM,GAC7C,IAAI,CAEN;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAwBxD;AAiED,wBAAgB,QAAQ,IAAI,IAAI,CAG/B;AAED,sDAAsD;AACtD,wBAAgB,SAAS,IAAI,IAAI,CAGhC;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAQpC;AAED,2EAA2E;AAC3E,wBAAgB,aAAa,IAAI,IAAI,CAQpC;AAED,0EAA0E;AAC1E,wBAAgB,OAAO,IAAI;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAErF"}
1
+ {"version":3,"file":"coordinator.d.ts","sourceRoot":"","sources":["../src/coordinator.ts"],"names":[],"mappings":"AAYA,OAAO,EAAkB,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3D;;;;;;;;GAQG;AAEH;;;;;GAKG;AACH,MAAM,MAAM,MAAM,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAEnC;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,aAAa,GAAG,aAAa,CAAC;AAElE;;;;;;;;GAQG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;;;;;;;;;;OAgBG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACnD;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;;;;;;;;;;;OAaG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AA4ED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAcvD;AA0DD,MAAM,WAAW,eAAe;IAC9B;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IACzB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AA0lBD,wBAAgB,SAAS,IAAI,IAAI,CA4FhC;AAmOD;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,gBAAgB,EAAE,OAAO,GAAE,eAAoB,GAAG,IAAI,CAgErF;AAED,kEAAkE;AAClE,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;AAEnD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CACzB,MAAM,GAAE,WAAyC,EACjD,OAAO,GAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAM,GAC7C,IAAI,CAEN;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAwBxD;AAiDD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,QAAQ,IAAI,IAAI,CAG/B;AAED,sDAAsD;AACtD,wBAAgB,SAAS,IAAI,IAAI,CAGhC;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAIpC;AAED,2EAA2E;AAC3E,wBAAgB,aAAa,IAAI,IAAI,CAQpC;AAED,0EAA0E;AAC1E,wBAAgB,OAAO,IAAI;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAErF"}