@sparkletree/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +105 -0
  3. package/dist/analytics.d.ts +75 -0
  4. package/dist/analytics.d.ts.map +1 -0
  5. package/dist/analytics.js +170 -0
  6. package/dist/analytics.js.map +1 -0
  7. package/dist/audio.d.ts +85 -0
  8. package/dist/audio.d.ts.map +1 -0
  9. package/dist/audio.js +465 -0
  10. package/dist/audio.js.map +1 -0
  11. package/dist/client.d.ts +79 -0
  12. package/dist/client.d.ts.map +1 -0
  13. package/dist/client.js +251 -0
  14. package/dist/client.js.map +1 -0
  15. package/dist/context.d.ts +104 -0
  16. package/dist/context.d.ts.map +1 -0
  17. package/dist/context.js +277 -0
  18. package/dist/context.js.map +1 -0
  19. package/dist/fragments.d.ts +108 -0
  20. package/dist/fragments.d.ts.map +1 -0
  21. package/dist/fragments.js +223 -0
  22. package/dist/fragments.js.map +1 -0
  23. package/dist/index.d.ts +31 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +30 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/protocol.d.ts +70 -0
  28. package/dist/protocol.d.ts.map +1 -0
  29. package/dist/protocol.js +97 -0
  30. package/dist/protocol.js.map +1 -0
  31. package/dist/publishableKey.d.ts +38 -0
  32. package/dist/publishableKey.d.ts.map +1 -0
  33. package/dist/publishableKey.js +69 -0
  34. package/dist/publishableKey.js.map +1 -0
  35. package/dist/safeUrl.d.ts +56 -0
  36. package/dist/safeUrl.d.ts.map +1 -0
  37. package/dist/safeUrl.js +117 -0
  38. package/dist/safeUrl.js.map +1 -0
  39. package/dist/sse.d.ts +51 -0
  40. package/dist/sse.d.ts.map +1 -0
  41. package/dist/sse.js +137 -0
  42. package/dist/sse.js.map +1 -0
  43. package/dist/state.d.ts +321 -0
  44. package/dist/state.d.ts.map +1 -0
  45. package/dist/state.js +594 -0
  46. package/dist/state.js.map +1 -0
  47. package/dist/text.d.ts +10 -0
  48. package/dist/text.d.ts.map +1 -0
  49. package/dist/text.js +29 -0
  50. package/dist/text.js.map +1 -0
  51. package/dist/theme.d.ts +52 -0
  52. package/dist/theme.d.ts.map +1 -0
  53. package/dist/theme.js +88 -0
  54. package/dist/theme.js.map +1 -0
  55. package/dist/trust.d.ts +52 -0
  56. package/dist/trust.d.ts.map +1 -0
  57. package/dist/trust.js +95 -0
  58. package/dist/trust.js.map +1 -0
  59. package/dist/variant.d.ts +117 -0
  60. package/dist/variant.d.ts.map +1 -0
  61. package/dist/variant.js +167 -0
  62. package/dist/variant.js.map +1 -0
  63. package/dist/wire.d.ts +564 -0
  64. package/dist/wire.d.ts.map +1 -0
  65. package/dist/wire.js +133 -0
  66. package/dist/wire.js.map +1 -0
  67. package/package.json +55 -0
package/dist/audio.js ADDED
@@ -0,0 +1,465 @@
1
+ /**
2
+ * Audio engine — W3, plan v1.1 decision (b): audio is CORE-ONLY.
3
+ *
4
+ * `window.__squidAudio` was an inline IIFE in the shell template. Moving it
5
+ * here makes it versioned and patchable: a provider changes their embed API
6
+ * and one package bump reaches every consumer, instead of every customer
7
+ * needing to re-copy a component.
8
+ *
9
+ * The accepted trade-off is that consumers cannot customise playback
10
+ * behaviour without forking. The mitigation is the shape of this module: what
11
+ * moves into core is the ENGINE — adapters, gesture wiring, the listen clock,
12
+ * media session — and NOT the chrome. `getState()` and `on()` expose
13
+ * everything a copied component needs to render its own player UI against an
14
+ * engine it does not own. Moving the shell's markup in here as well would have
15
+ * been "just moving the file", and would have made every consumer's player
16
+ * look like signage.
17
+ *
18
+ * Two invariants worth stating because both are load-bearing:
19
+ *
20
+ * - AUTOPLAY IS NEVER USED. Tap to play, always. Autoplaying audio in
21
+ * someone else's page is the single fastest way for a customer to remove
22
+ * the SDK.
23
+ * - ONE PLAYER AT A TIME. Mounting a second destroys the first, so a page
24
+ * that cycles variants cannot end up with two tracks over each other.
25
+ */
26
+ // --- listen clock -------------------------------------------------------------
27
+ /**
28
+ * Accumulates audible time.
29
+ *
30
+ * Capped at ten times the track duration (six hours when the duration is
31
+ * unknown). A tab left open for a week on a looping track would otherwise
32
+ * report a listen time that is technically true and analytically useless —
33
+ * and, since listen time feeds CVG, one such session can dominate a campaign's
34
+ * engagement numbers on its own.
35
+ */
36
+ function createListenClock(getDurationMs) {
37
+ let accumulatedMs = 0;
38
+ let startedAt = null;
39
+ const capMs = () => {
40
+ const total = getDurationMs() || 0;
41
+ return total > 0 ? total * 10 : 21_600_000;
42
+ };
43
+ const fold = () => {
44
+ if (startedAt === null)
45
+ return;
46
+ const now = Date.now();
47
+ accumulatedMs = Math.min(accumulatedMs + (now - startedAt), capMs());
48
+ startedAt = now;
49
+ };
50
+ return {
51
+ start: () => {
52
+ if (startedAt === null)
53
+ startedAt = Date.now();
54
+ },
55
+ stop: () => {
56
+ fold();
57
+ startedAt = null;
58
+ },
59
+ valueMs: () => {
60
+ fold();
61
+ return accumulatedMs;
62
+ },
63
+ };
64
+ }
65
+ function createEmitter() {
66
+ const listeners = new Map();
67
+ return {
68
+ on(event, listener) {
69
+ const set = listeners.get(event) ?? new Set();
70
+ set.add(listener);
71
+ listeners.set(event, set);
72
+ return () => set.delete(listener);
73
+ },
74
+ emit(event, state) {
75
+ for (const listener of listeners.get(event) ?? []) {
76
+ try {
77
+ listener(state);
78
+ }
79
+ catch {
80
+ // A consumer's listener throwing must not stop playback or the
81
+ // other listeners.
82
+ }
83
+ }
84
+ },
85
+ clear() {
86
+ listeners.clear();
87
+ },
88
+ };
89
+ }
90
+ // --- media session ------------------------------------------------------------
91
+ /**
92
+ * Publish lock-screen metadata and point the OS transport controls at the
93
+ * handle (not the raw element), so custom chrome stays in sync with the
94
+ * Dynamic Island.
95
+ *
96
+ * Best-effort throughout: every touch is wrapped, because an OS metadata
97
+ * failure must never break playback. The Spotify adapter deliberately never
98
+ * calls this — its iframe owns its own media session, and two sessions fight.
99
+ */
100
+ function armMediaSession(block, handle) {
101
+ try {
102
+ const nav = typeof navigator !== "undefined" ? navigator : undefined;
103
+ const session = nav?.mediaSession;
104
+ if (!session || typeof MediaMetadata === "undefined")
105
+ return;
106
+ const init = { title: block.title || "" };
107
+ // Suno ingestion often leaves artist empty — omit rather than pass "",
108
+ // which renders as a blank line on the lock screen.
109
+ if (block.artist)
110
+ init.artist = block.artist;
111
+ if (block.artwork?.url) {
112
+ init.artwork = [{ src: block.artwork.url, sizes: "512x512" }];
113
+ }
114
+ session.metadata = new MediaMetadata(init);
115
+ session.setActionHandler("play", () => handle.play());
116
+ session.setActionHandler("pause", () => handle.pause());
117
+ }
118
+ catch {
119
+ // No media session, or a browser that rejects one of the handlers.
120
+ }
121
+ }
122
+ function setPlaybackState(state) {
123
+ try {
124
+ const nav = typeof navigator !== "undefined" ? navigator : undefined;
125
+ if (nav?.mediaSession)
126
+ nav.mediaSession.playbackState = state;
127
+ }
128
+ catch {
129
+ // Best-effort.
130
+ }
131
+ }
132
+ // --- suno adapter -------------------------------------------------------------
133
+ const PROGRESS_INTERVAL_MS = 500;
134
+ function mountSuno(block, host) {
135
+ if (!block.audioUrl)
136
+ return null;
137
+ const emitter = createEmitter();
138
+ const audio = document.createElement("audio");
139
+ audio.preload = "metadata";
140
+ audio.loop = Boolean(block.loop);
141
+ audio.src = block.audioUrl;
142
+ // Hidden: the engine owns playback, the consumer owns the chrome.
143
+ audio.style.display = "none";
144
+ host.appendChild(audio);
145
+ let destroyed = false;
146
+ let lastProgressAt = 0;
147
+ const durationMs = () => audio.duration && Number.isFinite(audio.duration)
148
+ ? audio.duration * 1000
149
+ : block.durationMs || 0;
150
+ const positionMs = () => (audio.currentTime || 0) * 1000;
151
+ const clock = createListenClock(durationMs);
152
+ const getState = () => {
153
+ const duration = durationMs();
154
+ const position = positionMs();
155
+ return {
156
+ provider: "suno",
157
+ playing: !audio.paused && !audio.ended,
158
+ positionMs: position,
159
+ durationMs: duration,
160
+ percent: duration > 0 ? Math.max(0, Math.min(1, position / duration)) : 0,
161
+ listenedMs: clock.valueMs(),
162
+ ended: audio.ended,
163
+ errored: false,
164
+ };
165
+ };
166
+ const handle = {
167
+ provider: "suno",
168
+ caps: { customChrome: true, anonymousPlayback: true },
169
+ getState,
170
+ play() {
171
+ try {
172
+ // play() rejects when the browser blocks it; that is a normal outcome
173
+ // of a gesture policy, not an error worth surfacing.
174
+ void audio.play()?.catch(() => { });
175
+ }
176
+ catch {
177
+ /* element torn down */
178
+ }
179
+ },
180
+ pause() {
181
+ try {
182
+ audio.pause();
183
+ }
184
+ catch {
185
+ /* element torn down */
186
+ }
187
+ },
188
+ toggle() {
189
+ if (getState().playing)
190
+ handle.pause();
191
+ else
192
+ handle.play();
193
+ },
194
+ seek(target) {
195
+ try {
196
+ audio.currentTime = Math.max(0, target) / 1000;
197
+ }
198
+ catch {
199
+ /* not seekable yet */
200
+ }
201
+ },
202
+ on: emitter.on,
203
+ destroy() {
204
+ if (destroyed)
205
+ return;
206
+ destroyed = true;
207
+ clock.stop();
208
+ try {
209
+ audio.pause();
210
+ audio.removeAttribute("src");
211
+ audio.load();
212
+ audio.remove();
213
+ }
214
+ catch {
215
+ /* already gone */
216
+ }
217
+ setPlaybackState("none");
218
+ emitter.clear();
219
+ },
220
+ };
221
+ audio.addEventListener("playing", () => {
222
+ clock.start();
223
+ armMediaSession(block, handle);
224
+ setPlaybackState("playing");
225
+ emitter.emit("play", getState());
226
+ });
227
+ audio.addEventListener("pause", () => {
228
+ clock.stop();
229
+ setPlaybackState("paused");
230
+ emitter.emit("pause", getState());
231
+ });
232
+ audio.addEventListener("timeupdate", () => {
233
+ const now = Date.now();
234
+ if (now - lastProgressAt < PROGRESS_INTERVAL_MS)
235
+ return;
236
+ lastProgressAt = now;
237
+ emitter.emit("progress", getState());
238
+ });
239
+ audio.addEventListener("ended", () => {
240
+ clock.stop();
241
+ setPlaybackState("paused");
242
+ emitter.emit("complete", getState());
243
+ });
244
+ audio.addEventListener("error", () => {
245
+ clock.stop();
246
+ emitter.emit("error", { ...getState(), errored: true });
247
+ });
248
+ audio.addEventListener("loadedmetadata", () => emitter.emit("ready", getState()));
249
+ return handle;
250
+ }
251
+ const SPOTIFY_API_SRC = "https://open.spotify.com/embed/iframe-api/v1";
252
+ let spotifyApiPromise = null;
253
+ /** Lazy-load the Spotify iFrame API, once per page. */
254
+ function loadSpotifyIframeApi() {
255
+ if (spotifyApiPromise)
256
+ return spotifyApiPromise;
257
+ spotifyApiPromise = new Promise((resolve, reject) => {
258
+ const global = window;
259
+ // Chain rather than clobber: this global is THE handoff point for the
260
+ // iFrame API, so any other Spotify embed on the customer's page registers
261
+ // the same callback — overwriting it would silently kill their player.
262
+ const previous = global.onSpotifyIframeApiReady;
263
+ global.onSpotifyIframeApiReady = (api) => {
264
+ try {
265
+ previous?.(api);
266
+ }
267
+ catch {
268
+ // The other embed's handler throwing must not cost us the API.
269
+ }
270
+ resolve(api);
271
+ };
272
+ const script = document.createElement("script");
273
+ script.src = SPOTIFY_API_SRC;
274
+ script.async = true;
275
+ script.onerror = () => {
276
+ // Reset so a later mount can retry — a blocked third-party script is
277
+ // often a transient network or extension condition, and caching the
278
+ // failure forever would mean audio never recovers in that tab.
279
+ spotifyApiPromise = null;
280
+ reject(new Error("SparkleTree: Spotify iFrame API failed to load"));
281
+ };
282
+ document.head.appendChild(script);
283
+ });
284
+ return spotifyApiPromise;
285
+ }
286
+ function mountSpotify(block, host) {
287
+ if (!block.trackRef)
288
+ return null;
289
+ const emitter = createEmitter();
290
+ let controller = null;
291
+ let destroyed = false;
292
+ let pendingPlay = false;
293
+ let paused = true;
294
+ let position = 0;
295
+ let duration = block.durationMs || 0;
296
+ let ended = false;
297
+ let lastProgressAt = 0;
298
+ const clock = createListenClock(() => duration);
299
+ const getState = () => ({
300
+ provider: "spotify",
301
+ playing: !paused,
302
+ positionMs: position,
303
+ durationMs: duration,
304
+ percent: duration > 0 ? Math.max(0, Math.min(1, position / duration)) : 0,
305
+ listenedMs: clock.valueMs(),
306
+ ended,
307
+ errored: false,
308
+ });
309
+ const handle = {
310
+ provider: "spotify",
311
+ // The Spotify embed must remain visible and unmodified, so a consumer
312
+ // cannot legitimately render its own transport over it.
313
+ caps: { customChrome: false, anonymousPlayback: false },
314
+ getState,
315
+ play() {
316
+ if (!controller) {
317
+ // Arm rather than drop: a tap before the iframe is ready is the
318
+ // common case on a cold load, and losing it reads as a dead button.
319
+ pendingPlay = true;
320
+ return;
321
+ }
322
+ try {
323
+ controller.play();
324
+ }
325
+ catch {
326
+ /* controller torn down */
327
+ }
328
+ },
329
+ pause() {
330
+ try {
331
+ controller?.pause();
332
+ }
333
+ catch {
334
+ /* controller torn down */
335
+ }
336
+ },
337
+ toggle() {
338
+ if (!paused)
339
+ handle.pause();
340
+ else
341
+ handle.play();
342
+ },
343
+ seek(target) {
344
+ try {
345
+ controller?.seek(Math.max(0, target) / 1000);
346
+ }
347
+ catch {
348
+ /* not seekable */
349
+ }
350
+ },
351
+ on: emitter.on,
352
+ destroy() {
353
+ if (destroyed)
354
+ return;
355
+ destroyed = true;
356
+ clock.stop();
357
+ try {
358
+ controller?.destroy();
359
+ }
360
+ catch {
361
+ /* already gone */
362
+ }
363
+ controller = null;
364
+ emitter.clear();
365
+ },
366
+ };
367
+ void loadSpotifyIframeApi()
368
+ .then((api) => {
369
+ if (destroyed)
370
+ return;
371
+ api.createController(host, { uri: block.trackRef, width: "100%", height: 80 }, (ctrl) => {
372
+ if (destroyed) {
373
+ try {
374
+ ctrl.destroy();
375
+ }
376
+ catch {
377
+ /* already gone */
378
+ }
379
+ return;
380
+ }
381
+ controller = ctrl;
382
+ ctrl.addListener("ready", () => {
383
+ emitter.emit("ready", getState());
384
+ if (pendingPlay && !destroyed) {
385
+ pendingPlay = false;
386
+ try {
387
+ ctrl.play();
388
+ }
389
+ catch {
390
+ /* controller torn down */
391
+ }
392
+ }
393
+ });
394
+ // Spotify has no play/pause/ended events — everything is derived from
395
+ // playback_update transitions.
396
+ ctrl.addListener("playback_update", (event) => {
397
+ const data = event?.data ?? {};
398
+ if (typeof data.position === "number")
399
+ position = data.position;
400
+ if (typeof data.duration === "number" && data.duration > 0)
401
+ duration = data.duration;
402
+ const nowPaused = Boolean(data.isPaused);
403
+ if (!nowPaused && paused) {
404
+ paused = false;
405
+ ended = false;
406
+ clock.start();
407
+ emitter.emit("play", getState());
408
+ }
409
+ else if (nowPaused && !paused) {
410
+ paused = true;
411
+ clock.stop();
412
+ // Within half a second of the end counts as completion: the
413
+ // provider stops reporting before position reaches duration
414
+ // exactly, so an equality test would never fire.
415
+ if (duration > 0 && position >= duration - 500) {
416
+ ended = true;
417
+ emitter.emit("complete", getState());
418
+ }
419
+ else {
420
+ emitter.emit("pause", getState());
421
+ }
422
+ }
423
+ const now = Date.now();
424
+ if (now - lastProgressAt >= PROGRESS_INTERVAL_MS) {
425
+ lastProgressAt = now;
426
+ emitter.emit("progress", getState());
427
+ }
428
+ });
429
+ });
430
+ })
431
+ .catch(() => {
432
+ emitter.emit("error", { ...getState(), errored: true });
433
+ });
434
+ return handle;
435
+ }
436
+ // --- single-player registry ---------------------------------------------------
437
+ let activeHandle = null;
438
+ /** The currently mounted player, if any. */
439
+ export function activePlayer() {
440
+ return activeHandle;
441
+ }
442
+ /**
443
+ * Mount a player for `block` inside `host`.
444
+ *
445
+ * Destroys any existing player first — the single-player invariant. A page
446
+ * cycling variants would otherwise stack tracks on top of each other, and the
447
+ * viewer has no way to stop one they can no longer see.
448
+ */
449
+ export function mountAudio(block, host) {
450
+ destroyActiveAudio();
451
+ const handle = block.provider === "suno"
452
+ ? mountSuno(block, host)
453
+ : block.provider === "spotify"
454
+ ? mountSpotify(block, host)
455
+ : null;
456
+ activeHandle = handle;
457
+ return handle;
458
+ }
459
+ export function destroyActiveAudio() {
460
+ if (!activeHandle)
461
+ return;
462
+ activeHandle.destroy();
463
+ activeHandle = null;
464
+ }
465
+ //# sourceMappingURL=audio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio.js","sourceRoot":"","sources":["../src/audio.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * The client: fetch `/content` for first paint, then open the stream and feed
3
+ * every event into the choreographer.
4
+ *
5
+ * The event dispatch below is the ONLY place in the SDK that knows event
6
+ * names, and every name it knows comes from the generated contract. A server
7
+ * that starts emitting something newer than this build is not an error — it is
8
+ * an older client, which the protocol explicitly supports — so unknown events
9
+ * are ignored rather than warned about.
10
+ */
11
+ import { type StreamTarget } from "./protocol.js";
12
+ import { CopyChoreographer, type ChoreographerOptions, type CreativeState } from "./state.js";
13
+ export interface ContentSnapshot {
14
+ campaignId: string;
15
+ variantId: string;
16
+ content: {
17
+ headline?: string;
18
+ body?: string;
19
+ cta?: string | {
20
+ text?: string;
21
+ };
22
+ image?: string;
23
+ experienceManifest?: unknown;
24
+ };
25
+ theme?: {
26
+ colors: Record<string, string>;
27
+ sources: Record<string, string>;
28
+ };
29
+ products?: unknown[];
30
+ meta?: Record<string, unknown>;
31
+ }
32
+ export interface StreamOptions extends ChoreographerOptions {
33
+ target: StreamTarget;
34
+ signal?: AbortSignal;
35
+ /** Swap the transport (SSR, tests, a customer's instrumented fetch). */
36
+ fetchImpl?: typeof fetch;
37
+ /** Called on every state change. */
38
+ onState?: (state: CreativeState) => void;
39
+ /**
40
+ * Called when the server cannot speak the version this build requested. The
41
+ * SDK has already kept its own first paint by the time this fires; the hook
42
+ * exists so a consumer can log it once, not so it can retry.
43
+ */
44
+ onProtocolUnsupported?: (info: {
45
+ requested: number;
46
+ supported: number[];
47
+ }) => void;
48
+ }
49
+ export interface StreamHandle {
50
+ /** The live choreographer. Subscribe for updates. */
51
+ choreographer: CopyChoreographer;
52
+ /** Resolves when the stream ends, however it ends. Never rejects. */
53
+ finished: Promise<CreativeState>;
54
+ /** Stop early. Idempotent. */
55
+ close: () => void;
56
+ }
57
+ /**
58
+ * Fetch the first-paint content.
59
+ *
60
+ * Content-first, rewrite-once: this is what the SDK paints BEFORE any stream
61
+ * exists, so there is never a skeleton on screen. If it fails, the consumer's
62
+ * `fallback` prop is what stands in — which is why that prop is required
63
+ * rather than optional.
64
+ */
65
+ export declare function fetchContent(target: StreamTarget, options?: {
66
+ signal?: AbortSignal;
67
+ fetchImpl?: typeof fetch;
68
+ }): Promise<ContentSnapshot | null>;
69
+ /**
70
+ * Open an island stream and choreograph it.
71
+ *
72
+ * Returns immediately with a handle; `finished` resolves with the terminal
73
+ * state. It never rejects — a broken stream leaves whatever was painted on
74
+ * screen and reports `phase: "failed"`, because throwing from inside a
75
+ * customer's render tree is a worse outcome than a creative that stopped
76
+ * adapting.
77
+ */
78
+ export declare function openStream(options: StreamOptions): StreamHandle;
79
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAcH,OAAO,EAIL,KAAK,YAAY,EAClB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,iBAAiB,EACjB,KAAK,oBAAoB,EAEzB,KAAK,aAAa,EACnB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE;QACP,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,GAAG;YAAE,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACjC,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,kBAAkB,CAAC,EAAE,OAAO,CAAC;KAC9B,CAAC;IACF,KAAK,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAC;IAC5E,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,aAAc,SAAQ,oBAAoB;IACzD,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,wEAAwE;IACxE,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,oCAAoC;IACpC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IACzC;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,EAAE,CAAA;KAAE,KAAK,IAAI,CAAC;CACpF;AAED,MAAM,WAAW,YAAY;IAC3B,qDAAqD;IACrD,aAAa,EAAE,iBAAiB,CAAC;IACjC,qEAAqE;IACrE,QAAQ,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IACjC,8BAA8B;IAC9B,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAwBD;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,YAAY,EACpB,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,WAAW,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CAAO,GAC/D,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAwBjC;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,YAAY,CAwG/D"}