@microsoft/fast-element 2.0.0-beta.2 → 2.0.0-beta.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.json +488 -0
- package/CHANGELOG.md +180 -1
- package/dist/dts/components/attributes.d.ts +15 -0
- package/dist/dts/components/{controller.d.ts → element-controller.d.ts} +74 -28
- package/dist/dts/components/fast-definitions.d.ts +41 -9
- package/dist/dts/components/fast-element.d.ts +14 -26
- package/dist/dts/components/hydration.d.ts +14 -0
- package/dist/{esm/observation/behavior.js → dts/components/install-hydration.d.ts} +0 -0
- package/dist/dts/context.d.ts +1 -1
- package/dist/dts/di/di.d.ts +894 -0
- package/dist/dts/dom-policy.d.ts +68 -0
- package/dist/dts/dom.d.ts +100 -0
- package/dist/dts/index.d.ts +5 -4
- package/dist/dts/index.rollup.d.ts +0 -1
- package/dist/dts/index.rollup.debug.d.ts +0 -1
- package/dist/dts/interfaces.d.ts +60 -79
- package/dist/dts/observation/observable.d.ts +99 -54
- package/dist/dts/pending-task.d.ts +20 -0
- package/dist/dts/platform.d.ts +7 -0
- package/dist/dts/polyfills.d.ts +0 -8
- package/dist/dts/state/exports.d.ts +3 -0
- package/dist/dts/state/reactive.d.ts +8 -0
- package/dist/dts/state/state.d.ts +141 -0
- package/dist/dts/state/visitor.d.ts +6 -0
- package/dist/dts/state/watch.d.ts +10 -0
- package/dist/dts/styles/css-directive.d.ts +2 -2
- package/dist/dts/styles/css.d.ts +0 -5
- package/dist/dts/styles/element-styles.d.ts +10 -17
- package/dist/dts/styles/host.d.ts +68 -0
- package/dist/dts/styles/style-strategy.d.ts +42 -0
- package/dist/dts/templating/binding-signal.d.ts +12 -27
- package/dist/dts/templating/binding-two-way.d.ts +22 -37
- package/dist/dts/templating/binding.d.ts +76 -208
- package/dist/dts/templating/children.d.ts +1 -1
- package/dist/dts/templating/compiler.d.ts +11 -13
- package/dist/dts/templating/html-directive.d.ts +91 -97
- package/dist/dts/templating/node-observation.d.ts +15 -6
- package/dist/dts/templating/ref.d.ts +7 -11
- package/dist/dts/templating/render.d.ts +296 -0
- package/dist/dts/templating/repeat.d.ts +23 -34
- package/dist/dts/templating/slotted.d.ts +1 -1
- package/dist/dts/templating/template.d.ts +92 -14
- package/dist/dts/templating/view.d.ts +81 -11
- package/dist/dts/templating/when.d.ts +3 -3
- package/dist/dts/testing/exports.d.ts +3 -0
- package/dist/dts/testing/fakes.d.ts +14 -0
- package/dist/dts/testing/fixture.d.ts +84 -0
- package/dist/dts/testing/timeout.d.ts +7 -0
- package/dist/dts/utilities.d.ts +53 -18
- package/dist/esm/components/attributes.js +28 -5
- package/dist/esm/components/{controller.js → element-controller.js} +239 -137
- package/dist/esm/components/fast-definitions.js +38 -30
- package/dist/esm/components/fast-element.js +27 -16
- package/dist/esm/components/hydration.js +35 -0
- package/dist/esm/components/install-hydration.js +2 -0
- package/dist/esm/context.js +5 -1
- package/dist/esm/debug.js +40 -5
- package/dist/esm/di/di.js +1430 -0
- package/dist/esm/dom-policy.js +337 -0
- package/dist/esm/dom.js +101 -0
- package/dist/esm/index.js +4 -2
- package/dist/esm/index.rollup.debug.js +3 -1
- package/dist/esm/index.rollup.js +3 -1
- package/dist/esm/interfaces.js +52 -0
- package/dist/esm/observation/arrays.js +303 -2
- package/dist/esm/observation/observable.js +88 -142
- package/dist/esm/observation/update-queue.js +2 -2
- package/dist/esm/pending-task.js +16 -0
- package/dist/esm/platform.js +27 -2
- package/dist/esm/polyfills.js +3 -61
- package/dist/esm/state/exports.js +3 -0
- package/dist/esm/state/reactive.js +34 -0
- package/dist/esm/state/state.js +148 -0
- package/dist/esm/state/visitor.js +28 -0
- package/dist/esm/state/watch.js +36 -0
- package/dist/esm/styles/css.js +4 -9
- package/dist/esm/styles/element-styles.js +14 -33
- package/dist/esm/styles/host.js +1 -0
- package/dist/esm/styles/style-strategy.js +1 -0
- package/dist/esm/templating/binding-signal.js +67 -62
- package/dist/esm/templating/binding-two-way.js +72 -39
- package/dist/esm/templating/binding.js +142 -286
- package/dist/esm/templating/children.js +8 -4
- package/dist/esm/templating/compiler.js +59 -43
- package/dist/esm/templating/html-directive.js +56 -75
- package/dist/esm/templating/node-observation.js +20 -13
- package/dist/esm/templating/ref.js +4 -12
- package/dist/esm/templating/render.js +402 -0
- package/dist/esm/templating/repeat.js +88 -75
- package/dist/esm/templating/template.js +132 -60
- package/dist/esm/templating/view.js +113 -29
- package/dist/esm/templating/when.js +5 -4
- package/dist/esm/testing/exports.js +3 -0
- package/dist/esm/testing/fakes.js +107 -0
- package/dist/esm/testing/fixture.js +86 -0
- package/dist/esm/testing/timeout.js +24 -0
- package/dist/esm/utilities.js +95 -95
- package/dist/fast-element.api.json +9487 -8326
- package/dist/fast-element.d.ts +847 -644
- package/dist/fast-element.debug.js +1993 -1166
- package/dist/fast-element.debug.min.js +1 -1
- package/dist/fast-element.js +1903 -1111
- package/dist/fast-element.min.js +1 -1
- package/dist/fast-element.untrimmed.d.ts +911 -701
- package/docs/api-report.md +329 -252
- package/package.json +38 -16
- package/dist/dts/hooks.d.ts +0 -20
- package/dist/dts/observation/behavior.d.ts +0 -19
- package/dist/dts/observation/splice-strategies.d.ts +0 -13
- package/dist/dts/templating/dom.d.ts +0 -41
- package/dist/esm/hooks.js +0 -32
- package/dist/esm/observation/splice-strategies.js +0 -400
- package/dist/esm/templating/dom.js +0 -49
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@microsoft/fast-element",
|
|
3
3
|
"description": "A library for constructing Web Components",
|
|
4
|
-
"version": "2.0.0-beta.
|
|
4
|
+
"version": "2.0.0-beta.20",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Microsoft",
|
|
7
7
|
"url": "https://discord.gg/FcSNfg4"
|
|
@@ -26,18 +26,10 @@
|
|
|
26
26
|
"development": "./dist/esm/index.debug.js",
|
|
27
27
|
"default": "./dist/esm/index.js"
|
|
28
28
|
},
|
|
29
|
-
"./polyfills": {
|
|
30
|
-
"types": "./dist/dts/polyfills.d.ts",
|
|
31
|
-
"default": "./dist/esm/polyfills.js"
|
|
32
|
-
},
|
|
33
29
|
"./debug": {
|
|
34
30
|
"types": "./dist/dts/debug.d.ts",
|
|
35
31
|
"default": "./dist/esm/debug.js"
|
|
36
32
|
},
|
|
37
|
-
"./observation/splice-strategies": {
|
|
38
|
-
"types": "./dist/dts/observation/splice-strategies.d.ts",
|
|
39
|
-
"default": "./dist/esm/observation/splice-strategies.js"
|
|
40
|
-
},
|
|
41
33
|
"./binding/two-way": {
|
|
42
34
|
"types": "./dist/dts/templating/binding-two-way.d.ts",
|
|
43
35
|
"default": "./dist/esm/templating/binding-two-way.js"
|
|
@@ -46,13 +38,17 @@
|
|
|
46
38
|
"types": "./dist/dts/templating/binding-signal.d.ts",
|
|
47
39
|
"default": "./dist/esm/templating/binding-signal.js"
|
|
48
40
|
},
|
|
41
|
+
"./render": {
|
|
42
|
+
"types": "./dist/dts/templating/render.d.ts",
|
|
43
|
+
"default": "./dist/esm/templating/render.js"
|
|
44
|
+
},
|
|
49
45
|
"./utilities": {
|
|
50
46
|
"types": "./dist/dts/utilities.d.ts",
|
|
51
47
|
"default": "./dist/esm/utilities.js"
|
|
52
48
|
},
|
|
53
|
-
"./
|
|
54
|
-
"types": "./dist/dts/
|
|
55
|
-
"default": "./dist/esm/
|
|
49
|
+
"./state": {
|
|
50
|
+
"types": "./dist/dts/state/exports.d.ts",
|
|
51
|
+
"default": "./dist/esm/state/exports.js"
|
|
56
52
|
},
|
|
57
53
|
"./context": {
|
|
58
54
|
"types": "./dist/dts/context.d.ts",
|
|
@@ -61,12 +57,38 @@
|
|
|
61
57
|
"./metadata": {
|
|
62
58
|
"types": "./dist/dts/metadata.d.ts",
|
|
63
59
|
"default": "./dist/esm/metadata.js"
|
|
64
|
-
}
|
|
60
|
+
},
|
|
61
|
+
"./testing": {
|
|
62
|
+
"types": "./dist/dts/testing/exports.d.ts",
|
|
63
|
+
"default": "./dist/esm/testing/exports.js"
|
|
64
|
+
},
|
|
65
|
+
"./di": {
|
|
66
|
+
"types": "./dist/dts/di/di.d.ts",
|
|
67
|
+
"default": "./dist/esm/di/di.js"
|
|
68
|
+
},
|
|
69
|
+
"./element-hydration": {
|
|
70
|
+
"types": "./dist/dts/components/hydration.d.ts",
|
|
71
|
+
"default": "./dist/esm/components/hydration.js"
|
|
72
|
+
},
|
|
73
|
+
"./install-element-hydration": {
|
|
74
|
+
"types": "./dist/dts/components/install-hydration.d.ts",
|
|
75
|
+
"default": "./dist/esm/components/install-hydration.js"
|
|
76
|
+
},
|
|
77
|
+
"./pending-task": {
|
|
78
|
+
"types": "./dist/dts/pending-task.d.ts",
|
|
79
|
+
"default": "./dist/esm/pending-task.js"
|
|
80
|
+
},
|
|
81
|
+
"./dom-policy": {
|
|
82
|
+
"types": "./dist/dts/dom-policy.d.ts",
|
|
83
|
+
"default": "./dist/esm/dom-policy.js"
|
|
84
|
+
},
|
|
85
|
+
"./package.json": "./package.json"
|
|
65
86
|
},
|
|
66
87
|
"unpkg": "dist/fast-element.min.js",
|
|
67
88
|
"sideEffects": [
|
|
68
89
|
"./dist/esm/debug.js",
|
|
69
|
-
"./dist/esm/polyfills.js"
|
|
90
|
+
"./dist/esm/polyfills.js",
|
|
91
|
+
"./dist/esm/components/install-hydration.js"
|
|
70
92
|
],
|
|
71
93
|
"scripts": {
|
|
72
94
|
"clean:dist": "node ../../../build/clean.js dist",
|
|
@@ -98,7 +120,7 @@
|
|
|
98
120
|
"@microsoft/api-extractor": "7.24.2",
|
|
99
121
|
"@types/chai": "^4.2.11",
|
|
100
122
|
"@types/chai-spies": "^1.0.3",
|
|
101
|
-
"@types/karma": "^
|
|
123
|
+
"@types/karma": "^6.3.3",
|
|
102
124
|
"@types/mocha": "^7.0.2",
|
|
103
125
|
"@types/webpack-env": "^1.15.2",
|
|
104
126
|
"chai": "^4.2.0",
|
|
@@ -109,7 +131,7 @@
|
|
|
109
131
|
"istanbul-instrumenter-loader": "^3.0.1",
|
|
110
132
|
"jsdom": "^16.2.2",
|
|
111
133
|
"jsdom-global": "3.0.2",
|
|
112
|
-
"karma": "^
|
|
134
|
+
"karma": "^6.4.1",
|
|
113
135
|
"karma-chrome-launcher": "^3.1.0",
|
|
114
136
|
"karma-coverage": "^2.0.2",
|
|
115
137
|
"karma-coverage-istanbul-reporter": "^3.0.0",
|
package/dist/dts/hooks.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { BindingObserver } from "./observation/observable.js";
|
|
2
|
-
/**
|
|
3
|
-
* Functions used for getting and setting a stateful value.
|
|
4
|
-
* @beta
|
|
5
|
-
*/
|
|
6
|
-
export declare type State<T> = [() => T, (newValue: T) => T];
|
|
7
|
-
/**
|
|
8
|
-
* Creates an observable state value.
|
|
9
|
-
* @param value The initial state value.
|
|
10
|
-
* @param deep Whether or not to convert the state value to an observable.
|
|
11
|
-
* @returns The state accessor functions.
|
|
12
|
-
* @beta
|
|
13
|
-
*/
|
|
14
|
-
export declare function useState<T>(value: T, deep?: boolean): State<T>;
|
|
15
|
-
/**
|
|
16
|
-
* Executes an action once, and then whenever any of its dependent state changes.
|
|
17
|
-
* @param action An action that is affected by state changes.
|
|
18
|
-
* @returns A BindingObserver which can be used to dispose of the effect.
|
|
19
|
-
*/
|
|
20
|
-
export declare function useEffect(action: () => void): BindingObserver;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { ExecutionContext } from "./observable.js";
|
|
2
|
-
/**
|
|
3
|
-
* Represents an object that can contribute behavior to a view or
|
|
4
|
-
* element's bind/unbind operations.
|
|
5
|
-
* @public
|
|
6
|
-
*/
|
|
7
|
-
export interface Behavior<TSource = any, TParent = any> {
|
|
8
|
-
/**
|
|
9
|
-
* Bind this behavior to the source.
|
|
10
|
-
* @param source - The source to bind to.
|
|
11
|
-
* @param context - The execution context that the binding is operating within.
|
|
12
|
-
*/
|
|
13
|
-
bind(source: TSource, context: ExecutionContext<TParent>): void;
|
|
14
|
-
/**
|
|
15
|
-
* Unbinds this behavior from the source.
|
|
16
|
-
* @param source - The source to unbind from.
|
|
17
|
-
*/
|
|
18
|
-
unbind(source: TSource, context: ExecutionContext<TParent>): void;
|
|
19
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { SpliceStrategy } from "./arrays.js";
|
|
2
|
-
/**
|
|
3
|
-
* A SpliceStrategy that attempts to merge all splices into the minimal set of
|
|
4
|
-
* splices needed to represent the change from the old array to the new array.
|
|
5
|
-
* @public
|
|
6
|
-
*/
|
|
7
|
-
export declare const mergeSpliceStrategy: SpliceStrategy;
|
|
8
|
-
/**
|
|
9
|
-
* A splice strategy that doesn't create splices, but instead
|
|
10
|
-
* tracks every change as a full array reset.
|
|
11
|
-
* @public
|
|
12
|
-
*/
|
|
13
|
-
export declare const resetSpliceStrategy: SpliceStrategy;
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { Callable } from "../interfaces.js";
|
|
2
|
-
/**
|
|
3
|
-
* Common DOM APIs.
|
|
4
|
-
* @public
|
|
5
|
-
*/
|
|
6
|
-
export declare const DOM: Readonly<{
|
|
7
|
-
/**
|
|
8
|
-
* @deprecated
|
|
9
|
-
* Use Updates.enqueue().
|
|
10
|
-
*/
|
|
11
|
-
queueUpdate: (callable: Callable) => void;
|
|
12
|
-
/**
|
|
13
|
-
* @deprecated
|
|
14
|
-
* Use Updates.next()
|
|
15
|
-
*/
|
|
16
|
-
nextUpdate: () => Promise<void>;
|
|
17
|
-
/**
|
|
18
|
-
* @deprecated
|
|
19
|
-
* Use Updates.process()
|
|
20
|
-
*/
|
|
21
|
-
processUpdates: () => void;
|
|
22
|
-
/**
|
|
23
|
-
* Sets an attribute value on an element.
|
|
24
|
-
* @param element - The element to set the attribute value on.
|
|
25
|
-
* @param attributeName - The attribute name to set.
|
|
26
|
-
* @param value - The value of the attribute to set.
|
|
27
|
-
* @remarks
|
|
28
|
-
* If the value is `null` or `undefined`, the attribute is removed, otherwise
|
|
29
|
-
* it is set to the provided value using the standard `setAttribute` API.
|
|
30
|
-
*/
|
|
31
|
-
setAttribute(element: HTMLElement, attributeName: string, value: any): void;
|
|
32
|
-
/**
|
|
33
|
-
* Sets a boolean attribute value.
|
|
34
|
-
* @param element - The element to set the boolean attribute value on.
|
|
35
|
-
* @param attributeName - The attribute name to set.
|
|
36
|
-
* @param value - The value of the attribute to set.
|
|
37
|
-
* @remarks
|
|
38
|
-
* If the value is true, the attribute is added; otherwise it is removed.
|
|
39
|
-
*/
|
|
40
|
-
setBooleanAttribute(element: HTMLElement, attributeName: string, value: boolean): void;
|
|
41
|
-
}>;
|
package/dist/esm/hooks.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { Observable } from "./observation/observable.js";
|
|
2
|
-
import { makeObservable } from "./utilities.js";
|
|
3
|
-
/**
|
|
4
|
-
* Creates an observable state value.
|
|
5
|
-
* @param value The initial state value.
|
|
6
|
-
* @param deep Whether or not to convert the state value to an observable.
|
|
7
|
-
* @returns The state accessor functions.
|
|
8
|
-
* @beta
|
|
9
|
-
*/
|
|
10
|
-
export function useState(value, deep = false) {
|
|
11
|
-
const host = makeObservable({ value }, deep);
|
|
12
|
-
return [() => host.value, newValue => (host.value = newValue)];
|
|
13
|
-
}
|
|
14
|
-
const effectModel = Object.freeze({});
|
|
15
|
-
/**
|
|
16
|
-
* Executes an action once, and then whenever any of its dependent state changes.
|
|
17
|
-
* @param action An action that is affected by state changes.
|
|
18
|
-
* @returns A BindingObserver which can be used to dispose of the effect.
|
|
19
|
-
*/
|
|
20
|
-
export function useEffect(action) {
|
|
21
|
-
/* eslint prefer-const: 0 */
|
|
22
|
-
let observer;
|
|
23
|
-
const subscriber = {
|
|
24
|
-
handleChange() {
|
|
25
|
-
observer.observe(effectModel);
|
|
26
|
-
},
|
|
27
|
-
};
|
|
28
|
-
observer = Observable.binding(action, subscriber);
|
|
29
|
-
observer.setMode(false);
|
|
30
|
-
subscriber.handleChange();
|
|
31
|
-
return observer;
|
|
32
|
-
}
|
|
@@ -1,400 +0,0 @@
|
|
|
1
|
-
import { emptyArray } from "../platform.js";
|
|
2
|
-
import { Splice, SpliceStrategy, SpliceStrategySupport, } from "./arrays.js";
|
|
3
|
-
// Note: This function is *based* on the computation of the Levenshtein
|
|
4
|
-
// "edit" distance. The one change is that "updates" are treated as two
|
|
5
|
-
// edits - not one. With Array splices, an update is really a delete
|
|
6
|
-
// followed by an add. By retaining this, we optimize for "keeping" the
|
|
7
|
-
// maximum array items in the original array. For example:
|
|
8
|
-
//
|
|
9
|
-
// 'xxxx123' to '123yyyy'
|
|
10
|
-
//
|
|
11
|
-
// With 1-edit updates, the shortest path would be just to update all seven
|
|
12
|
-
// characters. With 2-edit updates, we delete 4, leave 3, and add 4. This
|
|
13
|
-
// leaves the substring '123' intact.
|
|
14
|
-
function calcEditDistances(current, currentStart, currentEnd, old, oldStart, oldEnd) {
|
|
15
|
-
// "Deletion" columns
|
|
16
|
-
const rowCount = oldEnd - oldStart + 1;
|
|
17
|
-
const columnCount = currentEnd - currentStart + 1;
|
|
18
|
-
const distances = new Array(rowCount);
|
|
19
|
-
let north;
|
|
20
|
-
let west;
|
|
21
|
-
// "Addition" rows. Initialize null column.
|
|
22
|
-
for (let i = 0; i < rowCount; ++i) {
|
|
23
|
-
distances[i] = new Array(columnCount);
|
|
24
|
-
distances[i][0] = i;
|
|
25
|
-
}
|
|
26
|
-
// Initialize null row
|
|
27
|
-
for (let j = 0; j < columnCount; ++j) {
|
|
28
|
-
distances[0][j] = j;
|
|
29
|
-
}
|
|
30
|
-
for (let i = 1; i < rowCount; ++i) {
|
|
31
|
-
for (let j = 1; j < columnCount; ++j) {
|
|
32
|
-
if (current[currentStart + j - 1] === old[oldStart + i - 1]) {
|
|
33
|
-
distances[i][j] = distances[i - 1][j - 1];
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
north = distances[i - 1][j] + 1;
|
|
37
|
-
west = distances[i][j - 1] + 1;
|
|
38
|
-
distances[i][j] = north < west ? north : west;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return distances;
|
|
43
|
-
}
|
|
44
|
-
// This starts at the final weight, and walks "backward" by finding
|
|
45
|
-
// the minimum previous weight recursively until the origin of the weight
|
|
46
|
-
// matrix.
|
|
47
|
-
function spliceOperationsFromEditDistances(distances) {
|
|
48
|
-
let i = distances.length - 1;
|
|
49
|
-
let j = distances[0].length - 1;
|
|
50
|
-
let current = distances[i][j];
|
|
51
|
-
const edits = [];
|
|
52
|
-
while (i > 0 || j > 0) {
|
|
53
|
-
if (i === 0) {
|
|
54
|
-
edits.push(2 /* Edit.add */);
|
|
55
|
-
j--;
|
|
56
|
-
continue;
|
|
57
|
-
}
|
|
58
|
-
if (j === 0) {
|
|
59
|
-
edits.push(3 /* Edit.delete */);
|
|
60
|
-
i--;
|
|
61
|
-
continue;
|
|
62
|
-
}
|
|
63
|
-
const northWest = distances[i - 1][j - 1];
|
|
64
|
-
const west = distances[i - 1][j];
|
|
65
|
-
const north = distances[i][j - 1];
|
|
66
|
-
let min;
|
|
67
|
-
if (west < north) {
|
|
68
|
-
min = west < northWest ? west : northWest;
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
min = north < northWest ? north : northWest;
|
|
72
|
-
}
|
|
73
|
-
if (min === northWest) {
|
|
74
|
-
if (northWest === current) {
|
|
75
|
-
edits.push(0 /* Edit.leave */);
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
edits.push(1 /* Edit.update */);
|
|
79
|
-
current = northWest;
|
|
80
|
-
}
|
|
81
|
-
i--;
|
|
82
|
-
j--;
|
|
83
|
-
}
|
|
84
|
-
else if (min === west) {
|
|
85
|
-
edits.push(3 /* Edit.delete */);
|
|
86
|
-
i--;
|
|
87
|
-
current = west;
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
edits.push(2 /* Edit.add */);
|
|
91
|
-
j--;
|
|
92
|
-
current = north;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
return edits.reverse();
|
|
96
|
-
}
|
|
97
|
-
function sharedPrefix(current, old, searchLength) {
|
|
98
|
-
for (let i = 0; i < searchLength; ++i) {
|
|
99
|
-
if (current[i] !== old[i]) {
|
|
100
|
-
return i;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
return searchLength;
|
|
104
|
-
}
|
|
105
|
-
function sharedSuffix(current, old, searchLength) {
|
|
106
|
-
let index1 = current.length;
|
|
107
|
-
let index2 = old.length;
|
|
108
|
-
let count = 0;
|
|
109
|
-
while (count < searchLength && current[--index1] === old[--index2]) {
|
|
110
|
-
count++;
|
|
111
|
-
}
|
|
112
|
-
return count;
|
|
113
|
-
}
|
|
114
|
-
function intersect(start1, end1, start2, end2) {
|
|
115
|
-
// Disjoint
|
|
116
|
-
if (end1 < start2 || end2 < start1) {
|
|
117
|
-
return -1;
|
|
118
|
-
}
|
|
119
|
-
// Adjacent
|
|
120
|
-
if (end1 === start2 || end2 === start1) {
|
|
121
|
-
return 0;
|
|
122
|
-
}
|
|
123
|
-
// Non-zero intersect, span1 first
|
|
124
|
-
if (start1 < start2) {
|
|
125
|
-
if (end1 < end2) {
|
|
126
|
-
return end1 - start2; // Overlap
|
|
127
|
-
}
|
|
128
|
-
return end2 - start2; // Contained
|
|
129
|
-
}
|
|
130
|
-
// Non-zero intersect, span2 first
|
|
131
|
-
if (end2 < end1) {
|
|
132
|
-
return end2 - start1; // Overlap
|
|
133
|
-
}
|
|
134
|
-
return end1 - start1; // Contained
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* @remarks
|
|
138
|
-
* Lacking individual splice mutation information, the minimal set of
|
|
139
|
-
* splices can be synthesized given the previous state and final state of an
|
|
140
|
-
* array. The basic approach is to calculate the edit distance matrix and
|
|
141
|
-
* choose the shortest path through it.
|
|
142
|
-
*
|
|
143
|
-
* Complexity: O(l * p)
|
|
144
|
-
* l: The length of the current array
|
|
145
|
-
* p: The length of the old array
|
|
146
|
-
*/
|
|
147
|
-
function calc(current, currentStart, currentEnd, old, oldStart, oldEnd) {
|
|
148
|
-
let prefixCount = 0;
|
|
149
|
-
let suffixCount = 0;
|
|
150
|
-
const minLength = Math.min(currentEnd - currentStart, oldEnd - oldStart);
|
|
151
|
-
if (currentStart === 0 && oldStart === 0) {
|
|
152
|
-
prefixCount = sharedPrefix(current, old, minLength);
|
|
153
|
-
}
|
|
154
|
-
if (currentEnd === current.length && oldEnd === old.length) {
|
|
155
|
-
suffixCount = sharedSuffix(current, old, minLength - prefixCount);
|
|
156
|
-
}
|
|
157
|
-
currentStart += prefixCount;
|
|
158
|
-
oldStart += prefixCount;
|
|
159
|
-
currentEnd -= suffixCount;
|
|
160
|
-
oldEnd -= suffixCount;
|
|
161
|
-
if (currentEnd - currentStart === 0 && oldEnd - oldStart === 0) {
|
|
162
|
-
return emptyArray;
|
|
163
|
-
}
|
|
164
|
-
if (currentStart === currentEnd) {
|
|
165
|
-
const splice = new Splice(currentStart, [], 0);
|
|
166
|
-
while (oldStart < oldEnd) {
|
|
167
|
-
splice.removed.push(old[oldStart++]);
|
|
168
|
-
}
|
|
169
|
-
return [splice];
|
|
170
|
-
}
|
|
171
|
-
else if (oldStart === oldEnd) {
|
|
172
|
-
return [new Splice(currentStart, [], currentEnd - currentStart)];
|
|
173
|
-
}
|
|
174
|
-
const ops = spliceOperationsFromEditDistances(calcEditDistances(current, currentStart, currentEnd, old, oldStart, oldEnd));
|
|
175
|
-
const splices = [];
|
|
176
|
-
let splice = void 0;
|
|
177
|
-
let index = currentStart;
|
|
178
|
-
let oldIndex = oldStart;
|
|
179
|
-
for (let i = 0; i < ops.length; ++i) {
|
|
180
|
-
switch (ops[i]) {
|
|
181
|
-
case 0 /* Edit.leave */:
|
|
182
|
-
if (splice !== void 0) {
|
|
183
|
-
splices.push(splice);
|
|
184
|
-
splice = void 0;
|
|
185
|
-
}
|
|
186
|
-
index++;
|
|
187
|
-
oldIndex++;
|
|
188
|
-
break;
|
|
189
|
-
case 1 /* Edit.update */:
|
|
190
|
-
if (splice === void 0) {
|
|
191
|
-
splice = new Splice(index, [], 0);
|
|
192
|
-
}
|
|
193
|
-
splice.addedCount++;
|
|
194
|
-
index++;
|
|
195
|
-
splice.removed.push(old[oldIndex]);
|
|
196
|
-
oldIndex++;
|
|
197
|
-
break;
|
|
198
|
-
case 2 /* Edit.add */:
|
|
199
|
-
if (splice === void 0) {
|
|
200
|
-
splice = new Splice(index, [], 0);
|
|
201
|
-
}
|
|
202
|
-
splice.addedCount++;
|
|
203
|
-
index++;
|
|
204
|
-
break;
|
|
205
|
-
case 3 /* Edit.delete */:
|
|
206
|
-
if (splice === void 0) {
|
|
207
|
-
splice = new Splice(index, [], 0);
|
|
208
|
-
}
|
|
209
|
-
splice.removed.push(old[oldIndex]);
|
|
210
|
-
oldIndex++;
|
|
211
|
-
break;
|
|
212
|
-
// no default
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
if (splice !== void 0) {
|
|
216
|
-
splices.push(splice);
|
|
217
|
-
}
|
|
218
|
-
return splices;
|
|
219
|
-
}
|
|
220
|
-
function merge(splice, splices) {
|
|
221
|
-
let inserted = false;
|
|
222
|
-
let insertionOffset = 0;
|
|
223
|
-
for (let i = 0; i < splices.length; i++) {
|
|
224
|
-
const current = splices[i];
|
|
225
|
-
current.index += insertionOffset;
|
|
226
|
-
if (inserted) {
|
|
227
|
-
continue;
|
|
228
|
-
}
|
|
229
|
-
const intersectCount = intersect(splice.index, splice.index + splice.removed.length, current.index, current.index + current.addedCount);
|
|
230
|
-
if (intersectCount >= 0) {
|
|
231
|
-
// Merge the two splices
|
|
232
|
-
splices.splice(i, 1);
|
|
233
|
-
i--;
|
|
234
|
-
insertionOffset -= current.addedCount - current.removed.length;
|
|
235
|
-
splice.addedCount += current.addedCount - intersectCount;
|
|
236
|
-
const deleteCount = splice.removed.length + current.removed.length - intersectCount;
|
|
237
|
-
if (!splice.addedCount && !deleteCount) {
|
|
238
|
-
// merged splice is a noop. discard.
|
|
239
|
-
inserted = true;
|
|
240
|
-
}
|
|
241
|
-
else {
|
|
242
|
-
let currentRemoved = current.removed;
|
|
243
|
-
if (splice.index < current.index) {
|
|
244
|
-
// some prefix of splice.removed is prepended to current.removed.
|
|
245
|
-
const prepend = splice.removed.slice(0, current.index - splice.index);
|
|
246
|
-
prepend.push(...currentRemoved);
|
|
247
|
-
currentRemoved = prepend;
|
|
248
|
-
}
|
|
249
|
-
if (splice.index + splice.removed.length >
|
|
250
|
-
current.index + current.addedCount) {
|
|
251
|
-
// some suffix of splice.removed is appended to current.removed.
|
|
252
|
-
const append = splice.removed.slice(current.index + current.addedCount - splice.index);
|
|
253
|
-
currentRemoved.push(...append);
|
|
254
|
-
}
|
|
255
|
-
splice.removed = currentRemoved;
|
|
256
|
-
if (current.index < splice.index) {
|
|
257
|
-
splice.index = current.index;
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
else if (splice.index < current.index) {
|
|
262
|
-
// Insert splice here.
|
|
263
|
-
inserted = true;
|
|
264
|
-
splices.splice(i, 0, splice);
|
|
265
|
-
i++;
|
|
266
|
-
const offset = splice.addedCount - splice.removed.length;
|
|
267
|
-
current.index += offset;
|
|
268
|
-
insertionOffset += offset;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
if (!inserted) {
|
|
272
|
-
splices.push(splice);
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
function project(array, changes) {
|
|
276
|
-
let splices = [];
|
|
277
|
-
const initialSplices = [];
|
|
278
|
-
for (let i = 0, ii = changes.length; i < ii; i++) {
|
|
279
|
-
merge(changes[i], initialSplices);
|
|
280
|
-
}
|
|
281
|
-
for (let i = 0, ii = initialSplices.length; i < ii; ++i) {
|
|
282
|
-
const splice = initialSplices[i];
|
|
283
|
-
if (splice.addedCount === 1 && splice.removed.length === 1) {
|
|
284
|
-
if (splice.removed[0] !== array[splice.index]) {
|
|
285
|
-
splices.push(splice);
|
|
286
|
-
}
|
|
287
|
-
continue;
|
|
288
|
-
}
|
|
289
|
-
splices = splices.concat(calc(array, splice.index, splice.index + splice.addedCount, splice.removed, 0, splice.removed.length));
|
|
290
|
-
}
|
|
291
|
-
return splices;
|
|
292
|
-
}
|
|
293
|
-
/**
|
|
294
|
-
* A SpliceStrategy that attempts to merge all splices into the minimal set of
|
|
295
|
-
* splices needed to represent the change from the old array to the new array.
|
|
296
|
-
* @public
|
|
297
|
-
*/
|
|
298
|
-
export const mergeSpliceStrategy = Object.freeze({
|
|
299
|
-
support: SpliceStrategySupport.optimized,
|
|
300
|
-
normalize(previous, current, changes) {
|
|
301
|
-
if (previous === void 0) {
|
|
302
|
-
if (changes === void 0) {
|
|
303
|
-
return emptyArray;
|
|
304
|
-
}
|
|
305
|
-
return changes.length > 1 ? project(current, changes) : changes;
|
|
306
|
-
}
|
|
307
|
-
return calc(current, 0, current.length, previous, 0, previous.length);
|
|
308
|
-
},
|
|
309
|
-
pop(array, observer, pop, args) {
|
|
310
|
-
const notEmpty = array.length > 0;
|
|
311
|
-
const result = pop.apply(array, args);
|
|
312
|
-
if (notEmpty) {
|
|
313
|
-
observer.addSplice(new Splice(array.length, [result], 0));
|
|
314
|
-
}
|
|
315
|
-
return result;
|
|
316
|
-
},
|
|
317
|
-
push(array, observer, push, args) {
|
|
318
|
-
const result = push.apply(array, args);
|
|
319
|
-
observer.addSplice(new Splice(array.length - args.length, [], args.length).adjustTo(array));
|
|
320
|
-
return result;
|
|
321
|
-
},
|
|
322
|
-
reverse(array, observer, reverse, args) {
|
|
323
|
-
observer.flush();
|
|
324
|
-
const oldArray = array.slice();
|
|
325
|
-
const result = reverse.apply(array, args);
|
|
326
|
-
observer.reset(oldArray);
|
|
327
|
-
return result;
|
|
328
|
-
},
|
|
329
|
-
shift(array, observer, shift, args) {
|
|
330
|
-
const notEmpty = array.length > 0;
|
|
331
|
-
const result = shift.apply(array, args);
|
|
332
|
-
if (notEmpty) {
|
|
333
|
-
observer.addSplice(new Splice(0, [result], 0));
|
|
334
|
-
}
|
|
335
|
-
return result;
|
|
336
|
-
},
|
|
337
|
-
sort(array, observer, sort, args) {
|
|
338
|
-
observer.flush();
|
|
339
|
-
const oldArray = array.slice();
|
|
340
|
-
const result = sort.apply(array, args);
|
|
341
|
-
observer.reset(oldArray);
|
|
342
|
-
return result;
|
|
343
|
-
},
|
|
344
|
-
splice(array, observer, splice, args) {
|
|
345
|
-
const result = splice.apply(array, args);
|
|
346
|
-
observer.addSplice(new Splice(+args[0], result, args.length > 2 ? args.length - 2 : 0).adjustTo(array));
|
|
347
|
-
return result;
|
|
348
|
-
},
|
|
349
|
-
unshift(array, observer, unshift, args) {
|
|
350
|
-
const result = unshift.apply(array, args);
|
|
351
|
-
observer.addSplice(new Splice(0, [], args.length).adjustTo(array));
|
|
352
|
-
return result;
|
|
353
|
-
},
|
|
354
|
-
});
|
|
355
|
-
/**
|
|
356
|
-
* A splice strategy that doesn't create splices, but instead
|
|
357
|
-
* tracks every change as a full array reset.
|
|
358
|
-
* @public
|
|
359
|
-
*/
|
|
360
|
-
export const resetSpliceStrategy = Object.freeze({
|
|
361
|
-
support: SpliceStrategySupport.reset,
|
|
362
|
-
normalize(previous, current, changes) {
|
|
363
|
-
return SpliceStrategy.reset;
|
|
364
|
-
},
|
|
365
|
-
pop(array, observer, pop, args) {
|
|
366
|
-
const result = pop.apply(array, args);
|
|
367
|
-
observer.reset(array);
|
|
368
|
-
return result;
|
|
369
|
-
},
|
|
370
|
-
push(array, observer, push, args) {
|
|
371
|
-
const result = push.apply(array, args);
|
|
372
|
-
observer.reset(array);
|
|
373
|
-
return result;
|
|
374
|
-
},
|
|
375
|
-
reverse(array, observer, reverse, args) {
|
|
376
|
-
const result = reverse.apply(array, args);
|
|
377
|
-
observer.reset(array);
|
|
378
|
-
return result;
|
|
379
|
-
},
|
|
380
|
-
shift(array, observer, shift, args) {
|
|
381
|
-
const result = shift.apply(array, args);
|
|
382
|
-
observer.reset(array);
|
|
383
|
-
return result;
|
|
384
|
-
},
|
|
385
|
-
sort(array, observer, sort, args) {
|
|
386
|
-
const result = sort.apply(array, args);
|
|
387
|
-
observer.reset(array);
|
|
388
|
-
return result;
|
|
389
|
-
},
|
|
390
|
-
splice(array, observer, splice, args) {
|
|
391
|
-
const result = splice.apply(array, args);
|
|
392
|
-
observer.reset(array);
|
|
393
|
-
return result;
|
|
394
|
-
},
|
|
395
|
-
unshift(array, observer, unshift, args) {
|
|
396
|
-
const result = unshift.apply(array, args);
|
|
397
|
-
observer.reset(array);
|
|
398
|
-
return result;
|
|
399
|
-
},
|
|
400
|
-
});
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { Updates } from "../observation/update-queue.js";
|
|
2
|
-
/**
|
|
3
|
-
* Common DOM APIs.
|
|
4
|
-
* @public
|
|
5
|
-
*/
|
|
6
|
-
export const DOM = Object.freeze({
|
|
7
|
-
/**
|
|
8
|
-
* @deprecated
|
|
9
|
-
* Use Updates.enqueue().
|
|
10
|
-
*/
|
|
11
|
-
queueUpdate: Updates.enqueue,
|
|
12
|
-
/**
|
|
13
|
-
* @deprecated
|
|
14
|
-
* Use Updates.next()
|
|
15
|
-
*/
|
|
16
|
-
nextUpdate: Updates.next,
|
|
17
|
-
/**
|
|
18
|
-
* @deprecated
|
|
19
|
-
* Use Updates.process()
|
|
20
|
-
*/
|
|
21
|
-
processUpdates: Updates.process,
|
|
22
|
-
/**
|
|
23
|
-
* Sets an attribute value on an element.
|
|
24
|
-
* @param element - The element to set the attribute value on.
|
|
25
|
-
* @param attributeName - The attribute name to set.
|
|
26
|
-
* @param value - The value of the attribute to set.
|
|
27
|
-
* @remarks
|
|
28
|
-
* If the value is `null` or `undefined`, the attribute is removed, otherwise
|
|
29
|
-
* it is set to the provided value using the standard `setAttribute` API.
|
|
30
|
-
*/
|
|
31
|
-
setAttribute(element, attributeName, value) {
|
|
32
|
-
value === null || value === undefined
|
|
33
|
-
? element.removeAttribute(attributeName)
|
|
34
|
-
: element.setAttribute(attributeName, value);
|
|
35
|
-
},
|
|
36
|
-
/**
|
|
37
|
-
* Sets a boolean attribute value.
|
|
38
|
-
* @param element - The element to set the boolean attribute value on.
|
|
39
|
-
* @param attributeName - The attribute name to set.
|
|
40
|
-
* @param value - The value of the attribute to set.
|
|
41
|
-
* @remarks
|
|
42
|
-
* If the value is true, the attribute is added; otherwise it is removed.
|
|
43
|
-
*/
|
|
44
|
-
setBooleanAttribute(element, attributeName, value) {
|
|
45
|
-
value
|
|
46
|
-
? element.setAttribute(attributeName, "")
|
|
47
|
-
: element.removeAttribute(attributeName);
|
|
48
|
-
},
|
|
49
|
-
});
|