@toyz/loom 0.3.0 → 0.5.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/app.d.ts +4 -1
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +9 -9
- package/dist/app.js.map +1 -1
- package/dist/decorators/create.d.ts +16 -25
- package/dist/decorators/create.d.ts.map +1 -1
- package/dist/decorators/create.js +25 -34
- package/dist/decorators/create.js.map +1 -1
- package/dist/decorators/events.d.ts +10 -8
- package/dist/decorators/events.d.ts.map +1 -1
- package/dist/decorators/events.js +53 -43
- package/dist/decorators/events.js.map +1 -1
- package/dist/decorators/symbols.d.ts +4 -0
- package/dist/decorators/symbols.d.ts.map +1 -1
- package/dist/decorators/symbols.js +4 -0
- package/dist/decorators/symbols.js.map +1 -1
- package/dist/di/decorators.d.ts +15 -15
- package/dist/di/decorators.d.ts.map +1 -1
- package/dist/di/decorators.js +23 -33
- package/dist/di/decorators.js.map +1 -1
- package/dist/di/watch.d.ts +1 -7
- package/dist/di/watch.d.ts.map +1 -1
- package/dist/di/watch.js +17 -20
- package/dist/di/watch.js.map +1 -1
- package/dist/element/decorators.d.ts +26 -10
- package/dist/element/decorators.d.ts.map +1 -1
- package/dist/element/decorators.js +75 -31
- package/dist/element/decorators.js.map +1 -1
- package/dist/element/element.d.ts.map +1 -1
- package/dist/element/element.js +15 -3
- package/dist/element/element.js.map +1 -1
- package/dist/element/form.d.ts +63 -0
- package/dist/element/form.d.ts.map +1 -0
- package/dist/element/form.js +167 -0
- package/dist/element/form.js.map +1 -0
- package/dist/element/icon.d.ts +3 -3
- package/dist/element/icon.d.ts.map +1 -1
- package/dist/element/icon.js +131 -74
- package/dist/element/icon.js.map +1 -1
- package/dist/element/index.d.ts +8 -1
- package/dist/element/index.d.ts.map +1 -1
- package/dist/element/index.js +9 -1
- package/dist/element/index.js.map +1 -1
- package/dist/element/lazy.d.ts +31 -0
- package/dist/element/lazy.d.ts.map +1 -0
- package/dist/element/lazy.js +71 -0
- package/dist/element/lazy.js.map +1 -0
- package/dist/element/lifecycle.d.ts +27 -29
- package/dist/element/lifecycle.d.ts.map +1 -1
- package/dist/element/lifecycle.js +60 -79
- package/dist/element/lifecycle.js.map +1 -1
- package/dist/element/slots.d.ts +23 -0
- package/dist/element/slots.d.ts.map +1 -0
- package/dist/element/slots.js +54 -0
- package/dist/element/slots.js.map +1 -0
- package/dist/element/timing.d.ts +10 -7
- package/dist/element/timing.d.ts.map +1 -1
- package/dist/element/timing.js +67 -52
- package/dist/element/timing.js.map +1 -1
- package/dist/element/transition.d.ts +32 -0
- package/dist/element/transition.d.ts.map +1 -0
- package/dist/element/transition.js +70 -0
- package/dist/element/transition.js.map +1 -0
- package/dist/element/virtual.js +235 -194
- package/dist/element/virtual.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/router/decorators.d.ts +9 -38
- package/dist/router/decorators.d.ts.map +1 -1
- package/dist/router/decorators.js +7 -52
- package/dist/router/decorators.js.map +1 -1
- package/dist/router/index.d.ts +1 -0
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/index.js +2 -0
- package/dist/router/index.js.map +1 -1
- package/dist/router/link.d.ts +4 -4
- package/dist/router/link.d.ts.map +1 -1
- package/dist/router/link.js +134 -72
- package/dist/router/link.js.map +1 -1
- package/dist/router/outlet.d.ts +2 -2
- package/dist/router/outlet.d.ts.map +1 -1
- package/dist/router/outlet.js +188 -138
- package/dist/router/outlet.js.map +1 -1
- package/dist/router/route-lifecycle.d.ts +28 -0
- package/dist/router/route-lifecycle.d.ts.map +1 -0
- package/dist/router/route-lifecycle.js +47 -0
- package/dist/router/route-lifecycle.js.map +1 -0
- package/dist/router/route.d.ts +1 -1
- package/dist/router/route.d.ts.map +1 -1
- package/dist/router/router.d.ts +5 -0
- package/dist/router/router.d.ts.map +1 -1
- package/dist/router/router.js +41 -4
- package/dist/router/router.js.map +1 -1
- package/dist/store/decorators.d.ts +39 -15
- package/dist/store/decorators.d.ts.map +1 -1
- package/dist/store/decorators.js +167 -79
- package/dist/store/decorators.js.map +1 -1
- package/dist/store/index.d.ts +1 -1
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +1 -1
- package/dist/store/index.js.map +1 -1
- package/dist/store/watch.d.ts +12 -11
- package/dist/store/watch.d.ts.map +1 -1
- package/dist/store/watch.js +20 -15
- package/dist/store/watch.js.map +1 -1
- package/dist/testing.d.ts +55 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +99 -0
- package/dist/testing.js.map +1 -0
- package/dist/transform/transform.d.ts +7 -3
- package/dist/transform/transform.d.ts.map +1 -1
- package/dist/transform/transform.js +17 -9
- package/dist/transform/transform.js.map +1 -1
- package/dist/transform/typed.d.ts +1 -1
- package/dist/transform/typed.d.ts.map +1 -1
- package/dist/transform/typed.js.map +1 -1
- package/package.json +5 -1
|
@@ -1,41 +1,55 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Loom — Store decorators
|
|
2
|
+
* Loom — Store decorators (TC39 Stage 3)
|
|
3
3
|
*
|
|
4
|
-
* @reactive — Internal reactive state backed by Reactive<T>
|
|
5
|
-
* @prop — External attribute with optional route binding
|
|
4
|
+
* @reactive — Internal reactive state backed by Reactive<T> (auto-accessor)
|
|
5
|
+
* @prop — External attribute with optional route binding (auto-accessor)
|
|
6
6
|
* @computed — Cached derived getter
|
|
7
|
+
* @store — Component-scoped reactive store (auto-accessor)
|
|
7
8
|
*/
|
|
8
|
-
|
|
9
|
+
import type { PersistOptions } from "./storage";
|
|
10
|
+
/**
|
|
11
|
+
* Staging area for @prop registrations.
|
|
12
|
+
* TC39 member decorators evaluate before class decorators,
|
|
13
|
+
* so @prop pushes here and @component flushes it.
|
|
14
|
+
*/
|
|
15
|
+
export declare const pendingProps: Array<{
|
|
16
|
+
key: string;
|
|
17
|
+
}>;
|
|
18
|
+
/** Sentinel for full route-param decompose: `@prop({params}) accessor p!: MyType` */
|
|
9
19
|
export declare const params: unique symbol;
|
|
10
|
-
/** Sentinel for full query-param decompose: `@prop({query}) q!: MyType` */
|
|
20
|
+
/** Sentinel for full query-param decompose: `@prop({query}) accessor q!: MyType` */
|
|
11
21
|
export declare const routeQuery: unique symbol;
|
|
12
22
|
/**
|
|
13
|
-
* Internal reactive state.
|
|
23
|
+
* Internal reactive state. Auto-accessor backed by Reactive<T>.
|
|
14
24
|
* Changes schedule batched `update()` via microtask.
|
|
15
25
|
*
|
|
16
26
|
* ```ts
|
|
17
|
-
* @reactive count = 0;
|
|
27
|
+
* @reactive accessor count = 0;
|
|
18
28
|
* ```
|
|
19
29
|
*/
|
|
20
|
-
export declare function reactive(target:
|
|
30
|
+
export declare function reactive<This extends object, V>(target: ClassAccessorDecoratorTarget<This, V>, context: ClassAccessorDecoratorContext<This, V>): ClassAccessorDecoratorResult<This, V>;
|
|
31
|
+
type PropRouteOpts = {
|
|
32
|
+
param?: string;
|
|
33
|
+
params?: symbol;
|
|
34
|
+
query?: string | symbol;
|
|
35
|
+
};
|
|
21
36
|
/**
|
|
22
37
|
* External attribute. Observed HTML attribute that auto-parses from strings.
|
|
23
38
|
* Uses @reactive under the hood.
|
|
24
39
|
*
|
|
25
40
|
* Bare decorator:
|
|
26
41
|
* ```ts
|
|
27
|
-
* @prop label = "Count";
|
|
42
|
+
* @prop accessor label = "Count";
|
|
28
43
|
* ```
|
|
29
44
|
*
|
|
30
45
|
* Route param injection:
|
|
31
46
|
* ```ts
|
|
32
|
-
* @prop({ param: "id" }) userId!: string;
|
|
33
|
-
* @prop({params}) params!: MyParamType;
|
|
34
|
-
* @prop({ query: "tab" }) activeTab!: string; // single query param
|
|
35
|
-
* @prop({query: routeQuery}) query!: MyQuery; // full query decompose
|
|
47
|
+
* @prop({ param: "id" }) accessor userId!: string;
|
|
48
|
+
* @prop({params}) accessor params!: MyParamType;
|
|
36
49
|
* ```
|
|
37
50
|
*/
|
|
38
|
-
export declare function prop(
|
|
51
|
+
export declare function prop<This extends object, V>(target: ClassAccessorDecoratorTarget<This, V>, context: ClassAccessorDecoratorContext<This, V>): ClassAccessorDecoratorResult<This, V>;
|
|
52
|
+
export declare function prop(opts: PropRouteOpts): <This extends object, V>(target: ClassAccessorDecoratorTarget<This, V>, context: ClassAccessorDecoratorContext<This, V>) => ClassAccessorDecoratorResult<This, V>;
|
|
39
53
|
/**
|
|
40
54
|
* Cached derived value. Re-computed only when reactive dependencies fire.
|
|
41
55
|
*
|
|
@@ -44,5 +58,15 @@ export declare function prop(targetOrOpts: any, key?: any): any;
|
|
|
44
58
|
* get displayName() { return `${this.firstName} ${this.lastName}`; }
|
|
45
59
|
* ```
|
|
46
60
|
*/
|
|
47
|
-
export declare function computed(target:
|
|
61
|
+
export declare function computed<This extends object, V>(target: (this: This) => V, context: ClassGetterDecoratorContext<This, V>): (this: This) => V;
|
|
62
|
+
/**
|
|
63
|
+
* Component-scoped reactive store with optional persistence (auto-accessor).
|
|
64
|
+
*
|
|
65
|
+
* ```ts
|
|
66
|
+
* @store<TodoState>({ items: [], filter: "all" })
|
|
67
|
+
* accessor state!: TodoState;
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export declare function store<T extends object>(defaults: T, persist?: PersistOptions): <This extends object>(_target: ClassAccessorDecoratorTarget<This, T>, context: ClassAccessorDecoratorContext<This, T>) => ClassAccessorDecoratorResult<This, T>;
|
|
71
|
+
export {};
|
|
48
72
|
//# sourceMappingURL=decorators.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/store/decorators.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/store/decorators.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAM,CAAC;AAIvD,qFAAqF;AACrF,eAAO,MAAM,MAAM,eAAiC,CAAC;AAErD,oFAAoF;AACpF,eAAO,MAAM,UAAU,eAAgC,CAAC;AAExD;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,IAAI,SAAS,MAAM,EAAE,CAAC,EAC7C,MAAM,EAAE,4BAA4B,CAAC,IAAI,EAAE,CAAC,CAAC,EAC7C,OAAO,EAAE,6BAA6B,CAAC,IAAI,EAAE,CAAC,CAAC,GAC9C,4BAA4B,CAAC,IAAI,EAAE,CAAC,CAAC,CAoDvC;AAWD,KAAK,aAAa,GAAG;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACzB,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,IAAI,CAAC,IAAI,SAAS,MAAM,EAAE,CAAC,EACzC,MAAM,EAAE,4BAA4B,CAAC,IAAI,EAAE,CAAC,CAAC,EAC7C,OAAO,EAAE,6BAA6B,CAAC,IAAI,EAAE,CAAC,CAAC,GAC9C,4BAA4B,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AACzC,wBAAgB,IAAI,CAAC,IAAI,EAAE,aAAa,GAAG,CAAC,IAAI,SAAS,MAAM,EAAE,CAAC,EAChE,MAAM,EAAE,4BAA4B,CAAC,IAAI,EAAE,CAAC,CAAC,EAC7C,OAAO,EAAE,6BAA6B,CAAC,IAAI,EAAE,CAAC,CAAC,KAC5C,4BAA4B,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AA+C3C;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,IAAI,SAAS,MAAM,EAAE,CAAC,EAC7C,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,CAAC,EACzB,OAAO,EAAE,2BAA2B,CAAC,IAAI,EAAE,CAAC,CAAC,GAC5C,CAAC,IAAI,EAAE,IAAI,KAAK,CAAC,CAsBnB;AA2DD;;;;;;;GAOG;AACH,wBAAgB,KAAK,CAAC,CAAC,SAAS,MAAM,EACpC,QAAQ,EAAE,CAAC,EACX,OAAO,CAAC,EAAE,cAAc,IAEhB,IAAI,SAAS,MAAM,EACzB,SAAS,4BAA4B,CAAC,IAAI,EAAE,CAAC,CAAC,EAC9C,SAAS,6BAA6B,CAAC,IAAI,EAAE,CAAC,CAAC,KAC9C,4BAA4B,CAAC,IAAI,EAAE,CAAC,CAAC,CAgCzC"}
|
package/dist/store/decorators.js
CHANGED
|
@@ -1,111 +1,111 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Loom — Store decorators
|
|
2
|
+
* Loom — Store decorators (TC39 Stage 3)
|
|
3
3
|
*
|
|
4
|
-
* @reactive — Internal reactive state backed by Reactive<T>
|
|
5
|
-
* @prop — External attribute with optional route binding
|
|
4
|
+
* @reactive — Internal reactive state backed by Reactive<T> (auto-accessor)
|
|
5
|
+
* @prop — External attribute with optional route binding (auto-accessor)
|
|
6
6
|
* @computed — Cached derived getter
|
|
7
|
+
* @store — Component-scoped reactive store (auto-accessor)
|
|
7
8
|
*/
|
|
8
|
-
import { REACTIVES,
|
|
9
|
+
import { REACTIVES, WATCHERS, EMITTERS, COMPUTED_DIRTY, ROUTE_PROPS } from "../decorators/symbols";
|
|
9
10
|
import { Reactive } from "./reactive";
|
|
10
11
|
import { bus } from "../bus";
|
|
12
|
+
/**
|
|
13
|
+
* Staging area for @prop registrations.
|
|
14
|
+
* TC39 member decorators evaluate before class decorators,
|
|
15
|
+
* so @prop pushes here and @component flushes it.
|
|
16
|
+
*/
|
|
17
|
+
export const pendingProps = [];
|
|
11
18
|
// ── Route sentinels ──
|
|
12
|
-
|
|
13
|
-
/** Sentinel for full route-param decompose: `@prop({params}) p!: MyType` */
|
|
19
|
+
/** Sentinel for full route-param decompose: `@prop({params}) accessor p!: MyType` */
|
|
14
20
|
export const params = Symbol("loom:sentinel:params");
|
|
15
|
-
/** Sentinel for full query-param decompose: `@prop({query}) q!: MyType` */
|
|
16
|
-
// NOTE: This is NOT the @query(".selector") DOM decorator — that's in element/decorators.
|
|
17
|
-
// This sentinel is re-exported from "@toyz/loom/router".
|
|
21
|
+
/** Sentinel for full query-param decompose: `@prop({query}) accessor q!: MyType` */
|
|
18
22
|
export const routeQuery = Symbol("loom:sentinel:query");
|
|
19
23
|
/**
|
|
20
|
-
* Internal reactive state.
|
|
24
|
+
* Internal reactive state. Auto-accessor backed by Reactive<T>.
|
|
21
25
|
* Changes schedule batched `update()` via microtask.
|
|
22
26
|
*
|
|
23
27
|
* ```ts
|
|
24
|
-
* @reactive count = 0;
|
|
28
|
+
* @reactive accessor count = 0;
|
|
25
29
|
* ```
|
|
26
30
|
*/
|
|
27
|
-
export function reactive(target,
|
|
28
|
-
|
|
29
|
-
if (!target[REACTIVES])
|
|
30
|
-
target[REACTIVES] = [];
|
|
31
|
-
target[REACTIVES].push(key);
|
|
31
|
+
export function reactive(target, context) {
|
|
32
|
+
const key = String(context.name);
|
|
32
33
|
const storageKey = Symbol(key);
|
|
33
|
-
|
|
34
|
+
// Store field name for LoomElement introspection
|
|
35
|
+
context.addInitializer(function () {
|
|
36
|
+
if (!this.constructor[REACTIVES])
|
|
37
|
+
this.constructor[REACTIVES] = [];
|
|
38
|
+
if (!this.constructor[REACTIVES].includes(key)) {
|
|
39
|
+
this.constructor[REACTIVES].push(key);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
return {
|
|
34
43
|
get() {
|
|
35
|
-
|
|
44
|
+
// Before first explicit set, fall back to the backing storage value from init()
|
|
45
|
+
if (!this[storageKey])
|
|
46
|
+
return target.get.call(this);
|
|
47
|
+
return this[storageKey].value;
|
|
36
48
|
},
|
|
37
49
|
set(val) {
|
|
38
50
|
if (!this[storageKey]) {
|
|
39
|
-
// First set
|
|
40
|
-
|
|
51
|
+
// First explicit set — create Reactive with the init'd backing value,
|
|
52
|
+
// wire all subscribers, then set the new value to fire them.
|
|
53
|
+
const backingValue = target.get.call(this);
|
|
54
|
+
const r = new Reactive(backingValue);
|
|
41
55
|
this[storageKey] = r;
|
|
42
56
|
r.subscribe(() => this.scheduleUpdate?.());
|
|
43
|
-
// Wire @watch handlers
|
|
57
|
+
// Wire @watch handlers (WATCHERS is populated because method
|
|
58
|
+
// addInitializer runs BEFORE accessor field init in TC39)
|
|
44
59
|
for (const w of (this[WATCHERS] ?? []).filter((w) => w.field === key)) {
|
|
45
60
|
r.subscribe((v, prev) => this[w.key](v, prev));
|
|
46
61
|
}
|
|
47
|
-
// Wire @emit handlers
|
|
62
|
+
// Wire @emit handlers
|
|
48
63
|
for (const e of (this[EMITTERS] ?? []).filter((e) => e.field === key)) {
|
|
49
64
|
r.subscribe((v) => bus.emit(e.factory(v)));
|
|
50
65
|
}
|
|
66
|
+
// Now set the new value — this fires all subscribers
|
|
67
|
+
r.set(val);
|
|
51
68
|
}
|
|
52
69
|
else {
|
|
53
70
|
this[storageKey].set(val);
|
|
54
71
|
}
|
|
55
72
|
},
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
73
|
+
init(val) {
|
|
74
|
+
return val;
|
|
75
|
+
},
|
|
76
|
+
};
|
|
59
77
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
*
|
|
69
|
-
* Route param injection:
|
|
70
|
-
* ```ts
|
|
71
|
-
* @prop({ param: "id" }) userId!: string; // single param
|
|
72
|
-
* @prop({params}) params!: MyParamType; // full decompose
|
|
73
|
-
* @prop({ query: "tab" }) activeTab!: string; // single query param
|
|
74
|
-
* @prop({query: routeQuery}) query!: MyQuery; // full query decompose
|
|
75
|
-
* ```
|
|
76
|
-
*/
|
|
77
|
-
export function prop(targetOrOpts, key) {
|
|
78
|
-
if (typeof key === "string") {
|
|
79
|
-
// Bare @prop — existing behavior
|
|
80
|
-
_registerProp(targetOrOpts, key);
|
|
81
|
-
return;
|
|
78
|
+
export function prop(targetOrOpts, context) {
|
|
79
|
+
// Bare @prop — auto-accessor decorator applied directly
|
|
80
|
+
if (context) {
|
|
81
|
+
const key = String(context.name);
|
|
82
|
+
const result = reactive(targetOrOpts, context);
|
|
83
|
+
// Stage for @component to flush at class-decoration time
|
|
84
|
+
pendingProps.push({ key });
|
|
85
|
+
return result;
|
|
82
86
|
}
|
|
83
|
-
// @prop({ param: "id" })
|
|
87
|
+
// @prop({ param: "id" }) — returns decorator factory
|
|
84
88
|
const opts = targetOrOpts;
|
|
85
|
-
return (target,
|
|
86
|
-
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
89
|
+
return (target, ctx) => {
|
|
90
|
+
const propKey = String(ctx.name);
|
|
91
|
+
const result = reactive(target, ctx);
|
|
92
|
+
// Store route binding metadata
|
|
93
|
+
ctx.addInitializer(function () {
|
|
94
|
+
const ctor = this.constructor;
|
|
95
|
+
if (!ctor[ROUTE_PROPS])
|
|
96
|
+
ctor[ROUTE_PROPS] = [];
|
|
97
|
+
const binding = { propKey };
|
|
98
|
+
if (opts.params)
|
|
99
|
+
binding.params = opts.params;
|
|
100
|
+
if (opts.param)
|
|
101
|
+
binding.param = opts.param;
|
|
102
|
+
if (opts.query)
|
|
103
|
+
binding.query = opts.query;
|
|
104
|
+
ctor[ROUTE_PROPS].push(binding);
|
|
105
|
+
});
|
|
106
|
+
return result;
|
|
100
107
|
};
|
|
101
108
|
}
|
|
102
|
-
/** Register a bare @prop (attribute-observed reactive) */
|
|
103
|
-
function _registerProp(target, key) {
|
|
104
|
-
if (!target.constructor[PROPS])
|
|
105
|
-
target.constructor[PROPS] = new Map();
|
|
106
|
-
target.constructor[PROPS].set(key.toLowerCase(), key);
|
|
107
|
-
reactive(target, key);
|
|
108
|
-
}
|
|
109
109
|
/**
|
|
110
110
|
* Cached derived value. Re-computed only when reactive dependencies fire.
|
|
111
111
|
*
|
|
@@ -114,21 +114,109 @@ function _registerProp(target, key) {
|
|
|
114
114
|
* get displayName() { return `${this.firstName} ${this.lastName}`; }
|
|
115
115
|
* ```
|
|
116
116
|
*/
|
|
117
|
-
export function computed(target,
|
|
118
|
-
|
|
119
|
-
const getter = desc.get;
|
|
117
|
+
export function computed(target, context) {
|
|
118
|
+
const key = String(context.name);
|
|
120
119
|
const cacheKey = Symbol(`computed:${key}`);
|
|
121
120
|
const dirtyKey = Symbol(`dirty:${key}`);
|
|
122
|
-
|
|
121
|
+
// Track dirty key for scheduleUpdate invalidation
|
|
122
|
+
context.addInitializer(function () {
|
|
123
|
+
if (!this.constructor.prototype[COMPUTED_DIRTY]) {
|
|
124
|
+
this.constructor.prototype[COMPUTED_DIRTY] = [];
|
|
125
|
+
}
|
|
126
|
+
if (!this.constructor.prototype[COMPUTED_DIRTY].includes(dirtyKey)) {
|
|
127
|
+
this.constructor.prototype[COMPUTED_DIRTY].push(dirtyKey);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
return function () {
|
|
123
131
|
if (this[dirtyKey] !== false) {
|
|
124
|
-
this[cacheKey] =
|
|
132
|
+
this[cacheKey] = target.call(this);
|
|
125
133
|
this[dirtyKey] = false;
|
|
126
134
|
}
|
|
127
135
|
return this[cacheKey];
|
|
128
136
|
};
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
137
|
+
}
|
|
138
|
+
// ── @store decorator ──
|
|
139
|
+
const STORE_META = Symbol("loom:store:meta");
|
|
140
|
+
/**
|
|
141
|
+
* Create a deep proxy that intercepts mutations and notifies the Reactive.
|
|
142
|
+
*/
|
|
143
|
+
function createDeepProxy(obj, onChange, persist) {
|
|
144
|
+
const proxyCache = new WeakMap();
|
|
145
|
+
function wrap(target) {
|
|
146
|
+
if (target === null || typeof target !== "object")
|
|
147
|
+
return target;
|
|
148
|
+
if (proxyCache.has(target))
|
|
149
|
+
return proxyCache.get(target);
|
|
150
|
+
const proxy = new Proxy(target, {
|
|
151
|
+
get(t, p, receiver) {
|
|
152
|
+
const value = Reflect.get(t, p, receiver);
|
|
153
|
+
if (value !== null && typeof value === "object" && typeof p !== "symbol") {
|
|
154
|
+
return wrap(value);
|
|
155
|
+
}
|
|
156
|
+
return value;
|
|
157
|
+
},
|
|
158
|
+
set(t, p, value, receiver) {
|
|
159
|
+
const result = Reflect.set(t, p, value, receiver);
|
|
160
|
+
if (persist) {
|
|
161
|
+
persist.storage.set(persist.key, JSON.stringify(obj));
|
|
162
|
+
}
|
|
163
|
+
onChange();
|
|
164
|
+
return result;
|
|
165
|
+
},
|
|
166
|
+
deleteProperty(t, p) {
|
|
167
|
+
const result = Reflect.deleteProperty(t, p);
|
|
168
|
+
if (persist) {
|
|
169
|
+
persist.storage.set(persist.key, JSON.stringify(obj));
|
|
170
|
+
}
|
|
171
|
+
onChange();
|
|
172
|
+
return result;
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
proxyCache.set(target, proxy);
|
|
176
|
+
return proxy;
|
|
177
|
+
}
|
|
178
|
+
return wrap(obj);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Component-scoped reactive store with optional persistence (auto-accessor).
|
|
182
|
+
*
|
|
183
|
+
* ```ts
|
|
184
|
+
* @store<TodoState>({ items: [], filter: "all" })
|
|
185
|
+
* accessor state!: TodoState;
|
|
186
|
+
* ```
|
|
187
|
+
*/
|
|
188
|
+
export function store(defaults, persist) {
|
|
189
|
+
return (_target, context) => {
|
|
190
|
+
const key = String(context.name);
|
|
191
|
+
const reactiveKey = Symbol(`store:${key}`);
|
|
192
|
+
const proxyKey = Symbol(`store:proxy:${key}`);
|
|
193
|
+
return {
|
|
194
|
+
get() {
|
|
195
|
+
if (!this[reactiveKey]) {
|
|
196
|
+
const initial = JSON.parse(JSON.stringify(defaults));
|
|
197
|
+
const r = new Reactive(initial, persist);
|
|
198
|
+
this[reactiveKey] = r;
|
|
199
|
+
r.subscribe(() => this.scheduleUpdate?.());
|
|
200
|
+
const notifyChange = () => this.scheduleUpdate?.();
|
|
201
|
+
this[proxyKey] = createDeepProxy(r.value, notifyChange, persist);
|
|
202
|
+
}
|
|
203
|
+
return this[proxyKey];
|
|
204
|
+
},
|
|
205
|
+
set(val) {
|
|
206
|
+
if (!this[reactiveKey]) {
|
|
207
|
+
const r = new Reactive(val, persist);
|
|
208
|
+
this[reactiveKey] = r;
|
|
209
|
+
r.subscribe(() => this.scheduleUpdate?.());
|
|
210
|
+
const notifyChange = () => this.scheduleUpdate?.();
|
|
211
|
+
this[proxyKey] = createDeepProxy(r.value, notifyChange, persist);
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
this[reactiveKey].set(val);
|
|
215
|
+
const notifyChange = () => this.scheduleUpdate?.();
|
|
216
|
+
this[proxyKey] = createDeepProxy(this[reactiveKey].value, notifyChange, persist);
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
};
|
|
220
|
+
};
|
|
133
221
|
}
|
|
134
222
|
//# sourceMappingURL=decorators.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../src/store/decorators.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../src/store/decorators.ts"],"names":[],"mappings":"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"}
|
package/dist/store/index.d.ts
CHANGED
|
@@ -7,6 +7,6 @@ export { Reactive, CollectionStore } from "./reactive";
|
|
|
7
7
|
export type { Subscriber, Updater, Identifiable } from "./reactive";
|
|
8
8
|
export { MemoryStorage, LocalAdapter, SessionAdapter, LocalMedium, SessionMedium } from "./storage";
|
|
9
9
|
export type { StorageAdapter, StorageMedium, PersistOptions } from "./storage";
|
|
10
|
-
export { reactive, prop, computed, params, routeQuery } from "./decorators";
|
|
10
|
+
export { reactive, prop, computed, params, routeQuery, store } from "./decorators";
|
|
11
11
|
export { watch } from "./watch";
|
|
12
12
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/store/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACvD,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAGpE,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACpG,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAG/E,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/store/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACvD,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAGpE,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACpG,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAG/E,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAGnF,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC"}
|
package/dist/store/index.js
CHANGED
|
@@ -8,7 +8,7 @@ export { Reactive, CollectionStore } from "./reactive";
|
|
|
8
8
|
// Storage adapters
|
|
9
9
|
export { MemoryStorage, LocalAdapter, SessionAdapter, LocalMedium, SessionMedium } from "./storage";
|
|
10
10
|
// Decorators
|
|
11
|
-
export { reactive, prop, computed, params, routeQuery } from "./decorators";
|
|
11
|
+
export { reactive, prop, computed, params, routeQuery, store } from "./decorators";
|
|
12
12
|
// Watch
|
|
13
13
|
export { watch } from "./watch";
|
|
14
14
|
//# sourceMappingURL=index.js.map
|
package/dist/store/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/store/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,sBAAsB;AACtB,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGvD,mBAAmB;AACnB,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAGpG,aAAa;AACb,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/store/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,sBAAsB;AACtB,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGvD,mBAAmB;AACnB,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAGpG,aAAa;AACb,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAEnF,QAAQ;AACR,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC"}
|
package/dist/store/watch.d.ts
CHANGED
|
@@ -1,27 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Loom — Store @watch
|
|
2
|
+
* Loom — Store @watch (TC39 Stage 3)
|
|
3
3
|
*
|
|
4
4
|
* Form 1: Watch a local @reactive field by name
|
|
5
5
|
* Form 2: Watch a direct Reactive/CollectionStore instance
|
|
6
6
|
*/
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
8
|
+
* Watch a local @reactive field or an external Reactive instance.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
10
|
+
* Form 1 — local field:
|
|
11
11
|
* ```ts
|
|
12
|
-
* @watch("
|
|
13
|
-
*
|
|
12
|
+
* @watch("count")
|
|
13
|
+
* onCount(val: number, prev: number) { … }
|
|
14
14
|
* ```
|
|
15
15
|
*
|
|
16
|
-
*
|
|
16
|
+
* Form 2 — external Reactive:
|
|
17
17
|
* ```ts
|
|
18
|
-
*
|
|
19
|
-
*
|
|
18
|
+
* const counter = new Reactive(0);
|
|
19
|
+
* @watch(counter)
|
|
20
|
+
* onCounter(val: number, prev: number) { … }
|
|
20
21
|
* ```
|
|
21
22
|
*/
|
|
22
|
-
export declare function watch(field: string): (
|
|
23
|
+
export declare function watch(field: string): (method: Function, context: ClassMethodDecoratorContext) => void;
|
|
23
24
|
export declare function watch(store: {
|
|
24
25
|
subscribe: Function;
|
|
25
|
-
value:
|
|
26
|
-
}): (
|
|
26
|
+
value: unknown;
|
|
27
|
+
}): (method: Function, context: ClassMethodDecoratorContext) => void;
|
|
27
28
|
//# sourceMappingURL=watch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/store/watch.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH
|
|
1
|
+
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/store/watch.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,2BAA2B,KAAK,IAAI,CAAC;AACvG,wBAAgB,KAAK,CAAC,KAAK,EAAE;IAAE,SAAS,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,2BAA2B,KAAK,IAAI,CAAC"}
|
package/dist/store/watch.js
CHANGED
|
@@ -1,29 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Loom — Store @watch
|
|
2
|
+
* Loom — Store @watch (TC39 Stage 3)
|
|
3
3
|
*
|
|
4
4
|
* Form 1: Watch a local @reactive field by name
|
|
5
5
|
* Form 2: Watch a direct Reactive/CollectionStore instance
|
|
6
6
|
*/
|
|
7
|
-
import { WATCHERS } from "../decorators/symbols";
|
|
7
|
+
import { WATCHERS, CONNECT_HOOKS } from "../decorators/symbols";
|
|
8
8
|
export function watch(target) {
|
|
9
|
-
return (
|
|
9
|
+
return (method, context) => {
|
|
10
|
+
const key = String(context.name);
|
|
10
11
|
if (typeof target === "string") {
|
|
11
12
|
// Form 1: local @reactive field — store metadata for @reactive to wire
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
context.addInitializer(function () {
|
|
14
|
+
if (!this[WATCHERS])
|
|
15
|
+
this[WATCHERS] = [];
|
|
16
|
+
this[WATCHERS].push({ field: target, key });
|
|
17
|
+
});
|
|
15
18
|
}
|
|
16
19
|
else if (typeof target === "object" && typeof target.subscribe === "function") {
|
|
17
|
-
// Form 2: direct Reactive instance — subscribe on connect
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
// Form 2: direct Reactive instance — subscribe on connect via CONNECT_HOOKS
|
|
21
|
+
context.addInitializer(function () {
|
|
22
|
+
if (!this[CONNECT_HOOKS])
|
|
23
|
+
this[CONNECT_HOOKS] = [];
|
|
24
|
+
this[CONNECT_HOOKS].push((el) => {
|
|
25
|
+
const unsub = target.subscribe((v, prev) => {
|
|
26
|
+
method.call(el, v, prev);
|
|
27
|
+
el.scheduleUpdate?.();
|
|
28
|
+
});
|
|
29
|
+
return unsub;
|
|
24
30
|
});
|
|
25
|
-
|
|
26
|
-
};
|
|
31
|
+
});
|
|
27
32
|
}
|
|
28
33
|
};
|
|
29
34
|
}
|
package/dist/store/watch.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/store/watch.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/store/watch.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAoBhE,MAAM,UAAU,KAAK,CAAC,MAAwD;IAC5E,OAAO,CAAC,MAAgB,EAAE,OAAoC,EAAE,EAAE;QAChE,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAEjC,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC/B,uEAAuE;YACvE,OAAO,CAAC,cAAc,CAAC;gBACrB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;oBAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;gBACzC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;YAC9C,CAAC,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,UAAU,EAAE,CAAC;YAChF,4EAA4E;YAC5E,OAAO,CAAC,cAAc,CAAC;gBACrB,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;oBAAE,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC;gBACnD,IAAI,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,EAAO,EAAE,EAAE;oBACnC,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAU,EAAE,IAAa,EAAE,EAAE;wBAC3D,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;wBACzB,EAAE,CAAC,cAAc,EAAE,EAAE,CAAC;oBACxB,CAAC,CAAC,CAAC;oBACH,OAAO,KAAK,CAAC;gBACf,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loom — Testing harness
|
|
3
|
+
*
|
|
4
|
+
* Utilities for mounting components in tests and waiting for renders.
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { fixture, fixtureHTML, cleanup, nextRender } from "@toyz/loom/testing";
|
|
8
|
+
*
|
|
9
|
+
* // Mount by tag name
|
|
10
|
+
* const el = await fixture<MyCounter>("my-counter");
|
|
11
|
+
* el.count = 5;
|
|
12
|
+
* await el.updateComplete;
|
|
13
|
+
* expect(el.shadow.querySelector("span")?.textContent).toBe("5");
|
|
14
|
+
*
|
|
15
|
+
* // Mount from an HTML template string
|
|
16
|
+
* const el2 = await fixtureHTML<MyCard>(`<my-card title="Hello">content</my-card>`);
|
|
17
|
+
* expect(el2.shadow.querySelector("h2")?.textContent).toBe("Hello");
|
|
18
|
+
*
|
|
19
|
+
* cleanup(); // removes all fixtures
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
import type { LoomElement } from "./element/element";
|
|
23
|
+
/** Type for elements returned by fixture helpers */
|
|
24
|
+
type Rendered<T> = T & {
|
|
25
|
+
updateComplete: Promise<void>;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Mount a component by tag name and wait for its first render.
|
|
29
|
+
* Returns the element instance with full type access.
|
|
30
|
+
*
|
|
31
|
+
* @param tag Custom element tag name
|
|
32
|
+
* @param attrs Optional attribute key/value pairs to set before mount
|
|
33
|
+
*/
|
|
34
|
+
export declare function fixture<T extends HTMLElement = LoomElement>(tag: string, attrs?: Record<string, string>): Promise<Rendered<T>>;
|
|
35
|
+
/**
|
|
36
|
+
* Mount a component from an HTML template string and wait for its first render.
|
|
37
|
+
* Useful for testing slot content, nested components, and attribute combinations.
|
|
38
|
+
*
|
|
39
|
+
* Returns the first child element with full type access.
|
|
40
|
+
*
|
|
41
|
+
* @param html HTML string containing the component to mount
|
|
42
|
+
*/
|
|
43
|
+
export declare function fixtureHTML<T extends HTMLElement = LoomElement>(html: string): Promise<Rendered<T>>;
|
|
44
|
+
/**
|
|
45
|
+
* Remove all fixture containers from the document.
|
|
46
|
+
* Call this in afterEach or test teardown.
|
|
47
|
+
*/
|
|
48
|
+
export declare function cleanup(): void;
|
|
49
|
+
/**
|
|
50
|
+
* Wait for a Loom element to complete its next render cycle.
|
|
51
|
+
* Useful after programmatic state changes.
|
|
52
|
+
*/
|
|
53
|
+
export declare function nextRender(): Promise<void>;
|
|
54
|
+
export {};
|
|
55
|
+
//# sourceMappingURL=testing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIrD,oDAAoD;AACpD,KAAK,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG;IAAE,cAAc,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC;AAEzD;;;;;;GAMG;AACH,wBAAsB,OAAO,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EAC/D,GAAG,EAAE,MAAM,EACX,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAkBtB;AAED;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EACnE,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CActB;AAED;;;GAGG;AACH,wBAAgB,OAAO,IAAI,IAAI,CAK9B;AAED;;;GAGG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAEhD"}
|