@microsoft/fast-element 1.7.2 → 1.10.0
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 +30 -0
- package/CHANGELOG.json +133 -1
- package/CHANGELOG.md +26 -2
- package/dist/dts/components/attributes.d.ts +1 -1
- package/dist/dts/components/controller.d.ts +6 -6
- package/dist/dts/components/fast-definitions.d.ts +5 -5
- package/dist/dts/components/fast-element.d.ts +2 -2
- package/dist/dts/dom.d.ts +4 -4
- package/dist/dts/index.d.ts +26 -26
- package/dist/dts/observation/behavior.d.ts +1 -1
- package/dist/dts/observation/observable.d.ts +51 -50
- package/dist/dts/platform.d.ts +37 -0
- package/dist/dts/styles/css-directive.d.ts +2 -2
- package/dist/dts/styles/css.d.ts +2 -2
- package/dist/dts/styles/element-styles.d.ts +1 -1
- package/dist/dts/templating/binding.d.ts +3 -3
- package/dist/dts/templating/children.d.ts +2 -2
- package/dist/dts/templating/compiler.d.ts +1 -1
- package/dist/dts/templating/html-directive.d.ts +1 -1
- package/dist/dts/templating/node-observation.d.ts +1 -1
- package/dist/dts/templating/ref.d.ts +2 -2
- package/dist/dts/templating/repeat.d.ts +6 -6
- package/dist/dts/templating/slotted.d.ts +2 -2
- package/dist/dts/templating/template.d.ts +3 -3
- package/dist/dts/templating/view.d.ts +2 -2
- package/dist/dts/templating/when.d.ts +2 -2
- package/dist/esm/components/attributes.js +2 -2
- package/dist/esm/components/controller.js +4 -4
- package/dist/esm/components/fast-definitions.js +31 -14
- package/dist/esm/components/fast-element.js +2 -2
- package/dist/esm/dom.js +55 -50
- package/dist/esm/index.js +24 -23
- package/dist/esm/interfaces.js +1 -0
- package/dist/esm/observation/array-change-records.js +1 -1
- package/dist/esm/observation/array-observer.js +4 -4
- package/dist/esm/observation/behavior.js +1 -0
- package/dist/esm/observation/notifier.js +2 -1
- package/dist/esm/observation/observable.js +245 -236
- package/dist/esm/platform.js +23 -0
- package/dist/esm/styles/css.js +2 -2
- package/dist/esm/styles/element-styles.js +1 -3
- package/dist/esm/templating/binding.js +5 -5
- package/dist/esm/templating/children.js +2 -2
- package/dist/esm/templating/compiler.js +3 -2
- package/dist/esm/templating/html-directive.js +1 -1
- package/dist/esm/templating/node-observation.js +2 -2
- package/dist/esm/templating/ref.js +1 -1
- package/dist/esm/templating/repeat.js +6 -6
- package/dist/esm/templating/slotted.js +2 -2
- package/dist/esm/templating/template.js +6 -6
- package/dist/fast-element.api.json +43 -48
- package/dist/fast-element.d.ts +53 -13
- package/dist/fast-element.js +423 -345
- package/dist/fast-element.min.js +1 -1
- package/docs/api-report.md +39 -12
- package/docs/guide/declaring-templates.md +1 -1
- package/docs/guide/next-steps.md +2 -4
- package/docs/guide/observables-and-state.md +10 -8
- package/docs/guide/using-directives.md +2 -2
- package/karma.conf.cjs +152 -0
- package/package.json +13 -11
package/dist/fast-element.js
CHANGED
|
@@ -41,6 +41,41 @@ if ($global.trustedTypes === void 0) {
|
|
|
41
41
|
createPolicy: (n, r) => r
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
|
+
|
|
45
|
+
const propConfig = {
|
|
46
|
+
configurable: false,
|
|
47
|
+
enumerable: false,
|
|
48
|
+
writable: false
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
if ($global.FAST === void 0) {
|
|
52
|
+
Reflect.defineProperty($global, "FAST", Object.assign({
|
|
53
|
+
value: Object.create(null)
|
|
54
|
+
}, propConfig));
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The FAST global.
|
|
58
|
+
* @internal
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
const FAST = $global.FAST;
|
|
63
|
+
|
|
64
|
+
if (FAST.getById === void 0) {
|
|
65
|
+
const storage = Object.create(null);
|
|
66
|
+
Reflect.defineProperty(FAST, "getById", Object.assign({
|
|
67
|
+
value(id, initialize) {
|
|
68
|
+
let found = storage[id];
|
|
69
|
+
|
|
70
|
+
if (found === void 0) {
|
|
71
|
+
found = initialize ? storage[id] = initialize() : null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return found;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
}, propConfig));
|
|
78
|
+
}
|
|
44
79
|
/**
|
|
45
80
|
* A readonly, empty array.
|
|
46
81
|
* @remarks
|
|
@@ -52,33 +87,75 @@ if ($global.trustedTypes === void 0) {
|
|
|
52
87
|
|
|
53
88
|
const emptyArray = Object.freeze([]);
|
|
54
89
|
|
|
55
|
-
const updateQueue =
|
|
56
|
-
/*
|
|
90
|
+
const updateQueue = $global.FAST.getById(1
|
|
91
|
+
/* updateQueue */
|
|
92
|
+
, () => {
|
|
93
|
+
const tasks = [];
|
|
94
|
+
const pendingErrors = [];
|
|
57
95
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
96
|
+
function throwFirstError() {
|
|
97
|
+
if (pendingErrors.length) {
|
|
98
|
+
throw pendingErrors.shift();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
62
101
|
|
|
63
|
-
|
|
102
|
+
function tryRunTask(task) {
|
|
103
|
+
try {
|
|
104
|
+
task.call();
|
|
105
|
+
} catch (error) {
|
|
106
|
+
pendingErrors.push(error);
|
|
107
|
+
setTimeout(throwFirstError, 0);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
64
110
|
|
|
65
|
-
|
|
111
|
+
function process() {
|
|
112
|
+
const capacity = 1024;
|
|
113
|
+
let index = 0;
|
|
66
114
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
115
|
+
while (index < tasks.length) {
|
|
116
|
+
tryRunTask(tasks[index]);
|
|
117
|
+
index++; // Prevent leaking memory for long chains of recursive calls to `DOM.queueUpdate`.
|
|
118
|
+
// If we call `DOM.queueUpdate` within a task scheduled by `DOM.queueUpdate`, the queue will
|
|
119
|
+
// grow, but to avoid an O(n) walk for every task we execute, we don't
|
|
120
|
+
// shift tasks off the queue after they have been executed.
|
|
121
|
+
// Instead, we periodically shift 1024 tasks off the queue.
|
|
122
|
+
|
|
123
|
+
if (index > capacity) {
|
|
124
|
+
// Manually shift all values starting at the index back to the
|
|
125
|
+
// beginning of the queue.
|
|
126
|
+
for (let scan = 0, newLength = tasks.length - index; scan < newLength; scan++) {
|
|
127
|
+
tasks[scan] = tasks[scan + index];
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
tasks.length -= index;
|
|
131
|
+
index = 0;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
tasks.length = 0;
|
|
70
136
|
}
|
|
71
|
-
}
|
|
72
137
|
|
|
73
|
-
function
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
138
|
+
function enqueue(callable) {
|
|
139
|
+
if (tasks.length < 1) {
|
|
140
|
+
$global.requestAnimationFrame(process);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
tasks.push(callable);
|
|
79
144
|
}
|
|
80
|
-
}
|
|
81
145
|
|
|
146
|
+
return Object.freeze({
|
|
147
|
+
enqueue,
|
|
148
|
+
process
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
/* eslint-disable */
|
|
152
|
+
|
|
153
|
+
const fastHTMLPolicy = $global.trustedTypes.createPolicy("fast-html", {
|
|
154
|
+
createHTML: html => html
|
|
155
|
+
});
|
|
156
|
+
/* eslint-enable */
|
|
157
|
+
|
|
158
|
+
let htmlPolicy = fastHTMLPolicy;
|
|
82
159
|
const marker = `fast-${Math.random().toString(36).substring(2, 8)}`;
|
|
83
160
|
/** @internal */
|
|
84
161
|
|
|
@@ -176,13 +253,7 @@ const DOM = Object.freeze({
|
|
|
176
253
|
* Schedules DOM update work in the next async batch.
|
|
177
254
|
* @param callable - The callable function or object to queue.
|
|
178
255
|
*/
|
|
179
|
-
queueUpdate
|
|
180
|
-
if (updateQueue.length < 1) {
|
|
181
|
-
window.requestAnimationFrame(DOM.processUpdates);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
updateQueue.push(callable);
|
|
185
|
-
},
|
|
256
|
+
queueUpdate: updateQueue.enqueue,
|
|
186
257
|
|
|
187
258
|
/**
|
|
188
259
|
* Immediately processes all work previously scheduled
|
|
@@ -191,40 +262,13 @@ const DOM = Object.freeze({
|
|
|
191
262
|
* This also forces nextUpdate promises
|
|
192
263
|
* to resolve.
|
|
193
264
|
*/
|
|
194
|
-
processUpdates
|
|
195
|
-
const capacity = 1024;
|
|
196
|
-
let index = 0;
|
|
197
|
-
|
|
198
|
-
while (index < updateQueue.length) {
|
|
199
|
-
tryRunTask(updateQueue[index]);
|
|
200
|
-
index++; // Prevent leaking memory for long chains of recursive calls to `DOM.queueUpdate`.
|
|
201
|
-
// If we call `DOM.queueUpdate` within a task scheduled by `DOM.queueUpdate`, the queue will
|
|
202
|
-
// grow, but to avoid an O(n) walk for every task we execute, we don't
|
|
203
|
-
// shift tasks off the queue after they have been executed.
|
|
204
|
-
// Instead, we periodically shift 1024 tasks off the queue.
|
|
205
|
-
|
|
206
|
-
if (index > capacity) {
|
|
207
|
-
// Manually shift all values starting at the index back to the
|
|
208
|
-
// beginning of the queue.
|
|
209
|
-
for (let scan = 0, newLength = updateQueue.length - index; scan < newLength; scan++) {
|
|
210
|
-
updateQueue[scan] = updateQueue[scan + index];
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
updateQueue.length -= index;
|
|
214
|
-
index = 0;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
updateQueue.length = 0;
|
|
219
|
-
},
|
|
265
|
+
processUpdates: updateQueue.process,
|
|
220
266
|
|
|
221
267
|
/**
|
|
222
268
|
* Resolves with the next DOM update.
|
|
223
269
|
*/
|
|
224
270
|
nextUpdate() {
|
|
225
|
-
return new Promise(
|
|
226
|
-
DOM.queueUpdate(resolve);
|
|
227
|
-
});
|
|
271
|
+
return new Promise(updateQueue.enqueue);
|
|
228
272
|
},
|
|
229
273
|
|
|
230
274
|
/**
|
|
@@ -484,69 +528,25 @@ class PropertyChangeNotifier {
|
|
|
484
528
|
|
|
485
529
|
}
|
|
486
530
|
|
|
487
|
-
const volatileRegex = /(:|&&|\|\||if)/;
|
|
488
|
-
const notifierLookup = new WeakMap();
|
|
489
|
-
const accessorLookup = new WeakMap();
|
|
490
|
-
let watcher = void 0;
|
|
491
|
-
|
|
492
|
-
let createArrayObserver = array => {
|
|
493
|
-
throw new Error("Must call enableArrayObservation before observing arrays.");
|
|
494
|
-
};
|
|
495
|
-
|
|
496
|
-
class DefaultObservableAccessor {
|
|
497
|
-
constructor(name) {
|
|
498
|
-
this.name = name;
|
|
499
|
-
this.field = `_${name}`;
|
|
500
|
-
this.callback = `${name}Changed`;
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
getValue(source) {
|
|
504
|
-
if (watcher !== void 0) {
|
|
505
|
-
watcher.watch(source, this.name);
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
return source[this.field];
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
setValue(source, newValue) {
|
|
512
|
-
const field = this.field;
|
|
513
|
-
const oldValue = source[field];
|
|
514
|
-
|
|
515
|
-
if (oldValue !== newValue) {
|
|
516
|
-
source[field] = newValue;
|
|
517
|
-
const callback = source[this.callback];
|
|
518
|
-
|
|
519
|
-
if (typeof callback === "function") {
|
|
520
|
-
callback.call(source, oldValue, newValue);
|
|
521
|
-
}
|
|
522
|
-
/* eslint-disable-next-line @typescript-eslint/no-use-before-define */
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
getNotifier(source).notify(this.name);
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
}
|
|
530
531
|
/**
|
|
531
532
|
* Common Observable APIs.
|
|
532
533
|
* @public
|
|
533
534
|
*/
|
|
534
535
|
|
|
536
|
+
const Observable = FAST.getById(2
|
|
537
|
+
/* observable */
|
|
538
|
+
, () => {
|
|
539
|
+
const volatileRegex = /(:|&&|\|\||if)/;
|
|
540
|
+
const notifierLookup = new WeakMap();
|
|
541
|
+
const accessorLookup = new WeakMap();
|
|
542
|
+
const queueUpdate = DOM.queueUpdate;
|
|
543
|
+
let watcher = void 0;
|
|
544
|
+
|
|
545
|
+
let createArrayObserver = array => {
|
|
546
|
+
throw new Error("Must call enableArrayObservation before observing arrays.");
|
|
547
|
+
};
|
|
535
548
|
|
|
536
|
-
|
|
537
|
-
/**
|
|
538
|
-
* @internal
|
|
539
|
-
* @param factory - The factory used to create array observers.
|
|
540
|
-
*/
|
|
541
|
-
setArrayObserverFactory(factory) {
|
|
542
|
-
createArrayObserver = factory;
|
|
543
|
-
},
|
|
544
|
-
|
|
545
|
-
/**
|
|
546
|
-
* Gets a notifier for an object or Array.
|
|
547
|
-
* @param source - The object or Array to get the notifier for.
|
|
548
|
-
*/
|
|
549
|
-
getNotifier(source) {
|
|
549
|
+
function getNotifier(source) {
|
|
550
550
|
let found = source.$fastController || notifierLookup.get(source);
|
|
551
551
|
|
|
552
552
|
if (found === void 0) {
|
|
@@ -558,68 +558,9 @@ const Observable = Object.freeze({
|
|
|
558
558
|
}
|
|
559
559
|
|
|
560
560
|
return found;
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
/**
|
|
564
|
-
* Records a property change for a source object.
|
|
565
|
-
* @param source - The object to record the change against.
|
|
566
|
-
* @param propertyName - The property to track as changed.
|
|
567
|
-
*/
|
|
568
|
-
track(source, propertyName) {
|
|
569
|
-
if (watcher !== void 0) {
|
|
570
|
-
watcher.watch(source, propertyName);
|
|
571
|
-
}
|
|
572
|
-
},
|
|
573
|
-
|
|
574
|
-
/**
|
|
575
|
-
* Notifies watchers that the currently executing property getter or function is volatile
|
|
576
|
-
* with respect to its observable dependencies.
|
|
577
|
-
*/
|
|
578
|
-
trackVolatile() {
|
|
579
|
-
if (watcher !== void 0) {
|
|
580
|
-
watcher.needsRefresh = true;
|
|
581
|
-
}
|
|
582
|
-
},
|
|
583
|
-
|
|
584
|
-
/**
|
|
585
|
-
* Notifies subscribers of a source object of changes.
|
|
586
|
-
* @param source - the object to notify of changes.
|
|
587
|
-
* @param args - The change args to pass to subscribers.
|
|
588
|
-
*/
|
|
589
|
-
notify(source, args) {
|
|
590
|
-
/* eslint-disable-next-line @typescript-eslint/no-use-before-define */
|
|
591
|
-
getNotifier(source).notify(args);
|
|
592
|
-
},
|
|
593
|
-
|
|
594
|
-
/**
|
|
595
|
-
* Defines an observable property on an object or prototype.
|
|
596
|
-
* @param target - The target object to define the observable on.
|
|
597
|
-
* @param nameOrAccessor - The name of the property to define as observable;
|
|
598
|
-
* or a custom accessor that specifies the property name and accessor implementation.
|
|
599
|
-
*/
|
|
600
|
-
defineProperty(target, nameOrAccessor) {
|
|
601
|
-
if (typeof nameOrAccessor === "string") {
|
|
602
|
-
nameOrAccessor = new DefaultObservableAccessor(nameOrAccessor);
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
this.getAccessors(target).push(nameOrAccessor);
|
|
606
|
-
Reflect.defineProperty(target, nameOrAccessor.name, {
|
|
607
|
-
enumerable: true,
|
|
608
|
-
get: function () {
|
|
609
|
-
return nameOrAccessor.getValue(this);
|
|
610
|
-
},
|
|
611
|
-
set: function (newValue) {
|
|
612
|
-
nameOrAccessor.setValue(this, newValue);
|
|
613
|
-
}
|
|
614
|
-
});
|
|
615
|
-
},
|
|
561
|
+
}
|
|
616
562
|
|
|
617
|
-
|
|
618
|
-
* Finds all the observable accessors defined on the target,
|
|
619
|
-
* including its prototype chain.
|
|
620
|
-
* @param target - The target object to search for accessor on.
|
|
621
|
-
*/
|
|
622
|
-
getAccessors(target) {
|
|
563
|
+
function getAccessors(target) {
|
|
623
564
|
let accessors = accessorLookup.get(target);
|
|
624
565
|
|
|
625
566
|
if (accessors === void 0) {
|
|
@@ -640,33 +581,255 @@ const Observable = Object.freeze({
|
|
|
640
581
|
}
|
|
641
582
|
|
|
642
583
|
return accessors;
|
|
643
|
-
}
|
|
584
|
+
}
|
|
644
585
|
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
586
|
+
class DefaultObservableAccessor {
|
|
587
|
+
constructor(name) {
|
|
588
|
+
this.name = name;
|
|
589
|
+
this.field = `_${name}`;
|
|
590
|
+
this.callback = `${name}Changed`;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
getValue(source) {
|
|
594
|
+
if (watcher !== void 0) {
|
|
595
|
+
watcher.watch(source, this.name);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
return source[this.field];
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
setValue(source, newValue) {
|
|
602
|
+
const field = this.field;
|
|
603
|
+
const oldValue = source[field];
|
|
604
|
+
|
|
605
|
+
if (oldValue !== newValue) {
|
|
606
|
+
source[field] = newValue;
|
|
607
|
+
const callback = source[this.callback];
|
|
608
|
+
|
|
609
|
+
if (typeof callback === "function") {
|
|
610
|
+
callback.call(source, oldValue, newValue);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
getNotifier(source).notify(this.name);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
656
616
|
|
|
657
|
-
/**
|
|
658
|
-
* Determines whether a binding expression is volatile and needs to have its dependency list re-evaluated
|
|
659
|
-
* on every evaluation of the value.
|
|
660
|
-
* @param binding - The binding to inspect.
|
|
661
|
-
*/
|
|
662
|
-
isVolatileBinding(binding) {
|
|
663
|
-
return volatileRegex.test(binding.toString());
|
|
664
617
|
}
|
|
665
618
|
|
|
619
|
+
class BindingObserverImplementation extends SubscriberSet {
|
|
620
|
+
constructor(binding, initialSubscriber, isVolatileBinding = false) {
|
|
621
|
+
super(binding, initialSubscriber);
|
|
622
|
+
this.binding = binding;
|
|
623
|
+
this.isVolatileBinding = isVolatileBinding;
|
|
624
|
+
this.needsRefresh = true;
|
|
625
|
+
this.needsQueue = true;
|
|
626
|
+
this.first = this;
|
|
627
|
+
this.last = null;
|
|
628
|
+
this.propertySource = void 0;
|
|
629
|
+
this.propertyName = void 0;
|
|
630
|
+
this.notifier = void 0;
|
|
631
|
+
this.next = void 0;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
observe(source, context) {
|
|
635
|
+
if (this.needsRefresh && this.last !== null) {
|
|
636
|
+
this.disconnect();
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
const previousWatcher = watcher;
|
|
640
|
+
watcher = this.needsRefresh ? this : void 0;
|
|
641
|
+
this.needsRefresh = this.isVolatileBinding;
|
|
642
|
+
const result = this.binding(source, context);
|
|
643
|
+
watcher = previousWatcher;
|
|
644
|
+
return result;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
disconnect() {
|
|
648
|
+
if (this.last !== null) {
|
|
649
|
+
let current = this.first;
|
|
650
|
+
|
|
651
|
+
while (current !== void 0) {
|
|
652
|
+
current.notifier.unsubscribe(this, current.propertyName);
|
|
653
|
+
current = current.next;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
this.last = null;
|
|
657
|
+
this.needsRefresh = this.needsQueue = true;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
watch(propertySource, propertyName) {
|
|
662
|
+
const prev = this.last;
|
|
663
|
+
const notifier = getNotifier(propertySource);
|
|
664
|
+
const current = prev === null ? this.first : {};
|
|
665
|
+
current.propertySource = propertySource;
|
|
666
|
+
current.propertyName = propertyName;
|
|
667
|
+
current.notifier = notifier;
|
|
668
|
+
notifier.subscribe(this, propertyName);
|
|
669
|
+
|
|
670
|
+
if (prev !== null) {
|
|
671
|
+
if (!this.needsRefresh) {
|
|
672
|
+
// Declaring the variable prior to assignment below circumvents
|
|
673
|
+
// a bug in Angular's optimization process causing infinite recursion
|
|
674
|
+
// of this watch() method. Details https://github.com/microsoft/fast/issues/4969
|
|
675
|
+
let prevValue;
|
|
676
|
+
watcher = void 0;
|
|
677
|
+
/* eslint-disable-next-line */
|
|
678
|
+
|
|
679
|
+
prevValue = prev.propertySource[prev.propertyName];
|
|
680
|
+
/* eslint-disable-next-line @typescript-eslint/no-this-alias */
|
|
681
|
+
|
|
682
|
+
watcher = this;
|
|
683
|
+
|
|
684
|
+
if (propertySource === prevValue) {
|
|
685
|
+
this.needsRefresh = true;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
prev.next = current;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
this.last = current;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
handleChange() {
|
|
696
|
+
if (this.needsQueue) {
|
|
697
|
+
this.needsQueue = false;
|
|
698
|
+
queueUpdate(this);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
call() {
|
|
703
|
+
if (this.last !== null) {
|
|
704
|
+
this.needsQueue = true;
|
|
705
|
+
this.notify(this);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
records() {
|
|
710
|
+
let next = this.first;
|
|
711
|
+
return {
|
|
712
|
+
next: () => {
|
|
713
|
+
const current = next;
|
|
714
|
+
|
|
715
|
+
if (current === undefined) {
|
|
716
|
+
return {
|
|
717
|
+
value: void 0,
|
|
718
|
+
done: true
|
|
719
|
+
};
|
|
720
|
+
} else {
|
|
721
|
+
next = next.next;
|
|
722
|
+
return {
|
|
723
|
+
value: current,
|
|
724
|
+
done: false
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
},
|
|
728
|
+
[Symbol.iterator]: function () {
|
|
729
|
+
return this;
|
|
730
|
+
}
|
|
731
|
+
};
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
return Object.freeze({
|
|
737
|
+
/**
|
|
738
|
+
* @internal
|
|
739
|
+
* @param factory - The factory used to create array observers.
|
|
740
|
+
*/
|
|
741
|
+
setArrayObserverFactory(factory) {
|
|
742
|
+
createArrayObserver = factory;
|
|
743
|
+
},
|
|
744
|
+
|
|
745
|
+
/**
|
|
746
|
+
* Gets a notifier for an object or Array.
|
|
747
|
+
* @param source - The object or Array to get the notifier for.
|
|
748
|
+
*/
|
|
749
|
+
getNotifier,
|
|
750
|
+
|
|
751
|
+
/**
|
|
752
|
+
* Records a property change for a source object.
|
|
753
|
+
* @param source - The object to record the change against.
|
|
754
|
+
* @param propertyName - The property to track as changed.
|
|
755
|
+
*/
|
|
756
|
+
track(source, propertyName) {
|
|
757
|
+
if (watcher !== void 0) {
|
|
758
|
+
watcher.watch(source, propertyName);
|
|
759
|
+
}
|
|
760
|
+
},
|
|
761
|
+
|
|
762
|
+
/**
|
|
763
|
+
* Notifies watchers that the currently executing property getter or function is volatile
|
|
764
|
+
* with respect to its observable dependencies.
|
|
765
|
+
*/
|
|
766
|
+
trackVolatile() {
|
|
767
|
+
if (watcher !== void 0) {
|
|
768
|
+
watcher.needsRefresh = true;
|
|
769
|
+
}
|
|
770
|
+
},
|
|
771
|
+
|
|
772
|
+
/**
|
|
773
|
+
* Notifies subscribers of a source object of changes.
|
|
774
|
+
* @param source - the object to notify of changes.
|
|
775
|
+
* @param args - The change args to pass to subscribers.
|
|
776
|
+
*/
|
|
777
|
+
notify(source, args) {
|
|
778
|
+
getNotifier(source).notify(args);
|
|
779
|
+
},
|
|
780
|
+
|
|
781
|
+
/**
|
|
782
|
+
* Defines an observable property on an object or prototype.
|
|
783
|
+
* @param target - The target object to define the observable on.
|
|
784
|
+
* @param nameOrAccessor - The name of the property to define as observable;
|
|
785
|
+
* or a custom accessor that specifies the property name and accessor implementation.
|
|
786
|
+
*/
|
|
787
|
+
defineProperty(target, nameOrAccessor) {
|
|
788
|
+
if (typeof nameOrAccessor === "string") {
|
|
789
|
+
nameOrAccessor = new DefaultObservableAccessor(nameOrAccessor);
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
getAccessors(target).push(nameOrAccessor);
|
|
793
|
+
Reflect.defineProperty(target, nameOrAccessor.name, {
|
|
794
|
+
enumerable: true,
|
|
795
|
+
get: function () {
|
|
796
|
+
return nameOrAccessor.getValue(this);
|
|
797
|
+
},
|
|
798
|
+
set: function (newValue) {
|
|
799
|
+
nameOrAccessor.setValue(this, newValue);
|
|
800
|
+
}
|
|
801
|
+
});
|
|
802
|
+
},
|
|
803
|
+
|
|
804
|
+
/**
|
|
805
|
+
* Finds all the observable accessors defined on the target,
|
|
806
|
+
* including its prototype chain.
|
|
807
|
+
* @param target - The target object to search for accessor on.
|
|
808
|
+
*/
|
|
809
|
+
getAccessors,
|
|
810
|
+
|
|
811
|
+
/**
|
|
812
|
+
* Creates a {@link BindingObserver} that can watch the
|
|
813
|
+
* provided {@link Binding} for changes.
|
|
814
|
+
* @param binding - The binding to observe.
|
|
815
|
+
* @param initialSubscriber - An initial subscriber to changes in the binding value.
|
|
816
|
+
* @param isVolatileBinding - Indicates whether the binding's dependency list must be re-evaluated on every value evaluation.
|
|
817
|
+
*/
|
|
818
|
+
binding(binding, initialSubscriber, isVolatileBinding = this.isVolatileBinding(binding)) {
|
|
819
|
+
return new BindingObserverImplementation(binding, initialSubscriber, isVolatileBinding);
|
|
820
|
+
},
|
|
821
|
+
|
|
822
|
+
/**
|
|
823
|
+
* Determines whether a binding expression is volatile and needs to have its dependency list re-evaluated
|
|
824
|
+
* on every evaluation of the value.
|
|
825
|
+
* @param binding - The binding to inspect.
|
|
826
|
+
*/
|
|
827
|
+
isVolatileBinding(binding) {
|
|
828
|
+
return volatileRegex.test(binding.toString());
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
});
|
|
666
832
|
});
|
|
667
|
-
const getNotifier = Observable.getNotifier;
|
|
668
|
-
const trackVolatile = Observable.trackVolatile;
|
|
669
|
-
const queueUpdate = DOM.queueUpdate;
|
|
670
833
|
/**
|
|
671
834
|
* Decorator: Defines an observable property on the target.
|
|
672
835
|
* @param target - The target to define the observable on.
|
|
@@ -688,20 +851,26 @@ function observable(target, nameOrAccessor) {
|
|
|
688
851
|
function volatile(target, name, descriptor) {
|
|
689
852
|
return Object.assign({}, descriptor, {
|
|
690
853
|
get: function () {
|
|
691
|
-
trackVolatile();
|
|
854
|
+
Observable.trackVolatile();
|
|
692
855
|
return descriptor.get.apply(this);
|
|
693
856
|
}
|
|
694
857
|
});
|
|
695
858
|
}
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
859
|
+
const contextEvent = FAST.getById(3
|
|
860
|
+
/* contextEvent */
|
|
861
|
+
, () => {
|
|
862
|
+
let current = null;
|
|
863
|
+
return {
|
|
864
|
+
get() {
|
|
865
|
+
return current;
|
|
866
|
+
},
|
|
701
867
|
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
}
|
|
868
|
+
set(event) {
|
|
869
|
+
current = event;
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
};
|
|
873
|
+
});
|
|
705
874
|
/**
|
|
706
875
|
* Provides additional contextual information available to behaviors and expressions.
|
|
707
876
|
* @public
|
|
@@ -735,7 +904,7 @@ class ExecutionContext {
|
|
|
735
904
|
|
|
736
905
|
|
|
737
906
|
get event() {
|
|
738
|
-
return
|
|
907
|
+
return contextEvent.get();
|
|
739
908
|
}
|
|
740
909
|
/**
|
|
741
910
|
* Indicates whether the current item within a repeat context
|
|
@@ -782,6 +951,16 @@ class ExecutionContext {
|
|
|
782
951
|
get isLast() {
|
|
783
952
|
return this.index === this.length - 1;
|
|
784
953
|
}
|
|
954
|
+
/**
|
|
955
|
+
* Sets the event for the current execution context.
|
|
956
|
+
* @param event - The event to set.
|
|
957
|
+
* @internal
|
|
958
|
+
*/
|
|
959
|
+
|
|
960
|
+
|
|
961
|
+
static setEvent(event) {
|
|
962
|
+
contextEvent.set(event);
|
|
963
|
+
}
|
|
785
964
|
|
|
786
965
|
}
|
|
787
966
|
Observable.defineProperty(ExecutionContext.prototype, "index");
|
|
@@ -793,127 +972,6 @@ Observable.defineProperty(ExecutionContext.prototype, "length");
|
|
|
793
972
|
|
|
794
973
|
const defaultExecutionContext = Object.seal(new ExecutionContext());
|
|
795
974
|
|
|
796
|
-
class BindingObserverImplementation extends SubscriberSet {
|
|
797
|
-
constructor(binding, initialSubscriber, isVolatileBinding = false) {
|
|
798
|
-
super(binding, initialSubscriber);
|
|
799
|
-
this.binding = binding;
|
|
800
|
-
this.isVolatileBinding = isVolatileBinding;
|
|
801
|
-
this.needsRefresh = true;
|
|
802
|
-
this.needsQueue = true;
|
|
803
|
-
this.first = this;
|
|
804
|
-
this.last = null;
|
|
805
|
-
this.propertySource = void 0;
|
|
806
|
-
this.propertyName = void 0;
|
|
807
|
-
this.notifier = void 0;
|
|
808
|
-
this.next = void 0;
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
observe(source, context) {
|
|
812
|
-
if (this.needsRefresh && this.last !== null) {
|
|
813
|
-
this.disconnect();
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
const previousWatcher = watcher;
|
|
817
|
-
watcher = this.needsRefresh ? this : void 0;
|
|
818
|
-
this.needsRefresh = this.isVolatileBinding;
|
|
819
|
-
const result = this.binding(source, context);
|
|
820
|
-
watcher = previousWatcher;
|
|
821
|
-
return result;
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
disconnect() {
|
|
825
|
-
if (this.last !== null) {
|
|
826
|
-
let current = this.first;
|
|
827
|
-
|
|
828
|
-
while (current !== void 0) {
|
|
829
|
-
current.notifier.unsubscribe(this, current.propertyName);
|
|
830
|
-
current = current.next;
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
this.last = null;
|
|
834
|
-
this.needsRefresh = this.needsQueue = true;
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
/** @internal */
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
watch(propertySource, propertyName) {
|
|
841
|
-
const prev = this.last;
|
|
842
|
-
const notifier = getNotifier(propertySource);
|
|
843
|
-
const current = prev === null ? this.first : {};
|
|
844
|
-
current.propertySource = propertySource;
|
|
845
|
-
current.propertyName = propertyName;
|
|
846
|
-
current.notifier = notifier;
|
|
847
|
-
notifier.subscribe(this, propertyName);
|
|
848
|
-
|
|
849
|
-
if (prev !== null) {
|
|
850
|
-
if (!this.needsRefresh) {
|
|
851
|
-
// Declaring the variable prior to assignment below circumvents
|
|
852
|
-
// a bug in Angular's optimization process causing infinite recursion
|
|
853
|
-
// of this watch() method. Details https://github.com/microsoft/fast/issues/4969
|
|
854
|
-
let prevValue;
|
|
855
|
-
watcher = void 0;
|
|
856
|
-
/* eslint-disable-next-line */
|
|
857
|
-
|
|
858
|
-
prevValue = prev.propertySource[prev.propertyName];
|
|
859
|
-
watcher = this;
|
|
860
|
-
|
|
861
|
-
if (propertySource === prevValue) {
|
|
862
|
-
this.needsRefresh = true;
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
prev.next = current;
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
this.last = current;
|
|
870
|
-
}
|
|
871
|
-
/** @internal */
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
handleChange() {
|
|
875
|
-
if (this.needsQueue) {
|
|
876
|
-
this.needsQueue = false;
|
|
877
|
-
queueUpdate(this);
|
|
878
|
-
}
|
|
879
|
-
}
|
|
880
|
-
/** @internal */
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
call() {
|
|
884
|
-
if (this.last !== null) {
|
|
885
|
-
this.needsQueue = true;
|
|
886
|
-
this.notify(this);
|
|
887
|
-
}
|
|
888
|
-
}
|
|
889
|
-
|
|
890
|
-
records() {
|
|
891
|
-
let next = this.first;
|
|
892
|
-
return {
|
|
893
|
-
next: () => {
|
|
894
|
-
const current = next;
|
|
895
|
-
|
|
896
|
-
if (current === undefined) {
|
|
897
|
-
return {
|
|
898
|
-
value: void 0,
|
|
899
|
-
done: true
|
|
900
|
-
};
|
|
901
|
-
} else {
|
|
902
|
-
next = next.next;
|
|
903
|
-
return {
|
|
904
|
-
value: current,
|
|
905
|
-
done: false
|
|
906
|
-
};
|
|
907
|
-
}
|
|
908
|
-
},
|
|
909
|
-
[Symbol.iterator]: function () {
|
|
910
|
-
return this;
|
|
911
|
-
}
|
|
912
|
-
};
|
|
913
|
-
}
|
|
914
|
-
|
|
915
|
-
}
|
|
916
|
-
|
|
917
975
|
/**
|
|
918
976
|
* Instructs the template engine to apply behavior to a node.
|
|
919
977
|
* @public
|
|
@@ -1276,9 +1334,9 @@ class BindingBehavior {
|
|
|
1276
1334
|
|
|
1277
1335
|
|
|
1278
1336
|
handleEvent(event) {
|
|
1279
|
-
|
|
1337
|
+
ExecutionContext.setEvent(event);
|
|
1280
1338
|
const result = this.binding(this.source, this.context);
|
|
1281
|
-
|
|
1339
|
+
ExecutionContext.setEvent(null);
|
|
1282
1340
|
|
|
1283
1341
|
if (result !== true) {
|
|
1284
1342
|
event.preventDefault();
|
|
@@ -1306,6 +1364,7 @@ class CompilationContext {
|
|
|
1306
1364
|
}
|
|
1307
1365
|
|
|
1308
1366
|
release() {
|
|
1367
|
+
/* eslint-disable-next-line @typescript-eslint/no-this-alias */
|
|
1309
1368
|
sharedContext = this;
|
|
1310
1369
|
}
|
|
1311
1370
|
|
|
@@ -1873,9 +1932,6 @@ function html(strings, ...values) {
|
|
|
1873
1932
|
class ElementStyles {
|
|
1874
1933
|
constructor() {
|
|
1875
1934
|
this.targets = new WeakSet();
|
|
1876
|
-
/** @internal */
|
|
1877
|
-
|
|
1878
|
-
this.behaviors = null;
|
|
1879
1935
|
}
|
|
1880
1936
|
/** @internal */
|
|
1881
1937
|
|
|
@@ -2274,7 +2330,26 @@ const defaultShadowOptions = {
|
|
|
2274
2330
|
mode: "open"
|
|
2275
2331
|
};
|
|
2276
2332
|
const defaultElementOptions = {};
|
|
2277
|
-
const
|
|
2333
|
+
const fastRegistry = FAST.getById(4
|
|
2334
|
+
/* elementRegistry */
|
|
2335
|
+
, () => {
|
|
2336
|
+
const typeToDefinition = new Map();
|
|
2337
|
+
return Object.freeze({
|
|
2338
|
+
register(definition) {
|
|
2339
|
+
if (typeToDefinition.has(definition.type)) {
|
|
2340
|
+
return false;
|
|
2341
|
+
}
|
|
2342
|
+
|
|
2343
|
+
typeToDefinition.set(definition.type, definition);
|
|
2344
|
+
return true;
|
|
2345
|
+
},
|
|
2346
|
+
|
|
2347
|
+
getByType(key) {
|
|
2348
|
+
return typeToDefinition.get(key);
|
|
2349
|
+
}
|
|
2350
|
+
|
|
2351
|
+
});
|
|
2352
|
+
});
|
|
2278
2353
|
/**
|
|
2279
2354
|
* Defines metadata for a FASTElement.
|
|
2280
2355
|
* @public
|
|
@@ -2317,6 +2392,14 @@ class FASTElementDefinition {
|
|
|
2317
2392
|
this.elementOptions = nameOrConfig.elementOptions === void 0 ? defaultElementOptions : Object.assign(Object.assign({}, defaultElementOptions), nameOrConfig.elementOptions);
|
|
2318
2393
|
this.styles = nameOrConfig.styles === void 0 ? void 0 : Array.isArray(nameOrConfig.styles) ? ElementStyles.create(nameOrConfig.styles) : nameOrConfig.styles instanceof ElementStyles ? nameOrConfig.styles : ElementStyles.create([nameOrConfig.styles]);
|
|
2319
2394
|
}
|
|
2395
|
+
/**
|
|
2396
|
+
* Indicates if this element has been defined in at least one registry.
|
|
2397
|
+
*/
|
|
2398
|
+
|
|
2399
|
+
|
|
2400
|
+
get isDefined() {
|
|
2401
|
+
return !!fastRegistry.getByType(this.type);
|
|
2402
|
+
}
|
|
2320
2403
|
/**
|
|
2321
2404
|
* Defines a custom element based on this definition.
|
|
2322
2405
|
* @param registry - The element registry to define the element in.
|
|
@@ -2326,7 +2409,7 @@ class FASTElementDefinition {
|
|
|
2326
2409
|
define(registry = customElements) {
|
|
2327
2410
|
const type = this.type;
|
|
2328
2411
|
|
|
2329
|
-
if (
|
|
2412
|
+
if (fastRegistry.register(this)) {
|
|
2330
2413
|
const attributes = this.attributes;
|
|
2331
2414
|
const proto = type.prototype;
|
|
2332
2415
|
|
|
@@ -2338,8 +2421,6 @@ class FASTElementDefinition {
|
|
|
2338
2421
|
value: this.observedAttributes,
|
|
2339
2422
|
enumerable: true
|
|
2340
2423
|
});
|
|
2341
|
-
fastDefinitions.set(type, this);
|
|
2342
|
-
this.isDefined = true;
|
|
2343
2424
|
}
|
|
2344
2425
|
|
|
2345
2426
|
if (!registry.get(this.name)) {
|
|
@@ -2348,17 +2429,14 @@ class FASTElementDefinition {
|
|
|
2348
2429
|
|
|
2349
2430
|
return this;
|
|
2350
2431
|
}
|
|
2351
|
-
/**
|
|
2352
|
-
* Gets the element definition associated with the specified type.
|
|
2353
|
-
* @param type - The custom element type to retrieve the definition for.
|
|
2354
|
-
*/
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
static forType(type) {
|
|
2358
|
-
return fastDefinitions.get(type);
|
|
2359
|
-
}
|
|
2360
2432
|
|
|
2361
2433
|
}
|
|
2434
|
+
/**
|
|
2435
|
+
* Gets the element definition associated with the specified type.
|
|
2436
|
+
* @param type - The custom element type to retrieve the definition for.
|
|
2437
|
+
*/
|
|
2438
|
+
|
|
2439
|
+
FASTElementDefinition.forType = fastRegistry.getByType;
|
|
2362
2440
|
|
|
2363
2441
|
const shadowRoots = new WeakMap();
|
|
2364
2442
|
const defaultEventOptions = {
|
|
@@ -4163,4 +4241,4 @@ function children(propertyOrOptions) {
|
|
|
4163
4241
|
return new AttachedBehaviorHTMLDirective("fast-children", ChildrenBehavior, propertyOrOptions);
|
|
4164
4242
|
}
|
|
4165
4243
|
|
|
4166
|
-
export { $global, AttachedBehaviorHTMLDirective, AttributeDefinition, BindingBehavior, CSSDirective, ChildrenBehavior, Controller, DOM, ElementStyles, ExecutionContext, FASTElement, FASTElementDefinition, HTMLBindingDirective, HTMLDirective, HTMLView, Observable, PropertyChangeNotifier, RefBehavior, RepeatBehavior, RepeatDirective, SlottedBehavior, SubscriberSet, TargetedHTMLDirective, ViewTemplate, attr, booleanConverter, children, compileTemplate, css, cssPartial, customElement, defaultExecutionContext, elements, emptyArray, enableArrayObservation, html, nullableNumberConverter, observable, ref, repeat,
|
|
4244
|
+
export { $global, AttachedBehaviorHTMLDirective, AttributeDefinition, BindingBehavior, CSSDirective, ChildrenBehavior, Controller, DOM, ElementStyles, ExecutionContext, FAST, FASTElement, FASTElementDefinition, HTMLBindingDirective, HTMLDirective, HTMLView, Observable, PropertyChangeNotifier, RefBehavior, RepeatBehavior, RepeatDirective, SlottedBehavior, SubscriberSet, TargetedHTMLDirective, ViewTemplate, attr, booleanConverter, children, compileTemplate, css, cssPartial, customElement, defaultExecutionContext, elements, emptyArray, enableArrayObservation, html, nullableNumberConverter, observable, ref, repeat, slotted, volatile, when };
|