@microsoft/fast-element 2.0.0-beta.1 → 2.0.0-beta.4
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 +147 -0
- package/CHANGELOG.md +42 -1
- package/dist/dts/components/fast-definitions.d.ts +11 -8
- package/dist/dts/components/fast-element.d.ts +13 -3
- package/dist/dts/context.d.ts +157 -0
- package/dist/dts/di/di.d.ts +854 -0
- package/dist/dts/hooks.d.ts +2 -2
- package/dist/dts/interfaces.d.ts +39 -7
- package/dist/dts/metadata.d.ts +25 -0
- package/dist/dts/observation/arrays.d.ts +1 -1
- package/dist/dts/observation/behavior.d.ts +4 -4
- package/dist/dts/observation/observable.d.ts +59 -72
- package/dist/dts/styles/element-styles.d.ts +6 -0
- package/dist/dts/templating/binding-signal.d.ts +21 -0
- package/dist/dts/templating/binding-two-way.d.ts +31 -0
- package/dist/dts/templating/binding.d.ts +74 -201
- package/dist/dts/templating/compiler.d.ts +1 -2
- package/dist/dts/templating/html-directive.d.ts +31 -3
- package/dist/dts/templating/render.d.ts +277 -0
- package/dist/dts/templating/repeat.d.ts +13 -63
- package/dist/dts/templating/template.d.ts +11 -60
- package/dist/dts/templating/view.d.ts +9 -9
- package/dist/dts/templating/when.d.ts +3 -3
- package/dist/dts/testing/exports.d.ts +2 -0
- package/dist/dts/testing/fixture.d.ts +90 -0
- package/dist/dts/testing/timeout.d.ts +7 -0
- package/dist/{tsdoc-metadata.json → dts/tsdoc-metadata.json} +0 -0
- package/dist/esm/components/fast-definitions.js +27 -27
- package/dist/esm/components/fast-element.js +20 -4
- package/dist/esm/context.js +163 -0
- package/dist/esm/debug.js +35 -4
- package/dist/esm/di/di.js +1349 -0
- package/dist/esm/metadata.js +60 -0
- package/dist/esm/observation/arrays.js +1 -1
- package/dist/esm/observation/observable.js +73 -21
- package/dist/esm/platform.js +1 -1
- package/dist/esm/styles/element-styles.js +14 -0
- package/dist/esm/templating/binding-signal.js +79 -0
- package/dist/esm/templating/binding-two-way.js +98 -0
- package/dist/esm/templating/binding.js +137 -313
- package/dist/esm/templating/compiler.js +30 -7
- package/dist/esm/templating/html-directive.js +16 -2
- package/dist/esm/templating/render.js +392 -0
- package/dist/esm/templating/repeat.js +60 -38
- package/dist/esm/templating/template.js +9 -26
- package/dist/esm/templating/when.js +5 -4
- package/dist/esm/testing/exports.js +2 -0
- package/dist/esm/testing/fixture.js +88 -0
- package/dist/esm/testing/timeout.js +24 -0
- package/dist/fast-element.api.json +8509 -10358
- package/dist/fast-element.d.ts +315 -522
- package/dist/fast-element.debug.js +417 -438
- package/dist/fast-element.debug.min.js +1 -1
- package/dist/fast-element.js +382 -434
- package/dist/fast-element.min.js +1 -1
- package/dist/fast-element.untrimmed.d.ts +324 -529
- package/docs/api-report.md +124 -232
- package/package.json +32 -4
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isFunction } from "../interfaces.js";
|
|
2
2
|
import { ExecutionContext, Observable, } from "../observation/observable.js";
|
|
3
3
|
import { FAST } from "../platform.js";
|
|
4
4
|
import { DOM } from "./dom.js";
|
|
5
|
-
import { Aspect, HTMLDirective, } from "./html-directive.js";
|
|
6
|
-
import { Markup } from "./markup.js";
|
|
5
|
+
import { Aspect, Binding, HTMLDirective, } from "./html-directive.js";
|
|
6
|
+
import { Markup, nextId } from "./markup.js";
|
|
7
7
|
const createInnerHTMLBinding = globalThis.TrustedHTML
|
|
8
8
|
? (binding) => (s, c) => {
|
|
9
9
|
const value = binding(s, c);
|
|
@@ -13,99 +13,28 @@ const createInnerHTMLBinding = globalThis.TrustedHTML
|
|
|
13
13
|
throw FAST.error(1202 /* Message.bindingInnerHTMLRequiresTrustedTypes */);
|
|
14
14
|
}
|
|
15
15
|
: (binding) => binding;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Creates a binding mode based on the supplied behavior types.
|
|
23
|
-
* @param UpdateType - The base behavior type used to update aspects.
|
|
24
|
-
* @param EventType - The base behavior type used to respond to events.
|
|
25
|
-
* @returns A new binding mode.
|
|
26
|
-
*/
|
|
27
|
-
define(UpdateType, EventType = EventBinding) {
|
|
28
|
-
return Object.freeze({
|
|
29
|
-
[1]: d => new UpdateType(d, DOM.setAttribute),
|
|
30
|
-
[2]: d => new UpdateType(d, DOM.setBooleanAttribute),
|
|
31
|
-
[3]: d => new UpdateType(d, (t, a, v) => (t[a] = v)),
|
|
32
|
-
[4]: d => new (createContentBinding(UpdateType))(d, updateContentTarget),
|
|
33
|
-
[5]: d => new UpdateType(d, updateTokenListTarget),
|
|
34
|
-
[6]: d => new EventType(d),
|
|
35
|
-
});
|
|
36
|
-
},
|
|
37
|
-
});
|
|
38
|
-
/**
|
|
39
|
-
* Describes the configuration for a binding expression.
|
|
40
|
-
* @public
|
|
41
|
-
*/
|
|
42
|
-
export const BindingConfig = Object.freeze({
|
|
43
|
-
/**
|
|
44
|
-
* Creates a binding configuration based on the provided mode and options.
|
|
45
|
-
* @param mode - The mode to use for the configuration.
|
|
46
|
-
* @param defaultOptions - The default options to use for the configuration.
|
|
47
|
-
* @returns A new binding configuration.
|
|
48
|
-
*/
|
|
49
|
-
define(mode, defaultOptions) {
|
|
50
|
-
const config = (options) => {
|
|
51
|
-
return {
|
|
52
|
-
mode: config.mode,
|
|
53
|
-
options: Object.assign({}, defaultOptions, options),
|
|
54
|
-
};
|
|
55
|
-
};
|
|
56
|
-
config.options = defaultOptions;
|
|
57
|
-
config.mode = mode;
|
|
58
|
-
return config;
|
|
59
|
-
},
|
|
60
|
-
});
|
|
61
|
-
/**
|
|
62
|
-
* A base binding behavior for DOM updates.
|
|
63
|
-
* @public
|
|
64
|
-
*/
|
|
65
|
-
export class UpdateBinding {
|
|
66
|
-
/**
|
|
67
|
-
* Creates an instance of UpdateBinding.
|
|
68
|
-
* @param directive - The directive that has the configuration for this behavior.
|
|
69
|
-
* @param updateTarget - The function used to update the target with the latest value.
|
|
70
|
-
*/
|
|
71
|
-
constructor(directive, updateTarget) {
|
|
72
|
-
this.directive = directive;
|
|
73
|
-
this.updateTarget = updateTarget;
|
|
16
|
+
class OnChangeBinding extends Binding {
|
|
17
|
+
constructor(evaluate, isVolatile) {
|
|
18
|
+
super();
|
|
19
|
+
this.evaluate = evaluate;
|
|
20
|
+
this.isVolatile = isVolatile;
|
|
74
21
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
* @param source - The source to bind to.
|
|
78
|
-
* @param context - The execution context that the binding is operating within.
|
|
79
|
-
* @param targets - The targets that behaviors in a view can attach to.
|
|
80
|
-
*/
|
|
81
|
-
bind(source, context, targets) { }
|
|
82
|
-
/**
|
|
83
|
-
* Unbinds this behavior from the source.
|
|
84
|
-
* @param source - The source to unbind from.
|
|
85
|
-
* @param context - The execution context that the binding is operating within.
|
|
86
|
-
* @param targets - The targets that behaviors in a view can attach to.
|
|
87
|
-
*/
|
|
88
|
-
unbind(source, context, targets) { }
|
|
89
|
-
/**
|
|
90
|
-
* Creates a behavior.
|
|
91
|
-
* @param targets - The targets available for behaviors to be attached to.
|
|
92
|
-
*/
|
|
93
|
-
createBehavior(targets) {
|
|
94
|
-
return this;
|
|
22
|
+
createObserver(_, subscriber) {
|
|
23
|
+
return Observable.binding(this.evaluate, subscriber, this.isVolatile);
|
|
95
24
|
}
|
|
96
25
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
26
|
+
class OneTimeBinding extends Binding {
|
|
27
|
+
constructor(evaluate) {
|
|
28
|
+
super();
|
|
29
|
+
this.evaluate = evaluate;
|
|
30
|
+
}
|
|
31
|
+
createObserver() {
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
observe(source, context) {
|
|
35
|
+
return this.evaluate(source, context);
|
|
36
|
+
}
|
|
37
|
+
dispose() { }
|
|
109
38
|
}
|
|
110
39
|
function updateContentTarget(target, aspect, value, source, context) {
|
|
111
40
|
// If there's no actual value, then this equates to the
|
|
@@ -113,7 +42,7 @@ function updateContentTarget(target, aspect, value, source, context) {
|
|
|
113
42
|
if (value === null || value === undefined) {
|
|
114
43
|
value = "";
|
|
115
44
|
}
|
|
116
|
-
// If the value has a "create" method, then it's a
|
|
45
|
+
// If the value has a "create" method, then it's a ContentTemplate.
|
|
117
46
|
if (value.create) {
|
|
118
47
|
target.textContent = "";
|
|
119
48
|
let view = target.$fastView;
|
|
@@ -199,118 +128,21 @@ function updateTokenListTarget(target, aspect, value) {
|
|
|
199
128
|
}
|
|
200
129
|
}
|
|
201
130
|
}
|
|
202
|
-
/**
|
|
203
|
-
* A binding behavior for one-time bindings.
|
|
204
|
-
* @public
|
|
205
|
-
*/
|
|
206
|
-
export class OneTimeBinding extends UpdateBinding {
|
|
207
|
-
/**
|
|
208
|
-
* Bind this behavior to the source.
|
|
209
|
-
* @param source - The source to bind to.
|
|
210
|
-
* @param context - The execution context that the binding is operating within.
|
|
211
|
-
* @param targets - The targets that behaviors in a view can attach to.
|
|
212
|
-
*/
|
|
213
|
-
bind(source, context, targets) {
|
|
214
|
-
const directive = this.directive;
|
|
215
|
-
this.updateTarget(targets[directive.nodeId], directive.targetAspect, directive.binding(source, context), source, context);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
const signals = Object.create(null);
|
|
219
|
-
/**
|
|
220
|
-
* A binding behavior for signal bindings.
|
|
221
|
-
* @public
|
|
222
|
-
*/
|
|
223
|
-
export class SignalBinding extends UpdateBinding {
|
|
224
|
-
constructor() {
|
|
225
|
-
super(...arguments);
|
|
226
|
-
this.handlerProperty = `${this.directive.id}-h`;
|
|
227
|
-
}
|
|
228
|
-
/**
|
|
229
|
-
* Bind this behavior to the source.
|
|
230
|
-
* @param source - The source to bind to.
|
|
231
|
-
* @param context - The execution context that the binding is operating within.
|
|
232
|
-
* @param targets - The targets that behaviors in a view can attach to.
|
|
233
|
-
*/
|
|
234
|
-
bind(source, context, targets) {
|
|
235
|
-
const directive = this.directive;
|
|
236
|
-
const target = targets[directive.nodeId];
|
|
237
|
-
const signal = this.getSignal(source, context);
|
|
238
|
-
const handler = (target[this.handlerProperty] = () => {
|
|
239
|
-
this.updateTarget(target, directive.targetAspect, directive.binding(source, context), source, context);
|
|
240
|
-
});
|
|
241
|
-
handler();
|
|
242
|
-
const found = signals[signal];
|
|
243
|
-
if (found) {
|
|
244
|
-
Array.isArray(found)
|
|
245
|
-
? found.push(handler)
|
|
246
|
-
: (signals[signal] = [found, handler]);
|
|
247
|
-
}
|
|
248
|
-
else {
|
|
249
|
-
signals[signal] = handler;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
/**
|
|
253
|
-
* Unbinds this behavior from the source.
|
|
254
|
-
* @param source - The source to unbind from.
|
|
255
|
-
* @param context - The execution context that the binding is operating within.
|
|
256
|
-
* @param targets - The targets that behaviors in a view can attach to.
|
|
257
|
-
*/
|
|
258
|
-
unbind(source, context, targets) {
|
|
259
|
-
const signal = this.getSignal(source, context);
|
|
260
|
-
const found = signals[signal];
|
|
261
|
-
if (found && Array.isArray(found)) {
|
|
262
|
-
const directive = this.directive;
|
|
263
|
-
const target = targets[directive.nodeId];
|
|
264
|
-
const handler = target[this.handlerProperty];
|
|
265
|
-
const index = found.indexOf(handler);
|
|
266
|
-
if (index !== -1) {
|
|
267
|
-
found.splice(index, 1);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
else {
|
|
271
|
-
signals[signal] = void 0;
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
getSignal(source, context) {
|
|
275
|
-
const options = this.directive.options;
|
|
276
|
-
return isString(options) ? options : options(source, context);
|
|
277
|
-
}
|
|
278
|
-
/**
|
|
279
|
-
* Sends the specified signal to signaled bindings.
|
|
280
|
-
* @param signal - The signal to send.
|
|
281
|
-
* @public
|
|
282
|
-
*/
|
|
283
|
-
static send(signal) {
|
|
284
|
-
const found = signals[signal];
|
|
285
|
-
if (found) {
|
|
286
|
-
Array.isArray(found) ? found.forEach(x => x()) : found();
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
131
|
/**
|
|
291
132
|
* A binding behavior for bindings that change.
|
|
292
133
|
* @public
|
|
293
134
|
*/
|
|
294
|
-
export class
|
|
135
|
+
export class BindingBehavior {
|
|
295
136
|
/**
|
|
296
137
|
* Creates an instance of ChangeBinding.
|
|
297
138
|
* @param directive - The directive that has the configuration for this behavior.
|
|
298
139
|
* @param updateTarget - The function used to update the target with the latest value.
|
|
299
140
|
*/
|
|
300
141
|
constructor(directive, updateTarget) {
|
|
301
|
-
|
|
302
|
-
this.
|
|
142
|
+
this.directive = directive;
|
|
143
|
+
this.updateTarget = updateTarget;
|
|
303
144
|
this.observerProperty = `${directive.id}-o`;
|
|
304
145
|
}
|
|
305
|
-
/**
|
|
306
|
-
* Returns the binding observer used to update the node.
|
|
307
|
-
* @param target - The target node.
|
|
308
|
-
* @returns A BindingObserver.
|
|
309
|
-
*/
|
|
310
|
-
getObserver(target) {
|
|
311
|
-
var _a;
|
|
312
|
-
return ((_a = target[this.observerProperty]) !== null && _a !== void 0 ? _a : (target[this.observerProperty] = Observable.binding(this.directive.binding, this, this.isBindingVolatile)));
|
|
313
|
-
}
|
|
314
146
|
/**
|
|
315
147
|
* Bind this behavior to the source.
|
|
316
148
|
* @param source - The source to bind to.
|
|
@@ -347,12 +179,49 @@ export class ChangeBinding extends UpdateBinding {
|
|
|
347
179
|
const context = observer.context;
|
|
348
180
|
this.updateTarget(target, this.directive.targetAspect, observer.observe(source, context), source, context);
|
|
349
181
|
}
|
|
182
|
+
/**
|
|
183
|
+
* Returns the binding observer used to update the node.
|
|
184
|
+
* @param target - The target node.
|
|
185
|
+
* @returns A BindingObserver.
|
|
186
|
+
*/
|
|
187
|
+
getObserver(target) {
|
|
188
|
+
var _a;
|
|
189
|
+
return ((_a = target[this.observerProperty]) !== null && _a !== void 0 ? _a : (target[this.observerProperty] = this.directive.dataBinding.createObserver(this.directive, this)));
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Creates a behavior.
|
|
193
|
+
* @param targets - The targets available for behaviors to be attached to.
|
|
194
|
+
*/
|
|
195
|
+
createBehavior(targets) {
|
|
196
|
+
return this;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* A special binding behavior that can bind node content.
|
|
201
|
+
* @public
|
|
202
|
+
*/
|
|
203
|
+
export class ContentBehavior extends BindingBehavior {
|
|
204
|
+
/**
|
|
205
|
+
* Unbinds this behavior from the source.
|
|
206
|
+
* @param source - The source to unbind from.
|
|
207
|
+
* @param context - The execution context that the binding is operating within.
|
|
208
|
+
* @param targets - The targets that behaviors in a view can attach to.
|
|
209
|
+
*/
|
|
210
|
+
unbind(source, context, targets) {
|
|
211
|
+
super.unbind(source, context, targets);
|
|
212
|
+
const target = targets[this.directive.nodeId];
|
|
213
|
+
const view = target.$fastView;
|
|
214
|
+
if (view !== void 0 && view.isComposed) {
|
|
215
|
+
view.unbind();
|
|
216
|
+
view.needsBindOnly = true;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
350
219
|
}
|
|
351
220
|
/**
|
|
352
221
|
* A binding behavior for handling events.
|
|
353
222
|
* @public
|
|
354
223
|
*/
|
|
355
|
-
export class
|
|
224
|
+
export class EventBehavior {
|
|
356
225
|
/**
|
|
357
226
|
* Creates an instance of EventBinding.
|
|
358
227
|
* @param directive - The directive that has the configuration for this behavior.
|
|
@@ -373,7 +242,7 @@ export class EventBinding {
|
|
|
373
242
|
const target = targets[directive.nodeId];
|
|
374
243
|
target[this.sourceProperty] = source;
|
|
375
244
|
target[this.contextProperty] = context;
|
|
376
|
-
target.addEventListener(directive.targetAspect, this, directive.options);
|
|
245
|
+
target.addEventListener(directive.targetAspect, this, directive.dataBinding.options);
|
|
377
246
|
}
|
|
378
247
|
/**
|
|
379
248
|
* Unbinds this behavior from the source.
|
|
@@ -385,7 +254,7 @@ export class EventBinding {
|
|
|
385
254
|
const directive = this.directive;
|
|
386
255
|
const target = targets[directive.nodeId];
|
|
387
256
|
target[this.sourceProperty] = target[this.contextProperty] = null;
|
|
388
|
-
target.removeEventListener(directive.targetAspect, this, directive.options);
|
|
257
|
+
target.removeEventListener(directive.targetAspect, this, directive.dataBinding.options);
|
|
389
258
|
}
|
|
390
259
|
/**
|
|
391
260
|
* Creates a behavior.
|
|
@@ -400,110 +269,13 @@ export class EventBinding {
|
|
|
400
269
|
handleEvent(event) {
|
|
401
270
|
const target = event.currentTarget;
|
|
402
271
|
ExecutionContext.setEvent(event);
|
|
403
|
-
const result = this.directive.
|
|
272
|
+
const result = this.directive.dataBinding.evaluate(target[this.sourceProperty], target[this.contextProperty]);
|
|
404
273
|
ExecutionContext.setEvent(null);
|
|
405
274
|
if (result !== true) {
|
|
406
275
|
event.preventDefault();
|
|
407
276
|
}
|
|
408
277
|
}
|
|
409
278
|
}
|
|
410
|
-
let twoWaySettings = {
|
|
411
|
-
determineChangeEvent() {
|
|
412
|
-
return "change";
|
|
413
|
-
},
|
|
414
|
-
};
|
|
415
|
-
/**
|
|
416
|
-
* A binding behavior for bindings that update in two directions.
|
|
417
|
-
* @public
|
|
418
|
-
*/
|
|
419
|
-
export class TwoWayBinding extends ChangeBinding {
|
|
420
|
-
/**
|
|
421
|
-
* Bind this behavior to the source.
|
|
422
|
-
* @param source - The source to bind to.
|
|
423
|
-
* @param context - The execution context that the binding is operating within.
|
|
424
|
-
* @param targets - The targets that behaviors in a view can attach to.
|
|
425
|
-
*/
|
|
426
|
-
bind(source, context, targets) {
|
|
427
|
-
var _a;
|
|
428
|
-
super.bind(source, context, targets);
|
|
429
|
-
const directive = this.directive;
|
|
430
|
-
const target = targets[directive.nodeId];
|
|
431
|
-
if (!this.changeEvent) {
|
|
432
|
-
this.changeEvent =
|
|
433
|
-
(_a = directive.options.changeEvent) !== null && _a !== void 0 ? _a : twoWaySettings.determineChangeEvent(directive, target);
|
|
434
|
-
}
|
|
435
|
-
target.addEventListener(this.changeEvent, this);
|
|
436
|
-
}
|
|
437
|
-
/**
|
|
438
|
-
* Unbinds this behavior from the source.
|
|
439
|
-
* @param source - The source to unbind from.
|
|
440
|
-
* @param context - The execution context that the binding is operating within.
|
|
441
|
-
* @param targets - The targets that behaviors in a view can attach to.
|
|
442
|
-
*/
|
|
443
|
-
unbind(source, context, targets) {
|
|
444
|
-
super.unbind(source, context, targets);
|
|
445
|
-
targets[this.directive.nodeId].removeEventListener(this.changeEvent, this);
|
|
446
|
-
}
|
|
447
|
-
/** @internal */
|
|
448
|
-
handleEvent(event) {
|
|
449
|
-
const directive = this.directive;
|
|
450
|
-
const target = event.currentTarget;
|
|
451
|
-
let value;
|
|
452
|
-
switch (directive.aspectType) {
|
|
453
|
-
case 1:
|
|
454
|
-
value = target.getAttribute(directive.targetAspect);
|
|
455
|
-
break;
|
|
456
|
-
case 2:
|
|
457
|
-
value = target.hasAttribute(directive.targetAspect);
|
|
458
|
-
break;
|
|
459
|
-
case 4:
|
|
460
|
-
value = target.innerText;
|
|
461
|
-
break;
|
|
462
|
-
default:
|
|
463
|
-
value = target[directive.targetAspect];
|
|
464
|
-
break;
|
|
465
|
-
}
|
|
466
|
-
const observer = this.getObserver(target);
|
|
467
|
-
const last = observer.last; // using internal API!!!
|
|
468
|
-
last.propertySource[last.propertyName] = directive.options.fromView(value);
|
|
469
|
-
}
|
|
470
|
-
/**
|
|
471
|
-
* Configures two-way binding.
|
|
472
|
-
* @param settings - The settings to use for the two-way binding system.
|
|
473
|
-
*/
|
|
474
|
-
static configure(settings) {
|
|
475
|
-
twoWaySettings = settings;
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
/**
|
|
479
|
-
* The default onChange binding configuration.
|
|
480
|
-
* @public
|
|
481
|
-
*/
|
|
482
|
-
export const onChange = BindingConfig.define(BindingMode.define(ChangeBinding), {});
|
|
483
|
-
/**
|
|
484
|
-
* The default twoWay binding configuration.
|
|
485
|
-
* @public
|
|
486
|
-
*/
|
|
487
|
-
export const twoWay = BindingConfig.define(BindingMode.define(TwoWayBinding), {
|
|
488
|
-
fromView: v => v,
|
|
489
|
-
});
|
|
490
|
-
/**
|
|
491
|
-
* The default onTime binding configuration.
|
|
492
|
-
* @public
|
|
493
|
-
*/
|
|
494
|
-
export const oneTime = BindingConfig.define(BindingMode.define(OneTimeBinding), {
|
|
495
|
-
once: true,
|
|
496
|
-
});
|
|
497
|
-
const signalMode = BindingMode.define(SignalBinding);
|
|
498
|
-
/**
|
|
499
|
-
* Creates a signal binding configuration with the supplied options.
|
|
500
|
-
* @param options - The signal name or a binding to use to retrieve the signal name.
|
|
501
|
-
* @returns A binding configuration.
|
|
502
|
-
* @public
|
|
503
|
-
*/
|
|
504
|
-
export const signal = (options) => {
|
|
505
|
-
return { mode: signalMode, options };
|
|
506
|
-
};
|
|
507
279
|
/**
|
|
508
280
|
* A directive that applies bindings.
|
|
509
281
|
* @public
|
|
@@ -511,15 +283,15 @@ export const signal = (options) => {
|
|
|
511
283
|
export class HTMLBindingDirective {
|
|
512
284
|
/**
|
|
513
285
|
* Creates an instance of HTMLBindingDirective.
|
|
514
|
-
* @param
|
|
515
|
-
* @param mode - The binding mode to use when applying the binding.
|
|
516
|
-
* @param options - The options to configure the binding with.
|
|
286
|
+
* @param dataBinding - The binding configuration to apply.
|
|
517
287
|
*/
|
|
518
|
-
constructor(
|
|
519
|
-
this.
|
|
520
|
-
this.mode = mode;
|
|
521
|
-
this.options = options;
|
|
288
|
+
constructor(dataBinding) {
|
|
289
|
+
this.dataBinding = dataBinding;
|
|
522
290
|
this.factory = null;
|
|
291
|
+
/**
|
|
292
|
+
* The unique id of the factory.
|
|
293
|
+
*/
|
|
294
|
+
this.id = nextId();
|
|
523
295
|
/**
|
|
524
296
|
* The type of aspect to target.
|
|
525
297
|
*/
|
|
@@ -539,24 +311,76 @@ export class HTMLBindingDirective {
|
|
|
539
311
|
createBehavior(targets) {
|
|
540
312
|
if (this.factory == null) {
|
|
541
313
|
if (this.targetAspect === "innerHTML") {
|
|
542
|
-
this.
|
|
314
|
+
this.dataBinding.evaluate = createInnerHTMLBinding(this.dataBinding.evaluate);
|
|
315
|
+
}
|
|
316
|
+
switch (this.aspectType) {
|
|
317
|
+
case 1:
|
|
318
|
+
this.factory = new BindingBehavior(this, DOM.setAttribute);
|
|
319
|
+
break;
|
|
320
|
+
case 2:
|
|
321
|
+
this.factory = new BindingBehavior(this, DOM.setBooleanAttribute);
|
|
322
|
+
break;
|
|
323
|
+
case 3:
|
|
324
|
+
this.factory = new BindingBehavior(this, (t, a, v) => (t[a] = v));
|
|
325
|
+
break;
|
|
326
|
+
case 4:
|
|
327
|
+
this.factory = new ContentBehavior(this, updateContentTarget);
|
|
328
|
+
break;
|
|
329
|
+
case 5:
|
|
330
|
+
this.factory = new BindingBehavior(this, updateTokenListTarget);
|
|
331
|
+
break;
|
|
332
|
+
case 6:
|
|
333
|
+
this.factory = new EventBehavior(this);
|
|
334
|
+
break;
|
|
335
|
+
default:
|
|
336
|
+
throw FAST.error(1205 /* Message.unsupportedBindingBehavior */);
|
|
543
337
|
}
|
|
544
|
-
this.factory = this.mode[this.aspectType](this);
|
|
545
338
|
}
|
|
546
339
|
return this.factory.createBehavior(targets);
|
|
547
340
|
}
|
|
548
341
|
}
|
|
549
342
|
HTMLDirective.define(HTMLBindingDirective, { aspected: true });
|
|
550
343
|
/**
|
|
551
|
-
* Creates
|
|
552
|
-
* @param binding - The binding
|
|
553
|
-
* @param
|
|
554
|
-
* @returns A binding
|
|
344
|
+
* Creates an standard binding.
|
|
345
|
+
* @param binding - The binding to refresh when changed.
|
|
346
|
+
* @param isVolatile - Indicates whether the binding is volatile or not.
|
|
347
|
+
* @returns A binding configuration.
|
|
555
348
|
* @public
|
|
556
349
|
*/
|
|
557
|
-
export function bind(binding,
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
350
|
+
export function bind(binding, isVolatile = Observable.isVolatileBinding(binding)) {
|
|
351
|
+
return new OnChangeBinding(binding, isVolatile);
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Creates a one time binding
|
|
355
|
+
* @param binding - The binding to refresh when signaled.
|
|
356
|
+
* @returns A binding configuration.
|
|
357
|
+
* @public
|
|
358
|
+
*/
|
|
359
|
+
export function oneTime(binding) {
|
|
360
|
+
return new OneTimeBinding(binding);
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Creates an event listener binding.
|
|
364
|
+
* @param binding - The binding to invoke when the event is raised.
|
|
365
|
+
* @param options - Event listener options.
|
|
366
|
+
* @returns A binding configuration.
|
|
367
|
+
* @public
|
|
368
|
+
*/
|
|
369
|
+
export function listener(binding, options) {
|
|
370
|
+
const config = new OnChangeBinding(binding, false);
|
|
371
|
+
config.options = options;
|
|
372
|
+
return config;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Normalizes the input value into a binding.
|
|
376
|
+
* @param value - The value to create the default binding for.
|
|
377
|
+
* @returns A binding configuration for the provided value.
|
|
378
|
+
* @public
|
|
379
|
+
*/
|
|
380
|
+
export function normalizeBinding(value) {
|
|
381
|
+
return isFunction(value)
|
|
382
|
+
? bind(value)
|
|
383
|
+
: value instanceof Binding
|
|
384
|
+
? value
|
|
385
|
+
: oneTime(() => value);
|
|
562
386
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { isString } from "../interfaces.js";
|
|
1
|
+
import { isFunction, isString } from "../interfaces.js";
|
|
2
2
|
import { FAST } from "../platform.js";
|
|
3
3
|
import { Parser } from "./markup.js";
|
|
4
|
-
import {
|
|
4
|
+
import { HTMLBindingDirective, oneTime } from "./binding.js";
|
|
5
5
|
import { Aspect } from "./html-directive.js";
|
|
6
6
|
import { HTMLView } from "./view.js";
|
|
7
7
|
const targetIdFrom = (parentId, nodeIndex) => `${parentId}.${nodeIndex}`;
|
|
@@ -11,6 +11,22 @@ const next = {
|
|
|
11
11
|
index: 0,
|
|
12
12
|
node: null,
|
|
13
13
|
};
|
|
14
|
+
function tryWarn(name) {
|
|
15
|
+
if (!name.startsWith("fast-")) {
|
|
16
|
+
FAST.warn(1204 /* Message.hostBindingWithoutHost */, { name });
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
const warningHost = new Proxy(document.createElement("div"), {
|
|
20
|
+
get(target, property) {
|
|
21
|
+
tryWarn(property);
|
|
22
|
+
const value = Reflect.get(target, property);
|
|
23
|
+
return isFunction(value) ? value.bind(target) : value;
|
|
24
|
+
},
|
|
25
|
+
set(target, property, value) {
|
|
26
|
+
tryWarn(property);
|
|
27
|
+
return Reflect.set(target, property, value);
|
|
28
|
+
},
|
|
29
|
+
});
|
|
14
30
|
class CompilationContext {
|
|
15
31
|
constructor(fragment, directives) {
|
|
16
32
|
this.fragment = fragment;
|
|
@@ -61,7 +77,7 @@ class CompilationContext {
|
|
|
61
77
|
const fragment = this.fragment.cloneNode(true);
|
|
62
78
|
const targets = Object.create(this.proto);
|
|
63
79
|
targets.r = fragment;
|
|
64
|
-
targets.h = hostBindingTarget !== null && hostBindingTarget !== void 0 ? hostBindingTarget :
|
|
80
|
+
targets.h = hostBindingTarget !== null && hostBindingTarget !== void 0 ? hostBindingTarget : warningHost;
|
|
65
81
|
for (const id of this.nodeIds) {
|
|
66
82
|
targets[id]; // trigger locator
|
|
67
83
|
}
|
|
@@ -78,7 +94,7 @@ function compileAttributes(context, parentId, node, nodeId, nodeIndex, includeBa
|
|
|
78
94
|
let result = null;
|
|
79
95
|
if (parseResult === null) {
|
|
80
96
|
if (includeBasicValues) {
|
|
81
|
-
result =
|
|
97
|
+
result = new HTMLBindingDirective(oneTime(() => attrValue));
|
|
82
98
|
Aspect.assign(result, attr.name);
|
|
83
99
|
}
|
|
84
100
|
}
|
|
@@ -115,6 +131,7 @@ function compileContent(context, node, parentId, nodeId, nodeIndex) {
|
|
|
115
131
|
}
|
|
116
132
|
else {
|
|
117
133
|
currentNode.textContent = " ";
|
|
134
|
+
Aspect.assign(currentPart);
|
|
118
135
|
context.addFactory(currentPart, parentId, nodeId, nodeIndex);
|
|
119
136
|
}
|
|
120
137
|
lastNode = currentNode;
|
|
@@ -247,22 +264,28 @@ export const Compiler = {
|
|
|
247
264
|
return parts[0];
|
|
248
265
|
}
|
|
249
266
|
let sourceAspect;
|
|
267
|
+
let binding;
|
|
268
|
+
let isVolatile = false;
|
|
250
269
|
const partCount = parts.length;
|
|
251
270
|
const finalParts = parts.map((x) => {
|
|
252
271
|
if (isString(x)) {
|
|
253
272
|
return () => x;
|
|
254
273
|
}
|
|
255
274
|
sourceAspect = x.sourceAspect || sourceAspect;
|
|
256
|
-
|
|
275
|
+
binding = x.dataBinding || binding;
|
|
276
|
+
isVolatile = isVolatile || x.dataBinding.isVolatile;
|
|
277
|
+
return x.dataBinding.evaluate;
|
|
257
278
|
});
|
|
258
|
-
const
|
|
279
|
+
const expression = (scope, context) => {
|
|
259
280
|
let output = "";
|
|
260
281
|
for (let i = 0; i < partCount; ++i) {
|
|
261
282
|
output += finalParts[i](scope, context);
|
|
262
283
|
}
|
|
263
284
|
return output;
|
|
264
285
|
};
|
|
265
|
-
|
|
286
|
+
binding.evaluate = expression;
|
|
287
|
+
binding.isVolatile = isVolatile;
|
|
288
|
+
const directive = new HTMLBindingDirective(binding);
|
|
266
289
|
Aspect.assign(directive, sourceAspect);
|
|
267
290
|
return directive;
|
|
268
291
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createTypeRegistry } from "../platform.js";
|
|
2
|
-
import { Markup } from "./markup.js";
|
|
2
|
+
import { Markup, nextId } from "./markup.js";
|
|
3
3
|
const registry = createTypeRegistry();
|
|
4
4
|
/**
|
|
5
5
|
* Instructs the template engine to apply behavior to a node.
|
|
@@ -39,6 +39,13 @@ export function htmlDirective(options) {
|
|
|
39
39
|
HTMLDirective.define(type, options);
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Captures a binding expression along with related information and capabilities.
|
|
44
|
+
*
|
|
45
|
+
* @public
|
|
46
|
+
*/
|
|
47
|
+
export class Binding {
|
|
48
|
+
}
|
|
42
49
|
/**
|
|
43
50
|
* The type of HTML aspect to target.
|
|
44
51
|
* @public
|
|
@@ -76,12 +83,15 @@ export const Aspect = Object.freeze({
|
|
|
76
83
|
*
|
|
77
84
|
* @param directive - The directive to assign the aspect to.
|
|
78
85
|
* @param value - The value to base the aspect determination on.
|
|
86
|
+
* @remarks
|
|
87
|
+
* If a falsy value is provided, then the content aspect will be assigned.
|
|
79
88
|
*/
|
|
80
89
|
assign(directive, value) {
|
|
81
|
-
directive.sourceAspect = value;
|
|
82
90
|
if (!value) {
|
|
91
|
+
directive.aspectType = Aspect.content;
|
|
83
92
|
return;
|
|
84
93
|
}
|
|
94
|
+
directive.sourceAspect = value;
|
|
85
95
|
switch (value[0]) {
|
|
86
96
|
case ":":
|
|
87
97
|
directive.targetAspect = value.substring(1);
|
|
@@ -129,6 +139,10 @@ export class StatelessAttachedAttributeDirective {
|
|
|
129
139
|
*/
|
|
130
140
|
constructor(options) {
|
|
131
141
|
this.options = options;
|
|
142
|
+
/**
|
|
143
|
+
* The unique id of the factory.
|
|
144
|
+
*/
|
|
145
|
+
this.id = nextId();
|
|
132
146
|
}
|
|
133
147
|
/**
|
|
134
148
|
* Creates a behavior.
|