@lushly-dev/fast-element 3.0.1-preview.0 → 3.0.1-preview.2
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.md +12 -0
- package/dist/command/command.api.json +7857 -0
- package/dist/context/context.api.json +1084 -0
- package/dist/declarative/declarative.api.json +8130 -0
- package/dist/definition-schema/definition-schema.api.json +2689 -0
- package/dist/di/di.api.json +4945 -0
- package/dist/dts/arrays.d.ts +2 -0
- package/dist/dts/binding/binding.d.ts +59 -0
- package/dist/dts/binding/exports.d.ts +9 -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/binding/signal.d.ts +36 -0
- package/dist/dts/binding/two-way.d.ts +44 -0
- package/dist/dts/command/behavior.d.ts +94 -0
- package/dist/dts/command/behaviors/confirm-behavior.d.ts +139 -0
- package/dist/dts/command/behaviors/undo-behavior.d.ts +178 -0
- package/dist/dts/command/command.d.ts +79 -0
- package/dist/dts/command/component-registry.d.ts +50 -0
- package/dist/dts/command/components/confirm-dialog.d.ts +117 -0
- package/dist/dts/command/index.d.ts +21 -0
- package/dist/dts/command/registry.d.ts +201 -0
- package/dist/dts/command/schema-validation.d.ts +45 -0
- package/dist/dts/command/types.d.ts +332 -0
- package/dist/dts/command/validation.d.ts +116 -0
- package/dist/dts/command/weak-ref.d.ts +11 -0
- package/dist/dts/components/attributes.d.ts +153 -0
- package/dist/dts/components/definition-schema-transforms.d.ts +9 -0
- package/dist/dts/components/element-controller.d.ts +349 -0
- package/dist/dts/components/element-hydration.d.ts +2 -0
- package/dist/dts/components/enable-hydration.d.ts +66 -0
- package/dist/dts/components/fast-definitions.d.ts +211 -0
- package/dist/dts/components/fast-element-registry.d.ts +23 -0
- package/dist/dts/components/fast-element.d.ts +91 -0
- package/dist/dts/components/hydration-tracker.d.ts +110 -0
- package/dist/dts/components/hydration.d.ts +52 -0
- package/dist/dts/components/schema.d.ts +205 -0
- package/dist/dts/context.d.ts +171 -0
- package/dist/dts/debug.d.ts +5 -0
- package/dist/dts/declarative/attribute-map.d.ts +58 -0
- package/dist/dts/declarative/debug.d.ts +4 -0
- package/dist/dts/declarative/index.d.ts +14 -0
- package/dist/dts/declarative/interfaces.d.ts +8 -0
- package/dist/dts/declarative/observer-map-utilities.d.ts +58 -0
- package/dist/dts/declarative/observer-map.d.ts +89 -0
- package/dist/dts/declarative/runtime.d.ts +5 -0
- package/dist/dts/declarative/syntax.d.ts +21 -0
- package/dist/dts/declarative/template-bridge.d.ts +33 -0
- package/dist/dts/declarative/template-parser.d.ts +98 -0
- package/dist/dts/declarative/template.d.ts +9 -0
- package/dist/dts/declarative/utilities.d.ts +358 -0
- package/dist/dts/definition-schema/api.d.ts +42 -0
- package/dist/dts/definition-schema/cem.d.ts +78 -0
- package/dist/dts/definition-schema/extension.d.ts +18 -0
- package/dist/dts/definition-schema/extract.d.ts +38 -0
- package/dist/dts/definition-schema/index.d.ts +9 -0
- package/dist/dts/definition-schema/storage.d.ts +35 -0
- package/dist/dts/definition-schema/types.d.ts +176 -0
- package/dist/dts/dev-mode.d.ts +13 -0
- package/dist/dts/di/di.d.ts +894 -0
- package/dist/dts/dom-policy.d.ts +101 -0
- package/dist/dts/dom.d.ts +88 -0
- package/dist/dts/hydration/diagnostics.d.ts +93 -0
- package/dist/dts/hydration/exports.d.ts +18 -0
- package/dist/dts/hydration/hydration-debugger.d.ts +35 -0
- package/dist/dts/hydration/messages.d.ts +62 -0
- package/dist/dts/hydration/runtime.d.ts +7 -0
- package/dist/dts/hydration/target-builder.d.ts +107 -0
- package/dist/dts/index.d.ts +51 -0
- package/dist/dts/index.debug.d.ts +1 -0
- package/dist/dts/index.rollup.d.ts +1 -0
- package/dist/dts/index.rollup.debug.d.ts +1 -0
- package/dist/dts/interfaces.d.ts +106 -0
- package/dist/dts/metadata.d.ts +26 -0
- package/dist/dts/observation/arrays.d.ts +248 -0
- package/dist/dts/observation/notifier.d.ts +127 -0
- package/dist/dts/observation/observable.d.ts +276 -0
- package/dist/dts/observation/update-queue.d.ts +40 -0
- package/dist/dts/observation/volatile.d.ts +9 -0
- package/dist/dts/platform.d.ts +87 -0
- package/dist/dts/registry.d.ts +2 -0
- package/dist/dts/render.d.ts +7 -0
- package/dist/dts/schema.d.ts +1 -0
- package/dist/dts/scoped/detection.d.ts +55 -0
- package/dist/dts/scoped/index.d.ts +68 -0
- package/dist/dts/scoped/mixin.d.ts +118 -0
- package/dist/dts/scoped/registry.d.ts +76 -0
- package/dist/dts/scoped/types.d.ts +48 -0
- 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 +50 -0
- package/dist/dts/styles/css.d.ts +34 -0
- package/dist/dts/styles/element-styles.d.ts +61 -0
- package/dist/dts/styles/host.d.ts +65 -0
- package/dist/dts/styles/style-strategy.d.ts +42 -0
- package/dist/dts/templating/children.d.ts +62 -0
- package/dist/dts/templating/compiler.d.ts +54 -0
- package/dist/dts/templating/html-binding-directive.d.ts +155 -0
- package/dist/dts/templating/html-directive.d.ts +218 -0
- package/dist/dts/templating/html.d.ts +1 -0
- package/dist/dts/templating/hydration-view.d.ts +130 -0
- package/dist/dts/templating/markup.d.ts +48 -0
- package/dist/dts/templating/node-observation.d.ts +99 -0
- package/dist/dts/templating/ref.d.ts +23 -0
- package/dist/dts/templating/render.d.ts +318 -0
- package/dist/dts/templating/repeat.d.ts +131 -0
- package/dist/dts/templating/slotted.d.ts +38 -0
- package/dist/dts/templating/template.d.ts +221 -0
- package/dist/dts/templating/view.d.ts +268 -0
- package/dist/dts/templating/when.d.ts +12 -0
- package/dist/dts/testing/exports.d.ts +3 -0
- package/dist/dts/testing/fakes.d.ts +16 -0
- package/dist/dts/testing/fixture.d.ts +84 -0
- package/dist/dts/testing/models.d.ts +20 -0
- package/dist/dts/testing/timeout.d.ts +7 -0
- package/dist/dts/trust/index.d.ts +8 -0
- package/dist/dts/trust/types.d.ts +48 -0
- package/dist/dts/trust/utils.d.ts +26 -0
- package/dist/dts/tsdoc-metadata.json +11 -0
- package/dist/dts/utilities.d.ts +76 -0
- package/dist/esm/arrays.js +1 -0
- package/dist/esm/binding/binding.js +18 -0
- package/dist/esm/binding/exports.js +6 -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/binding/signal.js +99 -0
- package/dist/esm/binding/two-way.js +109 -0
- package/dist/esm/command/behavior.js +155 -0
- package/dist/esm/command/behaviors/confirm-behavior.js +225 -0
- package/dist/esm/command/behaviors/undo-behavior.js +313 -0
- package/dist/esm/command/command.js +104 -0
- package/dist/esm/command/component-registry.js +107 -0
- package/dist/esm/command/components/confirm-dialog.js +370 -0
- package/dist/esm/command/index.js +22 -0
- package/dist/esm/command/registry.js +755 -0
- package/dist/esm/command/schema-validation.js +194 -0
- package/dist/esm/command/types.js +86 -0
- package/dist/esm/command/validation.js +508 -0
- package/dist/esm/command/weak-ref.js +5 -0
- package/dist/esm/components/attributes.js +219 -0
- package/dist/esm/components/definition-schema-transforms.js +23 -0
- package/dist/esm/components/element-controller.js +840 -0
- package/dist/esm/components/element-hydration.js +2 -0
- package/dist/esm/components/enable-hydration.js +123 -0
- package/dist/esm/components/fast-definitions.js +294 -0
- package/dist/esm/components/fast-element-registry.js +67 -0
- package/dist/esm/components/fast-element.js +82 -0
- package/dist/esm/components/hydration-tracker.js +211 -0
- package/dist/esm/components/hydration.js +187 -0
- package/dist/esm/components/schema.js +253 -0
- package/dist/esm/context.js +185 -0
- package/dist/esm/debug.js +71 -0
- package/dist/esm/declarative/attribute-map.js +122 -0
- package/dist/esm/declarative/debug.js +4 -0
- package/dist/esm/declarative/index.js +10 -0
- package/dist/esm/declarative/interfaces.js +9 -0
- package/dist/esm/declarative/observer-map-utilities.js +565 -0
- package/dist/esm/declarative/observer-map.js +216 -0
- package/dist/esm/declarative/runtime.js +14 -0
- package/dist/esm/declarative/syntax.js +36 -0
- package/dist/esm/declarative/template-bridge.js +160 -0
- package/dist/esm/declarative/template-parser.js +306 -0
- package/dist/esm/declarative/template.js +116 -0
- package/dist/esm/declarative/utilities.js +1069 -0
- package/dist/esm/definition-schema/api.js +129 -0
- package/dist/esm/definition-schema/cem.js +89 -0
- package/dist/esm/definition-schema/extension.js +53 -0
- package/dist/esm/definition-schema/extract.js +167 -0
- package/dist/esm/definition-schema/index.js +8 -0
- package/dist/esm/definition-schema/storage.js +58 -0
- package/dist/esm/definition-schema/types.js +8 -0
- package/dist/esm/dev-mode.js +22 -0
- package/dist/esm/di/di.js +1441 -0
- package/dist/esm/dom-policy.js +374 -0
- package/dist/esm/dom.js +101 -0
- package/dist/esm/hydration/diagnostics.js +50 -0
- package/dist/esm/hydration/exports.js +6 -0
- package/dist/esm/hydration/hydration-debugger.js +112 -0
- package/dist/esm/hydration/messages.js +84 -0
- package/dist/esm/hydration/runtime.js +33 -0
- package/dist/esm/hydration/target-builder.js +264 -0
- package/dist/esm/index.debug.js +3 -0
- package/dist/esm/index.js +49 -0
- package/dist/esm/index.rollup.debug.js +6 -0
- package/dist/esm/index.rollup.js +4 -0
- package/dist/esm/interfaces.js +55 -0
- package/dist/esm/metadata.js +57 -0
- package/dist/esm/observation/arrays.js +661 -0
- package/dist/esm/observation/notifier.js +162 -0
- package/dist/esm/observation/observable.js +324 -0
- package/dist/esm/observation/update-queue.js +56 -0
- package/dist/esm/observation/volatile.js +16 -0
- package/dist/esm/platform.js +98 -0
- package/dist/esm/registry.js +2 -0
- package/dist/esm/render.js +1 -0
- package/dist/esm/schema.js +1 -0
- package/dist/esm/scoped/detection.js +102 -0
- package/dist/esm/scoped/index.js +69 -0
- package/dist/esm/scoped/mixin.js +127 -0
- package/dist/esm/scoped/registry.js +125 -0
- package/dist/esm/scoped/types.js +4 -0
- 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-directive.js +36 -0
- package/dist/esm/styles/css.js +56 -0
- package/dist/esm/styles/element-styles.js +144 -0
- package/dist/esm/styles/host.js +1 -0
- package/dist/esm/styles/style-strategy.js +1 -0
- package/dist/esm/templating/children.js +67 -0
- package/dist/esm/templating/compiler.js +359 -0
- package/dist/esm/templating/html-binding-directive.js +288 -0
- package/dist/esm/templating/html-directive.js +113 -0
- package/dist/esm/templating/html.js +1 -0
- package/dist/esm/templating/hydration-view.js +228 -0
- package/dist/esm/templating/markup.js +83 -0
- package/dist/esm/templating/node-observation.js +84 -0
- package/dist/esm/templating/ref.js +21 -0
- package/dist/esm/templating/render.js +468 -0
- package/dist/esm/templating/repeat.js +434 -0
- package/dist/esm/templating/slotted.js +49 -0
- package/dist/esm/templating/template.js +206 -0
- package/dist/esm/templating/view.js +298 -0
- package/dist/esm/templating/when.js +22 -0
- 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/models.js +58 -0
- package/dist/esm/testing/timeout.js +24 -0
- package/dist/esm/trust/index.js +7 -0
- package/dist/esm/trust/types.js +6 -0
- package/dist/esm/trust/utils.js +126 -0
- package/dist/esm/utilities.js +140 -0
- package/dist/fast-element.api.json +26798 -0
- package/dist/fast-element.d.ts +3985 -0
- package/dist/fast-element.debug.js +7604 -0
- package/dist/fast-element.debug.min.js +3 -0
- package/dist/fast-element.js +7603 -0
- package/dist/fast-element.min.js +3 -0
- package/dist/fast-element.untrimmed.d.ts +4103 -0
- package/dist/observation/arrays/arrays.api.json +2621 -0
- package/dist/scoped/scoped.api.json +891 -0
- package/dist/trust/trust.api.json +629 -0
- package/package.json +21 -23
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { createTypeRegistry } from "../platform.js";
|
|
2
|
+
const registry = createTypeRegistry();
|
|
3
|
+
/**
|
|
4
|
+
* Instructs the css engine to provide styles during CSS template composition.
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export const CSSDirective = Object.freeze({
|
|
8
|
+
/**
|
|
9
|
+
* Gets the directive definition associated with the instance.
|
|
10
|
+
* @param instance - The directive instance to retrieve the definition for.
|
|
11
|
+
*/
|
|
12
|
+
getForInstance: registry.getForInstance,
|
|
13
|
+
/**
|
|
14
|
+
* Gets the directive definition associated with the specified type.
|
|
15
|
+
* @param type - The directive type to retrieve the definition for.
|
|
16
|
+
*/
|
|
17
|
+
getByType: registry.getByType,
|
|
18
|
+
/**
|
|
19
|
+
* Defines a CSSDirective.
|
|
20
|
+
* @param type - The type to define as a directive.
|
|
21
|
+
*/
|
|
22
|
+
define(type) {
|
|
23
|
+
registry.register({ type });
|
|
24
|
+
return type;
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
/**
|
|
28
|
+
* Decorator: Defines a CSSDirective.
|
|
29
|
+
* @public
|
|
30
|
+
*/
|
|
31
|
+
export function cssDirective() {
|
|
32
|
+
/* eslint-disable-next-line @typescript-eslint/explicit-function-return-type */
|
|
33
|
+
return function (type) {
|
|
34
|
+
CSSDirective.define(type);
|
|
35
|
+
};
|
|
36
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { CSSDirective } from "./css-directive.js";
|
|
2
|
+
import { ElementStyles } from "./element-styles.js";
|
|
3
|
+
function collectStyles(strings, values) {
|
|
4
|
+
const styles = [];
|
|
5
|
+
let cssString = "";
|
|
6
|
+
for (let i = 0, ii = strings.length - 1; i < ii; ++i) {
|
|
7
|
+
cssString += strings[i];
|
|
8
|
+
let value = values[i];
|
|
9
|
+
if (CSSDirective.getForInstance(value) !== void 0) {
|
|
10
|
+
value = value.createCSS();
|
|
11
|
+
}
|
|
12
|
+
if (value instanceof ElementStyles || value instanceof CSSStyleSheet) {
|
|
13
|
+
if (cssString.trim() !== "") {
|
|
14
|
+
styles.push(cssString);
|
|
15
|
+
cssString = "";
|
|
16
|
+
}
|
|
17
|
+
styles.push(value);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
cssString += value;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
cssString += strings[strings.length - 1];
|
|
24
|
+
if (cssString.trim() !== "") {
|
|
25
|
+
styles.push(cssString);
|
|
26
|
+
}
|
|
27
|
+
return styles;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Transforms a template literal string into styles.
|
|
31
|
+
* @param strings - The string fragments that are interpolated with the values.
|
|
32
|
+
* @param values - The values that are interpolated with the string fragments.
|
|
33
|
+
* @remarks
|
|
34
|
+
* The css helper supports interpolation of static composable styles and CSS directives.
|
|
35
|
+
* @public
|
|
36
|
+
*/
|
|
37
|
+
export const css = ((strings, ...values) => {
|
|
38
|
+
return new ElementStyles(collectStyles(strings, values));
|
|
39
|
+
});
|
|
40
|
+
class CSSPartial {
|
|
41
|
+
constructor(styles) {
|
|
42
|
+
this.value =
|
|
43
|
+
styles.length === 0
|
|
44
|
+
? ""
|
|
45
|
+
: styles.length === 1
|
|
46
|
+
? styles[0]
|
|
47
|
+
: new ElementStyles(styles);
|
|
48
|
+
}
|
|
49
|
+
createCSS() {
|
|
50
|
+
return this.value;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
CSSDirective.define(CSSPartial);
|
|
54
|
+
css.partial = (strings, ...values) => {
|
|
55
|
+
return new CSSPartial(collectStyles(strings, values));
|
|
56
|
+
};
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
let DefaultStyleStrategy;
|
|
2
|
+
function reduceStyles(styles) {
|
|
3
|
+
return styles.reduce((reduced, current) => {
|
|
4
|
+
if (current instanceof ElementStyles) {
|
|
5
|
+
reduced.push(...reduceStyles(current.styles));
|
|
6
|
+
}
|
|
7
|
+
else {
|
|
8
|
+
reduced.push(current);
|
|
9
|
+
}
|
|
10
|
+
return reduced;
|
|
11
|
+
}, []);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Represents styles that can be applied to a custom element.
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
export class ElementStyles {
|
|
18
|
+
/**
|
|
19
|
+
* Gets the StyleStrategy associated with these element styles.
|
|
20
|
+
*/
|
|
21
|
+
get strategy() {
|
|
22
|
+
if (this._strategy === null) {
|
|
23
|
+
if (!DefaultStyleStrategy) {
|
|
24
|
+
ElementStyles.setDefaultStrategy(ElementStyles.supportsAdoptedStyleSheets
|
|
25
|
+
? createAdoptedSheetsStrategy()
|
|
26
|
+
: createStyleElementStrategy());
|
|
27
|
+
}
|
|
28
|
+
this.withStrategy(DefaultStyleStrategy);
|
|
29
|
+
}
|
|
30
|
+
return this._strategy;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Creates an instance of ElementStyles.
|
|
34
|
+
* @param styles - The styles that will be associated with elements.
|
|
35
|
+
*/
|
|
36
|
+
constructor(styles) {
|
|
37
|
+
this.styles = styles;
|
|
38
|
+
this.targets = new WeakSet();
|
|
39
|
+
this._strategy = null;
|
|
40
|
+
}
|
|
41
|
+
/** @internal */
|
|
42
|
+
addStylesTo(target) {
|
|
43
|
+
this.strategy.addStylesTo(target);
|
|
44
|
+
this.targets.add(target);
|
|
45
|
+
}
|
|
46
|
+
/** @internal */
|
|
47
|
+
removeStylesFrom(target) {
|
|
48
|
+
this.strategy.removeStylesFrom(target);
|
|
49
|
+
this.targets.delete(target);
|
|
50
|
+
}
|
|
51
|
+
/** @internal */
|
|
52
|
+
isAttachedTo(target) {
|
|
53
|
+
return this.targets.has(target);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Sets the strategy that handles adding/removing these styles for an element.
|
|
57
|
+
* @param strategy - The strategy to use.
|
|
58
|
+
*/
|
|
59
|
+
withStrategy(Strategy) {
|
|
60
|
+
this._strategy = new Strategy(reduceStyles(this.styles));
|
|
61
|
+
return this;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Sets the default strategy type to use when creating style strategies.
|
|
65
|
+
* @param Strategy - The strategy type to construct.
|
|
66
|
+
*/
|
|
67
|
+
static setDefaultStrategy(Strategy) {
|
|
68
|
+
DefaultStyleStrategy = Strategy;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Normalizes a set of composable style options.
|
|
72
|
+
* @param styles - The style options to normalize.
|
|
73
|
+
* @returns A singular ElementStyles instance or undefined.
|
|
74
|
+
*/
|
|
75
|
+
static normalize(styles) {
|
|
76
|
+
return styles === void 0
|
|
77
|
+
? void 0
|
|
78
|
+
: Array.isArray(styles)
|
|
79
|
+
? new ElementStyles(styles)
|
|
80
|
+
: styles instanceof ElementStyles
|
|
81
|
+
? styles
|
|
82
|
+
: new ElementStyles([styles]);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Indicates whether the DOM supports the adoptedStyleSheets feature.
|
|
87
|
+
*/
|
|
88
|
+
ElementStyles.supportsAdoptedStyleSheets = Array.isArray(document.adoptedStyleSheets) &&
|
|
89
|
+
"replace" in CSSStyleSheet.prototype;
|
|
90
|
+
// Fallback strategy factories used when no strategy has been explicitly set
|
|
91
|
+
// via ElementStyles.setDefaultStrategy (e.g. when importing only from the
|
|
92
|
+
// styles.js subpath without loading element-controller.ts).
|
|
93
|
+
function createAdoptedSheetsStrategy() {
|
|
94
|
+
const cache = new Map();
|
|
95
|
+
return class FallbackAdoptedSheetsStrategy {
|
|
96
|
+
constructor(styles) {
|
|
97
|
+
this.sheets = styles.map(x => {
|
|
98
|
+
if (x instanceof CSSStyleSheet) {
|
|
99
|
+
return x;
|
|
100
|
+
}
|
|
101
|
+
let sheet = cache.get(x);
|
|
102
|
+
if (sheet === void 0) {
|
|
103
|
+
sheet = new CSSStyleSheet();
|
|
104
|
+
sheet.replaceSync(x);
|
|
105
|
+
cache.set(x, sheet);
|
|
106
|
+
}
|
|
107
|
+
return sheet;
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
addStylesTo(target) {
|
|
111
|
+
const t = target;
|
|
112
|
+
t.adoptedStyleSheets = [...t.adoptedStyleSheets, ...this.sheets];
|
|
113
|
+
}
|
|
114
|
+
removeStylesFrom(target) {
|
|
115
|
+
const t = target;
|
|
116
|
+
t.adoptedStyleSheets = t.adoptedStyleSheets.filter((x) => this.sheets.indexOf(x) === -1);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
let fallbackStyleId = 0;
|
|
121
|
+
function createStyleElementStrategy() {
|
|
122
|
+
return class FallbackStyleElementStrategy {
|
|
123
|
+
constructor(styles) {
|
|
124
|
+
this.styles = styles;
|
|
125
|
+
this.styleClass = `fast-${++fallbackStyleId}`;
|
|
126
|
+
}
|
|
127
|
+
addStylesTo(target) {
|
|
128
|
+
const t = target === document ? document.body : target;
|
|
129
|
+
for (let i = 0; i < this.styles.length; i++) {
|
|
130
|
+
const element = document.createElement("style");
|
|
131
|
+
element.innerHTML = this.styles[i];
|
|
132
|
+
element.className = this.styleClass;
|
|
133
|
+
t.append(element);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
removeStylesFrom(target) {
|
|
137
|
+
const t = target === document ? document.body : target;
|
|
138
|
+
const styles = t.querySelectorAll(`.${this.styleClass}`);
|
|
139
|
+
for (let i = 0, ii = styles.length; i < ii; ++i) {
|
|
140
|
+
t.removeChild(styles[i]);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { isString, noop } from "../interfaces.js";
|
|
2
|
+
import { HTMLDirective } from "./html-directive.js";
|
|
3
|
+
import { NodeObservationDirective, } from "./node-observation.js";
|
|
4
|
+
/**
|
|
5
|
+
* The runtime behavior for child node observation.
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
export class ChildrenDirective extends NodeObservationDirective {
|
|
9
|
+
/**
|
|
10
|
+
* Creates an instance of ChildrenDirective.
|
|
11
|
+
* @param options - The options to use in configuring the child observation behavior.
|
|
12
|
+
*/
|
|
13
|
+
constructor(options) {
|
|
14
|
+
super(options);
|
|
15
|
+
this.observerProperty = Symbol();
|
|
16
|
+
options.childList = true;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Begins observation of the nodes.
|
|
20
|
+
* @param target - The target to observe.
|
|
21
|
+
*/
|
|
22
|
+
observe(target) {
|
|
23
|
+
let observer = target[this.observerProperty];
|
|
24
|
+
if (!observer) {
|
|
25
|
+
const handleEvent = (mutations, observer) => {
|
|
26
|
+
this.updateTarget(this.getSource(target), this.computeNodes(target));
|
|
27
|
+
};
|
|
28
|
+
observer = new MutationObserver(handleEvent);
|
|
29
|
+
observer.toJSON = noop;
|
|
30
|
+
target[this.observerProperty] = observer;
|
|
31
|
+
}
|
|
32
|
+
observer.observe(target, this.options);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Disconnects observation of the nodes.
|
|
36
|
+
* @param target - The target to unobserve.
|
|
37
|
+
*/
|
|
38
|
+
disconnect(target) {
|
|
39
|
+
const observer = target[this.observerProperty];
|
|
40
|
+
observer.disconnect();
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Retrieves the raw nodes that should be assigned to the source property.
|
|
44
|
+
* @param target - The target to get the node to.
|
|
45
|
+
*/
|
|
46
|
+
getNodes(target) {
|
|
47
|
+
if ("selector" in this.options) {
|
|
48
|
+
return Array.from(target.querySelectorAll(this.options.selector));
|
|
49
|
+
}
|
|
50
|
+
return Array.from(target.childNodes);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
HTMLDirective.define(ChildrenDirective);
|
|
54
|
+
/**
|
|
55
|
+
* A directive that observes the `childNodes` of an element and updates a property
|
|
56
|
+
* whenever they change.
|
|
57
|
+
* @param propertyOrOptions - The options used to configure child node observation.
|
|
58
|
+
* @public
|
|
59
|
+
*/
|
|
60
|
+
export function children(propertyOrOptions) {
|
|
61
|
+
if (isString(propertyOrOptions)) {
|
|
62
|
+
propertyOrOptions = {
|
|
63
|
+
property: propertyOrOptions,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return new ChildrenDirective(propertyOrOptions);
|
|
67
|
+
}
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
import { oneTime } from "../binding/one-time.js";
|
|
2
|
+
import { oneWay } from "../binding/one-way.js";
|
|
3
|
+
import { DOM } from "../dom.js";
|
|
4
|
+
import { isFunction, isString, Message } from "../interfaces.js";
|
|
5
|
+
import { FAST } from "../platform.js";
|
|
6
|
+
import { HTMLBindingDirective } from "./html-binding-directive.js";
|
|
7
|
+
import { HTMLDirective, } from "./html-directive.js";
|
|
8
|
+
import { nextId, Parser } from "./markup.js";
|
|
9
|
+
import { HTMLView } from "./view.js";
|
|
10
|
+
/**
|
|
11
|
+
* Builds a hierarchical node ID by appending the child index to the parent's ID.
|
|
12
|
+
* For example, the third child of root is "r.2", and its first child is "r.2.0".
|
|
13
|
+
* These IDs are used as property names on the targets prototype so that each
|
|
14
|
+
* binding's target DOM node can be lazily resolved via a chain of childNodes lookups.
|
|
15
|
+
*/
|
|
16
|
+
const targetIdFrom = (parentId, nodeIndex) => `${parentId}.${nodeIndex}`;
|
|
17
|
+
const descriptorCache = {};
|
|
18
|
+
// used to prevent creating lots of objects just to track node and index while compiling
|
|
19
|
+
const next = {
|
|
20
|
+
index: 0,
|
|
21
|
+
node: null,
|
|
22
|
+
};
|
|
23
|
+
function tryWarn(name) {
|
|
24
|
+
if (!name.startsWith("fast-")) {
|
|
25
|
+
FAST.warn(Message.hostBindingWithoutHost, { name });
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const warningHost = new Proxy(document.createElement("div"), {
|
|
29
|
+
get(target, property) {
|
|
30
|
+
tryWarn(property);
|
|
31
|
+
const value = Reflect.get(target, property);
|
|
32
|
+
return isFunction(value) ? value.bind(target) : value;
|
|
33
|
+
},
|
|
34
|
+
set(target, property, value) {
|
|
35
|
+
tryWarn(property);
|
|
36
|
+
return Reflect.set(target, property, value);
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
class CompilationContext {
|
|
40
|
+
constructor(fragment, directives, policy) {
|
|
41
|
+
this.fragment = fragment;
|
|
42
|
+
this.directives = directives;
|
|
43
|
+
this.policy = policy;
|
|
44
|
+
this.proto = null;
|
|
45
|
+
this.nodeIds = new Set();
|
|
46
|
+
this.descriptors = {};
|
|
47
|
+
this.factories = [];
|
|
48
|
+
}
|
|
49
|
+
addFactory(factory, parentId, nodeId, targetIndex, tagName) {
|
|
50
|
+
var _a, _b;
|
|
51
|
+
if (!this.nodeIds.has(nodeId)) {
|
|
52
|
+
this.nodeIds.add(nodeId);
|
|
53
|
+
this.addTargetDescriptor(parentId, nodeId, targetIndex);
|
|
54
|
+
}
|
|
55
|
+
factory.id = (_a = factory.id) !== null && _a !== void 0 ? _a : nextId();
|
|
56
|
+
factory.targetNodeId = nodeId;
|
|
57
|
+
factory.targetTagName = tagName;
|
|
58
|
+
factory.policy = (_b = factory.policy) !== null && _b !== void 0 ? _b : this.policy;
|
|
59
|
+
this.factories.push(factory);
|
|
60
|
+
}
|
|
61
|
+
freeze() {
|
|
62
|
+
this.proto = Object.create(null, this.descriptors);
|
|
63
|
+
return this;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Registers a lazy getter on the targets prototype that resolves a DOM node
|
|
67
|
+
* by navigating from its parent's childNodes at the given index. Getters are
|
|
68
|
+
* chained: accessing targets["r.0.2"] first resolves targets["r.0"] (which
|
|
69
|
+
* resolves targets["r"]), then returns childNodes[2]. Results are cached so
|
|
70
|
+
* each node is resolved at most once per view instance.
|
|
71
|
+
*/
|
|
72
|
+
addTargetDescriptor(parentId, targetId, targetIndex) {
|
|
73
|
+
const descriptors = this.descriptors;
|
|
74
|
+
if (targetId === "r" || // root
|
|
75
|
+
targetId === "h" || // host
|
|
76
|
+
descriptors[targetId]) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (!descriptors[parentId]) {
|
|
80
|
+
const index = parentId.lastIndexOf(".");
|
|
81
|
+
const grandparentId = parentId.substring(0, index);
|
|
82
|
+
const childIndex = parseInt(parentId.substring(index + 1), 10);
|
|
83
|
+
this.addTargetDescriptor(grandparentId, parentId, childIndex);
|
|
84
|
+
}
|
|
85
|
+
let descriptor = descriptorCache[targetId];
|
|
86
|
+
if (!descriptor) {
|
|
87
|
+
const field = `_${targetId}`;
|
|
88
|
+
descriptorCache[targetId] = descriptor = {
|
|
89
|
+
get() {
|
|
90
|
+
var _a;
|
|
91
|
+
return ((_a = this[field]) !== null && _a !== void 0 ? _a : (this[field] = this[parentId].childNodes[targetIndex]));
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
descriptors[targetId] = descriptor;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Creates a new HTMLView by cloning the compiled DocumentFragment and building
|
|
99
|
+
* a targets object. The targets prototype contains lazy getters that resolve
|
|
100
|
+
* each binding's target DOM node via childNodes traversal. Accessing every
|
|
101
|
+
* registered nodeId eagerly triggers the getter chain so all nodes are resolved
|
|
102
|
+
* before behaviors are bound.
|
|
103
|
+
*/
|
|
104
|
+
createView(hostBindingTarget, scope) {
|
|
105
|
+
const fragment = scope === void 0
|
|
106
|
+
? this.fragment.cloneNode(true)
|
|
107
|
+
: cloneIntoScope(this.fragment, scope);
|
|
108
|
+
const targets = Object.create(this.proto);
|
|
109
|
+
targets.r = fragment; // root — the cloned DocumentFragment
|
|
110
|
+
targets.h = hostBindingTarget !== null && hostBindingTarget !== void 0 ? hostBindingTarget : warningHost; // host — the custom element
|
|
111
|
+
for (const id of this.nodeIds) {
|
|
112
|
+
Reflect.get(targets, id); // trigger lazy getter to resolve and cache the DOM node
|
|
113
|
+
}
|
|
114
|
+
return new HTMLView(fragment, this.factories, targets, scope);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
let inertDocument;
|
|
118
|
+
const registryFreeSources = new WeakMap();
|
|
119
|
+
/**
|
|
120
|
+
* Returns a copy of a compiled fragment whose elements have no custom element
|
|
121
|
+
* registry. Elements that already have one (all elements of the fragment that was
|
|
122
|
+
* adopted into the main document have the global registry) keep it when cloned, so
|
|
123
|
+
* a registry can only be chosen for clones of a registry-free source.
|
|
124
|
+
*/
|
|
125
|
+
function getRegistryFreeSource(fragment) {
|
|
126
|
+
let source = registryFreeSources.get(fragment);
|
|
127
|
+
if (source === void 0) {
|
|
128
|
+
inertDocument !== null && inertDocument !== void 0 ? inertDocument : (inertDocument = document.implementation.createHTMLDocument(""));
|
|
129
|
+
source = fragment.cloneNode(true);
|
|
130
|
+
inertDocument.adoptNode(source);
|
|
131
|
+
registryFreeSources.set(fragment, source);
|
|
132
|
+
}
|
|
133
|
+
return source;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Clones a compiled fragment so that custom elements inside it are created against
|
|
137
|
+
* the scoped custom element registry of `scope`.
|
|
138
|
+
*
|
|
139
|
+
* @remarks
|
|
140
|
+
* The compiled fragment is adopted into the main document, so a plain `cloneNode`
|
|
141
|
+
* creates its children against the *global* registry and a tag that is only defined
|
|
142
|
+
* in a scoped registry is never upgraded. Only views for hosts that were given a
|
|
143
|
+
* registry take this path (see `ElementController`); every other view keeps using
|
|
144
|
+
* `cloneNode(true)`.
|
|
145
|
+
*
|
|
146
|
+
* - Native scoped registries: `document.importNode` with a `customElementRegistry`,
|
|
147
|
+
* from a registry-free copy of the fragment (created once per template).
|
|
148
|
+
* - `@webcomponents/scoped-custom-element-registry` (0.0.x): `ShadowRoot.importNode`,
|
|
149
|
+
* which the polyfill patches to resolve the scope from the shadow root.
|
|
150
|
+
* - Otherwise: a plain clone.
|
|
151
|
+
*/
|
|
152
|
+
function cloneIntoScope(fragment, scope) {
|
|
153
|
+
var _a;
|
|
154
|
+
const scoped = scope;
|
|
155
|
+
const registry = (_a = scoped.customElementRegistry) !== null && _a !== void 0 ? _a : scoped.registry;
|
|
156
|
+
if (registry) {
|
|
157
|
+
// A registry that can `initialize` is the native (or spec-aligned) API.
|
|
158
|
+
if (registry !== globalThis.customElements &&
|
|
159
|
+
typeof registry.initialize === "function") {
|
|
160
|
+
return document.importNode(getRegistryFreeSource(fragment), {
|
|
161
|
+
selfOnly: false,
|
|
162
|
+
customElementRegistry: registry,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
if (typeof scoped.importNode === "function") {
|
|
166
|
+
return scoped.importNode(fragment, true);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return fragment.cloneNode(true);
|
|
170
|
+
}
|
|
171
|
+
function compileAttributes(context, parentId, node, nodeId, nodeIndex, includeBasicValues = false) {
|
|
172
|
+
const attributes = node.attributes;
|
|
173
|
+
const directives = context.directives;
|
|
174
|
+
for (let i = 0, ii = attributes.length; i < ii; ++i) {
|
|
175
|
+
const attr = attributes[i];
|
|
176
|
+
const attrValue = attr.value;
|
|
177
|
+
const parseResult = Parser.parse(attrValue, directives);
|
|
178
|
+
let result = null;
|
|
179
|
+
if (parseResult === null) {
|
|
180
|
+
if (includeBasicValues) {
|
|
181
|
+
result = new HTMLBindingDirective(oneTime(() => attrValue, context.policy));
|
|
182
|
+
HTMLDirective.assignAspect(result, attr.name);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
result = Compiler.aggregate(parseResult, context.policy);
|
|
187
|
+
}
|
|
188
|
+
if (result !== null) {
|
|
189
|
+
node.removeAttributeNode(attr);
|
|
190
|
+
i--;
|
|
191
|
+
ii--;
|
|
192
|
+
context.addFactory(result, parentId, nodeId, nodeIndex, node.tagName);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
function compileContent(context, node, parentId, nodeId, nodeIndex) {
|
|
197
|
+
const parseResult = Parser.parse(node.textContent, context.directives);
|
|
198
|
+
if (parseResult === null) {
|
|
199
|
+
next.node = node.nextSibling;
|
|
200
|
+
next.index = nodeIndex + 1;
|
|
201
|
+
return next;
|
|
202
|
+
}
|
|
203
|
+
let currentNode;
|
|
204
|
+
let lastNode = (currentNode = node);
|
|
205
|
+
for (let i = 0, ii = parseResult.length; i < ii; ++i) {
|
|
206
|
+
const currentPart = parseResult[i];
|
|
207
|
+
if (i !== 0) {
|
|
208
|
+
nodeIndex++;
|
|
209
|
+
nodeId = targetIdFrom(parentId, nodeIndex);
|
|
210
|
+
currentNode = lastNode.parentNode.insertBefore(document.createTextNode(""), lastNode.nextSibling);
|
|
211
|
+
}
|
|
212
|
+
if (isString(currentPart)) {
|
|
213
|
+
currentNode.textContent = currentPart;
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
currentNode.textContent = " ";
|
|
217
|
+
HTMLDirective.assignAspect(currentPart);
|
|
218
|
+
context.addFactory(currentPart, parentId, nodeId, nodeIndex, null);
|
|
219
|
+
}
|
|
220
|
+
lastNode = currentNode;
|
|
221
|
+
}
|
|
222
|
+
next.index = nodeIndex + 1;
|
|
223
|
+
next.node = lastNode.nextSibling;
|
|
224
|
+
return next;
|
|
225
|
+
}
|
|
226
|
+
function compileChildren(context, parent, parentId) {
|
|
227
|
+
let nodeIndex = 0;
|
|
228
|
+
let childNode = parent.firstChild;
|
|
229
|
+
while (childNode) {
|
|
230
|
+
const result = compileNode(context, parentId, childNode, nodeIndex);
|
|
231
|
+
childNode = result.node;
|
|
232
|
+
nodeIndex = result.index;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function compileNode(context, parentId, node, nodeIndex) {
|
|
236
|
+
const nodeId = targetIdFrom(parentId, nodeIndex);
|
|
237
|
+
switch (node.nodeType) {
|
|
238
|
+
case 1: // element node
|
|
239
|
+
compileAttributes(context, parentId, node, nodeId, nodeIndex);
|
|
240
|
+
compileChildren(context, node, nodeId);
|
|
241
|
+
break;
|
|
242
|
+
case 3: // text node
|
|
243
|
+
return compileContent(context, node, parentId, nodeId, nodeIndex);
|
|
244
|
+
case 8: {
|
|
245
|
+
// comment
|
|
246
|
+
const parts = Parser.parse(node.data, context.directives);
|
|
247
|
+
if (parts !== null) {
|
|
248
|
+
context.addFactory(Compiler.aggregate(parts), parentId, nodeId, nodeIndex, null);
|
|
249
|
+
}
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
next.index = nodeIndex + 1;
|
|
254
|
+
next.node = node.nextSibling;
|
|
255
|
+
return next;
|
|
256
|
+
}
|
|
257
|
+
function isMarker(node, directives) {
|
|
258
|
+
return (node &&
|
|
259
|
+
node.nodeType === 8 &&
|
|
260
|
+
Parser.parse(node.data, directives) !== null);
|
|
261
|
+
}
|
|
262
|
+
const templateTag = "TEMPLATE";
|
|
263
|
+
/**
|
|
264
|
+
* Common APIs related to compilation.
|
|
265
|
+
* @public
|
|
266
|
+
*/
|
|
267
|
+
export const Compiler = {
|
|
268
|
+
/**
|
|
269
|
+
* Compiles a template and associated directives into a compilation
|
|
270
|
+
* result which can be used to create views.
|
|
271
|
+
* @param html - The html string or template element to compile.
|
|
272
|
+
* @param factories - The behavior factories referenced by the template.
|
|
273
|
+
* @param policy - The security policy to compile the html with.
|
|
274
|
+
* @remarks
|
|
275
|
+
* The template that is provided for compilation is altered in-place
|
|
276
|
+
* and cannot be compiled again. If the original template must be preserved,
|
|
277
|
+
* it is recommended that you clone the original and pass the clone to this API.
|
|
278
|
+
* @public
|
|
279
|
+
*/
|
|
280
|
+
compile(html, factories, policy = DOM.policy) {
|
|
281
|
+
let template;
|
|
282
|
+
if (isString(html)) {
|
|
283
|
+
template = document.createElement(templateTag);
|
|
284
|
+
template.innerHTML = policy.createHTML(html);
|
|
285
|
+
const fec = template.content.firstElementChild;
|
|
286
|
+
if (fec !== null && fec.tagName === templateTag) {
|
|
287
|
+
template = fec;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
template = html;
|
|
292
|
+
}
|
|
293
|
+
if (!template.content.firstChild && !template.content.lastChild) {
|
|
294
|
+
template.content.appendChild(document.createComment(""));
|
|
295
|
+
}
|
|
296
|
+
// https://bugs.chromium.org/p/chromium/issues/detail?id=1111864
|
|
297
|
+
const fragment = document.adoptNode(template.content);
|
|
298
|
+
const context = new CompilationContext(fragment, factories, policy);
|
|
299
|
+
compileAttributes(context, "", template, /* host */ "h", 0, true);
|
|
300
|
+
if (
|
|
301
|
+
// If the first node in a fragment is a marker, that means it's an unstable first node,
|
|
302
|
+
// because something like a when, repeat, etc. could add nodes before the marker.
|
|
303
|
+
// To mitigate this, we insert a stable first node. However, if we insert a node,
|
|
304
|
+
// that will alter the result of the TreeWalker. So, we also need to offset the target index.
|
|
305
|
+
isMarker(fragment.firstChild, factories) ||
|
|
306
|
+
// Or if there is only one node and a directive, it means the template's content
|
|
307
|
+
// is *only* the directive. In that case, HTMLView.dispose() misses any nodes inserted by
|
|
308
|
+
// the directive. Inserting a new node ensures proper disposal of nodes added by the directive.
|
|
309
|
+
(fragment.childNodes.length === 1 && Object.keys(factories).length > 0)) {
|
|
310
|
+
fragment.insertBefore(document.createComment(""), fragment.firstChild);
|
|
311
|
+
}
|
|
312
|
+
compileChildren(context, fragment, /* root */ "r");
|
|
313
|
+
next.node = null; // prevent leaks
|
|
314
|
+
return context.freeze();
|
|
315
|
+
},
|
|
316
|
+
/**
|
|
317
|
+
* Sets the default compilation strategy that will be used by the ViewTemplate whenever
|
|
318
|
+
* it needs to compile a view preprocessed with the html template function.
|
|
319
|
+
* @param strategy - The compilation strategy to use when compiling templates.
|
|
320
|
+
*/
|
|
321
|
+
setDefaultStrategy(strategy) {
|
|
322
|
+
this.compile = strategy;
|
|
323
|
+
},
|
|
324
|
+
/**
|
|
325
|
+
* Aggregates an array of strings and directives into a single directive.
|
|
326
|
+
* @param parts - A heterogeneous array of static strings interspersed with
|
|
327
|
+
* directives.
|
|
328
|
+
* @param policy - The security policy to use with the aggregated bindings.
|
|
329
|
+
* @returns A single inline directive that aggregates the behavior of all the parts.
|
|
330
|
+
*/
|
|
331
|
+
aggregate(parts, policy = DOM.policy) {
|
|
332
|
+
if (parts.length === 1) {
|
|
333
|
+
return parts[0];
|
|
334
|
+
}
|
|
335
|
+
let sourceAspect;
|
|
336
|
+
let isVolatile = false;
|
|
337
|
+
let bindingPolicy = void 0;
|
|
338
|
+
const partCount = parts.length;
|
|
339
|
+
const finalParts = parts.map((x) => {
|
|
340
|
+
if (isString(x)) {
|
|
341
|
+
return () => x;
|
|
342
|
+
}
|
|
343
|
+
sourceAspect = x.sourceAspect || sourceAspect;
|
|
344
|
+
isVolatile = isVolatile || x.dataBinding.isVolatile;
|
|
345
|
+
bindingPolicy = bindingPolicy || x.dataBinding.policy;
|
|
346
|
+
return x.dataBinding.evaluate;
|
|
347
|
+
});
|
|
348
|
+
const expression = (scope, context) => {
|
|
349
|
+
let output = "";
|
|
350
|
+
for (let i = 0; i < partCount; ++i) {
|
|
351
|
+
output += finalParts[i](scope, context);
|
|
352
|
+
}
|
|
353
|
+
return output;
|
|
354
|
+
};
|
|
355
|
+
const directive = new HTMLBindingDirective(oneWay(expression, bindingPolicy !== null && bindingPolicy !== void 0 ? bindingPolicy : policy, isVolatile));
|
|
356
|
+
HTMLDirective.assignAspect(directive, sourceAspect);
|
|
357
|
+
return directive;
|
|
358
|
+
},
|
|
359
|
+
};
|