@microsoft/fast-element 1.10.5 → 2.0.0-beta.10
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 +629 -6
- package/CHANGELOG.md +152 -5
- package/dist/dts/components/attributes.d.ts +14 -1
- package/dist/dts/components/{controller.d.ts → element-controller.d.ts} +32 -32
- package/dist/dts/components/fast-definitions.d.ts +51 -11
- package/dist/dts/components/fast-element.d.ts +18 -23
- package/dist/dts/context.d.ts +157 -0
- package/dist/{esm/observation/behavior.js → dts/debug.d.ts} +0 -0
- package/dist/dts/di/di.d.ts +899 -0
- package/dist/dts/index.d.ts +17 -16
- 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 +176 -0
- package/dist/dts/metadata.d.ts +25 -0
- package/dist/dts/observation/arrays.d.ts +207 -0
- package/dist/dts/observation/notifier.d.ts +18 -18
- package/dist/dts/observation/observable.d.ts +117 -34
- package/dist/dts/observation/update-queue.d.ts +40 -0
- package/dist/dts/pending-task.d.ts +20 -0
- package/dist/dts/platform.d.ts +23 -66
- package/dist/dts/polyfills.d.ts +8 -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 +44 -6
- package/dist/dts/styles/css.d.ts +19 -3
- package/dist/dts/styles/element-styles.d.ts +49 -63
- package/dist/dts/styles/host.d.ts +68 -0
- package/dist/dts/templating/binding-signal.d.ts +21 -0
- package/dist/dts/templating/binding-two-way.d.ts +39 -0
- package/dist/dts/templating/binding.d.ts +101 -70
- package/dist/dts/templating/children.d.ts +18 -15
- package/dist/dts/templating/compiler.d.ts +46 -28
- package/dist/dts/templating/dom.d.ts +41 -0
- package/dist/dts/templating/html-directive.d.ts +239 -45
- package/dist/dts/templating/markup.d.ts +48 -0
- package/dist/dts/templating/node-observation.d.ts +45 -30
- package/dist/dts/templating/ref.d.ts +6 -20
- package/dist/dts/templating/render.d.ts +272 -0
- package/dist/dts/templating/repeat.d.ts +36 -33
- package/dist/dts/templating/slotted.d.ts +13 -14
- package/dist/dts/templating/template.d.ts +28 -22
- package/dist/dts/templating/view.d.ts +82 -24
- package/dist/dts/templating/when.d.ts +3 -3
- package/dist/dts/testing/exports.d.ts +3 -0
- package/dist/dts/testing/fakes.d.ts +4 -0
- package/dist/dts/testing/fixture.d.ts +84 -0
- package/dist/dts/testing/timeout.d.ts +7 -0
- package/dist/{tsdoc-metadata.json → dts/tsdoc-metadata.json} +1 -1
- package/dist/dts/utilities.d.ts +22 -0
- package/dist/esm/components/attributes.js +38 -28
- package/dist/esm/components/{controller.js → element-controller.js} +150 -140
- package/dist/esm/components/fast-definitions.js +48 -46
- package/dist/esm/components/fast-element.js +31 -12
- package/dist/esm/context.js +163 -0
- package/dist/esm/debug.js +61 -0
- package/dist/esm/di/di.js +1435 -0
- package/dist/esm/index.debug.js +2 -0
- package/dist/esm/index.js +20 -14
- package/dist/esm/index.rollup.debug.js +3 -0
- package/dist/esm/index.rollup.js +2 -0
- package/dist/esm/interfaces.js +12 -1
- package/dist/esm/metadata.js +60 -0
- package/dist/esm/observation/arrays.js +570 -0
- package/dist/esm/observation/notifier.js +27 -35
- package/dist/esm/observation/observable.js +116 -149
- package/dist/esm/observation/update-queue.js +67 -0
- package/dist/esm/pending-task.js +16 -0
- package/dist/esm/platform.js +60 -42
- package/dist/esm/polyfills.js +85 -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 +29 -13
- package/dist/esm/styles/css.js +29 -42
- package/dist/esm/styles/element-styles.js +79 -104
- package/dist/esm/styles/host.js +1 -0
- package/dist/esm/templating/binding-signal.js +83 -0
- package/dist/esm/templating/binding-two-way.js +103 -0
- package/dist/esm/templating/binding.js +189 -159
- package/dist/esm/templating/children.js +33 -23
- package/dist/esm/templating/compiler.js +258 -152
- package/dist/esm/templating/dom.js +49 -0
- package/dist/esm/templating/html-directive.js +193 -36
- package/dist/esm/templating/markup.js +75 -0
- package/dist/esm/templating/node-observation.js +51 -45
- package/dist/esm/templating/ref.js +8 -25
- package/dist/esm/templating/render.js +391 -0
- package/dist/esm/templating/repeat.js +83 -79
- package/dist/esm/templating/slotted.js +23 -20
- package/dist/esm/templating/template.js +51 -93
- package/dist/esm/templating/view.js +125 -46
- package/dist/esm/templating/when.js +6 -4
- package/dist/esm/testing/exports.js +3 -0
- package/dist/esm/testing/fakes.js +76 -0
- package/dist/esm/testing/fixture.js +86 -0
- package/dist/esm/testing/timeout.js +24 -0
- package/dist/esm/utilities.js +44 -0
- package/dist/fast-element.api.json +12153 -5373
- package/dist/fast-element.d.ts +1448 -696
- package/dist/fast-element.debug.js +4107 -0
- package/dist/fast-element.debug.min.js +1 -0
- package/dist/fast-element.js +3817 -4029
- package/dist/fast-element.min.js +1 -1
- package/dist/fast-element.untrimmed.d.ts +2814 -0
- package/docs/api-report.md +567 -254
- package/docs/fast-element-2-changes.md +15 -0
- package/karma.conf.cjs +6 -17
- package/package.json +76 -15
- 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/dts/observation/behavior.d.ts +0 -19
- package/dist/esm/dom.js +0 -207
- package/dist/esm/observation/array-change-records.js +0 -326
- package/dist/esm/observation/array-observer.js +0 -177
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,66 @@ 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(`Error ${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
|
+
if (object === null || object === void 0) {
|
|
61
|
+
return void 0;
|
|
62
|
+
}
|
|
63
|
+
return typeToDefinition.get(object.constructor);
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Creates a function capable of locating metadata associated with a type.
|
|
69
|
+
* @returns A metadata locator function.
|
|
70
|
+
* @internal
|
|
71
|
+
*/
|
|
72
|
+
export function createMetadataLocator() {
|
|
73
|
+
const metadataLookup = new WeakMap();
|
|
74
|
+
return function (target) {
|
|
75
|
+
let metadata = metadataLookup.get(target);
|
|
76
|
+
if (metadata === void 0) {
|
|
77
|
+
let currentTarget = Reflect.getPrototypeOf(target);
|
|
78
|
+
while (metadata === void 0 && currentTarget !== null) {
|
|
79
|
+
metadata = metadataLookup.get(currentTarget);
|
|
80
|
+
currentTarget = Reflect.getPrototypeOf(currentTarget);
|
|
81
|
+
}
|
|
82
|
+
metadata = metadata === void 0 ? [] : metadata.slice(0);
|
|
83
|
+
metadataLookup.set(target, metadata);
|
|
84
|
+
}
|
|
85
|
+
return metadata;
|
|
86
|
+
};
|
|
87
|
+
}
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { noop } from "../interfaces.js";
|
|
2
|
+
import { Observable } from "../observation/observable.js";
|
|
3
|
+
import { visitObject } from "./visitor.js";
|
|
4
|
+
const observed = new WeakSet();
|
|
5
|
+
const makeObserverVisitor = {
|
|
6
|
+
visitObject: noop,
|
|
7
|
+
visitArray: noop,
|
|
8
|
+
visitProperty(object, propertyName, value) {
|
|
9
|
+
Reflect.defineProperty(object, propertyName, {
|
|
10
|
+
enumerable: true,
|
|
11
|
+
get() {
|
|
12
|
+
Observable.track(object, propertyName);
|
|
13
|
+
return value;
|
|
14
|
+
},
|
|
15
|
+
set(newValue) {
|
|
16
|
+
if (value !== newValue) {
|
|
17
|
+
value = newValue;
|
|
18
|
+
Observable.notify(object, propertyName);
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Converts a plain object to a reactive, observable object.
|
|
26
|
+
* @param object - The object to make reactive.
|
|
27
|
+
* @param deep - Indicates whether or not to deeply convert the oject.
|
|
28
|
+
* @returns The converted object.
|
|
29
|
+
* @beta
|
|
30
|
+
*/
|
|
31
|
+
export function reactive(object, deep = false) {
|
|
32
|
+
visitObject(object, deep, makeObserverVisitor, void 0, observed);
|
|
33
|
+
return object;
|
|
34
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// Inspired by https://www.starbeamjs.com/
|
|
2
|
+
import { isFunction, isString } from "../interfaces.js";
|
|
3
|
+
import { Observable } from "../observation/observable.js";
|
|
4
|
+
import { reactive } from "./reactive.js";
|
|
5
|
+
const defaultStateOptions = {
|
|
6
|
+
deep: false,
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Creates a reactive state value.
|
|
10
|
+
* @param value - The initial state value.
|
|
11
|
+
* @param options - Options to customize the state or a friendly name.
|
|
12
|
+
* @returns A State instance.
|
|
13
|
+
* @beta
|
|
14
|
+
*/
|
|
15
|
+
export function state(value, options = defaultStateOptions) {
|
|
16
|
+
var _a;
|
|
17
|
+
if (isString(options)) {
|
|
18
|
+
options = { deep: false, name: options };
|
|
19
|
+
}
|
|
20
|
+
const host = reactive({ value }, options.deep);
|
|
21
|
+
const state = (() => host.value);
|
|
22
|
+
Object.defineProperty(state, "current", {
|
|
23
|
+
get: () => host.value,
|
|
24
|
+
set: (value) => (host.value = value),
|
|
25
|
+
});
|
|
26
|
+
Object.defineProperty(state, "name", {
|
|
27
|
+
value: (_a = options.name) !== null && _a !== void 0 ? _a : "SharedState",
|
|
28
|
+
});
|
|
29
|
+
state.set = (value) => (host.value = value);
|
|
30
|
+
state.asReadonly = () => {
|
|
31
|
+
const readonlyState = (() => host.value);
|
|
32
|
+
Object.defineProperty(readonlyState, "current", {
|
|
33
|
+
get: () => host.value,
|
|
34
|
+
});
|
|
35
|
+
Object.defineProperty(readonlyState, "name", {
|
|
36
|
+
value: `${state.name} (Readonly)`,
|
|
37
|
+
});
|
|
38
|
+
return Object.freeze(readonlyState);
|
|
39
|
+
};
|
|
40
|
+
return state;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Creates a reactive state that has its value associated with a specific owner.
|
|
44
|
+
* @param value - The initial value or a factory that provides an initial value for each owner.
|
|
45
|
+
* @param options - Options to customize the state or a friendly name.
|
|
46
|
+
* @returns An OwnedState instance.
|
|
47
|
+
* @beta
|
|
48
|
+
*/
|
|
49
|
+
export function ownedState(value, options = defaultStateOptions) {
|
|
50
|
+
var _a;
|
|
51
|
+
if (isString(options)) {
|
|
52
|
+
options = { deep: false, name: options };
|
|
53
|
+
}
|
|
54
|
+
if (!isFunction(value)) {
|
|
55
|
+
const v = value;
|
|
56
|
+
value = () => v;
|
|
57
|
+
}
|
|
58
|
+
const storage = new WeakMap();
|
|
59
|
+
const getHost = (owner) => {
|
|
60
|
+
let host = storage.get(owner);
|
|
61
|
+
if (host === void 0) {
|
|
62
|
+
host = reactive({ value: value() }, options.deep);
|
|
63
|
+
storage.set(owner, host);
|
|
64
|
+
}
|
|
65
|
+
return host;
|
|
66
|
+
};
|
|
67
|
+
const state = ((owner) => getHost(owner).value);
|
|
68
|
+
Object.defineProperty(state, "name", {
|
|
69
|
+
value: (_a = options.name) !== null && _a !== void 0 ? _a : "OwnedState",
|
|
70
|
+
});
|
|
71
|
+
state.set = (owner, value) => (getHost(owner).value = value);
|
|
72
|
+
state.asReadonly = () => {
|
|
73
|
+
const readonlyState = ((owner) => getHost(owner).value);
|
|
74
|
+
Object.defineProperty(readonlyState, "name", {
|
|
75
|
+
value: `${state.name} (Readonly)`,
|
|
76
|
+
});
|
|
77
|
+
return Object.freeze(readonlyState);
|
|
78
|
+
};
|
|
79
|
+
return state;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Creates a ComputedState.
|
|
83
|
+
* @param initialize - The initialization callback.
|
|
84
|
+
* @param name - A friendly name for this computation.
|
|
85
|
+
* @returns A ComputedState
|
|
86
|
+
* @beta
|
|
87
|
+
*/
|
|
88
|
+
export function computedState(initialize, name = "ComputedState") {
|
|
89
|
+
let setupCallback = null;
|
|
90
|
+
const builder = {
|
|
91
|
+
on: {
|
|
92
|
+
setup(callback) {
|
|
93
|
+
setupCallback = callback;
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
const computer = initialize(builder);
|
|
98
|
+
const host = reactive({ value: null }, false);
|
|
99
|
+
const output = (() => host.value);
|
|
100
|
+
Object.defineProperty(output, "current", {
|
|
101
|
+
get: () => host.value,
|
|
102
|
+
});
|
|
103
|
+
Object.defineProperty(output, "name", {
|
|
104
|
+
value: name,
|
|
105
|
+
});
|
|
106
|
+
// eslint-disable-next-line prefer-const
|
|
107
|
+
let computedNotifier;
|
|
108
|
+
const computedSubscriber = {
|
|
109
|
+
handleChange() {
|
|
110
|
+
host.value = computedNotifier.observe(null);
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
computedNotifier = Observable.binding(computer, computedSubscriber);
|
|
114
|
+
computedNotifier.setMode(false);
|
|
115
|
+
let cleanup;
|
|
116
|
+
let setupNotifier;
|
|
117
|
+
if (setupCallback) {
|
|
118
|
+
const setupSubscriber = {
|
|
119
|
+
handleChange() {
|
|
120
|
+
if (cleanup) {
|
|
121
|
+
cleanup();
|
|
122
|
+
}
|
|
123
|
+
cleanup = setupNotifier.observe(null);
|
|
124
|
+
host.value = computer();
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
setupNotifier = Observable.binding(setupCallback, setupSubscriber);
|
|
128
|
+
setupNotifier.setMode(false);
|
|
129
|
+
cleanup = setupNotifier.observe(null);
|
|
130
|
+
}
|
|
131
|
+
host.value = computedNotifier.observe(null);
|
|
132
|
+
output.dispose = () => {
|
|
133
|
+
if (cleanup) {
|
|
134
|
+
cleanup();
|
|
135
|
+
}
|
|
136
|
+
if (setupNotifier) {
|
|
137
|
+
setupNotifier.dispose();
|
|
138
|
+
}
|
|
139
|
+
computedNotifier.dispose();
|
|
140
|
+
};
|
|
141
|
+
output.subscribe = (subscriber) => {
|
|
142
|
+
computedNotifier.subscribe(subscriber);
|
|
143
|
+
};
|
|
144
|
+
output.unsubscribe = (subscriber) => {
|
|
145
|
+
computedNotifier.unsubscribe(subscriber);
|
|
146
|
+
};
|
|
147
|
+
return output;
|
|
148
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
function shouldTraverse(value, traversed) {
|
|
2
|
+
return (value !== null &&
|
|
3
|
+
value !== void 0 &&
|
|
4
|
+
typeof value === "object" &&
|
|
5
|
+
!traversed.has(value));
|
|
6
|
+
}
|
|
7
|
+
export function visitObject(object, deep, visitor, data, traversed) {
|
|
8
|
+
if (!shouldTraverse(object, traversed)) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
traversed.add(object);
|
|
12
|
+
if (Array.isArray(object)) {
|
|
13
|
+
visitor.visitArray(object, data);
|
|
14
|
+
for (const item of object) {
|
|
15
|
+
visitObject(item, deep, visitor, data, traversed);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
visitor.visitObject(object, data);
|
|
20
|
+
for (const key in object) {
|
|
21
|
+
const value = object[key];
|
|
22
|
+
visitor.visitProperty(object, key, value, data);
|
|
23
|
+
if (deep) {
|
|
24
|
+
visitObject(value, deep, visitor, data, traversed);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { isFunction, noop } from "../interfaces.js";
|
|
2
|
+
import { ArrayObserver } from "../observation/arrays.js";
|
|
3
|
+
import { Observable } from "../observation/observable.js";
|
|
4
|
+
import { visitObject } from "./visitor.js";
|
|
5
|
+
function watchObject(object, data) {
|
|
6
|
+
const notifier = Observable.getNotifier(object);
|
|
7
|
+
notifier.subscribe(data.subscriber);
|
|
8
|
+
data.notifiers.push(notifier);
|
|
9
|
+
}
|
|
10
|
+
const watchVisitor = {
|
|
11
|
+
visitProperty: noop,
|
|
12
|
+
visitObject: watchObject,
|
|
13
|
+
visitArray: watchObject,
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Deeply subscribes to changes in existing observable objects.
|
|
17
|
+
* @param object - The observable object to watch.
|
|
18
|
+
* @param subscriber - The handler to call when changes are made to the object.
|
|
19
|
+
* @returns A disposable that can be used to unsubscribe from change updates.
|
|
20
|
+
* @beta
|
|
21
|
+
*/
|
|
22
|
+
export function watch(object, subscriber) {
|
|
23
|
+
const data = {
|
|
24
|
+
notifiers: [],
|
|
25
|
+
subscriber: isFunction(subscriber) ? { handleChange: subscriber } : subscriber,
|
|
26
|
+
};
|
|
27
|
+
ArrayObserver.enable();
|
|
28
|
+
visitObject(object, true, watchVisitor, data, new Set());
|
|
29
|
+
return {
|
|
30
|
+
dispose() {
|
|
31
|
+
for (const n of data.notifiers) {
|
|
32
|
+
n.unsubscribe(data.subscriber);
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
@@ -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
|
-
createCSS() {
|
|
75
|
-
return this.css;
|
|
76
|
-
}
|
|
77
|
-
bind(el) {
|
|
67
|
+
createCSS(add) {
|
|
68
|
+
this.behaviors.forEach(add);
|
|
78
69
|
if (this.styles) {
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
if (this.behaviors.length) {
|
|
82
|
-
el.$fastController.addBehaviors(this.behaviors);
|
|
70
|
+
add(this);
|
|
83
71
|
}
|
|
72
|
+
return this.css;
|
|
84
73
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
el.$fastController.removeBehaviors(this.behaviors);
|
|
91
|
-
}
|
|
74
|
+
addedCallback(controller) {
|
|
75
|
+
controller.addStyles(this.styles);
|
|
76
|
+
}
|
|
77
|
+
removedCallback(controller) {
|
|
78
|
+
controller.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;
|