@praxisjs/decorators 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/dist/__tests__/ref.test.d.ts +2 -0
- package/dist/__tests__/ref.test.d.ts.map +1 -0
- package/dist/__tests__/ref.test.js +106 -0
- package/dist/__tests__/ref.test.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/properties/index.d.ts +1 -0
- package/dist/properties/index.d.ts.map +1 -1
- package/dist/properties/index.js +1 -0
- package/dist/properties/index.js.map +1 -1
- package/dist/properties/ref.d.ts +7 -0
- package/dist/properties/ref.d.ts.map +1 -0
- package/dist/properties/ref.js +21 -0
- package/dist/properties/ref.js.map +1 -0
- package/package.json +2 -2
- package/src/__tests__/ref.test.ts +131 -0
- package/src/index.ts +2 -0
- package/src/properties/index.ts +1 -0
- package/src/properties/ref.ts +27 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @praxisjs/decorators
|
|
2
2
|
|
|
3
|
+
## 1.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- bcaad96: Add `@Ref<T>()` decorator, `createRef<T>()` helper, and `Ref<T>` type for typed DOM element refs.
|
|
8
|
+
|
|
9
|
+
Replaces the manual `{ current: null as T | null }` field with a decorator that produces a callable ref — pass it directly to the JSX `ref` prop and read `.current` to access the element. Works transparently with `@Compose` via the existing string-name resolution. Use `createRef<T>()` for module-level refs outside of classes.
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [376e38c]
|
|
14
|
+
- @praxisjs/core@1.8.2
|
|
15
|
+
|
|
16
|
+
## 1.3.1
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- Updated dependencies [dc031d0]
|
|
21
|
+
- @praxisjs/core@1.8.1
|
|
22
|
+
|
|
3
23
|
## 1.3.0
|
|
4
24
|
|
|
5
25
|
### Minor Changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ref.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ref.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
import { describe, it, expect } from "vitest";
|
|
3
|
+
import { StatefulComponent } from "@praxisjs/core";
|
|
4
|
+
import { Ref, createRef } from "../properties/ref";
|
|
5
|
+
function fieldCtx(name) {
|
|
6
|
+
const initializers = [];
|
|
7
|
+
return {
|
|
8
|
+
ctx: {
|
|
9
|
+
name,
|
|
10
|
+
kind: "field",
|
|
11
|
+
addInitializer(fn) {
|
|
12
|
+
initializers.push(fn);
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
run(instance) {
|
|
16
|
+
initializers.forEach((fn) => { fn.call(instance); });
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
class TestComponent extends StatefulComponent {
|
|
21
|
+
render() { return null; }
|
|
22
|
+
}
|
|
23
|
+
describe("Ref decorator", () => {
|
|
24
|
+
it("initializes .current to null", () => {
|
|
25
|
+
const { ctx, run } = fieldCtx("elRef");
|
|
26
|
+
Ref()(undefined, ctx);
|
|
27
|
+
const instance = new TestComponent();
|
|
28
|
+
run(instance);
|
|
29
|
+
const ref = instance.elRef;
|
|
30
|
+
expect(ref.current).toBeNull();
|
|
31
|
+
});
|
|
32
|
+
it("is callable and sets .current", () => {
|
|
33
|
+
const { ctx, run } = fieldCtx("elRef");
|
|
34
|
+
Ref()(undefined, ctx);
|
|
35
|
+
const instance = new TestComponent();
|
|
36
|
+
run(instance);
|
|
37
|
+
const ref = instance.elRef;
|
|
38
|
+
const fakeEl = document.createElement("div");
|
|
39
|
+
ref(fakeEl);
|
|
40
|
+
expect(ref.current).toBe(fakeEl);
|
|
41
|
+
});
|
|
42
|
+
it("calling with null clears .current", () => {
|
|
43
|
+
const { ctx, run } = fieldCtx("elRef");
|
|
44
|
+
Ref()(undefined, ctx);
|
|
45
|
+
const instance = new TestComponent();
|
|
46
|
+
run(instance);
|
|
47
|
+
const ref = instance.elRef;
|
|
48
|
+
const fakeEl = document.createElement("div");
|
|
49
|
+
ref(fakeEl);
|
|
50
|
+
expect(ref.current).toBe(fakeEl);
|
|
51
|
+
ref(null);
|
|
52
|
+
expect(ref.current).toBeNull();
|
|
53
|
+
});
|
|
54
|
+
it("returns the same ref object on every access", () => {
|
|
55
|
+
const { ctx, run } = fieldCtx("elRef");
|
|
56
|
+
Ref()(undefined, ctx);
|
|
57
|
+
const instance = new TestComponent();
|
|
58
|
+
run(instance);
|
|
59
|
+
const inst = instance;
|
|
60
|
+
expect(inst.elRef).toBe(inst.elRef);
|
|
61
|
+
});
|
|
62
|
+
it("each instance gets its own independent ref", () => {
|
|
63
|
+
const { ctx: ctx1, run: run1 } = fieldCtx("elRef");
|
|
64
|
+
const { ctx: ctx2, run: run2 } = fieldCtx("elRef");
|
|
65
|
+
Ref()(undefined, ctx1);
|
|
66
|
+
Ref()(undefined, ctx2);
|
|
67
|
+
const a = new TestComponent();
|
|
68
|
+
const b = new TestComponent();
|
|
69
|
+
run1(a);
|
|
70
|
+
run2(b);
|
|
71
|
+
const refA = a.elRef;
|
|
72
|
+
const refB = b.elRef;
|
|
73
|
+
const el = document.createElement("div");
|
|
74
|
+
refA(el);
|
|
75
|
+
expect(refA.current).toBe(el);
|
|
76
|
+
expect(refB.current).toBeNull();
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
describe("createRef", () => {
|
|
80
|
+
it("initializes .current to null", () => {
|
|
81
|
+
const ref = createRef();
|
|
82
|
+
expect(ref.current).toBeNull();
|
|
83
|
+
});
|
|
84
|
+
it("is callable and sets .current", () => {
|
|
85
|
+
const ref = createRef();
|
|
86
|
+
const el = document.createElement("div");
|
|
87
|
+
ref(el);
|
|
88
|
+
expect(ref.current).toBe(el);
|
|
89
|
+
});
|
|
90
|
+
it("calling with null clears .current", () => {
|
|
91
|
+
const ref = createRef();
|
|
92
|
+
const el = document.createElement("div");
|
|
93
|
+
ref(el);
|
|
94
|
+
ref(null);
|
|
95
|
+
expect(ref.current).toBeNull();
|
|
96
|
+
});
|
|
97
|
+
it("each call creates an independent ref", () => {
|
|
98
|
+
const a = createRef();
|
|
99
|
+
const b = createRef();
|
|
100
|
+
const el = document.createElement("div");
|
|
101
|
+
a(el);
|
|
102
|
+
expect(a.current).toBe(el);
|
|
103
|
+
expect(b.current).toBeNull();
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
//# sourceMappingURL=ref.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ref.test.js","sourceRoot":"","sources":["../../src/__tests__/ref.test.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { Component, Lazy } from "./component";
|
|
2
2
|
export { Memo, Bind, Log, Once, Retry, Debounce, Throttle, When, Until, Watch, type WatchVal, type WatchVals, } from "./functions";
|
|
3
|
-
export { Prop, State, Computed, Persisted, Slot, initSlots, History, type HistoryOf, Compose, getter, Resource, invalidateResource, type ResourceInstance, type ResourceOptions, Synced, DeepState, } from "./properties";
|
|
3
|
+
export { Prop, State, Computed, Persisted, Slot, initSlots, History, type HistoryOf, Compose, getter, Resource, invalidateResource, type ResourceInstance, type ResourceOptions, Synced, DeepState, Ref, createRef, } from "./properties";
|
|
4
4
|
export { type Command, createCommand, Emit, OnCommand } from "./events";
|
|
5
5
|
export { createFieldDecorator, type FieldBehavior, type FieldBinding, } from "./create-field-decorator";
|
|
6
6
|
export { type ReactiveHost } from "./reactive-host";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EACL,IAAI,EACJ,IAAI,EACJ,GAAG,EACH,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,KAAK,EACL,KAAK,QAAQ,EACb,KAAK,SAAS,GACf,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,SAAS,EACT,OAAO,EACP,KAAK,SAAS,EACd,OAAO,EACP,MAAM,EACN,QAAQ,EACR,kBAAkB,EAClB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,MAAM,EACN,SAAS,GACV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,KAAK,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACxE,OAAO,EACL,oBAAoB,EACpB,KAAK,aAAa,EAClB,KAAK,YAAY,GAClB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,KAAK,gBAAgB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,qBAAqB,EACrB,KAAK,cAAc,GACpB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,8BAA8B,EAC9B,KAAK,uBAAuB,GAC7B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,qBAAqB,EACrB,KAAK,cAAc,EACnB,6BAA6B,EAC7B,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,6BAA6B,EAC7B,KAAK,sBAAsB,GAC5B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,uBAAuB,EACvB,KAAK,gBAAgB,EACrB,KAAK,eAAe,GACrB,MAAM,6BAA6B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EACL,IAAI,EACJ,IAAI,EACJ,GAAG,EACH,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,KAAK,EACL,KAAK,QAAQ,EACb,KAAK,SAAS,GACf,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,SAAS,EACT,OAAO,EACP,KAAK,SAAS,EACd,OAAO,EACP,MAAM,EACN,QAAQ,EACR,kBAAkB,EAClB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,MAAM,EACN,SAAS,EACT,GAAG,EACH,SAAS,GACV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,KAAK,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACxE,OAAO,EACL,oBAAoB,EACpB,KAAK,aAAa,EAClB,KAAK,YAAY,GAClB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,KAAK,gBAAgB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,qBAAqB,EACrB,KAAK,cAAc,GACpB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,8BAA8B,EAC9B,KAAK,uBAAuB,GAC7B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,qBAAqB,EACrB,KAAK,cAAc,EACnB,6BAA6B,EAC7B,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,6BAA6B,EAC7B,KAAK,sBAAsB,GAC5B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,uBAAuB,EACvB,KAAK,gBAAgB,EACrB,KAAK,eAAe,GACrB,MAAM,6BAA6B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { Component, Lazy } from "./component";
|
|
2
2
|
export { Memo, Bind, Log, Once, Retry, Debounce, Throttle, When, Until, Watch, } from "./functions";
|
|
3
|
-
export { Prop, State, Computed, Persisted, Slot, initSlots, History, Compose, getter, Resource, invalidateResource, Synced, DeepState, } from "./properties";
|
|
3
|
+
export { Prop, State, Computed, Persisted, Slot, initSlots, History, Compose, getter, Resource, invalidateResource, Synced, DeepState, Ref, createRef, } from "./properties";
|
|
4
4
|
export { createCommand, Emit, OnCommand } from "./events";
|
|
5
5
|
export { createFieldDecorator, } from "./create-field-decorator";
|
|
6
6
|
export { createClassDecorator, ClassBehavior, } from "./create-class-decorator";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EACL,IAAI,EACJ,IAAI,EACJ,GAAG,EACH,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,KAAK,GAGN,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,SAAS,EACT,OAAO,EAEP,OAAO,EACP,MAAM,EACN,QAAQ,EACR,kBAAkB,EAGlB,MAAM,EACN,SAAS,GACV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAgB,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACxE,OAAO,EACL,oBAAoB,GAGrB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,oBAAoB,EACpB,aAAa,GAEd,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,qBAAqB,GAEtB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,8BAA8B,GAE/B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,qBAAqB,EAErB,6BAA6B,EAG7B,6BAA6B,GAE9B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,uBAAuB,GAGxB,MAAM,6BAA6B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EACL,IAAI,EACJ,IAAI,EACJ,GAAG,EACH,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,KAAK,GAGN,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,SAAS,EACT,OAAO,EAEP,OAAO,EACP,MAAM,EACN,QAAQ,EACR,kBAAkB,EAGlB,MAAM,EACN,SAAS,EACT,GAAG,EACH,SAAS,GACV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAgB,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACxE,OAAO,EACL,oBAAoB,GAGrB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,oBAAoB,EACpB,aAAa,GAEd,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,qBAAqB,GAEtB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,8BAA8B,GAE/B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,qBAAqB,EAErB,6BAA6B,EAG7B,6BAA6B,GAE9B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,uBAAuB,GAGxB,MAAM,6BAA6B,CAAC"}
|
|
@@ -8,4 +8,5 @@ export { Compose, getter } from "./compose";
|
|
|
8
8
|
export { Resource, invalidateResource, type ResourceInstance, type ResourceOptions } from "./resource";
|
|
9
9
|
export { Synced } from "./synced";
|
|
10
10
|
export { DeepState } from "./deep-state";
|
|
11
|
+
export { Ref, createRef } from "./ref";
|
|
11
12
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/properties/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AACvG,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/properties/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AACvG,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC"}
|
package/dist/properties/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/properties/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAE,OAAO,EAAkB,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAA+C,MAAM,YAAY,CAAC;AACvG,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/properties/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAE,OAAO,EAAkB,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAA+C,MAAM,YAAY,CAAC;AACvG,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type Ref<T extends Element = Element> = ((el: T | null) => void) & {
|
|
2
|
+
current: T | null;
|
|
3
|
+
};
|
|
4
|
+
/** Creates a standalone ref object for use outside of class fields (e.g. module-level or passed to @Lazy). */
|
|
5
|
+
export declare function createRef<T extends Element = Element>(): Ref<T>;
|
|
6
|
+
export declare function Ref<T extends Element = Element>(): <This extends import("@praxisjs/core").StatefulComponent, Value = unknown>(_value: undefined, context: ClassFieldDecoratorContext<This, Value>) => void;
|
|
7
|
+
//# sourceMappingURL=ref.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ref.d.ts","sourceRoot":"","sources":["../../src/properties/ref.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,GAAG,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC,GAAG;IACxE,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC;CACnB,CAAC;AAEF,8GAA8G;AAE9G,wBAAgB,SAAS,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAM/D;AAGD,wBAAgB,GAAG,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,6JAS9C"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createFieldDecorator } from "../create-field-decorator";
|
|
2
|
+
/** Creates a standalone ref object for use outside of class fields (e.g. module-level or passed to @Lazy). */
|
|
3
|
+
export function createRef() {
|
|
4
|
+
function refFn(el) {
|
|
5
|
+
refFn.current = el;
|
|
6
|
+
}
|
|
7
|
+
refFn.current = null;
|
|
8
|
+
return refFn;
|
|
9
|
+
}
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
|
|
11
|
+
export function Ref() {
|
|
12
|
+
return createFieldDecorator({
|
|
13
|
+
bind(_instance, _name, _initialValue) {
|
|
14
|
+
const ref = createRef();
|
|
15
|
+
return {
|
|
16
|
+
descriptor: { get: () => ref },
|
|
17
|
+
};
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=ref.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ref.js","sourceRoot":"","sources":["../../src/properties/ref.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAMjE,8GAA8G;AAE9G,MAAM,UAAU,SAAS;IACvB,SAAS,KAAK,CAAC,EAAY;QACxB,KAAgB,CAAC,OAAO,GAAG,EAAE,CAAC;IACjC,CAAC;IACA,KAAgB,CAAC,OAAO,GAAG,IAAI,CAAC;IACjC,OAAO,KAAe,CAAC;AACzB,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,GAAG;IACjB,OAAO,oBAAoB,CAAC;QAC1B,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,aAAa;YAClC,MAAM,GAAG,GAAG,SAAS,EAAK,CAAC;YAC3B,OAAO;gBACL,UAAU,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE;aAC/B,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxisjs/decorators",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"typescript": "^5.9.3"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@praxisjs/core": "1.8.
|
|
18
|
+
"@praxisjs/core": "1.8.2",
|
|
19
19
|
"@praxisjs/shared": "0.3.0"
|
|
20
20
|
},
|
|
21
21
|
"scripts": {
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
import { describe, it, expect } from "vitest";
|
|
3
|
+
|
|
4
|
+
import { StatefulComponent } from "@praxisjs/core";
|
|
5
|
+
import { Ref, createRef } from "../properties/ref";
|
|
6
|
+
|
|
7
|
+
function fieldCtx(name: string) {
|
|
8
|
+
const initializers: Array<(this: unknown) => void> = [];
|
|
9
|
+
return {
|
|
10
|
+
ctx: {
|
|
11
|
+
name,
|
|
12
|
+
kind: "field" as const,
|
|
13
|
+
addInitializer(fn: (this: unknown) => void) {
|
|
14
|
+
initializers.push(fn);
|
|
15
|
+
},
|
|
16
|
+
} as ClassFieldDecoratorContext,
|
|
17
|
+
run(instance: unknown) {
|
|
18
|
+
initializers.forEach((fn) => { fn.call(instance); });
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
class TestComponent extends StatefulComponent {
|
|
24
|
+
render() { return null; }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
describe("Ref decorator", () => {
|
|
28
|
+
it("initializes .current to null", () => {
|
|
29
|
+
const { ctx, run } = fieldCtx("elRef");
|
|
30
|
+
Ref()(undefined, ctx);
|
|
31
|
+
|
|
32
|
+
const instance = new TestComponent();
|
|
33
|
+
run(instance);
|
|
34
|
+
|
|
35
|
+
const ref = (instance as unknown as Record<string, unknown>).elRef as { current: unknown };
|
|
36
|
+
expect(ref.current).toBeNull();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("is callable and sets .current", () => {
|
|
40
|
+
const { ctx, run } = fieldCtx("elRef");
|
|
41
|
+
Ref<HTMLDivElement>()(undefined, ctx);
|
|
42
|
+
|
|
43
|
+
const instance = new TestComponent();
|
|
44
|
+
run(instance);
|
|
45
|
+
|
|
46
|
+
const ref = (instance as unknown as Record<string, unknown>).elRef as ((el: HTMLDivElement | null) => void) & { current: HTMLDivElement | null };
|
|
47
|
+
const fakeEl = document.createElement("div") as HTMLDivElement;
|
|
48
|
+
ref(fakeEl);
|
|
49
|
+
|
|
50
|
+
expect(ref.current).toBe(fakeEl);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("calling with null clears .current", () => {
|
|
54
|
+
const { ctx, run } = fieldCtx("elRef");
|
|
55
|
+
Ref<HTMLDivElement>()(undefined, ctx);
|
|
56
|
+
|
|
57
|
+
const instance = new TestComponent();
|
|
58
|
+
run(instance);
|
|
59
|
+
|
|
60
|
+
const ref = (instance as unknown as Record<string, unknown>).elRef as ((el: HTMLDivElement | null) => void) & { current: HTMLDivElement | null };
|
|
61
|
+
const fakeEl = document.createElement("div") as HTMLDivElement;
|
|
62
|
+
ref(fakeEl);
|
|
63
|
+
expect(ref.current).toBe(fakeEl);
|
|
64
|
+
|
|
65
|
+
ref(null);
|
|
66
|
+
expect(ref.current).toBeNull();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("returns the same ref object on every access", () => {
|
|
70
|
+
const { ctx, run } = fieldCtx("elRef");
|
|
71
|
+
Ref()(undefined, ctx);
|
|
72
|
+
|
|
73
|
+
const instance = new TestComponent();
|
|
74
|
+
run(instance);
|
|
75
|
+
|
|
76
|
+
const inst = instance as unknown as Record<string, unknown>;
|
|
77
|
+
expect(inst.elRef).toBe(inst.elRef);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("each instance gets its own independent ref", () => {
|
|
81
|
+
const { ctx: ctx1, run: run1 } = fieldCtx("elRef");
|
|
82
|
+
const { ctx: ctx2, run: run2 } = fieldCtx("elRef");
|
|
83
|
+
Ref<HTMLDivElement>()(undefined, ctx1);
|
|
84
|
+
Ref<HTMLDivElement>()(undefined, ctx2);
|
|
85
|
+
|
|
86
|
+
const a = new TestComponent();
|
|
87
|
+
const b = new TestComponent();
|
|
88
|
+
run1(a);
|
|
89
|
+
run2(b);
|
|
90
|
+
|
|
91
|
+
const refA = (a as unknown as Record<string, unknown>).elRef as ((el: HTMLDivElement | null) => void) & { current: HTMLDivElement | null };
|
|
92
|
+
const refB = (b as unknown as Record<string, unknown>).elRef as ((el: HTMLDivElement | null) => void) & { current: HTMLDivElement | null };
|
|
93
|
+
|
|
94
|
+
const el = document.createElement("div") as HTMLDivElement;
|
|
95
|
+
refA(el);
|
|
96
|
+
|
|
97
|
+
expect(refA.current).toBe(el);
|
|
98
|
+
expect(refB.current).toBeNull();
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
describe("createRef", () => {
|
|
103
|
+
it("initializes .current to null", () => {
|
|
104
|
+
const ref = createRef<HTMLDivElement>();
|
|
105
|
+
expect(ref.current).toBeNull();
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("is callable and sets .current", () => {
|
|
109
|
+
const ref = createRef<HTMLDivElement>();
|
|
110
|
+
const el = document.createElement("div") as HTMLDivElement;
|
|
111
|
+
ref(el);
|
|
112
|
+
expect(ref.current).toBe(el);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("calling with null clears .current", () => {
|
|
116
|
+
const ref = createRef<HTMLDivElement>();
|
|
117
|
+
const el = document.createElement("div") as HTMLDivElement;
|
|
118
|
+
ref(el);
|
|
119
|
+
ref(null);
|
|
120
|
+
expect(ref.current).toBeNull();
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it("each call creates an independent ref", () => {
|
|
124
|
+
const a = createRef<HTMLDivElement>();
|
|
125
|
+
const b = createRef<HTMLDivElement>();
|
|
126
|
+
const el = document.createElement("div") as HTMLDivElement;
|
|
127
|
+
a(el);
|
|
128
|
+
expect(a.current).toBe(el);
|
|
129
|
+
expect(b.current).toBeNull();
|
|
130
|
+
});
|
|
131
|
+
});
|
package/src/index.ts
CHANGED
package/src/properties/index.ts
CHANGED
|
@@ -8,3 +8,4 @@ export { Compose, getter } from "./compose";
|
|
|
8
8
|
export { Resource, invalidateResource, type ResourceInstance, type ResourceOptions } from "./resource";
|
|
9
9
|
export { Synced } from "./synced";
|
|
10
10
|
export { DeepState } from "./deep-state";
|
|
11
|
+
export { Ref, createRef } from "./ref";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { createFieldDecorator } from "../create-field-decorator";
|
|
2
|
+
|
|
3
|
+
export type Ref<T extends Element = Element> = ((el: T | null) => void) & {
|
|
4
|
+
current: T | null;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
/** Creates a standalone ref object for use outside of class fields (e.g. module-level or passed to @Lazy). */
|
|
8
|
+
|
|
9
|
+
export function createRef<T extends Element = Element>(): Ref<T> {
|
|
10
|
+
function refFn(el: T | null): void {
|
|
11
|
+
(refFn as Ref<T>).current = el;
|
|
12
|
+
}
|
|
13
|
+
(refFn as Ref<T>).current = null;
|
|
14
|
+
return refFn as Ref<T>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
|
|
18
|
+
export function Ref<T extends Element = Element>() {
|
|
19
|
+
return createFieldDecorator({
|
|
20
|
+
bind(_instance, _name, _initialValue) {
|
|
21
|
+
const ref = createRef<T>();
|
|
22
|
+
return {
|
|
23
|
+
descriptor: { get: () => ref },
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
}
|