@joist/templating 4.2.4-next.0 → 4.2.4-next.10
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/README.md +43 -164
- package/package.json +1 -1
- package/src/lib/bind.test.ts +72 -0
- package/src/lib/bind.ts +32 -9
- package/src/lib/define.ts +1 -0
- package/src/lib/elements/async.element.test.ts +90 -0
- package/src/lib/elements/async.element.ts +13 -2
- package/src/lib/elements/bind.element.test.ts +21 -2
- package/src/lib/elements/bind.element.ts +14 -17
- package/src/lib/elements/for.element.ts +16 -9
- package/src/lib/elements/if.element.test.ts +210 -0
- package/src/lib/elements/if.element.ts +16 -11
- package/src/lib/elements/scope.element.test.ts +32 -0
- package/src/lib/elements/scope.element.ts +19 -0
- package/src/lib/elements/value.element.test.ts +28 -0
- package/src/lib/elements/value.element.ts +9 -11
- package/src/lib/events.ts +10 -5
- package/src/lib/expression.test.ts +204 -0
- package/src/lib/expression.ts +179 -0
- package/target/lib/bind.d.ts +5 -1
- package/target/lib/bind.js +22 -8
- package/target/lib/bind.js.map +1 -1
- package/target/lib/bind.test.js +76 -0
- package/target/lib/bind.test.js.map +1 -0
- package/target/lib/define.d.ts +1 -0
- package/target/lib/define.js +1 -0
- package/target/lib/define.js.map +1 -1
- package/target/lib/elements/async.element.js +11 -2
- package/target/lib/elements/async.element.js.map +1 -1
- package/target/lib/elements/async.element.test.js +76 -0
- package/target/lib/elements/async.element.test.js.map +1 -1
- package/target/lib/elements/bind.element.d.ts +8 -3
- package/target/lib/elements/bind.element.js +11 -17
- package/target/lib/elements/bind.element.js.map +1 -1
- package/target/lib/elements/bind.element.test.js +18 -2
- package/target/lib/elements/bind.element.test.js.map +1 -1
- package/target/lib/elements/for.element.d.ts +1 -1
- package/target/lib/elements/for.element.js +13 -7
- package/target/lib/elements/for.element.js.map +1 -1
- package/target/lib/elements/if.element.js +12 -12
- package/target/lib/elements/if.element.js.map +1 -1
- package/target/lib/elements/if.element.test.js +184 -0
- package/target/lib/elements/if.element.test.js.map +1 -1
- package/target/lib/elements/scope.element.d.ts +8 -0
- package/target/lib/elements/scope.element.js +38 -0
- package/target/lib/elements/scope.element.js.map +1 -0
- package/target/lib/elements/scope.element.test.d.ts +2 -0
- package/target/lib/elements/scope.element.test.js +25 -0
- package/target/lib/elements/scope.element.test.js.map +1 -0
- package/target/lib/elements/value.element.js +7 -11
- package/target/lib/elements/value.element.js.map +1 -1
- package/target/lib/elements/value.element.test.js +24 -0
- package/target/lib/elements/value.element.test.js.map +1 -1
- package/target/lib/events.d.ts +8 -4
- package/target/lib/events.js +3 -3
- package/target/lib/events.js.map +1 -1
- package/target/lib/expression.d.ts +13 -0
- package/target/lib/expression.js +87 -0
- package/target/lib/expression.js.map +1 -0
- package/target/lib/expression.test.d.ts +1 -0
- package/target/lib/expression.test.js +171 -0
- package/target/lib/expression.test.js.map +1 -0
- package/src/lib/elements/scope.ts +0 -39
- package/src/lib/token.test.ts +0 -74
- package/src/lib/token.ts +0 -34
- package/target/lib/elements/scope.d.ts +0 -13
- package/target/lib/elements/scope.js +0 -56
- package/target/lib/elements/scope.js.map +0 -1
- package/target/lib/token.d.ts +0 -8
- package/target/lib/token.js +0 -27
- package/target/lib/token.js.map +0 -1
- package/target/lib/token.test.js +0 -56
- package/target/lib/token.test.js.map +0 -1
- /package/target/lib/{token.test.d.ts → bind.test.d.ts} +0 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { assert } from "chai";
|
|
2
|
+
|
|
3
|
+
import { JExpression } from "./expression.js";
|
|
4
|
+
|
|
5
|
+
describe("JExpression", () => {
|
|
6
|
+
describe("constructor", () => {
|
|
7
|
+
it("should initialize with a raw token", () => {
|
|
8
|
+
const token = new JExpression("example.token");
|
|
9
|
+
assert.equal(token.rawToken, "example.token");
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it("should set isNegated to true if the token starts with '!'", () => {
|
|
13
|
+
const token = new JExpression("!example.token");
|
|
14
|
+
assert.isTrue(token.isNegated);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("should set isNegated to false if the token does not start with '!'", () => {
|
|
18
|
+
const token = new JExpression("example.token");
|
|
19
|
+
assert.isFalse(token.isNegated);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("should correctly parse the bindTo property", () => {
|
|
23
|
+
const token = new JExpression("example.token");
|
|
24
|
+
assert.equal(token.bindTo, "example");
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("should correctly parse the path property", () => {
|
|
28
|
+
const token = new JExpression("example.token.part");
|
|
29
|
+
assert.deepEqual(token.path, ["token", "part"]);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("should remove '!' from bindTo if present", () => {
|
|
33
|
+
const token = new JExpression("!example.token");
|
|
34
|
+
assert.equal(token.bindTo, "example");
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("should parse equals operator value", () => {
|
|
38
|
+
const token = new JExpression("example==value");
|
|
39
|
+
assert.equal(token.equalsValue, "value");
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("should handle equals operator with negation", () => {
|
|
43
|
+
const token = new JExpression("!example == value");
|
|
44
|
+
assert.equal(token.equalsValue, "value");
|
|
45
|
+
assert.isTrue(token.isNegated);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("should handle equals operator with nested paths", () => {
|
|
49
|
+
const token = new JExpression("example.nested == value");
|
|
50
|
+
assert.equal(token.equalsValue, "value");
|
|
51
|
+
assert.deepEqual(token.path, ["nested"]);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("should parse greater than operator value", () => {
|
|
55
|
+
const token = new JExpression("example > 5");
|
|
56
|
+
assert.equal(token.gtValue, "5");
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("should parse less than operator value", () => {
|
|
60
|
+
const token = new JExpression("example < 10");
|
|
61
|
+
assert.equal(token.ltValue, "10");
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("should handle greater than operator with negation", () => {
|
|
65
|
+
const token = new JExpression("!example > 5");
|
|
66
|
+
assert.equal(token.gtValue, "5");
|
|
67
|
+
assert.isTrue(token.isNegated);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("should handle less than operator with nested paths", () => {
|
|
71
|
+
const token = new JExpression("example.count < 10");
|
|
72
|
+
assert.equal(token.ltValue, "10");
|
|
73
|
+
assert.deepEqual(token.path, ["count"]);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
describe("readTokenValueFrom", () => {
|
|
78
|
+
it("should read the value from a nested object", () => {
|
|
79
|
+
const token = new JExpression("example.token.part");
|
|
80
|
+
const obj = { token: { part: 42 } };
|
|
81
|
+
const value = token.evaluate<number>(obj);
|
|
82
|
+
assert.equal(value, 42);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("should return undefined if the path does not exist", () => {
|
|
86
|
+
const token = new JExpression("example.nonexistent.path");
|
|
87
|
+
const obj = { token: { part: 42 } };
|
|
88
|
+
const value = token.evaluate(obj);
|
|
89
|
+
assert.isUndefined(value);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("should handle empty paths gracefully", () => {
|
|
93
|
+
const token = new JExpression("example");
|
|
94
|
+
const obj = { foo: 42 };
|
|
95
|
+
const value = token.evaluate(obj);
|
|
96
|
+
|
|
97
|
+
assert.deepEqual(value, { foo: 42 });
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("should parse values from strings", () => {
|
|
101
|
+
const token = new JExpression("example.length");
|
|
102
|
+
const value = token.evaluate("42");
|
|
103
|
+
|
|
104
|
+
assert.equal(value, 2);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it("should return true when equals against primative", () => {
|
|
108
|
+
const token = new JExpression("example == active");
|
|
109
|
+
const value = token.evaluate<boolean>("active");
|
|
110
|
+
assert.isTrue(value);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("should return true when equals comparison matches", () => {
|
|
114
|
+
const token = new JExpression("example.status==active");
|
|
115
|
+
const obj = { status: "active" };
|
|
116
|
+
const value = token.evaluate<boolean>(obj);
|
|
117
|
+
assert.isTrue(value);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("should return false when equals comparison does not match", () => {
|
|
121
|
+
const token = new JExpression("example.status==active");
|
|
122
|
+
const obj = { status: "inactive" };
|
|
123
|
+
const value = token.evaluate<boolean>(obj);
|
|
124
|
+
assert.isFalse(value);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("should handle equals comparison with numbers", () => {
|
|
128
|
+
const token = new JExpression("example.count == 5");
|
|
129
|
+
const obj = { count: 5 };
|
|
130
|
+
const value = token.evaluate<boolean>(obj);
|
|
131
|
+
assert.isTrue(value);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it("should handle equals comparison with nested paths", () => {
|
|
135
|
+
const token = new JExpression("example.user.status == active");
|
|
136
|
+
const obj = { user: { status: "active" } };
|
|
137
|
+
const value = token.evaluate<boolean>(obj);
|
|
138
|
+
assert.isTrue(value);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it("should handle equals comparison with undefined values", () => {
|
|
142
|
+
const token = new JExpression("example.status == active");
|
|
143
|
+
const obj = { status: undefined };
|
|
144
|
+
const value = token.evaluate<boolean>(obj);
|
|
145
|
+
assert.isFalse(value);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it("should return true when greater than comparison matches", () => {
|
|
149
|
+
const token = new JExpression("example.count > 5");
|
|
150
|
+
const obj = { count: 10 };
|
|
151
|
+
const value = token.evaluate<boolean>(obj);
|
|
152
|
+
assert.isTrue(value);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it("should return false when greater than comparison does not match", () => {
|
|
156
|
+
const token = new JExpression("example.count > 5");
|
|
157
|
+
const obj = { count: 3 };
|
|
158
|
+
const value = token.evaluate<boolean>(obj);
|
|
159
|
+
assert.isFalse(value);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it("should return true when less than comparison matches", () => {
|
|
163
|
+
const token = new JExpression("example.count < 10");
|
|
164
|
+
const obj = { count: 5 };
|
|
165
|
+
const value = token.evaluate<boolean>(obj);
|
|
166
|
+
assert.isTrue(value);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it("should return false when less than comparison does not match", () => {
|
|
170
|
+
const token = new JExpression("example.count < 10");
|
|
171
|
+
const obj = { count: 15 };
|
|
172
|
+
const value = token.evaluate<boolean>(obj);
|
|
173
|
+
assert.isFalse(value);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it("should handle greater than comparison with string numbers", () => {
|
|
177
|
+
const token = new JExpression("example.count > 5");
|
|
178
|
+
const obj = { count: "10" };
|
|
179
|
+
const value = token.evaluate<boolean>(obj);
|
|
180
|
+
assert.isTrue(value);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it("should handle less than comparison with string numbers", () => {
|
|
184
|
+
const token = new JExpression("example.count < 10");
|
|
185
|
+
const obj = { count: "5" };
|
|
186
|
+
const value = token.evaluate<boolean>(obj);
|
|
187
|
+
assert.isTrue(value);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it("should handle greater than comparison with undefined values", () => {
|
|
191
|
+
const token = new JExpression("example.count > 5");
|
|
192
|
+
const obj = { count: undefined };
|
|
193
|
+
const value = token.evaluate<boolean>(obj);
|
|
194
|
+
assert.isFalse(value);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it("should handle less than comparison with undefined values", () => {
|
|
198
|
+
const token = new JExpression("example.count < 10");
|
|
199
|
+
const obj = { count: undefined };
|
|
200
|
+
const value = token.evaluate<boolean>(obj);
|
|
201
|
+
assert.isFalse(value);
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
});
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
type ComparisonOperator = "==" | "!=" | ">" | "<";
|
|
2
|
+
|
|
3
|
+
interface TokenParts {
|
|
4
|
+
path: string[];
|
|
5
|
+
value?: string;
|
|
6
|
+
operator?: ComparisonOperator;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* JExpression represents a token that can be used to extract and compare values from objects.
|
|
11
|
+
*
|
|
12
|
+
* Supported operators:
|
|
13
|
+
* - `==` : Equality comparison (e.g., "status==active")
|
|
14
|
+
* - `!=` : Inequality comparison (e.g., "status!=active")
|
|
15
|
+
* - `>` : Greater than comparison (e.g., "count>5")
|
|
16
|
+
* - `<` : Less than comparison (e.g., "count<10")
|
|
17
|
+
*
|
|
18
|
+
* Examples:
|
|
19
|
+
* ```typescript
|
|
20
|
+
* // Basic path access
|
|
21
|
+
* new JExpression("user.name").readTokenValueFrom({ user: { name: "John" } }) // "John"
|
|
22
|
+
*
|
|
23
|
+
* // Equality comparison
|
|
24
|
+
* new JExpression("status == active").readTokenValueFrom({ status: "active" }) // true
|
|
25
|
+
*
|
|
26
|
+
* // Inequality comparison
|
|
27
|
+
* new JExpression("status != active").readTokenValueFrom({ status: "inactive" }) // true
|
|
28
|
+
*
|
|
29
|
+
* // Greater than comparison
|
|
30
|
+
* new JExpression("count > 5").readTokenValueFrom({ count: 10 }) // true
|
|
31
|
+
*
|
|
32
|
+
* // Less than comparison
|
|
33
|
+
* new JExpression("count < 10").readTokenValueFrom({ count: 5 }) // true
|
|
34
|
+
*
|
|
35
|
+
* // With negation
|
|
36
|
+
* new JExpression("!status == active").readTokenValueFrom({ status: "inactive" }) // true
|
|
37
|
+
*
|
|
38
|
+
* // Nested paths
|
|
39
|
+
* new JExpression("user.score > 100").readTokenValueFrom({ user: { score: 150 } }) // true
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export class JExpression {
|
|
43
|
+
/** The raw token string as provided to the constructor */
|
|
44
|
+
rawToken: string;
|
|
45
|
+
/** Whether the token is negated (starts with '!') */
|
|
46
|
+
isNegated = false;
|
|
47
|
+
/** The first part of the path (before the first dot) */
|
|
48
|
+
bindTo: string;
|
|
49
|
+
/** The remaining parts of the path (after the first dot) */
|
|
50
|
+
path: string[] = [];
|
|
51
|
+
/** The value to compare against for equality (==) */
|
|
52
|
+
equalsValue: string | undefined;
|
|
53
|
+
/** The value to compare against for inequality (!=) */
|
|
54
|
+
notEqualsValue: string | undefined;
|
|
55
|
+
/** The value to compare against for greater than (>) */
|
|
56
|
+
gtValue: string | undefined;
|
|
57
|
+
/** The value to compare against for less than (<) */
|
|
58
|
+
ltValue: string | undefined;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Creates a new JExpression instance.
|
|
62
|
+
* @param rawToken - The token string to parse. Can include operators (==, !=, >, <) and negation (!)
|
|
63
|
+
*/
|
|
64
|
+
constructor(rawToken: string) {
|
|
65
|
+
this.rawToken = rawToken;
|
|
66
|
+
this.isNegated = this.rawToken.startsWith("!");
|
|
67
|
+
|
|
68
|
+
const { path, value, operator } = this.#parseToken();
|
|
69
|
+
this.path = path;
|
|
70
|
+
this.bindTo = this.path.shift() ?? "";
|
|
71
|
+
this.bindTo = this.bindTo.replaceAll("!", "");
|
|
72
|
+
|
|
73
|
+
// Set the appropriate comparison value based on the operator
|
|
74
|
+
switch (operator) {
|
|
75
|
+
case "==":
|
|
76
|
+
this.equalsValue = value;
|
|
77
|
+
break;
|
|
78
|
+
case "!=":
|
|
79
|
+
this.notEqualsValue = value;
|
|
80
|
+
break;
|
|
81
|
+
case ">":
|
|
82
|
+
this.gtValue = value;
|
|
83
|
+
break;
|
|
84
|
+
case "<":
|
|
85
|
+
this.ltValue = value;
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Reads a value from the provided object using the token's path and performs any comparison.
|
|
92
|
+
* @param value - The object to read from
|
|
93
|
+
* @returns The value at the path, or the result of the comparison if an operator is present
|
|
94
|
+
* @template T - The expected return type
|
|
95
|
+
*/
|
|
96
|
+
evaluate<T = unknown>(value: unknown): T {
|
|
97
|
+
if (typeof value !== "object" && typeof value !== "string") {
|
|
98
|
+
return value as T;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const pathValue = this.#getValueAtPath(value);
|
|
102
|
+
|
|
103
|
+
return this.#performComparison(pathValue) as T;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Parses the raw token into its components.
|
|
108
|
+
* @returns An object containing the path parts and any comparison operator/value
|
|
109
|
+
*/
|
|
110
|
+
#parseToken(): TokenParts {
|
|
111
|
+
const operators: ComparisonOperator[] = ["==", "!=", ">", "<"];
|
|
112
|
+
|
|
113
|
+
for (const operator of operators) {
|
|
114
|
+
if (this.rawToken.includes(operator)) {
|
|
115
|
+
const [tokenPart, value] = this.rawToken.split(operator).map((part) => part.trim());
|
|
116
|
+
return {
|
|
117
|
+
path: tokenPart.split("."),
|
|
118
|
+
value,
|
|
119
|
+
operator,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
path: this.rawToken.split("."),
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Gets the value at the token's path in the provided object.
|
|
131
|
+
* @param value - The object to read from
|
|
132
|
+
* @returns The value at the path, or undefined if the path doesn't exist
|
|
133
|
+
*/
|
|
134
|
+
#getValueAtPath(value: unknown): unknown {
|
|
135
|
+
if (value === null || value === undefined) {
|
|
136
|
+
return value;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (!this.path.length) {
|
|
140
|
+
return value;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
let pointer: any = value;
|
|
144
|
+
|
|
145
|
+
for (const part of this.path) {
|
|
146
|
+
pointer = pointer?.[part];
|
|
147
|
+
if (pointer === undefined) {
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return pointer;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Performs the comparison operation if an operator is present.
|
|
157
|
+
* @param value - The value to compare
|
|
158
|
+
* @returns The result of the comparison, or the original value if no operator is present
|
|
159
|
+
*/
|
|
160
|
+
#performComparison(value: unknown): boolean | unknown {
|
|
161
|
+
if (this.equalsValue !== undefined) {
|
|
162
|
+
return String(value) === this.equalsValue;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (this.notEqualsValue !== undefined) {
|
|
166
|
+
return String(value) !== this.notEqualsValue;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (this.gtValue !== undefined) {
|
|
170
|
+
return Number(value) > Number(this.gtValue);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (this.ltValue !== undefined) {
|
|
174
|
+
return Number(value) < Number(this.ltValue);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return value;
|
|
178
|
+
}
|
|
179
|
+
}
|
package/target/lib/bind.d.ts
CHANGED
|
@@ -1 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import { ObserveOpts } from "@joist/observable";
|
|
2
|
+
export interface BindOpts<This, Value> extends ObserveOpts<This, Value> {
|
|
3
|
+
alwaysUpdate?: boolean;
|
|
4
|
+
}
|
|
5
|
+
export declare function bind<This extends HTMLElement, Value>(opts?: BindOpts<This, Value>): (base: ClassAccessorDecoratorTarget<This, Value>, ctx: ClassAccessorDecoratorContext<This, Value>) => ClassAccessorDecoratorResult<This, Value>;
|
package/target/lib/bind.js
CHANGED
|
@@ -1,19 +1,33 @@
|
|
|
1
1
|
import { instanceMetadataStore, observe } from "@joist/observable";
|
|
2
|
-
export function bind(
|
|
2
|
+
export function bind(opts = {}) {
|
|
3
3
|
return function bindDecorator(base, ctx) {
|
|
4
|
-
const internalObserve = observe(
|
|
4
|
+
const internalObserve = observe(opts)(base, ctx);
|
|
5
5
|
return {
|
|
6
6
|
init(value) {
|
|
7
7
|
this.addEventListener("joist::value", (e) => {
|
|
8
|
-
if (e.
|
|
8
|
+
if (e.expression.bindTo === ctx.name) {
|
|
9
9
|
const instanceMeta = instanceMetadataStore.read(this);
|
|
10
10
|
e.stopPropagation();
|
|
11
|
-
e.update({
|
|
11
|
+
e.update({
|
|
12
|
+
oldValue: null,
|
|
13
|
+
newValue: ctx.access.get(this),
|
|
14
|
+
alwaysUpdate: opts.alwaysUpdate,
|
|
15
|
+
firstChange: true,
|
|
16
|
+
});
|
|
17
|
+
const name = ctx.name;
|
|
12
18
|
instanceMeta.bindings.add((changes) => {
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
19
|
+
const change = changes.get(name);
|
|
20
|
+
if (change) {
|
|
21
|
+
e.update({ ...change, alwaysUpdate: opts.alwaysUpdate, firstChange: false });
|
|
22
|
+
}
|
|
23
|
+
else if (opts.alwaysUpdate) {
|
|
24
|
+
const value = ctx.access.get(this);
|
|
25
|
+
e.update({
|
|
26
|
+
oldValue: value,
|
|
27
|
+
newValue: value,
|
|
28
|
+
alwaysUpdate: opts.alwaysUpdate,
|
|
29
|
+
firstChange: false,
|
|
30
|
+
});
|
|
17
31
|
}
|
|
18
32
|
});
|
|
19
33
|
}
|
package/target/lib/bind.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bind.js","sourceRoot":"","sources":["../../src/lib/bind.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"bind.js","sourceRoot":"","sources":["../../src/lib/bind.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,OAAO,EAAe,MAAM,mBAAmB,CAAC;AAUhF,MAAM,UAAU,IAAI,CAAkC,OAA8B,EAAE;IACpF,OAAO,SAAS,aAAa,CAC3B,IAA+C,EAC/C,GAA+C;QAE/C,MAAM,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAEjD,OAAO;YACL,IAAI,CAAC,KAAK;gBACR,IAAI,CAAC,gBAAgB,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE;oBAC1C,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,KAAK,GAAG,CAAC,IAAI,EAAE,CAAC;wBACrC,MAAM,YAAY,GAAG,qBAAqB,CAAC,IAAI,CAAO,IAAI,CAAC,CAAC;wBAE5D,CAAC,CAAC,eAAe,EAAE,CAAC;wBAEpB,CAAC,CAAC,MAAM,CAAC;4BACP,QAAQ,EAAE,IAAI;4BACd,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;4BAC9B,YAAY,EAAE,IAAI,CAAC,YAAY;4BAC/B,WAAW,EAAE,IAAI;yBAClB,CAAC,CAAC;wBAEH,MAAM,IAAI,GAAG,GAAG,CAAC,IAAkB,CAAC;wBAEpC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;4BACpC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;4BAEjC,IAAI,MAAM,EAAE,CAAC;gCACX,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;4BAC/E,CAAC;iCAAM,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;gCAC7B,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gCAEnC,CAAC,CAAC,MAAM,CAAC;oCACP,QAAQ,EAAE,KAAK;oCACf,QAAQ,EAAE,KAAK;oCACf,YAAY,EAAE,IAAI,CAAC,YAAY;oCAC/B,WAAW,EAAE,KAAK;iCACnB,CAAC,CAAC;4BACL,CAAC;wBACH,CAAC,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC,CAAC,CAAC;gBAEH,IAAI,eAAe,CAAC,IAAI,EAAE,CAAC;oBACzB,OAAO,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAU,CAAC;gBACzD,CAAC;gBAED,OAAO,KAAK,CAAC;YACf,CAAC;YACD,GAAG,EAAE,eAAe,CAAC,GAAG;YACxB,GAAG,EAAE,eAAe,CAAC,GAAG;SACzB,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { __esDecorate, __runInitializers } from "tslib";
|
|
2
|
+
import { assert } from "chai";
|
|
3
|
+
import { bind } from "./bind.js";
|
|
4
|
+
import { JoistValueEvent } from "./events.js";
|
|
5
|
+
import { JExpression } from "./expression.js";
|
|
6
|
+
describe("bind decorator", () => {
|
|
7
|
+
let TestElement = (() => {
|
|
8
|
+
let _classSuper = HTMLElement;
|
|
9
|
+
let _value_decorators;
|
|
10
|
+
let _value_initializers = [];
|
|
11
|
+
let _value_extraInitializers = [];
|
|
12
|
+
let _alwaysUpdateValue_decorators;
|
|
13
|
+
let _alwaysUpdateValue_initializers = [];
|
|
14
|
+
let _alwaysUpdateValue_extraInitializers = [];
|
|
15
|
+
return class TestElement extends _classSuper {
|
|
16
|
+
static {
|
|
17
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
18
|
+
_value_decorators = [bind()];
|
|
19
|
+
_alwaysUpdateValue_decorators = [bind({ alwaysUpdate: true })];
|
|
20
|
+
__esDecorate(this, null, _value_decorators, { kind: "accessor", name: "value", static: false, private: false, access: { has: obj => "value" in obj, get: obj => obj.value, set: (obj, value) => { obj.value = value; } }, metadata: _metadata }, _value_initializers, _value_extraInitializers);
|
|
21
|
+
__esDecorate(this, null, _alwaysUpdateValue_decorators, { kind: "accessor", name: "alwaysUpdateValue", static: false, private: false, access: { has: obj => "alwaysUpdateValue" in obj, get: obj => obj.alwaysUpdateValue, set: (obj, value) => { obj.alwaysUpdateValue = value; } }, metadata: _metadata }, _alwaysUpdateValue_initializers, _alwaysUpdateValue_extraInitializers);
|
|
22
|
+
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
23
|
+
}
|
|
24
|
+
#value_accessor_storage = __runInitializers(this, _value_initializers, "initial");
|
|
25
|
+
get value() { return this.#value_accessor_storage; }
|
|
26
|
+
set value(value) { this.#value_accessor_storage = value; }
|
|
27
|
+
#alwaysUpdateValue_accessor_storage = (__runInitializers(this, _value_extraInitializers), __runInitializers(this, _alwaysUpdateValue_initializers, "initial"));
|
|
28
|
+
get alwaysUpdateValue() { return this.#alwaysUpdateValue_accessor_storage; }
|
|
29
|
+
set alwaysUpdateValue(value) { this.#alwaysUpdateValue_accessor_storage = value; }
|
|
30
|
+
constructor() {
|
|
31
|
+
super(...arguments);
|
|
32
|
+
__runInitializers(this, _alwaysUpdateValue_extraInitializers);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
customElements.define("test-element", TestElement);
|
|
37
|
+
it("should initialize with default value", () => {
|
|
38
|
+
const element = new TestElement();
|
|
39
|
+
assert.equal(element.value, "initial");
|
|
40
|
+
});
|
|
41
|
+
it("should update value and trigger binding", async () => {
|
|
42
|
+
const element = new TestElement();
|
|
43
|
+
let oldValue = null;
|
|
44
|
+
let newValue = null;
|
|
45
|
+
element.dispatchEvent(new JoistValueEvent(new JExpression("value"), (update) => {
|
|
46
|
+
oldValue = update.oldValue;
|
|
47
|
+
newValue = update.newValue;
|
|
48
|
+
}));
|
|
49
|
+
assert.equal(oldValue, null);
|
|
50
|
+
assert.equal(newValue, "initial");
|
|
51
|
+
element.value = "updated";
|
|
52
|
+
await Promise.resolve();
|
|
53
|
+
assert.equal(oldValue, "initial");
|
|
54
|
+
assert.equal(newValue, "updated");
|
|
55
|
+
});
|
|
56
|
+
it("should trigger binding on every change with alwaysUpdate option", async () => {
|
|
57
|
+
const element = new TestElement();
|
|
58
|
+
let bindingCount = 0;
|
|
59
|
+
let oldValue;
|
|
60
|
+
let newValue;
|
|
61
|
+
element.dispatchEvent(new JoistValueEvent(new JExpression("alwaysUpdateValue"), (update) => {
|
|
62
|
+
bindingCount++;
|
|
63
|
+
oldValue = update.oldValue;
|
|
64
|
+
newValue = update.newValue;
|
|
65
|
+
}));
|
|
66
|
+
assert.equal(bindingCount, 1);
|
|
67
|
+
assert.equal(oldValue, null);
|
|
68
|
+
assert.equal(newValue, "initial");
|
|
69
|
+
element.value = "something else";
|
|
70
|
+
await Promise.resolve();
|
|
71
|
+
assert.equal(bindingCount, 2);
|
|
72
|
+
assert.equal(oldValue, "initial");
|
|
73
|
+
assert.equal(newValue, "initial");
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
//# sourceMappingURL=bind.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bind.test.js","sourceRoot":"","sources":["../../src/lib/bind.test.ts"],"names":[],"mappings":"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"}
|
package/target/lib/define.d.ts
CHANGED
package/target/lib/define.js
CHANGED
package/target/lib/define.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define.js","sourceRoot":"","sources":["../../src/lib/define.ts"],"names":[],"mappings":"AAAA,OAAO,6BAA6B,CAAC;AACrC,OAAO,2BAA2B,CAAC;AACnC,OAAO,0BAA0B,CAAC;AAClC,OAAO,4BAA4B,CAAC;AACpC,OAAO,6BAA6B,CAAC"}
|
|
1
|
+
{"version":3,"file":"define.js","sourceRoot":"","sources":["../../src/lib/define.ts"],"names":[],"mappings":"AAAA,OAAO,6BAA6B,CAAC;AACrC,OAAO,2BAA2B,CAAC;AACnC,OAAO,0BAA0B,CAAC;AAClC,OAAO,4BAA4B,CAAC;AACpC,OAAO,6BAA6B,CAAC;AACrC,OAAO,6BAA6B,CAAC"}
|
|
@@ -2,7 +2,7 @@ import { __esDecorate, __runInitializers } from "tslib";
|
|
|
2
2
|
import { attr, element, queryAll, css, html } from "@joist/element";
|
|
3
3
|
import { bind } from "../bind.js";
|
|
4
4
|
import { JoistValueEvent } from "../events.js";
|
|
5
|
-
import {
|
|
5
|
+
import { JExpression } from "../expression.js";
|
|
6
6
|
let JoistAsyncElement = (() => {
|
|
7
7
|
let _classDecorators = [element({
|
|
8
8
|
tagName: "j-async",
|
|
@@ -52,18 +52,27 @@ let JoistAsyncElement = (() => {
|
|
|
52
52
|
error: templates.find((t) => t.hasAttribute("error")),
|
|
53
53
|
success: templates.find((t) => t.hasAttribute("success")),
|
|
54
54
|
};
|
|
55
|
-
const token = new
|
|
55
|
+
const token = new JExpression(this.bind);
|
|
56
56
|
this.dispatchEvent(new JoistValueEvent(token, ({ newValue, oldValue }) => {
|
|
57
57
|
if (newValue !== oldValue) {
|
|
58
58
|
if (newValue instanceof Promise) {
|
|
59
59
|
this.#handlePromise(newValue);
|
|
60
60
|
}
|
|
61
|
+
else if (this.#isAsyncState(newValue)) {
|
|
62
|
+
this.#handleState(newValue);
|
|
63
|
+
}
|
|
61
64
|
else {
|
|
62
65
|
console.warn("j-async bind value must be a Promise or AsyncState");
|
|
63
66
|
}
|
|
64
67
|
}
|
|
65
68
|
}));
|
|
66
69
|
}
|
|
70
|
+
#isAsyncState(value) {
|
|
71
|
+
return (typeof value === "object" &&
|
|
72
|
+
value !== null &&
|
|
73
|
+
"status" in value &&
|
|
74
|
+
(value.status === "loading" || value.status === "error" || value.status === "success"));
|
|
75
|
+
}
|
|
67
76
|
async #handlePromise(promise) {
|
|
68
77
|
try {
|
|
69
78
|
this.#handleState({ status: "loading" });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"async.element.js","sourceRoot":"","sources":["../../../src/lib/elements/async.element.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAEpE,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"async.element.js","sourceRoot":"","sources":["../../../src/lib/elements/async.element.ts"],"names":[],"mappings":"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"}
|