@microsoft/fast-element 2.0.0-beta.20 → 2.0.0-beta.22
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 +54 -0
- package/CHANGELOG.md +21 -1
- package/dist/dts/binding/binding.d.ts +49 -0
- package/dist/dts/binding/normalize.d.ts +9 -0
- package/dist/dts/binding/one-time.d.ts +11 -0
- package/dist/dts/binding/one-way.d.ts +20 -0
- package/dist/dts/{templating/binding-signal.d.ts → binding/signal.d.ts} +1 -1
- package/dist/dts/{templating/binding-two-way.d.ts → binding/two-way.d.ts} +3 -4
- package/dist/dts/components/element-controller.d.ts +20 -5
- package/dist/dts/context.d.ts +26 -13
- package/dist/dts/dom-policy.d.ts +15 -0
- package/dist/dts/index.d.ts +6 -2
- package/dist/dts/interfaces.d.ts +6 -5
- package/dist/dts/metadata.d.ts +6 -5
- package/dist/dts/pending-task.d.ts +19 -7
- package/dist/dts/platform.d.ts +10 -2
- package/dist/dts/styles/css-binding-directive.d.ts +60 -0
- package/dist/dts/styles/css.d.ts +9 -2
- package/dist/dts/styles/host.d.ts +2 -5
- package/dist/dts/templating/{binding.d.ts → html-binding-directive.d.ts} +3 -34
- package/dist/dts/templating/html-directive.d.ts +3 -35
- package/dist/dts/templating/render.d.ts +19 -5
- package/dist/dts/templating/repeat.d.ts +3 -2
- package/dist/dts/templating/template.d.ts +2 -6
- package/dist/dts/templating/view.d.ts +16 -6
- package/dist/dts/testing/fakes.d.ts +2 -1
- package/dist/dts/utilities.d.ts +3 -2
- package/dist/esm/binding/binding.js +18 -0
- package/dist/esm/binding/normalize.js +17 -0
- package/dist/esm/binding/one-time.js +21 -0
- package/dist/esm/binding/one-way.js +30 -0
- package/dist/esm/{templating/binding-signal.js → binding/signal.js} +5 -8
- package/dist/esm/{templating/binding-two-way.js → binding/two-way.js} +11 -15
- package/dist/esm/components/element-controller.js +33 -9
- package/dist/esm/context.js +24 -3
- package/dist/esm/debug.js +1 -0
- package/dist/esm/di/di.js +5 -5
- package/dist/esm/dom-policy.js +9 -1
- package/dist/esm/index.js +8 -2
- package/dist/esm/interfaces.js +3 -3
- package/dist/esm/metadata.js +11 -8
- package/dist/esm/observation/observable.js +3 -6
- package/dist/esm/pending-task.js +13 -1
- package/dist/esm/platform.js +10 -1
- package/dist/esm/styles/css-binding-directive.js +76 -0
- package/dist/esm/styles/css.js +14 -2
- package/dist/esm/templating/compiler.js +2 -1
- package/dist/esm/templating/{binding.js → html-binding-directive.js} +3 -70
- package/dist/esm/templating/html-directive.js +2 -25
- package/dist/esm/templating/render.js +25 -12
- package/dist/esm/templating/repeat.js +3 -3
- package/dist/esm/templating/template.js +9 -10
- package/dist/esm/templating/view.js +2 -6
- package/dist/esm/testing/fakes.js +1 -1
- package/dist/esm/utilities.js +3 -2
- package/dist/fast-element.api.json +1827 -663
- package/dist/fast-element.d.ts +167 -43
- package/dist/fast-element.debug.js +227 -120
- package/dist/fast-element.debug.min.js +1 -1
- package/dist/fast-element.js +226 -120
- package/dist/fast-element.min.js +1 -1
- package/dist/fast-element.untrimmed.d.ts +134 -82
- package/docs/api-report.md +54 -57
- package/package.json +5 -5
package/dist/esm/context.js
CHANGED
|
@@ -1,17 +1,32 @@
|
|
|
1
1
|
import "./interfaces.js";
|
|
2
2
|
import { Metadata } from "./metadata.js";
|
|
3
3
|
import { FAST } from "./platform.js";
|
|
4
|
+
const contextsByName = new Map();
|
|
4
5
|
const contextEventType = "context-request";
|
|
5
6
|
let requestStrategy;
|
|
6
7
|
/**
|
|
7
8
|
* Enables using the {@link https://github.com/webcomponents-cg/community-protocols/blob/main/proposals/context.md | W3C Community Context protocol.}
|
|
8
|
-
* @
|
|
9
|
+
* @public
|
|
9
10
|
*/
|
|
10
11
|
export const Context = Object.freeze({
|
|
11
12
|
/**
|
|
12
13
|
* The event type used for W3C Context Protocol requests.
|
|
13
14
|
*/
|
|
14
15
|
eventType: contextEventType,
|
|
16
|
+
/**
|
|
17
|
+
* Returns a FASTContext object from the global context registry matching the given name if found.
|
|
18
|
+
* Otherwise, returns a new FASTContext with this name.
|
|
19
|
+
* @param name - The name of the FASTContext to get or create.
|
|
20
|
+
* @returns A FASTContext object.
|
|
21
|
+
*/
|
|
22
|
+
for(name) {
|
|
23
|
+
let c = contextsByName.get(name);
|
|
24
|
+
if (c === void 0) {
|
|
25
|
+
c = Context.create(name);
|
|
26
|
+
contextsByName.set(name, c);
|
|
27
|
+
}
|
|
28
|
+
return c;
|
|
29
|
+
},
|
|
15
30
|
/**
|
|
16
31
|
* Creates a W3C Community Protocol-based Context object to use in requesting/providing
|
|
17
32
|
* context through the DOM.
|
|
@@ -94,8 +109,14 @@ export const Context = Object.freeze({
|
|
|
94
109
|
dispatch(target, context, callback, multiple = false) {
|
|
95
110
|
target.dispatchEvent(new ContextEvent(context, callback, multiple));
|
|
96
111
|
},
|
|
112
|
+
/**
|
|
113
|
+
* Enables an event target to provide a context value.
|
|
114
|
+
* @param target The target to provide the context value for.
|
|
115
|
+
* @param context The context to provide the value for.
|
|
116
|
+
* @param value The value to provide for the context.
|
|
117
|
+
*/
|
|
97
118
|
provide(target, context, value) {
|
|
98
|
-
|
|
119
|
+
Context.handle(target, (event) => {
|
|
99
120
|
event.stopImmediatePropagation();
|
|
100
121
|
event.callback(value);
|
|
101
122
|
}, context);
|
|
@@ -132,7 +153,7 @@ export const Context = Object.freeze({
|
|
|
132
153
|
* initialValue if the context isn't handled.
|
|
133
154
|
*/
|
|
134
155
|
defineProperty(target, propertyName, context) {
|
|
135
|
-
const field =
|
|
156
|
+
const field = Symbol.for(`fast:di:${propertyName}`);
|
|
136
157
|
Reflect.defineProperty(target, propertyName, {
|
|
137
158
|
get: function () {
|
|
138
159
|
var _a;
|
package/dist/esm/debug.js
CHANGED
|
@@ -17,6 +17,7 @@ const debugMessages = {
|
|
|
17
17
|
[1206 /* directCallToHTMLTagNotAllowed */]: "Calling html`` as a normal function invalidates the security guarantees provided by FAST.",
|
|
18
18
|
[1207 /* onlySetTemplatePolicyOnce */]: "The DOM Policy for an HTML template can only be set once.",
|
|
19
19
|
[1208 /* cannotSetTemplatePolicyAfterCompilation */]: "The DOM Policy cannot be set after a template is compiled.",
|
|
20
|
+
[1209 /* blockedByDOMPolicy */]: "'${aspectName}' on '${tagName}' is blocked by the current DOMPolicy.",
|
|
20
21
|
[1401 /* missingElementDefinition */]: "Missing FASTElement definition.",
|
|
21
22
|
[1501 /* noRegistrationForContext */]: "No registration for Context/Interface '${name}'.",
|
|
22
23
|
[1502 /* noFactoryForResolver */]: "Dependency injection resolver for '${key}' returned a null factory.",
|
package/dist/esm/di/di.js
CHANGED
|
@@ -371,16 +371,16 @@ export const DI = Object.freeze({
|
|
|
371
371
|
* The respectConnection option is only applicable to elements that descend from FASTElement.
|
|
372
372
|
*/
|
|
373
373
|
defineProperty(target, propertyName, key, respectConnection = false) {
|
|
374
|
-
const
|
|
374
|
+
const field = Symbol.for(`fast:di:${propertyName}`);
|
|
375
375
|
Reflect.defineProperty(target, propertyName, {
|
|
376
376
|
get: function () {
|
|
377
|
-
let value = this[
|
|
377
|
+
let value = this[field];
|
|
378
378
|
if (value === void 0) {
|
|
379
379
|
const container = this instanceof Node
|
|
380
380
|
? DI.findResponsibleContainer(this)
|
|
381
381
|
: DI.getOrCreateDOMContainer();
|
|
382
382
|
value = container.get(key);
|
|
383
|
-
this[
|
|
383
|
+
this[field] = value;
|
|
384
384
|
if (respectConnection) {
|
|
385
385
|
const notifier = this.$fastController;
|
|
386
386
|
if (!notifier) {
|
|
@@ -389,9 +389,9 @@ export const DI = Object.freeze({
|
|
|
389
389
|
const handleChange = () => {
|
|
390
390
|
const newContainer = DI.findResponsibleContainer(this);
|
|
391
391
|
const newValue = newContainer.get(key);
|
|
392
|
-
const oldValue = this[
|
|
392
|
+
const oldValue = this[field];
|
|
393
393
|
if (newValue !== oldValue) {
|
|
394
|
-
this[
|
|
394
|
+
this[field] = value;
|
|
395
395
|
notifier.notify(propertyName);
|
|
396
396
|
}
|
|
397
397
|
};
|
package/dist/esm/dom-policy.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DOMAspect } from "./dom.js";
|
|
2
2
|
import { isString } from "./interfaces.js";
|
|
3
|
+
import { FAST } from "./platform.js";
|
|
3
4
|
function safeURL(tagName, aspect, aspectName, sink) {
|
|
4
5
|
return (target, name, value, ...rest) => {
|
|
5
6
|
if (isString(value)) {
|
|
@@ -9,7 +10,10 @@ function safeURL(tagName, aspect, aspectName, sink) {
|
|
|
9
10
|
};
|
|
10
11
|
}
|
|
11
12
|
function block(tagName, aspect, aspectName, sink) {
|
|
12
|
-
throw
|
|
13
|
+
throw FAST.error(1209 /* Message.blockedByDOMPolicy */, {
|
|
14
|
+
aspectName,
|
|
15
|
+
tagName: tagName !== null && tagName !== void 0 ? tagName : "text",
|
|
16
|
+
});
|
|
13
17
|
}
|
|
14
18
|
const defaultDOMElementGuards = {
|
|
15
19
|
a: {
|
|
@@ -303,6 +307,10 @@ function tryGuard(aspectGuards, tagName, aspect, aspectName, sink) {
|
|
|
303
307
|
}
|
|
304
308
|
}
|
|
305
309
|
}
|
|
310
|
+
/**
|
|
311
|
+
* A helper for creating DOM policies.
|
|
312
|
+
* @public
|
|
313
|
+
*/
|
|
306
314
|
const DOMPolicy = Object.freeze({
|
|
307
315
|
/**
|
|
308
316
|
* Creates a new DOM Policy object.
|
package/dist/esm/index.js
CHANGED
|
@@ -1,21 +1,27 @@
|
|
|
1
|
-
export
|
|
1
|
+
export { FAST, emptyArray } from "./platform.js";
|
|
2
|
+
// DOM
|
|
2
3
|
export * from "./dom.js";
|
|
3
4
|
// Observation
|
|
4
5
|
export * from "./observation/observable.js";
|
|
5
6
|
export * from "./observation/notifier.js";
|
|
6
7
|
export * from "./observation/arrays.js";
|
|
7
8
|
export * from "./observation/update-queue.js";
|
|
9
|
+
// Binding
|
|
10
|
+
export * from "./binding/binding.js";
|
|
11
|
+
export * from "./binding/one-way.js";
|
|
12
|
+
export * from "./binding/one-time.js";
|
|
8
13
|
// Styles
|
|
9
14
|
export * from "./styles/element-styles.js";
|
|
10
15
|
export * from "./styles/css.js";
|
|
11
16
|
export * from "./styles/css-directive.js";
|
|
12
17
|
export * from "./styles/host.js";
|
|
13
18
|
export * from "./styles/style-strategy.js";
|
|
19
|
+
export * from "./styles/css-binding-directive.js";
|
|
14
20
|
// Templating
|
|
15
21
|
export * from "./templating/template.js";
|
|
16
22
|
export * from "./templating/compiler.js";
|
|
17
23
|
export { Markup, Parser } from "./templating/markup.js";
|
|
18
|
-
export * from "./templating/binding.js";
|
|
24
|
+
export * from "./templating/html-binding-directive.js";
|
|
19
25
|
export * from "./templating/html-directive.js";
|
|
20
26
|
export * from "./templating/ref.js";
|
|
21
27
|
export * from "./templating/when.js";
|
package/dist/esm/interfaces.js
CHANGED
|
@@ -45,16 +45,16 @@ switch (kernelMode) {
|
|
|
45
45
|
export { KernelServiceId };
|
|
46
46
|
/**
|
|
47
47
|
* Determines whether or not an object is a function.
|
|
48
|
-
* @
|
|
48
|
+
* @public
|
|
49
49
|
*/
|
|
50
50
|
export const isFunction = (object) => typeof object === "function";
|
|
51
51
|
/**
|
|
52
52
|
* Determines whether or not an object is a string.
|
|
53
|
-
* @
|
|
53
|
+
* @public
|
|
54
54
|
*/
|
|
55
55
|
export const isString = (object) => typeof object === "string";
|
|
56
56
|
/**
|
|
57
57
|
* A function which does nothing.
|
|
58
|
-
* @
|
|
58
|
+
* @public
|
|
59
59
|
*/
|
|
60
60
|
export const noop = () => void 0;
|
package/dist/esm/metadata.js
CHANGED
|
@@ -22,8 +22,11 @@ if (!("metadata" in Reflect)) {
|
|
|
22
22
|
return void 0;
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
|
+
const annotationParamTypesKey = "annotation:paramtypes";
|
|
26
|
+
const designParamTypesKey = "design:paramtypes";
|
|
25
27
|
/**
|
|
26
28
|
* Provides basic metadata capabilities used by Context and Dependency Injection.
|
|
29
|
+
* @public
|
|
27
30
|
*/
|
|
28
31
|
export const Metadata = Object.freeze({
|
|
29
32
|
/**
|
|
@@ -31,29 +34,29 @@ export const Metadata = Object.freeze({
|
|
|
31
34
|
* @param Type - The type to get the metadata for.
|
|
32
35
|
* @returns The metadata array or a frozen empty array if no metadata is found.
|
|
33
36
|
*/
|
|
34
|
-
getDesignParamTypes: Type => {
|
|
37
|
+
getDesignParamTypes: (Type) => {
|
|
35
38
|
var _a;
|
|
36
|
-
return (_a = Reflect.getOwnMetadata(
|
|
39
|
+
return ((_a = Reflect.getOwnMetadata(designParamTypesKey, Type)) !== null && _a !== void 0 ? _a : emptyArray);
|
|
37
40
|
},
|
|
38
41
|
/**
|
|
39
42
|
* Gets the "annotation:paramtypes" metadata for the specified type.
|
|
40
43
|
* @param Type - The type to get the metadata for.
|
|
41
44
|
* @returns The metadata array or a frozen empty array if no metadata is found.
|
|
42
45
|
*/
|
|
43
|
-
getAnnotationParamTypes: Type => {
|
|
46
|
+
getAnnotationParamTypes: (Type) => {
|
|
44
47
|
var _a;
|
|
45
|
-
return (_a = Reflect.getOwnMetadata(
|
|
48
|
+
return ((_a = Reflect.getOwnMetadata(annotationParamTypesKey, Type)) !== null && _a !== void 0 ? _a : emptyArray);
|
|
46
49
|
},
|
|
47
50
|
/**
|
|
48
|
-
*
|
|
49
|
-
* @param Type - Gets the "annotation:paramtypes" metadata for the specified type. If none is found,
|
|
51
|
+
* Gets the "annotation:paramtypes" metadata for the specified type. If none is found,
|
|
50
52
|
* an empty, mutable metadata array is created and added.
|
|
51
|
-
* @
|
|
53
|
+
* @param Type - The type to get or create the metadata for.
|
|
54
|
+
* @returns A mutable metadata array.
|
|
52
55
|
*/
|
|
53
56
|
getOrCreateAnnotationParamTypes(Type) {
|
|
54
57
|
let types = this.getAnnotationParamTypes(Type);
|
|
55
58
|
if (types === emptyArray) {
|
|
56
|
-
Reflect.defineMetadata(
|
|
59
|
+
Reflect.defineMetadata(annotationParamTypesKey, (types = []), Type);
|
|
57
60
|
}
|
|
58
61
|
return types;
|
|
59
62
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { isFunction, isString, KernelServiceId,
|
|
2
|
-
import { createMetadataLocator, FAST } from "../platform.js";
|
|
1
|
+
import { isFunction, isString, KernelServiceId, } from "../interfaces.js";
|
|
2
|
+
import { createMetadataLocator, FAST, makeSerializationNoop } from "../platform.js";
|
|
3
3
|
import { Updates } from "./update-queue.js";
|
|
4
4
|
import { PropertyChangeNotifier, SubscriberSet } from "./notifier.js";
|
|
5
5
|
/**
|
|
@@ -79,10 +79,6 @@ export const Observable = FAST.getById(KernelServiceId.observable, () => {
|
|
|
79
79
|
this.propertyName = void 0;
|
|
80
80
|
this.notifier = void 0;
|
|
81
81
|
this.next = void 0;
|
|
82
|
-
/**
|
|
83
|
-
* Opts out of JSON stringification.
|
|
84
|
-
*/
|
|
85
|
-
this.toJSON = noop;
|
|
86
82
|
}
|
|
87
83
|
setMode(isAsync) {
|
|
88
84
|
this.isAsync = this.needsQueue = isAsync;
|
|
@@ -184,6 +180,7 @@ export const Observable = FAST.getById(KernelServiceId.observable, () => {
|
|
|
184
180
|
}
|
|
185
181
|
}
|
|
186
182
|
}
|
|
183
|
+
makeSerializationNoop(ExpressionNotifierImplementation);
|
|
187
184
|
return Object.freeze({
|
|
188
185
|
/**
|
|
189
186
|
* @internal
|
package/dist/esm/pending-task.js
CHANGED
|
@@ -1,16 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A concrete implementation of {@link PendingTask}
|
|
3
|
-
* @
|
|
3
|
+
* @public
|
|
4
4
|
*/
|
|
5
5
|
export class PendingTaskEvent extends Event {
|
|
6
|
+
/**
|
|
7
|
+
* Creates an instance of PendingTaskEvent.
|
|
8
|
+
* @param complete - A promise that resolves when the pending task is complete.
|
|
9
|
+
*/
|
|
6
10
|
constructor(complete) {
|
|
7
11
|
super(PendingTaskEvent.type, { bubbles: true, composed: true });
|
|
8
12
|
this.complete = complete;
|
|
9
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Determines whether a value is a PendingTaskEvent.
|
|
16
|
+
* @param value - The value to check.
|
|
17
|
+
* @returns True if the value is a PendingTaskEvent; false otherwise.
|
|
18
|
+
*/
|
|
10
19
|
static isPendingTask(value) {
|
|
11
20
|
var _a;
|
|
12
21
|
return (value.type === PendingTaskEvent.type &&
|
|
13
22
|
typeof ((_a = value.complete) === null || _a === void 0 ? void 0 : _a.then) === "function");
|
|
14
23
|
}
|
|
15
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* The type of the pending task event.
|
|
27
|
+
*/
|
|
16
28
|
PendingTaskEvent.type = "pending-task";
|
package/dist/esm/platform.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { noop } from "./interfaces.js";
|
|
1
2
|
import "./polyfills.js";
|
|
2
3
|
// ensure FAST global - duplicated debug.ts
|
|
3
4
|
const propConfig = {
|
|
@@ -10,7 +11,7 @@ if (globalThis.FAST === void 0) {
|
|
|
10
11
|
}
|
|
11
12
|
/**
|
|
12
13
|
* The FAST global.
|
|
13
|
-
* @
|
|
14
|
+
* @public
|
|
14
15
|
*/
|
|
15
16
|
export const FAST = globalThis.FAST;
|
|
16
17
|
if (FAST.getById === void 0) {
|
|
@@ -86,3 +87,11 @@ export function createMetadataLocator() {
|
|
|
86
87
|
return metadata;
|
|
87
88
|
};
|
|
88
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Makes a type noop for JSON serialization.
|
|
92
|
+
* @param type - The type to make noop for JSON serialization.
|
|
93
|
+
* @internal
|
|
94
|
+
*/
|
|
95
|
+
export function makeSerializationNoop(type) {
|
|
96
|
+
type.prototype.toJSON = noop;
|
|
97
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { CSSDirective } from "./css-directive.js";
|
|
2
|
+
function handleChange(directive, controller, observer) {
|
|
3
|
+
controller.source.style.setProperty(directive.targetAspect, observer.bind(controller));
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Enables bindings in CSS.
|
|
7
|
+
*
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
export class CSSBindingDirective {
|
|
11
|
+
/**
|
|
12
|
+
* Creates an instance of CSSBindingDirective.
|
|
13
|
+
* @param dataBinding - The binding to use in CSS.
|
|
14
|
+
* @param targetAspect - The CSS property to target.
|
|
15
|
+
*/
|
|
16
|
+
constructor(dataBinding, targetAspect) {
|
|
17
|
+
this.dataBinding = dataBinding;
|
|
18
|
+
this.targetAspect = targetAspect;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Creates a CSS fragment to interpolate into the CSS document.
|
|
22
|
+
* @returns - the string to interpolate into CSS
|
|
23
|
+
*/
|
|
24
|
+
createCSS(add) {
|
|
25
|
+
add(this);
|
|
26
|
+
return `var(${this.targetAspect})`;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Executed when this behavior is attached to a controller.
|
|
30
|
+
* @param controller - Controls the behavior lifecycle.
|
|
31
|
+
*/
|
|
32
|
+
addedCallback(controller) {
|
|
33
|
+
var _a;
|
|
34
|
+
const element = controller.source;
|
|
35
|
+
if (!element.$cssBindings) {
|
|
36
|
+
element.$cssBindings = new Map();
|
|
37
|
+
const setAttribute = element.setAttribute;
|
|
38
|
+
element.setAttribute = (attr, value) => {
|
|
39
|
+
setAttribute.call(element, attr, value);
|
|
40
|
+
if (attr === "style") {
|
|
41
|
+
element.$cssBindings.forEach((v, k) => handleChange(k, v.controller, v.observer));
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const observer = (_a = controller[this.targetAspect]) !== null && _a !== void 0 ? _a : (controller[this.targetAspect] = this.dataBinding.createObserver(this, this));
|
|
46
|
+
observer.controller = controller;
|
|
47
|
+
controller.source.$cssBindings.set(this, { controller, observer });
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Executed when this behavior's host is connected.
|
|
51
|
+
* @param controller - Controls the behavior lifecycle.
|
|
52
|
+
*/
|
|
53
|
+
connectedCallback(controller) {
|
|
54
|
+
handleChange(this, controller, controller[this.targetAspect]);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Executed when this behavior is detached from a controller.
|
|
58
|
+
* @param controller - Controls the behavior lifecycle.
|
|
59
|
+
*/
|
|
60
|
+
removedCallback(controller) {
|
|
61
|
+
if (controller.source.$cssBindings) {
|
|
62
|
+
controller.source.$cssBindings.delete(this);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Called when a subject this instance has subscribed to changes.
|
|
67
|
+
* @param subject - The subject of the change.
|
|
68
|
+
* @param args - The event args detailing the change that occurred.
|
|
69
|
+
*
|
|
70
|
+
* @internal
|
|
71
|
+
*/
|
|
72
|
+
handleChange(_, observer) {
|
|
73
|
+
handleChange(this, observer.controller, observer);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
CSSDirective.define(CSSBindingDirective);
|
package/dist/esm/styles/css.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import { isString } from "../interfaces.js";
|
|
1
|
+
import { isFunction, isString } from "../interfaces.js";
|
|
2
|
+
import { Binding } from "../binding/binding.js";
|
|
3
|
+
import { oneWay } from "../binding/one-way.js";
|
|
2
4
|
import { CSSDirective } from "./css-directive.js";
|
|
3
5
|
import { ElementStyles } from "./element-styles.js";
|
|
6
|
+
import { CSSBindingDirective } from "./css-binding-directive.js";
|
|
7
|
+
const marker = `${Math.random().toString(36).substring(2, 8)}`;
|
|
8
|
+
let varId = 0;
|
|
9
|
+
const nextCSSVariable = () => `--v${marker}${++varId}`;
|
|
4
10
|
function collectStyles(strings, values) {
|
|
5
11
|
const styles = [];
|
|
6
12
|
let cssString = "";
|
|
@@ -11,7 +17,13 @@ function collectStyles(strings, values) {
|
|
|
11
17
|
for (let i = 0, ii = strings.length - 1; i < ii; ++i) {
|
|
12
18
|
cssString += strings[i];
|
|
13
19
|
let value = values[i];
|
|
14
|
-
if (
|
|
20
|
+
if (isFunction(value)) {
|
|
21
|
+
value = new CSSBindingDirective(oneWay(value), nextCSSVariable()).createCSS(add);
|
|
22
|
+
}
|
|
23
|
+
else if (value instanceof Binding) {
|
|
24
|
+
value = new CSSBindingDirective(value, nextCSSVariable()).createCSS(add);
|
|
25
|
+
}
|
|
26
|
+
else if (CSSDirective.getForInstance(value) !== void 0) {
|
|
15
27
|
value = value.createCSS(add);
|
|
16
28
|
}
|
|
17
29
|
if (value instanceof ElementStyles || value instanceof CSSStyleSheet) {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { isFunction, isString } from "../interfaces.js";
|
|
2
2
|
import { FAST } from "../platform.js";
|
|
3
3
|
import { DOM } from "../dom.js";
|
|
4
|
+
import { oneTime } from "../binding/one-time.js";
|
|
4
5
|
import { nextId, Parser } from "./markup.js";
|
|
5
|
-
import { HTMLBindingDirective
|
|
6
|
+
import { HTMLBindingDirective } from "./html-binding-directive.js";
|
|
6
7
|
import { HTMLDirective, } from "./html-directive.js";
|
|
7
8
|
import { HTMLView } from "./view.js";
|
|
8
9
|
const targetIdFrom = (parentId, nodeIndex) => `${parentId}.${nodeIndex}`;
|
|
@@ -1,30 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { ExecutionContext,
|
|
1
|
+
import "../interfaces.js";
|
|
2
|
+
import { ExecutionContext, } from "../observation/observable.js";
|
|
3
3
|
import { FAST } from "../platform.js";
|
|
4
4
|
import { DOM, DOMAspect } from "../dom.js";
|
|
5
|
-
import {
|
|
5
|
+
import { HTMLDirective, } from "./html-directive.js";
|
|
6
6
|
import { Markup } from "./markup.js";
|
|
7
|
-
class OnChangeBinding extends Binding {
|
|
8
|
-
createObserver(_, subscriber) {
|
|
9
|
-
return Observable.binding(this.evaluate, subscriber, this.isVolatile);
|
|
10
|
-
}
|
|
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;
|
|
20
|
-
}
|
|
21
|
-
createObserver() {
|
|
22
|
-
return this;
|
|
23
|
-
}
|
|
24
|
-
bind(controller) {
|
|
25
|
-
return this.evaluate(controller.source, controller.context);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
7
|
function updateContent(target, aspect, value, controller) {
|
|
29
8
|
// If there's no actual value, then this equates to the
|
|
30
9
|
// empty string for the purposes of content bindings.
|
|
@@ -213,49 +192,3 @@ export class HTMLBindingDirective {
|
|
|
213
192
|
}
|
|
214
193
|
}
|
|
215
194
|
HTMLDirective.define(HTMLBindingDirective, { aspected: true });
|
|
216
|
-
/**
|
|
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.
|
|
222
|
-
* @public
|
|
223
|
-
*/
|
|
224
|
-
export function bind(expression, policy, isVolatile = Observable.isVolatileBinding(expression)) {
|
|
225
|
-
return new OnChangeBinding(expression, policy, isVolatile);
|
|
226
|
-
}
|
|
227
|
-
/**
|
|
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.
|
|
232
|
-
* @public
|
|
233
|
-
*/
|
|
234
|
-
export function oneTime(expression, policy) {
|
|
235
|
-
return new OneTimeBinding(expression, policy);
|
|
236
|
-
}
|
|
237
|
-
/**
|
|
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.
|
|
242
|
-
* @public
|
|
243
|
-
*/
|
|
244
|
-
export function listener(expression, options) {
|
|
245
|
-
const config = new OnChangeBinding(expression);
|
|
246
|
-
config.options = options;
|
|
247
|
-
return config;
|
|
248
|
-
}
|
|
249
|
-
/**
|
|
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.
|
|
253
|
-
* @public
|
|
254
|
-
*/
|
|
255
|
-
export function normalizeBinding(value) {
|
|
256
|
-
return isFunction(value)
|
|
257
|
-
? bind(value)
|
|
258
|
-
: value instanceof Binding
|
|
259
|
-
? value
|
|
260
|
-
: oneTime(() => value);
|
|
261
|
-
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { DOMAspect } from "../dom.js";
|
|
2
|
-
import {
|
|
3
|
-
import { createTypeRegistry } from "../platform.js";
|
|
2
|
+
import { createTypeRegistry, makeSerializationNoop } from "../platform.js";
|
|
4
3
|
import { Markup } from "./markup.js";
|
|
5
4
|
const registry = createTypeRegistry();
|
|
6
5
|
/**
|
|
@@ -76,24 +75,6 @@ export function htmlDirective(options) {
|
|
|
76
75
|
HTMLDirective.define(type, options);
|
|
77
76
|
};
|
|
78
77
|
}
|
|
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
|
-
}
|
|
97
78
|
/**
|
|
98
79
|
* A base class used for attribute directives that don't need internal state.
|
|
99
80
|
* @public
|
|
@@ -105,11 +86,6 @@ export class StatelessAttachedAttributeDirective {
|
|
|
105
86
|
*/
|
|
106
87
|
constructor(options) {
|
|
107
88
|
this.options = options;
|
|
108
|
-
/**
|
|
109
|
-
* Opts out of JSON stringification.
|
|
110
|
-
* @internal
|
|
111
|
-
*/
|
|
112
|
-
this.toJSON = noop;
|
|
113
89
|
}
|
|
114
90
|
/**
|
|
115
91
|
* Creates a placeholder string based on the directive's index within the template.
|
|
@@ -128,3 +104,4 @@ export class StatelessAttachedAttributeDirective {
|
|
|
128
104
|
return this;
|
|
129
105
|
}
|
|
130
106
|
}
|
|
107
|
+
makeSerializationNoop(StatelessAttachedAttributeDirective);
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { FASTElementDefinition } from "../components/fast-definitions.js";
|
|
2
2
|
import { isFunction, isString } from "../interfaces.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { Binding } from "../binding/binding.js";
|
|
4
|
+
import { oneTime } from "../binding/one-time.js";
|
|
5
|
+
import { oneWay } from "../binding/one-way.js";
|
|
6
|
+
import { normalizeBinding } from "../binding/normalize.js";
|
|
7
|
+
import { HTMLDirective, } from "./html-directive.js";
|
|
5
8
|
import { Markup } from "./markup.js";
|
|
6
9
|
import { html, ViewTemplate, } from "./template.js";
|
|
7
10
|
/**
|
|
@@ -19,8 +22,8 @@ export class RenderBehavior {
|
|
|
19
22
|
this.controller = null;
|
|
20
23
|
this.view = null;
|
|
21
24
|
this.data = null;
|
|
22
|
-
this.dataBindingObserver = directive.dataBinding.createObserver(
|
|
23
|
-
this.templateBindingObserver = directive.templateBinding.createObserver(
|
|
25
|
+
this.dataBindingObserver = directive.dataBinding.createObserver(this, directive);
|
|
26
|
+
this.templateBindingObserver = directive.templateBinding.createObserver(this, directive);
|
|
24
27
|
}
|
|
25
28
|
/**
|
|
26
29
|
* Bind this behavior.
|
|
@@ -141,12 +144,13 @@ function instructionToTemplate(def) {
|
|
|
141
144
|
}
|
|
142
145
|
return def.template;
|
|
143
146
|
}
|
|
144
|
-
function createElementTemplate(tagName,
|
|
147
|
+
function createElementTemplate(tagName, options) {
|
|
145
148
|
const markup = [];
|
|
146
149
|
const values = [];
|
|
150
|
+
const { attributes, directives, content, policy } = options !== null && options !== void 0 ? options : {};
|
|
151
|
+
markup.push(`<${tagName}`);
|
|
147
152
|
if (attributes) {
|
|
148
153
|
const attrNames = Object.getOwnPropertyNames(attributes);
|
|
149
|
-
markup.push(`<${tagName}`);
|
|
150
154
|
for (let i = 0, ii = attrNames.length; i < ii; ++i) {
|
|
151
155
|
const name = attrNames[i];
|
|
152
156
|
if (i === 0) {
|
|
@@ -157,11 +161,17 @@ function createElementTemplate(tagName, attributes, content, policy) {
|
|
|
157
161
|
}
|
|
158
162
|
values.push(attributes[name]);
|
|
159
163
|
}
|
|
160
|
-
markup.push(`"
|
|
164
|
+
markup.push(`"`);
|
|
161
165
|
}
|
|
162
|
-
|
|
163
|
-
markup.
|
|
166
|
+
if (directives) {
|
|
167
|
+
markup[markup.length - 1] += " ";
|
|
168
|
+
for (let i = 0, ii = directives.length; i < ii; ++i) {
|
|
169
|
+
const directive = directives[i];
|
|
170
|
+
markup.push(i > 0 ? "" : " ");
|
|
171
|
+
values.push(directive);
|
|
172
|
+
}
|
|
164
173
|
}
|
|
174
|
+
markup[markup.length - 1] += ">";
|
|
165
175
|
if (content && isFunction(content.create)) {
|
|
166
176
|
values.push(content);
|
|
167
177
|
markup.push(`</${tagName}>`);
|
|
@@ -173,7 +183,7 @@ function createElementTemplate(tagName, attributes, content, policy) {
|
|
|
173
183
|
return ViewTemplate.create(markup, values, policy);
|
|
174
184
|
}
|
|
175
185
|
function create(options) {
|
|
176
|
-
var _a
|
|
186
|
+
var _a;
|
|
177
187
|
const name = (_a = options.name) !== null && _a !== void 0 ? _a : defaultViewName;
|
|
178
188
|
let template;
|
|
179
189
|
if (isElementRenderOptions(options)) {
|
|
@@ -187,7 +197,10 @@ function create(options) {
|
|
|
187
197
|
throw new Error("Invalid element for model rendering.");
|
|
188
198
|
}
|
|
189
199
|
}
|
|
190
|
-
|
|
200
|
+
if (!options.attributes) {
|
|
201
|
+
options.attributes = defaultAttributes;
|
|
202
|
+
}
|
|
203
|
+
template = createElementTemplate(tagName, options);
|
|
191
204
|
}
|
|
192
205
|
else {
|
|
193
206
|
template = options.template;
|
|
@@ -357,7 +370,7 @@ export function render(value, template) {
|
|
|
357
370
|
});
|
|
358
371
|
}
|
|
359
372
|
else if (isFunction(template)) {
|
|
360
|
-
templateBinding =
|
|
373
|
+
templateBinding = oneWay((s, c) => {
|
|
361
374
|
var _a;
|
|
362
375
|
let result = template(s, c);
|
|
363
376
|
if (isString(result)) {
|