@praxisjs/decorators 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/component/component.d.ts +2 -2
  3. package/dist/component/component.d.ts.map +1 -1
  4. package/dist/component/component.js +5 -2
  5. package/dist/component/component.js.map +1 -1
  6. package/dist/component/index.d.ts +0 -1
  7. package/dist/component/index.d.ts.map +1 -1
  8. package/dist/component/index.js +0 -1
  9. package/dist/component/index.js.map +1 -1
  10. package/dist/component/lazy.d.ts +2 -2
  11. package/dist/component/lazy.d.ts.map +1 -1
  12. package/dist/component/lazy.js +8 -8
  13. package/dist/component/lazy.js.map +1 -1
  14. package/dist/component/virtual.d.ts +2 -2
  15. package/dist/component/virtual.d.ts.map +1 -1
  16. package/dist/component/virtual.js +45 -14
  17. package/dist/component/virtual.js.map +1 -1
  18. package/dist/events/emit.d.ts +2 -1
  19. package/dist/events/emit.d.ts.map +1 -1
  20. package/dist/events/emit.js +11 -16
  21. package/dist/events/emit.js.map +1 -1
  22. package/dist/events/helper.d.ts +2 -2
  23. package/dist/events/helper.d.ts.map +1 -1
  24. package/dist/events/helper.js.map +1 -1
  25. package/dist/events/on-command.d.ts +2 -1
  26. package/dist/events/on-command.d.ts.map +1 -1
  27. package/dist/events/on-command.js +30 -27
  28. package/dist/events/on-command.js.map +1 -1
  29. package/dist/functions/bind.d.ts +2 -1
  30. package/dist/functions/bind.d.ts.map +1 -1
  31. package/dist/functions/bind.js +10 -15
  32. package/dist/functions/bind.js.map +1 -1
  33. package/dist/functions/debounce.d.ts +2 -1
  34. package/dist/functions/debounce.d.ts.map +1 -1
  35. package/dist/functions/debounce.js +20 -24
  36. package/dist/functions/debounce.js.map +1 -1
  37. package/dist/functions/log.d.ts +2 -1
  38. package/dist/functions/log.d.ts.map +1 -1
  39. package/dist/functions/log.js +5 -6
  40. package/dist/functions/log.js.map +1 -1
  41. package/dist/functions/memo.d.ts +2 -1
  42. package/dist/functions/memo.d.ts.map +1 -1
  43. package/dist/functions/memo.js +5 -6
  44. package/dist/functions/memo.js.map +1 -1
  45. package/dist/functions/once.d.ts +2 -1
  46. package/dist/functions/once.d.ts.map +1 -1
  47. package/dist/functions/once.js +3 -5
  48. package/dist/functions/once.js.map +1 -1
  49. package/dist/functions/retry.d.ts +2 -1
  50. package/dist/functions/retry.d.ts.map +1 -1
  51. package/dist/functions/retry.js +3 -5
  52. package/dist/functions/retry.js.map +1 -1
  53. package/dist/functions/throttle.d.ts +2 -1
  54. package/dist/functions/throttle.d.ts.map +1 -1
  55. package/dist/functions/throttle.js +18 -22
  56. package/dist/functions/throttle.js.map +1 -1
  57. package/dist/functions/watch.d.ts +7 -7
  58. package/dist/functions/watch.d.ts.map +1 -1
  59. package/dist/functions/watch.js +31 -35
  60. package/dist/functions/watch.js.map +1 -1
  61. package/dist/functions/when.d.ts +2 -1
  62. package/dist/functions/when.d.ts.map +1 -1
  63. package/dist/functions/when.js +24 -24
  64. package/dist/functions/when.js.map +1 -1
  65. package/dist/index.d.ts +2 -2
  66. package/dist/index.d.ts.map +1 -1
  67. package/dist/index.js +2 -2
  68. package/dist/index.js.map +1 -1
  69. package/dist/properties/history.d.ts +3 -2
  70. package/dist/properties/history.d.ts.map +1 -1
  71. package/dist/properties/history.js +35 -27
  72. package/dist/properties/history.js.map +1 -1
  73. package/dist/properties/persisted.d.ts +3 -2
  74. package/dist/properties/persisted.d.ts.map +1 -1
  75. package/dist/properties/persisted.js +20 -23
  76. package/dist/properties/persisted.js.map +1 -1
  77. package/dist/properties/prop.d.ts +2 -1
  78. package/dist/properties/prop.d.ts.map +1 -1
  79. package/dist/properties/prop.js +24 -13
  80. package/dist/properties/prop.js.map +1 -1
  81. package/dist/properties/slot.d.ts +4 -8
  82. package/dist/properties/slot.d.ts.map +1 -1
  83. package/dist/properties/slot.js +34 -24
  84. package/dist/properties/slot.js.map +1 -1
  85. package/dist/properties/state.d.ts +2 -1
  86. package/dist/properties/state.d.ts.map +1 -1
  87. package/dist/properties/state.js +19 -19
  88. package/dist/properties/state.js.map +1 -1
  89. package/package.json +3 -4
  90. package/src/component/component.ts +9 -2
  91. package/src/component/index.ts +0 -1
  92. package/src/component/lazy.ts +10 -8
  93. package/src/component/virtual.tsx +71 -28
  94. package/src/events/emit.ts +15 -22
  95. package/src/events/helper.ts +5 -2
  96. package/src/events/on-command.ts +43 -44
  97. package/src/functions/bind.ts +14 -18
  98. package/src/functions/debounce.ts +23 -26
  99. package/src/functions/log.ts +11 -11
  100. package/src/functions/memo.ts +8 -9
  101. package/src/functions/once.ts +7 -10
  102. package/src/functions/retry.ts +7 -12
  103. package/src/functions/throttle.ts +21 -24
  104. package/src/functions/watch.ts +44 -48
  105. package/src/functions/when.ts +30 -32
  106. package/src/index.ts +10 -2
  107. package/src/properties/history.ts +49 -32
  108. package/src/properties/persisted.ts +40 -31
  109. package/src/properties/prop.ts +30 -13
  110. package/src/properties/slot.ts +46 -50
  111. package/src/properties/state.ts +24 -18
  112. package/dist/component/lifecycle.d.ts +0 -3
  113. package/dist/component/lifecycle.d.ts.map +0 -1
  114. package/dist/component/lifecycle.js +0 -35
  115. package/dist/component/lifecycle.js.map +0 -1
  116. package/dist/component/memoize.d.ts +0 -5
  117. package/dist/component/memoize.d.ts.map +0 -1
  118. package/dist/component/memoize.js +0 -23
  119. package/dist/component/memoize.js.map +0 -1
  120. package/src/component/lifecycle.ts +0 -47
  121. package/src/component/memoize.ts +0 -31
@@ -1,3 +1,4 @@
1
- import { type PersistedSignalOptions } from "@praxisjs/core";
2
- export declare function Persisted<T>(key?: string, options?: PersistedSignalOptions<T>): (target: object, propertyKey: string) => void;
1
+ import type { StatefulComponent } from "@praxisjs/core";
2
+ import { type PersistedSignalOptions } from "@praxisjs/core/internal";
3
+ export declare function Persisted<T>(key?: string, options?: PersistedSignalOptions<T>): (_value: undefined, context: ClassFieldDecoratorContext<StatefulComponent>) => void;
3
4
  //# sourceMappingURL=persisted.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"persisted.d.ts","sourceRoot":"","sources":["../../src/properties/persisted.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAsC9E,wBAAgB,SAAS,CAAC,CAAC,EACzB,GAAG,CAAC,EAAE,MAAM,EACZ,OAAO,GAAE,sBAAsB,CAAC,CAAC,CAAM,IAEtB,QAAQ,MAAM,EAAE,aAAa,MAAM,KAAG,IAAI,CAgC5D"}
1
+ {"version":3,"file":"persisted.d.ts","sourceRoot":"","sources":["../../src/properties/persisted.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,yBAAyB,CAAC;AAkCjC,wBAAgB,SAAS,CAAC,CAAC,EACzB,GAAG,CAAC,EAAE,MAAM,EACZ,OAAO,GAAE,sBAAsB,CAAC,CAAC,CAAM,IAGrC,QAAQ,SAAS,EACjB,SAAS,0BAA0B,CAAC,iBAAiB,CAAC,KACrD,IAAI,CAsCR"}
@@ -1,9 +1,6 @@
1
- import { persistedSignal } from "@praxisjs/core";
1
+ import { persistedSignal, } from "@praxisjs/core/internal";
2
2
  const signalMap = new WeakMap();
3
3
  const initMap = new WeakMap();
4
- function isInitialized(instance, propKey) {
5
- return initMap.get(instance)?.has(propKey) ?? false;
6
- }
7
4
  function markInitialized(instance, propKey) {
8
5
  if (!initMap.has(instance)) {
9
6
  initMap.set(instance, new Set());
@@ -21,25 +18,25 @@ function getOrCreateSignal(instance, storageKey, initialValue, options) {
21
18
  return map.get(storageKey);
22
19
  }
23
20
  export function Persisted(key, options = {}) {
24
- return function (target, propertyKey) {
25
- const storageKey = key ?? propertyKey;
26
- Object.defineProperty(target, propertyKey, {
27
- get() {
28
- if (!isInitialized(this, propertyKey)) {
29
- return undefined;
30
- }
31
- return getOrCreateSignal(this, storageKey, undefined, options)();
32
- },
33
- set(value) {
34
- if (!isInitialized(this, propertyKey)) {
35
- markInitialized(this, propertyKey);
36
- getOrCreateSignal(this, storageKey, value, options);
37
- return;
38
- }
39
- getOrCreateSignal(this, storageKey, undefined, options).set(value);
40
- },
41
- enumerable: true,
42
- configurable: true,
21
+ return function (_value, context) {
22
+ context.addInitializer(function () {
23
+ const instance = this;
24
+ const propertyKey = context.name;
25
+ const storageKey = key ?? propertyKey;
26
+ const initialValue = instance[propertyKey];
27
+ Reflect.deleteProperty(instance, propertyKey);
28
+ markInitialized(instance, propertyKey);
29
+ getOrCreateSignal(instance, storageKey, initialValue, options);
30
+ Object.defineProperty(instance, propertyKey, {
31
+ get() {
32
+ return getOrCreateSignal(instance, storageKey, undefined, options)();
33
+ },
34
+ set(value) {
35
+ getOrCreateSignal(instance, storageKey, undefined, options).set(value);
36
+ },
37
+ enumerable: true,
38
+ configurable: true,
39
+ });
43
40
  });
44
41
  };
45
42
  }
@@ -1 +1 @@
1
- {"version":3,"file":"persisted.js","sourceRoot":"","sources":["../../src/properties/persisted.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAA+B,MAAM,gBAAgB,CAAC;AAG9E,MAAM,SAAS,GAAG,IAAI,OAAO,EAAwC,CAAC;AACtE,MAAM,OAAO,GAAG,IAAI,OAAO,EAAuB,CAAC;AAEnD,SAAS,aAAa,CAAC,QAAgB,EAAE,OAAe;IACtD,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC;AACtD,CAAC;AAED,SAAS,eAAe,CAAC,QAAgB,EAAE,OAAe;IACxD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;IACnC,CAAC;IACA,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACtD,CAAC;AAED,SAAS,iBAAiB,CACxB,QAAgB,EAChB,UAAkB,EAClB,YAAe,EACf,OAAkC;IAElC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;IACrC,CAAC;IACD,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAiC,CAAC;IAEpE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;QACzB,GAAG,CAAC,GAAG,CACL,UAAU,EACV,eAAe,CAAC,UAAU,EAAE,YAAY,EAAE,OAAO,CAAoB,CACtE,CAAC;IACJ,CAAC;IAED,OAAO,GAAG,CAAC,GAAG,CAAC,UAAU,CAAc,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,SAAS,CACvB,GAAY,EACZ,UAAqC,EAAE;IAEvC,OAAO,UAAU,MAAc,EAAE,WAAmB;QAClD,MAAM,UAAU,GAAG,GAAG,IAAI,WAAW,CAAC;QAEtC,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE;YACzC,GAAG;gBACD,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,CAAC;oBACtC,OAAO,SAAc,CAAC;gBACxB,CAAC;gBAED,OAAO,iBAAiB,CACtB,IAAI,EACJ,UAAU,EACV,SAAc,EACd,OAAO,CACR,EAAE,CAAC;YACN,CAAC;YAED,GAAG,CAAe,KAAQ;gBACxB,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,CAAC;oBACtC,eAAe,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;oBACnC,iBAAiB,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;oBACpD,OAAO;gBACT,CAAC;gBACD,iBAAiB,CAAI,IAAI,EAAE,UAAU,EAAE,SAAc,EAAE,OAAO,CAAC,CAAC,GAAG,CACjE,KAAK,CACN,CAAC;YACJ,CAAC;YAED,UAAU,EAAE,IAAI;YAChB,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"persisted.js","sourceRoot":"","sources":["../../src/properties/persisted.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,GAEhB,MAAM,yBAAyB,CAAC;AAGjC,MAAM,SAAS,GAAG,IAAI,OAAO,EAAwC,CAAC;AACtE,MAAM,OAAO,GAAG,IAAI,OAAO,EAAuB,CAAC;AAEnD,SAAS,eAAe,CAAC,QAAgB,EAAE,OAAe;IACxD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;IACnC,CAAC;IACA,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACtD,CAAC;AAED,SAAS,iBAAiB,CACxB,QAAgB,EAChB,UAAkB,EAClB,YAAe,EACf,OAAkC;IAElC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;IACrC,CAAC;IACD,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAiC,CAAC;IAEpE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;QACzB,GAAG,CAAC,GAAG,CACL,UAAU,EACV,eAAe,CAAC,UAAU,EAAE,YAAY,EAAE,OAAO,CAAoB,CACtE,CAAC;IACJ,CAAC;IAED,OAAO,GAAG,CAAC,GAAG,CAAC,UAAU,CAAc,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,SAAS,CACvB,GAAY,EACZ,UAAqC,EAAE;IAEvC,OAAO,UACL,MAAiB,EACjB,OAAsD;QAEtD,OAAO,CAAC,cAAc,CAAC;YACrB,MAAM,QAAQ,GAAG,IAAc,CAAC;YAChC,MAAM,WAAW,GAAG,OAAO,CAAC,IAAc,CAAC;YAC3C,MAAM,UAAU,GAAG,GAAG,IAAI,WAAW,CAAC;YACtC,MAAM,YAAY,GAAI,QAAoC,CACxD,WAAW,CACP,CAAC;YAEP,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;YAE9C,eAAe,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;YACvC,iBAAiB,CAAC,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;YAE/D,MAAM,CAAC,cAAc,CAAC,QAAQ,EAAE,WAAW,EAAE;gBAC3C,GAAG;oBACD,OAAO,iBAAiB,CACtB,QAAQ,EACR,UAAU,EACV,SAAc,EACd,OAAO,CACR,EAAE,CAAC;gBACN,CAAC;gBAED,GAAG,CAAC,KAAQ;oBACV,iBAAiB,CACf,QAAQ,EACR,UAAU,EACV,SAAc,EACd,OAAO,CACR,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBACf,CAAC;gBAED,UAAU,EAAE,IAAI;gBAChB,YAAY,EAAE,IAAI;aACnB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
@@ -1,2 +1,3 @@
1
- export declare function Prop(): (target: object, propertyKey: string) => void;
1
+ import type { StatefulComponent } from "@praxisjs/core";
2
+ export declare function Prop(): (_value: undefined, context: ClassFieldDecoratorContext<StatefulComponent>) => void;
2
3
  //# sourceMappingURL=prop.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"prop.d.ts","sourceRoot":"","sources":["../../src/properties/prop.ts"],"names":[],"mappings":"AAEA,wBAAgB,IAAI,KACD,QAAQ,MAAM,EAAE,aAAa,MAAM,UAcrD"}
1
+ {"version":3,"file":"prop.d.ts","sourceRoot":"","sources":["../../src/properties/prop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAExD,wBAAgB,IAAI,KAEhB,QAAQ,SAAS,EACjB,SAAS,0BAA0B,CAAC,iBAAiB,CAAC,KACrD,IAAI,CA4BR"}
@@ -1,17 +1,28 @@
1
1
  export function Prop() {
2
- return function (target, propertyKey) {
3
- Object.defineProperty(target, propertyKey, {
4
- get() {
5
- const fromParent = this._rawProps[propertyKey];
6
- if (fromParent !== undefined)
7
- return fromParent;
8
- return this._defaults[propertyKey];
9
- },
10
- set(value) {
11
- this._defaults[propertyKey] = value;
12
- },
13
- enumerable: true,
14
- configurable: true,
2
+ return function (_value, context) {
3
+ context.addInitializer(function () {
4
+ const instance = this;
5
+ const name = context.name;
6
+ const raw = instance;
7
+ const defaultValue = raw[name];
8
+ Reflect.deleteProperty(raw, name);
9
+ instance._defaults[name] = defaultValue;
10
+ Object.defineProperty(instance, name, {
11
+ get() {
12
+ const fromParent = this._rawProps[name];
13
+ if (fromParent !== undefined) {
14
+ return typeof fromParent === "function"
15
+ ? fromParent()
16
+ : fromParent;
17
+ }
18
+ return this._defaults[name];
19
+ },
20
+ set(value) {
21
+ this._defaults[name] = value;
22
+ },
23
+ enumerable: true,
24
+ configurable: true,
25
+ });
15
26
  });
16
27
  };
17
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"prop.js","sourceRoot":"","sources":["../../src/properties/prop.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,IAAI;IAClB,OAAO,UAAU,MAAc,EAAE,WAAmB;QAClD,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE;YACzC,GAAG;gBACD,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;gBAC/C,IAAI,UAAU,KAAK,SAAS;oBAAE,OAAO,UAAU,CAAC;gBAChD,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;YACrC,CAAC;YACD,GAAG,CAAsB,KAAc;gBACrC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,KAAK,CAAC;YACtC,CAAC;YACD,UAAU,EAAE,IAAI;YAChB,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"prop.js","sourceRoot":"","sources":["../../src/properties/prop.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,IAAI;IAClB,OAAO,UACL,MAAiB,EACjB,OAAsD;QAEtD,OAAO,CAAC,cAAc,CAAC;YACrB,MAAM,QAAQ,GAAG,IAAyB,CAAC;YAC3C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAc,CAAC;YACpC,MAAM,GAAG,GAAG,QAA8C,CAAC;YAC3D,MAAM,YAAY,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;YAC/B,OAAO,CAAC,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAElC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC;YAExC,MAAM,CAAC,cAAc,CAAC,QAAQ,EAAE,IAAI,EAAE;gBACpC,GAAG;oBACD,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;oBACxC,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;wBAC7B,OAAO,OAAO,UAAU,KAAK,UAAU;4BACrC,CAAC,CAAE,UAA4B,EAAE;4BACjC,CAAC,CAAC,UAAU,CAAC;oBACjB,CAAC;oBACD,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;gBAC9B,CAAC;gBACD,GAAG,CAA0B,KAAc;oBACzC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;gBAC/B,CAAC;gBACD,UAAU,EAAE,IAAI;gBAChB,YAAY,EAAE,IAAI;aACnB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
@@ -1,9 +1,5 @@
1
- import { type Children, type ChildrenInternal, type VNode } from "@praxisjs/shared";
2
- export interface SlottedVNode extends VNode {
3
- slot?: string;
4
- }
5
- export declare function resolveSlots(children: ChildrenInternal | ChildrenInternal[] | undefined): Map<string, ChildrenInternal[]>;
6
- export declare function initSlots(instance: object, children: Children | undefined): void;
7
- export declare function getSlot(instance: object, name: string): ChildrenInternal[];
8
- export declare function Slot(name?: string): (target: object, propertyKey: string) => void;
1
+ import type { StatefulComponent } from "@praxisjs/core";
2
+ export declare function initSlots(instance: object, children: unknown): void;
3
+ export declare function getSlot(instance: object, name: string): unknown[];
4
+ export declare function Slot(name?: string): (_value: undefined, context: ClassFieldDecoratorContext<StatefulComponent>) => void;
9
5
  //# sourceMappingURL=slot.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"slot.d.ts","sourceRoot":"","sources":["../../src/properties/slot.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,gBAAgB,EAErB,KAAK,KAAK,EACX,MAAM,kBAAkB,CAAC;AAI1B,MAAM,WAAW,YAAa,SAAQ,KAAK;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,gBAAgB,GAAG,gBAAgB,EAAE,GAAG,SAAS,GAC1D,GAAG,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAuBjC;AAED,wBAAgB,SAAS,CACvB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,QAAQ,GAAG,SAAS,GAC7B,IAAI,CAEN;AAED,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAE1E;AAED,wBAAgB,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,IACf,QAAQ,MAAM,EAAE,aAAa,MAAM,KAAG,IAAI,CAqB5D"}
1
+ {"version":3,"file":"slot.d.ts","sourceRoot":"","sources":["../../src/properties/slot.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAgCxD,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI,CAEnE;AAED,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,CAEjE;AAED,wBAAgB,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,IAE9B,QAAQ,SAAS,EACjB,SAAS,0BAA0B,CAAC,iBAAiB,CAAC,KACrD,IAAI,CA0BR"}
@@ -1,22 +1,27 @@
1
- import { flattenChildren, } from "@praxisjs/shared";
2
1
  const slotsMap = new WeakMap();
3
- export function resolveSlots(children) {
2
+ function resolveSlots(children) {
4
3
  const slots = new Map();
5
4
  const defaultSlot = [];
6
5
  slots.set("default", defaultSlot);
7
- if (!children)
6
+ if (children == null)
8
7
  return slots;
9
- const arr = flattenChildren(children);
8
+ const arr = Array.isArray(children)
9
+ ? children.flat(Infinity)
10
+ : [children];
10
11
  for (const child of arr) {
11
- const slotName = child.props.slot ?? child.slot;
12
- if (slotName) {
13
- if (!slots.has(slotName))
14
- slots.set(slotName, []);
15
- slots.get(slotName).push(child);
12
+ // Named slots via `slot` attribute on DOM elements
13
+ if (child instanceof Element) {
14
+ const slotName = child.getAttribute("slot");
15
+ if (slotName) {
16
+ child.removeAttribute("slot");
17
+ if (!slots.has(slotName))
18
+ slots.set(slotName, []);
19
+ slots.get(slotName).push(child);
20
+ continue;
21
+ }
16
22
  }
17
- else {
23
+ if (child != null)
18
24
  defaultSlot.push(child);
19
- }
20
25
  }
21
26
  return slots;
22
27
  }
@@ -27,19 +32,24 @@ export function getSlot(instance, name) {
27
32
  return slotsMap.get(instance)?.get(name) ?? [];
28
33
  }
29
34
  export function Slot(name) {
30
- return function (target, propertyKey) {
31
- const slotName = name ?? (propertyKey === "default" ? "default" : propertyKey);
32
- Object.defineProperty(target, propertyKey, {
33
- get() {
34
- return getSlot(this, slotName);
35
- },
36
- set(_value) {
37
- if (process.env.NODE_ENV !== "production") {
38
- console.warn(`[Slot] "${propertyKey}" is a slot and cannot be assigned directly. Slots are filled by the parent component.`);
39
- }
40
- },
41
- enumerable: true,
42
- configurable: true,
35
+ return function (_value, context) {
36
+ context.addInitializer(function () {
37
+ const instance = this;
38
+ const propKey = context.name;
39
+ const slotName = name ?? (propKey === "default" ? "default" : propKey);
40
+ Reflect.deleteProperty(instance, propKey);
41
+ Object.defineProperty(instance, propKey, {
42
+ get() {
43
+ return getSlot(this, slotName);
44
+ },
45
+ set(_value) {
46
+ if (process.env.NODE_ENV !== "production") {
47
+ console.warn(`[Slot] "${propKey}" is a slot and cannot be assigned directly. Slots are filled by the parent component.`);
48
+ }
49
+ },
50
+ enumerable: true,
51
+ configurable: true,
52
+ });
43
53
  });
44
54
  };
45
55
  }
@@ -1 +1 @@
1
- {"version":3,"file":"slot.js","sourceRoot":"","sources":["../../src/properties/slot.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,eAAe,GAEhB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,QAAQ,GAAG,IAAI,OAAO,EAA2C,CAAC;AAMxE,MAAM,UAAU,YAAY,CAC1B,QAA2D;IAE3D,MAAM,KAAK,GAAG,IAAI,GAAG,EAA8B,CAAC;IACpD,MAAM,WAAW,GAAuB,EAAE,CAAC;IAC3C,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAElC,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAE5B,MAAM,GAAG,GAAuB,eAAe,CAAC,QAAQ,CAAC,CAAC;IAE1D,KAAK,MAAM,KAAK,IAAI,GAAqB,EAAE,CAAC;QAC1C,MAAM,QAAQ,GAAI,KAAK,CAAC,KAAK,CAAC,IAA2B,IAAI,KAAK,CAAC,IAAI,CAAC;QAExE,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAAE,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YACjD,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAwB,CAAC,IAAI,CAC9C,KAAyB,CAC1B,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,WAAW,CAAC,IAAI,CAAC,KAAyB,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,SAAS,CACvB,QAAgB,EAChB,QAA8B;IAE9B,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,QAAgB,EAAE,IAAY;IACpD,OAAO,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,IAAa;IAChC,OAAO,UAAU,MAAc,EAAE,WAAmB;QAClD,MAAM,QAAQ,GACZ,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;QAEhE,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE;YACzC,GAAG;gBACD,OAAO,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YACjC,CAAC;YAED,GAAG,CAAC,MAAe;gBACjB,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;oBAC1C,OAAO,CAAC,IAAI,CACV,WAAW,WAAW,wFAAwF,CAC/G,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,UAAU,EAAE,IAAI;YAChB,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"slot.js","sourceRoot":"","sources":["../../src/properties/slot.ts"],"names":[],"mappings":"AAEA,MAAM,QAAQ,GAAG,IAAI,OAAO,EAAkC,CAAC;AAE/D,SAAS,YAAY,CAAC,QAAiB;IACrC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAqB,CAAC;IAC3C,MAAM,WAAW,GAAc,EAAE,CAAC;IAClC,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAElC,IAAI,QAAQ,IAAI,IAAI;QAAE,OAAO,KAAK,CAAC;IAEnC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;QACjC,CAAC,CAAE,QAAsB,CAAC,IAAI,CAAC,QAAQ,CAAC;QACxC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAEf,KAAK,MAAM,KAAK,IAAI,GAAG,EAAE,CAAC;QACxB,mDAAmD;QACnD,IAAI,KAAK,YAAY,OAAO,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;YAC5C,IAAI,QAAQ,EAAE,CAAC;gBACb,KAAK,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;gBAC9B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;oBAAE,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;gBACjD,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC/C,SAAS;YACX,CAAC;QACH,CAAC;QACD,IAAI,KAAK,IAAI,IAAI;YAAE,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7C,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,QAAgB,EAAE,QAAiB;IAC3D,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,QAAgB,EAAE,IAAY;IACpD,OAAO,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,IAAa;IAChC,OAAO,UACL,MAAiB,EACjB,OAAsD;QAEtD,OAAO,CAAC,cAAc,CAAC;YACrB,MAAM,QAAQ,GAAG,IAAyB,CAAC;YAC3C,MAAM,OAAO,GAAG,OAAO,CAAC,IAAc,CAAC;YACvC,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YAEvE,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAE1C,MAAM,CAAC,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE;gBACvC,GAAG;oBACD,OAAO,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;gBACjC,CAAC;gBAED,GAAG,CAAC,MAAe;oBACjB,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;wBAC1C,OAAO,CAAC,IAAI,CACV,WAAW,OAAO,wFAAwF,CAC3G,CAAC;oBACJ,CAAC;gBACH,CAAC;gBAED,UAAU,EAAE,IAAI;gBAChB,YAAY,EAAE,IAAI;aACnB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
@@ -1,2 +1,3 @@
1
- export declare function State(): (target: object, propertyKey: string) => void;
1
+ import type { StatefulComponent } from "@praxisjs/core";
2
+ export declare function State(): (_value: undefined, context: ClassFieldDecoratorContext<StatefulComponent>) => void;
2
3
  //# sourceMappingURL=state.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/properties/state.ts"],"names":[],"mappings":"AAGA,wBAAgB,KAAK,KACF,QAAQ,MAAM,EAAE,aAAa,MAAM,UAmBrD"}
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/properties/state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGxD,wBAAgB,KAAK,KAEjB,QAAQ,SAAS,EACjB,SAAS,0BAA0B,CAAC,iBAAiB,CAAC,KACrD,IAAI,CAsBR"}
@@ -1,23 +1,23 @@
1
- import { signal } from "@praxisjs/core";
1
+ import { signal } from "@praxisjs/core/internal";
2
2
  export function State() {
3
- return function (target, propertyKey) {
4
- const signalMap = new WeakMap();
5
- Object.defineProperty(target, propertyKey, {
6
- get() {
7
- if (!signalMap.has(this))
8
- signalMap.set(this, signal(undefined));
9
- return signalMap.get(this)();
10
- },
11
- set(value) {
12
- if (!signalMap.has(this))
13
- signalMap.set(this, signal(value));
14
- else {
15
- this._stateDirty = true;
16
- signalMap.get(this).set(value);
17
- }
18
- },
19
- enumerable: true,
20
- configurable: true,
3
+ return function (_value, context) {
4
+ context.addInitializer(function () {
5
+ const instance = this;
6
+ const name = context.name;
7
+ const initialValue = instance[name];
8
+ Reflect.deleteProperty(instance, name);
9
+ const sig = signal(initialValue);
10
+ Object.defineProperty(instance, name, {
11
+ get() {
12
+ return sig();
13
+ },
14
+ set(value) {
15
+ instance._stateDirty = true;
16
+ sig.set(value);
17
+ },
18
+ enumerable: true,
19
+ configurable: true,
20
+ });
21
21
  });
22
22
  };
23
23
  }
@@ -1 +1 @@
1
- {"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/properties/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAGxC,MAAM,UAAU,KAAK;IACnB,OAAO,UAAU,MAAc,EAAE,WAAmB;QAClD,MAAM,SAAS,GAAG,IAAI,OAAO,EAA2B,CAAC;QAEzD,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE;YACzC,GAAG;gBACD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;oBAAE,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;gBACjE,OAAQ,SAAS,CAAC,GAAG,CAAC,IAAI,CAAqB,EAAE,CAAC;YACpD,CAAC;YACD,GAAG,CAAe,KAAc;gBAC9B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;oBAAE,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;qBACxD,CAAC;oBACH,IAA0B,CAAC,WAAW,GAAG,IAAI,CAAC;oBAC9C,SAAS,CAAC,GAAG,CAAC,IAAI,CAAqB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBACtD,CAAC;YACH,CAAC;YACD,UAAU,EAAE,IAAI;YAChB,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/properties/state.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEjD,MAAM,UAAU,KAAK;IACnB,OAAO,UACL,MAAiB,EACjB,OAAsD;QAEtD,OAAO,CAAC,cAAc,CAAC;YACrB,MAAM,QAAQ,GAAG,IAAmD,CAAC;YACrE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAc,CAAC;YACpC,MAAM,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YACpC,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAEvC,MAAM,GAAG,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;YAEjC,MAAM,CAAC,cAAc,CAAC,QAAQ,EAAE,IAAI,EAAE;gBACpC,GAAG;oBACD,OAAO,GAAG,EAAE,CAAC;gBACf,CAAC;gBACD,GAAG,CAAC,KAAc;oBAChB,QAAQ,CAAC,WAAW,GAAG,IAAI,CAAC;oBAC5B,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBACjB,CAAC;gBACD,UAAU,EAAE,IAAI;gBAChB,YAAY,EAAE,IAAI;aACnB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxisjs/decorators",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -15,9 +15,8 @@
15
15
  "typescript": "^5.9.3"
16
16
  },
17
17
  "dependencies": {
18
- "@praxisjs/core": "0.2.0",
19
- "@praxisjs/jsx": "0.1.0",
20
- "@praxisjs/shared": "0.1.0"
18
+ "@praxisjs/core": "0.3.0",
19
+ "@praxisjs/shared": "0.2.0"
21
20
  },
22
21
  "scripts": {
23
22
  "build": "tsc",
@@ -1,12 +1,19 @@
1
- import type { ComponentConstructor, ComponentInstance } from "@praxisjs/shared";
1
+ import { StatelessComponent } from "@praxisjs/core";
2
+ import type {
3
+ ComponentConstructor,
4
+ ComponentInstance,
5
+ } from "@praxisjs/shared/internal";
2
6
 
3
7
  export function Component() {
4
8
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
5
9
  return function <T extends new (...args: any[]) => ComponentInstance>(
6
10
  constructor: T,
11
+ _context: ClassDecoratorContext,
7
12
  ): T & ComponentConstructor {
13
+ const isStateless = constructor.prototype instanceof StatelessComponent;
8
14
  const Enhanced = class extends constructor {
9
- static isComponent = true as const;
15
+ static __isComponent = true as const;
16
+ static __isStateless = isStateless;
10
17
  } as unknown as T & ComponentConstructor;
11
18
 
12
19
  Object.defineProperty(Enhanced, "name", {
@@ -1,4 +1,3 @@
1
1
  export { Component } from "./component";
2
- export { Memoize } from "./memoize";
3
2
  export { Lazy } from "./lazy";
4
3
  export { Virtual } from "./virtual";
@@ -1,22 +1,24 @@
1
- import { type BaseComponent, signal } from "@praxisjs/core";
2
- import type { VNode } from "@praxisjs/shared";
1
+ import { type RootComponent, signal } from "@praxisjs/core/internal";
3
2
 
4
3
  export function Lazy(placeholder = 200) {
5
4
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
- return function <T extends new (...args: any[]) => BaseComponent>(
5
+ return function <T extends new (...args: any[]) => RootComponent>(
7
6
  constructor: T,
7
+ _context: ClassDecoratorContext,
8
8
  ): T {
9
9
  return class LazyWrapper extends constructor {
10
10
  private readonly _lazyVisible = signal(false);
11
11
  private _observer?: IntersectionObserver;
12
- private readonly _originalRender: () => VNode | null = this.render.bind(this);
12
+ private readonly _originalRender: () => Node | Node[] | null =
13
+ this.render.bind(this);
13
14
 
14
15
  onMount() {
15
16
  super.onMount?.();
16
17
 
17
- const el = document.querySelector<HTMLElement>(
18
- `[data-component="${constructor.name}"]`,
19
- );
18
+ // Use the end anchor to find the parent element
19
+ const el =
20
+ (this as unknown as { _anchor?: Comment })._anchor
21
+ ?.parentElement ?? null;
20
22
  if (!el) return;
21
23
 
22
24
  if (!("IntersectionObserver" in window)) {
@@ -47,7 +49,7 @@ export function Lazy(placeholder = 200) {
47
49
  this._observer?.disconnect();
48
50
  }
49
51
 
50
- render(): VNode | null {
52
+ render(): Node | Node[] | null {
51
53
  if (!this._lazyVisible()) return null;
52
54
  return this._originalRender();
53
55
  }
@@ -1,24 +1,30 @@
1
- import { type BaseComponent, computed, signal } from "@praxisjs/core";
2
- import type { VNode } from "@praxisjs/shared";
1
+ import { computed, effect, type RootComponent, signal } from "@praxisjs/core/internal";
2
+
3
+ interface VirtualHost {
4
+ _anchor?: Comment;
5
+ items?: unknown[];
6
+ renderItem(item: unknown, index: number): Node | Node[] | null;
7
+ }
3
8
 
4
9
  export function Virtual(itemHeight: number, buffer = 3) {
5
10
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
- return function <T extends new (...args: any[]) => BaseComponent>(
11
+ return function <T extends new (...args: any[]) => RootComponent>(
7
12
  constructor: T,
13
+ _context: ClassDecoratorContext,
8
14
  ): T {
9
15
  return class VirtualWrapper extends constructor {
10
16
  private readonly _scrollTop = signal(0);
11
17
  private readonly _viewHeight = signal(600);
12
18
  private _container?: HTMLElement;
13
19
  private _scrollHandler?: () => void;
20
+ private _cleanups: Array<() => void> = [];
14
21
 
15
22
  onMount() {
16
23
  super.onMount?.();
17
24
 
25
+ // Use the end anchor set by the runtime to locate the parent element
18
26
  this._container =
19
- document.querySelector<HTMLElement>(
20
- `[data-component="${constructor.name}"]`,
21
- ) ?? undefined;
27
+ (this as unknown as VirtualHost)._anchor?.parentElement ?? undefined;
22
28
 
23
29
  if (!this._container) return;
24
30
 
@@ -39,24 +45,25 @@ export function Virtual(itemHeight: number, buffer = 3) {
39
45
  if (this._container && this._scrollHandler) {
40
46
  this._container.removeEventListener("scroll", this._scrollHandler);
41
47
  }
48
+ this._cleanups.forEach((c) => { c(); });
49
+ this._cleanups = [];
42
50
  }
43
51
 
44
52
  render() {
45
- const instance = this as unknown as Record<string, unknown>;
46
- const items = (instance.items as unknown[] | undefined) ?? [];
53
+ const host = this as unknown as VirtualHost;
54
+ const items = host.items ?? [];
47
55
  const total = items.length;
48
56
  const totalH = total * itemHeight;
49
57
 
50
- const renderItem = instance.renderItem as
51
- | ((item: unknown, i: number) => VNode | null)
52
- | undefined;
53
- if (!renderItem) {
58
+ if (typeof host.renderItem !== "function") {
54
59
  console.warn(
55
60
  `[Virtual] ${constructor.name} must implement renderItem(item, index)`,
56
61
  );
57
62
  return null;
58
63
  }
59
64
 
65
+ const renderItem = host.renderItem.bind(host);
66
+
60
67
  const startIdx = computed(() => {
61
68
  const start = Math.floor(this._scrollTop() / itemHeight) - buffer;
62
69
  return Math.max(0, start);
@@ -70,7 +77,7 @@ export function Virtual(itemHeight: number, buffer = 3) {
70
77
  });
71
78
 
72
79
  const visibleItems = computed(() => {
73
- const result = [];
80
+ const result: Array<{ item: unknown; index: number }> = [];
74
81
  for (let i = startIdx(); i <= endIdx(); i++) {
75
82
  result.push({ item: items[i], index: i });
76
83
  }
@@ -82,22 +89,58 @@ export function Virtual(itemHeight: number, buffer = 3) {
82
89
  () => (total - 1 - endIdx()) * itemHeight,
83
90
  );
84
91
 
85
- return (
86
- <div style={`height:${String(totalH)}px; position:relative;`}>
87
- <div style={() => `height:${String(offsetTop())}px;`} />
88
- {() =>
89
- visibleItems().map(({ item, index }) => (
90
- <div
91
- key={String(index)}
92
- style={`height:${String(itemHeight)}px; overflow:hidden;`}
93
- >
94
- {renderItem.call(this, item, index)}
95
- </div>
96
- ))
92
+ const outer = document.createElement("div");
93
+ outer.setAttribute(
94
+ "style",
95
+ `height:${String(totalH)}px; position:relative;`,
96
+ );
97
+
98
+ const spacerTop = document.createElement("div");
99
+ this._cleanups.push(
100
+ effect(() => {
101
+ spacerTop.setAttribute("style", `height:${String(offsetTop())}px;`);
102
+ }),
103
+ );
104
+
105
+ const itemsSlot = document.createElement("div");
106
+ this._cleanups.push(
107
+ effect(() => {
108
+ while (itemsSlot.firstChild) {
109
+ itemsSlot.removeChild(itemsSlot.firstChild);
97
110
  }
98
- <div style={() => `height:${String(offsetBottom())}px;`} />
99
- </div>
100
- ) as unknown as VNode;
111
+ visibleItems().forEach(({ item, index }) => {
112
+ const wrapper = document.createElement("div");
113
+ wrapper.setAttribute(
114
+ "style",
115
+ `height:${String(itemHeight)}px; overflow:hidden;`,
116
+ );
117
+ const rendered = renderItem(item, index);
118
+ if (rendered) {
119
+ const nodes = (
120
+ Array.isArray(rendered) ? rendered.flat() : [rendered]
121
+ );
122
+ nodes.forEach((n) => wrapper.appendChild(n));
123
+ }
124
+ itemsSlot.appendChild(wrapper);
125
+ });
126
+ }),
127
+ );
128
+
129
+ const spacerBottom = document.createElement("div");
130
+ this._cleanups.push(
131
+ effect(() => {
132
+ spacerBottom.setAttribute(
133
+ "style",
134
+ `height:${String(offsetBottom())}px;`,
135
+ );
136
+ }),
137
+ );
138
+
139
+ outer.appendChild(spacerTop);
140
+ outer.appendChild(itemsSlot);
141
+ outer.appendChild(spacerBottom);
142
+
143
+ return outer;
101
144
  }
102
145
  } as unknown as T;
103
146
  };
@@ -1,20 +1,17 @@
1
- import type { BaseComponent } from "@praxisjs/core";
1
+ import type { StatefulComponent } from "@praxisjs/core";
2
2
 
3
3
  import { readProp } from "./helper";
4
4
 
5
5
  export function Emit(propName: string) {
6
6
  return function (
7
- _target: object,
8
- methodKey: string,
9
- descriptor: PropertyDescriptor,
10
- ): PropertyDescriptor {
11
- const originalMethod = descriptor.value as (...args: unknown[]) => unknown;
12
-
7
+ value: (this: StatefulComponent, ...args: unknown[]) => unknown,
8
+ context: ClassMethodDecoratorContext<StatefulComponent>,
9
+ ): void {
13
10
  const wrapped = function (
14
- this: BaseComponent,
11
+ this: StatefulComponent,
15
12
  ...args: unknown[]
16
13
  ): unknown {
17
- const result = originalMethod.apply(this, args);
14
+ const result = value.apply(this, args);
18
15
 
19
16
  const callback = readProp(this, propName);
20
17
  if (typeof callback !== "function") return result;
@@ -30,18 +27,14 @@ export function Emit(propName: string) {
30
27
  return result;
31
28
  };
32
29
 
33
- return {
34
- configurable: true,
35
- enumerable: false,
36
- get(this: BaseComponent) {
37
- const bound = wrapped.bind(this);
38
- Object.defineProperty(this, methodKey, {
39
- value: bound,
40
- configurable: true,
41
- writable: true,
42
- });
43
- return bound;
44
- },
45
- };
30
+ context.addInitializer(function (this: unknown) {
31
+ const name = context.name as string;
32
+ const bound = wrapped.bind(this as StatefulComponent);
33
+ Object.defineProperty(this as object, name, {
34
+ value: bound,
35
+ configurable: true,
36
+ writable: true,
37
+ });
38
+ });
46
39
  };
47
40
  }