@microsoft/fast-element 2.8.0 → 2.8.2
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 +31 -1
- package/CHANGELOG.md +18 -2
- package/dist/dts/components/element-controller.d.ts +107 -6
- package/dist/dts/index.d.ts +1 -1
- package/dist/esm/components/element-controller.js +156 -27
- package/dist/esm/components/fast-element.js +15 -14
- package/dist/esm/index.js +1 -1
- package/dist/esm/polyfills.js +33 -0
- package/dist/fast-element.api.json +262 -81
- package/dist/fast-element.debug.js +205 -33
- package/dist/fast-element.debug.min.js +2 -2
- package/dist/fast-element.js +205 -33
- package/dist/fast-element.min.js +2 -2
- package/dist/fast-element.untrimmed.d.ts +111 -5
- package/docs/api-report.api.md +18 -15
- package/package.json +1 -1
package/CHANGELOG.json
CHANGED
|
@@ -2,7 +2,37 @@
|
|
|
2
2
|
"name": "@microsoft/fast-element",
|
|
3
3
|
"entries": [
|
|
4
4
|
{
|
|
5
|
-
"date": "
|
|
5
|
+
"date": "Fri, 31 Oct 2025 20:45:23 GMT",
|
|
6
|
+
"version": "2.8.2",
|
|
7
|
+
"tag": "@microsoft/fast-element_v2.8.2",
|
|
8
|
+
"comments": {
|
|
9
|
+
"patch": [
|
|
10
|
+
{
|
|
11
|
+
"author": "863023+radium-v@users.noreply.github.com",
|
|
12
|
+
"package": "@microsoft/fast-element",
|
|
13
|
+
"commit": "1c008047c3c0b651dbec6dd74ece2da71693cbf3",
|
|
14
|
+
"comment": "fix: use shadowOptions getter override to set hydration attributes"
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"date": "Tue, 21 Oct 2025 16:17:27 GMT",
|
|
21
|
+
"version": "2.8.1",
|
|
22
|
+
"tag": "@microsoft/fast-element_v2.8.1",
|
|
23
|
+
"comments": {
|
|
24
|
+
"patch": [
|
|
25
|
+
{
|
|
26
|
+
"author": "863023+radium-v@users.noreply.github.com",
|
|
27
|
+
"package": "@microsoft/fast-element",
|
|
28
|
+
"commit": "d66ae6571c97341890e5320048fc1a3ef38dc5be",
|
|
29
|
+
"comment": "feat: add methods to track hydrating instances"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"date": "Mon, 13 Oct 2025 00:37:08 GMT",
|
|
6
36
|
"version": "2.8.0",
|
|
7
37
|
"tag": "@microsoft/fast-element_v2.8.0",
|
|
8
38
|
"comments": {
|
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
# Change Log - @microsoft/fast-element
|
|
2
2
|
|
|
3
|
-
<!-- This log was last generated on
|
|
3
|
+
<!-- This log was last generated on Fri, 31 Oct 2025 20:45:23 GMT and should not be manually modified. -->
|
|
4
4
|
|
|
5
5
|
<!-- Start content -->
|
|
6
6
|
|
|
7
|
+
## 2.8.2
|
|
8
|
+
|
|
9
|
+
Fri, 31 Oct 2025 20:45:23 GMT
|
|
10
|
+
|
|
11
|
+
### Patches
|
|
12
|
+
|
|
13
|
+
- fix: use shadowOptions getter override to set hydration attributes (863023+radium-v@users.noreply.github.com)
|
|
14
|
+
|
|
15
|
+
## 2.8.1
|
|
16
|
+
|
|
17
|
+
Tue, 21 Oct 2025 16:17:27 GMT
|
|
18
|
+
|
|
19
|
+
### Patches
|
|
20
|
+
|
|
21
|
+
- feat: add methods to track hydrating instances (863023+radium-v@users.noreply.github.com)
|
|
22
|
+
|
|
7
23
|
## 2.8.0
|
|
8
24
|
|
|
9
|
-
Mon, 13 Oct 2025 00:
|
|
25
|
+
Mon, 13 Oct 2025 00:37:08 GMT
|
|
10
26
|
|
|
11
27
|
### Minor changes
|
|
12
28
|
|
|
@@ -13,10 +13,18 @@ import { FASTElementDefinition, ShadowRootOptions } from "./fast-definitions.js"
|
|
|
13
13
|
export interface ElementControllerStrategy {
|
|
14
14
|
new (element: HTMLElement, definition: FASTElementDefinition): ElementController;
|
|
15
15
|
}
|
|
16
|
-
|
|
16
|
+
/**
|
|
17
|
+
* The various lifecycle stages of an ElementController.
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
export declare const enum Stages {
|
|
21
|
+
/** The element is in the process of connecting. */
|
|
17
22
|
connecting = 0,
|
|
23
|
+
/** The element is connected. */
|
|
18
24
|
connected = 1,
|
|
25
|
+
/** The element is in the process of disconnecting. */
|
|
19
26
|
disconnecting = 2,
|
|
27
|
+
/** The element is disconnected. */
|
|
20
28
|
disconnected = 3
|
|
21
29
|
}
|
|
22
30
|
/**
|
|
@@ -24,11 +32,29 @@ declare const enum Stages {
|
|
|
24
32
|
* @public
|
|
25
33
|
*/
|
|
26
34
|
export declare class ElementController<TElement extends HTMLElement = HTMLElement> extends PropertyChangeNotifier implements HostController<TElement> {
|
|
35
|
+
/**
|
|
36
|
+
* A map of observable properties that were set on the element before upgrade.
|
|
37
|
+
*/
|
|
27
38
|
private boundObservables;
|
|
39
|
+
/**
|
|
40
|
+
* Indicates whether the controller needs to perform initial rendering.
|
|
41
|
+
*/
|
|
28
42
|
protected needsInitialization: boolean;
|
|
29
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Indicates whether the element has an existing shadow root (e.g. from declarative shadow DOM).
|
|
45
|
+
*/
|
|
46
|
+
protected hasExistingShadowRoot: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* The template used to render the component.
|
|
49
|
+
*/
|
|
30
50
|
private _template;
|
|
51
|
+
/**
|
|
52
|
+
* The shadow root options for the component.
|
|
53
|
+
*/
|
|
31
54
|
private _shadowRootOptions;
|
|
55
|
+
/**
|
|
56
|
+
* The current lifecycle stage of the controller.
|
|
57
|
+
*/
|
|
32
58
|
protected stage: Stages;
|
|
33
59
|
/**
|
|
34
60
|
* A guard against connecting behaviors multiple times
|
|
@@ -36,12 +62,19 @@ export declare class ElementController<TElement extends HTMLElement = HTMLElemen
|
|
|
36
62
|
* another behavior during it's connectedCallback
|
|
37
63
|
*/
|
|
38
64
|
private guardBehaviorConnection;
|
|
65
|
+
/**
|
|
66
|
+
* The behaviors associated with the component.
|
|
67
|
+
*/
|
|
39
68
|
protected behaviors: Map<HostBehavior<TElement>, number> | null;
|
|
40
69
|
/**
|
|
41
70
|
* Tracks whether behaviors are connected so that
|
|
42
71
|
* behaviors cant be connected multiple times
|
|
43
72
|
*/
|
|
44
73
|
private behaviorsConnected;
|
|
74
|
+
/**
|
|
75
|
+
* The main set of styles used for the component, independent of any
|
|
76
|
+
* dynamically added styles.
|
|
77
|
+
*/
|
|
45
78
|
private _mainStyles;
|
|
46
79
|
/**
|
|
47
80
|
* This allows Observable.getNotifier(...) to return the Controller
|
|
@@ -91,6 +124,9 @@ export declare class ElementController<TElement extends HTMLElement = HTMLElemen
|
|
|
91
124
|
*/
|
|
92
125
|
get template(): ElementViewTemplate<TElement> | null;
|
|
93
126
|
set template(value: ElementViewTemplate<TElement> | null);
|
|
127
|
+
/**
|
|
128
|
+
* The shadow root options for the component.
|
|
129
|
+
*/
|
|
94
130
|
get shadowOptions(): ShadowRootOptions | undefined;
|
|
95
131
|
set shadowOptions(value: ShadowRootOptions | undefined);
|
|
96
132
|
/**
|
|
@@ -139,8 +175,17 @@ export declare class ElementController<TElement extends HTMLElement = HTMLElemen
|
|
|
139
175
|
* Runs connected lifecycle behavior on the associated element.
|
|
140
176
|
*/
|
|
141
177
|
connect(): void;
|
|
178
|
+
/**
|
|
179
|
+
* Binds any observables that were set before upgrade.
|
|
180
|
+
*/
|
|
142
181
|
protected bindObservables(): void;
|
|
182
|
+
/**
|
|
183
|
+
* Connects any existing behaviors on the associated element.
|
|
184
|
+
*/
|
|
143
185
|
protected connectBehaviors(): void;
|
|
186
|
+
/**
|
|
187
|
+
* Disconnects any behaviors on the associated element.
|
|
188
|
+
*/
|
|
144
189
|
protected disconnectBehaviors(): void;
|
|
145
190
|
/**
|
|
146
191
|
* Runs disconnected lifecycle behavior on the associated element.
|
|
@@ -162,6 +207,13 @@ export declare class ElementController<TElement extends HTMLElement = HTMLElemen
|
|
|
162
207
|
* Only emits events if connected.
|
|
163
208
|
*/
|
|
164
209
|
emit(type: string, detail?: any, options?: Omit<CustomEventInit, "detail">): void | boolean;
|
|
210
|
+
/**
|
|
211
|
+
* Renders the provided template to the element.
|
|
212
|
+
*
|
|
213
|
+
* @param template - The template to render.
|
|
214
|
+
* @remarks
|
|
215
|
+
* If `null` is provided, any existing view will be removed.
|
|
216
|
+
*/
|
|
165
217
|
protected renderTemplate(template: ElementViewTemplate | null | undefined): void;
|
|
166
218
|
/**
|
|
167
219
|
* Locates or creates a controller for the specified element.
|
|
@@ -204,7 +256,15 @@ export declare class StyleElementStrategy implements StyleStrategy {
|
|
|
204
256
|
addStylesTo(target: StyleTarget): void;
|
|
205
257
|
removeStylesFrom(target: StyleTarget): void;
|
|
206
258
|
}
|
|
259
|
+
/**
|
|
260
|
+
* The attribute used to defer hydration of an element.
|
|
261
|
+
* @public
|
|
262
|
+
*/
|
|
207
263
|
export declare const deferHydrationAttribute = "defer-hydration";
|
|
264
|
+
/**
|
|
265
|
+
* The attribute used to indicate that an element needs hydration.
|
|
266
|
+
* @public
|
|
267
|
+
*/
|
|
208
268
|
export declare const needsHydrationAttribute = "needs-hydration";
|
|
209
269
|
/**
|
|
210
270
|
* Lifecycle callbacks for element hydration events
|
|
@@ -238,22 +298,63 @@ export declare class HydratableElementController<TElement extends HTMLElement =
|
|
|
238
298
|
*/
|
|
239
299
|
protected needsHydration?: boolean;
|
|
240
300
|
private static hydrationObserver;
|
|
301
|
+
/**
|
|
302
|
+
* {@inheritdoc ElementController.shadowOptions}
|
|
303
|
+
*/
|
|
304
|
+
get shadowOptions(): ShadowRootOptions | undefined;
|
|
305
|
+
set shadowOptions(value: ShadowRootOptions | undefined);
|
|
241
306
|
/**
|
|
242
307
|
* Lifecycle callbacks for hydration events
|
|
243
308
|
*/
|
|
244
|
-
|
|
309
|
+
static lifecycleCallbacks?: HydrationControllerCallbacks;
|
|
310
|
+
/**
|
|
311
|
+
* An idle callback ID used to track hydration completion
|
|
312
|
+
*/
|
|
313
|
+
private static idleCallbackId;
|
|
314
|
+
/**
|
|
315
|
+
* Adds the current element instance to the hydrating instances map
|
|
316
|
+
*/
|
|
317
|
+
private addHydratingInstance;
|
|
245
318
|
/**
|
|
246
319
|
* Configure lifecycle callbacks for hydration events
|
|
247
320
|
*/
|
|
248
321
|
static config(callbacks: HydrationControllerCallbacks): typeof HydratableElementController;
|
|
249
322
|
private static hydrationObserverHandler;
|
|
250
323
|
/**
|
|
251
|
-
* Checks
|
|
324
|
+
* Checks to see if hydration is complete and if so, invokes the hydrationComplete callback.
|
|
325
|
+
* Then resets the ElementController strategy to the default so that future elements
|
|
326
|
+
* don't use the HydratableElementController.
|
|
327
|
+
*
|
|
328
|
+
* @param deadline - the idle deadline object
|
|
252
329
|
*/
|
|
253
330
|
private static checkHydrationComplete;
|
|
254
|
-
|
|
331
|
+
/**
|
|
332
|
+
* Runs connected lifecycle behavior on the associated element.
|
|
333
|
+
*/
|
|
255
334
|
connect(): void;
|
|
335
|
+
/**
|
|
336
|
+
* A map of element instances by the name of the custom element they are
|
|
337
|
+
* associated with. The key is the custom element name, and the value is the
|
|
338
|
+
* instances of hydratable elements which currently need to be hydrated.
|
|
339
|
+
*
|
|
340
|
+
* When all of the instances in the set have been hydrated, the set is
|
|
341
|
+
* cleared and removed from the map. If the map is empty, the
|
|
342
|
+
* hydrationComplete callback is invoked.
|
|
343
|
+
*/
|
|
344
|
+
private static hydratingInstances?;
|
|
345
|
+
/**
|
|
346
|
+
* Removes the current element instance from the hydrating instances map
|
|
347
|
+
*/
|
|
348
|
+
private removeHydratingInstance;
|
|
349
|
+
/**
|
|
350
|
+
* Unregisters the hydration observer when the element is disconnected.
|
|
351
|
+
*/
|
|
256
352
|
disconnect(): void;
|
|
353
|
+
/**
|
|
354
|
+
* Sets the ElementController strategy to HydratableElementController.
|
|
355
|
+
* @remarks
|
|
356
|
+
* This method is typically called during application startup to enable
|
|
357
|
+
* hydration support for FAST elements.
|
|
358
|
+
*/
|
|
257
359
|
static install(): void;
|
|
258
360
|
}
|
|
259
|
-
export {};
|
package/dist/dts/index.d.ts
CHANGED
|
@@ -31,4 +31,4 @@ export { render, RenderBehavior, RenderDirective } from "./templating/render.js"
|
|
|
31
31
|
export { customElement, FASTElement } from "./components/fast-element.js";
|
|
32
32
|
export { FASTElementDefinition, PartialFASTElementDefinition, ShadowRootOptions, fastElementRegistry, TemplateOptions, TypeRegistry, type TemplateLifecycleCallbacks, } from "./components/fast-definitions.js";
|
|
33
33
|
export { attr, AttributeConfiguration, AttributeDefinition, AttributeMode, booleanConverter, DecoratorAttributeConfiguration, nullableBooleanConverter, nullableNumberConverter, ValueConverter, } from "./components/attributes.js";
|
|
34
|
-
export { ElementController, ElementControllerStrategy, HydratableElementController, type HydrationControllerCallbacks, } from "./components/element-controller.js";
|
|
34
|
+
export { deferHydrationAttribute, ElementController, ElementControllerStrategy, HydratableElementController, type HydrationControllerCallbacks, needsHydrationAttribute, Stages, } from "./components/element-controller.js";
|
|
@@ -32,10 +32,25 @@ export class ElementController extends PropertyChangeNotifier {
|
|
|
32
32
|
*/
|
|
33
33
|
constructor(element, definition) {
|
|
34
34
|
super(element);
|
|
35
|
+
/**
|
|
36
|
+
* A map of observable properties that were set on the element before upgrade.
|
|
37
|
+
*/
|
|
35
38
|
this.boundObservables = null;
|
|
39
|
+
/**
|
|
40
|
+
* Indicates whether the controller needs to perform initial rendering.
|
|
41
|
+
*/
|
|
36
42
|
this.needsInitialization = true;
|
|
43
|
+
/**
|
|
44
|
+
* Indicates whether the element has an existing shadow root (e.g. from declarative shadow DOM).
|
|
45
|
+
*/
|
|
37
46
|
this.hasExistingShadowRoot = false;
|
|
47
|
+
/**
|
|
48
|
+
* The template used to render the component.
|
|
49
|
+
*/
|
|
38
50
|
this._template = null;
|
|
51
|
+
/**
|
|
52
|
+
* The current lifecycle stage of the controller.
|
|
53
|
+
*/
|
|
39
54
|
this.stage = 3 /* Stages.disconnected */;
|
|
40
55
|
/**
|
|
41
56
|
* A guard against connecting behaviors multiple times
|
|
@@ -43,12 +58,19 @@ export class ElementController extends PropertyChangeNotifier {
|
|
|
43
58
|
* another behavior during it's connectedCallback
|
|
44
59
|
*/
|
|
45
60
|
this.guardBehaviorConnection = false;
|
|
61
|
+
/**
|
|
62
|
+
* The behaviors associated with the component.
|
|
63
|
+
*/
|
|
46
64
|
this.behaviors = null;
|
|
47
65
|
/**
|
|
48
66
|
* Tracks whether behaviors are connected so that
|
|
49
67
|
* behaviors cant be connected multiple times
|
|
50
68
|
*/
|
|
51
69
|
this.behaviorsConnected = false;
|
|
70
|
+
/**
|
|
71
|
+
* The main set of styles used for the component, independent of any
|
|
72
|
+
* dynamically added styles.
|
|
73
|
+
*/
|
|
52
74
|
this._mainStyles = null;
|
|
53
75
|
/**
|
|
54
76
|
* This allows Observable.getNotifier(...) to return the Controller
|
|
@@ -144,6 +166,9 @@ export class ElementController extends PropertyChangeNotifier {
|
|
|
144
166
|
this.renderTemplate(value);
|
|
145
167
|
}
|
|
146
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* The shadow root options for the component.
|
|
171
|
+
*/
|
|
147
172
|
get shadowOptions() {
|
|
148
173
|
return this._shadowRootOptions;
|
|
149
174
|
}
|
|
@@ -318,6 +343,9 @@ export class ElementController extends PropertyChangeNotifier {
|
|
|
318
343
|
this.stage = 1 /* Stages.connected */;
|
|
319
344
|
Observable.notify(this, isConnectedPropertyName);
|
|
320
345
|
}
|
|
346
|
+
/**
|
|
347
|
+
* Binds any observables that were set before upgrade.
|
|
348
|
+
*/
|
|
321
349
|
bindObservables() {
|
|
322
350
|
if (this.boundObservables !== null) {
|
|
323
351
|
const element = this.source;
|
|
@@ -330,6 +358,9 @@ export class ElementController extends PropertyChangeNotifier {
|
|
|
330
358
|
this.boundObservables = null;
|
|
331
359
|
}
|
|
332
360
|
}
|
|
361
|
+
/**
|
|
362
|
+
* Connects any existing behaviors on the associated element.
|
|
363
|
+
*/
|
|
333
364
|
connectBehaviors() {
|
|
334
365
|
if (this.behaviorsConnected === false) {
|
|
335
366
|
const behaviors = this.behaviors;
|
|
@@ -343,6 +374,9 @@ export class ElementController extends PropertyChangeNotifier {
|
|
|
343
374
|
this.behaviorsConnected = true;
|
|
344
375
|
}
|
|
345
376
|
}
|
|
377
|
+
/**
|
|
378
|
+
* Disconnects any behaviors on the associated element.
|
|
379
|
+
*/
|
|
346
380
|
disconnectBehaviors() {
|
|
347
381
|
if (this.behaviorsConnected === true) {
|
|
348
382
|
const behaviors = this.behaviors;
|
|
@@ -395,6 +429,13 @@ export class ElementController extends PropertyChangeNotifier {
|
|
|
395
429
|
}
|
|
396
430
|
return false;
|
|
397
431
|
}
|
|
432
|
+
/**
|
|
433
|
+
* Renders the provided template to the element.
|
|
434
|
+
*
|
|
435
|
+
* @param template - The template to render.
|
|
436
|
+
* @remarks
|
|
437
|
+
* If `null` is provided, any existing view will be removed.
|
|
438
|
+
*/
|
|
398
439
|
renderTemplate(template) {
|
|
399
440
|
var _a;
|
|
400
441
|
// When getting the host to render to, we start by looking
|
|
@@ -582,7 +623,15 @@ if (ElementStyles.supportsAdoptedStyleSheets) {
|
|
|
582
623
|
else {
|
|
583
624
|
ElementStyles.setDefaultStrategy(StyleElementStrategy);
|
|
584
625
|
}
|
|
626
|
+
/**
|
|
627
|
+
* The attribute used to defer hydration of an element.
|
|
628
|
+
* @public
|
|
629
|
+
*/
|
|
585
630
|
export const deferHydrationAttribute = "defer-hydration";
|
|
631
|
+
/**
|
|
632
|
+
* The attribute used to indicate that an element needs hydration.
|
|
633
|
+
* @public
|
|
634
|
+
*/
|
|
586
635
|
export const needsHydrationAttribute = "needs-hydration";
|
|
587
636
|
/**
|
|
588
637
|
* An ElementController capable of hydrating FAST elements from
|
|
@@ -591,6 +640,35 @@ export const needsHydrationAttribute = "needs-hydration";
|
|
|
591
640
|
* @beta
|
|
592
641
|
*/
|
|
593
642
|
export class HydratableElementController extends ElementController {
|
|
643
|
+
/**
|
|
644
|
+
* {@inheritdoc ElementController.shadowOptions}
|
|
645
|
+
*/
|
|
646
|
+
get shadowOptions() {
|
|
647
|
+
return super.shadowOptions;
|
|
648
|
+
}
|
|
649
|
+
set shadowOptions(value) {
|
|
650
|
+
super.shadowOptions = value;
|
|
651
|
+
if (this.hasExistingShadowRoot &&
|
|
652
|
+
this.definition.templateOptions === TemplateOptions.deferAndHydrate) {
|
|
653
|
+
this.source.toggleAttribute(deferHydrationAttribute, true);
|
|
654
|
+
this.source.toggleAttribute(needsHydrationAttribute, true);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* Adds the current element instance to the hydrating instances map
|
|
659
|
+
*/
|
|
660
|
+
addHydratingInstance() {
|
|
661
|
+
if (!HydratableElementController.hydratingInstances) {
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
const name = this.definition.name;
|
|
665
|
+
let instances = HydratableElementController.hydratingInstances.get(name);
|
|
666
|
+
if (!instances) {
|
|
667
|
+
instances = new Set();
|
|
668
|
+
HydratableElementController.hydratingInstances.set(name, instances);
|
|
669
|
+
}
|
|
670
|
+
instances.add(this.source);
|
|
671
|
+
}
|
|
594
672
|
/**
|
|
595
673
|
* Configure lifecycle callbacks for hydration events
|
|
596
674
|
*/
|
|
@@ -600,38 +678,47 @@ export class HydratableElementController extends ElementController {
|
|
|
600
678
|
}
|
|
601
679
|
static hydrationObserverHandler(records) {
|
|
602
680
|
for (const record of records) {
|
|
603
|
-
|
|
604
|
-
|
|
681
|
+
if (!record.target.hasAttribute(deferHydrationAttribute)) {
|
|
682
|
+
HydratableElementController.hydrationObserver.unobserve(record.target);
|
|
683
|
+
record.target.$fastController.connect();
|
|
684
|
+
}
|
|
605
685
|
}
|
|
606
686
|
}
|
|
607
687
|
/**
|
|
608
|
-
* Checks
|
|
688
|
+
* Checks to see if hydration is complete and if so, invokes the hydrationComplete callback.
|
|
689
|
+
* Then resets the ElementController strategy to the default so that future elements
|
|
690
|
+
* don't use the HydratableElementController.
|
|
691
|
+
*
|
|
692
|
+
* @param deadline - the idle deadline object
|
|
609
693
|
*/
|
|
610
|
-
static checkHydrationComplete() {
|
|
611
|
-
var _a, _b;
|
|
612
|
-
if (
|
|
613
|
-
|
|
694
|
+
static checkHydrationComplete(deadline) {
|
|
695
|
+
var _a, _b, _c;
|
|
696
|
+
if (deadline.didTimeout) {
|
|
697
|
+
HydratableElementController.idleCallbackId = requestIdleCallback(HydratableElementController.checkHydrationComplete, { timeout: 50 });
|
|
698
|
+
return;
|
|
614
699
|
}
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
element.toggleAttribute(deferHydrationAttribute, true);
|
|
621
|
-
element.toggleAttribute(needsHydrationAttribute, true);
|
|
700
|
+
// If there are no more hydrating instances, invoke the hydrationComplete callback
|
|
701
|
+
if (((_a = HydratableElementController.hydratingInstances) === null || _a === void 0 ? void 0 : _a.size) === 0) {
|
|
702
|
+
(_c = (_b = HydratableElementController.lifecycleCallbacks) === null || _b === void 0 ? void 0 : _b.hydrationComplete) === null || _c === void 0 ? void 0 : _c.call(_b);
|
|
703
|
+
// Reset to the default strategy after hydration is complete
|
|
704
|
+
ElementController.setStrategy(ElementController);
|
|
622
705
|
}
|
|
623
|
-
return super.forCustomElement(element, override);
|
|
624
706
|
}
|
|
707
|
+
/**
|
|
708
|
+
* Runs connected lifecycle behavior on the associated element.
|
|
709
|
+
*/
|
|
625
710
|
connect() {
|
|
626
|
-
var _a, _b, _c, _d, _e
|
|
711
|
+
var _a, _b, _c, _d, _e;
|
|
627
712
|
// Initialize needsHydration on first connect
|
|
628
|
-
|
|
629
|
-
this.needsHydration
|
|
630
|
-
|
|
713
|
+
this.needsHydration =
|
|
714
|
+
(_a = this.needsHydration) !== null && _a !== void 0 ? _a : this.source.hasAttribute(needsHydrationAttribute);
|
|
715
|
+
if (this.needsHydration) {
|
|
716
|
+
(_c = (_b = HydratableElementController.lifecycleCallbacks) === null || _b === void 0 ? void 0 : _b.elementWillHydrate) === null || _c === void 0 ? void 0 : _c.call(_b, this.definition.name);
|
|
631
717
|
}
|
|
632
718
|
// If the `defer-hydration` attribute exists on the source,
|
|
633
719
|
// wait for it to be removed before continuing connection behavior.
|
|
634
720
|
if (this.source.hasAttribute(deferHydrationAttribute)) {
|
|
721
|
+
this.addHydratingInstance();
|
|
635
722
|
HydratableElementController.hydrationObserver.observe(this.source, {
|
|
636
723
|
attributeFilter: [deferHydrationAttribute],
|
|
637
724
|
});
|
|
@@ -643,20 +730,19 @@ export class HydratableElementController extends ElementController {
|
|
|
643
730
|
// class
|
|
644
731
|
if (!this.needsHydration) {
|
|
645
732
|
super.connect();
|
|
733
|
+
this.removeHydratingInstance();
|
|
646
734
|
return;
|
|
647
735
|
}
|
|
648
736
|
if (this.stage !== 3 /* Stages.disconnected */) {
|
|
649
737
|
return;
|
|
650
738
|
}
|
|
651
|
-
// Callback: Before hydration has started
|
|
652
|
-
(_b = (_a = HydratableElementController.lifecycleCallbacks) === null || _a === void 0 ? void 0 : _a.elementWillHydrate) === null || _b === void 0 ? void 0 : _b.call(_a, this.definition.name);
|
|
653
739
|
this.stage = 0 /* Stages.connecting */;
|
|
654
740
|
this.bindObservables();
|
|
655
741
|
this.connectBehaviors();
|
|
656
|
-
const element = this.source;
|
|
657
|
-
const host = (_c = getShadowRoot(element)) !== null && _c !== void 0 ? _c : element;
|
|
658
742
|
if (this.template) {
|
|
659
743
|
if (isHydratable(this.template)) {
|
|
744
|
+
const element = this.source;
|
|
745
|
+
const host = (_d = getShadowRoot(element)) !== null && _d !== void 0 ? _d : element;
|
|
660
746
|
let firstChild = host.firstChild;
|
|
661
747
|
let lastChild = host.lastChild;
|
|
662
748
|
if (element.shadowRoot === null) {
|
|
@@ -671,7 +757,7 @@ export class HydratableElementController extends ElementController {
|
|
|
671
757
|
}
|
|
672
758
|
}
|
|
673
759
|
this.view = this.template.hydrate(firstChild, lastChild, element);
|
|
674
|
-
(
|
|
760
|
+
(_e = this.view) === null || _e === void 0 ? void 0 : _e.bind(this.source);
|
|
675
761
|
}
|
|
676
762
|
else {
|
|
677
763
|
this.renderTemplate(this.template);
|
|
@@ -681,18 +767,61 @@ export class HydratableElementController extends ElementController {
|
|
|
681
767
|
this.stage = 1 /* Stages.connected */;
|
|
682
768
|
this.source.removeAttribute(needsHydrationAttribute);
|
|
683
769
|
this.needsInitialization = this.needsHydration = false;
|
|
770
|
+
this.removeHydratingInstance();
|
|
684
771
|
Observable.notify(this, isConnectedPropertyName);
|
|
772
|
+
}
|
|
773
|
+
/**
|
|
774
|
+
* Removes the current element instance from the hydrating instances map
|
|
775
|
+
*/
|
|
776
|
+
removeHydratingInstance() {
|
|
777
|
+
var _a, _b;
|
|
778
|
+
if (!HydratableElementController.hydratingInstances) {
|
|
779
|
+
return;
|
|
780
|
+
}
|
|
781
|
+
const name = this.definition.name;
|
|
782
|
+
const instances = HydratableElementController.hydratingInstances.get(name);
|
|
685
783
|
// Callback: After hydration has finished
|
|
686
|
-
(
|
|
687
|
-
|
|
688
|
-
|
|
784
|
+
(_b = (_a = HydratableElementController.lifecycleCallbacks) === null || _a === void 0 ? void 0 : _a.elementDidHydrate) === null || _b === void 0 ? void 0 : _b.call(_a, this.definition.name);
|
|
785
|
+
if (instances) {
|
|
786
|
+
instances.delete(this.source);
|
|
787
|
+
if (!instances.size) {
|
|
788
|
+
HydratableElementController.hydratingInstances.delete(name);
|
|
789
|
+
}
|
|
790
|
+
if (HydratableElementController.idleCallbackId) {
|
|
791
|
+
cancelIdleCallback(HydratableElementController.idleCallbackId);
|
|
792
|
+
}
|
|
793
|
+
HydratableElementController.idleCallbackId = requestIdleCallback(HydratableElementController.checkHydrationComplete, { timeout: 50 });
|
|
794
|
+
}
|
|
689
795
|
}
|
|
796
|
+
/**
|
|
797
|
+
* Unregisters the hydration observer when the element is disconnected.
|
|
798
|
+
*/
|
|
690
799
|
disconnect() {
|
|
691
800
|
super.disconnect();
|
|
692
801
|
HydratableElementController.hydrationObserver.unobserve(this.source);
|
|
693
802
|
}
|
|
803
|
+
/**
|
|
804
|
+
* Sets the ElementController strategy to HydratableElementController.
|
|
805
|
+
* @remarks
|
|
806
|
+
* This method is typically called during application startup to enable
|
|
807
|
+
* hydration support for FAST elements.
|
|
808
|
+
*/
|
|
694
809
|
static install() {
|
|
695
810
|
ElementController.setStrategy(HydratableElementController);
|
|
696
811
|
}
|
|
697
812
|
}
|
|
698
813
|
HydratableElementController.hydrationObserver = new UnobservableMutationObserver(HydratableElementController.hydrationObserverHandler);
|
|
814
|
+
/**
|
|
815
|
+
* An idle callback ID used to track hydration completion
|
|
816
|
+
*/
|
|
817
|
+
HydratableElementController.idleCallbackId = null;
|
|
818
|
+
/**
|
|
819
|
+
* A map of element instances by the name of the custom element they are
|
|
820
|
+
* associated with. The key is the custom element name, and the value is the
|
|
821
|
+
* instances of hydratable elements which currently need to be hydrated.
|
|
822
|
+
*
|
|
823
|
+
* When all of the instances in the set have been hydrated, the set is
|
|
824
|
+
* cleared and removed from the map. If the map is empty, the
|
|
825
|
+
* hydrationComplete callback is invoked.
|
|
826
|
+
*/
|
|
827
|
+
HydratableElementController.hydratingInstances = new Map();
|
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
import { isFunction } from "../interfaces.js";
|
|
11
2
|
import { ElementController } from "./element-controller.js";
|
|
12
3
|
import { FASTElementDefinition, } from "./fast-definitions.js";
|
|
@@ -41,11 +32,21 @@ function compose(type, nameOrDef) {
|
|
|
41
32
|
return FASTElementDefinition.compose(this, type);
|
|
42
33
|
}
|
|
43
34
|
function defineAsync(type, nameOrDef) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
35
|
+
if (isFunction(type)) {
|
|
36
|
+
return new Promise(resolve => {
|
|
37
|
+
FASTElementDefinition.composeAsync(type, nameOrDef).then(value => {
|
|
38
|
+
resolve(value);
|
|
39
|
+
});
|
|
40
|
+
}).then(value => {
|
|
41
|
+
return value.define().type;
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return new Promise(resolve => {
|
|
45
|
+
FASTElementDefinition.composeAsync(this, type).then(value => {
|
|
46
|
+
resolve(value);
|
|
47
|
+
});
|
|
48
|
+
}).then(value => {
|
|
49
|
+
return value.define().type;
|
|
49
50
|
});
|
|
50
51
|
}
|
|
51
52
|
function define(type, nameOrDef) {
|
package/dist/esm/index.js
CHANGED
|
@@ -36,4 +36,4 @@ export { render, RenderBehavior, RenderDirective } from "./templating/render.js"
|
|
|
36
36
|
export { customElement, FASTElement } from "./components/fast-element.js";
|
|
37
37
|
export { FASTElementDefinition, fastElementRegistry, TemplateOptions, } from "./components/fast-definitions.js";
|
|
38
38
|
export { attr, AttributeConfiguration, AttributeDefinition, booleanConverter, nullableBooleanConverter, nullableNumberConverter, } from "./components/attributes.js";
|
|
39
|
-
export { ElementController, HydratableElementController, } from "./components/element-controller.js";
|
|
39
|
+
export { deferHydrationAttribute, ElementController, HydratableElementController, needsHydrationAttribute, } from "./components/element-controller.js";
|
package/dist/esm/polyfills.js
CHANGED
|
@@ -25,3 +25,36 @@
|
|
|
25
25
|
result.globalThis = result;
|
|
26
26
|
}
|
|
27
27
|
})();
|
|
28
|
+
(function requestIdleCallbackPolyfill() {
|
|
29
|
+
if ("requestIdleCallback" in globalThis) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* A polyfill for requestIdleCallback that falls back to setTimeout.
|
|
34
|
+
*
|
|
35
|
+
* @param callback - The function to call when the browser is idle.
|
|
36
|
+
* @param options - Options object that may contain a timeout property.
|
|
37
|
+
* @returns An ID that can be used to cancel the callback.
|
|
38
|
+
* @public
|
|
39
|
+
*/
|
|
40
|
+
globalThis.requestIdleCallback = function requestIdleCallback(callback, options) {
|
|
41
|
+
const start = Date.now();
|
|
42
|
+
return setTimeout(() => {
|
|
43
|
+
callback({
|
|
44
|
+
didTimeout: (options === null || options === void 0 ? void 0 : options.timeout)
|
|
45
|
+
? Date.now() - start >= options.timeout
|
|
46
|
+
: false,
|
|
47
|
+
timeRemaining: () => 0,
|
|
48
|
+
});
|
|
49
|
+
}, 1);
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* A polyfill for cancelIdleCallback that falls back to clearTimeout.
|
|
53
|
+
*
|
|
54
|
+
* @param id - The ID of the callback to cancel.
|
|
55
|
+
* @public
|
|
56
|
+
*/
|
|
57
|
+
globalThis.cancelIdleCallback = function cancelIdleCallback(id) {
|
|
58
|
+
clearTimeout(id);
|
|
59
|
+
};
|
|
60
|
+
})();
|