@microsoft/fast-element 2.0.0-beta.1 → 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/CHANGELOG.json +333 -0
- package/CHANGELOG.md +106 -1
- package/dist/dts/components/attributes.d.ts +10 -0
- package/dist/dts/components/{controller.d.ts → element-controller.d.ts} +24 -25
- package/dist/dts/components/fast-definitions.d.ts +43 -9
- package/dist/dts/components/fast-element.d.ts +15 -21
- package/dist/dts/context.d.ts +157 -0
- package/dist/dts/di/di.d.ts +899 -0
- package/dist/dts/index.d.ts +2 -2
- package/dist/dts/interfaces.d.ts +44 -12
- package/dist/dts/metadata.d.ts +25 -0
- package/dist/dts/observation/arrays.d.ts +1 -1
- package/dist/dts/observation/observable.d.ts +101 -75
- package/dist/dts/pending-task.d.ts +20 -0
- package/dist/dts/platform.d.ts +6 -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 +2 -2
- package/dist/dts/styles/element-styles.d.ts +9 -3
- 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 +69 -294
- package/dist/dts/templating/children.d.ts +1 -1
- package/dist/dts/templating/compiler.d.ts +1 -2
- package/dist/dts/templating/html-directive.d.ts +93 -35
- package/dist/dts/templating/node-observation.d.ts +4 -5
- package/dist/dts/templating/ref.d.ts +5 -13
- package/dist/dts/templating/render.d.ts +272 -0
- package/dist/dts/templating/repeat.d.ts +20 -75
- package/dist/dts/templating/slotted.d.ts +1 -1
- package/dist/dts/templating/template.d.ts +12 -61
- package/dist/dts/templating/view.d.ts +77 -12
- 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} +0 -0
- package/dist/dts/utilities.d.ts +0 -18
- package/dist/esm/components/attributes.js +13 -4
- package/dist/esm/components/{controller.js → element-controller.js} +95 -105
- package/dist/esm/components/fast-definitions.js +38 -28
- package/dist/esm/components/fast-element.js +31 -12
- package/dist/esm/context.js +163 -0
- package/dist/esm/debug.js +36 -4
- package/dist/esm/di/di.js +1435 -0
- package/dist/esm/index.js +2 -1
- package/dist/esm/interfaces.js +4 -0
- package/dist/esm/metadata.js +60 -0
- package/dist/esm/observation/arrays.js +304 -3
- package/dist/esm/observation/observable.js +81 -87
- package/dist/esm/pending-task.js +16 -0
- package/dist/esm/platform.js +25 -1
- 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 -4
- package/dist/esm/styles/element-styles.js +14 -0
- package/dist/esm/{observation/behavior.js → styles/host.js} +0 -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 +134 -414
- package/dist/esm/templating/compiler.js +30 -7
- package/dist/esm/templating/html-directive.js +100 -28
- package/dist/esm/templating/node-observation.js +9 -8
- package/dist/esm/templating/ref.js +4 -12
- package/dist/esm/templating/render.js +391 -0
- package/dist/esm/templating/repeat.js +96 -72
- package/dist/esm/templating/template.js +11 -29
- package/dist/esm/templating/view.js +107 -29
- package/dist/esm/templating/when.js +5 -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 +0 -95
- package/dist/fast-element.api.json +9034 -10524
- package/dist/fast-element.d.ts +707 -811
- package/dist/fast-element.debug.js +1133 -850
- package/dist/fast-element.debug.min.js +1 -1
- package/dist/fast-element.js +1097 -846
- package/dist/fast-element.min.js +1 -1
- package/dist/fast-element.untrimmed.d.ts +724 -818
- package/docs/api-report.md +264 -305
- package/package.json +39 -10
- 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/esm/hooks.js +0 -32
- package/dist/esm/observation/splice-strategies.js +0 -400
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import "../interfaces.js";
|
|
2
2
|
import { PropertyChangeNotifier } from "../observation/notifier.js";
|
|
3
|
-
import {
|
|
3
|
+
import { Observable, SourceLifetime } from "../observation/observable.js";
|
|
4
4
|
import { FAST } from "../platform.js";
|
|
5
5
|
import { FASTElementDefinition } from "./fast-definitions.js";
|
|
6
|
-
const shadowRoots = new WeakMap();
|
|
7
6
|
const defaultEventOptions = {
|
|
8
7
|
bubbles: true,
|
|
9
8
|
composed: true,
|
|
10
9
|
cancelable: true,
|
|
11
10
|
};
|
|
11
|
+
const isConnectedPropertyName = "isConnected";
|
|
12
|
+
const shadowRoots = new WeakMap();
|
|
12
13
|
function getShadowRoot(element) {
|
|
13
14
|
var _a, _b;
|
|
14
15
|
return (_b = (_a = element.shadowRoot) !== null && _a !== void 0 ? _a : shadowRoots.get(element)) !== null && _b !== void 0 ? _b : null;
|
|
15
16
|
}
|
|
16
|
-
const isConnectedPropertyName = "isConnected";
|
|
17
17
|
/**
|
|
18
18
|
* Controls the lifecycle and rendering of a `FASTElement`.
|
|
19
19
|
* @public
|
|
20
20
|
*/
|
|
21
|
-
export class
|
|
21
|
+
export class ElementController extends PropertyChangeNotifier {
|
|
22
22
|
/**
|
|
23
23
|
* Creates a Controller to control the specified element.
|
|
24
24
|
* @param element - The element to be controlled by this controller.
|
|
@@ -29,12 +29,12 @@ export class Controller extends PropertyChangeNotifier {
|
|
|
29
29
|
constructor(element, definition) {
|
|
30
30
|
super(element);
|
|
31
31
|
this.boundObservables = null;
|
|
32
|
-
this.behaviors = null;
|
|
33
32
|
this.needsInitialization = true;
|
|
34
33
|
this.hasExistingShadowRoot = false;
|
|
35
34
|
this._template = null;
|
|
36
|
-
this._styles = null;
|
|
37
35
|
this._isConnected = false;
|
|
36
|
+
this.behaviors = null;
|
|
37
|
+
this._mainStyles = null;
|
|
38
38
|
/**
|
|
39
39
|
* This allows Observable.getNotifier(...) to return the Controller
|
|
40
40
|
* when the notifier for the Controller itself is being requested. The
|
|
@@ -50,7 +50,7 @@ export class Controller extends PropertyChangeNotifier {
|
|
|
50
50
|
* If `null` then the element is managing its own rendering.
|
|
51
51
|
*/
|
|
52
52
|
this.view = null;
|
|
53
|
-
this.
|
|
53
|
+
this.source = element;
|
|
54
54
|
this.definition = definition;
|
|
55
55
|
const shadowOptions = definition.shadowOptions;
|
|
56
56
|
if (shadowOptions !== void 0) {
|
|
@@ -104,9 +104,9 @@ export class Controller extends PropertyChangeNotifier {
|
|
|
104
104
|
// 1. Template overrides take top precedence.
|
|
105
105
|
if (this._template === null) {
|
|
106
106
|
const definition = this.definition;
|
|
107
|
-
if (this.
|
|
107
|
+
if (this.source.resolveTemplate) {
|
|
108
108
|
// 2. Allow for element instance overrides next.
|
|
109
|
-
this._template = this.
|
|
109
|
+
this._template = this.source.resolveTemplate();
|
|
110
110
|
}
|
|
111
111
|
else if (definition.template) {
|
|
112
112
|
// 3. Default to the static definition.
|
|
@@ -125,48 +125,92 @@ export class Controller extends PropertyChangeNotifier {
|
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
127
|
/**
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
* 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.
|
|
131
130
|
*/
|
|
132
|
-
get
|
|
131
|
+
get mainStyles() {
|
|
133
132
|
var _a;
|
|
134
133
|
// 1. Styles overrides take top precedence.
|
|
135
|
-
if (this.
|
|
134
|
+
if (this._mainStyles === null) {
|
|
136
135
|
const definition = this.definition;
|
|
137
|
-
if (this.
|
|
136
|
+
if (this.source.resolveStyles) {
|
|
138
137
|
// 2. Allow for element instance overrides next.
|
|
139
|
-
this.
|
|
138
|
+
this._mainStyles = this.source.resolveStyles();
|
|
140
139
|
}
|
|
141
140
|
else if (definition.styles) {
|
|
142
141
|
// 3. Default to the static definition.
|
|
143
|
-
this.
|
|
142
|
+
this._mainStyles = (_a = definition.styles) !== null && _a !== void 0 ? _a : null;
|
|
144
143
|
}
|
|
145
144
|
}
|
|
146
|
-
return this.
|
|
145
|
+
return this._mainStyles;
|
|
147
146
|
}
|
|
148
|
-
set
|
|
149
|
-
if (this.
|
|
147
|
+
set mainStyles(value) {
|
|
148
|
+
if (this._mainStyles === value) {
|
|
150
149
|
return;
|
|
151
150
|
}
|
|
152
|
-
if (this.
|
|
153
|
-
this.removeStyles(this.
|
|
151
|
+
if (this._mainStyles !== null) {
|
|
152
|
+
this.removeStyles(this._mainStyles);
|
|
154
153
|
}
|
|
155
|
-
this.
|
|
154
|
+
this._mainStyles = value;
|
|
156
155
|
if (!this.needsInitialization) {
|
|
157
156
|
this.addStyles(value);
|
|
158
157
|
}
|
|
159
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
|
+
}
|
|
160
203
|
/**
|
|
161
204
|
* Adds styles to this element. Providing an HTMLStyleElement will attach the element instance to the shadowRoot.
|
|
162
205
|
* @param styles - The styles to add.
|
|
163
206
|
*/
|
|
164
207
|
addStyles(styles) {
|
|
208
|
+
var _a;
|
|
165
209
|
if (!styles) {
|
|
166
210
|
return;
|
|
167
211
|
}
|
|
168
|
-
const
|
|
169
|
-
|
|
212
|
+
const source = this.source;
|
|
213
|
+
const target = (_a = getShadowRoot(source)) !== null && _a !== void 0 ? _a : source.getRootNode();
|
|
170
214
|
if (styles instanceof HTMLElement) {
|
|
171
215
|
target.append(styles);
|
|
172
216
|
}
|
|
@@ -174,7 +218,9 @@ export class Controller extends PropertyChangeNotifier {
|
|
|
174
218
|
const sourceBehaviors = styles.behaviors;
|
|
175
219
|
styles.addStylesTo(target);
|
|
176
220
|
if (sourceBehaviors !== null) {
|
|
177
|
-
|
|
221
|
+
for (let i = 0, ii = sourceBehaviors.length; i < ii; ++i) {
|
|
222
|
+
this.addBehavior(sourceBehaviors[i]);
|
|
223
|
+
}
|
|
178
224
|
}
|
|
179
225
|
}
|
|
180
226
|
}
|
|
@@ -183,11 +229,12 @@ export class Controller extends PropertyChangeNotifier {
|
|
|
183
229
|
* @param styles - the styles to remove.
|
|
184
230
|
*/
|
|
185
231
|
removeStyles(styles) {
|
|
232
|
+
var _a;
|
|
186
233
|
if (!styles) {
|
|
187
234
|
return;
|
|
188
235
|
}
|
|
189
|
-
const
|
|
190
|
-
|
|
236
|
+
const source = this.source;
|
|
237
|
+
const target = (_a = getShadowRoot(source)) !== null && _a !== void 0 ? _a : source.getRootNode();
|
|
191
238
|
if (styles instanceof HTMLElement) {
|
|
192
239
|
target.removeChild(styles);
|
|
193
240
|
}
|
|
@@ -195,85 +242,29 @@ export class Controller extends PropertyChangeNotifier {
|
|
|
195
242
|
const sourceBehaviors = styles.behaviors;
|
|
196
243
|
styles.removeStylesFrom(target);
|
|
197
244
|
if (sourceBehaviors !== null) {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}
|
|
202
|
-
/**
|
|
203
|
-
* Adds behaviors to this element.
|
|
204
|
-
* @param behaviors - The behaviors to add.
|
|
205
|
-
*/
|
|
206
|
-
addBehaviors(behaviors) {
|
|
207
|
-
var _a;
|
|
208
|
-
const targetBehaviors = (_a = this.behaviors) !== null && _a !== void 0 ? _a : (this.behaviors = new Map());
|
|
209
|
-
const length = behaviors.length;
|
|
210
|
-
const behaviorsToBind = [];
|
|
211
|
-
for (let i = 0; i < length; ++i) {
|
|
212
|
-
const behavior = behaviors[i];
|
|
213
|
-
if (targetBehaviors.has(behavior)) {
|
|
214
|
-
targetBehaviors.set(behavior, targetBehaviors.get(behavior) + 1);
|
|
215
|
-
}
|
|
216
|
-
else {
|
|
217
|
-
targetBehaviors.set(behavior, 1);
|
|
218
|
-
behaviorsToBind.push(behavior);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
if (this._isConnected) {
|
|
222
|
-
const element = this.element;
|
|
223
|
-
const context = ExecutionContext.default;
|
|
224
|
-
for (let i = 0; i < behaviorsToBind.length; ++i) {
|
|
225
|
-
behaviorsToBind[i].bind(element, context);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
/**
|
|
230
|
-
* Removes behaviors from this element.
|
|
231
|
-
* @param behaviors - The behaviors to remove.
|
|
232
|
-
* @param force - Forces unbinding of behaviors.
|
|
233
|
-
*/
|
|
234
|
-
removeBehaviors(behaviors, force = false) {
|
|
235
|
-
const targetBehaviors = this.behaviors;
|
|
236
|
-
if (targetBehaviors === null) {
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
const length = behaviors.length;
|
|
240
|
-
const behaviorsToUnbind = [];
|
|
241
|
-
for (let i = 0; i < length; ++i) {
|
|
242
|
-
const behavior = behaviors[i];
|
|
243
|
-
if (targetBehaviors.has(behavior)) {
|
|
244
|
-
const count = targetBehaviors.get(behavior) - 1;
|
|
245
|
-
count === 0 || force
|
|
246
|
-
? targetBehaviors.delete(behavior) && behaviorsToUnbind.push(behavior)
|
|
247
|
-
: targetBehaviors.set(behavior, count);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
if (this._isConnected) {
|
|
251
|
-
const element = this.element;
|
|
252
|
-
const context = ExecutionContext.default;
|
|
253
|
-
for (let i = 0; i < behaviorsToUnbind.length; ++i) {
|
|
254
|
-
behaviorsToUnbind[i].unbind(element, context);
|
|
245
|
+
for (let i = 0, ii = sourceBehaviors.length; i < ii; ++i) {
|
|
246
|
+
this.addBehavior(sourceBehaviors[i]);
|
|
247
|
+
}
|
|
255
248
|
}
|
|
256
249
|
}
|
|
257
250
|
}
|
|
258
251
|
/**
|
|
259
252
|
* Runs connected lifecycle behavior on the associated element.
|
|
260
253
|
*/
|
|
261
|
-
|
|
254
|
+
connect() {
|
|
262
255
|
if (this._isConnected) {
|
|
263
256
|
return;
|
|
264
257
|
}
|
|
265
|
-
const element = this.element;
|
|
266
|
-
const context = ExecutionContext.default;
|
|
267
258
|
if (this.needsInitialization) {
|
|
268
259
|
this.finishInitialization();
|
|
269
260
|
}
|
|
270
261
|
else if (this.view !== null) {
|
|
271
|
-
this.view.bind(
|
|
262
|
+
this.view.bind(this.source);
|
|
272
263
|
}
|
|
273
264
|
const behaviors = this.behaviors;
|
|
274
265
|
if (behaviors !== null) {
|
|
275
|
-
for (const
|
|
276
|
-
|
|
266
|
+
for (const key of behaviors.keys()) {
|
|
267
|
+
key.connectedCallback && key.connectedCallback(this);
|
|
277
268
|
}
|
|
278
269
|
}
|
|
279
270
|
this.setIsConnected(true);
|
|
@@ -281,21 +272,18 @@ export class Controller extends PropertyChangeNotifier {
|
|
|
281
272
|
/**
|
|
282
273
|
* Runs disconnected lifecycle behavior on the associated element.
|
|
283
274
|
*/
|
|
284
|
-
|
|
275
|
+
disconnect() {
|
|
285
276
|
if (!this._isConnected) {
|
|
286
277
|
return;
|
|
287
278
|
}
|
|
288
279
|
this.setIsConnected(false);
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
view.unbind();
|
|
280
|
+
if (this.view !== null) {
|
|
281
|
+
this.view.unbind();
|
|
292
282
|
}
|
|
293
283
|
const behaviors = this.behaviors;
|
|
294
284
|
if (behaviors !== null) {
|
|
295
|
-
const
|
|
296
|
-
|
|
297
|
-
for (const behavior of behaviors.keys()) {
|
|
298
|
-
behavior.unbind(element, context);
|
|
285
|
+
for (const key of behaviors.keys()) {
|
|
286
|
+
key.disconnectedCallback && key.disconnectedCallback(this);
|
|
299
287
|
}
|
|
300
288
|
}
|
|
301
289
|
}
|
|
@@ -308,7 +296,7 @@ export class Controller extends PropertyChangeNotifier {
|
|
|
308
296
|
onAttributeChangedCallback(name, oldValue, newValue) {
|
|
309
297
|
const attrDef = this.definition.attributeLookup[name];
|
|
310
298
|
if (attrDef !== void 0) {
|
|
311
|
-
attrDef.onAttributeChangedCallback(this.
|
|
299
|
+
attrDef.onAttributeChangedCallback(this.source, newValue);
|
|
312
300
|
}
|
|
313
301
|
}
|
|
314
302
|
/**
|
|
@@ -321,12 +309,12 @@ export class Controller extends PropertyChangeNotifier {
|
|
|
321
309
|
*/
|
|
322
310
|
emit(type, detail, options) {
|
|
323
311
|
if (this._isConnected) {
|
|
324
|
-
return this.
|
|
312
|
+
return this.source.dispatchEvent(new CustomEvent(type, Object.assign(Object.assign({ detail }, defaultEventOptions), options)));
|
|
325
313
|
}
|
|
326
314
|
return false;
|
|
327
315
|
}
|
|
328
316
|
finishInitialization() {
|
|
329
|
-
const element = this.
|
|
317
|
+
const element = this.source;
|
|
330
318
|
const boundObservables = this.boundObservables;
|
|
331
319
|
// If we have any observables that were bound, re-apply their values.
|
|
332
320
|
if (boundObservables !== null) {
|
|
@@ -338,15 +326,15 @@ export class Controller extends PropertyChangeNotifier {
|
|
|
338
326
|
this.boundObservables = null;
|
|
339
327
|
}
|
|
340
328
|
this.renderTemplate(this.template);
|
|
341
|
-
this.addStyles(this.
|
|
329
|
+
this.addStyles(this.mainStyles);
|
|
342
330
|
this.needsInitialization = false;
|
|
343
331
|
}
|
|
344
332
|
renderTemplate(template) {
|
|
345
333
|
var _a;
|
|
346
|
-
const element = this.element;
|
|
347
334
|
// When getting the host to render to, we start by looking
|
|
348
335
|
// up the shadow root. If there isn't one, then that means
|
|
349
336
|
// we're doing a Light DOM render to the element's direct children.
|
|
337
|
+
const element = this.source;
|
|
350
338
|
const host = (_a = getShadowRoot(element)) !== null && _a !== void 0 ? _a : element;
|
|
351
339
|
if (this.view !== null) {
|
|
352
340
|
// If there's already a view, we need to unbind and remove through dispose.
|
|
@@ -363,6 +351,8 @@ export class Controller extends PropertyChangeNotifier {
|
|
|
363
351
|
if (template) {
|
|
364
352
|
// If a new template was provided, render it.
|
|
365
353
|
this.view = template.render(element, host, element);
|
|
354
|
+
this.view.sourceLifetime =
|
|
355
|
+
SourceLifetime.coupled;
|
|
366
356
|
}
|
|
367
357
|
}
|
|
368
358
|
/**
|
|
@@ -382,6 +372,6 @@ export class Controller extends PropertyChangeNotifier {
|
|
|
382
372
|
if (definition === void 0) {
|
|
383
373
|
throw FAST.error(1401 /* Message.missingElementDefinition */);
|
|
384
374
|
}
|
|
385
|
-
return (element.$fastController = new
|
|
375
|
+
return (element.$fastController = new ElementController(element, definition));
|
|
386
376
|
}
|
|
387
377
|
}
|
|
@@ -5,25 +5,24 @@ import { ElementStyles } from "../styles/element-styles.js";
|
|
|
5
5
|
import { AttributeDefinition } from "./attributes.js";
|
|
6
6
|
const defaultShadowOptions = { mode: "open" };
|
|
7
7
|
const defaultElementOptions = {};
|
|
8
|
+
const fastElementBaseTypes = new Set();
|
|
8
9
|
const fastElementRegistry = FAST.getById(4 /* KernelServiceId.elementRegistry */, () => createTypeRegistry());
|
|
9
10
|
/**
|
|
10
11
|
* Defines metadata for a FASTElement.
|
|
11
12
|
* @public
|
|
12
13
|
*/
|
|
13
14
|
export class FASTElementDefinition {
|
|
14
|
-
/**
|
|
15
|
-
* Creates an instance of FASTElementDefinition.
|
|
16
|
-
* @param type - The type this definition is being created for.
|
|
17
|
-
* @param nameOrConfig - The name of the element to define or a config object
|
|
18
|
-
* that describes the element to define.
|
|
19
|
-
*/
|
|
20
15
|
constructor(type, nameOrConfig = type.definition) {
|
|
16
|
+
var _a;
|
|
17
|
+
this.platformDefined = false;
|
|
21
18
|
if (isString(nameOrConfig)) {
|
|
22
19
|
nameOrConfig = { name: nameOrConfig };
|
|
23
20
|
}
|
|
24
21
|
this.type = type;
|
|
25
22
|
this.name = nameOrConfig.name;
|
|
26
23
|
this.template = nameOrConfig.template;
|
|
24
|
+
this.registry = (_a = nameOrConfig.registry) !== null && _a !== void 0 ? _a : customElements;
|
|
25
|
+
const proto = type.prototype;
|
|
27
26
|
const attributes = AttributeDefinition.collect(type, nameOrConfig.attributes);
|
|
28
27
|
const observedAttributes = new Array(attributes.length);
|
|
29
28
|
const propertyLookup = {};
|
|
@@ -33,9 +32,13 @@ export class FASTElementDefinition {
|
|
|
33
32
|
observedAttributes[i] = current.attribute;
|
|
34
33
|
propertyLookup[current.name] = current;
|
|
35
34
|
attributeLookup[current.attribute] = current;
|
|
35
|
+
Observable.defineProperty(proto, current);
|
|
36
36
|
}
|
|
37
|
+
Reflect.defineProperty(type, "observedAttributes", {
|
|
38
|
+
value: observedAttributes,
|
|
39
|
+
enumerable: true,
|
|
40
|
+
});
|
|
37
41
|
this.attributes = attributes;
|
|
38
|
-
this.observedAttributes = observedAttributes;
|
|
39
42
|
this.propertyLookup = propertyLookup;
|
|
40
43
|
this.attributeLookup = attributeLookup;
|
|
41
44
|
this.shadowOptions =
|
|
@@ -48,43 +51,50 @@ export class FASTElementDefinition {
|
|
|
48
51
|
nameOrConfig.elementOptions === void 0
|
|
49
52
|
? defaultElementOptions
|
|
50
53
|
: Object.assign(Object.assign({}, defaultElementOptions), nameOrConfig.elementOptions);
|
|
51
|
-
this.styles =
|
|
52
|
-
|
|
53
|
-
? void 0
|
|
54
|
-
: Array.isArray(nameOrConfig.styles)
|
|
55
|
-
? new ElementStyles(nameOrConfig.styles)
|
|
56
|
-
: nameOrConfig.styles instanceof ElementStyles
|
|
57
|
-
? nameOrConfig.styles
|
|
58
|
-
: new ElementStyles([nameOrConfig.styles]);
|
|
54
|
+
this.styles = ElementStyles.normalize(nameOrConfig.styles);
|
|
55
|
+
fastElementRegistry.register(this);
|
|
59
56
|
}
|
|
60
57
|
/**
|
|
61
58
|
* Indicates if this element has been defined in at least one registry.
|
|
62
59
|
*/
|
|
63
60
|
get isDefined() {
|
|
64
|
-
return
|
|
61
|
+
return this.platformDefined;
|
|
65
62
|
}
|
|
66
63
|
/**
|
|
67
64
|
* Defines a custom element based on this definition.
|
|
68
65
|
* @param registry - The element registry to define the element in.
|
|
66
|
+
* @remarks
|
|
67
|
+
* This operation is idempotent per registry.
|
|
69
68
|
*/
|
|
70
|
-
define(registry =
|
|
69
|
+
define(registry = this.registry) {
|
|
71
70
|
const type = this.type;
|
|
72
|
-
if (fastElementRegistry.register(this)) {
|
|
73
|
-
const attributes = this.attributes;
|
|
74
|
-
const proto = type.prototype;
|
|
75
|
-
for (let i = 0, ii = attributes.length; i < ii; ++i) {
|
|
76
|
-
Observable.defineProperty(proto, attributes[i]);
|
|
77
|
-
}
|
|
78
|
-
Reflect.defineProperty(type, "observedAttributes", {
|
|
79
|
-
value: this.observedAttributes,
|
|
80
|
-
enumerable: true,
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
71
|
if (!registry.get(this.name)) {
|
|
72
|
+
this.platformDefined = true;
|
|
84
73
|
registry.define(this.name, type, this.elementOptions);
|
|
85
74
|
}
|
|
86
75
|
return this;
|
|
87
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
|
+
}
|
|
88
98
|
}
|
|
89
99
|
/**
|
|
90
100
|
* Gets the element definition associated with the specified type.
|
|
@@ -1,26 +1,44 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isFunction } from "../interfaces.js";
|
|
2
|
+
import { ElementController } from "./element-controller.js";
|
|
2
3
|
import { FASTElementDefinition, } from "./fast-definitions.js";
|
|
3
4
|
/* eslint-disable-next-line @typescript-eslint/explicit-function-return-type */
|
|
4
5
|
function createFASTElement(BaseType) {
|
|
5
|
-
|
|
6
|
+
const type = class extends BaseType {
|
|
6
7
|
constructor() {
|
|
7
8
|
/* eslint-disable-next-line */
|
|
8
9
|
super();
|
|
9
|
-
|
|
10
|
+
ElementController.forCustomElement(this);
|
|
10
11
|
}
|
|
11
12
|
$emit(type, detail, options) {
|
|
12
13
|
return this.$fastController.emit(type, detail, options);
|
|
13
14
|
}
|
|
14
15
|
connectedCallback() {
|
|
15
|
-
this.$fastController.
|
|
16
|
+
this.$fastController.connect();
|
|
16
17
|
}
|
|
17
18
|
disconnectedCallback() {
|
|
18
|
-
this.$fastController.
|
|
19
|
+
this.$fastController.disconnect();
|
|
19
20
|
}
|
|
20
21
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
21
22
|
this.$fastController.onAttributeChangedCallback(name, oldValue, newValue);
|
|
22
23
|
}
|
|
23
24
|
};
|
|
25
|
+
FASTElementDefinition.registerBaseType(type);
|
|
26
|
+
return type;
|
|
27
|
+
}
|
|
28
|
+
function compose(type, nameOrDef) {
|
|
29
|
+
if (isFunction(type)) {
|
|
30
|
+
return FASTElementDefinition.compose(type, nameOrDef);
|
|
31
|
+
}
|
|
32
|
+
return FASTElementDefinition.compose(this, type);
|
|
33
|
+
}
|
|
34
|
+
function define(type, nameOrDef) {
|
|
35
|
+
if (isFunction(type)) {
|
|
36
|
+
return FASTElementDefinition.compose(type, nameOrDef).define().type;
|
|
37
|
+
}
|
|
38
|
+
return FASTElementDefinition.compose(this, type).define().type;
|
|
39
|
+
}
|
|
40
|
+
function from(BaseType) {
|
|
41
|
+
return createFASTElement(BaseType);
|
|
24
42
|
}
|
|
25
43
|
/**
|
|
26
44
|
* A minimal base class for FASTElements that also provides
|
|
@@ -33,18 +51,19 @@ export const FASTElement = Object.assign(createFASTElement(HTMLElement), {
|
|
|
33
51
|
* provided base type.
|
|
34
52
|
* @param BaseType - The base element type to inherit from.
|
|
35
53
|
*/
|
|
36
|
-
from
|
|
37
|
-
return createFASTElement(BaseType);
|
|
38
|
-
},
|
|
54
|
+
from,
|
|
39
55
|
/**
|
|
40
56
|
* Defines a platform custom element based on the provided type and definition.
|
|
41
57
|
* @param type - The custom element type to define.
|
|
42
58
|
* @param nameOrDef - The name of the element to define or a definition object
|
|
43
59
|
* that describes the element to define.
|
|
44
60
|
*/
|
|
45
|
-
define
|
|
46
|
-
|
|
47
|
-
|
|
61
|
+
define,
|
|
62
|
+
/**
|
|
63
|
+
* Defines metadata for a FASTElement which can be used to later define the element.
|
|
64
|
+
* @public
|
|
65
|
+
*/
|
|
66
|
+
compose,
|
|
48
67
|
});
|
|
49
68
|
/**
|
|
50
69
|
* Decorator: Defines a platform custom element based on `FASTElement`.
|
|
@@ -55,6 +74,6 @@ export const FASTElement = Object.assign(createFASTElement(HTMLElement), {
|
|
|
55
74
|
export function customElement(nameOrDef) {
|
|
56
75
|
/* eslint-disable-next-line @typescript-eslint/explicit-function-return-type */
|
|
57
76
|
return function (type) {
|
|
58
|
-
|
|
77
|
+
define(type, nameOrDef);
|
|
59
78
|
};
|
|
60
79
|
}
|