@toyz/loom 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +108 -0
- package/dist/app.d.ts +70 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +152 -0
- package/dist/app.js.map +1 -0
- package/dist/bus.d.ts +27 -0
- package/dist/bus.d.ts.map +1 -0
- package/dist/bus.js +41 -0
- package/dist/bus.js.map +1 -0
- package/dist/css.d.ts +25 -0
- package/dist/css.d.ts.map +1 -0
- package/dist/css.js +48 -0
- package/dist/css.js.map +1 -0
- package/dist/decorators/component.d.ts +11 -0
- package/dist/decorators/component.d.ts.map +1 -0
- package/dist/decorators/component.js +38 -0
- package/dist/decorators/component.js.map +1 -0
- package/dist/decorators/di.d.ts +37 -0
- package/dist/decorators/di.d.ts.map +1 -0
- package/dist/decorators/di.js +65 -0
- package/dist/decorators/di.js.map +1 -0
- package/dist/decorators/dom.d.ts +15 -0
- package/dist/decorators/dom.d.ts.map +1 -0
- package/dist/decorators/dom.js +33 -0
- package/dist/decorators/dom.js.map +1 -0
- package/dist/decorators/events.d.ts +46 -0
- package/dist/decorators/events.d.ts.map +1 -0
- package/dist/decorators/events.js +69 -0
- package/dist/decorators/events.js.map +1 -0
- package/dist/decorators/index.d.ts +18 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/dist/decorators/index.js +27 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/decorators/lifecycle.d.ts +49 -0
- package/dist/decorators/lifecycle.d.ts.map +1 -0
- package/dist/decorators/lifecycle.js +105 -0
- package/dist/decorators/lifecycle.js.map +1 -0
- package/dist/decorators/state.d.ts +41 -0
- package/dist/decorators/state.d.ts.map +1 -0
- package/dist/decorators/state.js +125 -0
- package/dist/decorators/state.js.map +1 -0
- package/dist/decorators/symbols.d.ts +13 -0
- package/dist/decorators/symbols.d.ts.map +1 -0
- package/dist/decorators/symbols.js +15 -0
- package/dist/decorators/symbols.js.map +1 -0
- package/dist/decorators/timing.d.ts +35 -0
- package/dist/decorators/timing.d.ts.map +1 -0
- package/dist/decorators/timing.js +57 -0
- package/dist/decorators/timing.js.map +1 -0
- package/dist/decorators/transform.d.ts +45 -0
- package/dist/decorators/transform.d.ts.map +1 -0
- package/dist/decorators/transform.js +48 -0
- package/dist/decorators/transform.js.map +1 -0
- package/dist/element.d.ts +62 -0
- package/dist/element.d.ts.map +1 -0
- package/dist/element.js +150 -0
- package/dist/element.js.map +1 -0
- package/dist/event.d.ts +24 -0
- package/dist/event.d.ts.map +1 -0
- package/dist/event.js +35 -0
- package/dist/event.js.map +1 -0
- package/dist/icon.d.ts +35 -0
- package/dist/icon.d.ts.map +1 -0
- package/dist/icon.js +119 -0
- package/dist/icon.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/jsx-dev-runtime.d.ts +8 -0
- package/dist/jsx-dev-runtime.d.ts.map +1 -0
- package/dist/jsx-dev-runtime.js +8 -0
- package/dist/jsx-dev-runtime.js.map +1 -0
- package/dist/jsx-runtime.d.ts +13 -0
- package/dist/jsx-runtime.d.ts.map +1 -0
- package/dist/jsx-runtime.js +101 -0
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/morph.d.ts +23 -0
- package/dist/morph.d.ts.map +1 -0
- package/dist/morph.js +212 -0
- package/dist/morph.js.map +1 -0
- package/dist/reactive.d.ts +75 -0
- package/dist/reactive.d.ts.map +1 -0
- package/dist/reactive.js +133 -0
- package/dist/reactive.js.map +1 -0
- package/dist/render-loop.d.ts +34 -0
- package/dist/render-loop.d.ts.map +1 -0
- package/dist/render-loop.js +70 -0
- package/dist/render-loop.js.map +1 -0
- package/dist/router/events.d.ts +12 -0
- package/dist/router/events.d.ts.map +1 -0
- package/dist/router/events.js +17 -0
- package/dist/router/events.js.map +1 -0
- package/dist/router/index.d.ts +14 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js +18 -0
- package/dist/router/index.js.map +1 -0
- package/dist/router/link.d.ts +18 -0
- package/dist/router/link.d.ts.map +1 -0
- package/dist/router/link.js +75 -0
- package/dist/router/link.js.map +1 -0
- package/dist/router/mode.d.ts +33 -0
- package/dist/router/mode.d.ts.map +1 -0
- package/dist/router/mode.js +48 -0
- package/dist/router/mode.js.map +1 -0
- package/dist/router/outlet.d.ts +40 -0
- package/dist/router/outlet.d.ts.map +1 -0
- package/dist/router/outlet.js +171 -0
- package/dist/router/outlet.js.map +1 -0
- package/dist/router/route.d.ts +76 -0
- package/dist/router/route.d.ts.map +1 -0
- package/dist/router/route.js +147 -0
- package/dist/router/route.js.map +1 -0
- package/dist/router/router.d.ts +50 -0
- package/dist/router/router.d.ts.map +1 -0
- package/dist/router/router.js +140 -0
- package/dist/router/router.js.map +1 -0
- package/dist/storage.d.ts +55 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +90 -0
- package/dist/storage.js.map +1 -0
- package/dist/virtual.d.ts +69 -0
- package/dist/virtual.d.ts.map +1 -0
- package/dist/virtual.js +247 -0
- package/dist/virtual.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { INJECT_PARAMS } from "./symbols";
|
|
2
|
+
import { app } from "../app";
|
|
3
|
+
/**
|
|
4
|
+
* Auto-instantiated singleton. Registered on app.start().
|
|
5
|
+
* Constructor @inject params are resolved automatically.
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* @service
|
|
9
|
+
* class BookmarkStore extends CollectionStore<Bookmark> { ... }
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export function service(ctor) {
|
|
13
|
+
app.registerService(ctor);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Dual-mode dependency injection.
|
|
17
|
+
*
|
|
18
|
+
* Property: @inject(Foo) foo!: Foo;
|
|
19
|
+
* Constructor: constructor(@inject(Config) config: Config)
|
|
20
|
+
* Factory arg: createChat(@inject(NatsConn) nc: NatsConn)
|
|
21
|
+
*
|
|
22
|
+
* T is optional — use for explicit typing if desired.
|
|
23
|
+
*/
|
|
24
|
+
export function inject(key) {
|
|
25
|
+
return (target, propOrMethod, index) => {
|
|
26
|
+
if (index !== undefined) {
|
|
27
|
+
// Parameter decorator → store metadata for resolution on start()
|
|
28
|
+
const proto = propOrMethod ? target : target.prototype;
|
|
29
|
+
const method = propOrMethod ?? "constructor";
|
|
30
|
+
if (!proto[INJECT_PARAMS])
|
|
31
|
+
proto[INJECT_PARAMS] = [];
|
|
32
|
+
proto[INJECT_PARAMS].push({ method, index, key });
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
// Property decorator → lazy getter
|
|
36
|
+
Object.defineProperty(target, propOrMethod, {
|
|
37
|
+
get() {
|
|
38
|
+
return app.get(key);
|
|
39
|
+
},
|
|
40
|
+
configurable: true,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Method decorator on @service classes.
|
|
47
|
+
* Return value is registered as a provider on app.start().
|
|
48
|
+
* Supports @inject on parameters. Async methods are awaited.
|
|
49
|
+
*
|
|
50
|
+
* ```ts
|
|
51
|
+
* @service
|
|
52
|
+
* class Boot {
|
|
53
|
+
* @factory(ChatServiceNatsClient)
|
|
54
|
+
* createChat(@inject(NatsConnection) nc: NatsConnection) {
|
|
55
|
+
* return new ChatServiceNatsClient(nc);
|
|
56
|
+
* }
|
|
57
|
+
* }
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export function factory(key) {
|
|
61
|
+
return (target, method) => {
|
|
62
|
+
app.registerFactory(key, target, method);
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=di.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"di.js","sourceRoot":"","sources":["../../src/decorators/di.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAE7B;;;;;;;;GAQG;AACH,MAAM,UAAU,OAAO,CAAC,IAAS;IAC/B,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,MAAM,CAAU,GAAQ;IACtC,OAAO,CAAC,MAAW,EAAE,YAAgC,EAAE,KAAc,EAAE,EAAE;QACvE,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,iEAAiE;YACjE,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC;YACvD,MAAM,MAAM,GAAG,YAAY,IAAI,aAAa,CAAC;YAC7C,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC;gBAAE,KAAK,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC;YACrD,KAAK,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QACpD,CAAC;aAAM,CAAC;YACN,mCAAmC;YACnC,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,YAAa,EAAE;gBAC3C,GAAG;oBACD,OAAO,GAAG,CAAC,GAAG,CAAI,GAAG,CAAC,CAAC;gBACzB,CAAC;gBACD,YAAY,EAAE,IAAI;aACnB,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,OAAO,CAAC,GAAS;IAC/B,OAAO,CAAC,MAAW,EAAE,MAAc,EAAE,EAAE;QACrC,GAAG,CAAC,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy shadow DOM querySelector.
|
|
3
|
+
* ```ts
|
|
4
|
+
* @query(".submit-btn") submitBtn!: HTMLButtonElement;
|
|
5
|
+
* ```
|
|
6
|
+
*/
|
|
7
|
+
export declare function query(selector: string): (target: any, key: string) => void;
|
|
8
|
+
/**
|
|
9
|
+
* Lazy shadow DOM querySelectorAll.
|
|
10
|
+
* ```ts
|
|
11
|
+
* @queryAll("input") inputs!: HTMLInputElement[];
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export declare function queryAll(selector: string): (target: any, key: string) => void;
|
|
15
|
+
//# sourceMappingURL=dom.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../../src/decorators/dom.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,QAAQ,EAAE,MAAM,IAC5B,QAAQ,GAAG,EAAE,KAAK,MAAM,UAQjC;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAC/B,QAAQ,GAAG,EAAE,KAAK,MAAM,UAQjC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy shadow DOM querySelector.
|
|
3
|
+
* ```ts
|
|
4
|
+
* @query(".submit-btn") submitBtn!: HTMLButtonElement;
|
|
5
|
+
* ```
|
|
6
|
+
*/
|
|
7
|
+
export function query(selector) {
|
|
8
|
+
return (target, key) => {
|
|
9
|
+
Object.defineProperty(target, key, {
|
|
10
|
+
get() {
|
|
11
|
+
return this.shadow.querySelector(selector);
|
|
12
|
+
},
|
|
13
|
+
configurable: true,
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Lazy shadow DOM querySelectorAll.
|
|
19
|
+
* ```ts
|
|
20
|
+
* @queryAll("input") inputs!: HTMLInputElement[];
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export function queryAll(selector) {
|
|
24
|
+
return (target, key) => {
|
|
25
|
+
Object.defineProperty(target, key, {
|
|
26
|
+
get() {
|
|
27
|
+
return Array.from(this.shadow.querySelectorAll(selector));
|
|
28
|
+
},
|
|
29
|
+
configurable: true,
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=dom.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom.js","sourceRoot":"","sources":["../../src/decorators/dom.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,KAAK,CAAC,QAAgB;IACpC,OAAO,CAAC,MAAW,EAAE,GAAW,EAAE,EAAE;QAClC,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE;YACjC,GAAG;gBACD,OAAO,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YAC7C,CAAC;YACD,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,QAAgB;IACvC,OAAO,CAAC,MAAW,EAAE,GAAW,EAAE,EAAE;QAClC,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE;YACjC,GAAG;gBACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC5D,CAAC;YACD,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { LoomEvent } from "../event";
|
|
2
|
+
import { type Constructor } from "../bus";
|
|
3
|
+
/**
|
|
4
|
+
* Declarative event subscription. Auto-subscribed on connect, auto-cleaned on disconnect.
|
|
5
|
+
*
|
|
6
|
+
* Bus event:
|
|
7
|
+
* ```ts
|
|
8
|
+
* @on(ColorSelect)
|
|
9
|
+
* handleColor(e: ColorSelect) { ... }
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* DOM event (window, document, or any EventTarget):
|
|
13
|
+
* ```ts
|
|
14
|
+
* @on(window, "resize")
|
|
15
|
+
* onResize(e: Event) { ... }
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare function on<T extends LoomEvent>(type: Constructor<T>): (target: any, key: string) => void;
|
|
19
|
+
export declare function on(target: EventTarget, event: string): (target: any, key: string) => void;
|
|
20
|
+
/**
|
|
21
|
+
* React to specific field changes. Receives new and previous values.
|
|
22
|
+
*
|
|
23
|
+
* ```ts
|
|
24
|
+
* @watch("value")
|
|
25
|
+
* onValueChange(newVal: number, oldVal: number) { ... }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare function watch(field: string): (target: any, key: string) => void;
|
|
29
|
+
/**
|
|
30
|
+
* Auto-broadcast to the bus.
|
|
31
|
+
*
|
|
32
|
+
* On a field: fires an event via factory whenever value changes.
|
|
33
|
+
* On a method: return value is auto-emitted (must be LoomEvent subclass).
|
|
34
|
+
*
|
|
35
|
+
* ```ts
|
|
36
|
+
* @reactive @emit(ColorSelect, idx => new ColorSelect(idx, 0))
|
|
37
|
+
* selectedIndex = 0;
|
|
38
|
+
*
|
|
39
|
+
* @emit()
|
|
40
|
+
* placePixel(x: bigint, y: bigint): PixelPlaced {
|
|
41
|
+
* return new PixelPlaced(x, y, this.selectedColor);
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare function emit<T extends LoomEvent>(_type?: Constructor<T>, factory?: (val: any) => T): (target: any, key: string, desc?: PropertyDescriptor) => void;
|
|
46
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/decorators/events.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAO,KAAK,WAAW,EAAE,MAAM,QAAQ,CAAC;AAE/C;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,EAAE,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;AAClG,wBAAgB,EAAE,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;AAc3F;;;;;;;GAOG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,IACzB,QAAQ,GAAG,EAAE,KAAK,MAAM,UAIjC;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,IAAI,CAAC,CAAC,SAAS,SAAS,EACtC,KAAK,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,EACtB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,IAEjB,QAAQ,GAAG,EAAE,KAAK,MAAM,EAAE,OAAO,kBAAkB,UAe5D"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { ON_HANDLERS, WATCHERS, EMITTERS } from "./symbols";
|
|
2
|
+
import { LoomEvent } from "../event";
|
|
3
|
+
import { bus } from "../bus";
|
|
4
|
+
export function on(typeOrTarget, event) {
|
|
5
|
+
return (target, key) => {
|
|
6
|
+
if (!target[ON_HANDLERS])
|
|
7
|
+
target[ON_HANDLERS] = [];
|
|
8
|
+
if (event !== undefined) {
|
|
9
|
+
// DOM EventTarget binding: @on(window, "resize")
|
|
10
|
+
target[ON_HANDLERS].push({ domTarget: typeOrTarget, event, key });
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
// Bus event binding: @on(ColorSelect)
|
|
14
|
+
target[ON_HANDLERS].push({ type: typeOrTarget, key });
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* React to specific field changes. Receives new and previous values.
|
|
20
|
+
*
|
|
21
|
+
* ```ts
|
|
22
|
+
* @watch("value")
|
|
23
|
+
* onValueChange(newVal: number, oldVal: number) { ... }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export function watch(field) {
|
|
27
|
+
return (target, key) => {
|
|
28
|
+
if (!target[WATCHERS])
|
|
29
|
+
target[WATCHERS] = [];
|
|
30
|
+
target[WATCHERS].push({ field, key });
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Auto-broadcast to the bus.
|
|
35
|
+
*
|
|
36
|
+
* On a field: fires an event via factory whenever value changes.
|
|
37
|
+
* On a method: return value is auto-emitted (must be LoomEvent subclass).
|
|
38
|
+
*
|
|
39
|
+
* ```ts
|
|
40
|
+
* @reactive @emit(ColorSelect, idx => new ColorSelect(idx, 0))
|
|
41
|
+
* selectedIndex = 0;
|
|
42
|
+
*
|
|
43
|
+
* @emit()
|
|
44
|
+
* placePixel(x: bigint, y: bigint): PixelPlaced {
|
|
45
|
+
* return new PixelPlaced(x, y, this.selectedColor);
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export function emit(_type, factory) {
|
|
50
|
+
return (target, key, desc) => {
|
|
51
|
+
if (desc?.value) {
|
|
52
|
+
// Method decorator — wrap, emit return value
|
|
53
|
+
const orig = desc.value;
|
|
54
|
+
desc.value = function (...args) {
|
|
55
|
+
const result = orig.apply(this, args);
|
|
56
|
+
if (result instanceof LoomEvent)
|
|
57
|
+
bus.emit(result);
|
|
58
|
+
return result;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
// Field decorator — hook into @reactive subscriber
|
|
63
|
+
if (!target[EMITTERS])
|
|
64
|
+
target[EMITTERS] = [];
|
|
65
|
+
target[EMITTERS].push({ field: key, factory });
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/decorators/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,GAAG,EAAoB,MAAM,QAAQ,CAAC;AAmB/C,MAAM,UAAU,EAAE,CAAC,YAAiB,EAAE,KAAc;IAClD,OAAO,CAAC,MAAW,EAAE,GAAW,EAAE,EAAE;QAClC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC;YAAE,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC;QACnD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,iDAAiD;YACjD,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QACpE,CAAC;aAAM,CAAC;YACN,sCAAsC;YACtC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,CAAC;QACxD,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,KAAK,CAAC,KAAa;IACjC,OAAO,CAAC,MAAW,EAAE,GAAW,EAAE,EAAE;QAClC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;YAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;QAC7C,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IACxC,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,IAAI,CAClB,KAAsB,EACtB,OAAyB;IAEzB,OAAO,CAAC,MAAW,EAAE,GAAW,EAAE,IAAyB,EAAE,EAAE;QAC7D,IAAI,IAAI,EAAE,KAAK,EAAE,CAAC;YAChB,6CAA6C;YAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC;YACxB,IAAI,CAAC,KAAK,GAAG,UAAU,GAAG,IAAW;gBACnC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBACtC,IAAI,MAAM,YAAY,SAAS;oBAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAClD,OAAO,MAAM,CAAC;YAChB,CAAC,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,mDAAmD;YACnD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;gBAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;YAC7C,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QACjD,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loom — Decorators
|
|
3
|
+
*
|
|
4
|
+
* Barrel re-export for the full decorator arsenal:
|
|
5
|
+
* @component, @prop, @reactive, @computed, @on, @watch, @emit,
|
|
6
|
+
* @query, @queryAll, @catch_, @suspend, @mount, @unmount,
|
|
7
|
+
* @interval, @timeout, @animationFrame, @service, @inject, @factory
|
|
8
|
+
*/
|
|
9
|
+
export { REACTIVES, PROPS, ON_HANDLERS, WATCHERS, EMITTERS, COMPUTED_DIRTY, CATCH_HANDLER, MOUNT_HANDLERS, UNMOUNT_HANDLERS, INJECT_PARAMS, ROUTE_PROPS, TRANSFORMS, } from "./symbols";
|
|
10
|
+
export { component } from "./component";
|
|
11
|
+
export { reactive, prop, computed, params, routeQuery } from "./state";
|
|
12
|
+
export { transform, typed } from "./transform";
|
|
13
|
+
export { on, watch, emit } from "./events";
|
|
14
|
+
export { query, queryAll } from "./dom";
|
|
15
|
+
export { catch_, suspend, mount, unmount } from "./lifecycle";
|
|
16
|
+
export { interval, timeout, animationFrame } from "./timing";
|
|
17
|
+
export { service, inject, factory } from "./di";
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/decorators/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EACL,SAAS,EACT,KAAK,EACL,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,cAAc,EACd,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,UAAU,GACX,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAGvE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAG/C,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAG3C,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGxC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAG9D,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAG7D,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loom — Decorators
|
|
3
|
+
*
|
|
4
|
+
* Barrel re-export for the full decorator arsenal:
|
|
5
|
+
* @component, @prop, @reactive, @computed, @on, @watch, @emit,
|
|
6
|
+
* @query, @queryAll, @catch_, @suspend, @mount, @unmount,
|
|
7
|
+
* @interval, @timeout, @animationFrame, @service, @inject, @factory
|
|
8
|
+
*/
|
|
9
|
+
// Symbols (consumed by LoomElement and App)
|
|
10
|
+
export { REACTIVES, PROPS, ON_HANDLERS, WATCHERS, EMITTERS, COMPUTED_DIRTY, CATCH_HANDLER, MOUNT_HANDLERS, UNMOUNT_HANDLERS, INJECT_PARAMS, ROUTE_PROPS, TRANSFORMS, } from "./symbols";
|
|
11
|
+
// Component registration
|
|
12
|
+
export { component } from "./component";
|
|
13
|
+
// State management
|
|
14
|
+
export { reactive, prop, computed, params, routeQuery } from "./state";
|
|
15
|
+
// Type conversion
|
|
16
|
+
export { transform, typed } from "./transform";
|
|
17
|
+
// Event system
|
|
18
|
+
export { on, watch, emit } from "./events";
|
|
19
|
+
// DOM queries
|
|
20
|
+
export { query, queryAll } from "./dom";
|
|
21
|
+
// Lifecycle & error boundaries
|
|
22
|
+
export { catch_, suspend, mount, unmount } from "./lifecycle";
|
|
23
|
+
// Timers & animation
|
|
24
|
+
export { interval, timeout, animationFrame } from "./timing";
|
|
25
|
+
// Dependency injection
|
|
26
|
+
export { service, inject, factory } from "./di";
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/decorators/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,4CAA4C;AAC5C,OAAO,EACL,SAAS,EACT,KAAK,EACL,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,cAAc,EACd,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,UAAU,GACX,MAAM,WAAW,CAAC;AAEnB,yBAAyB;AACzB,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,mBAAmB;AACnB,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAEvE,kBAAkB;AAClB,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAE/C,eAAe;AACf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAE3C,cAAc;AACd,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAExC,+BAA+B;AAC/B,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE9D,qBAAqB;AACrB,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE7D,uBAAuB;AACvB,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
type CatchFn = (error: Error, element: any) => void;
|
|
2
|
+
/**
|
|
3
|
+
* Error boundary. Wraps lifecycle methods with try/catch, renders fallback on error.
|
|
4
|
+
* Named catch_ since `catch` is reserved.
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* @component("my-widget")
|
|
8
|
+
* @catch_((err, el) => {
|
|
9
|
+
* el.shadow.replaceChildren(<div>{err.message}</div>);
|
|
10
|
+
* })
|
|
11
|
+
* class MyWidget extends LoomElement { ... }
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export declare function catch_(handler: CatchFn): (ctor: any) => void;
|
|
15
|
+
/**
|
|
16
|
+
* Async suspense. Wraps async methods to auto-manage loading/error state.
|
|
17
|
+
* Expects the component to have @reactive loading and @reactive error fields.
|
|
18
|
+
*
|
|
19
|
+
* ```ts
|
|
20
|
+
* @suspend()
|
|
21
|
+
* async fetchUser() {
|
|
22
|
+
* const res = await fetch(`/api/users/${this.userId}`);
|
|
23
|
+
* this.user = await res.json();
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare function suspend(): (_target: any, _key: string, desc: PropertyDescriptor) => void;
|
|
28
|
+
/**
|
|
29
|
+
* Lifecycle: runs when element connects to the DOM.
|
|
30
|
+
* Multiple @mount methods per class allowed. No need to call super.
|
|
31
|
+
*
|
|
32
|
+
* ```ts
|
|
33
|
+
* @mount
|
|
34
|
+
* setup() { this.ctx = this.canvas.getContext("2d"); }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare function mount(target: any, key: string): void;
|
|
38
|
+
/**
|
|
39
|
+
* Lifecycle: runs when element disconnects from the DOM.
|
|
40
|
+
* Multiple @unmount methods per class allowed. Runs BEFORE track() cleanup.
|
|
41
|
+
*
|
|
42
|
+
* ```ts
|
|
43
|
+
* @unmount
|
|
44
|
+
* saveState() { localStorage.setItem("state", JSON.stringify(this.state)); }
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export declare function unmount(target: any, key: string): void;
|
|
48
|
+
export {};
|
|
49
|
+
//# sourceMappingURL=lifecycle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../src/decorators/lifecycle.ts"],"names":[],"mappings":"AAEA,KAAK,OAAO,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,KAAK,IAAI,CAAC;AAEpD;;;;;;;;;;;GAWG;AACH,wBAAgB,MAAM,CAAC,OAAO,EAAE,OAAO,IAC7B,MAAM,GAAG,UA2BlB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,OAAO,KACb,SAAS,GAAG,EAAE,MAAM,MAAM,EAAE,MAAM,kBAAkB,UAkB7D;AAED;;;;;;;;GAQG;AACH,wBAAgB,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAGpD;AAED;;;;;;;;GAQG;AACH,wBAAgB,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAGtD"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { CATCH_HANDLER, MOUNT_HANDLERS, UNMOUNT_HANDLERS } from "./symbols";
|
|
2
|
+
/**
|
|
3
|
+
* Error boundary. Wraps lifecycle methods with try/catch, renders fallback on error.
|
|
4
|
+
* Named catch_ since `catch` is reserved.
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* @component("my-widget")
|
|
8
|
+
* @catch_((err, el) => {
|
|
9
|
+
* el.shadow.replaceChildren(<div>{err.message}</div>);
|
|
10
|
+
* })
|
|
11
|
+
* class MyWidget extends LoomElement { ... }
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export function catch_(handler) {
|
|
15
|
+
return (ctor) => {
|
|
16
|
+
ctor[CATCH_HANDLER] = handler;
|
|
17
|
+
// Wrap update()
|
|
18
|
+
const origUpdate = ctor.prototype.update;
|
|
19
|
+
if (origUpdate) {
|
|
20
|
+
ctor.prototype.update = function () {
|
|
21
|
+
try {
|
|
22
|
+
return origUpdate.call(this);
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
handler(err, this);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
// Wrap connectedCallback()
|
|
30
|
+
const origConnect = ctor.prototype.connectedCallback;
|
|
31
|
+
if (origConnect) {
|
|
32
|
+
ctor.prototype.connectedCallback = function () {
|
|
33
|
+
try {
|
|
34
|
+
origConnect.call(this);
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
handler(err, this);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Async suspense. Wraps async methods to auto-manage loading/error state.
|
|
45
|
+
* Expects the component to have @reactive loading and @reactive error fields.
|
|
46
|
+
*
|
|
47
|
+
* ```ts
|
|
48
|
+
* @suspend()
|
|
49
|
+
* async fetchUser() {
|
|
50
|
+
* const res = await fetch(`/api/users/${this.userId}`);
|
|
51
|
+
* this.user = await res.json();
|
|
52
|
+
* }
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export function suspend() {
|
|
56
|
+
return (_target, _key, desc) => {
|
|
57
|
+
const orig = desc.value;
|
|
58
|
+
desc.value = async function (...args) {
|
|
59
|
+
this.loading = true;
|
|
60
|
+
this.error = null;
|
|
61
|
+
try {
|
|
62
|
+
const result = await orig.apply(this, args);
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
this.error = err;
|
|
67
|
+
const handler = this.constructor[CATCH_HANDLER];
|
|
68
|
+
if (handler)
|
|
69
|
+
handler(err, this);
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
this.loading = false;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Lifecycle: runs when element connects to the DOM.
|
|
79
|
+
* Multiple @mount methods per class allowed. No need to call super.
|
|
80
|
+
*
|
|
81
|
+
* ```ts
|
|
82
|
+
* @mount
|
|
83
|
+
* setup() { this.ctx = this.canvas.getContext("2d"); }
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
export function mount(target, key) {
|
|
87
|
+
if (!target[MOUNT_HANDLERS])
|
|
88
|
+
target[MOUNT_HANDLERS] = [];
|
|
89
|
+
target[MOUNT_HANDLERS].push(key);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Lifecycle: runs when element disconnects from the DOM.
|
|
93
|
+
* Multiple @unmount methods per class allowed. Runs BEFORE track() cleanup.
|
|
94
|
+
*
|
|
95
|
+
* ```ts
|
|
96
|
+
* @unmount
|
|
97
|
+
* saveState() { localStorage.setItem("state", JSON.stringify(this.state)); }
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
export function unmount(target, key) {
|
|
101
|
+
if (!target[UNMOUNT_HANDLERS])
|
|
102
|
+
target[UNMOUNT_HANDLERS] = [];
|
|
103
|
+
target[UNMOUNT_HANDLERS].push(key);
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../src/decorators/lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAI5E;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,MAAM,CAAC,OAAgB;IACrC,OAAO,CAAC,IAAS,EAAE,EAAE;QAClB,IAAY,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC;QAEvC,gBAAgB;QAChB,MAAM,UAAU,GAAI,IAAI,CAAC,SAAiB,CAAC,MAAM,CAAC;QAClD,IAAI,UAAU,EAAE,CAAC;YACd,IAAI,CAAC,SAAiB,CAAC,MAAM,GAAG;gBAC/B,IAAI,CAAC;oBACH,OAAO,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC/B,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,CAAC,GAAY,EAAE,IAAI,CAAC,CAAC;gBAC9B,CAAC;YACH,CAAC,CAAC;QACJ,CAAC;QAED,2BAA2B;QAC3B,MAAM,WAAW,GAAI,IAAI,CAAC,SAAiB,CAAC,iBAAiB,CAAC;QAC9D,IAAI,WAAW,EAAE,CAAC;YACf,IAAI,CAAC,SAAiB,CAAC,iBAAiB,GAAG;gBAC1C,IAAI,CAAC;oBACH,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACzB,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,CAAC,GAAY,EAAE,IAAI,CAAC,CAAC;gBAC9B,CAAC;YACH,CAAC,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,OAAO;IACrB,OAAO,CAAC,OAAY,EAAE,IAAY,EAAE,IAAwB,EAAE,EAAE;QAC9D,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC;QAExB,IAAI,CAAC,KAAK,GAAG,KAAK,WAAsB,GAAG,IAAW;YACpD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACpB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;YAClB,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBAC5C,OAAO,MAAM,CAAC;YAChB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,KAAK,GAAG,GAAY,CAAC;gBAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;gBAChD,IAAI,OAAO;oBAAE,OAAO,CAAC,GAAY,EAAE,IAAI,CAAC,CAAC;YAC3C,CAAC;oBAAS,CAAC;gBACT,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;YACvB,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,KAAK,CAAC,MAAW,EAAE,GAAW;IAC5C,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC;QAAE,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,CAAC;IACzD,MAAM,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACnC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,OAAO,CAAC,MAAW,EAAE,GAAW;IAC9C,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC;QAAE,MAAM,CAAC,gBAAgB,CAAC,GAAG,EAAE,CAAC;IAC7D,MAAM,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACrC,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** Sentinel for full route-param decompose: `@prop({params}) p!: MyType` */
|
|
2
|
+
export declare const params: unique symbol;
|
|
3
|
+
/** Sentinel for full query-param decompose: `@prop({query}) q!: MyType` */
|
|
4
|
+
export declare const routeQuery: unique symbol;
|
|
5
|
+
/**
|
|
6
|
+
* Internal reactive state. Creates a getter/setter backed by Reactive<T>.
|
|
7
|
+
* Changes schedule batched `update()` via microtask.
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* @reactive count = 0;
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export declare function reactive(target: any, key: string): void;
|
|
14
|
+
/**
|
|
15
|
+
* External attribute. Observed HTML attribute that auto-parses from strings.
|
|
16
|
+
* Uses @reactive under the hood.
|
|
17
|
+
*
|
|
18
|
+
* Bare decorator:
|
|
19
|
+
* ```ts
|
|
20
|
+
* @prop label = "Count"; // <my-counter label="Clicks">
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* Route param injection:
|
|
24
|
+
* ```ts
|
|
25
|
+
* @prop({ param: "id" }) userId!: string; // single param
|
|
26
|
+
* @prop({params}) params!: MyParamType; // full decompose
|
|
27
|
+
* @prop({ query: "tab" }) activeTab!: string; // single query param
|
|
28
|
+
* @prop({query: routeQuery}) query!: MyQuery; // full query decompose
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare function prop(targetOrOpts: any, key?: any): any;
|
|
32
|
+
/**
|
|
33
|
+
* Cached derived value. Re-computed only when reactive dependencies fire.
|
|
34
|
+
*
|
|
35
|
+
* ```ts
|
|
36
|
+
* @computed
|
|
37
|
+
* get displayName() { return `${this.firstName} ${this.lastName}`; }
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare function computed(target: any, key: string, desc: PropertyDescriptor): void;
|
|
41
|
+
//# sourceMappingURL=state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/decorators/state.ts"],"names":[],"mappings":"AAOA,4EAA4E;AAC5E,eAAO,MAAM,MAAM,eAAiC,CAAC;AAErD,2EAA2E;AAG3E,eAAO,MAAM,UAAU,eAAgC,CAAC;AAExD;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAqCvD;AAiBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,IAAI,CAClB,YAAY,EAAE,GAAG,EACjB,GAAG,CAAC,EAAE,GAAG,GACR,GAAG,CAuBL;AASD;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CACtB,MAAM,EAAE,GAAG,EACX,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,kBAAkB,GACvB,IAAI,CAgBN"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { REACTIVES, PROPS, WATCHERS, EMITTERS, COMPUTED_DIRTY, ROUTE_PROPS } from "./symbols";
|
|
2
|
+
import { Reactive } from "../reactive";
|
|
3
|
+
import { bus } from "../bus";
|
|
4
|
+
// ── Route sentinels ──
|
|
5
|
+
// Used with @prop shorthand: @prop({params}) or @prop({query})
|
|
6
|
+
/** Sentinel for full route-param decompose: `@prop({params}) p!: MyType` */
|
|
7
|
+
export const params = Symbol("loom:sentinel:params");
|
|
8
|
+
/** Sentinel for full query-param decompose: `@prop({query}) q!: MyType` */
|
|
9
|
+
// NOTE: This is NOT the @query(".selector") DOM decorator — that's in dom.ts.
|
|
10
|
+
// This sentinel is re-exported from "@toyz/loom/router".
|
|
11
|
+
export const routeQuery = Symbol("loom:sentinel:query");
|
|
12
|
+
/**
|
|
13
|
+
* Internal reactive state. Creates a getter/setter backed by Reactive<T>.
|
|
14
|
+
* Changes schedule batched `update()` via microtask.
|
|
15
|
+
*
|
|
16
|
+
* ```ts
|
|
17
|
+
* @reactive count = 0;
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export function reactive(target, key) {
|
|
21
|
+
if (!target[REACTIVES])
|
|
22
|
+
target[REACTIVES] = [];
|
|
23
|
+
target[REACTIVES].push(key);
|
|
24
|
+
const storageKey = Symbol(key);
|
|
25
|
+
Object.defineProperty(target, key, {
|
|
26
|
+
get() {
|
|
27
|
+
return this[storageKey]?.value;
|
|
28
|
+
},
|
|
29
|
+
set(val) {
|
|
30
|
+
if (!this[storageKey]) {
|
|
31
|
+
// First set (from field initializer)
|
|
32
|
+
const r = new Reactive(val);
|
|
33
|
+
this[storageKey] = r;
|
|
34
|
+
r.subscribe(() => this.scheduleUpdate?.());
|
|
35
|
+
// Wire @watch handlers for this field
|
|
36
|
+
for (const w of (this[WATCHERS] ?? []).filter((w) => w.field === key)) {
|
|
37
|
+
r.subscribe((v, prev) => this[w.key](v, prev));
|
|
38
|
+
}
|
|
39
|
+
// Wire @emit handlers for this field
|
|
40
|
+
for (const e of (this[EMITTERS] ?? []).filter((e) => e.field === key)) {
|
|
41
|
+
r.subscribe((v) => bus.emit(e.factory(v)));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
this[storageKey].set(val);
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
enumerable: true,
|
|
49
|
+
configurable: true,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* External attribute. Observed HTML attribute that auto-parses from strings.
|
|
54
|
+
* Uses @reactive under the hood.
|
|
55
|
+
*
|
|
56
|
+
* Bare decorator:
|
|
57
|
+
* ```ts
|
|
58
|
+
* @prop label = "Count"; // <my-counter label="Clicks">
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* Route param injection:
|
|
62
|
+
* ```ts
|
|
63
|
+
* @prop({ param: "id" }) userId!: string; // single param
|
|
64
|
+
* @prop({params}) params!: MyParamType; // full decompose
|
|
65
|
+
* @prop({ query: "tab" }) activeTab!: string; // single query param
|
|
66
|
+
* @prop({query: routeQuery}) query!: MyQuery; // full query decompose
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export function prop(targetOrOpts, key) {
|
|
70
|
+
if (typeof key === "string") {
|
|
71
|
+
// Bare @prop — existing behavior
|
|
72
|
+
_registerProp(targetOrOpts, key);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
// @prop({ param: "id" }) or @prop({params}) etc.
|
|
76
|
+
const opts = targetOrOpts;
|
|
77
|
+
return (target, propKey) => {
|
|
78
|
+
// Store route binding metadata on the constructor
|
|
79
|
+
const ctor = target.constructor;
|
|
80
|
+
if (!ctor[ROUTE_PROPS])
|
|
81
|
+
ctor[ROUTE_PROPS] = [];
|
|
82
|
+
const binding = { propKey };
|
|
83
|
+
if (opts.params)
|
|
84
|
+
binding.params = opts.params;
|
|
85
|
+
if (opts.param)
|
|
86
|
+
binding.param = opts.param;
|
|
87
|
+
if (opts.query)
|
|
88
|
+
binding.query = opts.query;
|
|
89
|
+
ctor[ROUTE_PROPS].push(binding);
|
|
90
|
+
// Wire @reactive so changes trigger re-renders
|
|
91
|
+
reactive(target, propKey);
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/** Register a bare @prop (attribute-observed reactive) */
|
|
95
|
+
function _registerProp(target, key) {
|
|
96
|
+
if (!target.constructor[PROPS])
|
|
97
|
+
target.constructor[PROPS] = new Map();
|
|
98
|
+
target.constructor[PROPS].set(key.toLowerCase(), key);
|
|
99
|
+
reactive(target, key);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Cached derived value. Re-computed only when reactive dependencies fire.
|
|
103
|
+
*
|
|
104
|
+
* ```ts
|
|
105
|
+
* @computed
|
|
106
|
+
* get displayName() { return `${this.firstName} ${this.lastName}`; }
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
export function computed(target, key, desc) {
|
|
110
|
+
const getter = desc.get;
|
|
111
|
+
const cacheKey = Symbol(`computed:${key}`);
|
|
112
|
+
const dirtyKey = Symbol(`dirty:${key}`);
|
|
113
|
+
desc.get = function () {
|
|
114
|
+
if (this[dirtyKey] !== false) {
|
|
115
|
+
this[cacheKey] = getter.call(this);
|
|
116
|
+
this[dirtyKey] = false;
|
|
117
|
+
}
|
|
118
|
+
return this[cacheKey];
|
|
119
|
+
};
|
|
120
|
+
// Track the dirty key so scheduleUpdate can dirty all computed properties
|
|
121
|
+
if (!target[COMPUTED_DIRTY])
|
|
122
|
+
target[COMPUTED_DIRTY] = [];
|
|
123
|
+
target[COMPUTED_DIRTY].push(dirtyKey);
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/decorators/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC9F,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAE7B,wBAAwB;AACxB,+DAA+D;AAE/D,4EAA4E;AAC5E,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,sBAAsB,CAAC,CAAC;AAErD,2EAA2E;AAC3E,8EAA8E;AAC9E,yDAAyD;AACzD,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,qBAAqB,CAAC,CAAC;AAExD;;;;;;;GAOG;AACH,MAAM,UAAU,QAAQ,CAAC,MAAW,EAAE,GAAW;IAC/C,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;QAAE,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;IAC/C,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE5B,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAE/B,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE;QACjC,GAAG;YACD,OAAQ,IAAI,CAAC,UAAU,CAAmB,EAAE,KAAK,CAAC;QACpD,CAAC;QACD,GAAG,CAAC,GAAQ;YACV,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;gBACtB,qCAAqC;gBACrC,MAAM,CAAC,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC;gBAC5B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;gBACrB,CAAC,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;gBAE3C,sCAAsC;gBACtC,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAC3C,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,GAAG,CAC5B,EAAE,CAAC;oBACF,CAAC,CAAC,SAAS,CAAC,CAAC,CAAM,EAAE,IAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;gBAC3D,CAAC;gBAED,qCAAqC;gBACrC,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAC3C,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,GAAG,CAC5B,EAAE,CAAC;oBACF,CAAC,CAAC,SAAS,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAClD,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;QACD,UAAU,EAAE,IAAI;QAChB,YAAY,EAAE,IAAI;KACnB,CAAC,CAAC;AACL,CAAC;AAiBD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,IAAI,CAClB,YAAiB,EACjB,GAAS;IAET,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,iCAAiC;QACjC,aAAa,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;QACjC,OAAO;IACT,CAAC;IAED,iDAAiD;IACjD,MAAM,IAAI,GAAG,YAA6B,CAAC;IAC3C,OAAO,CAAC,MAAW,EAAE,OAAe,EAAE,EAAE;QACtC,kDAAkD;QAClD,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC;QAChC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC;YAAE,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC;QAE/C,MAAM,OAAO,GAAiB,EAAE,OAAO,EAAE,CAAC;QAC1C,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC9C,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QAC3C,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QAC3C,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAEhC,+CAA+C;QAC/C,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5B,CAAC,CAAC;AACJ,CAAC;AAED,0DAA0D;AAC1D,SAAS,aAAa,CAAC,MAAW,EAAE,GAAW;IAC7C,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC;QAAE,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;IACtE,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,GAAG,CAAC,CAAC;IACtD,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AACxB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,QAAQ,CACtB,MAAW,EACX,GAAW,EACX,IAAwB;IAExB,MAAM,MAAM,GAAG,IAAI,CAAC,GAAI,CAAC;IACzB,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,GAAG,EAAE,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,GAAG,EAAE,CAAC,CAAC;IAExC,IAAI,CAAC,GAAG,GAAG;QACT,IAAK,IAAY,CAAC,QAAQ,CAAC,KAAK,KAAK,EAAE,CAAC;YACrC,IAAY,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC3C,IAAY,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC;QAClC,CAAC;QACD,OAAQ,IAAY,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC,CAAC;IAEF,0EAA0E;IAC1E,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC;QAAE,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,CAAC;IACzD,MAAM,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACxC,CAAC"}
|