@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.
Files changed (127) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +108 -0
  3. package/dist/app.d.ts +70 -0
  4. package/dist/app.d.ts.map +1 -0
  5. package/dist/app.js +152 -0
  6. package/dist/app.js.map +1 -0
  7. package/dist/bus.d.ts +27 -0
  8. package/dist/bus.d.ts.map +1 -0
  9. package/dist/bus.js +41 -0
  10. package/dist/bus.js.map +1 -0
  11. package/dist/css.d.ts +25 -0
  12. package/dist/css.d.ts.map +1 -0
  13. package/dist/css.js +48 -0
  14. package/dist/css.js.map +1 -0
  15. package/dist/decorators/component.d.ts +11 -0
  16. package/dist/decorators/component.d.ts.map +1 -0
  17. package/dist/decorators/component.js +38 -0
  18. package/dist/decorators/component.js.map +1 -0
  19. package/dist/decorators/di.d.ts +37 -0
  20. package/dist/decorators/di.d.ts.map +1 -0
  21. package/dist/decorators/di.js +65 -0
  22. package/dist/decorators/di.js.map +1 -0
  23. package/dist/decorators/dom.d.ts +15 -0
  24. package/dist/decorators/dom.d.ts.map +1 -0
  25. package/dist/decorators/dom.js +33 -0
  26. package/dist/decorators/dom.js.map +1 -0
  27. package/dist/decorators/events.d.ts +46 -0
  28. package/dist/decorators/events.d.ts.map +1 -0
  29. package/dist/decorators/events.js +69 -0
  30. package/dist/decorators/events.js.map +1 -0
  31. package/dist/decorators/index.d.ts +18 -0
  32. package/dist/decorators/index.d.ts.map +1 -0
  33. package/dist/decorators/index.js +27 -0
  34. package/dist/decorators/index.js.map +1 -0
  35. package/dist/decorators/lifecycle.d.ts +49 -0
  36. package/dist/decorators/lifecycle.d.ts.map +1 -0
  37. package/dist/decorators/lifecycle.js +105 -0
  38. package/dist/decorators/lifecycle.js.map +1 -0
  39. package/dist/decorators/state.d.ts +41 -0
  40. package/dist/decorators/state.d.ts.map +1 -0
  41. package/dist/decorators/state.js +125 -0
  42. package/dist/decorators/state.js.map +1 -0
  43. package/dist/decorators/symbols.d.ts +13 -0
  44. package/dist/decorators/symbols.d.ts.map +1 -0
  45. package/dist/decorators/symbols.js +15 -0
  46. package/dist/decorators/symbols.js.map +1 -0
  47. package/dist/decorators/timing.d.ts +35 -0
  48. package/dist/decorators/timing.d.ts.map +1 -0
  49. package/dist/decorators/timing.js +57 -0
  50. package/dist/decorators/timing.js.map +1 -0
  51. package/dist/decorators/transform.d.ts +45 -0
  52. package/dist/decorators/transform.d.ts.map +1 -0
  53. package/dist/decorators/transform.js +48 -0
  54. package/dist/decorators/transform.js.map +1 -0
  55. package/dist/element.d.ts +62 -0
  56. package/dist/element.d.ts.map +1 -0
  57. package/dist/element.js +150 -0
  58. package/dist/element.js.map +1 -0
  59. package/dist/event.d.ts +24 -0
  60. package/dist/event.d.ts.map +1 -0
  61. package/dist/event.js +35 -0
  62. package/dist/event.js.map +1 -0
  63. package/dist/icon.d.ts +35 -0
  64. package/dist/icon.d.ts.map +1 -0
  65. package/dist/icon.js +119 -0
  66. package/dist/icon.js.map +1 -0
  67. package/dist/index.d.ts +29 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +34 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/jsx-dev-runtime.d.ts +8 -0
  72. package/dist/jsx-dev-runtime.d.ts.map +1 -0
  73. package/dist/jsx-dev-runtime.js +8 -0
  74. package/dist/jsx-dev-runtime.js.map +1 -0
  75. package/dist/jsx-runtime.d.ts +13 -0
  76. package/dist/jsx-runtime.d.ts.map +1 -0
  77. package/dist/jsx-runtime.js +101 -0
  78. package/dist/jsx-runtime.js.map +1 -0
  79. package/dist/morph.d.ts +23 -0
  80. package/dist/morph.d.ts.map +1 -0
  81. package/dist/morph.js +212 -0
  82. package/dist/morph.js.map +1 -0
  83. package/dist/reactive.d.ts +75 -0
  84. package/dist/reactive.d.ts.map +1 -0
  85. package/dist/reactive.js +133 -0
  86. package/dist/reactive.js.map +1 -0
  87. package/dist/render-loop.d.ts +34 -0
  88. package/dist/render-loop.d.ts.map +1 -0
  89. package/dist/render-loop.js +70 -0
  90. package/dist/render-loop.js.map +1 -0
  91. package/dist/router/events.d.ts +12 -0
  92. package/dist/router/events.d.ts.map +1 -0
  93. package/dist/router/events.js +17 -0
  94. package/dist/router/events.js.map +1 -0
  95. package/dist/router/index.d.ts +14 -0
  96. package/dist/router/index.d.ts.map +1 -0
  97. package/dist/router/index.js +18 -0
  98. package/dist/router/index.js.map +1 -0
  99. package/dist/router/link.d.ts +18 -0
  100. package/dist/router/link.d.ts.map +1 -0
  101. package/dist/router/link.js +75 -0
  102. package/dist/router/link.js.map +1 -0
  103. package/dist/router/mode.d.ts +33 -0
  104. package/dist/router/mode.d.ts.map +1 -0
  105. package/dist/router/mode.js +48 -0
  106. package/dist/router/mode.js.map +1 -0
  107. package/dist/router/outlet.d.ts +40 -0
  108. package/dist/router/outlet.d.ts.map +1 -0
  109. package/dist/router/outlet.js +171 -0
  110. package/dist/router/outlet.js.map +1 -0
  111. package/dist/router/route.d.ts +76 -0
  112. package/dist/router/route.d.ts.map +1 -0
  113. package/dist/router/route.js +147 -0
  114. package/dist/router/route.js.map +1 -0
  115. package/dist/router/router.d.ts +50 -0
  116. package/dist/router/router.d.ts.map +1 -0
  117. package/dist/router/router.js +140 -0
  118. package/dist/router/router.js.map +1 -0
  119. package/dist/storage.d.ts +55 -0
  120. package/dist/storage.d.ts.map +1 -0
  121. package/dist/storage.js +90 -0
  122. package/dist/storage.js.map +1 -0
  123. package/dist/virtual.d.ts +69 -0
  124. package/dist/virtual.d.ts.map +1 -0
  125. package/dist/virtual.js +247 -0
  126. package/dist/virtual.js.map +1 -0
  127. 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":"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"}