@bodil/signal 0.3.5 → 0.4.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/dist/index.js CHANGED
@@ -3,201 +3,5 @@
3
3
  * Proposal](https://github.com/tc39/proposal-signals).
4
4
  * @module
5
5
  */
6
- import { AbortablePromise } from "@bodil/core/async";
7
- import { toDisposable } from "@bodil/core/disposable";
8
- import { Err, Ok } from "@bodil/opt";
9
- import { Signal } from "signal-polyfill";
10
- import { SignalArray } from "./array";
11
- /**
12
- * A writable state signal.
13
- */
14
- class StateSignal extends Signal.State {
15
- get value() {
16
- return this.get();
17
- }
18
- set value(value) {
19
- this.set(value);
20
- }
21
- /**
22
- * Update the current value of this signal using a function.
23
- */
24
- update(fn) {
25
- this.set(Signal.subtle.untrack(() => fn(this.get())));
26
- }
27
- /**
28
- * Get a read only version of this signal.
29
- */
30
- readOnly() {
31
- return SignalGlobal.computed(() => this.get());
32
- }
33
- map(fn) {
34
- return SignalGlobal.computed(() => fn(this.get()));
35
- }
36
- on(callback) {
37
- return SignalGlobal.subscribe(this, callback);
38
- }
39
- static is(v) {
40
- return v instanceof StateSignal;
41
- }
42
- }
43
- /**
44
- * A read only signal computed from the values of other signals.
45
- */
46
- class ComputedSignal extends Signal.Computed {
47
- get value() {
48
- return this.get();
49
- }
50
- map(fn) {
51
- return SignalGlobal.computed(() => fn(this.get()));
52
- }
53
- on(callback) {
54
- return SignalGlobal.subscribe(this, callback);
55
- }
56
- static is(v) {
57
- return v instanceof ComputedSignal;
58
- }
59
- }
60
- let effectNeedsEnqueue = true;
61
- const effectWatcher = new Signal.subtle.Watcher(() => {
62
- if (effectNeedsEnqueue) {
63
- effectNeedsEnqueue = false;
64
- queueMicrotask(effectProcess);
65
- }
66
- });
67
- function effectProcess() {
68
- effectNeedsEnqueue = true;
69
- for (const sig of effectWatcher.getPending()) {
70
- sig.get();
71
- }
72
- effectWatcher.watch();
73
- }
74
- const SignalGlobal = Object.assign(
75
- /**
76
- * Construct a new {@link Signal.State} signal containing the provided value.
77
- *
78
- * @example
79
- * const sig = Signal("Hello Joe!");
80
- */
81
- function (value, options) {
82
- return new SignalGlobal.State(value, options);
83
- }, {
84
- /**
85
- * Test whether the given value is a signal.
86
- */
87
- is(v) {
88
- return SignalGlobal.State.is(v) || SignalGlobal.Computed.is(v);
89
- },
90
- /**
91
- * Construct a new {@link Signal.Computed} signal using the provided
92
- * computation function.
93
- *
94
- * @example
95
- * const sig1 = Signal(2);
96
- * const sig2 = Signal(3);
97
- * const sum = Signal.computed(() => sig1.get() + sig2.get());
98
- * assert(sum.get() === 5);
99
- */
100
- computed(fn, options) {
101
- return new SignalGlobal.Computed(fn, options);
102
- },
103
- /**
104
- * Suscribe to a signal.
105
- *
106
- * The provided callback will be called every time the value of the
107
- * signal changes.
108
- */
109
- subscribe(signal, callback) {
110
- return SignalGlobal.effect(() => callback(signal.value));
111
- },
112
- /**
113
- * Create an effect responding to signal changes.
114
- *
115
- * The provided function will be called immediately, and again every
116
- * time a signal that was read by the function changes.
117
- *
118
- * @example
119
- * const sig = Signal("Hello Joe!");
120
- * effect(() => console.log("Signal value is:", sig.get()));
121
- * // prints "Signal value is: Hello Joe!"
122
- * sig.set("Hello Mike!");
123
- * // prints "Signal value is: Hello Mike!"
124
- */
125
- effect(fn) {
126
- let cleanup;
127
- const computed = new SignalGlobal.Computed(() => {
128
- if (cleanup !== undefined) {
129
- cleanup[Symbol.dispose]();
130
- }
131
- const result = fn();
132
- cleanup = result !== undefined ? toDisposable(result) : undefined;
133
- });
134
- effectWatcher.watch(computed);
135
- computed.get();
136
- return toDisposable(() => {
137
- effectWatcher.unwatch(computed);
138
- if (cleanup !== undefined) {
139
- cleanup[Symbol.dispose]();
140
- }
141
- });
142
- },
143
- /**
144
- * Construct a new {@link Signal.Computed} signal using an async
145
- * computation function.
146
- *
147
- * This returns a promise which will resolve to a
148
- * {@link Signal.Computed} signal once the promise returned by the
149
- * computation function resolves, and will update itself whenever
150
- * subsequent calls to the computation function resolve.
151
- *
152
- * The function is provided with an {@link AbortSignal} which any async
153
- * jobs started from it should abide by. If a signal dependency changes
154
- * while the job is running, the {@link AbortSignal} will be triggered
155
- * and the job restarted.
156
- */
157
- asyncComputed(fn, options) {
158
- const result = Promise.withResolvers();
159
- const stream = SignalGlobal.computed(() => AbortablePromise.run((resolve, reject, abort) => {
160
- try {
161
- fn(abort).then(resolve, reject);
162
- }
163
- catch (e) {
164
- reject(e);
165
- }
166
- }));
167
- const sig = SignalGlobal(Err(new Error()));
168
- let job = undefined;
169
- let resolved = false;
170
- const resolve = () => {
171
- if (!resolved) {
172
- resolved = true;
173
- result.resolve(SignalGlobal.computed(() => sig.get().unwrapExact(), options));
174
- }
175
- };
176
- SignalGlobal.effect(() => {
177
- if (job !== undefined) {
178
- job.abort();
179
- }
180
- job = stream.get();
181
- job.then((next) => {
182
- sig.set(Ok(next));
183
- resolve();
184
- }, (error) => {
185
- if (job?.signal.aborted === true) {
186
- return;
187
- }
188
- sig.set(Err(error));
189
- resolve();
190
- });
191
- });
192
- return result.promise;
193
- },
194
- array(values) {
195
- return SignalArray.from(values);
196
- },
197
- State: StateSignal,
198
- Computed: ComputedSignal,
199
- Array: SignalArray,
200
- subtle: Signal.subtle,
201
- });
202
- export { SignalGlobal as Signal };
6
+ export * as Signal from "./signal";
203
7
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC"}
package/dist/map.d.ts ADDED
@@ -0,0 +1,130 @@
1
+ import type { Equals } from "@bodil/core/types";
2
+ import { type Option } from "@bodil/opt";
3
+ import * as Signal from "./signal";
4
+ declare const instance: unique symbol;
5
+ type InstanceProps<K, V> = {
6
+ map: Map<K, V>;
7
+ signal: Signal.State<null>;
8
+ signals: Map<K, WeakRef<Signal.State<Option<V>>>>;
9
+ readonlySignals: WeakMap<Signal.State<Option<V>>, Signal.Computed<Option<V>>>;
10
+ registry: FinalizationRegistry<K>;
11
+ };
12
+ /**
13
+ * A read-only view of a {@link Signal.Map}.
14
+ *
15
+ * This acts just like the {@link Signal.Map} it was created from, mirroring
16
+ * the current contents of the source map, but without the ability to modify
17
+ * it.
18
+ */
19
+ export declare class ReadonlySignalMap<K, V> implements Iterable<[K, V]>, Equals {
20
+ /** @ignore */
21
+ protected readonly [instance]: InstanceProps<K, V>;
22
+ /** @ignore */
23
+ protected constructor(instanceProps: InstanceProps<K, V>);
24
+ /**
25
+ * Test whether a value is a `Signal.ReadonlyMap`.
26
+ */
27
+ static is(value: unknown): value is ReadonlySignalMap<unknown, unknown>;
28
+ /**
29
+ * Obtain a {@link Signal.Computed} representing the current value of the
30
+ * given key in the map. The signal will update when the value changes, and
31
+ * will not respond to changes to any other elements of the map.
32
+ */
33
+ signal(key: K): Signal.Computed<Option<V>>;
34
+ /**
35
+ * Get the value associated with the given key in the map.
36
+ */
37
+ get(key: K): Option<V>;
38
+ /**
39
+ * Test whether the given key is defined in the map.
40
+ */
41
+ has(key: K): boolean;
42
+ /**
43
+ * Get the size of the map.
44
+ */
45
+ size(): number;
46
+ /**
47
+ * Test whether the map is empty.
48
+ */
49
+ isEmpty(): boolean;
50
+ /**
51
+ * Iterate over the key/value pairs the map contains.
52
+ */
53
+ entries(): MapIterator<[K, V]>;
54
+ /**
55
+ * Iterate over the keys the map contains.
56
+ */
57
+ keys(): MapIterator<K>;
58
+ /**
59
+ * Iterate over the values associated with every key in the map.
60
+ */
61
+ values(): MapIterator<V>;
62
+ /**
63
+ * Test whether a given value is a `Signal.Map` with identical contents to
64
+ * this map.
65
+ */
66
+ equals(other: unknown): other is ReadonlySignalMap<K, V>;
67
+ /**
68
+ * Iterate over the key/value pairs the map contains.
69
+ */
70
+ [Symbol.iterator](): MapIterator<[K, V]>;
71
+ }
72
+ /**
73
+ * A map which behaves like a signal.
74
+ *
75
+ * Any read operation on the map, like {@link Signal.Map.get},
76
+ * {@link Signal.Map.size}, or iteration, acts like a
77
+ * {@link Signal.State.get}, registering the map as a dependency in any
78
+ * computed signals or effects it's used in. Correspondingly, any write
79
+ * operation to the map will cause all of these dependencies to update as
80
+ * with a {@link Signal.State.set}.
81
+ *
82
+ * Note that there's no granularity to this access by default: if you read only
83
+ * a single key from the map inside a computed signal, *any* write to the map,
84
+ * even to a different key, causes the signal to recompute. If you want
85
+ * granularity (and you normally do), use {@link Signal.Map.signal} instead of
86
+ * {@link Signal.Map.get}.
87
+ */
88
+ export declare class SignalMap<K, V> extends ReadonlySignalMap<K, V> {
89
+ /**
90
+ * Test whether a value is a `Signal.Map`.
91
+ */
92
+ static is(value: unknown): value is SignalMap<unknown, unknown>;
93
+ /**
94
+ * Construct a new map, optionally populating it with the provided key/value
95
+ * pairs.
96
+ */
97
+ constructor(entries?: Iterable<readonly [K, V]>);
98
+ /**
99
+ * Discard every key/value pair defined in the map, leaving an empty map.
100
+ */
101
+ clear(): void;
102
+ /**
103
+ * Remove the given key from the map, returning its associated value. If the
104
+ * key isn't defined in the map, return {@link None}.
105
+ */
106
+ remove(key: K): Option<V>;
107
+ /**
108
+ * Add the given key/value pair to the map, overwriting any previous
109
+ * definitions of the same key.
110
+ */
111
+ set(key: K, value: V): this;
112
+ /**
113
+ * Get the value associated with the given key, or, if the key doesn't
114
+ * already exist, call the provided function to create a new value and
115
+ * insert it into the map under the given key.
116
+ */
117
+ getOrSet(key: K, defaultFn: (this: SignalMap<K, V>) => V): V;
118
+ /**
119
+ * Get a signal reflecting the value at the given key, as in
120
+ * {@link Signal.Map.signal}, except that if the key isn't defined,
121
+ * initialise it with the value produced by calling `defaultFn` first, as in
122
+ * {@link Signal.Map.getOrSet}.
123
+ */
124
+ signalOrSet(key: K, defaultFn: (this: SignalMap<K, V>) => V): Signal.Computed<Option<V>>;
125
+ /**
126
+ * Return a read-only view of the map.
127
+ */
128
+ readOnly(): ReadonlySignalMap<K, V>;
129
+ }
130
+ export {};
package/dist/map.js ADDED
@@ -0,0 +1,227 @@
1
+ import { present } from "@bodil/core/assert";
2
+ import { None, Some } from "@bodil/opt";
3
+ import * as Signal from "./signal";
4
+ const instance = Symbol("Signal.Map");
5
+ /**
6
+ * A read-only view of a {@link Signal.Map}.
7
+ *
8
+ * This acts just like the {@link Signal.Map} it was created from, mirroring
9
+ * the current contents of the source map, but without the ability to modify
10
+ * it.
11
+ */
12
+ export class ReadonlySignalMap {
13
+ /** @ignore */
14
+ constructor(instanceProps) {
15
+ this[instance] = instanceProps;
16
+ }
17
+ /**
18
+ * Test whether a value is a `Signal.ReadonlyMap`.
19
+ */
20
+ static is(value) {
21
+ return value instanceof ReadonlySignalMap;
22
+ }
23
+ /**
24
+ * Obtain a {@link Signal.Computed} representing the current value of the
25
+ * given key in the map. The signal will update when the value changes, and
26
+ * will not respond to changes to any other elements of the map.
27
+ */
28
+ signal(key) {
29
+ const self = this[instance];
30
+ const active = self.signals.get(key)?.deref();
31
+ if (active !== undefined) {
32
+ return present(self.readonlySignals.get(active), "Signal.Map.signal(): unexpected absence of readonly signal for a signal which still exists");
33
+ }
34
+ const sig = new Signal.State(self.map.has(key) ? Some(self.map.get(key)) : None);
35
+ self.registry.register(sig, key);
36
+ self.signals.set(key, new WeakRef(sig));
37
+ const roSig = sig.readOnly();
38
+ self.readonlySignals.set(sig, roSig);
39
+ return roSig;
40
+ }
41
+ /**
42
+ * Get the value associated with the given key in the map.
43
+ */
44
+ get(key) {
45
+ return this.has(key) ? Some(this[instance].map.get(key)) : None;
46
+ }
47
+ /**
48
+ * Test whether the given key is defined in the map.
49
+ */
50
+ has(key) {
51
+ const self = this[instance];
52
+ self.signal.get();
53
+ return self.map.has(key);
54
+ }
55
+ /**
56
+ * Get the size of the map.
57
+ */
58
+ size() {
59
+ const self = this[instance];
60
+ self.signal.get();
61
+ return self.map.size;
62
+ }
63
+ /**
64
+ * Test whether the map is empty.
65
+ */
66
+ isEmpty() {
67
+ return this.size() === 0;
68
+ }
69
+ /**
70
+ * Iterate over the key/value pairs the map contains.
71
+ */
72
+ entries() {
73
+ const self = this[instance];
74
+ self.signal.get();
75
+ return self.map.entries();
76
+ }
77
+ /**
78
+ * Iterate over the keys the map contains.
79
+ */
80
+ keys() {
81
+ const self = this[instance];
82
+ self.signal.get();
83
+ return self.map.keys();
84
+ }
85
+ /**
86
+ * Iterate over the values associated with every key in the map.
87
+ */
88
+ values() {
89
+ const self = this[instance];
90
+ self.signal.get();
91
+ return self.map.values();
92
+ }
93
+ /**
94
+ * Test whether a given value is a `Signal.Map` with identical contents to
95
+ * this map.
96
+ */
97
+ equals(other) {
98
+ if (!ReadonlySignalMap.is(other) || this.size() !== other.size()) {
99
+ return false;
100
+ }
101
+ for (const [key, value] of this) {
102
+ const otherValue = other.get(key);
103
+ if (otherValue.isNone() || !Object.is(value, otherValue.value)) {
104
+ return false;
105
+ }
106
+ }
107
+ return true;
108
+ }
109
+ /**
110
+ * Iterate over the key/value pairs the map contains.
111
+ */
112
+ [Symbol.iterator]() {
113
+ const self = this[instance];
114
+ self.signal.get();
115
+ return self.map[Symbol.iterator]();
116
+ }
117
+ }
118
+ /**
119
+ * A map which behaves like a signal.
120
+ *
121
+ * Any read operation on the map, like {@link Signal.Map.get},
122
+ * {@link Signal.Map.size}, or iteration, acts like a
123
+ * {@link Signal.State.get}, registering the map as a dependency in any
124
+ * computed signals or effects it's used in. Correspondingly, any write
125
+ * operation to the map will cause all of these dependencies to update as
126
+ * with a {@link Signal.State.set}.
127
+ *
128
+ * Note that there's no granularity to this access by default: if you read only
129
+ * a single key from the map inside a computed signal, *any* write to the map,
130
+ * even to a different key, causes the signal to recompute. If you want
131
+ * granularity (and you normally do), use {@link Signal.Map.signal} instead of
132
+ * {@link Signal.Map.get}.
133
+ */
134
+ export class SignalMap extends ReadonlySignalMap {
135
+ /**
136
+ * Test whether a value is a `Signal.Map`.
137
+ */
138
+ static is(value) {
139
+ return value instanceof SignalMap;
140
+ }
141
+ /**
142
+ * Construct a new map, optionally populating it with the provided key/value
143
+ * pairs.
144
+ */
145
+ constructor(entries = []) {
146
+ const signals = new Map();
147
+ super({
148
+ map: new Map(entries),
149
+ signal: new Signal.State(null, { equals: () => false }),
150
+ signals,
151
+ readonlySignals: new WeakMap(),
152
+ registry: new FinalizationRegistry((key) => signals.delete(key)),
153
+ });
154
+ }
155
+ /**
156
+ * Discard every key/value pair defined in the map, leaving an empty map.
157
+ */
158
+ clear() {
159
+ const self = this[instance];
160
+ self.map.clear();
161
+ self.signals.forEach((sig) => sig.deref()?.set(None));
162
+ self.signal.set(null);
163
+ }
164
+ /**
165
+ * Remove the given key from the map, returning its associated value. If the
166
+ * key isn't defined in the map, return {@link None}.
167
+ */
168
+ remove(key) {
169
+ const self = this[instance];
170
+ if (!self.map.has(key)) {
171
+ return None;
172
+ }
173
+ const result = Some(self.map.get(key));
174
+ self.map.delete(key);
175
+ self.signals.get(key)?.deref()?.set(None);
176
+ self.signal.set(null);
177
+ return result;
178
+ }
179
+ /**
180
+ * Add the given key/value pair to the map, overwriting any previous
181
+ * definitions of the same key.
182
+ */
183
+ set(key, value) {
184
+ const self = this[instance];
185
+ self.map.set(key, value);
186
+ self.signals.get(key)?.deref()?.set(Some(value));
187
+ self.signal.set(null);
188
+ return this;
189
+ }
190
+ /**
191
+ * Get the value associated with the given key, or, if the key doesn't
192
+ * already exist, call the provided function to create a new value and
193
+ * insert it into the map under the given key.
194
+ */
195
+ getOrSet(key, defaultFn) {
196
+ const self = this[instance];
197
+ self.signal.get();
198
+ if (self.map.has(key)) {
199
+ return self.map.get(key);
200
+ }
201
+ const value = defaultFn.call(this);
202
+ self.map.set(key, value);
203
+ self.signal.set(null);
204
+ return value;
205
+ }
206
+ /**
207
+ * Get a signal reflecting the value at the given key, as in
208
+ * {@link Signal.Map.signal}, except that if the key isn't defined,
209
+ * initialise it with the value produced by calling `defaultFn` first, as in
210
+ * {@link Signal.Map.getOrSet}.
211
+ */
212
+ signalOrSet(key, defaultFn) {
213
+ const self = this[instance];
214
+ if (!self.map.has(key)) {
215
+ self.map.set(key, defaultFn.call(this));
216
+ self.signal.set(null);
217
+ }
218
+ return this.signal(key);
219
+ }
220
+ /**
221
+ * Return a read-only view of the map.
222
+ */
223
+ readOnly() {
224
+ return new ReadonlySignalMap(this[instance]);
225
+ }
226
+ }
227
+ //# sourceMappingURL=map.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"map.js","sourceRoot":"","sources":["../src/map.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,52 @@
1
+ import { None, Some } from "@bodil/opt";
2
+ import { expect, test } from "vitest";
3
+ import { Signal } from ".";
4
+ test("SignalMap", () => {
5
+ const map = Signal.map([
6
+ ["Joe", "Armstrong"],
7
+ ["Mike", "Williams"],
8
+ ["Robert", "Virding"],
9
+ ]);
10
+ expect(map.entries().toArray()).toEqual([
11
+ ["Joe", "Armstrong"],
12
+ ["Mike", "Williams"],
13
+ ["Robert", "Virding"],
14
+ ]);
15
+ const mike = map.signal("Mike");
16
+ expect(mike.get()).toEqual(Some("Williams"));
17
+ const bjarne = map.signal("Bjarne");
18
+ expect(bjarne.get()).toEqual(None);
19
+ const size = Signal.computed(() => map.size());
20
+ expect(map.size()).toBe(3);
21
+ expect(size.get()).toBe(3);
22
+ expect(mike.get()).toEqual(Some("Williams"));
23
+ expect(bjarne.get()).toEqual(None);
24
+ map.set("Bjarne", "Däcker");
25
+ expect(map.size()).toBe(4);
26
+ expect(size.get()).toBe(4);
27
+ expect(mike.get()).toEqual(Some("Williams"));
28
+ expect(bjarne.get()).toEqual(Some("Däcker"));
29
+ expect(map.entries().toArray()).toEqual([
30
+ ["Joe", "Armstrong"],
31
+ ["Mike", "Williams"],
32
+ ["Robert", "Virding"],
33
+ ["Bjarne", "Däcker"],
34
+ ]);
35
+ expect(map.remove("Mike")).toEqual(Some("Williams"));
36
+ expect(map.size()).toBe(3);
37
+ expect(size.get()).toBe(3);
38
+ expect(mike.get()).toEqual(None);
39
+ expect(bjarne.get()).toEqual(Some("Däcker"));
40
+ expect(map.entries().toArray()).toEqual([
41
+ ["Joe", "Armstrong"],
42
+ ["Robert", "Virding"],
43
+ ["Bjarne", "Däcker"],
44
+ ]);
45
+ map.clear();
46
+ expect(map.size()).toBe(0);
47
+ expect(size.get()).toBe(0);
48
+ expect(mike.get()).toEqual(None);
49
+ expect(bjarne.get()).toEqual(None);
50
+ expect(map.entries().toArray()).toEqual([]);
51
+ });
52
+ //# sourceMappingURL=map.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"map.test.js","sourceRoot":"","sources":["../src/map.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC;AAE3B,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE;IACnB,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAiB;QACnC,CAAC,KAAK,EAAE,WAAW,CAAC;QACpB,CAAC,MAAM,EAAE,UAAU,CAAC;QACpB,CAAC,QAAQ,EAAE,SAAS,CAAC;KACxB,CAAC,CAAC;IAEH,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC;QACpC,CAAC,KAAK,EAAE,WAAW,CAAC;QACpB,CAAC,MAAM,EAAE,UAAU,CAAC;QACpB,CAAC,QAAQ,EAAE,SAAS,CAAC;KACxB,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAChC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;IAE7C,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACpC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnC,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/C,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;IAC7C,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnC,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC5B,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;IAC7C,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IAE7C,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC;QACpC,CAAC,KAAK,EAAE,WAAW,CAAC;QACpB,CAAC,MAAM,EAAE,UAAU,CAAC;QACpB,CAAC,QAAQ,EAAE,SAAS,CAAC;QACrB,CAAC,QAAQ,EAAE,QAAQ,CAAC;KACvB,CAAC,CAAC;IAEH,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;IACrD,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IAE7C,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC;QACpC,CAAC,KAAK,EAAE,WAAW,CAAC;QACpB,CAAC,QAAQ,EAAE,SAAS,CAAC;QACrB,CAAC,QAAQ,EAAE,QAAQ,CAAC;KACvB,CAAC,CAAC;IAEH,GAAG,CAAC,KAAK,EAAE,CAAC;IACZ,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;AAChD,CAAC,CAAC,CAAC"}