@sylwellsoftware/glue 0.1.0-alpha.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +145 -9
- package/dist/commands/asyncCommand.d.ts +1 -1
- package/dist/commands/asyncCommand.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +537 -116
- package/dist/index.js.map +1 -1
- package/package.json +2 -7
- package/EXPERIMENTAL.md +0 -44
- package/dist/emitter-upM7NC28.js +0 -293
- package/dist/emitter-upM7NC28.js.map +0 -1
- package/dist/experimental.d.ts +0 -7
- package/dist/experimental.d.ts.map +0 -1
- package/dist/experimental.js +0 -151
- package/dist/experimental.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Glue
|
|
2
2
|
|
|
3
|
-
Glue is
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
maps.
|
|
3
|
+
Glue is a small, platform-neutral reactive value and live-query library. Fray
|
|
4
|
+
uses it as its state/data-flow layer, but Glue does not depend on Fray, a DOM,
|
|
5
|
+
or any UI framework. Its implementation and tests are strict TypeScript; the
|
|
6
|
+
ESM build includes declarations and declaration maps.
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Install with pnpm:
|
|
9
9
|
|
|
10
10
|
```bash
|
|
11
11
|
pnpm add @sylwellsoftware/glue
|
|
@@ -15,6 +15,73 @@ Glue is ESM-only. Core emitters, derived state, and diagnostics support Node 22+
|
|
|
15
15
|
and modern ESM runtimes without a DOM. `LiveQuery` needs `AbortController`, and
|
|
16
16
|
`RestQueryHandler` needs Fetch and URL capabilities unless they are injected.
|
|
17
17
|
|
|
18
|
+
## Design model
|
|
19
|
+
|
|
20
|
+
Glue models values that stay current rather than requests that callers must
|
|
21
|
+
manually rerun and redistribute. The same small read-side protocol applies to
|
|
22
|
+
local state, computed state, query inputs, and asynchronous results:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
interface ReadableEmitter<TValue, TError = unknown> {
|
|
26
|
+
get(): TValue
|
|
27
|
+
getFetchState(): FetchStateValue
|
|
28
|
+
getError(): TError | null
|
|
29
|
+
subscribe(listener: (notification: {
|
|
30
|
+
value: TValue
|
|
31
|
+
fetchState: FetchStateValue
|
|
32
|
+
error: TError | null
|
|
33
|
+
event: EventBubble<unknown> | null
|
|
34
|
+
}) => void): () => void
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
That uniformity is the central design constraint. It lets a consumer bind to a
|
|
39
|
+
current value without knowing whether the value is mutable, derived, or backed
|
|
40
|
+
by asynchronous retrieval. Richer responsibilities remain separate:
|
|
41
|
+
|
|
42
|
+
| Concept | Responsibility |
|
|
43
|
+
| --- | --- |
|
|
44
|
+
| `BaseEmitter` | Synchronously readable value/snapshot, subscriptions, mapping, equality, diagnostics, and disposal |
|
|
45
|
+
| `Emitter` | An explicitly writable leaf value |
|
|
46
|
+
| `DerivedEmitter` | A cached value computed from one or more readable emitters |
|
|
47
|
+
| `QueryArg` | A named query-input view over another emitter when a semantic name is useful |
|
|
48
|
+
| `LiveQuery` | Reactive request timing, latest-request ownership, status/error state, and cached results |
|
|
49
|
+
| `QueryHandler` | Non-reactive retrieval strategy over a plain named argument object |
|
|
50
|
+
| `RestQueryHandler` | HTTP URL construction, wire serialization, Fetch execution, and JSON result retrieval |
|
|
51
|
+
| `EventBubble` / `EventBus` | Optional cause-and-effect diagnostics without owning application history |
|
|
52
|
+
|
|
53
|
+
The intended flow is explicit and one-directional:
|
|
54
|
+
|
|
55
|
+
```text
|
|
56
|
+
Emitter(s) ──► DerivedEmitter(s) ──► named query arguments
|
|
57
|
+
│
|
|
58
|
+
▼
|
|
59
|
+
LiveQuery
|
|
60
|
+
│ current plain values
|
|
61
|
+
▼
|
|
62
|
+
QueryHandler
|
|
63
|
+
│
|
|
64
|
+
▼
|
|
65
|
+
value + fetch state + error
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
This separation prevents several kinds of accidental coupling:
|
|
69
|
+
|
|
70
|
+
- leaf values do not need to know that a distant consumer may use them in a
|
|
71
|
+
request;
|
|
72
|
+
- derived values express semantic computation rather than transport encoding;
|
|
73
|
+
- `LiveQuery` decides *when* the current inputs require retrieval, while its
|
|
74
|
+
handler decides *how* retrieval works;
|
|
75
|
+
- REST-specific formats, base URLs, authentication wrappers, and response
|
|
76
|
+
validation remain at application/adapter boundaries;
|
|
77
|
+
- one live query can be mapped into multiple local views without multiplying
|
|
78
|
+
network requests.
|
|
79
|
+
|
|
80
|
+
Glue deliberately favors explicit graphs over hidden tracking, proxy-created
|
|
81
|
+
state, hooks, or a global store. If a value can be computed, prefer a
|
|
82
|
+
`DerivedEmitter` to manually mirroring it. Use callbacks for commands and
|
|
83
|
+
emitters for state that other objects need to read, combine, or observe.
|
|
84
|
+
|
|
18
85
|
## Emitters
|
|
19
86
|
|
|
20
87
|
```ts
|
|
@@ -56,6 +123,42 @@ current ones.
|
|
|
56
123
|
`emitter.map(fn)` transforms the complete value. `emitter.mapEach(fn)` requires
|
|
57
124
|
an array and transforms its non-nullish members.
|
|
58
125
|
|
|
126
|
+
### Ownership, equality, and disposal
|
|
127
|
+
|
|
128
|
+
Emitters eagerly cache their current snapshot so reads are synchronous.
|
|
129
|
+
`Object.is` is the default value equality rule; pass `equals` when the domain
|
|
130
|
+
has a better equivalence relation. A derived emitter subscribes eagerly to its
|
|
131
|
+
sources and releases those subscriptions when sources are replaced or the
|
|
132
|
+
derived value is disposed.
|
|
133
|
+
|
|
134
|
+
The object that creates a long-lived emitter/query normally owns its disposal.
|
|
135
|
+
Disposal is idempotent, prevents new subscriptions, and releases owned source
|
|
136
|
+
subscriptions. A UI or service lifecycle should therefore dispose the graph it
|
|
137
|
+
constructs rather than relying on garbage collection to sever active edges.
|
|
138
|
+
|
|
139
|
+
## Query arguments
|
|
140
|
+
|
|
141
|
+
`LiveQuery` accepts a named record of any readable emitters, so wrapping every
|
|
142
|
+
input in `QueryArg` is neither required nor desirable. Use `QueryArg` when a
|
|
143
|
+
stable query-facing name and separately owned bridge clarify the boundary:
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
import {DerivedEmitter, Emitter, LiveQuery, QueryArg} from '@sylwellsoftware/glue'
|
|
147
|
+
|
|
148
|
+
const firstName = new Emitter('Ada')
|
|
149
|
+
const lastName = new Emitter('Lovelace')
|
|
150
|
+
const searchText = new DerivedEmitter(
|
|
151
|
+
[firstName, lastName] as const,
|
|
152
|
+
([first, last]) => `${first} ${last}`,
|
|
153
|
+
)
|
|
154
|
+
const search = new QueryArg('search', searchText)
|
|
155
|
+
const users = new LiveQuery({handler, args: {search}})
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Here the leaf emitters know nothing about querying, and the computation knows
|
|
159
|
+
nothing about REST. Dispose `users`, `search`, and `searchText` at the lifetime
|
|
160
|
+
boundary that created them.
|
|
161
|
+
|
|
59
162
|
## Live queries
|
|
60
163
|
|
|
61
164
|
```js
|
|
@@ -98,14 +201,47 @@ process-local IDs, timestamps, weak owner references where supported, and
|
|
|
98
201
|
explicit parent/child causality. The bus retains neither event history nor
|
|
99
202
|
owners; its unsubscribe function is idempotent.
|
|
100
203
|
|
|
101
|
-
|
|
204
|
+
Tracing follows the same design as data flow: mutation, derivation, query
|
|
205
|
+
start, and query completion can retain explicit parent/child causality without
|
|
206
|
+
turning diagnostics into a second execution system. Applications decide
|
|
207
|
+
whether to retain, render, or export observed events.
|
|
208
|
+
|
|
209
|
+
## Async commands
|
|
102
210
|
|
|
103
|
-
|
|
211
|
+
`AsyncCommand` is exported from Glue's package root. It is an abortable
|
|
104
212
|
mutation lifecycle with explicit `ignore`, `replace`, and `reject` concurrency
|
|
105
213
|
policies. It exposes the last result/error through the standard emitter
|
|
106
214
|
snapshot and a read-only `isRunning` view. It deliberately does not own batch
|
|
107
215
|
progress, retries, notifications, or UI behavior. See
|
|
108
|
-
|
|
216
|
+
the API reference below for the command contract.
|
|
217
|
+
|
|
218
|
+
## Integration with Fray and other consumers
|
|
219
|
+
|
|
220
|
+
Glue's UI seam is intentionally just the readable/writable emitter protocol.
|
|
221
|
+
A typical Fray path is:
|
|
222
|
+
|
|
223
|
+
```text
|
|
224
|
+
browser event
|
|
225
|
+
└──► Fray control writes an Emitter
|
|
226
|
+
└──► DerivedEmitter computes shared/domain state
|
|
227
|
+
├──► Fray renders a local view
|
|
228
|
+
└──► LiveQuery refreshes through a handler
|
|
229
|
+
└──► Fray renders query snapshot state
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Leaf controls should normally receive ordinary writable emitters, not
|
|
233
|
+
`QueryArg` objects. The component or service that understands an aggregate
|
|
234
|
+
interaction owns its derived value. The data-aware consumer owns the query
|
|
235
|
+
bridge and watches the result it actually renders. This keeps UI components
|
|
236
|
+
reusable for local state, static data, remote data, and tests.
|
|
237
|
+
|
|
238
|
+
Fray's theme and color selection is not a Glue feature. An application may
|
|
239
|
+
store selected theme/color identifiers in ordinary Glue emitters when it wants
|
|
240
|
+
observable or persistent selection state, but Fray and the browser remain
|
|
241
|
+
responsible for CSS assets, stylesheet links, and rendering.
|
|
242
|
+
|
|
243
|
+
Nothing in this contract is Fray-specific: another UI framework, a CLI, a Node
|
|
244
|
+
service, or a test can consume the same emitters and live queries.
|
|
109
245
|
|
|
110
246
|
## Local checks
|
|
111
247
|
|
|
@@ -120,7 +256,7 @@ Glue intentionally does not own a DOM renderer, component lifecycle,
|
|
|
120
256
|
application-specific query encoding, persistent event history, CommonJS build,
|
|
121
257
|
or framework adapter. Fray consumes Glue as a peer; browser UI belongs there.
|
|
122
258
|
|
|
123
|
-
See the [workspace overview](../../README.md), [
|
|
259
|
+
See the [workspace overview](../../README.md), [API
|
|
124
260
|
surface](../../docs/API_SURFACE.md), [changelog](../../CHANGELOG.md),
|
|
125
261
|
[contribution guide](../../CONTRIBUTING.md), and [security
|
|
126
262
|
policy](../../SECURITY.md).
|
|
@@ -19,7 +19,7 @@ export interface AsyncCommandOptions<TArguments, TResult, TError = unknown> {
|
|
|
19
19
|
export declare class AsyncCommandConcurrencyError extends Error {
|
|
20
20
|
constructor();
|
|
21
21
|
}
|
|
22
|
-
/**
|
|
22
|
+
/** Abortable mutation state with an explicit concurrency policy. */
|
|
23
23
|
export declare class AsyncCommand<TArguments, TResult, TError = unknown> extends BaseEmitter<TResult | undefined, TError> {
|
|
24
24
|
readonly execute: AsyncCommandExecutor<TArguments, TResult>;
|
|
25
25
|
readonly concurrency: AsyncCommandConcurrency;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"asyncCommand.d.ts","sourceRoot":"","sources":["../../src/commands/asyncCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,6BAA6B,CAAA;AACvD,OAAO,EAAC,WAAW,EAAC,MAAM,4BAA4B,CAAA;AACtD,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,4BAA4B,CAAA;AAG/D,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,kCAAkC,CAAA;AAErE,MAAM,MAAM,uBAAuB,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAA;AAErE,MAAM,WAAW,mBAAmB;IAChC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAA;IAChC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,GAAG,IAAI,CAAA;CAC9C;AAED,MAAM,MAAM,oBAAoB,CAAC,UAAU,EAAE,OAAO,IAAI,CACpD,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,mBAAmB,KAC3B,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,CAAA;AAEnC,MAAM,WAAW,mBAAmB,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO;IACtE,OAAO,EAAE,oBAAoB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;IAClD,WAAW,CAAC,EAAE,uBAAuB,CAAA;IACrC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,CAAA;IACrC,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,OAAO,CAAA;CAClB;AAWD,qBAAa,4BAA6B,SAAQ,KAAK;;CAKtD;AAED,
|
|
1
|
+
{"version":3,"file":"asyncCommand.d.ts","sourceRoot":"","sources":["../../src/commands/asyncCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,6BAA6B,CAAA;AACvD,OAAO,EAAC,WAAW,EAAC,MAAM,4BAA4B,CAAA;AACtD,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,4BAA4B,CAAA;AAG/D,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,kCAAkC,CAAA;AAErE,MAAM,MAAM,uBAAuB,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAA;AAErE,MAAM,WAAW,mBAAmB;IAChC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAA;IAChC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,GAAG,IAAI,CAAA;CAC9C;AAED,MAAM,MAAM,oBAAoB,CAAC,UAAU,EAAE,OAAO,IAAI,CACpD,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,mBAAmB,KAC3B,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,CAAA;AAEnC,MAAM,WAAW,mBAAmB,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO;IACtE,OAAO,EAAE,oBAAoB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;IAClD,WAAW,CAAC,EAAE,uBAAuB,CAAA;IACrC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,CAAA;IACrC,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,OAAO,CAAA;CAClB;AAWD,qBAAa,4BAA6B,SAAQ,KAAK;;CAKtD;AAED,oEAAoE;AACpE,qBAAa,YAAY,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAC3D,SAAQ,WAAW,CAAC,OAAO,GAAG,SAAS,EAAE,MAAM,CAAC;IAChD,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;IAC3D,QAAQ,CAAC,WAAW,EAAE,uBAAuB,CAAA;IAC7C,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;IACnD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA4B;IACrD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAyB;IACxD,OAAO,CAAC,SAAS,CAAI;IACrB,OAAO,CAAC,eAAe,CAAmC;IAC1D,OAAO,CAAC,mBAAmB,CAAqB;IAChD,OAAO,CAAC,kBAAkB,CAAQ;IAClC,2EAA2E;IAC3E,cAAc,EAAE,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,GAAG,IAAI,CAAO;gBAE9C,OAAO,EAAE,mBAAmB,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,CAAC;IAgCrE,GAAG,CACC,UAAU,EAAE,UAAU,EACtB,YAAY,GAAE,WAAW,CAAC,OAAO,CAAC,GAAG,OAAuB,GAC7D,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC;IAiE/B,KAAK,CAAC,YAAY,GAAE,WAAW,CAAC,OAAO,CAAC,GAAG,OAA2B,GAAG,OAAO;IAmBhF,KAAK,CAAC,YAAY,GAAE,WAAW,CAAC,OAAO,CAAC,GAAG,OAAyB,GAAG,IAAI;IAelE,OAAO,IAAI,IAAI;IAWxB,OAAO,CAAC,gBAAgB;IAOxB,OAAO,CAAC,eAAe;CAO1B"}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export type { BubbleGraph, EventListener } from './debugging/eventBus.js';
|
|
|
5
5
|
export { BaseEmitter, DerivedEmitter } from './emitters/baseEmitter.js';
|
|
6
6
|
export type { DerivedEmitterOptions, DerivedErrorEntry, DerivedErrors, EmitterNotification, EmitterOptions, EmitterValue, EmitterValues, MapOptions, ReadableEmitter, SnapshotUpdate, SubscribeOptions, } from './emitters/baseEmitter.js';
|
|
7
7
|
export { Emitter } from './emitters/emitter.js';
|
|
8
|
+
export { AsyncCommand, AsyncCommandConcurrencyError } from './commands/asyncCommand.js';
|
|
9
|
+
export type { AsyncCommandConcurrency, AsyncCommandContext, AsyncCommandExecutor, AsyncCommandOptions, } from './commands/asyncCommand.js';
|
|
8
10
|
export { LiveQuery } from './emitters/liveQuery.js';
|
|
9
11
|
export type { LiveQueryOptions, QueryArgumentEmitters, QueryArgumentValues, } from './emitters/liveQuery.js';
|
|
10
12
|
export { combineFetchStates, FetchState, FetchStateValues } from './enums/fetchState.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,4BAA4B,CAAA;AACtD,YAAY,EAAC,YAAY,EAAC,MAAM,4BAA4B,CAAA;AAC5D,OAAO,EAAC,QAAQ,EAAC,MAAM,yBAAyB,CAAA;AAChD,YAAY,EAAC,WAAW,EAAE,aAAa,EAAC,MAAM,yBAAyB,CAAA;AAEvE,OAAO,EAAC,WAAW,EAAE,cAAc,EAAC,MAAM,2BAA2B,CAAA;AACrE,YAAY,EACR,qBAAqB,EACrB,iBAAiB,EACjB,aAAa,EACb,mBAAmB,EACnB,cAAc,EACd,YAAY,EACZ,aAAa,EACb,UAAU,EACV,eAAe,EACf,cAAc,EACd,gBAAgB,GACnB,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAAC,OAAO,EAAC,MAAM,uBAAuB,CAAA;AAC7C,OAAO,EAAC,SAAS,EAAC,MAAM,yBAAyB,CAAA;AACjD,YAAY,EACR,gBAAgB,EAChB,qBAAqB,EACrB,mBAAmB,GACtB,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EAAC,kBAAkB,EAAE,UAAU,EAAE,gBAAgB,EAAC,MAAM,uBAAuB,CAAA;AACtF,YAAY,EAAC,eAAe,EAAC,MAAM,uBAAuB,CAAA;AAE1D,OAAO,EAAC,QAAQ,EAAC,MAAM,6BAA6B,CAAA;AACpD,OAAO,EAAC,YAAY,EAAC,MAAM,iCAAiC,CAAA;AAC5D,YAAY,EACR,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,WAAW,GACd,MAAM,iCAAiC,CAAA;AACxC,OAAO,EAAC,gBAAgB,EAAC,MAAM,qCAAqC,CAAA;AACpE,YAAY,EACR,SAAS,EACT,gBAAgB,EAChB,eAAe,EACf,uBAAuB,EACvB,gBAAgB,EAChB,OAAO,GACV,MAAM,qCAAqC,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,4BAA4B,CAAA;AACtD,YAAY,EAAC,YAAY,EAAC,MAAM,4BAA4B,CAAA;AAC5D,OAAO,EAAC,QAAQ,EAAC,MAAM,yBAAyB,CAAA;AAChD,YAAY,EAAC,WAAW,EAAE,aAAa,EAAC,MAAM,yBAAyB,CAAA;AAEvE,OAAO,EAAC,WAAW,EAAE,cAAc,EAAC,MAAM,2BAA2B,CAAA;AACrE,YAAY,EACR,qBAAqB,EACrB,iBAAiB,EACjB,aAAa,EACb,mBAAmB,EACnB,cAAc,EACd,YAAY,EACZ,aAAa,EACb,UAAU,EACV,eAAe,EACf,cAAc,EACd,gBAAgB,GACnB,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAAC,OAAO,EAAC,MAAM,uBAAuB,CAAA;AAC7C,OAAO,EAAC,YAAY,EAAE,4BAA4B,EAAC,MAAM,4BAA4B,CAAA;AACrF,YAAY,EACR,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,GACtB,MAAM,4BAA4B,CAAA;AACnC,OAAO,EAAC,SAAS,EAAC,MAAM,yBAAyB,CAAA;AACjD,YAAY,EACR,gBAAgB,EAChB,qBAAqB,EACrB,mBAAmB,GACtB,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EAAC,kBAAkB,EAAE,UAAU,EAAE,gBAAgB,EAAC,MAAM,uBAAuB,CAAA;AACtF,YAAY,EAAC,eAAe,EAAC,MAAM,uBAAuB,CAAA;AAE1D,OAAO,EAAC,QAAQ,EAAC,MAAM,6BAA6B,CAAA;AACpD,OAAO,EAAC,YAAY,EAAC,MAAM,iCAAiC,CAAA;AAC5D,YAAY,EACR,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,WAAW,GACd,MAAM,iCAAiC,CAAA;AACxC,OAAO,EAAC,gBAAgB,EAAC,MAAM,qCAAqC,CAAA;AACpE,YAAY,EACR,SAAS,EACT,gBAAgB,EAChB,eAAe,EACf,uBAAuB,EACvB,gBAAgB,EAChB,OAAO,GACV,MAAM,qCAAqC,CAAA"}
|