@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
|
@@ -1,21 +1,24 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "../interfaces.js";
|
|
2
2
|
import { PropertyChangeNotifier } from "../observation/notifier.js";
|
|
3
|
-
import {
|
|
3
|
+
import { Observable, SourceLifetime } from "../observation/observable.js";
|
|
4
|
+
import { FAST } from "../platform.js";
|
|
4
5
|
import { FASTElementDefinition } from "./fast-definitions.js";
|
|
5
|
-
const shadowRoots = new WeakMap();
|
|
6
6
|
const defaultEventOptions = {
|
|
7
7
|
bubbles: true,
|
|
8
8
|
composed: true,
|
|
9
9
|
cancelable: true,
|
|
10
10
|
};
|
|
11
|
+
const isConnectedPropertyName = "isConnected";
|
|
12
|
+
const shadowRoots = new WeakMap();
|
|
11
13
|
function getShadowRoot(element) {
|
|
12
|
-
|
|
14
|
+
var _a, _b;
|
|
15
|
+
return (_b = (_a = element.shadowRoot) !== null && _a !== void 0 ? _a : shadowRoots.get(element)) !== null && _b !== void 0 ? _b : null;
|
|
13
16
|
}
|
|
14
17
|
/**
|
|
15
18
|
* Controls the lifecycle and rendering of a `FASTElement`.
|
|
16
19
|
* @public
|
|
17
20
|
*/
|
|
18
|
-
export class
|
|
21
|
+
export class ElementController extends PropertyChangeNotifier {
|
|
19
22
|
/**
|
|
20
23
|
* Creates a Controller to control the specified element.
|
|
21
24
|
* @param element - The element to be controlled by this controller.
|
|
@@ -26,11 +29,12 @@ export class Controller extends PropertyChangeNotifier {
|
|
|
26
29
|
constructor(element, definition) {
|
|
27
30
|
super(element);
|
|
28
31
|
this.boundObservables = null;
|
|
29
|
-
this.behaviors = null;
|
|
30
32
|
this.needsInitialization = true;
|
|
33
|
+
this.hasExistingShadowRoot = false;
|
|
31
34
|
this._template = null;
|
|
32
|
-
this._styles = null;
|
|
33
35
|
this._isConnected = false;
|
|
36
|
+
this.behaviors = null;
|
|
37
|
+
this._mainStyles = null;
|
|
34
38
|
/**
|
|
35
39
|
* This allows Observable.getNotifier(...) to return the Controller
|
|
36
40
|
* when the notifier for the Controller itself is being requested. The
|
|
@@ -46,13 +50,19 @@ export class Controller extends PropertyChangeNotifier {
|
|
|
46
50
|
* If `null` then the element is managing its own rendering.
|
|
47
51
|
*/
|
|
48
52
|
this.view = null;
|
|
49
|
-
this.
|
|
53
|
+
this.source = element;
|
|
50
54
|
this.definition = definition;
|
|
51
55
|
const shadowOptions = definition.shadowOptions;
|
|
52
56
|
if (shadowOptions !== void 0) {
|
|
53
|
-
|
|
54
|
-
if (
|
|
55
|
-
|
|
57
|
+
let shadowRoot = element.shadowRoot;
|
|
58
|
+
if (shadowRoot) {
|
|
59
|
+
this.hasExistingShadowRoot = true;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
shadowRoot = element.attachShadow(shadowOptions);
|
|
63
|
+
if (shadowOptions.mode === "closed") {
|
|
64
|
+
shadowRoots.set(element, shadowRoot);
|
|
65
|
+
}
|
|
56
66
|
}
|
|
57
67
|
}
|
|
58
68
|
// Capture any observable values that were set by the binding engine before
|
|
@@ -77,12 +87,12 @@ export class Controller extends PropertyChangeNotifier {
|
|
|
77
87
|
* connected to the document.
|
|
78
88
|
*/
|
|
79
89
|
get isConnected() {
|
|
80
|
-
Observable.track(this,
|
|
90
|
+
Observable.track(this, isConnectedPropertyName);
|
|
81
91
|
return this._isConnected;
|
|
82
92
|
}
|
|
83
93
|
setIsConnected(value) {
|
|
84
94
|
this._isConnected = value;
|
|
85
|
-
Observable.notify(this,
|
|
95
|
+
Observable.notify(this, isConnectedPropertyName);
|
|
86
96
|
}
|
|
87
97
|
/**
|
|
88
98
|
* Gets/sets the template used to render the component.
|
|
@@ -90,6 +100,19 @@ export class Controller extends PropertyChangeNotifier {
|
|
|
90
100
|
* This value can only be accurately read after connect but can be set at any time.
|
|
91
101
|
*/
|
|
92
102
|
get template() {
|
|
103
|
+
var _a;
|
|
104
|
+
// 1. Template overrides take top precedence.
|
|
105
|
+
if (this._template === null) {
|
|
106
|
+
const definition = this.definition;
|
|
107
|
+
if (this.source.resolveTemplate) {
|
|
108
|
+
// 2. Allow for element instance overrides next.
|
|
109
|
+
this._template = this.source.resolveTemplate();
|
|
110
|
+
}
|
|
111
|
+
else if (definition.template) {
|
|
112
|
+
// 3. Default to the static definition.
|
|
113
|
+
this._template = (_a = definition.template) !== null && _a !== void 0 ? _a : null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
93
116
|
return this._template;
|
|
94
117
|
}
|
|
95
118
|
set template(value) {
|
|
@@ -102,40 +125,102 @@ export class Controller extends PropertyChangeNotifier {
|
|
|
102
125
|
}
|
|
103
126
|
}
|
|
104
127
|
/**
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
* This value can only be accurately read after connect but can be set at any time.
|
|
128
|
+
* The main set of styles used for the component, independent
|
|
129
|
+
* of any dynamically added styles.
|
|
108
130
|
*/
|
|
109
|
-
get
|
|
110
|
-
|
|
131
|
+
get mainStyles() {
|
|
132
|
+
var _a;
|
|
133
|
+
// 1. Styles overrides take top precedence.
|
|
134
|
+
if (this._mainStyles === null) {
|
|
135
|
+
const definition = this.definition;
|
|
136
|
+
if (this.source.resolveStyles) {
|
|
137
|
+
// 2. Allow for element instance overrides next.
|
|
138
|
+
this._mainStyles = this.source.resolveStyles();
|
|
139
|
+
}
|
|
140
|
+
else if (definition.styles) {
|
|
141
|
+
// 3. Default to the static definition.
|
|
142
|
+
this._mainStyles = (_a = definition.styles) !== null && _a !== void 0 ? _a : null;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return this._mainStyles;
|
|
111
146
|
}
|
|
112
|
-
set
|
|
113
|
-
if (this.
|
|
147
|
+
set mainStyles(value) {
|
|
148
|
+
if (this._mainStyles === value) {
|
|
114
149
|
return;
|
|
115
150
|
}
|
|
116
|
-
if (this.
|
|
117
|
-
this.removeStyles(this.
|
|
151
|
+
if (this._mainStyles !== null) {
|
|
152
|
+
this.removeStyles(this._mainStyles);
|
|
118
153
|
}
|
|
119
|
-
this.
|
|
120
|
-
if (!this.needsInitialization
|
|
154
|
+
this._mainStyles = value;
|
|
155
|
+
if (!this.needsInitialization) {
|
|
121
156
|
this.addStyles(value);
|
|
122
157
|
}
|
|
123
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* Adds the behavior to the component.
|
|
161
|
+
* @param behavior - The behavior to add.
|
|
162
|
+
*/
|
|
163
|
+
addBehavior(behavior) {
|
|
164
|
+
var _a, _b;
|
|
165
|
+
const targetBehaviors = (_a = this.behaviors) !== null && _a !== void 0 ? _a : (this.behaviors = new Map());
|
|
166
|
+
const count = (_b = targetBehaviors.get(behavior)) !== null && _b !== void 0 ? _b : 0;
|
|
167
|
+
if (count === 0) {
|
|
168
|
+
targetBehaviors.set(behavior, 1);
|
|
169
|
+
behavior.addedCallback && behavior.addedCallback(this);
|
|
170
|
+
if (behavior.connectedCallback && this.isConnected) {
|
|
171
|
+
behavior.connectedCallback(this);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
targetBehaviors.set(behavior, count + 1);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Removes the behavior from the component.
|
|
180
|
+
* @param behavior - The behavior to remove.
|
|
181
|
+
* @param force - Forces removal even if this behavior was added more than once.
|
|
182
|
+
*/
|
|
183
|
+
removeBehavior(behavior, force = false) {
|
|
184
|
+
const targetBehaviors = this.behaviors;
|
|
185
|
+
if (targetBehaviors === null) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
const count = targetBehaviors.get(behavior);
|
|
189
|
+
if (count === void 0) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
if (count === 1 || force) {
|
|
193
|
+
targetBehaviors.delete(behavior);
|
|
194
|
+
if (behavior.disconnectedCallback && this.isConnected) {
|
|
195
|
+
behavior.disconnectedCallback(this);
|
|
196
|
+
}
|
|
197
|
+
behavior.removedCallback && behavior.removedCallback(this);
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
targetBehaviors.set(behavior, count - 1);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
124
203
|
/**
|
|
125
204
|
* Adds styles to this element. Providing an HTMLStyleElement will attach the element instance to the shadowRoot.
|
|
126
205
|
* @param styles - The styles to add.
|
|
127
206
|
*/
|
|
128
207
|
addStyles(styles) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
208
|
+
var _a;
|
|
209
|
+
if (!styles) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
const source = this.source;
|
|
213
|
+
const target = (_a = getShadowRoot(source)) !== null && _a !== void 0 ? _a : source.getRootNode();
|
|
214
|
+
if (styles instanceof HTMLElement) {
|
|
132
215
|
target.append(styles);
|
|
133
216
|
}
|
|
134
217
|
else if (!styles.isAttachedTo(target)) {
|
|
135
218
|
const sourceBehaviors = styles.behaviors;
|
|
136
219
|
styles.addStylesTo(target);
|
|
137
220
|
if (sourceBehaviors !== null) {
|
|
138
|
-
|
|
221
|
+
for (let i = 0, ii = sourceBehaviors.length; i < ii; ++i) {
|
|
222
|
+
this.addBehavior(sourceBehaviors[i]);
|
|
223
|
+
}
|
|
139
224
|
}
|
|
140
225
|
}
|
|
141
226
|
}
|
|
@@ -144,90 +229,42 @@ export class Controller extends PropertyChangeNotifier {
|
|
|
144
229
|
* @param styles - the styles to remove.
|
|
145
230
|
*/
|
|
146
231
|
removeStyles(styles) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
232
|
+
var _a;
|
|
233
|
+
if (!styles) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const source = this.source;
|
|
237
|
+
const target = (_a = getShadowRoot(source)) !== null && _a !== void 0 ? _a : source.getRootNode();
|
|
238
|
+
if (styles instanceof HTMLElement) {
|
|
150
239
|
target.removeChild(styles);
|
|
151
240
|
}
|
|
152
241
|
else if (styles.isAttachedTo(target)) {
|
|
153
242
|
const sourceBehaviors = styles.behaviors;
|
|
154
243
|
styles.removeStylesFrom(target);
|
|
155
244
|
if (sourceBehaviors !== null) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* Adds behaviors to this element.
|
|
162
|
-
* @param behaviors - The behaviors to add.
|
|
163
|
-
*/
|
|
164
|
-
addBehaviors(behaviors) {
|
|
165
|
-
const targetBehaviors = this.behaviors || (this.behaviors = new Map());
|
|
166
|
-
const length = behaviors.length;
|
|
167
|
-
const behaviorsToBind = [];
|
|
168
|
-
for (let i = 0; i < length; ++i) {
|
|
169
|
-
const behavior = behaviors[i];
|
|
170
|
-
if (targetBehaviors.has(behavior)) {
|
|
171
|
-
targetBehaviors.set(behavior, targetBehaviors.get(behavior) + 1);
|
|
172
|
-
}
|
|
173
|
-
else {
|
|
174
|
-
targetBehaviors.set(behavior, 1);
|
|
175
|
-
behaviorsToBind.push(behavior);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
if (this._isConnected) {
|
|
179
|
-
const element = this.element;
|
|
180
|
-
for (let i = 0; i < behaviorsToBind.length; ++i) {
|
|
181
|
-
behaviorsToBind[i].bind(element, defaultExecutionContext);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* Removes behaviors from this element.
|
|
187
|
-
* @param behaviors - The behaviors to remove.
|
|
188
|
-
* @param force - Forces unbinding of behaviors.
|
|
189
|
-
*/
|
|
190
|
-
removeBehaviors(behaviors, force = false) {
|
|
191
|
-
const targetBehaviors = this.behaviors;
|
|
192
|
-
if (targetBehaviors === null) {
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
195
|
-
const length = behaviors.length;
|
|
196
|
-
const behaviorsToUnbind = [];
|
|
197
|
-
for (let i = 0; i < length; ++i) {
|
|
198
|
-
const behavior = behaviors[i];
|
|
199
|
-
if (targetBehaviors.has(behavior)) {
|
|
200
|
-
const count = targetBehaviors.get(behavior) - 1;
|
|
201
|
-
count === 0 || force
|
|
202
|
-
? targetBehaviors.delete(behavior) && behaviorsToUnbind.push(behavior)
|
|
203
|
-
: targetBehaviors.set(behavior, count);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
if (this._isConnected) {
|
|
207
|
-
const element = this.element;
|
|
208
|
-
for (let i = 0; i < behaviorsToUnbind.length; ++i) {
|
|
209
|
-
behaviorsToUnbind[i].unbind(element);
|
|
245
|
+
for (let i = 0, ii = sourceBehaviors.length; i < ii; ++i) {
|
|
246
|
+
this.addBehavior(sourceBehaviors[i]);
|
|
247
|
+
}
|
|
210
248
|
}
|
|
211
249
|
}
|
|
212
250
|
}
|
|
213
251
|
/**
|
|
214
252
|
* Runs connected lifecycle behavior on the associated element.
|
|
215
253
|
*/
|
|
216
|
-
|
|
254
|
+
connect() {
|
|
217
255
|
if (this._isConnected) {
|
|
218
256
|
return;
|
|
219
257
|
}
|
|
220
|
-
const element = this.element;
|
|
221
258
|
if (this.needsInitialization) {
|
|
222
259
|
this.finishInitialization();
|
|
223
260
|
}
|
|
224
261
|
else if (this.view !== null) {
|
|
225
|
-
this.view.bind(
|
|
262
|
+
this.view.bind(this.source);
|
|
226
263
|
}
|
|
227
264
|
const behaviors = this.behaviors;
|
|
228
265
|
if (behaviors !== null) {
|
|
229
|
-
for (const
|
|
230
|
-
|
|
266
|
+
for (const key of behaviors.keys()) {
|
|
267
|
+
key.connectedCallback && key.connectedCallback(this);
|
|
231
268
|
}
|
|
232
269
|
}
|
|
233
270
|
this.setIsConnected(true);
|
|
@@ -235,20 +272,18 @@ export class Controller extends PropertyChangeNotifier {
|
|
|
235
272
|
/**
|
|
236
273
|
* Runs disconnected lifecycle behavior on the associated element.
|
|
237
274
|
*/
|
|
238
|
-
|
|
275
|
+
disconnect() {
|
|
239
276
|
if (!this._isConnected) {
|
|
240
277
|
return;
|
|
241
278
|
}
|
|
242
279
|
this.setIsConnected(false);
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
view.unbind();
|
|
280
|
+
if (this.view !== null) {
|
|
281
|
+
this.view.unbind();
|
|
246
282
|
}
|
|
247
283
|
const behaviors = this.behaviors;
|
|
248
284
|
if (behaviors !== null) {
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
behavior.unbind(element);
|
|
285
|
+
for (const key of behaviors.keys()) {
|
|
286
|
+
key.disconnectedCallback && key.disconnectedCallback(this);
|
|
252
287
|
}
|
|
253
288
|
}
|
|
254
289
|
}
|
|
@@ -261,7 +296,7 @@ export class Controller extends PropertyChangeNotifier {
|
|
|
261
296
|
onAttributeChangedCallback(name, oldValue, newValue) {
|
|
262
297
|
const attrDef = this.definition.attributeLookup[name];
|
|
263
298
|
if (attrDef !== void 0) {
|
|
264
|
-
attrDef.onAttributeChangedCallback(this.
|
|
299
|
+
attrDef.onAttributeChangedCallback(this.source, newValue);
|
|
265
300
|
}
|
|
266
301
|
}
|
|
267
302
|
/**
|
|
@@ -274,12 +309,12 @@ export class Controller extends PropertyChangeNotifier {
|
|
|
274
309
|
*/
|
|
275
310
|
emit(type, detail, options) {
|
|
276
311
|
if (this._isConnected) {
|
|
277
|
-
return this.
|
|
312
|
+
return this.source.dispatchEvent(new CustomEvent(type, Object.assign(Object.assign({ detail }, defaultEventOptions), options)));
|
|
278
313
|
}
|
|
279
314
|
return false;
|
|
280
315
|
}
|
|
281
316
|
finishInitialization() {
|
|
282
|
-
const element = this.
|
|
317
|
+
const element = this.source;
|
|
283
318
|
const boundObservables = this.boundObservables;
|
|
284
319
|
// If we have any observables that were bound, re-apply their values.
|
|
285
320
|
if (boundObservables !== null) {
|
|
@@ -290,59 +325,34 @@ export class Controller extends PropertyChangeNotifier {
|
|
|
290
325
|
}
|
|
291
326
|
this.boundObservables = null;
|
|
292
327
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
if (this._template === null) {
|
|
296
|
-
if (this.element.resolveTemplate) {
|
|
297
|
-
// 2. Allow for element instance overrides next.
|
|
298
|
-
this._template = this.element.resolveTemplate();
|
|
299
|
-
}
|
|
300
|
-
else if (definition.template) {
|
|
301
|
-
// 3. Default to the static definition.
|
|
302
|
-
this._template = definition.template || null;
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
// If we have a template after the above process, render it.
|
|
306
|
-
// If there's no template, then the element author has opted into
|
|
307
|
-
// custom rendering and they will managed the shadow root's content themselves.
|
|
308
|
-
if (this._template !== null) {
|
|
309
|
-
this.renderTemplate(this._template);
|
|
310
|
-
}
|
|
311
|
-
// 1. Styles overrides take top precedence.
|
|
312
|
-
if (this._styles === null) {
|
|
313
|
-
if (this.element.resolveStyles) {
|
|
314
|
-
// 2. Allow for element instance overrides next.
|
|
315
|
-
this._styles = this.element.resolveStyles();
|
|
316
|
-
}
|
|
317
|
-
else if (definition.styles) {
|
|
318
|
-
// 3. Default to the static definition.
|
|
319
|
-
this._styles = definition.styles || null;
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
// If we have styles after the above process, add them.
|
|
323
|
-
if (this._styles !== null) {
|
|
324
|
-
this.addStyles(this._styles);
|
|
325
|
-
}
|
|
328
|
+
this.renderTemplate(this.template);
|
|
329
|
+
this.addStyles(this.mainStyles);
|
|
326
330
|
this.needsInitialization = false;
|
|
327
331
|
}
|
|
328
332
|
renderTemplate(template) {
|
|
329
|
-
|
|
333
|
+
var _a;
|
|
330
334
|
// When getting the host to render to, we start by looking
|
|
331
335
|
// up the shadow root. If there isn't one, then that means
|
|
332
336
|
// we're doing a Light DOM render to the element's direct children.
|
|
333
|
-
const
|
|
337
|
+
const element = this.source;
|
|
338
|
+
const host = (_a = getShadowRoot(element)) !== null && _a !== void 0 ? _a : element;
|
|
334
339
|
if (this.view !== null) {
|
|
335
340
|
// If there's already a view, we need to unbind and remove through dispose.
|
|
336
341
|
this.view.dispose();
|
|
337
342
|
this.view = null;
|
|
338
343
|
}
|
|
339
|
-
else if (!this.needsInitialization) {
|
|
344
|
+
else if (!this.needsInitialization || this.hasExistingShadowRoot) {
|
|
345
|
+
this.hasExistingShadowRoot = false;
|
|
340
346
|
// If there was previous custom rendering, we need to clear out the host.
|
|
341
|
-
|
|
347
|
+
for (let child = host.firstChild; child !== null; child = host.firstChild) {
|
|
348
|
+
host.removeChild(child);
|
|
349
|
+
}
|
|
342
350
|
}
|
|
343
351
|
if (template) {
|
|
344
352
|
// If a new template was provided, render it.
|
|
345
353
|
this.view = template.render(element, host, element);
|
|
354
|
+
this.view.sourceLifetime =
|
|
355
|
+
SourceLifetime.coupled;
|
|
346
356
|
}
|
|
347
357
|
}
|
|
348
358
|
/**
|
|
@@ -358,10 +368,10 @@ export class Controller extends PropertyChangeNotifier {
|
|
|
358
368
|
if (controller !== void 0) {
|
|
359
369
|
return controller;
|
|
360
370
|
}
|
|
361
|
-
const definition = FASTElementDefinition.
|
|
371
|
+
const definition = FASTElementDefinition.getForInstance(element);
|
|
362
372
|
if (definition === void 0) {
|
|
363
|
-
throw
|
|
373
|
+
throw FAST.error(1401 /* Message.missingElementDefinition */);
|
|
364
374
|
}
|
|
365
|
-
return (element.$fastController = new
|
|
375
|
+
return (element.$fastController = new ElementController(element, definition));
|
|
366
376
|
}
|
|
367
377
|
}
|
|
@@ -1,42 +1,28 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isString } from "../interfaces.js";
|
|
2
2
|
import { Observable } from "../observation/observable.js";
|
|
3
|
+
import { createTypeRegistry, FAST } from "../platform.js";
|
|
3
4
|
import { ElementStyles } from "../styles/element-styles.js";
|
|
4
5
|
import { AttributeDefinition } from "./attributes.js";
|
|
5
6
|
const defaultShadowOptions = { mode: "open" };
|
|
6
7
|
const defaultElementOptions = {};
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
return Object.freeze({
|
|
10
|
-
register(definition) {
|
|
11
|
-
if (typeToDefinition.has(definition.type)) {
|
|
12
|
-
return false;
|
|
13
|
-
}
|
|
14
|
-
typeToDefinition.set(definition.type, definition);
|
|
15
|
-
return true;
|
|
16
|
-
},
|
|
17
|
-
getByType(key) {
|
|
18
|
-
return typeToDefinition.get(key);
|
|
19
|
-
},
|
|
20
|
-
});
|
|
21
|
-
});
|
|
8
|
+
const fastElementBaseTypes = new Set();
|
|
9
|
+
const fastElementRegistry = FAST.getById(4 /* KernelServiceId.elementRegistry */, () => createTypeRegistry());
|
|
22
10
|
/**
|
|
23
11
|
* Defines metadata for a FASTElement.
|
|
24
12
|
* @public
|
|
25
13
|
*/
|
|
26
14
|
export class FASTElementDefinition {
|
|
27
|
-
/**
|
|
28
|
-
* Creates an instance of FASTElementDefinition.
|
|
29
|
-
* @param type - The type this definition is being created for.
|
|
30
|
-
* @param nameOrConfig - The name of the element to define or a config object
|
|
31
|
-
* that describes the element to define.
|
|
32
|
-
*/
|
|
33
15
|
constructor(type, nameOrConfig = type.definition) {
|
|
34
|
-
|
|
16
|
+
var _a;
|
|
17
|
+
this.platformDefined = false;
|
|
18
|
+
if (isString(nameOrConfig)) {
|
|
35
19
|
nameOrConfig = { name: nameOrConfig };
|
|
36
20
|
}
|
|
37
21
|
this.type = type;
|
|
38
22
|
this.name = nameOrConfig.name;
|
|
39
23
|
this.template = nameOrConfig.template;
|
|
24
|
+
this.registry = (_a = nameOrConfig.registry) !== null && _a !== void 0 ? _a : customElements;
|
|
25
|
+
const proto = type.prototype;
|
|
40
26
|
const attributes = AttributeDefinition.collect(type, nameOrConfig.attributes);
|
|
41
27
|
const observedAttributes = new Array(attributes.length);
|
|
42
28
|
const propertyLookup = {};
|
|
@@ -46,9 +32,13 @@ export class FASTElementDefinition {
|
|
|
46
32
|
observedAttributes[i] = current.attribute;
|
|
47
33
|
propertyLookup[current.name] = current;
|
|
48
34
|
attributeLookup[current.attribute] = current;
|
|
35
|
+
Observable.defineProperty(proto, current);
|
|
49
36
|
}
|
|
37
|
+
Reflect.defineProperty(type, "observedAttributes", {
|
|
38
|
+
value: observedAttributes,
|
|
39
|
+
enumerable: true,
|
|
40
|
+
});
|
|
50
41
|
this.attributes = attributes;
|
|
51
|
-
this.observedAttributes = observedAttributes;
|
|
52
42
|
this.propertyLookup = propertyLookup;
|
|
53
43
|
this.attributeLookup = attributeLookup;
|
|
54
44
|
this.shadowOptions =
|
|
@@ -61,46 +51,58 @@ export class FASTElementDefinition {
|
|
|
61
51
|
nameOrConfig.elementOptions === void 0
|
|
62
52
|
? defaultElementOptions
|
|
63
53
|
: Object.assign(Object.assign({}, defaultElementOptions), nameOrConfig.elementOptions);
|
|
64
|
-
this.styles =
|
|
65
|
-
|
|
66
|
-
? void 0
|
|
67
|
-
: Array.isArray(nameOrConfig.styles)
|
|
68
|
-
? ElementStyles.create(nameOrConfig.styles)
|
|
69
|
-
: nameOrConfig.styles instanceof ElementStyles
|
|
70
|
-
? nameOrConfig.styles
|
|
71
|
-
: ElementStyles.create([nameOrConfig.styles]);
|
|
54
|
+
this.styles = ElementStyles.normalize(nameOrConfig.styles);
|
|
55
|
+
fastElementRegistry.register(this);
|
|
72
56
|
}
|
|
73
57
|
/**
|
|
74
58
|
* Indicates if this element has been defined in at least one registry.
|
|
75
59
|
*/
|
|
76
60
|
get isDefined() {
|
|
77
|
-
return
|
|
61
|
+
return this.platformDefined;
|
|
78
62
|
}
|
|
79
63
|
/**
|
|
80
64
|
* Defines a custom element based on this definition.
|
|
81
65
|
* @param registry - The element registry to define the element in.
|
|
66
|
+
* @remarks
|
|
67
|
+
* This operation is idempotent per registry.
|
|
82
68
|
*/
|
|
83
|
-
define(registry =
|
|
69
|
+
define(registry = this.registry) {
|
|
84
70
|
const type = this.type;
|
|
85
|
-
if (fastRegistry.register(this)) {
|
|
86
|
-
const attributes = this.attributes;
|
|
87
|
-
const proto = type.prototype;
|
|
88
|
-
for (let i = 0, ii = attributes.length; i < ii; ++i) {
|
|
89
|
-
Observable.defineProperty(proto, attributes[i]);
|
|
90
|
-
}
|
|
91
|
-
Reflect.defineProperty(type, "observedAttributes", {
|
|
92
|
-
value: this.observedAttributes,
|
|
93
|
-
enumerable: true,
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
71
|
if (!registry.get(this.name)) {
|
|
72
|
+
this.platformDefined = true;
|
|
97
73
|
registry.define(this.name, type, this.elementOptions);
|
|
98
74
|
}
|
|
99
75
|
return this;
|
|
100
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Creates an instance of FASTElementDefinition.
|
|
79
|
+
* @param type - The type this definition is being created for.
|
|
80
|
+
* @param nameOrDef - The name of the element to define or a config object
|
|
81
|
+
* that describes the element to define.
|
|
82
|
+
*/
|
|
83
|
+
static compose(type, nameOrDef) {
|
|
84
|
+
if (fastElementBaseTypes.has(type) || fastElementRegistry.getByType(type)) {
|
|
85
|
+
return new FASTElementDefinition(class extends type {
|
|
86
|
+
}, nameOrDef);
|
|
87
|
+
}
|
|
88
|
+
return new FASTElementDefinition(type, nameOrDef);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Registers a FASTElement base type.
|
|
92
|
+
* @param type - The type to register as a base type.
|
|
93
|
+
* @internal
|
|
94
|
+
*/
|
|
95
|
+
static registerBaseType(type) {
|
|
96
|
+
fastElementBaseTypes.add(type);
|
|
97
|
+
}
|
|
101
98
|
}
|
|
102
99
|
/**
|
|
103
100
|
* Gets the element definition associated with the specified type.
|
|
104
101
|
* @param type - The custom element type to retrieve the definition for.
|
|
105
102
|
*/
|
|
106
|
-
FASTElementDefinition.
|
|
103
|
+
FASTElementDefinition.getByType = fastElementRegistry.getByType;
|
|
104
|
+
/**
|
|
105
|
+
* Gets the element definition associated with the instance.
|
|
106
|
+
* @param instance - The custom element instance to retrieve the definition for.
|
|
107
|
+
*/
|
|
108
|
+
FASTElementDefinition.getForInstance = fastElementRegistry.getForInstance;
|