@saeris/hanko 0.0.0 → 0.2.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.
Files changed (57) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/LICENSE.md +21 -0
  3. package/README.md +346 -0
  4. package/dist/approve/index.d.mts +318 -0
  5. package/dist/approve/index.d.mts.map +1 -0
  6. package/dist/approve/index.mjs +393 -0
  7. package/dist/approve/index.mjs.map +1 -0
  8. package/dist/client/index.d.mts +101 -0
  9. package/dist/client/index.d.mts.map +1 -0
  10. package/dist/client/index.mjs +215 -0
  11. package/dist/client/index.mjs.map +1 -0
  12. package/dist/codes-Ba_qYH6u.mjs +93 -0
  13. package/dist/codes-Ba_qYH6u.mjs.map +1 -0
  14. package/dist/handlers.d.mts +113 -0
  15. package/dist/handlers.d.mts.map +1 -0
  16. package/dist/handlers.mjs +194 -0
  17. package/dist/handlers.mjs.map +1 -0
  18. package/dist/index.d.mts +5 -0
  19. package/dist/index.mjs +345 -0
  20. package/dist/index.mjs.map +1 -0
  21. package/dist/linking-DcQSMgem.mjs +177 -0
  22. package/dist/linking-DcQSMgem.mjs.map +1 -0
  23. package/dist/linking-nKoayyHf.d.mts +133 -0
  24. package/dist/linking-nKoayyHf.d.mts.map +1 -0
  25. package/dist/machine-CRHKjtoP.d.mts +223 -0
  26. package/dist/machine-CRHKjtoP.d.mts.map +1 -0
  27. package/dist/machine-D_5DAFxi.mjs +155 -0
  28. package/dist/machine-D_5DAFxi.mjs.map +1 -0
  29. package/dist/qr.d.mts +58 -0
  30. package/dist/qr.d.mts.map +1 -0
  31. package/dist/qr.mjs +27 -0
  32. package/dist/qr.mjs.map +1 -0
  33. package/dist/scan/index.d.mts +384 -0
  34. package/dist/scan/index.d.mts.map +1 -0
  35. package/dist/scan/index.mjs +409 -0
  36. package/dist/scan/index.mjs.map +1 -0
  37. package/dist/scan/worker.d.mts +2 -0
  38. package/dist/scan/worker.mjs +2 -0
  39. package/dist/server-BhoYRkCm.d.mts +257 -0
  40. package/dist/server-BhoYRkCm.d.mts.map +1 -0
  41. package/dist/stores/kv.d.mts +64 -0
  42. package/dist/stores/kv.d.mts.map +1 -0
  43. package/dist/stores/kv.mjs +87 -0
  44. package/dist/stores/kv.mjs.map +1 -0
  45. package/dist/stores/memory.d.mts +22 -0
  46. package/dist/stores/memory.d.mts.map +1 -0
  47. package/dist/stores/memory.mjs +42 -0
  48. package/dist/stores/memory.mjs.map +1 -0
  49. package/dist/types-BvBIFPH6.mjs +7 -0
  50. package/dist/types-BvBIFPH6.mjs.map +1 -0
  51. package/dist/types-C82lb-zX.d.mts +82 -0
  52. package/dist/types-C82lb-zX.d.mts.map +1 -0
  53. package/dist/worker-BdwaK1uX.mjs +5291 -0
  54. package/dist/worker-BdwaK1uX.mjs.map +1 -0
  55. package/dist/worker-DxbdBA2z.d.mts +164 -0
  56. package/dist/worker-DxbdBA2z.d.mts.map +1 -0
  57. package/package.json +116 -3
@@ -0,0 +1,384 @@
1
+ import { a as createQrDecoder, c as GrayImage, i as QrDecoderOptions, l as Point, n as DecodeResponse, o as BitMatrix, r as serveDecoder, s as DecodedSymbol, t as DecodeRequest, u as SymbolDecoder } from "../worker-DxbdBA2z.mjs";
2
+ //#region src/scan/qr/progressive.d.ts
3
+ /** A scanner that improves its effort as frames arrive. */
4
+ interface ProgressiveScanner {
5
+ /**
6
+ * Offer one frame.
7
+ *
8
+ * Returns a symbol as soon as one is read, and `null` otherwise — including
9
+ * while effort is still ramping up.
10
+ */
11
+ scan(image: GrayImage): DecodedSymbol | null;
12
+ /**
13
+ * Reset the effort ramp.
14
+ *
15
+ * Call when the scene changes — a new code presented, the camera moved
16
+ * somewhere else — so the next frame starts cheap again rather than
17
+ * inheriting effort earned by a symbol that is no longer there.
18
+ */
19
+ reset(): void;
20
+ /** How much effort the next frame will receive, in milliseconds. */
21
+ readonly budgetMs: number;
22
+ }
23
+ /** Options for {@link createProgressiveScanner}. */
24
+ interface ProgressiveOptions extends Omit<QrDecoderOptions, `timeBudgetMs`> {
25
+ /**
26
+ * Budget for the first frame, in milliseconds.
27
+ *
28
+ * Deliberately small. Most frames a camera delivers contain no code at all,
29
+ * and this is what every one of them costs.
30
+ */
31
+ initialBudgetMs?: number;
32
+ /**
33
+ * Ceiling on the per-frame budget.
34
+ *
35
+ * 400ms by default: beyond that a single frame stalls the preview
36
+ * noticeably, and at 30fps the ladder has had a dozen frames to work with
37
+ * by the time the ramp reaches it.
38
+ */
39
+ maxBudgetMs?: number;
40
+ /**
41
+ * How much the budget grows per consecutive frame that shows a symbol.
42
+ *
43
+ * Growth is conditional on there being something to find: a frame with no
44
+ * finder candidate at all should not earn the next frame more time, or a
45
+ * camera pointed at a wall would ramp to its ceiling and stay there.
46
+ */
47
+ growth?: number;
48
+ }
49
+ /**
50
+ * Create a scanner that spreads decoding effort across frames.
51
+ *
52
+ * The ramp is driven by evidence rather than by a timer. A frame in which the
53
+ * decoder finds nothing resets it, because nothing is there to spend effort
54
+ * on; a frame that finds a symbol but cannot read it raises the budget,
55
+ * because that is exactly the case where more effort pays.
56
+ */
57
+ declare const createProgressiveScanner: ({ initialBudgetMs, maxBudgetMs, growth, ...decoderOptions }?: ProgressiveOptions) => ProgressiveScanner;
58
+ /**
59
+ * Drive a decoder running in a worker.
60
+ *
61
+ * Same shape as {@link createProgressiveScanner} but asynchronous, because
62
+ * the work happens elsewhere. The main thread stays free: measured on a hard
63
+ * frame, an in-thread decode blocks 208ms at a 40ms budget and 481ms at
64
+ * 400ms, which at 60fps is 12 and 28 dropped frames respectively — a visible
65
+ * freeze on exactly the frames where someone is lining up a shot.
66
+ *
67
+ * Frames offered while a decode is in flight are DROPPED rather than queued.
68
+ * A camera produces frames faster than they can be decoded, and a queue would
69
+ * grow without bound while returning increasingly stale results; the next
70
+ * frame is always a better input than a backlogged one.
71
+ */
72
+ interface WorkerScanner {
73
+ /** Offer a frame. Resolves `null` if dropped, still ramping, or unreadable. */
74
+ scan(image: GrayImage): Promise<DecodedSymbol | null>;
75
+ /** Reset the effort ramp — call when the scene changes. */
76
+ reset(): void;
77
+ /** Stop the worker and release it. */
78
+ close(): void;
79
+ /** Whether a decode is currently in flight. */
80
+ readonly busy: boolean;
81
+ }
82
+ /**
83
+ * Wrap a worker in the progressive interface.
84
+ *
85
+ * The worker is supplied rather than constructed here, because how a worker
86
+ * is created is a bundler question — `new Worker(new URL(...), { type:
87
+ * "module" })` in Vite, a blob URL elsewhere — and a library that guessed
88
+ * would be wrong for most consumers.
89
+ */
90
+ declare const createWorkerScanner: (worker: {
91
+ postMessage: {
92
+ (message: unknown, transfer: never[]): void;
93
+ (message: unknown, options?: unknown): void;
94
+ };
95
+ addEventListener?: (type: string, listener: (event: {
96
+ data: unknown;
97
+ }) => void) => void;
98
+ on?: (type: string, listener: (message: unknown) => void) => void;
99
+ terminate?: () => void;
100
+ }, { initialBudgetMs, maxBudgetMs, growth }?: ProgressiveOptions) => WorkerScanner;
101
+ //#endregion
102
+ //#region src/scan/qr/locate.d.ts
103
+ /** A located finder pattern. */
104
+ interface FinderPattern {
105
+ readonly center: Point;
106
+ /** Estimated module size in pixels, from the pattern's own width. */
107
+ readonly moduleSize: number;
108
+ }
109
+ /**
110
+ * Drop candidates that have no clear space around them.
111
+ *
112
+ * Returns the original list when filtering would leave fewer than three, so a
113
+ * symbol photographed without its full quiet zone — against a dark table
114
+ * edge, say — is never made undecodable by this check.
115
+ */
116
+ declare const withClearance: (matrix: BitMatrix, patterns: readonly FinderPattern[]) => FinderPattern[];
117
+ //#endregion
118
+ //#region src/scan/binarize.d.ts
119
+ /** Convert RGBA pixels to greyscale using perceptual luminance weights. */
120
+ declare const toGray: (rgba: Uint8ClampedArray, width: number, height: number) => GrayImage;
121
+ /**
122
+ * Binarize against one threshold chosen from the whole image's histogram.
123
+ *
124
+ * The opposite trade to {@link binarize}. A single threshold cannot follow a
125
+ * shadow across a page — which is why local thresholding exists and why it
126
+ * takes the `brightness` and `monitor` categories from nothing to something.
127
+ * But local thresholding invents structure in flat regions, and on a clean,
128
+ * evenly-lit image a global threshold is both more faithful and less prone to
129
+ * that.
130
+ *
131
+ * Neither dominates, so this is a retry rather than a replacement. zxing-cpp
132
+ * reached the same conclusion from the other direction: its issue #809 is an
133
+ * image its local binarizer cannot read and its global one can, and its
134
+ * issue #500 is a prototype for supporting several binarizers for exactly
135
+ * this reason.
136
+ *
137
+ * The threshold is the midpoint between the two dominant peaks of the
138
+ * histogram rather than the mean. A QR is mostly two tones, so the histogram
139
+ * is bimodal, and the mean of a symbol with more light area than dark sits
140
+ * inside the light peak and thresholds half the modules away.
141
+ */
142
+ declare const binarizeGlobal: (image: GrayImage, { invert }?: {
143
+ invert?: boolean;
144
+ }) => BitMatrix;
145
+ /**
146
+ * Morphological closing on a bit matrix — dilate, then erode.
147
+ *
148
+ * Fills small light specks inside dark regions while leaving real structure
149
+ * intact, because dilation closes a gap smaller than the kernel and the
150
+ * following erosion restores every boundary the dilation moved.
151
+ *
152
+ * The failure this targets is specific: zxing-cpp issue #951 diagnoses an
153
+ * undetected symbol as "white pixels inside the black square that disrupt
154
+ * their detection" of the finder patterns, and its remedy is exactly this
155
+ * operation. Speckle inside a finder breaks the run-length signature — a
156
+ * single light pixel splits one dark run into two — so the pattern stops
157
+ * matching 1:1:3:1:1 even though a human sees it perfectly well.
158
+ *
159
+ * A 3x3 kernel: large enough for sensor speckle and dust, small enough that
160
+ * it cannot close a real one-module gap at any usable resolution.
161
+ */
162
+ declare const close: (matrix: BitMatrix) => BitMatrix;
163
+ /**
164
+ * Downscale by box-averaging whole blocks of pixels.
165
+ *
166
+ * Not for speed — for signal. A symbol photographed from a distance on a
167
+ * 12-megapixel sensor has modules two or three pixels wide, and at that scale
168
+ * neither run-length scanning nor shape detection produces reliable
169
+ * structure: measured on the corpus, both detectors return module-size
170
+ * estimates spanning 1.1 to 137.9 pixels within a single image, which is
171
+ * noise rather than measurement.
172
+ *
173
+ * Averaging blocks of pixels down trades resolution the symbol does not have
174
+ * for a cleaner signal it does. BoofCV builds an image pyramid for the same
175
+ * reason and scores 100% on that corpus category.
176
+ *
177
+ * Box averaging rather than nearest-neighbour sampling, because dropping
178
+ * pixels aliases a module grid badly — the very structure being looked for
179
+ * beats against the sampling lattice.
180
+ */
181
+ declare const downscale: (image: GrayImage, factor: number) => GrayImage;
182
+ /**
183
+ * Blur an image with a separable box filter, approximating a Gaussian.
184
+ *
185
+ * Two passes of a box filter — one horizontal, one vertical — is a standard
186
+ * cheap stand-in for a true Gaussian, and it is separable, so cost is linear
187
+ * in radius rather than quadratic.
188
+ *
189
+ * This exists for one specific failure: photographing a screen. Moire banding
190
+ * is frequency ALIASING between the camera sensor grid and the display's
191
+ * sub-pixel grid, so the interference sits at a much higher spatial frequency
192
+ * than the modules do. Low-pass filtering suppresses the banding and leaves
193
+ * the modules — measured on the benchmark corpus, it takes the `monitor`
194
+ * category from 0 of 25 to 10 of 25.
195
+ *
196
+ * It is NOT a free win and must not be applied by default: the same filter
197
+ * takes `blurred` from 5 of 14 down to 1, and `nominal` from 3 to 0. A blurred
198
+ * photograph blurred again is unreadable. Use it as a retry after a sharp
199
+ * pass fails.
200
+ */
201
+ declare const blur: (image: GrayImage, radius: number) => GrayImage;
202
+ /**
203
+ * Binarize a greyscale image into a bit matrix.
204
+ *
205
+ * `true` (1) means DARK, matching the QR convention where a set module is a
206
+ * dark one. Fixing polarity here — at the single boundary where pixels become
207
+ * bits — is deliberate: every stage above this one can then assume one
208
+ * orientation, and none of them has to ask which way round the image was.
209
+ *
210
+ * @param invert Treat light modules as set. Needed for symbols rendered
211
+ * light-on-dark, which decoders that assume dark-on-light read as nothing at
212
+ * all. Callers that do not know should try both.
213
+ */
214
+ declare const binarize: (image: GrayImage, { invert }?: {
215
+ invert?: boolean;
216
+ }) => BitMatrix;
217
+ //#endregion
218
+ //#region src/scan/qr/format.d.ts
219
+ /** Error-correction level, in the order the format field encodes them. */
220
+ type ErrorCorrectionLevel = `L` | `M` | `Q` | `H`;
221
+ //#endregion
222
+ //#region src/scan/qr/decode-matrix.d.ts
223
+ /** What a successful matrix decode yields. */
224
+ interface MatrixDecodeResult {
225
+ readonly value: string;
226
+ readonly version: number;
227
+ readonly errorCorrectionLevel: ErrorCorrectionLevel;
228
+ readonly mask: number;
229
+ }
230
+ /**
231
+ * Decode a bit matrix into the text it encodes.
232
+ *
233
+ * Returns `null` for anything unreadable. Every failure here is a normal
234
+ * outcome rather than an exception: a camera sees far more non-symbols than
235
+ * symbols, and a decoder that threw on each one would make its callers write
236
+ * try/catch around their hot loop.
237
+ */
238
+ declare const decodeMatrix: (matrix: BitMatrix,
239
+ /**
240
+ * Modules the imaging layer could not read confidently, as a mask the same
241
+ * shape as `matrix` where 1 marks "do not trust this".
242
+ *
243
+ * Reed-Solomon corrects twice as many codewords when it is told WHERE the
244
+ * damage is: the bound is `2 * errors + erasures <= check codewords`. A
245
+ * region blown out by glare or crushed by shadow is visibly untrustworthy,
246
+ * and thresholding it into a confident bit throws that away. Measured on a
247
+ * version 3 symbol at ecM, a blob covering 15% of the area decodes 0% of the
248
+ * time as errors and 100% as erasures.
249
+ *
250
+ * Optional because it costs a per-frame allocation the ordinary path does
251
+ * not need, and because a decoder handed no mask must behave exactly as it
252
+ * did before.
253
+ */
254
+ unreliable?: Uint8Array) => MatrixDecodeResult | null;
255
+ //#endregion
256
+ //#region src/scan/qr/sample.d.ts
257
+ /**
258
+ * A projective (homography) transform between two quadrilaterals.
259
+ *
260
+ * Affine is not enough. An affine transform preserves parallel lines, and
261
+ * perspective does not — the far edge of a tilted square is genuinely shorter
262
+ * than the near one. Only a projective transform models that, which is why
263
+ * this carries the two extra terms an affine matrix lacks.
264
+ */
265
+ interface Transform {
266
+ readonly a11: number;
267
+ readonly a12: number;
268
+ readonly a13: number;
269
+ readonly a21: number;
270
+ readonly a22: number;
271
+ readonly a23: number;
272
+ readonly a31: number;
273
+ readonly a32: number;
274
+ readonly a33: number;
275
+ }
276
+ //#endregion
277
+ //#region src/scan/gpu.d.ts
278
+ /** Scores many transforms against one image, on the GPU. */
279
+ interface GpuScorer {
280
+ score(image: BitMatrix, transforms: readonly Transform[], size: number, alignmentCenters: readonly number[]): Promise<Int32Array>;
281
+ destroy(): void;
282
+ }
283
+ /** Whether this runtime exposes WebGPU at all. */
284
+ declare const hasWebGpu: () => boolean;
285
+ /**
286
+ * Create a GPU scorer, or `null` where WebGPU is unavailable.
287
+ *
288
+ * Returns `null` rather than throwing: every caller must have a CPU path
289
+ * anyway, so an absent GPU is a normal condition and not an error.
290
+ */
291
+ declare const createGpuScorer: () => Promise<GpuScorer | null>;
292
+ //#endregion
293
+ //#region src/scan/machine.d.ts
294
+ /**
295
+ * A scan session, as a state machine.
296
+ *
297
+ * Modeled the way `machine.ts` models the device flow: states, events, and a
298
+ * declarative transition table, hand-rolled so this stays dependency-free.
299
+ *
300
+ * Deliberately NOT applied to the decode pipeline itself. Binarize → locate →
301
+ * extract → decode is a fallible sequential pipeline, not a machine: each
302
+ * stage runs once per frame and either produces a value or does not. Modeling
303
+ * it as states would add ceremony without making a single illegal move
304
+ * impossible, which is the only thing a transition table buys.
305
+ *
306
+ * What IS a machine is the session around it — permission, camera lifecycle,
307
+ * pause and resume — and that part is identical whether the frames are being
308
+ * searched for a QR, a DataMatrix, or an Aztec code. So it lives here,
309
+ * symbology-agnostic, and the decoders plug into it.
310
+ */
311
+ /**
312
+ * Lifecycle of one scanning session.
313
+ *
314
+ * `scanning` is the only state that consumes frames. `decoded` is terminal
315
+ * rather than a return to `scanning`: a scanner that kept reading after a
316
+ * successful decode would fire twice on the same symbol, and every consumer
317
+ * would have to debounce it. Restarting is explicit.
318
+ *
319
+ * `denied` is separate from `failed` because they are different conversations
320
+ * with the user — one asks them to change a browser setting, the other is a
321
+ * fault they cannot act on. Collapsing them is how a permission prompt ends up
322
+ * reported as "something went wrong".
323
+ */
324
+ type ScanState = `idle` | `starting` | `scanning` | `paused` | `decoded` | `denied` | `failed` | `stopped`;
325
+ /** Why a scan session ended without a result. */
326
+ type ScanFailure =
327
+ /** No camera on this device, or none matching the requested facing mode. */
328
+ `no-camera` |
329
+ /** The page is not a secure context, so `getUserMedia` is unavailable. */
330
+ `insecure-context` |
331
+ /** The camera was lost mid-session — unplugged, or claimed by another app. */
332
+ `camera-lost` |
333
+ /** The decoder itself threw. Distinct from "no code in this frame". */
334
+ `decoder-error`;
335
+ /** Events driving a scan session. */
336
+ type ScanEvent =
337
+ /** Consumer asked to begin. */
338
+ {
339
+ type: `START`;
340
+ } |
341
+ /** Camera acquired and frames are flowing. */
342
+ {
343
+ type: `READY`;
344
+ } |
345
+ /** A frame decoded successfully. Terminal — restarting is explicit. */
346
+ {
347
+ type: `DECODE`;
348
+ value: string;
349
+ } |
350
+ /** The user refused camera access. */
351
+ {
352
+ type: `DENY`;
353
+ } |
354
+ /** Something broke that the user cannot act on. */
355
+ {
356
+ type: `FAIL`;
357
+ reason: ScanFailure;
358
+ } |
359
+ /** Tab hidden, or the consumer suspended scanning. */
360
+ {
361
+ type: `PAUSE`;
362
+ } |
363
+ /** Visible again. */
364
+ {
365
+ type: `RESUME`;
366
+ } |
367
+ /** Consumer tore the session down. */
368
+ {
369
+ type: `STOP`;
370
+ };
371
+ /** Whether `event` would move `state`. */
372
+ declare const canTransitionScan: (state: ScanState, event: ScanEvent[`type`]) => boolean;
373
+ /** Apply an event. Unknown events for the current state are no-ops. */
374
+ declare const scanTransition: (state: ScanState, event: ScanEvent) => ScanState;
375
+ /**
376
+ * Terminal states accept no further events.
377
+ *
378
+ * Derived from the table rather than listed, so a new state cannot be added
379
+ * without its terminality following automatically.
380
+ */
381
+ declare const isScanSettled: (state: ScanState) => boolean;
382
+ //#endregion
383
+ export { type BitMatrix, type DecodeRequest, type DecodeResponse, type DecodedSymbol, type GpuScorer, type GrayImage, type MatrixDecodeResult, type Point, type ProgressiveOptions, type ProgressiveScanner, type QrDecoderOptions, type ScanEvent, type ScanFailure, type ScanState, type SymbolDecoder, type WorkerScanner, binarize, binarizeGlobal, blur, canTransitionScan, close, createGpuScorer, createProgressiveScanner, createQrDecoder, createWorkerScanner, decodeMatrix, downscale, hasWebGpu, isScanSettled, scanTransition, serveDecoder, toGray, withClearance };
384
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/scan/qr/progressive.ts","../../src/scan/qr/locate.ts","../../src/scan/binarize.ts","../../src/scan/qr/format.ts","../../src/scan/qr/decode-matrix.ts","../../src/scan/qr/sample.ts","../../src/scan/gpu.ts","../../src/scan/machine.ts"],"mappings":";;;UA6BiB;;;;;;;EAOf,KAAK,OAAO,YAAY;;;;;;;;EASxB;;WAGS;;;UAIM,2BAA2B,KAC1C;;;;;;;EASA;;;;;;;;EASA;;;;;;;;EASA;;;;;;;;;;cAWW,6BAA4B,iBAAA,aAAA,WAAA,mBAKtC,uBAA0B;;;;;;;;;;;;;;;UA2DZ;;EAEf,KAAK,OAAO,YAAY,QAAQ;;EAEhC;;EAEA;;WAES;;;;;;;;;;cAWE,sBACX;EAUE;KACG,kBAAkB;KAClB,kBAAkB;;EAErB,oBACE,cACA,WAAW;IAAS;;EAEtB,MAAM,cAAc,WAAW;EAC/B;KAEF,iBAAA,aAAA,WAIG,uBACF;;;;UCtLc;WACN,QAAQ;;WAER;;;;;;;;;cAynBE,gBACX,QAAQ,WACR,mBAAmB,oBAClB;;;;cCpmBU,SACX,MAAM,mBACN,eACA,mBACC;;;;;;;;;;;;;;;;;;;;;;cAiNU,iBACX,OAAO,aACP;EAAsB;MACrB;;;;;;;;;;;;;;;;;;cAmEU,QAAS,QAAQ,cAAY;;;;;;;;;;;;;;;;;;;cAkF7B,YAAa,OAAO,WAAW,mBAAiB;;;;;;;;;;;;;;;;;;;;cAgEhD,OAAQ,OAAO,WAAW,mBAAiB;;;;;;;;;;;;;cAmL3C,WACX,OAAO,aACP;EAAsB;MACrB;;;;KC5nBS;;;;UCKK;WACN;WACA;WACA,sBAAsB;WACtB;;;;;;;;;;cAWE,eACX,QAAQ,WAgBR;;;;;;;;;;;;;;;;AAAA,aAAa,eACZ;;;;;;;;;;;UC9Bc;WACN;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;;;;UC6HM;EACf,MACE,OAAO,WACP,qBAAqB,aACrB,cACA,sCACC,QAAQ;EACX;;;cAIW;;;;;;;cASA,uBAA4B,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KCxJrC;;KAWA;;;;;;;;;;KAWA;;;EAEN;;;;EAEA;;;;EAEA;EAAgB;;;;EAEhB;;;;EAEA;EAAc,QAAQ;;;;EAEtB;;;;EAEA;;;;EAEA;;;cAyCO,oBACX,OAAO,WACP,OAAO;;cAII,iBAAkB,OAAO,WAAW,OAAO,cAAY;;;;;;;cASvD,gBAAiB,OAAO"}