@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,45 +1,66 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isString, noop } from "../interfaces.js";
|
|
2
|
+
import { Observable, } from "../observation/observable.js";
|
|
3
|
+
import { FAST } from "../platform.js";
|
|
4
|
+
import { Binding } from "./html-directive.js";
|
|
5
|
+
const defaultOptions = {
|
|
6
|
+
fromView: v => v,
|
|
7
|
+
};
|
|
2
8
|
let twoWaySettings = {
|
|
3
9
|
determineChangeEvent() {
|
|
4
10
|
return "change";
|
|
5
11
|
},
|
|
6
12
|
};
|
|
7
|
-
|
|
8
|
-
* A binding behavior for bindings that update in two directions.
|
|
9
|
-
* @public
|
|
10
|
-
*/
|
|
11
|
-
export class TwoWayBinding extends ChangeBinding {
|
|
13
|
+
export const TwoWaySettings = Object.freeze({
|
|
12
14
|
/**
|
|
13
|
-
*
|
|
14
|
-
* @param
|
|
15
|
-
* @param context - The execution context that the binding is operating within.
|
|
16
|
-
* @param targets - The targets that behaviors in a view can attach to.
|
|
15
|
+
* Configures two-way binding.
|
|
16
|
+
* @param settings - The settings to use for the two-way binding system.
|
|
17
17
|
*/
|
|
18
|
-
|
|
18
|
+
configure(settings) {
|
|
19
|
+
twoWaySettings = settings;
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
class TwoWayObserver {
|
|
23
|
+
constructor(directive, subscriber, dataBinding) {
|
|
24
|
+
this.directive = directive;
|
|
25
|
+
this.subscriber = subscriber;
|
|
26
|
+
this.dataBinding = dataBinding;
|
|
27
|
+
this.isNotBound = true;
|
|
28
|
+
/**
|
|
29
|
+
* Opts out of JSON stringification.
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
this.toJSON = noop;
|
|
33
|
+
this.notifier = Observable.binding(dataBinding.evaluate, this, dataBinding.isVolatile);
|
|
34
|
+
}
|
|
35
|
+
bind(controller) {
|
|
19
36
|
var _a;
|
|
20
|
-
super.bind(source, context, targets);
|
|
21
|
-
const directive = this.directive;
|
|
22
|
-
const target = targets[directive.nodeId];
|
|
23
37
|
if (!this.changeEvent) {
|
|
24
38
|
this.changeEvent =
|
|
25
|
-
(_a =
|
|
39
|
+
(_a = this.dataBinding.options.changeEvent) !== null && _a !== void 0 ? _a : twoWaySettings.determineChangeEvent(this.directive, this.target);
|
|
26
40
|
}
|
|
27
|
-
|
|
41
|
+
if (this.isNotBound) {
|
|
42
|
+
this.target.addEventListener(this.changeEvent, this);
|
|
43
|
+
controller.onUnbind(this);
|
|
44
|
+
this.isNotBound = false;
|
|
45
|
+
}
|
|
46
|
+
return this.notifier.bind(controller);
|
|
28
47
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
unbind(source, context, targets) {
|
|
36
|
-
super.unbind(source, context, targets);
|
|
37
|
-
targets[this.directive.nodeId].removeEventListener(this.changeEvent, this);
|
|
48
|
+
unbind(controller) {
|
|
49
|
+
this.isNotBound = true;
|
|
50
|
+
this.target.removeEventListener(this.changeEvent, this);
|
|
51
|
+
}
|
|
52
|
+
handleChange(subject, args) {
|
|
53
|
+
this.subscriber.handleChange(this.dataBinding.evaluate, this);
|
|
38
54
|
}
|
|
39
|
-
/** @internal */
|
|
40
55
|
handleEvent(event) {
|
|
41
56
|
const directive = this.directive;
|
|
42
57
|
const target = event.currentTarget;
|
|
58
|
+
const notifier = this.notifier;
|
|
59
|
+
const last = notifier.last; // using internal API!!!
|
|
60
|
+
if (!last) {
|
|
61
|
+
FAST.warn(1203 /* Message.twoWayBindingRequiresObservables */);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
43
64
|
let value;
|
|
44
65
|
switch (directive.aspectType) {
|
|
45
66
|
case 1:
|
|
@@ -55,22 +76,34 @@ export class TwoWayBinding extends ChangeBinding {
|
|
|
55
76
|
value = target[directive.targetAspect];
|
|
56
77
|
break;
|
|
57
78
|
}
|
|
58
|
-
|
|
59
|
-
const last = observer.last; // using internal API!!!
|
|
60
|
-
last.propertySource[last.propertyName] = directive.options.fromView(value);
|
|
79
|
+
last.propertySource[last.propertyName] = this.dataBinding.options.fromView(value);
|
|
61
80
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
static configure(settings) {
|
|
67
|
-
twoWaySettings = settings;
|
|
81
|
+
}
|
|
82
|
+
class TwoWayBinding extends Binding {
|
|
83
|
+
createObserver(directive, subscriber) {
|
|
84
|
+
return new TwoWayObserver(directive, subscriber, this);
|
|
68
85
|
}
|
|
69
86
|
}
|
|
70
87
|
/**
|
|
71
|
-
*
|
|
88
|
+
* Creates a default binding.
|
|
89
|
+
* @param expression - The binding to refresh when changed.
|
|
90
|
+
* @param optionsOrChangeEvent - The binding options or the name of the change event to use.
|
|
91
|
+
* @param policy - The security policy to associate with the binding.
|
|
92
|
+
* @param isBindingVolatile - Indicates whether the binding is volatile or not.
|
|
93
|
+
* @returns A binding.
|
|
72
94
|
* @public
|
|
73
95
|
*/
|
|
74
|
-
export
|
|
75
|
-
|
|
76
|
-
}
|
|
96
|
+
export function twoWay(expression, optionsOrChangeEvent, policy, isBindingVolatile = Observable.isVolatileBinding(expression)) {
|
|
97
|
+
if (isString(optionsOrChangeEvent)) {
|
|
98
|
+
optionsOrChangeEvent = { changeEvent: optionsOrChangeEvent };
|
|
99
|
+
}
|
|
100
|
+
if (!optionsOrChangeEvent) {
|
|
101
|
+
optionsOrChangeEvent = defaultOptions;
|
|
102
|
+
}
|
|
103
|
+
else if (!optionsOrChangeEvent.fromView) {
|
|
104
|
+
optionsOrChangeEvent.fromView = defaultOptions.fromView;
|
|
105
|
+
}
|
|
106
|
+
const binding = new TwoWayBinding(expression, policy, isBindingVolatile);
|
|
107
|
+
binding.options = optionsOrChangeEvent;
|
|
108
|
+
return binding;
|
|
109
|
+
}
|
|
@@ -1,119 +1,37 @@
|
|
|
1
|
-
import "../interfaces.js";
|
|
1
|
+
import { isFunction, noop } from "../interfaces.js";
|
|
2
2
|
import { ExecutionContext, Observable, } from "../observation/observable.js";
|
|
3
3
|
import { FAST } from "../platform.js";
|
|
4
|
-
import { DOM } from "
|
|
5
|
-
import {
|
|
4
|
+
import { DOM, DOMAspect } from "../dom.js";
|
|
5
|
+
import { Binding, HTMLDirective, } from "./html-directive.js";
|
|
6
6
|
import { Markup } from "./markup.js";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (value instanceof TrustedHTML) {
|
|
11
|
-
return value;
|
|
12
|
-
}
|
|
13
|
-
throw FAST.error(1202 /* Message.bindingInnerHTMLRequiresTrustedTypes */);
|
|
7
|
+
class OnChangeBinding extends Binding {
|
|
8
|
+
createObserver(_, subscriber) {
|
|
9
|
+
return Observable.binding(this.evaluate, subscriber, this.isVolatile);
|
|
14
10
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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;
|
|
11
|
+
}
|
|
12
|
+
class OneTimeBinding extends Binding {
|
|
13
|
+
constructor() {
|
|
14
|
+
super(...arguments);
|
|
15
|
+
/**
|
|
16
|
+
* Opts out of JSON stringification.
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
this.toJSON = noop;
|
|
74
20
|
}
|
|
75
|
-
|
|
76
|
-
* Bind this behavior to the source.
|
|
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) {
|
|
21
|
+
createObserver() {
|
|
94
22
|
return this;
|
|
95
23
|
}
|
|
24
|
+
bind(controller) {
|
|
25
|
+
return this.evaluate(controller.source, controller.context);
|
|
26
|
+
}
|
|
96
27
|
}
|
|
97
|
-
function
|
|
98
|
-
return class extends Type {
|
|
99
|
-
unbind(source, context, targets) {
|
|
100
|
-
super.unbind(source, context, targets);
|
|
101
|
-
const target = targets[this.directive.nodeId];
|
|
102
|
-
const view = target.$fastView;
|
|
103
|
-
if (view !== void 0 && view.isComposed) {
|
|
104
|
-
view.unbind();
|
|
105
|
-
view.needsBindOnly = true;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
function updateContentTarget(target, aspect, value, source, context) {
|
|
28
|
+
function updateContent(target, aspect, value, controller) {
|
|
111
29
|
// If there's no actual value, then this equates to the
|
|
112
30
|
// empty string for the purposes of content bindings.
|
|
113
31
|
if (value === null || value === undefined) {
|
|
114
32
|
value = "";
|
|
115
33
|
}
|
|
116
|
-
// If the value has a "create" method, then it's a
|
|
34
|
+
// If the value has a "create" method, then it's a ContentTemplate.
|
|
117
35
|
if (value.create) {
|
|
118
36
|
target.textContent = "";
|
|
119
37
|
let view = target.$fastView;
|
|
@@ -139,14 +57,14 @@ function updateContentTarget(target, aspect, value, source, context) {
|
|
|
139
57
|
// and that there's actually no need to compose it.
|
|
140
58
|
if (!view.isComposed) {
|
|
141
59
|
view.isComposed = true;
|
|
142
|
-
view.bind(source, context);
|
|
60
|
+
view.bind(controller.source, controller.context);
|
|
143
61
|
view.insertBefore(target);
|
|
144
62
|
target.$fastView = view;
|
|
145
63
|
target.$fastTemplate = value;
|
|
146
64
|
}
|
|
147
65
|
else if (view.needsBindOnly) {
|
|
148
66
|
view.needsBindOnly = false;
|
|
149
|
-
view.bind(source, context);
|
|
67
|
+
view.bind(controller.source, controller.context);
|
|
150
68
|
}
|
|
151
69
|
}
|
|
152
70
|
else {
|
|
@@ -166,13 +84,12 @@ function updateContentTarget(target, aspect, value, source, context) {
|
|
|
166
84
|
target.textContent = value;
|
|
167
85
|
}
|
|
168
86
|
}
|
|
169
|
-
function
|
|
87
|
+
function updateTokenList(target, aspect, value) {
|
|
170
88
|
var _a;
|
|
171
|
-
const
|
|
172
|
-
const lookup =
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
let currentVersion = state.c;
|
|
89
|
+
const lookup = `${this.id}-t`;
|
|
90
|
+
const state = (_a = target[lookup]) !== null && _a !== void 0 ? _a : (target[lookup] = { v: 0, cv: Object.create(null) });
|
|
91
|
+
const classVersions = state.cv;
|
|
92
|
+
let version = state.v;
|
|
176
93
|
const tokenList = target[aspect];
|
|
177
94
|
// Add the classes, tracking the version at which they were added.
|
|
178
95
|
if (value !== null && value !== undefined && value.length) {
|
|
@@ -182,224 +99,163 @@ function updateTokenListTarget(target, aspect, value) {
|
|
|
182
99
|
if (currentName === "") {
|
|
183
100
|
continue;
|
|
184
101
|
}
|
|
185
|
-
|
|
102
|
+
classVersions[currentName] = version;
|
|
186
103
|
tokenList.add(currentName);
|
|
187
104
|
}
|
|
188
105
|
}
|
|
189
|
-
state.v =
|
|
106
|
+
state.v = version + 1;
|
|
190
107
|
// If this is the first call to add classes, there's no need to remove old ones.
|
|
191
|
-
if (
|
|
108
|
+
if (version === 0) {
|
|
192
109
|
return;
|
|
193
110
|
}
|
|
194
111
|
// Remove classes from the previous version.
|
|
195
|
-
|
|
196
|
-
for (const name in
|
|
197
|
-
if (
|
|
112
|
+
version -= 1;
|
|
113
|
+
for (const name in classVersions) {
|
|
114
|
+
if (classVersions[name] === version) {
|
|
198
115
|
tokenList.remove(name);
|
|
199
116
|
}
|
|
200
117
|
}
|
|
201
118
|
}
|
|
119
|
+
const sinkLookup = {
|
|
120
|
+
[DOMAspect.attribute]: DOM.setAttribute,
|
|
121
|
+
[DOMAspect.booleanAttribute]: DOM.setBooleanAttribute,
|
|
122
|
+
[DOMAspect.property]: (t, a, v) => (t[a] = v),
|
|
123
|
+
[DOMAspect.content]: updateContent,
|
|
124
|
+
[DOMAspect.tokenList]: updateTokenList,
|
|
125
|
+
[DOMAspect.event]: () => void 0,
|
|
126
|
+
};
|
|
202
127
|
/**
|
|
203
|
-
* A
|
|
128
|
+
* A directive that applies bindings.
|
|
204
129
|
* @public
|
|
205
130
|
*/
|
|
206
|
-
export class
|
|
131
|
+
export class HTMLBindingDirective {
|
|
207
132
|
/**
|
|
208
|
-
*
|
|
209
|
-
* @param
|
|
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.
|
|
133
|
+
* Creates an instance of HTMLBindingDirective.
|
|
134
|
+
* @param dataBinding - The binding configuration to apply.
|
|
212
135
|
*/
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
this.updateTarget
|
|
136
|
+
constructor(dataBinding) {
|
|
137
|
+
this.dataBinding = dataBinding;
|
|
138
|
+
this.updateTarget = null;
|
|
139
|
+
/**
|
|
140
|
+
* The type of aspect to target.
|
|
141
|
+
*/
|
|
142
|
+
this.aspectType = DOMAspect.content;
|
|
216
143
|
}
|
|
217
|
-
}
|
|
218
|
-
/**
|
|
219
|
-
* A binding behavior for bindings that change.
|
|
220
|
-
* @public
|
|
221
|
-
*/
|
|
222
|
-
export class ChangeBinding extends UpdateBinding {
|
|
223
144
|
/**
|
|
224
|
-
* Creates
|
|
225
|
-
* @param
|
|
226
|
-
* @param updateTarget - The function used to update the target with the latest value.
|
|
145
|
+
* Creates HTML to be used within a template.
|
|
146
|
+
* @param add - Can be used to add behavior factories to a template.
|
|
227
147
|
*/
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
this.isBindingVolatile = Observable.isVolatileBinding(directive.binding);
|
|
231
|
-
this.observerProperty = `${directive.id}-o`;
|
|
148
|
+
createHTML(add) {
|
|
149
|
+
return Markup.interpolation(add(this));
|
|
232
150
|
}
|
|
233
151
|
/**
|
|
234
|
-
*
|
|
235
|
-
* @param target - The target node.
|
|
236
|
-
* @returns A BindingObserver.
|
|
152
|
+
* Creates a behavior.
|
|
237
153
|
*/
|
|
238
|
-
|
|
154
|
+
createBehavior() {
|
|
239
155
|
var _a;
|
|
240
|
-
|
|
156
|
+
if (this.updateTarget === null) {
|
|
157
|
+
const sink = sinkLookup[this.aspectType];
|
|
158
|
+
const policy = (_a = this.dataBinding.policy) !== null && _a !== void 0 ? _a : this.policy;
|
|
159
|
+
if (!sink) {
|
|
160
|
+
throw FAST.error(1205 /* Message.unsupportedBindingBehavior */);
|
|
161
|
+
}
|
|
162
|
+
this.data = `${this.id}-d`;
|
|
163
|
+
this.updateTarget = policy.protect(this.targetTagName, this.aspectType, this.targetAspect, sink);
|
|
164
|
+
}
|
|
165
|
+
return this;
|
|
241
166
|
}
|
|
242
|
-
/**
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
167
|
+
/** @internal */
|
|
168
|
+
bind(controller) {
|
|
169
|
+
var _a;
|
|
170
|
+
const target = controller.targets[this.targetNodeId];
|
|
171
|
+
switch (this.aspectType) {
|
|
172
|
+
case DOMAspect.event:
|
|
173
|
+
target[this.data] = controller;
|
|
174
|
+
target.addEventListener(this.targetAspect, this, this.dataBinding.options);
|
|
175
|
+
break;
|
|
176
|
+
case DOMAspect.content:
|
|
177
|
+
controller.onUnbind(this);
|
|
178
|
+
// intentional fall through
|
|
179
|
+
default:
|
|
180
|
+
const observer = (_a = target[this.data]) !== null && _a !== void 0 ? _a : (target[this.data] = this.dataBinding.createObserver(this, this));
|
|
181
|
+
observer.target = target;
|
|
182
|
+
observer.controller = controller;
|
|
183
|
+
this.updateTarget(target, this.targetAspect, observer.bind(controller), controller);
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
256
186
|
}
|
|
257
|
-
/**
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
187
|
+
/** @internal */
|
|
188
|
+
unbind(controller) {
|
|
189
|
+
const target = controller.targets[this.targetNodeId];
|
|
190
|
+
const view = target.$fastView;
|
|
191
|
+
if (view !== void 0 && view.isComposed) {
|
|
192
|
+
view.unbind();
|
|
193
|
+
view.needsBindOnly = true;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/** @internal */
|
|
197
|
+
handleEvent(event) {
|
|
198
|
+
const controller = event.currentTarget[this.data];
|
|
199
|
+
if (controller.isBound) {
|
|
200
|
+
ExecutionContext.setEvent(event);
|
|
201
|
+
const result = this.dataBinding.evaluate(controller.source, controller.context);
|
|
202
|
+
ExecutionContext.setEvent(null);
|
|
203
|
+
if (result !== true) {
|
|
204
|
+
event.preventDefault();
|
|
205
|
+
}
|
|
206
|
+
}
|
|
270
207
|
}
|
|
271
208
|
/** @internal */
|
|
272
209
|
handleChange(binding, observer) {
|
|
273
210
|
const target = observer.target;
|
|
274
|
-
const
|
|
275
|
-
|
|
276
|
-
this.updateTarget(target, this.directive.targetAspect, observer.observe(source, context), source, context);
|
|
211
|
+
const controller = observer.controller;
|
|
212
|
+
this.updateTarget(target, this.targetAspect, observer.bind(controller), controller);
|
|
277
213
|
}
|
|
278
214
|
}
|
|
215
|
+
HTMLDirective.define(HTMLBindingDirective, { aspected: true });
|
|
279
216
|
/**
|
|
280
|
-
*
|
|
217
|
+
* Creates an standard binding.
|
|
218
|
+
* @param expression - The binding to refresh when changed.
|
|
219
|
+
* @param policy - The security policy to associate with th binding.
|
|
220
|
+
* @param isVolatile - Indicates whether the binding is volatile or not.
|
|
221
|
+
* @returns A binding configuration.
|
|
281
222
|
* @public
|
|
282
223
|
*/
|
|
283
|
-
export
|
|
284
|
-
|
|
285
|
-
* Creates an instance of EventBinding.
|
|
286
|
-
* @param directive - The directive that has the configuration for this behavior.
|
|
287
|
-
*/
|
|
288
|
-
constructor(directive) {
|
|
289
|
-
this.directive = directive;
|
|
290
|
-
this.sourceProperty = `${directive.id}-s`;
|
|
291
|
-
this.contextProperty = `${directive.id}-c`;
|
|
292
|
-
}
|
|
293
|
-
/**
|
|
294
|
-
* Bind this behavior to the source.
|
|
295
|
-
* @param source - The source to bind to.
|
|
296
|
-
* @param context - The execution context that the binding is operating within.
|
|
297
|
-
* @param targets - The targets that behaviors in a view can attach to.
|
|
298
|
-
*/
|
|
299
|
-
bind(source, context, targets) {
|
|
300
|
-
const directive = this.directive;
|
|
301
|
-
const target = targets[directive.nodeId];
|
|
302
|
-
target[this.sourceProperty] = source;
|
|
303
|
-
target[this.contextProperty] = context;
|
|
304
|
-
target.addEventListener(directive.targetAspect, this, directive.options);
|
|
305
|
-
}
|
|
306
|
-
/**
|
|
307
|
-
* Unbinds this behavior from the source.
|
|
308
|
-
* @param source - The source to unbind from.
|
|
309
|
-
* @param context - The execution context that the binding is operating within.
|
|
310
|
-
* @param targets - The targets that behaviors in a view can attach to.
|
|
311
|
-
*/
|
|
312
|
-
unbind(source, context, targets) {
|
|
313
|
-
const directive = this.directive;
|
|
314
|
-
const target = targets[directive.nodeId];
|
|
315
|
-
target[this.sourceProperty] = target[this.contextProperty] = null;
|
|
316
|
-
target.removeEventListener(directive.targetAspect, this, directive.options);
|
|
317
|
-
}
|
|
318
|
-
/**
|
|
319
|
-
* Creates a behavior.
|
|
320
|
-
* @param targets - The targets available for behaviors to be attached to.
|
|
321
|
-
*/
|
|
322
|
-
createBehavior(targets) {
|
|
323
|
-
return this;
|
|
324
|
-
}
|
|
325
|
-
/**
|
|
326
|
-
* @internal
|
|
327
|
-
*/
|
|
328
|
-
handleEvent(event) {
|
|
329
|
-
const target = event.currentTarget;
|
|
330
|
-
ExecutionContext.setEvent(event);
|
|
331
|
-
const result = this.directive.binding(target[this.sourceProperty], target[this.contextProperty]);
|
|
332
|
-
ExecutionContext.setEvent(null);
|
|
333
|
-
if (result !== true) {
|
|
334
|
-
event.preventDefault();
|
|
335
|
-
}
|
|
336
|
-
}
|
|
224
|
+
export function bind(expression, policy, isVolatile = Observable.isVolatileBinding(expression)) {
|
|
225
|
+
return new OnChangeBinding(expression, policy, isVolatile);
|
|
337
226
|
}
|
|
338
227
|
/**
|
|
339
|
-
*
|
|
228
|
+
* Creates a one time binding
|
|
229
|
+
* @param expression - The binding to refresh when signaled.
|
|
230
|
+
* @param policy - The security policy to associate with th binding.
|
|
231
|
+
* @returns A binding configuration.
|
|
340
232
|
* @public
|
|
341
233
|
*/
|
|
342
|
-
export
|
|
234
|
+
export function oneTime(expression, policy) {
|
|
235
|
+
return new OneTimeBinding(expression, policy);
|
|
236
|
+
}
|
|
343
237
|
/**
|
|
344
|
-
*
|
|
238
|
+
* Creates an event listener binding.
|
|
239
|
+
* @param expression - The binding to invoke when the event is raised.
|
|
240
|
+
* @param options - Event listener options.
|
|
241
|
+
* @returns A binding configuration.
|
|
345
242
|
* @public
|
|
346
243
|
*/
|
|
347
|
-
export
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
* A directive that applies bindings.
|
|
352
|
-
* @public
|
|
353
|
-
*/
|
|
354
|
-
export class HTMLBindingDirective {
|
|
355
|
-
/**
|
|
356
|
-
* Creates an instance of HTMLBindingDirective.
|
|
357
|
-
* @param binding - The binding to apply.
|
|
358
|
-
* @param mode - The binding mode to use when applying the binding.
|
|
359
|
-
* @param options - The options to configure the binding with.
|
|
360
|
-
*/
|
|
361
|
-
constructor(binding, mode, options) {
|
|
362
|
-
this.binding = binding;
|
|
363
|
-
this.mode = mode;
|
|
364
|
-
this.options = options;
|
|
365
|
-
this.factory = null;
|
|
366
|
-
/**
|
|
367
|
-
* The type of aspect to target.
|
|
368
|
-
*/
|
|
369
|
-
this.aspectType = Aspect.content;
|
|
370
|
-
}
|
|
371
|
-
/**
|
|
372
|
-
* Creates HTML to be used within a template.
|
|
373
|
-
* @param add - Can be used to add behavior factories to a template.
|
|
374
|
-
*/
|
|
375
|
-
createHTML(add) {
|
|
376
|
-
return Markup.interpolation(add(this));
|
|
377
|
-
}
|
|
378
|
-
/**
|
|
379
|
-
* Creates a behavior.
|
|
380
|
-
* @param targets - The targets available for behaviors to be attached to.
|
|
381
|
-
*/
|
|
382
|
-
createBehavior(targets) {
|
|
383
|
-
if (this.factory == null) {
|
|
384
|
-
if (this.targetAspect === "innerHTML") {
|
|
385
|
-
this.binding = createInnerHTMLBinding(this.binding);
|
|
386
|
-
}
|
|
387
|
-
this.factory = this.mode[this.aspectType](this);
|
|
388
|
-
}
|
|
389
|
-
return this.factory.createBehavior(targets);
|
|
390
|
-
}
|
|
244
|
+
export function listener(expression, options) {
|
|
245
|
+
const config = new OnChangeBinding(expression);
|
|
246
|
+
config.options = options;
|
|
247
|
+
return config;
|
|
391
248
|
}
|
|
392
|
-
HTMLDirective.define(HTMLBindingDirective, { aspected: true });
|
|
393
249
|
/**
|
|
394
|
-
*
|
|
395
|
-
* @param
|
|
396
|
-
* @
|
|
397
|
-
* @returns A binding directive.
|
|
250
|
+
* Normalizes the input value into a binding.
|
|
251
|
+
* @param value - The value to create the default binding for.
|
|
252
|
+
* @returns A binding configuration for the provided value.
|
|
398
253
|
* @public
|
|
399
254
|
*/
|
|
400
|
-
export function
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
255
|
+
export function normalizeBinding(value) {
|
|
256
|
+
return isFunction(value)
|
|
257
|
+
? bind(value)
|
|
258
|
+
: value instanceof Binding
|
|
259
|
+
? value
|
|
260
|
+
: oneTime(() => value);
|
|
405
261
|
}
|