@microsoft/fast-element 1.10.2 → 2.0.0-beta.1
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/.eslintrc.json +1 -12
- package/CHANGELOG.json +321 -1
- package/CHANGELOG.md +52 -2
- package/README.md +2 -2
- package/dist/dts/components/attributes.d.ts +4 -1
- package/dist/dts/components/controller.d.ts +12 -11
- package/dist/dts/components/fast-definitions.d.ts +8 -2
- package/dist/dts/components/fast-element.d.ts +5 -4
- package/dist/dts/debug.d.ts +1 -0
- package/dist/dts/hooks.d.ts +20 -0
- package/dist/dts/index.d.ts +16 -15
- package/dist/dts/index.debug.d.ts +2 -0
- package/dist/dts/index.rollup.d.ts +2 -0
- package/dist/dts/index.rollup.debug.d.ts +3 -0
- package/dist/dts/interfaces.d.ts +144 -0
- package/dist/dts/observation/arrays.d.ts +207 -0
- package/dist/dts/observation/behavior.d.ts +5 -5
- package/dist/dts/observation/notifier.d.ts +18 -18
- package/dist/dts/observation/observable.d.ts +86 -29
- package/dist/dts/observation/splice-strategies.d.ts +13 -0
- package/dist/dts/observation/update-queue.d.ts +40 -0
- package/dist/dts/platform.d.ts +18 -67
- package/dist/dts/polyfills.d.ts +8 -0
- package/dist/dts/styles/css-directive.d.ts +43 -5
- package/dist/dts/styles/css.d.ts +19 -3
- package/dist/dts/styles/element-styles.d.ts +42 -62
- package/dist/dts/templating/binding.d.ts +320 -64
- package/dist/dts/templating/children.d.ts +18 -15
- package/dist/dts/templating/compiler.d.ts +47 -28
- package/dist/dts/templating/dom.d.ts +41 -0
- package/dist/dts/templating/html-directive.d.ts +179 -43
- package/dist/dts/templating/markup.d.ts +48 -0
- package/dist/dts/templating/node-observation.d.ts +45 -29
- package/dist/dts/templating/ref.d.ts +6 -12
- package/dist/dts/templating/repeat.d.ts +72 -14
- package/dist/dts/templating/slotted.d.ts +13 -14
- package/dist/dts/templating/template.d.ts +78 -23
- package/dist/dts/templating/view.d.ts +16 -23
- package/dist/dts/utilities.d.ts +40 -0
- package/dist/esm/components/attributes.js +25 -24
- package/dist/esm/components/controller.js +77 -57
- package/dist/esm/components/fast-definitions.js +14 -22
- package/dist/esm/debug.js +29 -0
- package/dist/esm/hooks.js +32 -0
- package/dist/esm/index.debug.js +2 -0
- package/dist/esm/index.js +19 -14
- package/dist/esm/index.rollup.debug.js +3 -0
- package/dist/esm/index.rollup.js +2 -0
- package/dist/esm/interfaces.js +8 -1
- package/dist/esm/observation/arrays.js +269 -0
- package/dist/esm/observation/notifier.js +27 -35
- package/dist/esm/observation/observable.js +80 -107
- package/dist/esm/observation/{array-change-records.js → splice-strategies.js} +136 -62
- package/dist/esm/observation/update-queue.js +67 -0
- package/dist/esm/platform.js +36 -42
- package/dist/esm/polyfills.js +85 -0
- package/dist/esm/styles/css-directive.js +29 -13
- package/dist/esm/styles/css.js +27 -40
- package/dist/esm/styles/element-styles.js +65 -104
- package/dist/esm/templating/binding.js +465 -155
- package/dist/esm/templating/children.js +33 -23
- package/dist/esm/templating/compiler.js +235 -152
- package/dist/esm/templating/dom.js +49 -0
- package/dist/esm/templating/html-directive.js +125 -40
- package/dist/esm/templating/markup.js +75 -0
- package/dist/esm/templating/node-observation.js +50 -45
- package/dist/esm/templating/ref.js +7 -16
- package/dist/esm/templating/repeat.js +38 -43
- package/dist/esm/templating/slotted.js +23 -20
- package/dist/esm/templating/template.js +71 -95
- package/dist/esm/templating/view.js +44 -43
- package/dist/esm/templating/when.js +2 -1
- package/dist/esm/utilities.js +139 -0
- package/dist/fast-element.api.json +13633 -5266
- package/dist/fast-element.d.ts +1434 -578
- package/dist/fast-element.debug.js +3824 -0
- package/dist/fast-element.debug.min.js +1 -0
- package/dist/fast-element.js +3574 -4020
- package/dist/fast-element.min.js +1 -1
- package/dist/fast-element.untrimmed.d.ts +2908 -0
- package/dist/tsdoc-metadata.json +1 -1
- package/docs/api-report.md +590 -231
- package/docs/fast-element-2-changes.md +15 -0
- package/docs/guide/declaring-templates.md +4 -4
- package/docs/guide/defining-elements.md +2 -2
- package/docs/guide/next-steps.md +2 -2
- package/docs/guide/observables-and-state.md +1 -1
- package/docs/guide/using-directives.md +1 -1
- package/karma.conf.cjs +6 -17
- package/package.json +46 -14
- package/dist/dts/dom.d.ts +0 -112
- package/dist/dts/observation/array-change-records.d.ts +0 -48
- package/dist/dts/observation/array-observer.d.ts +0 -9
- package/dist/esm/dom.js +0 -207
- package/dist/esm/observation/array-observer.js +0 -177
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import "../interfaces.js";
|
|
2
|
+
import { FAST } from "../platform.js";
|
|
3
|
+
/**
|
|
4
|
+
* The default UpdateQueue.
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export const Updates = FAST.getById(1 /* KernelServiceId.updateQueue */, () => {
|
|
8
|
+
const tasks = [];
|
|
9
|
+
const pendingErrors = [];
|
|
10
|
+
const rAF = globalThis.requestAnimationFrame;
|
|
11
|
+
let updateAsync = true;
|
|
12
|
+
function throwFirstError() {
|
|
13
|
+
if (pendingErrors.length) {
|
|
14
|
+
throw pendingErrors.shift();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function tryRunTask(task) {
|
|
18
|
+
try {
|
|
19
|
+
task.call();
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
if (updateAsync) {
|
|
23
|
+
pendingErrors.push(error);
|
|
24
|
+
setTimeout(throwFirstError, 0);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
tasks.length = 0;
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function process() {
|
|
33
|
+
const capacity = 1024;
|
|
34
|
+
let index = 0;
|
|
35
|
+
while (index < tasks.length) {
|
|
36
|
+
tryRunTask(tasks[index]);
|
|
37
|
+
index++;
|
|
38
|
+
// Prevent leaking memory for long chains of recursive calls to `enqueue`.
|
|
39
|
+
// If we call `enqueue` within a task scheduled by `enqueue`, the queue will
|
|
40
|
+
// grow, but to avoid an O(n) walk for every task we execute, we don't
|
|
41
|
+
// shift tasks off the queue after they have been executed.
|
|
42
|
+
// Instead, we periodically shift 1024 tasks off the queue.
|
|
43
|
+
if (index > capacity) {
|
|
44
|
+
// Manually shift all values starting at the index back to the
|
|
45
|
+
// beginning of the queue.
|
|
46
|
+
for (let scan = 0, newLength = tasks.length - index; scan < newLength; scan++) {
|
|
47
|
+
tasks[scan] = tasks[scan + index];
|
|
48
|
+
}
|
|
49
|
+
tasks.length -= index;
|
|
50
|
+
index = 0;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
tasks.length = 0;
|
|
54
|
+
}
|
|
55
|
+
function enqueue(callable) {
|
|
56
|
+
tasks.push(callable);
|
|
57
|
+
if (tasks.length < 2) {
|
|
58
|
+
updateAsync ? rAF(process) : process();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return Object.freeze({
|
|
62
|
+
enqueue,
|
|
63
|
+
next: () => new Promise(enqueue),
|
|
64
|
+
process,
|
|
65
|
+
setMode: (isAsync) => (updateAsync = isAsync),
|
|
66
|
+
});
|
|
67
|
+
});
|
package/dist/esm/platform.js
CHANGED
|
@@ -1,54 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
* A reference to globalThis, with support
|
|
3
|
-
* for browsers that don't yet support the spec.
|
|
4
|
-
* @public
|
|
5
|
-
*/
|
|
6
|
-
export const $global = (function () {
|
|
7
|
-
if (typeof globalThis !== "undefined") {
|
|
8
|
-
// We're running in a modern environment.
|
|
9
|
-
return globalThis;
|
|
10
|
-
}
|
|
11
|
-
if (typeof global !== "undefined") {
|
|
12
|
-
// We're running in NodeJS
|
|
13
|
-
return global;
|
|
14
|
-
}
|
|
15
|
-
if (typeof self !== "undefined") {
|
|
16
|
-
// We're running in a worker.
|
|
17
|
-
return self;
|
|
18
|
-
}
|
|
19
|
-
if (typeof window !== "undefined") {
|
|
20
|
-
// We're running in the browser's main thread.
|
|
21
|
-
return window;
|
|
22
|
-
}
|
|
23
|
-
try {
|
|
24
|
-
// Hopefully we never get here...
|
|
25
|
-
// Not all environments allow eval and Function. Use only as a last resort:
|
|
26
|
-
// eslint-disable-next-line no-new-func
|
|
27
|
-
return new Function("return this")();
|
|
28
|
-
}
|
|
29
|
-
catch (_a) {
|
|
30
|
-
// If all fails, give up and create an object.
|
|
31
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
32
|
-
return {};
|
|
33
|
-
}
|
|
34
|
-
})();
|
|
35
|
-
// API-only Polyfill for trustedTypes
|
|
36
|
-
if ($global.trustedTypes === void 0) {
|
|
37
|
-
$global.trustedTypes = { createPolicy: (n, r) => r };
|
|
38
|
-
}
|
|
1
|
+
// ensure FAST global - duplicated in polyfills.ts and debug.ts
|
|
39
2
|
const propConfig = {
|
|
40
3
|
configurable: false,
|
|
41
4
|
enumerable: false,
|
|
42
5
|
writable: false,
|
|
43
6
|
};
|
|
44
|
-
if (
|
|
45
|
-
Reflect.defineProperty(
|
|
7
|
+
if (globalThis.FAST === void 0) {
|
|
8
|
+
Reflect.defineProperty(globalThis, "FAST", Object.assign({ value: Object.create(null) }, propConfig));
|
|
46
9
|
}
|
|
47
10
|
/**
|
|
48
11
|
* The FAST global.
|
|
49
12
|
* @internal
|
|
50
13
|
*/
|
|
51
|
-
export const FAST =
|
|
14
|
+
export const FAST = globalThis.FAST;
|
|
52
15
|
if (FAST.getById === void 0) {
|
|
53
16
|
const storage = Object.create(null);
|
|
54
17
|
Reflect.defineProperty(FAST, "getById", Object.assign({ value(id, initialize) {
|
|
@@ -59,11 +22,42 @@ if (FAST.getById === void 0) {
|
|
|
59
22
|
return found;
|
|
60
23
|
} }, propConfig));
|
|
61
24
|
}
|
|
25
|
+
if (FAST.error === void 0) {
|
|
26
|
+
Object.assign(FAST, {
|
|
27
|
+
warn() { },
|
|
28
|
+
error(code) {
|
|
29
|
+
return new Error(`Code ${code}`);
|
|
30
|
+
},
|
|
31
|
+
addMessages() { },
|
|
32
|
+
});
|
|
33
|
+
}
|
|
62
34
|
/**
|
|
63
35
|
* A readonly, empty array.
|
|
64
36
|
* @remarks
|
|
65
37
|
* Typically returned by APIs that return arrays when there are
|
|
66
38
|
* no actual items to return.
|
|
67
|
-
* @
|
|
39
|
+
* @public
|
|
68
40
|
*/
|
|
69
41
|
export const emptyArray = Object.freeze([]);
|
|
42
|
+
/**
|
|
43
|
+
* Do not change. Part of shared kernel contract.
|
|
44
|
+
* @internal
|
|
45
|
+
*/
|
|
46
|
+
export function createTypeRegistry() {
|
|
47
|
+
const typeToDefinition = new Map();
|
|
48
|
+
return Object.freeze({
|
|
49
|
+
register(definition) {
|
|
50
|
+
if (typeToDefinition.has(definition.type)) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
typeToDefinition.set(definition.type, definition);
|
|
54
|
+
return true;
|
|
55
|
+
},
|
|
56
|
+
getByType(key) {
|
|
57
|
+
return typeToDefinition.get(key);
|
|
58
|
+
},
|
|
59
|
+
getForInstance(object) {
|
|
60
|
+
return typeToDefinition.get(object.constructor);
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
(function ensureGlobalThis() {
|
|
2
|
+
if (typeof globalThis !== "undefined") {
|
|
3
|
+
// We're running in a modern environment.
|
|
4
|
+
return;
|
|
5
|
+
}
|
|
6
|
+
if (typeof global !== "undefined") {
|
|
7
|
+
// We're running in NodeJS
|
|
8
|
+
global.globalThis = global;
|
|
9
|
+
}
|
|
10
|
+
else if (typeof self !== "undefined") {
|
|
11
|
+
self.globalThis = self;
|
|
12
|
+
}
|
|
13
|
+
else if (typeof window !== "undefined") {
|
|
14
|
+
// We're running in the browser's main thread.
|
|
15
|
+
window.globalThis = window;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
// Hopefully we never get here...
|
|
19
|
+
// Not all environments allow eval and Function. Use only as a last resort:
|
|
20
|
+
// eslint-disable-next-line no-new-func
|
|
21
|
+
const result = new Function("return this")();
|
|
22
|
+
result.globalThis = result;
|
|
23
|
+
}
|
|
24
|
+
})();
|
|
25
|
+
// API-only Polyfill for trustedTypes
|
|
26
|
+
if (!globalThis.trustedTypes) {
|
|
27
|
+
globalThis.trustedTypes = {
|
|
28
|
+
createPolicy: (n, r) => r,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
// ensure FAST global - duplicated in platform.ts
|
|
32
|
+
const propConfig = {
|
|
33
|
+
configurable: false,
|
|
34
|
+
enumerable: false,
|
|
35
|
+
writable: false,
|
|
36
|
+
};
|
|
37
|
+
if (globalThis.FAST === void 0) {
|
|
38
|
+
Reflect.defineProperty(globalThis, "FAST", Object.assign({ value: Object.create(null) }, propConfig));
|
|
39
|
+
}
|
|
40
|
+
const FAST = globalThis.FAST;
|
|
41
|
+
if (FAST.getById === void 0) {
|
|
42
|
+
const storage = Object.create(null);
|
|
43
|
+
Reflect.defineProperty(FAST, "getById", Object.assign({ value(id, initialize) {
|
|
44
|
+
let found = storage[id];
|
|
45
|
+
if (found === void 0) {
|
|
46
|
+
found = initialize ? (storage[id] = initialize()) : null;
|
|
47
|
+
}
|
|
48
|
+
return found;
|
|
49
|
+
} }, propConfig));
|
|
50
|
+
}
|
|
51
|
+
// duplicated from DOM
|
|
52
|
+
const supportsAdoptedStyleSheets = Array.isArray(document.adoptedStyleSheets) &&
|
|
53
|
+
"replace" in CSSStyleSheet.prototype;
|
|
54
|
+
function usableStyleTarget(target) {
|
|
55
|
+
return target === document ? document.body : target;
|
|
56
|
+
}
|
|
57
|
+
let id = 0;
|
|
58
|
+
const nextStyleId = () => `fast-${++id}`;
|
|
59
|
+
export class StyleElementStrategy {
|
|
60
|
+
constructor(styles) {
|
|
61
|
+
this.styles = styles;
|
|
62
|
+
this.styleClass = nextStyleId();
|
|
63
|
+
}
|
|
64
|
+
addStylesTo(target) {
|
|
65
|
+
target = usableStyleTarget(target);
|
|
66
|
+
const styles = this.styles;
|
|
67
|
+
const styleClass = this.styleClass;
|
|
68
|
+
for (let i = 0; i < styles.length; i++) {
|
|
69
|
+
const element = document.createElement("style");
|
|
70
|
+
element.innerHTML = styles[i];
|
|
71
|
+
element.className = styleClass;
|
|
72
|
+
target.append(element);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
removeStylesFrom(target) {
|
|
76
|
+
const styles = target.querySelectorAll(`.${this.styleClass}`);
|
|
77
|
+
target = usableStyleTarget(target);
|
|
78
|
+
for (let i = 0, ii = styles.length; i < ii; ++i) {
|
|
79
|
+
target.removeChild(styles[i]);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (!supportsAdoptedStyleSheets) {
|
|
84
|
+
FAST.getById(/* KernelServiceId.styleSheetStrategy */ 5, () => StyleElementStrategy);
|
|
85
|
+
}
|
|
@@ -1,21 +1,37 @@
|
|
|
1
|
+
import { createTypeRegistry } from "../platform.js";
|
|
2
|
+
const registry = createTypeRegistry();
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
+
* Instructs the css engine to provide dynamic styles or
|
|
5
|
+
* associate behaviors with styles.
|
|
4
6
|
* @public
|
|
5
7
|
*/
|
|
6
|
-
export
|
|
8
|
+
export const CSSDirective = Object.freeze({
|
|
7
9
|
/**
|
|
8
|
-
*
|
|
9
|
-
* @
|
|
10
|
+
* Gets the directive definition associated with the instance.
|
|
11
|
+
* @param instance - The directive instance to retrieve the definition for.
|
|
10
12
|
*/
|
|
11
|
-
|
|
12
|
-
return "";
|
|
13
|
-
}
|
|
13
|
+
getForInstance: registry.getForInstance,
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
16
|
-
* @
|
|
15
|
+
* Gets the directive definition associated with the specified type.
|
|
16
|
+
* @param type - The directive type to retrieve the definition for.
|
|
17
17
|
*/
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
getByType: registry.getByType,
|
|
19
|
+
/**
|
|
20
|
+
* Defines a CSSDirective.
|
|
21
|
+
* @param type - The type to define as a directive.
|
|
22
|
+
*/
|
|
23
|
+
define(type) {
|
|
24
|
+
registry.register({ type });
|
|
25
|
+
return type;
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
/**
|
|
29
|
+
* Decorator: Defines a CSSDirective.
|
|
30
|
+
* @public
|
|
31
|
+
*/
|
|
32
|
+
export function cssDirective() {
|
|
33
|
+
/* eslint-disable-next-line @typescript-eslint/explicit-function-return-type */
|
|
34
|
+
return function (type) {
|
|
35
|
+
CSSDirective.define(type);
|
|
36
|
+
};
|
|
21
37
|
}
|
package/dist/esm/styles/css.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
+
import { isString } from "../interfaces.js";
|
|
1
2
|
import { CSSDirective } from "./css-directive.js";
|
|
2
3
|
import { ElementStyles } from "./element-styles.js";
|
|
3
4
|
function collectStyles(strings, values) {
|
|
4
5
|
const styles = [];
|
|
5
6
|
let cssString = "";
|
|
6
7
|
const behaviors = [];
|
|
8
|
+
const add = (behavior) => {
|
|
9
|
+
behaviors.push(behavior);
|
|
10
|
+
};
|
|
7
11
|
for (let i = 0, ii = strings.length - 1; i < ii; ++i) {
|
|
8
12
|
cssString += strings[i];
|
|
9
13
|
let value = values[i];
|
|
10
|
-
if (value
|
|
11
|
-
|
|
12
|
-
value = value.createCSS();
|
|
13
|
-
if (behavior) {
|
|
14
|
-
behaviors.push(behavior);
|
|
15
|
-
}
|
|
14
|
+
if (CSSDirective.getForInstance(value) !== void 0) {
|
|
15
|
+
value = value.createCSS(add);
|
|
16
16
|
}
|
|
17
17
|
if (value instanceof ElementStyles || value instanceof CSSStyleSheet) {
|
|
18
18
|
if (cssString.trim() !== "") {
|
|
@@ -42,21 +42,17 @@ function collectStyles(strings, values) {
|
|
|
42
42
|
* The css helper supports interpolation of strings and ElementStyle instances.
|
|
43
43
|
* @public
|
|
44
44
|
*/
|
|
45
|
-
export
|
|
45
|
+
export const css = ((strings, ...values) => {
|
|
46
46
|
const { styles, behaviors } = collectStyles(strings, values);
|
|
47
|
-
const elementStyles = ElementStyles
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return elementStyles;
|
|
52
|
-
}
|
|
53
|
-
class CSSPartial extends CSSDirective {
|
|
47
|
+
const elementStyles = new ElementStyles(styles);
|
|
48
|
+
return behaviors.length ? elementStyles.withBehaviors(...behaviors) : elementStyles;
|
|
49
|
+
});
|
|
50
|
+
class CSSPartial {
|
|
54
51
|
constructor(styles, behaviors) {
|
|
55
|
-
super();
|
|
56
52
|
this.behaviors = behaviors;
|
|
57
53
|
this.css = "";
|
|
58
54
|
const stylesheets = styles.reduce((accumulated, current) => {
|
|
59
|
-
if (
|
|
55
|
+
if (isString(current)) {
|
|
60
56
|
this.css += current;
|
|
61
57
|
}
|
|
62
58
|
else {
|
|
@@ -65,39 +61,30 @@ class CSSPartial extends CSSDirective {
|
|
|
65
61
|
return accumulated;
|
|
66
62
|
}, []);
|
|
67
63
|
if (stylesheets.length) {
|
|
68
|
-
this.styles = ElementStyles
|
|
64
|
+
this.styles = new ElementStyles(stylesheets);
|
|
69
65
|
}
|
|
70
66
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
67
|
+
createCSS(add) {
|
|
68
|
+
this.behaviors.forEach(add);
|
|
69
|
+
if (this.styles) {
|
|
70
|
+
add(this);
|
|
71
|
+
}
|
|
75
72
|
return this.css;
|
|
76
73
|
}
|
|
77
74
|
bind(el) {
|
|
78
|
-
|
|
79
|
-
el.$fastController.addStyles(this.styles);
|
|
80
|
-
}
|
|
81
|
-
if (this.behaviors.length) {
|
|
82
|
-
el.$fastController.addBehaviors(this.behaviors);
|
|
83
|
-
}
|
|
75
|
+
el.$fastController.addStyles(this.styles);
|
|
84
76
|
}
|
|
85
77
|
unbind(el) {
|
|
86
|
-
|
|
87
|
-
el.$fastController.removeStyles(this.styles);
|
|
88
|
-
}
|
|
89
|
-
if (this.behaviors.length) {
|
|
90
|
-
el.$fastController.removeBehaviors(this.behaviors);
|
|
91
|
-
}
|
|
78
|
+
el.$fastController.removeStyles(this.styles);
|
|
92
79
|
}
|
|
93
80
|
}
|
|
81
|
+
CSSDirective.define(CSSPartial);
|
|
82
|
+
css.partial = (strings, ...values) => {
|
|
83
|
+
const { styles, behaviors } = collectStyles(strings, values);
|
|
84
|
+
return new CSSPartial(styles, behaviors);
|
|
85
|
+
};
|
|
94
86
|
/**
|
|
95
|
-
*
|
|
96
|
-
* @param strings - The string fragments that are interpolated with the values.
|
|
97
|
-
* @param values - The values that are interpolated with the string fragments.
|
|
87
|
+
* @deprecated Use css.partial instead.
|
|
98
88
|
* @public
|
|
99
89
|
*/
|
|
100
|
-
export
|
|
101
|
-
const { styles, behaviors } = collectStyles(strings, values);
|
|
102
|
-
return new CSSPartial(styles, behaviors);
|
|
103
|
-
}
|
|
90
|
+
export const cssPartial = css.partial;
|
|
@@ -1,18 +1,46 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FAST } from "../platform.js";
|
|
2
|
+
import "../interfaces.js";
|
|
3
|
+
const styleSheetCache = new Map();
|
|
4
|
+
let DefaultStyleStrategy;
|
|
5
|
+
function reduceStyles(styles) {
|
|
6
|
+
return styles
|
|
7
|
+
.map((x) => x instanceof ElementStyles ? reduceStyles(x.styles) : [x])
|
|
8
|
+
.reduce((prev, curr) => prev.concat(curr), []);
|
|
9
|
+
}
|
|
2
10
|
/**
|
|
3
11
|
* Represents styles that can be applied to a custom element.
|
|
4
12
|
* @public
|
|
5
13
|
*/
|
|
6
14
|
export class ElementStyles {
|
|
7
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Creates an instance of ElementStyles.
|
|
17
|
+
* @param styles - The styles that will be associated with elements.
|
|
18
|
+
*/
|
|
19
|
+
constructor(styles) {
|
|
20
|
+
this.styles = styles;
|
|
8
21
|
this.targets = new WeakSet();
|
|
22
|
+
this._strategy = null;
|
|
23
|
+
this.behaviors = styles
|
|
24
|
+
.map((x) => x instanceof ElementStyles ? x.behaviors : null)
|
|
25
|
+
.reduce((prev, curr) => (curr === null ? prev : prev === null ? curr : prev.concat(curr)), null);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Gets the StyleStrategy associated with these element styles.
|
|
29
|
+
*/
|
|
30
|
+
get strategy() {
|
|
31
|
+
if (this._strategy === null) {
|
|
32
|
+
this.withStrategy(DefaultStyleStrategy);
|
|
33
|
+
}
|
|
34
|
+
return this._strategy;
|
|
9
35
|
}
|
|
10
36
|
/** @internal */
|
|
11
37
|
addStylesTo(target) {
|
|
38
|
+
this.strategy.addStylesTo(target);
|
|
12
39
|
this.targets.add(target);
|
|
13
40
|
}
|
|
14
41
|
/** @internal */
|
|
15
42
|
removeStylesFrom(target) {
|
|
43
|
+
this.strategy.removeStylesFrom(target);
|
|
16
44
|
this.targets.delete(target);
|
|
17
45
|
}
|
|
18
46
|
/** @internal */
|
|
@@ -28,121 +56,54 @@ export class ElementStyles {
|
|
|
28
56
|
this.behaviors === null ? behaviors : this.behaviors.concat(behaviors);
|
|
29
57
|
return this;
|
|
30
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Sets the strategy that handles adding/removing these styles for an element.
|
|
61
|
+
* @param strategy - The strategy to use.
|
|
62
|
+
*/
|
|
63
|
+
withStrategy(Strategy) {
|
|
64
|
+
this._strategy = new Strategy(reduceStyles(this.styles));
|
|
65
|
+
return this;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Sets the default strategy type to use when creating style strategies.
|
|
69
|
+
* @param Strategy - The strategy type to construct.
|
|
70
|
+
*/
|
|
71
|
+
static setDefaultStrategy(Strategy) {
|
|
72
|
+
DefaultStyleStrategy = Strategy;
|
|
73
|
+
}
|
|
31
74
|
}
|
|
32
75
|
/**
|
|
33
|
-
*
|
|
76
|
+
* Indicates whether the DOM supports the adoptedStyleSheets feature.
|
|
34
77
|
*/
|
|
35
|
-
ElementStyles.
|
|
36
|
-
|
|
37
|
-
const styleSheetCache = new Map();
|
|
38
|
-
return (styles) =>
|
|
39
|
-
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
40
|
-
new AdoptedStyleSheetsStyles(styles, styleSheetCache);
|
|
41
|
-
}
|
|
42
|
-
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
43
|
-
return (styles) => new StyleElementStyles(styles);
|
|
44
|
-
})();
|
|
45
|
-
function reduceStyles(styles) {
|
|
46
|
-
return styles
|
|
47
|
-
.map((x) => x instanceof ElementStyles ? reduceStyles(x.styles) : [x])
|
|
48
|
-
.reduce((prev, curr) => prev.concat(curr), []);
|
|
49
|
-
}
|
|
50
|
-
function reduceBehaviors(styles) {
|
|
51
|
-
return styles
|
|
52
|
-
.map((x) => (x instanceof ElementStyles ? x.behaviors : null))
|
|
53
|
-
.reduce((prev, curr) => {
|
|
54
|
-
if (curr === null) {
|
|
55
|
-
return prev;
|
|
56
|
-
}
|
|
57
|
-
if (prev === null) {
|
|
58
|
-
prev = [];
|
|
59
|
-
}
|
|
60
|
-
return prev.concat(curr);
|
|
61
|
-
}, null);
|
|
62
|
-
}
|
|
78
|
+
ElementStyles.supportsAdoptedStyleSheets = Array.isArray(document.adoptedStyleSheets) &&
|
|
79
|
+
"replace" in CSSStyleSheet.prototype;
|
|
63
80
|
/**
|
|
64
81
|
* https://wicg.github.io/construct-stylesheets/
|
|
65
82
|
* https://developers.google.com/web/updates/2019/02/constructable-stylesheets
|
|
66
83
|
*
|
|
67
84
|
* @internal
|
|
68
85
|
*/
|
|
69
|
-
export class
|
|
70
|
-
constructor(styles, styleSheetCache) {
|
|
71
|
-
super();
|
|
72
|
-
this.styles = styles;
|
|
73
|
-
this.styleSheetCache = styleSheetCache;
|
|
74
|
-
this._styleSheets = void 0;
|
|
75
|
-
this.behaviors = reduceBehaviors(styles);
|
|
76
|
-
}
|
|
77
|
-
get styleSheets() {
|
|
78
|
-
if (this._styleSheets === void 0) {
|
|
79
|
-
const styles = this.styles;
|
|
80
|
-
const styleSheetCache = this.styleSheetCache;
|
|
81
|
-
this._styleSheets = reduceStyles(styles).map((x) => {
|
|
82
|
-
if (x instanceof CSSStyleSheet) {
|
|
83
|
-
return x;
|
|
84
|
-
}
|
|
85
|
-
let sheet = styleSheetCache.get(x);
|
|
86
|
-
if (sheet === void 0) {
|
|
87
|
-
sheet = new CSSStyleSheet();
|
|
88
|
-
sheet.replaceSync(x);
|
|
89
|
-
styleSheetCache.set(x, sheet);
|
|
90
|
-
}
|
|
91
|
-
return sheet;
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
return this._styleSheets;
|
|
95
|
-
}
|
|
96
|
-
addStylesTo(target) {
|
|
97
|
-
target.adoptedStyleSheets = [...target.adoptedStyleSheets, ...this.styleSheets];
|
|
98
|
-
super.addStylesTo(target);
|
|
99
|
-
}
|
|
100
|
-
removeStylesFrom(target) {
|
|
101
|
-
const sourceSheets = this.styleSheets;
|
|
102
|
-
target.adoptedStyleSheets = target.adoptedStyleSheets.filter((x) => sourceSheets.indexOf(x) === -1);
|
|
103
|
-
super.removeStylesFrom(target);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
let styleClassId = 0;
|
|
107
|
-
function getNextStyleClass() {
|
|
108
|
-
return `fast-style-class-${++styleClassId}`;
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* @internal
|
|
112
|
-
*/
|
|
113
|
-
export class StyleElementStyles extends ElementStyles {
|
|
86
|
+
export class AdoptedStyleSheetsStrategy {
|
|
114
87
|
constructor(styles) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
88
|
+
this.sheets = styles.map((x) => {
|
|
89
|
+
if (x instanceof CSSStyleSheet) {
|
|
90
|
+
return x;
|
|
91
|
+
}
|
|
92
|
+
let sheet = styleSheetCache.get(x);
|
|
93
|
+
if (sheet === void 0) {
|
|
94
|
+
sheet = new CSSStyleSheet();
|
|
95
|
+
sheet.replaceSync(x);
|
|
96
|
+
styleSheetCache.set(x, sheet);
|
|
97
|
+
}
|
|
98
|
+
return sheet;
|
|
99
|
+
});
|
|
121
100
|
}
|
|
122
101
|
addStylesTo(target) {
|
|
123
|
-
|
|
124
|
-
const styleClass = this.styleClass;
|
|
125
|
-
target = this.normalizeTarget(target);
|
|
126
|
-
for (let i = 0; i < styleSheets.length; i++) {
|
|
127
|
-
const element = document.createElement("style");
|
|
128
|
-
element.innerHTML = styleSheets[i];
|
|
129
|
-
element.className = styleClass;
|
|
130
|
-
target.append(element);
|
|
131
|
-
}
|
|
132
|
-
super.addStylesTo(target);
|
|
102
|
+
target.adoptedStyleSheets = [...target.adoptedStyleSheets, ...this.sheets];
|
|
133
103
|
}
|
|
134
104
|
removeStylesFrom(target) {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
for (let i = 0, ii = styles.length; i < ii; ++i) {
|
|
138
|
-
target.removeChild(styles[i]);
|
|
139
|
-
}
|
|
140
|
-
super.removeStylesFrom(target);
|
|
141
|
-
}
|
|
142
|
-
isAttachedTo(target) {
|
|
143
|
-
return super.isAttachedTo(this.normalizeTarget(target));
|
|
144
|
-
}
|
|
145
|
-
normalizeTarget(target) {
|
|
146
|
-
return target === document ? document.body : target;
|
|
105
|
+
const sheets = this.sheets;
|
|
106
|
+
target.adoptedStyleSheets = target.adoptedStyleSheets.filter((x) => sheets.indexOf(x) === -1);
|
|
147
107
|
}
|
|
148
108
|
}
|
|
109
|
+
ElementStyles.setDefaultStrategy(FAST.getById(5 /* KernelServiceId.styleSheetStrategy */, () => AdoptedStyleSheetsStrategy));
|