@microsoft/fast-element 2.0.0-beta.2 → 2.0.0-beta.21
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.json +509 -0
- package/CHANGELOG.md +189 -1
- package/dist/dts/components/attributes.d.ts +15 -0
- package/dist/dts/components/{controller.d.ts → element-controller.d.ts} +74 -28
- package/dist/dts/components/fast-definitions.d.ts +41 -9
- package/dist/dts/components/fast-element.d.ts +14 -26
- package/dist/dts/components/hydration.d.ts +14 -0
- package/dist/{esm/observation/behavior.js → dts/components/install-hydration.d.ts} +0 -0
- package/dist/dts/context.d.ts +7 -7
- package/dist/dts/di/di.d.ts +894 -0
- package/dist/dts/dom-policy.d.ts +83 -0
- package/dist/dts/dom.d.ts +100 -0
- package/dist/dts/index.d.ts +5 -4
- package/dist/dts/index.rollup.d.ts +0 -1
- package/dist/dts/index.rollup.debug.d.ts +0 -1
- package/dist/dts/interfaces.d.ts +62 -80
- package/dist/dts/metadata.d.ts +5 -5
- package/dist/dts/observation/observable.d.ts +99 -54
- package/dist/dts/pending-task.d.ts +32 -0
- package/dist/dts/platform.d.ts +8 -1
- package/dist/dts/polyfills.d.ts +0 -8
- package/dist/dts/state/exports.d.ts +3 -0
- package/dist/dts/state/reactive.d.ts +8 -0
- package/dist/dts/state/state.d.ts +141 -0
- package/dist/dts/state/visitor.d.ts +6 -0
- package/dist/dts/state/watch.d.ts +10 -0
- package/dist/dts/styles/css-directive.d.ts +2 -2
- package/dist/dts/styles/css.d.ts +0 -5
- package/dist/dts/styles/element-styles.d.ts +10 -17
- package/dist/dts/styles/host.d.ts +68 -0
- package/dist/dts/styles/style-strategy.d.ts +42 -0
- package/dist/dts/templating/binding-signal.d.ts +12 -27
- package/dist/dts/templating/binding-two-way.d.ts +22 -37
- package/dist/dts/templating/binding.d.ts +76 -208
- package/dist/dts/templating/children.d.ts +1 -1
- package/dist/dts/templating/compiler.d.ts +11 -13
- package/dist/dts/templating/html-directive.d.ts +91 -97
- package/dist/dts/templating/node-observation.d.ts +15 -6
- package/dist/dts/templating/ref.d.ts +7 -11
- package/dist/dts/templating/render.d.ts +296 -0
- package/dist/dts/templating/repeat.d.ts +23 -34
- package/dist/dts/templating/slotted.d.ts +1 -1
- package/dist/dts/templating/template.d.ts +92 -14
- package/dist/dts/templating/view.d.ts +81 -11
- package/dist/dts/templating/when.d.ts +3 -3
- package/dist/dts/testing/exports.d.ts +3 -0
- package/dist/dts/testing/fakes.d.ts +14 -0
- package/dist/dts/testing/fixture.d.ts +84 -0
- package/dist/dts/testing/timeout.d.ts +7 -0
- package/dist/dts/utilities.d.ts +55 -19
- package/dist/esm/components/attributes.js +28 -5
- package/dist/esm/components/{controller.js → element-controller.js} +238 -137
- package/dist/esm/components/fast-definitions.js +38 -30
- package/dist/esm/components/fast-element.js +27 -16
- package/dist/esm/components/hydration.js +35 -0
- package/dist/esm/components/install-hydration.js +2 -0
- package/dist/esm/context.js +7 -3
- package/dist/esm/debug.js +41 -5
- package/dist/esm/di/di.js +1430 -0
- package/dist/esm/dom-policy.js +345 -0
- package/dist/esm/dom.js +101 -0
- package/dist/esm/index.js +4 -2
- package/dist/esm/index.rollup.debug.js +3 -1
- package/dist/esm/index.rollup.js +3 -1
- package/dist/esm/interfaces.js +52 -0
- package/dist/esm/metadata.js +9 -8
- package/dist/esm/observation/arrays.js +303 -2
- package/dist/esm/observation/observable.js +88 -142
- package/dist/esm/observation/update-queue.js +2 -2
- package/dist/esm/pending-task.js +28 -0
- package/dist/esm/platform.js +28 -3
- package/dist/esm/polyfills.js +3 -61
- package/dist/esm/state/exports.js +3 -0
- package/dist/esm/state/reactive.js +34 -0
- package/dist/esm/state/state.js +148 -0
- package/dist/esm/state/visitor.js +28 -0
- package/dist/esm/state/watch.js +36 -0
- package/dist/esm/styles/css.js +4 -9
- package/dist/esm/styles/element-styles.js +14 -33
- package/dist/esm/styles/host.js +1 -0
- package/dist/esm/styles/style-strategy.js +1 -0
- package/dist/esm/templating/binding-signal.js +67 -62
- package/dist/esm/templating/binding-two-way.js +72 -39
- package/dist/esm/templating/binding.js +142 -286
- package/dist/esm/templating/children.js +8 -4
- package/dist/esm/templating/compiler.js +59 -43
- package/dist/esm/templating/html-directive.js +56 -75
- package/dist/esm/templating/node-observation.js +20 -13
- package/dist/esm/templating/ref.js +4 -12
- package/dist/esm/templating/render.js +402 -0
- package/dist/esm/templating/repeat.js +88 -75
- package/dist/esm/templating/template.js +132 -60
- package/dist/esm/templating/view.js +113 -29
- package/dist/esm/templating/when.js +5 -4
- package/dist/esm/testing/exports.js +3 -0
- package/dist/esm/testing/fakes.js +107 -0
- package/dist/esm/testing/fixture.js +86 -0
- package/dist/esm/testing/timeout.js +24 -0
- package/dist/esm/utilities.js +97 -96
- package/dist/fast-element.api.json +9741 -8201
- package/dist/fast-element.d.ts +889 -646
- package/dist/fast-element.debug.js +2001 -1167
- package/dist/fast-element.debug.min.js +1 -1
- package/dist/fast-element.js +1907 -1109
- package/dist/fast-element.min.js +1 -1
- package/dist/fast-element.untrimmed.d.ts +913 -703
- package/docs/api-report.md +331 -258
- package/package.json +38 -16
- package/dist/dts/hooks.d.ts +0 -20
- package/dist/dts/observation/behavior.d.ts +0 -19
- package/dist/dts/observation/splice-strategies.d.ts +0 -13
- package/dist/dts/templating/dom.d.ts +0 -41
- package/dist/esm/hooks.js +0 -32
- package/dist/esm/observation/splice-strategies.js +0 -400
- package/dist/esm/templating/dom.js +0 -49
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isString } from "../interfaces.js";
|
|
1
|
+
import { isString, noop } from "../interfaces.js";
|
|
2
2
|
import { HTMLDirective } from "./html-directive.js";
|
|
3
3
|
import { NodeObservationDirective } from "./node-observation.js";
|
|
4
4
|
/**
|
|
@@ -24,9 +24,13 @@ export class ChildrenDirective extends NodeObservationDirective {
|
|
|
24
24
|
* @param target - The target to observe.
|
|
25
25
|
*/
|
|
26
26
|
observe(target) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
let observer = target[this.observerProperty];
|
|
28
|
+
if (!observer) {
|
|
29
|
+
observer = new MutationObserver(this.handleEvent);
|
|
30
|
+
observer.toJSON = noop;
|
|
31
|
+
observer.target = target;
|
|
32
|
+
target[this.observerProperty] = observer;
|
|
33
|
+
}
|
|
30
34
|
observer.observe(target, this.options);
|
|
31
35
|
}
|
|
32
36
|
/**
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { isString } from "../interfaces.js";
|
|
1
|
+
import { isFunction, isString } from "../interfaces.js";
|
|
2
2
|
import { FAST } from "../platform.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { DOM } from "../dom.js";
|
|
4
|
+
import { nextId, Parser } from "./markup.js";
|
|
5
|
+
import { HTMLBindingDirective, oneTime } from "./binding.js";
|
|
6
|
+
import { HTMLDirective, } from "./html-directive.js";
|
|
6
7
|
import { HTMLView } from "./view.js";
|
|
7
8
|
const targetIdFrom = (parentId, nodeIndex) => `${parentId}.${nodeIndex}`;
|
|
8
9
|
const descriptorCache = {};
|
|
@@ -11,21 +12,42 @@ const next = {
|
|
|
11
12
|
index: 0,
|
|
12
13
|
node: null,
|
|
13
14
|
};
|
|
15
|
+
function tryWarn(name) {
|
|
16
|
+
if (!name.startsWith("fast-")) {
|
|
17
|
+
FAST.warn(1204 /* Message.hostBindingWithoutHost */, { name });
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const warningHost = new Proxy(document.createElement("div"), {
|
|
21
|
+
get(target, property) {
|
|
22
|
+
tryWarn(property);
|
|
23
|
+
const value = Reflect.get(target, property);
|
|
24
|
+
return isFunction(value) ? value.bind(target) : value;
|
|
25
|
+
},
|
|
26
|
+
set(target, property, value) {
|
|
27
|
+
tryWarn(property);
|
|
28
|
+
return Reflect.set(target, property, value);
|
|
29
|
+
},
|
|
30
|
+
});
|
|
14
31
|
class CompilationContext {
|
|
15
|
-
constructor(fragment, directives) {
|
|
32
|
+
constructor(fragment, directives, policy) {
|
|
16
33
|
this.fragment = fragment;
|
|
17
34
|
this.directives = directives;
|
|
35
|
+
this.policy = policy;
|
|
18
36
|
this.proto = null;
|
|
19
37
|
this.nodeIds = new Set();
|
|
20
38
|
this.descriptors = {};
|
|
21
39
|
this.factories = [];
|
|
22
40
|
}
|
|
23
|
-
addFactory(factory, parentId, nodeId, targetIndex) {
|
|
41
|
+
addFactory(factory, parentId, nodeId, targetIndex, tagName) {
|
|
42
|
+
var _a, _b;
|
|
24
43
|
if (!this.nodeIds.has(nodeId)) {
|
|
25
44
|
this.nodeIds.add(nodeId);
|
|
26
45
|
this.addTargetDescriptor(parentId, nodeId, targetIndex);
|
|
27
46
|
}
|
|
28
|
-
factory.
|
|
47
|
+
factory.id = (_a = factory.id) !== null && _a !== void 0 ? _a : nextId();
|
|
48
|
+
factory.targetNodeId = nodeId;
|
|
49
|
+
factory.targetTagName = tagName;
|
|
50
|
+
factory.policy = (_b = factory.policy) !== null && _b !== void 0 ? _b : this.policy;
|
|
29
51
|
this.factories.push(factory);
|
|
30
52
|
}
|
|
31
53
|
freeze() {
|
|
@@ -61,7 +83,7 @@ class CompilationContext {
|
|
|
61
83
|
const fragment = this.fragment.cloneNode(true);
|
|
62
84
|
const targets = Object.create(this.proto);
|
|
63
85
|
targets.r = fragment;
|
|
64
|
-
targets.h = hostBindingTarget !== null && hostBindingTarget !== void 0 ? hostBindingTarget :
|
|
86
|
+
targets.h = hostBindingTarget !== null && hostBindingTarget !== void 0 ? hostBindingTarget : warningHost;
|
|
65
87
|
for (const id of this.nodeIds) {
|
|
66
88
|
targets[id]; // trigger locator
|
|
67
89
|
}
|
|
@@ -78,19 +100,19 @@ function compileAttributes(context, parentId, node, nodeId, nodeIndex, includeBa
|
|
|
78
100
|
let result = null;
|
|
79
101
|
if (parseResult === null) {
|
|
80
102
|
if (includeBasicValues) {
|
|
81
|
-
result =
|
|
82
|
-
|
|
103
|
+
result = new HTMLBindingDirective(oneTime(() => attrValue, context.policy));
|
|
104
|
+
HTMLDirective.assignAspect(result, attr.name);
|
|
83
105
|
}
|
|
84
106
|
}
|
|
85
107
|
else {
|
|
86
108
|
/* eslint-disable-next-line @typescript-eslint/no-use-before-define */
|
|
87
|
-
result = Compiler.aggregate(parseResult);
|
|
109
|
+
result = Compiler.aggregate(parseResult, context.policy);
|
|
88
110
|
}
|
|
89
111
|
if (result !== null) {
|
|
90
112
|
node.removeAttributeNode(attr);
|
|
91
113
|
i--;
|
|
92
114
|
ii--;
|
|
93
|
-
context.addFactory(result, parentId, nodeId, nodeIndex);
|
|
115
|
+
context.addFactory(result, parentId, nodeId, nodeIndex, node.tagName);
|
|
94
116
|
}
|
|
95
117
|
}
|
|
96
118
|
}
|
|
@@ -115,7 +137,8 @@ function compileContent(context, node, parentId, nodeId, nodeIndex) {
|
|
|
115
137
|
}
|
|
116
138
|
else {
|
|
117
139
|
currentNode.textContent = " ";
|
|
118
|
-
|
|
140
|
+
HTMLDirective.assignAspect(currentPart);
|
|
141
|
+
context.addFactory(currentPart, parentId, nodeId, nodeIndex, null);
|
|
119
142
|
}
|
|
120
143
|
lastNode = currentNode;
|
|
121
144
|
}
|
|
@@ -147,7 +170,7 @@ function compileNode(context, parentId, node, nodeIndex) {
|
|
|
147
170
|
if (parts !== null) {
|
|
148
171
|
context.addFactory(
|
|
149
172
|
/* eslint-disable-next-line @typescript-eslint/no-use-before-define */
|
|
150
|
-
Compiler.aggregate(parts), parentId, nodeId, nodeIndex);
|
|
173
|
+
Compiler.aggregate(parts), parentId, nodeId, nodeIndex, null);
|
|
151
174
|
}
|
|
152
175
|
break;
|
|
153
176
|
}
|
|
@@ -161,45 +184,28 @@ function isMarker(node, directives) {
|
|
|
161
184
|
Parser.parse(node.data, directives) !== null);
|
|
162
185
|
}
|
|
163
186
|
const templateTag = "TEMPLATE";
|
|
164
|
-
const policyOptions = { createHTML: html => html };
|
|
165
|
-
let htmlPolicy = globalThis.trustedTypes
|
|
166
|
-
? globalThis.trustedTypes.createPolicy("fast-html", policyOptions)
|
|
167
|
-
: policyOptions;
|
|
168
|
-
const fastHTMLPolicy = htmlPolicy;
|
|
169
187
|
/**
|
|
170
188
|
* Common APIs related to compilation.
|
|
171
189
|
* @public
|
|
172
190
|
*/
|
|
173
191
|
export const Compiler = {
|
|
174
|
-
/**
|
|
175
|
-
* Sets the HTML trusted types policy used by the compiler.
|
|
176
|
-
* @param policy - The policy to set for HTML.
|
|
177
|
-
* @remarks
|
|
178
|
-
* This API can only be called once, for security reasons. It should be
|
|
179
|
-
* called by the application developer at the start of their program.
|
|
180
|
-
*/
|
|
181
|
-
setHTMLPolicy(policy) {
|
|
182
|
-
if (htmlPolicy !== fastHTMLPolicy) {
|
|
183
|
-
throw FAST.error(1201 /* Message.onlySetHTMLPolicyOnce */);
|
|
184
|
-
}
|
|
185
|
-
htmlPolicy = policy;
|
|
186
|
-
},
|
|
187
192
|
/**
|
|
188
193
|
* Compiles a template and associated directives into a compilation
|
|
189
194
|
* result which can be used to create views.
|
|
190
195
|
* @param html - The html string or template element to compile.
|
|
191
|
-
* @param
|
|
196
|
+
* @param factories - The behavior factories referenced by the template.
|
|
197
|
+
* @param policy - The security policy to compile the html with.
|
|
192
198
|
* @remarks
|
|
193
199
|
* The template that is provided for compilation is altered in-place
|
|
194
200
|
* and cannot be compiled again. If the original template must be preserved,
|
|
195
201
|
* it is recommended that you clone the original and pass the clone to this API.
|
|
196
202
|
* @public
|
|
197
203
|
*/
|
|
198
|
-
compile(html,
|
|
204
|
+
compile(html, factories, policy = DOM.policy) {
|
|
199
205
|
let template;
|
|
200
206
|
if (isString(html)) {
|
|
201
207
|
template = document.createElement(templateTag);
|
|
202
|
-
template.innerHTML =
|
|
208
|
+
template.innerHTML = policy.createHTML(html);
|
|
203
209
|
const fec = template.content.firstElementChild;
|
|
204
210
|
if (fec !== null && fec.tagName === templateTag) {
|
|
205
211
|
template = fec;
|
|
@@ -210,18 +216,18 @@ export const Compiler = {
|
|
|
210
216
|
}
|
|
211
217
|
// https://bugs.chromium.org/p/chromium/issues/detail?id=1111864
|
|
212
218
|
const fragment = document.adoptNode(template.content);
|
|
213
|
-
const context = new CompilationContext(fragment,
|
|
219
|
+
const context = new CompilationContext(fragment, factories, policy);
|
|
214
220
|
compileAttributes(context, "", template, /* host */ "h", 0, true);
|
|
215
221
|
if (
|
|
216
222
|
// If the first node in a fragment is a marker, that means it's an unstable first node,
|
|
217
223
|
// because something like a when, repeat, etc. could add nodes before the marker.
|
|
218
224
|
// To mitigate this, we insert a stable first node. However, if we insert a node,
|
|
219
225
|
// that will alter the result of the TreeWalker. So, we also need to offset the target index.
|
|
220
|
-
isMarker(fragment.firstChild,
|
|
226
|
+
isMarker(fragment.firstChild, factories) ||
|
|
221
227
|
// Or if there is only one node and a directive, it means the template's content
|
|
222
228
|
// is *only* the directive. In that case, HTMLView.dispose() misses any nodes inserted by
|
|
223
229
|
// the directive. Inserting a new node ensures proper disposal of nodes added by the directive.
|
|
224
|
-
(fragment.childNodes.length === 1 && Object.keys(
|
|
230
|
+
(fragment.childNodes.length === 1 && Object.keys(factories).length > 0)) {
|
|
225
231
|
fragment.insertBefore(document.createComment(""), fragment.firstChild);
|
|
226
232
|
}
|
|
227
233
|
compileChildren(context, fragment, /* root */ "r");
|
|
@@ -240,30 +246,40 @@ export const Compiler = {
|
|
|
240
246
|
* Aggregates an array of strings and directives into a single directive.
|
|
241
247
|
* @param parts - A heterogeneous array of static strings interspersed with
|
|
242
248
|
* directives.
|
|
249
|
+
* @param policy - The security policy to use with the aggregated bindings.
|
|
243
250
|
* @returns A single inline directive that aggregates the behavior of all the parts.
|
|
244
251
|
*/
|
|
245
|
-
aggregate(parts) {
|
|
252
|
+
aggregate(parts, policy = DOM.policy) {
|
|
246
253
|
if (parts.length === 1) {
|
|
247
254
|
return parts[0];
|
|
248
255
|
}
|
|
249
256
|
let sourceAspect;
|
|
257
|
+
let binding;
|
|
258
|
+
let isVolatile = false;
|
|
259
|
+
let bindingPolicy = void 0;
|
|
250
260
|
const partCount = parts.length;
|
|
251
261
|
const finalParts = parts.map((x) => {
|
|
252
262
|
if (isString(x)) {
|
|
253
263
|
return () => x;
|
|
254
264
|
}
|
|
255
265
|
sourceAspect = x.sourceAspect || sourceAspect;
|
|
256
|
-
|
|
266
|
+
binding = x.dataBinding || binding;
|
|
267
|
+
isVolatile = isVolatile || x.dataBinding.isVolatile;
|
|
268
|
+
bindingPolicy = bindingPolicy || x.dataBinding.policy;
|
|
269
|
+
return x.dataBinding.evaluate;
|
|
257
270
|
});
|
|
258
|
-
const
|
|
271
|
+
const expression = (scope, context) => {
|
|
259
272
|
let output = "";
|
|
260
273
|
for (let i = 0; i < partCount; ++i) {
|
|
261
274
|
output += finalParts[i](scope, context);
|
|
262
275
|
}
|
|
263
276
|
return output;
|
|
264
277
|
};
|
|
265
|
-
|
|
266
|
-
|
|
278
|
+
binding.evaluate = expression;
|
|
279
|
+
binding.isVolatile = isVolatile;
|
|
280
|
+
binding.policy = bindingPolicy !== null && bindingPolicy !== void 0 ? bindingPolicy : policy;
|
|
281
|
+
const directive = new HTMLBindingDirective(binding);
|
|
282
|
+
HTMLDirective.assignAspect(directive, sourceAspect);
|
|
267
283
|
return directive;
|
|
268
284
|
},
|
|
269
285
|
};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { DOMAspect } from "../dom.js";
|
|
2
|
+
import { noop } from "../interfaces.js";
|
|
1
3
|
import { createTypeRegistry } from "../platform.js";
|
|
2
4
|
import { Markup } from "./markup.js";
|
|
3
5
|
const registry = createTypeRegistry();
|
|
@@ -27,97 +29,71 @@ export const HTMLDirective = Object.freeze({
|
|
|
27
29
|
registry.register(options);
|
|
28
30
|
return type;
|
|
29
31
|
},
|
|
30
|
-
});
|
|
31
|
-
/**
|
|
32
|
-
* Decorator: Defines an HTMLDirective.
|
|
33
|
-
* @param options - Provides options that specify the directive's application.
|
|
34
|
-
* @public
|
|
35
|
-
*/
|
|
36
|
-
export function htmlDirective(options) {
|
|
37
|
-
/* eslint-disable-next-line @typescript-eslint/explicit-function-return-type */
|
|
38
|
-
return function (type) {
|
|
39
|
-
HTMLDirective.define(type, options);
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* The type of HTML aspect to target.
|
|
44
|
-
* @public
|
|
45
|
-
*/
|
|
46
|
-
export const Aspect = Object.freeze({
|
|
47
|
-
/**
|
|
48
|
-
* Not aspected.
|
|
49
|
-
*/
|
|
50
|
-
none: 0,
|
|
51
|
-
/**
|
|
52
|
-
* An attribute.
|
|
53
|
-
*/
|
|
54
|
-
attribute: 1,
|
|
55
|
-
/**
|
|
56
|
-
* A boolean attribute.
|
|
57
|
-
*/
|
|
58
|
-
booleanAttribute: 2,
|
|
59
|
-
/**
|
|
60
|
-
* A property.
|
|
61
|
-
*/
|
|
62
|
-
property: 3,
|
|
63
|
-
/**
|
|
64
|
-
* Content
|
|
65
|
-
*/
|
|
66
|
-
content: 4,
|
|
67
|
-
/**
|
|
68
|
-
* A token list.
|
|
69
|
-
*/
|
|
70
|
-
tokenList: 5,
|
|
71
|
-
/**
|
|
72
|
-
* An event.
|
|
73
|
-
*/
|
|
74
|
-
event: 6,
|
|
75
32
|
/**
|
|
76
33
|
*
|
|
77
34
|
* @param directive - The directive to assign the aspect to.
|
|
78
35
|
* @param value - The value to base the aspect determination on.
|
|
36
|
+
* @remarks
|
|
37
|
+
* If a falsy value is provided, then the content aspect will be assigned.
|
|
79
38
|
*/
|
|
80
|
-
|
|
81
|
-
directive.sourceAspect = value;
|
|
39
|
+
assignAspect(directive, value) {
|
|
82
40
|
if (!value) {
|
|
41
|
+
directive.aspectType = DOMAspect.content;
|
|
83
42
|
return;
|
|
84
43
|
}
|
|
44
|
+
directive.sourceAspect = value;
|
|
85
45
|
switch (value[0]) {
|
|
86
46
|
case ":":
|
|
87
47
|
directive.targetAspect = value.substring(1);
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
case "classList":
|
|
93
|
-
directive.aspectType = Aspect.tokenList;
|
|
94
|
-
break;
|
|
95
|
-
default:
|
|
96
|
-
directive.aspectType = Aspect.property;
|
|
97
|
-
break;
|
|
98
|
-
}
|
|
48
|
+
directive.aspectType =
|
|
49
|
+
directive.targetAspect === "classList"
|
|
50
|
+
? DOMAspect.tokenList
|
|
51
|
+
: DOMAspect.property;
|
|
99
52
|
break;
|
|
100
53
|
case "?":
|
|
101
54
|
directive.targetAspect = value.substring(1);
|
|
102
|
-
directive.aspectType =
|
|
55
|
+
directive.aspectType = DOMAspect.booleanAttribute;
|
|
103
56
|
break;
|
|
104
57
|
case "@":
|
|
105
58
|
directive.targetAspect = value.substring(1);
|
|
106
|
-
directive.aspectType =
|
|
59
|
+
directive.aspectType = DOMAspect.event;
|
|
107
60
|
break;
|
|
108
61
|
default:
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
directive.aspectType = Aspect.property;
|
|
112
|
-
}
|
|
113
|
-
else {
|
|
114
|
-
directive.targetAspect = value;
|
|
115
|
-
directive.aspectType = Aspect.attribute;
|
|
116
|
-
}
|
|
62
|
+
directive.targetAspect = value;
|
|
63
|
+
directive.aspectType = DOMAspect.attribute;
|
|
117
64
|
break;
|
|
118
65
|
}
|
|
119
66
|
},
|
|
120
67
|
});
|
|
68
|
+
/**
|
|
69
|
+
* Decorator: Defines an HTMLDirective.
|
|
70
|
+
* @param options - Provides options that specify the directive's application.
|
|
71
|
+
* @public
|
|
72
|
+
*/
|
|
73
|
+
export function htmlDirective(options) {
|
|
74
|
+
/* eslint-disable-next-line @typescript-eslint/explicit-function-return-type */
|
|
75
|
+
return function (type) {
|
|
76
|
+
HTMLDirective.define(type, options);
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Captures a binding expression along with related information and capabilities.
|
|
81
|
+
*
|
|
82
|
+
* @public
|
|
83
|
+
*/
|
|
84
|
+
export class Binding {
|
|
85
|
+
/**
|
|
86
|
+
* Creates a binding.
|
|
87
|
+
* @param evaluate - Evaluates the binding.
|
|
88
|
+
* @param policy - The security policy to associate with this binding.
|
|
89
|
+
* @param isVolatile - Indicates whether the binding is volatile.
|
|
90
|
+
*/
|
|
91
|
+
constructor(evaluate, policy, isVolatile = false) {
|
|
92
|
+
this.evaluate = evaluate;
|
|
93
|
+
this.policy = policy;
|
|
94
|
+
this.isVolatile = isVolatile;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
121
97
|
/**
|
|
122
98
|
* A base class used for attribute directives that don't need internal state.
|
|
123
99
|
* @public
|
|
@@ -129,13 +105,11 @@ export class StatelessAttachedAttributeDirective {
|
|
|
129
105
|
*/
|
|
130
106
|
constructor(options) {
|
|
131
107
|
this.options = options;
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
createBehavior(targets) {
|
|
138
|
-
return this;
|
|
108
|
+
/**
|
|
109
|
+
* Opts out of JSON stringification.
|
|
110
|
+
* @internal
|
|
111
|
+
*/
|
|
112
|
+
this.toJSON = noop;
|
|
139
113
|
}
|
|
140
114
|
/**
|
|
141
115
|
* Creates a placeholder string based on the directive's index within the template.
|
|
@@ -146,4 +120,11 @@ export class StatelessAttachedAttributeDirective {
|
|
|
146
120
|
createHTML(add) {
|
|
147
121
|
return Markup.attribute(add(this));
|
|
148
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* Creates a behavior.
|
|
125
|
+
* @param targets - The targets available for behaviors to be attached to.
|
|
126
|
+
*/
|
|
127
|
+
createBehavior() {
|
|
128
|
+
return this;
|
|
129
|
+
}
|
|
149
130
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { emptyArray } from "../platform.js";
|
|
2
|
-
import { StatelessAttachedAttributeDirective
|
|
2
|
+
import { StatelessAttachedAttributeDirective } from "./html-directive.js";
|
|
3
3
|
const selectElements = (value) => value.nodeType === 1;
|
|
4
4
|
/**
|
|
5
5
|
* Creates a function that can be used to filter a Node array, selecting only elements.
|
|
@@ -16,9 +16,15 @@ export const elements = (selector) => selector
|
|
|
16
16
|
* Internally used by the SlottedDirective and the ChildrenDirective.
|
|
17
17
|
*/
|
|
18
18
|
export class NodeObservationDirective extends StatelessAttachedAttributeDirective {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
/**
|
|
20
|
+
* The unique id of the factory.
|
|
21
|
+
*/
|
|
22
|
+
get id() {
|
|
23
|
+
return this._id;
|
|
24
|
+
}
|
|
25
|
+
set id(value) {
|
|
26
|
+
this._id = value;
|
|
27
|
+
this._controllerProperty = `${value}-c`;
|
|
22
28
|
}
|
|
23
29
|
/**
|
|
24
30
|
* Bind this behavior to the source.
|
|
@@ -26,11 +32,12 @@ export class NodeObservationDirective extends StatelessAttachedAttributeDirectiv
|
|
|
26
32
|
* @param context - The execution context that the binding is operating within.
|
|
27
33
|
* @param targets - The targets that behaviors in a view can attach to.
|
|
28
34
|
*/
|
|
29
|
-
bind(
|
|
30
|
-
const target = targets[this.
|
|
31
|
-
target[this.
|
|
32
|
-
this.updateTarget(source, this.computeNodes(target));
|
|
35
|
+
bind(controller) {
|
|
36
|
+
const target = controller.targets[this.targetNodeId];
|
|
37
|
+
target[this._controllerProperty] = controller;
|
|
38
|
+
this.updateTarget(controller.source, this.computeNodes(target));
|
|
33
39
|
this.observe(target);
|
|
40
|
+
controller.onUnbind(this);
|
|
34
41
|
}
|
|
35
42
|
/**
|
|
36
43
|
* Unbinds this behavior from the source.
|
|
@@ -38,11 +45,11 @@ export class NodeObservationDirective extends StatelessAttachedAttributeDirectiv
|
|
|
38
45
|
* @param context - The execution context that the binding is operating within.
|
|
39
46
|
* @param targets - The targets that behaviors in a view can attach to.
|
|
40
47
|
*/
|
|
41
|
-
unbind(
|
|
42
|
-
const target = targets[this.
|
|
43
|
-
this.updateTarget(source, emptyArray);
|
|
48
|
+
unbind(controller) {
|
|
49
|
+
const target = controller.targets[this.targetNodeId];
|
|
50
|
+
this.updateTarget(controller.source, emptyArray);
|
|
44
51
|
this.disconnect(target);
|
|
45
|
-
target[this.
|
|
52
|
+
target[this._controllerProperty] = null;
|
|
46
53
|
}
|
|
47
54
|
/**
|
|
48
55
|
* Gets the data source for the target.
|
|
@@ -50,7 +57,7 @@ export class NodeObservationDirective extends StatelessAttachedAttributeDirectiv
|
|
|
50
57
|
* @returns The source.
|
|
51
58
|
*/
|
|
52
59
|
getSource(target) {
|
|
53
|
-
return target[this.
|
|
60
|
+
return target[this._controllerProperty].source;
|
|
54
61
|
}
|
|
55
62
|
/**
|
|
56
63
|
* Updates the source property with the computed nodes.
|
|
@@ -5,20 +5,12 @@ import { HTMLDirective, StatelessAttachedAttributeDirective, } from "./html-dire
|
|
|
5
5
|
*/
|
|
6
6
|
export class RefDirective extends StatelessAttachedAttributeDirective {
|
|
7
7
|
/**
|
|
8
|
-
* Bind this behavior
|
|
9
|
-
* @param
|
|
10
|
-
* @param context - The execution context that the binding is operating within.
|
|
11
|
-
* @param targets - The targets that behaviors in a view can attach to.
|
|
8
|
+
* Bind this behavior.
|
|
9
|
+
* @param controller - The view controller that manages the lifecycle of this behavior.
|
|
12
10
|
*/
|
|
13
|
-
bind(
|
|
14
|
-
source[this.options] = targets[this.
|
|
11
|
+
bind(controller) {
|
|
12
|
+
controller.source[this.options] = controller.targets[this.targetNodeId];
|
|
15
13
|
}
|
|
16
|
-
/**
|
|
17
|
-
* Unbinds this behavior from the source.
|
|
18
|
-
* @param source - The source to unbind from.
|
|
19
|
-
*/
|
|
20
|
-
/* eslint-disable-next-line @typescript-eslint/no-empty-function */
|
|
21
|
-
unbind() { }
|
|
22
14
|
}
|
|
23
15
|
HTMLDirective.define(RefDirective);
|
|
24
16
|
/**
|