@microsoft/fast-element 2.0.0-beta.2 → 2.0.0-beta.5
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 +147 -0
- package/CHANGELOG.md +42 -1
- package/dist/dts/components/fast-definitions.d.ts +9 -8
- package/dist/dts/components/fast-element.d.ts +12 -24
- package/dist/dts/context.d.ts +1 -1
- package/dist/dts/di/di.d.ts +858 -0
- package/dist/dts/hooks.d.ts +2 -2
- package/dist/dts/interfaces.d.ts +40 -7
- package/dist/dts/observation/observable.d.ts +19 -13
- package/dist/dts/styles/element-styles.d.ts +6 -0
- package/dist/dts/templating/binding-signal.d.ts +10 -27
- package/dist/dts/templating/binding-two-way.d.ts +16 -41
- package/dist/dts/templating/binding.d.ts +79 -118
- package/dist/dts/templating/html-directive.d.ts +31 -3
- package/dist/dts/templating/render.d.ts +277 -0
- package/dist/dts/templating/repeat.d.ts +12 -16
- package/dist/dts/templating/template.d.ts +3 -3
- package/dist/dts/templating/when.d.ts +3 -3
- package/dist/dts/testing/exports.d.ts +2 -0
- package/dist/dts/testing/fixture.d.ts +90 -0
- package/dist/dts/testing/timeout.d.ts +7 -0
- package/dist/esm/components/fast-definitions.js +25 -27
- package/dist/esm/components/fast-element.js +20 -11
- package/dist/esm/context.js +5 -1
- package/dist/esm/debug.js +36 -4
- package/dist/esm/di/di.js +1351 -0
- package/dist/esm/observation/arrays.js +303 -2
- package/dist/esm/observation/observable.js +11 -6
- package/dist/esm/platform.js +1 -1
- package/dist/esm/styles/element-styles.js +14 -0
- package/dist/esm/templating/binding-signal.js +56 -61
- package/dist/esm/templating/binding-two-way.js +56 -34
- package/dist/esm/templating/binding.js +137 -156
- package/dist/esm/templating/compiler.js +30 -7
- package/dist/esm/templating/html-directive.js +16 -2
- package/dist/esm/templating/render.js +392 -0
- package/dist/esm/templating/repeat.js +57 -40
- package/dist/esm/templating/template.js +8 -5
- package/dist/esm/templating/view.js +3 -1
- package/dist/esm/templating/when.js +5 -4
- package/dist/esm/testing/exports.js +2 -0
- package/dist/esm/testing/fixture.js +88 -0
- package/dist/esm/testing/timeout.js +24 -0
- package/dist/fast-element.api.json +2828 -2758
- package/dist/fast-element.d.ts +218 -230
- package/dist/fast-element.debug.js +656 -257
- package/dist/fast-element.debug.min.js +1 -1
- package/dist/fast-element.js +620 -253
- package/dist/fast-element.min.js +1 -1
- package/dist/fast-element.untrimmed.d.ts +226 -235
- package/docs/api-report.md +88 -91
- package/package.json +15 -6
- package/dist/dts/observation/splice-strategies.d.ts +0 -13
- package/dist/esm/observation/splice-strategies.js +0 -400
|
@@ -97,19 +97,51 @@ const debugMessages = {
|
|
|
97
97
|
[1101 /* needsArrayObservation */]: "Must call enableArrayObservation before observing arrays.",
|
|
98
98
|
[1201 /* onlySetHTMLPolicyOnce */]: "The HTML policy can only be set once.",
|
|
99
99
|
[1202 /* bindingInnerHTMLRequiresTrustedTypes */]: "To bind innerHTML, you must use a TrustedTypesPolicy.",
|
|
100
|
+
[1203 /* twoWayBindingRequiresObservables */]: "View=>Model update skipped. To use twoWay binding, the target property must be observable.",
|
|
101
|
+
[1204 /* hostBindingWithoutHost */]: "No host element is present. Cannot bind host with ${name}.",
|
|
102
|
+
[1205 /* unsupportedBindingBehavior */]: "The requested binding behavior is not supported by the binding engine.",
|
|
100
103
|
[1401 /* missingElementDefinition */]: "Missing FASTElement definition.",
|
|
104
|
+
[1501 /* noRegistrationForContext */]: "No registration for Context/Interface '${name}'.",
|
|
105
|
+
[1502 /* noFactoryForResolver */]: "Dependency injection resolver for '${key}' returned a null factory.",
|
|
106
|
+
[1503 /* invalidResolverStrategy */]: "Invalid dependency injection resolver strategy specified '${strategy}'.",
|
|
107
|
+
[1504 /* cannotAutoregisterDependency */]: "Unable to autoregister dependency.",
|
|
108
|
+
[1505 /* cannotResolveKey */]: "Unable to resolve dependency injection key '${key}'.",
|
|
109
|
+
[1506 /* cannotConstructNativeFunction */]: "'${name}' is a native function and therefore cannot be safely constructed by DI. If this is intentional, please use a callback or cachedCallback resolver.",
|
|
110
|
+
[1507 /* cannotJITRegisterNonConstructor */]: "Attempted to jitRegister something that is not a constructor '${value}'. Did you forget to register this dependency?",
|
|
111
|
+
[1508 /* cannotJITRegisterIntrinsic */]: "Attempted to jitRegister an intrinsic type '${value}'. Did you forget to add @inject(Key)?",
|
|
112
|
+
[1509 /* cannotJITRegisterInterface */]: "Attempted to jitRegister an interface '${value}'.",
|
|
113
|
+
[1510 /* invalidResolver */]: "A valid resolver was not returned from the register method.",
|
|
114
|
+
[1511 /* invalidKey */]: "Key/value cannot be null or undefined. Are you trying to inject/register something that doesn't exist with DI?",
|
|
115
|
+
[1512 /* noDefaultResolver */]: "'${key}' not registered. Did you forget to add @singleton()?",
|
|
116
|
+
[1513 /* cyclicDependency */]: "Cyclic dependency found '${name}'.",
|
|
117
|
+
[1514 /* connectUpdateRequiresController */]: "Injected properties that are updated on changes to DOM connectivity require the target object to be an instance of FASTElement.",
|
|
101
118
|
};
|
|
119
|
+
const allPlaceholders = /(\$\{\w+?})/g;
|
|
120
|
+
const placeholder = /\$\{(\w+?)}/g;
|
|
121
|
+
const noValues = Object.freeze({});
|
|
122
|
+
function formatMessage(message, values) {
|
|
123
|
+
return message
|
|
124
|
+
.split(allPlaceholders)
|
|
125
|
+
.map(v => {
|
|
126
|
+
var _a;
|
|
127
|
+
const replaced = v.replace(placeholder, "$1");
|
|
128
|
+
return String((_a = values[replaced]) !== null && _a !== void 0 ? _a : v);
|
|
129
|
+
})
|
|
130
|
+
.join("");
|
|
131
|
+
}
|
|
102
132
|
Object.assign(FAST$1, {
|
|
103
133
|
addMessages(messages) {
|
|
104
134
|
Object.assign(debugMessages, messages);
|
|
105
135
|
},
|
|
106
|
-
warn(code,
|
|
136
|
+
warn(code, values = noValues) {
|
|
107
137
|
var _a;
|
|
108
|
-
|
|
138
|
+
const message = (_a = debugMessages[code]) !== null && _a !== void 0 ? _a : "Unknown Warning";
|
|
139
|
+
console.warn(formatMessage(message, values));
|
|
109
140
|
},
|
|
110
|
-
error(code,
|
|
141
|
+
error(code, values = noValues) {
|
|
111
142
|
var _a;
|
|
112
|
-
|
|
143
|
+
const message = (_a = debugMessages[code]) !== null && _a !== void 0 ? _a : "Unknown Error";
|
|
144
|
+
return new Error(formatMessage(message, values));
|
|
113
145
|
},
|
|
114
146
|
});
|
|
115
147
|
|
|
@@ -141,7 +173,7 @@ if (FAST.error === void 0) {
|
|
|
141
173
|
Object.assign(FAST, {
|
|
142
174
|
warn() { },
|
|
143
175
|
error(code) {
|
|
144
|
-
return new Error(`
|
|
176
|
+
return new Error(`Error ${code}`);
|
|
145
177
|
},
|
|
146
178
|
addMessages() { },
|
|
147
179
|
});
|
|
@@ -478,7 +510,7 @@ const Observable = FAST.getById(2 /* KernelServiceId.observable */, () => {
|
|
|
478
510
|
}
|
|
479
511
|
}
|
|
480
512
|
}
|
|
481
|
-
class
|
|
513
|
+
class ExpressionNotifierImplementation extends SubscriberSet {
|
|
482
514
|
constructor(binding, initialSubscriber, isVolatileBinding = false) {
|
|
483
515
|
super(binding, initialSubscriber);
|
|
484
516
|
this.binding = binding;
|
|
@@ -503,8 +535,13 @@ const Observable = FAST.getById(2 /* KernelServiceId.observable */, () => {
|
|
|
503
535
|
const previousWatcher = watcher;
|
|
504
536
|
watcher = this.needsRefresh ? this : void 0;
|
|
505
537
|
this.needsRefresh = this.isVolatileBinding;
|
|
506
|
-
|
|
507
|
-
|
|
538
|
+
let result;
|
|
539
|
+
try {
|
|
540
|
+
result = this.binding(source, context !== null && context !== void 0 ? context : ExecutionContext.default);
|
|
541
|
+
}
|
|
542
|
+
finally {
|
|
543
|
+
watcher = previousWatcher;
|
|
544
|
+
}
|
|
508
545
|
return result;
|
|
509
546
|
}
|
|
510
547
|
dispose() {
|
|
@@ -633,14 +670,14 @@ const Observable = FAST.getById(2 /* KernelServiceId.observable */, () => {
|
|
|
633
670
|
*/
|
|
634
671
|
getAccessors,
|
|
635
672
|
/**
|
|
636
|
-
* Creates a {@link
|
|
637
|
-
* provided {@link
|
|
673
|
+
* Creates a {@link ExpressionNotifier} that can watch the
|
|
674
|
+
* provided {@link Expression} for changes.
|
|
638
675
|
* @param binding - The binding to observe.
|
|
639
676
|
* @param initialSubscriber - An initial subscriber to changes in the binding value.
|
|
640
677
|
* @param isVolatileBinding - Indicates whether the binding's dependency list must be re-evaluated on every value evaluation.
|
|
641
678
|
*/
|
|
642
679
|
binding(binding, initialSubscriber, isVolatileBinding = this.isVolatileBinding(binding)) {
|
|
643
|
-
return new
|
|
680
|
+
return new ExpressionNotifierImplementation(binding, initialSubscriber, isVolatileBinding);
|
|
644
681
|
},
|
|
645
682
|
/**
|
|
646
683
|
* Determines whether a binding expression is volatile and needs to have its dependency list re-evaluated
|
|
@@ -874,10 +911,311 @@ const SpliceStrategySupport = Object.freeze({
|
|
|
874
911
|
const reset = new Splice(0, emptyArray, 0);
|
|
875
912
|
reset.reset = true;
|
|
876
913
|
const resetSplices = [reset];
|
|
914
|
+
// Note: This function is *based* on the computation of the Levenshtein
|
|
915
|
+
// "edit" distance. The one change is that "updates" are treated as two
|
|
916
|
+
// edits - not one. With Array splices, an update is really a delete
|
|
917
|
+
// followed by an add. By retaining this, we optimize for "keeping" the
|
|
918
|
+
// maximum array items in the original array. For example:
|
|
919
|
+
//
|
|
920
|
+
// 'xxxx123' to '123yyyy'
|
|
921
|
+
//
|
|
922
|
+
// With 1-edit updates, the shortest path would be just to update all seven
|
|
923
|
+
// characters. With 2-edit updates, we delete 4, leave 3, and add 4. This
|
|
924
|
+
// leaves the substring '123' intact.
|
|
925
|
+
function calcEditDistances(current, currentStart, currentEnd, old, oldStart, oldEnd) {
|
|
926
|
+
// "Deletion" columns
|
|
927
|
+
const rowCount = oldEnd - oldStart + 1;
|
|
928
|
+
const columnCount = currentEnd - currentStart + 1;
|
|
929
|
+
const distances = new Array(rowCount);
|
|
930
|
+
let north;
|
|
931
|
+
let west;
|
|
932
|
+
// "Addition" rows. Initialize null column.
|
|
933
|
+
for (let i = 0; i < rowCount; ++i) {
|
|
934
|
+
distances[i] = new Array(columnCount);
|
|
935
|
+
distances[i][0] = i;
|
|
936
|
+
}
|
|
937
|
+
// Initialize null row
|
|
938
|
+
for (let j = 0; j < columnCount; ++j) {
|
|
939
|
+
distances[0][j] = j;
|
|
940
|
+
}
|
|
941
|
+
for (let i = 1; i < rowCount; ++i) {
|
|
942
|
+
for (let j = 1; j < columnCount; ++j) {
|
|
943
|
+
if (current[currentStart + j - 1] === old[oldStart + i - 1]) {
|
|
944
|
+
distances[i][j] = distances[i - 1][j - 1];
|
|
945
|
+
}
|
|
946
|
+
else {
|
|
947
|
+
north = distances[i - 1][j] + 1;
|
|
948
|
+
west = distances[i][j - 1] + 1;
|
|
949
|
+
distances[i][j] = north < west ? north : west;
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
return distances;
|
|
954
|
+
}
|
|
955
|
+
// This starts at the final weight, and walks "backward" by finding
|
|
956
|
+
// the minimum previous weight recursively until the origin of the weight
|
|
957
|
+
// matrix.
|
|
958
|
+
function spliceOperationsFromEditDistances(distances) {
|
|
959
|
+
let i = distances.length - 1;
|
|
960
|
+
let j = distances[0].length - 1;
|
|
961
|
+
let current = distances[i][j];
|
|
962
|
+
const edits = [];
|
|
963
|
+
while (i > 0 || j > 0) {
|
|
964
|
+
if (i === 0) {
|
|
965
|
+
edits.push(2 /* Edit.add */);
|
|
966
|
+
j--;
|
|
967
|
+
continue;
|
|
968
|
+
}
|
|
969
|
+
if (j === 0) {
|
|
970
|
+
edits.push(3 /* Edit.delete */);
|
|
971
|
+
i--;
|
|
972
|
+
continue;
|
|
973
|
+
}
|
|
974
|
+
const northWest = distances[i - 1][j - 1];
|
|
975
|
+
const west = distances[i - 1][j];
|
|
976
|
+
const north = distances[i][j - 1];
|
|
977
|
+
let min;
|
|
978
|
+
if (west < north) {
|
|
979
|
+
min = west < northWest ? west : northWest;
|
|
980
|
+
}
|
|
981
|
+
else {
|
|
982
|
+
min = north < northWest ? north : northWest;
|
|
983
|
+
}
|
|
984
|
+
if (min === northWest) {
|
|
985
|
+
if (northWest === current) {
|
|
986
|
+
edits.push(0 /* Edit.leave */);
|
|
987
|
+
}
|
|
988
|
+
else {
|
|
989
|
+
edits.push(1 /* Edit.update */);
|
|
990
|
+
current = northWest;
|
|
991
|
+
}
|
|
992
|
+
i--;
|
|
993
|
+
j--;
|
|
994
|
+
}
|
|
995
|
+
else if (min === west) {
|
|
996
|
+
edits.push(3 /* Edit.delete */);
|
|
997
|
+
i--;
|
|
998
|
+
current = west;
|
|
999
|
+
}
|
|
1000
|
+
else {
|
|
1001
|
+
edits.push(2 /* Edit.add */);
|
|
1002
|
+
j--;
|
|
1003
|
+
current = north;
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
return edits.reverse();
|
|
1007
|
+
}
|
|
1008
|
+
function sharedPrefix(current, old, searchLength) {
|
|
1009
|
+
for (let i = 0; i < searchLength; ++i) {
|
|
1010
|
+
if (current[i] !== old[i]) {
|
|
1011
|
+
return i;
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
return searchLength;
|
|
1015
|
+
}
|
|
1016
|
+
function sharedSuffix(current, old, searchLength) {
|
|
1017
|
+
let index1 = current.length;
|
|
1018
|
+
let index2 = old.length;
|
|
1019
|
+
let count = 0;
|
|
1020
|
+
while (count < searchLength && current[--index1] === old[--index2]) {
|
|
1021
|
+
count++;
|
|
1022
|
+
}
|
|
1023
|
+
return count;
|
|
1024
|
+
}
|
|
1025
|
+
function intersect(start1, end1, start2, end2) {
|
|
1026
|
+
// Disjoint
|
|
1027
|
+
if (end1 < start2 || end2 < start1) {
|
|
1028
|
+
return -1;
|
|
1029
|
+
}
|
|
1030
|
+
// Adjacent
|
|
1031
|
+
if (end1 === start2 || end2 === start1) {
|
|
1032
|
+
return 0;
|
|
1033
|
+
}
|
|
1034
|
+
// Non-zero intersect, span1 first
|
|
1035
|
+
if (start1 < start2) {
|
|
1036
|
+
if (end1 < end2) {
|
|
1037
|
+
return end1 - start2; // Overlap
|
|
1038
|
+
}
|
|
1039
|
+
return end2 - start2; // Contained
|
|
1040
|
+
}
|
|
1041
|
+
// Non-zero intersect, span2 first
|
|
1042
|
+
if (end2 < end1) {
|
|
1043
|
+
return end2 - start1; // Overlap
|
|
1044
|
+
}
|
|
1045
|
+
return end1 - start1; // Contained
|
|
1046
|
+
}
|
|
1047
|
+
/**
|
|
1048
|
+
* @remarks
|
|
1049
|
+
* Lacking individual splice mutation information, the minimal set of
|
|
1050
|
+
* splices can be synthesized given the previous state and final state of an
|
|
1051
|
+
* array. The basic approach is to calculate the edit distance matrix and
|
|
1052
|
+
* choose the shortest path through it.
|
|
1053
|
+
*
|
|
1054
|
+
* Complexity: O(l * p)
|
|
1055
|
+
* l: The length of the current array
|
|
1056
|
+
* p: The length of the old array
|
|
1057
|
+
*/
|
|
1058
|
+
function calc(current, currentStart, currentEnd, old, oldStart, oldEnd) {
|
|
1059
|
+
let prefixCount = 0;
|
|
1060
|
+
let suffixCount = 0;
|
|
1061
|
+
const minLength = Math.min(currentEnd - currentStart, oldEnd - oldStart);
|
|
1062
|
+
if (currentStart === 0 && oldStart === 0) {
|
|
1063
|
+
prefixCount = sharedPrefix(current, old, minLength);
|
|
1064
|
+
}
|
|
1065
|
+
if (currentEnd === current.length && oldEnd === old.length) {
|
|
1066
|
+
suffixCount = sharedSuffix(current, old, minLength - prefixCount);
|
|
1067
|
+
}
|
|
1068
|
+
currentStart += prefixCount;
|
|
1069
|
+
oldStart += prefixCount;
|
|
1070
|
+
currentEnd -= suffixCount;
|
|
1071
|
+
oldEnd -= suffixCount;
|
|
1072
|
+
if (currentEnd - currentStart === 0 && oldEnd - oldStart === 0) {
|
|
1073
|
+
return emptyArray;
|
|
1074
|
+
}
|
|
1075
|
+
if (currentStart === currentEnd) {
|
|
1076
|
+
const splice = new Splice(currentStart, [], 0);
|
|
1077
|
+
while (oldStart < oldEnd) {
|
|
1078
|
+
splice.removed.push(old[oldStart++]);
|
|
1079
|
+
}
|
|
1080
|
+
return [splice];
|
|
1081
|
+
}
|
|
1082
|
+
else if (oldStart === oldEnd) {
|
|
1083
|
+
return [new Splice(currentStart, [], currentEnd - currentStart)];
|
|
1084
|
+
}
|
|
1085
|
+
const ops = spliceOperationsFromEditDistances(calcEditDistances(current, currentStart, currentEnd, old, oldStart, oldEnd));
|
|
1086
|
+
const splices = [];
|
|
1087
|
+
let splice = void 0;
|
|
1088
|
+
let index = currentStart;
|
|
1089
|
+
let oldIndex = oldStart;
|
|
1090
|
+
for (let i = 0; i < ops.length; ++i) {
|
|
1091
|
+
switch (ops[i]) {
|
|
1092
|
+
case 0 /* Edit.leave */:
|
|
1093
|
+
if (splice !== void 0) {
|
|
1094
|
+
splices.push(splice);
|
|
1095
|
+
splice = void 0;
|
|
1096
|
+
}
|
|
1097
|
+
index++;
|
|
1098
|
+
oldIndex++;
|
|
1099
|
+
break;
|
|
1100
|
+
case 1 /* Edit.update */:
|
|
1101
|
+
if (splice === void 0) {
|
|
1102
|
+
splice = new Splice(index, [], 0);
|
|
1103
|
+
}
|
|
1104
|
+
splice.addedCount++;
|
|
1105
|
+
index++;
|
|
1106
|
+
splice.removed.push(old[oldIndex]);
|
|
1107
|
+
oldIndex++;
|
|
1108
|
+
break;
|
|
1109
|
+
case 2 /* Edit.add */:
|
|
1110
|
+
if (splice === void 0) {
|
|
1111
|
+
splice = new Splice(index, [], 0);
|
|
1112
|
+
}
|
|
1113
|
+
splice.addedCount++;
|
|
1114
|
+
index++;
|
|
1115
|
+
break;
|
|
1116
|
+
case 3 /* Edit.delete */:
|
|
1117
|
+
if (splice === void 0) {
|
|
1118
|
+
splice = new Splice(index, [], 0);
|
|
1119
|
+
}
|
|
1120
|
+
splice.removed.push(old[oldIndex]);
|
|
1121
|
+
oldIndex++;
|
|
1122
|
+
break;
|
|
1123
|
+
// no default
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
if (splice !== void 0) {
|
|
1127
|
+
splices.push(splice);
|
|
1128
|
+
}
|
|
1129
|
+
return splices;
|
|
1130
|
+
}
|
|
1131
|
+
function merge(splice, splices) {
|
|
1132
|
+
let inserted = false;
|
|
1133
|
+
let insertionOffset = 0;
|
|
1134
|
+
for (let i = 0; i < splices.length; i++) {
|
|
1135
|
+
const current = splices[i];
|
|
1136
|
+
current.index += insertionOffset;
|
|
1137
|
+
if (inserted) {
|
|
1138
|
+
continue;
|
|
1139
|
+
}
|
|
1140
|
+
const intersectCount = intersect(splice.index, splice.index + splice.removed.length, current.index, current.index + current.addedCount);
|
|
1141
|
+
if (intersectCount >= 0) {
|
|
1142
|
+
// Merge the two splices
|
|
1143
|
+
splices.splice(i, 1);
|
|
1144
|
+
i--;
|
|
1145
|
+
insertionOffset -= current.addedCount - current.removed.length;
|
|
1146
|
+
splice.addedCount += current.addedCount - intersectCount;
|
|
1147
|
+
const deleteCount = splice.removed.length + current.removed.length - intersectCount;
|
|
1148
|
+
if (!splice.addedCount && !deleteCount) {
|
|
1149
|
+
// merged splice is a noop. discard.
|
|
1150
|
+
inserted = true;
|
|
1151
|
+
}
|
|
1152
|
+
else {
|
|
1153
|
+
let currentRemoved = current.removed;
|
|
1154
|
+
if (splice.index < current.index) {
|
|
1155
|
+
// some prefix of splice.removed is prepended to current.removed.
|
|
1156
|
+
const prepend = splice.removed.slice(0, current.index - splice.index);
|
|
1157
|
+
prepend.push(...currentRemoved);
|
|
1158
|
+
currentRemoved = prepend;
|
|
1159
|
+
}
|
|
1160
|
+
if (splice.index + splice.removed.length >
|
|
1161
|
+
current.index + current.addedCount) {
|
|
1162
|
+
// some suffix of splice.removed is appended to current.removed.
|
|
1163
|
+
const append = splice.removed.slice(current.index + current.addedCount - splice.index);
|
|
1164
|
+
currentRemoved.push(...append);
|
|
1165
|
+
}
|
|
1166
|
+
splice.removed = currentRemoved;
|
|
1167
|
+
if (current.index < splice.index) {
|
|
1168
|
+
splice.index = current.index;
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
else if (splice.index < current.index) {
|
|
1173
|
+
// Insert splice here.
|
|
1174
|
+
inserted = true;
|
|
1175
|
+
splices.splice(i, 0, splice);
|
|
1176
|
+
i++;
|
|
1177
|
+
const offset = splice.addedCount - splice.removed.length;
|
|
1178
|
+
current.index += offset;
|
|
1179
|
+
insertionOffset += offset;
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
if (!inserted) {
|
|
1183
|
+
splices.push(splice);
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
function project(array, changes) {
|
|
1187
|
+
let splices = [];
|
|
1188
|
+
const initialSplices = [];
|
|
1189
|
+
for (let i = 0, ii = changes.length; i < ii; i++) {
|
|
1190
|
+
merge(changes[i], initialSplices);
|
|
1191
|
+
}
|
|
1192
|
+
for (let i = 0, ii = initialSplices.length; i < ii; ++i) {
|
|
1193
|
+
const splice = initialSplices[i];
|
|
1194
|
+
if (splice.addedCount === 1 && splice.removed.length === 1) {
|
|
1195
|
+
if (splice.removed[0] !== array[splice.index]) {
|
|
1196
|
+
splices.push(splice);
|
|
1197
|
+
}
|
|
1198
|
+
continue;
|
|
1199
|
+
}
|
|
1200
|
+
splices = splices.concat(calc(array, splice.index, splice.index + splice.addedCount, splice.removed, 0, splice.removed.length));
|
|
1201
|
+
}
|
|
1202
|
+
return splices;
|
|
1203
|
+
}
|
|
1204
|
+
/**
|
|
1205
|
+
* A SpliceStrategy that attempts to merge all splices into the minimal set of
|
|
1206
|
+
* splices needed to represent the change from the old array to the new array.
|
|
1207
|
+
* @public
|
|
1208
|
+
*/
|
|
877
1209
|
let defaultSpliceStrategy = Object.freeze({
|
|
878
|
-
support: SpliceStrategySupport.
|
|
1210
|
+
support: SpliceStrategySupport.optimized,
|
|
879
1211
|
normalize(previous, current, changes) {
|
|
880
|
-
|
|
1212
|
+
if (previous === void 0) {
|
|
1213
|
+
if (changes === void 0) {
|
|
1214
|
+
return emptyArray;
|
|
1215
|
+
}
|
|
1216
|
+
return changes.length > 1 ? project(current, changes) : changes;
|
|
1217
|
+
}
|
|
1218
|
+
return resetSplices;
|
|
881
1219
|
},
|
|
882
1220
|
pop(array, observer, pop, args) {
|
|
883
1221
|
const notEmpty = array.length > 0;
|
|
@@ -1146,6 +1484,20 @@ class ElementStyles {
|
|
|
1146
1484
|
static setDefaultStrategy(Strategy) {
|
|
1147
1485
|
DefaultStyleStrategy = Strategy;
|
|
1148
1486
|
}
|
|
1487
|
+
/**
|
|
1488
|
+
* Normalizes a set of composable style options.
|
|
1489
|
+
* @param styles - The style options to normalize.
|
|
1490
|
+
* @returns A singular ElementStyles instance or undefined.
|
|
1491
|
+
*/
|
|
1492
|
+
static normalize(styles) {
|
|
1493
|
+
return styles === void 0
|
|
1494
|
+
? void 0
|
|
1495
|
+
: Array.isArray(styles)
|
|
1496
|
+
? new ElementStyles(styles)
|
|
1497
|
+
: styles instanceof ElementStyles
|
|
1498
|
+
? styles
|
|
1499
|
+
: new ElementStyles([styles]);
|
|
1500
|
+
}
|
|
1149
1501
|
}
|
|
1150
1502
|
/**
|
|
1151
1503
|
* Indicates whether the DOM supports the adoptedStyleSheets feature.
|
|
@@ -1472,6 +1824,13 @@ function htmlDirective(options) {
|
|
|
1472
1824
|
HTMLDirective.define(type, options);
|
|
1473
1825
|
};
|
|
1474
1826
|
}
|
|
1827
|
+
/**
|
|
1828
|
+
* Captures a binding expression along with related information and capabilities.
|
|
1829
|
+
*
|
|
1830
|
+
* @public
|
|
1831
|
+
*/
|
|
1832
|
+
class Binding {
|
|
1833
|
+
}
|
|
1475
1834
|
/**
|
|
1476
1835
|
* The type of HTML aspect to target.
|
|
1477
1836
|
* @public
|
|
@@ -1509,12 +1868,15 @@ const Aspect = Object.freeze({
|
|
|
1509
1868
|
*
|
|
1510
1869
|
* @param directive - The directive to assign the aspect to.
|
|
1511
1870
|
* @param value - The value to base the aspect determination on.
|
|
1871
|
+
* @remarks
|
|
1872
|
+
* If a falsy value is provided, then the content aspect will be assigned.
|
|
1512
1873
|
*/
|
|
1513
1874
|
assign(directive, value) {
|
|
1514
|
-
directive.sourceAspect = value;
|
|
1515
1875
|
if (!value) {
|
|
1876
|
+
directive.aspectType = Aspect.content;
|
|
1516
1877
|
return;
|
|
1517
1878
|
}
|
|
1879
|
+
directive.sourceAspect = value;
|
|
1518
1880
|
switch (value[0]) {
|
|
1519
1881
|
case ":":
|
|
1520
1882
|
directive.targetAspect = value.substring(1);
|
|
@@ -1562,6 +1924,10 @@ class StatelessAttachedAttributeDirective {
|
|
|
1562
1924
|
*/
|
|
1563
1925
|
constructor(options) {
|
|
1564
1926
|
this.options = options;
|
|
1927
|
+
/**
|
|
1928
|
+
* The unique id of the factory.
|
|
1929
|
+
*/
|
|
1930
|
+
this.id = nextId();
|
|
1565
1931
|
}
|
|
1566
1932
|
/**
|
|
1567
1933
|
* Creates a behavior.
|
|
@@ -1590,99 +1956,28 @@ const createInnerHTMLBinding = globalThis.TrustedHTML
|
|
|
1590
1956
|
throw FAST.error(1202 /* Message.bindingInnerHTMLRequiresTrustedTypes */);
|
|
1591
1957
|
}
|
|
1592
1958
|
: (binding) => binding;
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
/**
|
|
1599
|
-
* Creates a binding mode based on the supplied behavior types.
|
|
1600
|
-
* @param UpdateType - The base behavior type used to update aspects.
|
|
1601
|
-
* @param EventType - The base behavior type used to respond to events.
|
|
1602
|
-
* @returns A new binding mode.
|
|
1603
|
-
*/
|
|
1604
|
-
define(UpdateType, EventType = EventBinding) {
|
|
1605
|
-
return Object.freeze({
|
|
1606
|
-
[1]: d => new UpdateType(d, DOM.setAttribute),
|
|
1607
|
-
[2]: d => new UpdateType(d, DOM.setBooleanAttribute),
|
|
1608
|
-
[3]: d => new UpdateType(d, (t, a, v) => (t[a] = v)),
|
|
1609
|
-
[4]: d => new (createContentBinding(UpdateType))(d, updateContentTarget),
|
|
1610
|
-
[5]: d => new UpdateType(d, updateTokenListTarget),
|
|
1611
|
-
[6]: d => new EventType(d),
|
|
1612
|
-
});
|
|
1613
|
-
},
|
|
1614
|
-
});
|
|
1615
|
-
/**
|
|
1616
|
-
* Describes the configuration for a binding expression.
|
|
1617
|
-
* @public
|
|
1618
|
-
*/
|
|
1619
|
-
const BindingConfig = Object.freeze({
|
|
1620
|
-
/**
|
|
1621
|
-
* Creates a binding configuration based on the provided mode and options.
|
|
1622
|
-
* @param mode - The mode to use for the configuration.
|
|
1623
|
-
* @param defaultOptions - The default options to use for the configuration.
|
|
1624
|
-
* @returns A new binding configuration.
|
|
1625
|
-
*/
|
|
1626
|
-
define(mode, defaultOptions) {
|
|
1627
|
-
const config = (options) => {
|
|
1628
|
-
return {
|
|
1629
|
-
mode: config.mode,
|
|
1630
|
-
options: Object.assign({}, defaultOptions, options),
|
|
1631
|
-
};
|
|
1632
|
-
};
|
|
1633
|
-
config.options = defaultOptions;
|
|
1634
|
-
config.mode = mode;
|
|
1635
|
-
return config;
|
|
1636
|
-
},
|
|
1637
|
-
});
|
|
1638
|
-
/**
|
|
1639
|
-
* A base binding behavior for DOM updates.
|
|
1640
|
-
* @public
|
|
1641
|
-
*/
|
|
1642
|
-
class UpdateBinding {
|
|
1643
|
-
/**
|
|
1644
|
-
* Creates an instance of UpdateBinding.
|
|
1645
|
-
* @param directive - The directive that has the configuration for this behavior.
|
|
1646
|
-
* @param updateTarget - The function used to update the target with the latest value.
|
|
1647
|
-
*/
|
|
1648
|
-
constructor(directive, updateTarget) {
|
|
1649
|
-
this.directive = directive;
|
|
1650
|
-
this.updateTarget = updateTarget;
|
|
1959
|
+
class OnChangeBinding extends Binding {
|
|
1960
|
+
constructor(evaluate, isVolatile) {
|
|
1961
|
+
super();
|
|
1962
|
+
this.evaluate = evaluate;
|
|
1963
|
+
this.isVolatile = isVolatile;
|
|
1651
1964
|
}
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
* @param source - The source to bind to.
|
|
1655
|
-
* @param context - The execution context that the binding is operating within.
|
|
1656
|
-
* @param targets - The targets that behaviors in a view can attach to.
|
|
1657
|
-
*/
|
|
1658
|
-
bind(source, context, targets) { }
|
|
1659
|
-
/**
|
|
1660
|
-
* Unbinds this behavior from the source.
|
|
1661
|
-
* @param source - The source to unbind from.
|
|
1662
|
-
* @param context - The execution context that the binding is operating within.
|
|
1663
|
-
* @param targets - The targets that behaviors in a view can attach to.
|
|
1664
|
-
*/
|
|
1665
|
-
unbind(source, context, targets) { }
|
|
1666
|
-
/**
|
|
1667
|
-
* Creates a behavior.
|
|
1668
|
-
* @param targets - The targets available for behaviors to be attached to.
|
|
1669
|
-
*/
|
|
1670
|
-
createBehavior(targets) {
|
|
1671
|
-
return this;
|
|
1965
|
+
createObserver(_, subscriber) {
|
|
1966
|
+
return Observable.binding(this.evaluate, subscriber, this.isVolatile);
|
|
1672
1967
|
}
|
|
1673
1968
|
}
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
}
|
|
1969
|
+
class OneTimeBinding extends Binding {
|
|
1970
|
+
constructor(evaluate) {
|
|
1971
|
+
super();
|
|
1972
|
+
this.evaluate = evaluate;
|
|
1973
|
+
}
|
|
1974
|
+
createObserver() {
|
|
1975
|
+
return this;
|
|
1976
|
+
}
|
|
1977
|
+
observe(source, context) {
|
|
1978
|
+
return this.evaluate(source, context);
|
|
1979
|
+
}
|
|
1980
|
+
dispose() { }
|
|
1686
1981
|
}
|
|
1687
1982
|
function updateContentTarget(target, aspect, value, source, context) {
|
|
1688
1983
|
// If there's no actual value, then this equates to the
|
|
@@ -1690,7 +1985,7 @@ function updateContentTarget(target, aspect, value, source, context) {
|
|
|
1690
1985
|
if (value === null || value === undefined) {
|
|
1691
1986
|
value = "";
|
|
1692
1987
|
}
|
|
1693
|
-
// If the value has a "create" method, then it's a
|
|
1988
|
+
// If the value has a "create" method, then it's a ContentTemplate.
|
|
1694
1989
|
if (value.create) {
|
|
1695
1990
|
target.textContent = "";
|
|
1696
1991
|
let view = target.$fastView;
|
|
@@ -1776,46 +2071,21 @@ function updateTokenListTarget(target, aspect, value) {
|
|
|
1776
2071
|
}
|
|
1777
2072
|
}
|
|
1778
2073
|
}
|
|
1779
|
-
/**
|
|
1780
|
-
* A binding behavior for one-time bindings.
|
|
1781
|
-
* @public
|
|
1782
|
-
*/
|
|
1783
|
-
class OneTimeBinding extends UpdateBinding {
|
|
1784
|
-
/**
|
|
1785
|
-
* Bind this behavior to the source.
|
|
1786
|
-
* @param source - The source to bind to.
|
|
1787
|
-
* @param context - The execution context that the binding is operating within.
|
|
1788
|
-
* @param targets - The targets that behaviors in a view can attach to.
|
|
1789
|
-
*/
|
|
1790
|
-
bind(source, context, targets) {
|
|
1791
|
-
const directive = this.directive;
|
|
1792
|
-
this.updateTarget(targets[directive.nodeId], directive.targetAspect, directive.binding(source, context), source, context);
|
|
1793
|
-
}
|
|
1794
|
-
}
|
|
1795
2074
|
/**
|
|
1796
2075
|
* A binding behavior for bindings that change.
|
|
1797
2076
|
* @public
|
|
1798
2077
|
*/
|
|
1799
|
-
class
|
|
2078
|
+
class BindingBehavior {
|
|
1800
2079
|
/**
|
|
1801
2080
|
* Creates an instance of ChangeBinding.
|
|
1802
2081
|
* @param directive - The directive that has the configuration for this behavior.
|
|
1803
2082
|
* @param updateTarget - The function used to update the target with the latest value.
|
|
1804
2083
|
*/
|
|
1805
2084
|
constructor(directive, updateTarget) {
|
|
1806
|
-
|
|
1807
|
-
this.
|
|
2085
|
+
this.directive = directive;
|
|
2086
|
+
this.updateTarget = updateTarget;
|
|
1808
2087
|
this.observerProperty = `${directive.id}-o`;
|
|
1809
2088
|
}
|
|
1810
|
-
/**
|
|
1811
|
-
* Returns the binding observer used to update the node.
|
|
1812
|
-
* @param target - The target node.
|
|
1813
|
-
* @returns A BindingObserver.
|
|
1814
|
-
*/
|
|
1815
|
-
getObserver(target) {
|
|
1816
|
-
var _a;
|
|
1817
|
-
return ((_a = target[this.observerProperty]) !== null && _a !== void 0 ? _a : (target[this.observerProperty] = Observable.binding(this.directive.binding, this, this.isBindingVolatile)));
|
|
1818
|
-
}
|
|
1819
2089
|
/**
|
|
1820
2090
|
* Bind this behavior to the source.
|
|
1821
2091
|
* @param source - The source to bind to.
|
|
@@ -1852,12 +2122,49 @@ class ChangeBinding extends UpdateBinding {
|
|
|
1852
2122
|
const context = observer.context;
|
|
1853
2123
|
this.updateTarget(target, this.directive.targetAspect, observer.observe(source, context), source, context);
|
|
1854
2124
|
}
|
|
2125
|
+
/**
|
|
2126
|
+
* Returns the binding observer used to update the node.
|
|
2127
|
+
* @param target - The target node.
|
|
2128
|
+
* @returns A BindingObserver.
|
|
2129
|
+
*/
|
|
2130
|
+
getObserver(target) {
|
|
2131
|
+
var _a;
|
|
2132
|
+
return ((_a = target[this.observerProperty]) !== null && _a !== void 0 ? _a : (target[this.observerProperty] = this.directive.dataBinding.createObserver(this.directive, this)));
|
|
2133
|
+
}
|
|
2134
|
+
/**
|
|
2135
|
+
* Creates a behavior.
|
|
2136
|
+
* @param targets - The targets available for behaviors to be attached to.
|
|
2137
|
+
*/
|
|
2138
|
+
createBehavior(targets) {
|
|
2139
|
+
return this;
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
/**
|
|
2143
|
+
* A special binding behavior that can bind node content.
|
|
2144
|
+
* @public
|
|
2145
|
+
*/
|
|
2146
|
+
class ContentBehavior extends BindingBehavior {
|
|
2147
|
+
/**
|
|
2148
|
+
* Unbinds this behavior from the source.
|
|
2149
|
+
* @param source - The source to unbind from.
|
|
2150
|
+
* @param context - The execution context that the binding is operating within.
|
|
2151
|
+
* @param targets - The targets that behaviors in a view can attach to.
|
|
2152
|
+
*/
|
|
2153
|
+
unbind(source, context, targets) {
|
|
2154
|
+
super.unbind(source, context, targets);
|
|
2155
|
+
const target = targets[this.directive.nodeId];
|
|
2156
|
+
const view = target.$fastView;
|
|
2157
|
+
if (view !== void 0 && view.isComposed) {
|
|
2158
|
+
view.unbind();
|
|
2159
|
+
view.needsBindOnly = true;
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
1855
2162
|
}
|
|
1856
2163
|
/**
|
|
1857
2164
|
* A binding behavior for handling events.
|
|
1858
2165
|
* @public
|
|
1859
2166
|
*/
|
|
1860
|
-
class
|
|
2167
|
+
class EventBehavior {
|
|
1861
2168
|
/**
|
|
1862
2169
|
* Creates an instance of EventBinding.
|
|
1863
2170
|
* @param directive - The directive that has the configuration for this behavior.
|
|
@@ -1878,7 +2185,7 @@ class EventBinding {
|
|
|
1878
2185
|
const target = targets[directive.nodeId];
|
|
1879
2186
|
target[this.sourceProperty] = source;
|
|
1880
2187
|
target[this.contextProperty] = context;
|
|
1881
|
-
target.addEventListener(directive.targetAspect, this, directive.options);
|
|
2188
|
+
target.addEventListener(directive.targetAspect, this, directive.dataBinding.options);
|
|
1882
2189
|
}
|
|
1883
2190
|
/**
|
|
1884
2191
|
* Unbinds this behavior from the source.
|
|
@@ -1890,7 +2197,7 @@ class EventBinding {
|
|
|
1890
2197
|
const directive = this.directive;
|
|
1891
2198
|
const target = targets[directive.nodeId];
|
|
1892
2199
|
target[this.sourceProperty] = target[this.contextProperty] = null;
|
|
1893
|
-
target.removeEventListener(directive.targetAspect, this, directive.options);
|
|
2200
|
+
target.removeEventListener(directive.targetAspect, this, directive.dataBinding.options);
|
|
1894
2201
|
}
|
|
1895
2202
|
/**
|
|
1896
2203
|
* Creates a behavior.
|
|
@@ -1905,25 +2212,13 @@ class EventBinding {
|
|
|
1905
2212
|
handleEvent(event) {
|
|
1906
2213
|
const target = event.currentTarget;
|
|
1907
2214
|
ExecutionContext.setEvent(event);
|
|
1908
|
-
const result = this.directive.
|
|
2215
|
+
const result = this.directive.dataBinding.evaluate(target[this.sourceProperty], target[this.contextProperty]);
|
|
1909
2216
|
ExecutionContext.setEvent(null);
|
|
1910
2217
|
if (result !== true) {
|
|
1911
2218
|
event.preventDefault();
|
|
1912
2219
|
}
|
|
1913
2220
|
}
|
|
1914
2221
|
}
|
|
1915
|
-
/**
|
|
1916
|
-
* The default onChange binding configuration.
|
|
1917
|
-
* @public
|
|
1918
|
-
*/
|
|
1919
|
-
const onChange = BindingConfig.define(BindingMode.define(ChangeBinding), {});
|
|
1920
|
-
/**
|
|
1921
|
-
* The default onTime binding configuration.
|
|
1922
|
-
* @public
|
|
1923
|
-
*/
|
|
1924
|
-
const oneTime = BindingConfig.define(BindingMode.define(OneTimeBinding), {
|
|
1925
|
-
once: true,
|
|
1926
|
-
});
|
|
1927
2222
|
/**
|
|
1928
2223
|
* A directive that applies bindings.
|
|
1929
2224
|
* @public
|
|
@@ -1931,15 +2226,15 @@ const oneTime = BindingConfig.define(BindingMode.define(OneTimeBinding), {
|
|
|
1931
2226
|
class HTMLBindingDirective {
|
|
1932
2227
|
/**
|
|
1933
2228
|
* Creates an instance of HTMLBindingDirective.
|
|
1934
|
-
* @param
|
|
1935
|
-
* @param mode - The binding mode to use when applying the binding.
|
|
1936
|
-
* @param options - The options to configure the binding with.
|
|
2229
|
+
* @param dataBinding - The binding configuration to apply.
|
|
1937
2230
|
*/
|
|
1938
|
-
constructor(
|
|
1939
|
-
this.
|
|
1940
|
-
this.mode = mode;
|
|
1941
|
-
this.options = options;
|
|
2231
|
+
constructor(dataBinding) {
|
|
2232
|
+
this.dataBinding = dataBinding;
|
|
1942
2233
|
this.factory = null;
|
|
2234
|
+
/**
|
|
2235
|
+
* The unique id of the factory.
|
|
2236
|
+
*/
|
|
2237
|
+
this.id = nextId();
|
|
1943
2238
|
/**
|
|
1944
2239
|
* The type of aspect to target.
|
|
1945
2240
|
*/
|
|
@@ -1959,26 +2254,78 @@ class HTMLBindingDirective {
|
|
|
1959
2254
|
createBehavior(targets) {
|
|
1960
2255
|
if (this.factory == null) {
|
|
1961
2256
|
if (this.targetAspect === "innerHTML") {
|
|
1962
|
-
this.
|
|
2257
|
+
this.dataBinding.evaluate = createInnerHTMLBinding(this.dataBinding.evaluate);
|
|
2258
|
+
}
|
|
2259
|
+
switch (this.aspectType) {
|
|
2260
|
+
case 1:
|
|
2261
|
+
this.factory = new BindingBehavior(this, DOM.setAttribute);
|
|
2262
|
+
break;
|
|
2263
|
+
case 2:
|
|
2264
|
+
this.factory = new BindingBehavior(this, DOM.setBooleanAttribute);
|
|
2265
|
+
break;
|
|
2266
|
+
case 3:
|
|
2267
|
+
this.factory = new BindingBehavior(this, (t, a, v) => (t[a] = v));
|
|
2268
|
+
break;
|
|
2269
|
+
case 4:
|
|
2270
|
+
this.factory = new ContentBehavior(this, updateContentTarget);
|
|
2271
|
+
break;
|
|
2272
|
+
case 5:
|
|
2273
|
+
this.factory = new BindingBehavior(this, updateTokenListTarget);
|
|
2274
|
+
break;
|
|
2275
|
+
case 6:
|
|
2276
|
+
this.factory = new EventBehavior(this);
|
|
2277
|
+
break;
|
|
2278
|
+
default:
|
|
2279
|
+
throw FAST.error(1205 /* Message.unsupportedBindingBehavior */);
|
|
1963
2280
|
}
|
|
1964
|
-
this.factory = this.mode[this.aspectType](this);
|
|
1965
2281
|
}
|
|
1966
2282
|
return this.factory.createBehavior(targets);
|
|
1967
2283
|
}
|
|
1968
2284
|
}
|
|
1969
2285
|
HTMLDirective.define(HTMLBindingDirective, { aspected: true });
|
|
1970
2286
|
/**
|
|
1971
|
-
* Creates
|
|
1972
|
-
* @param binding - The binding
|
|
1973
|
-
* @param
|
|
1974
|
-
* @returns A binding
|
|
2287
|
+
* Creates an standard binding.
|
|
2288
|
+
* @param binding - The binding to refresh when changed.
|
|
2289
|
+
* @param isVolatile - Indicates whether the binding is volatile or not.
|
|
2290
|
+
* @returns A binding configuration.
|
|
1975
2291
|
* @public
|
|
1976
2292
|
*/
|
|
1977
|
-
function bind(binding,
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
2293
|
+
function bind(binding, isVolatile = Observable.isVolatileBinding(binding)) {
|
|
2294
|
+
return new OnChangeBinding(binding, isVolatile);
|
|
2295
|
+
}
|
|
2296
|
+
/**
|
|
2297
|
+
* Creates a one time binding
|
|
2298
|
+
* @param binding - The binding to refresh when signaled.
|
|
2299
|
+
* @returns A binding configuration.
|
|
2300
|
+
* @public
|
|
2301
|
+
*/
|
|
2302
|
+
function oneTime(binding) {
|
|
2303
|
+
return new OneTimeBinding(binding);
|
|
2304
|
+
}
|
|
2305
|
+
/**
|
|
2306
|
+
* Creates an event listener binding.
|
|
2307
|
+
* @param binding - The binding to invoke when the event is raised.
|
|
2308
|
+
* @param options - Event listener options.
|
|
2309
|
+
* @returns A binding configuration.
|
|
2310
|
+
* @public
|
|
2311
|
+
*/
|
|
2312
|
+
function listener(binding, options) {
|
|
2313
|
+
const config = new OnChangeBinding(binding, false);
|
|
2314
|
+
config.options = options;
|
|
2315
|
+
return config;
|
|
2316
|
+
}
|
|
2317
|
+
/**
|
|
2318
|
+
* Normalizes the input value into a binding.
|
|
2319
|
+
* @param value - The value to create the default binding for.
|
|
2320
|
+
* @returns A binding configuration for the provided value.
|
|
2321
|
+
* @public
|
|
2322
|
+
*/
|
|
2323
|
+
function normalizeBinding(value) {
|
|
2324
|
+
return isFunction(value)
|
|
2325
|
+
? bind(value)
|
|
2326
|
+
: value instanceof Binding
|
|
2327
|
+
? value
|
|
2328
|
+
: oneTime(() => value);
|
|
1982
2329
|
}
|
|
1983
2330
|
|
|
1984
2331
|
function removeNodeSequence(firstNode, lastNode) {
|
|
@@ -2034,8 +2381,10 @@ class HTMLView {
|
|
|
2034
2381
|
node.parentNode.insertBefore(this.fragment, node);
|
|
2035
2382
|
}
|
|
2036
2383
|
else {
|
|
2037
|
-
const parentNode = node.parentNode;
|
|
2038
2384
|
const end = this.lastChild;
|
|
2385
|
+
if (node.previousSibling === end)
|
|
2386
|
+
return;
|
|
2387
|
+
const parentNode = node.parentNode;
|
|
2039
2388
|
let current = this.firstChild;
|
|
2040
2389
|
let next;
|
|
2041
2390
|
while (current !== end) {
|
|
@@ -2145,6 +2494,22 @@ const next = {
|
|
|
2145
2494
|
index: 0,
|
|
2146
2495
|
node: null,
|
|
2147
2496
|
};
|
|
2497
|
+
function tryWarn(name) {
|
|
2498
|
+
if (!name.startsWith("fast-")) {
|
|
2499
|
+
FAST.warn(1204 /* Message.hostBindingWithoutHost */, { name });
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
const warningHost = new Proxy(document.createElement("div"), {
|
|
2503
|
+
get(target, property) {
|
|
2504
|
+
tryWarn(property);
|
|
2505
|
+
const value = Reflect.get(target, property);
|
|
2506
|
+
return isFunction(value) ? value.bind(target) : value;
|
|
2507
|
+
},
|
|
2508
|
+
set(target, property, value) {
|
|
2509
|
+
tryWarn(property);
|
|
2510
|
+
return Reflect.set(target, property, value);
|
|
2511
|
+
},
|
|
2512
|
+
});
|
|
2148
2513
|
class CompilationContext {
|
|
2149
2514
|
constructor(fragment, directives) {
|
|
2150
2515
|
this.fragment = fragment;
|
|
@@ -2195,7 +2560,7 @@ class CompilationContext {
|
|
|
2195
2560
|
const fragment = this.fragment.cloneNode(true);
|
|
2196
2561
|
const targets = Object.create(this.proto);
|
|
2197
2562
|
targets.r = fragment;
|
|
2198
|
-
targets.h = hostBindingTarget !== null && hostBindingTarget !== void 0 ? hostBindingTarget :
|
|
2563
|
+
targets.h = hostBindingTarget !== null && hostBindingTarget !== void 0 ? hostBindingTarget : warningHost;
|
|
2199
2564
|
for (const id of this.nodeIds) {
|
|
2200
2565
|
targets[id]; // trigger locator
|
|
2201
2566
|
}
|
|
@@ -2212,7 +2577,7 @@ function compileAttributes(context, parentId, node, nodeId, nodeIndex, includeBa
|
|
|
2212
2577
|
let result = null;
|
|
2213
2578
|
if (parseResult === null) {
|
|
2214
2579
|
if (includeBasicValues) {
|
|
2215
|
-
result =
|
|
2580
|
+
result = new HTMLBindingDirective(oneTime(() => attrValue));
|
|
2216
2581
|
Aspect.assign(result, attr.name);
|
|
2217
2582
|
}
|
|
2218
2583
|
}
|
|
@@ -2249,6 +2614,7 @@ function compileContent(context, node, parentId, nodeId, nodeIndex) {
|
|
|
2249
2614
|
}
|
|
2250
2615
|
else {
|
|
2251
2616
|
currentNode.textContent = " ";
|
|
2617
|
+
Aspect.assign(currentPart);
|
|
2252
2618
|
context.addFactory(currentPart, parentId, nodeId, nodeIndex);
|
|
2253
2619
|
}
|
|
2254
2620
|
lastNode = currentNode;
|
|
@@ -2381,22 +2747,28 @@ const Compiler = {
|
|
|
2381
2747
|
return parts[0];
|
|
2382
2748
|
}
|
|
2383
2749
|
let sourceAspect;
|
|
2750
|
+
let binding;
|
|
2751
|
+
let isVolatile = false;
|
|
2384
2752
|
const partCount = parts.length;
|
|
2385
2753
|
const finalParts = parts.map((x) => {
|
|
2386
2754
|
if (isString(x)) {
|
|
2387
2755
|
return () => x;
|
|
2388
2756
|
}
|
|
2389
2757
|
sourceAspect = x.sourceAspect || sourceAspect;
|
|
2390
|
-
|
|
2758
|
+
binding = x.dataBinding || binding;
|
|
2759
|
+
isVolatile = isVolatile || x.dataBinding.isVolatile;
|
|
2760
|
+
return x.dataBinding.evaluate;
|
|
2391
2761
|
});
|
|
2392
|
-
const
|
|
2762
|
+
const expression = (scope, context) => {
|
|
2393
2763
|
let output = "";
|
|
2394
2764
|
for (let i = 0; i < partCount; ++i) {
|
|
2395
2765
|
output += finalParts[i](scope, context);
|
|
2396
2766
|
}
|
|
2397
2767
|
return output;
|
|
2398
2768
|
};
|
|
2399
|
-
|
|
2769
|
+
binding.evaluate = expression;
|
|
2770
|
+
binding.isVolatile = isVolatile;
|
|
2771
|
+
const directive = new HTMLBindingDirective(binding);
|
|
2400
2772
|
Aspect.assign(directive, sourceAspect);
|
|
2401
2773
|
return directive;
|
|
2402
2774
|
},
|
|
@@ -2476,12 +2848,12 @@ function html(strings, ...values) {
|
|
|
2476
2848
|
let definition;
|
|
2477
2849
|
html += currentString;
|
|
2478
2850
|
if (isFunction(currentValue)) {
|
|
2479
|
-
html += createAspectedHTML(bind(currentValue), currentString, add);
|
|
2851
|
+
html += createAspectedHTML(new HTMLBindingDirective(bind(currentValue)), currentString, add);
|
|
2480
2852
|
}
|
|
2481
2853
|
else if (isString(currentValue)) {
|
|
2482
2854
|
const match = lastAttributeNameRegex.exec(currentString);
|
|
2483
2855
|
if (match !== null) {
|
|
2484
|
-
const directive =
|
|
2856
|
+
const directive = new HTMLBindingDirective(oneTime(() => currentValue));
|
|
2485
2857
|
Aspect.assign(directive, match[2]);
|
|
2486
2858
|
html += directive.createHTML(add);
|
|
2487
2859
|
}
|
|
@@ -2489,8 +2861,11 @@ function html(strings, ...values) {
|
|
|
2489
2861
|
html += currentValue;
|
|
2490
2862
|
}
|
|
2491
2863
|
}
|
|
2864
|
+
else if (currentValue instanceof Binding) {
|
|
2865
|
+
html += createAspectedHTML(new HTMLBindingDirective(currentValue), currentString, add);
|
|
2866
|
+
}
|
|
2492
2867
|
else if ((definition = HTMLDirective.getForInstance(currentValue)) === void 0) {
|
|
2493
|
-
html += createAspectedHTML(
|
|
2868
|
+
html += createAspectedHTML(new HTMLBindingDirective(oneTime(() => currentValue)), currentString, add);
|
|
2494
2869
|
}
|
|
2495
2870
|
else {
|
|
2496
2871
|
if (definition.aspected) {
|
|
@@ -2535,16 +2910,17 @@ const ref = (propertyName) => new RefDirective(propertyName);
|
|
|
2535
2910
|
|
|
2536
2911
|
/**
|
|
2537
2912
|
* A directive that enables basic conditional rendering in a template.
|
|
2538
|
-
* @param
|
|
2913
|
+
* @param condition - The condition to test for rendering.
|
|
2539
2914
|
* @param templateOrTemplateBinding - The template or a binding that gets
|
|
2540
2915
|
* the template to render when the condition is true.
|
|
2541
2916
|
* @public
|
|
2542
2917
|
*/
|
|
2543
|
-
function when(
|
|
2544
|
-
const
|
|
2918
|
+
function when(condition, templateOrTemplateBinding) {
|
|
2919
|
+
const dataBinding = isFunction(condition) ? condition : () => condition;
|
|
2920
|
+
const templateBinding = isFunction(templateOrTemplateBinding)
|
|
2545
2921
|
? templateOrTemplateBinding
|
|
2546
2922
|
: () => templateOrTemplateBinding;
|
|
2547
|
-
return (source, context) =>
|
|
2923
|
+
return (source, context) => dataBinding(source, context) ? templateBinding(source, context) : null;
|
|
2548
2924
|
}
|
|
2549
2925
|
|
|
2550
2926
|
const defaultRepeatOptions = Object.freeze({
|
|
@@ -2565,17 +2941,15 @@ class RepeatBehavior {
|
|
|
2565
2941
|
/**
|
|
2566
2942
|
* Creates an instance of RepeatBehavior.
|
|
2567
2943
|
* @param location - The location in the DOM to render the repeat.
|
|
2568
|
-
* @param
|
|
2944
|
+
* @param dataBinding - The array to render.
|
|
2569
2945
|
* @param isItemsBindingVolatile - Indicates whether the items binding has volatile dependencies.
|
|
2570
2946
|
* @param templateBinding - The template to render for each item.
|
|
2571
2947
|
* @param isTemplateBindingVolatile - Indicates whether the template binding has volatile dependencies.
|
|
2572
2948
|
* @param options - Options used to turn on special repeat features.
|
|
2573
2949
|
*/
|
|
2574
|
-
constructor(
|
|
2950
|
+
constructor(directive, location) {
|
|
2951
|
+
this.directive = directive;
|
|
2575
2952
|
this.location = location;
|
|
2576
|
-
this.itemsBinding = itemsBinding;
|
|
2577
|
-
this.templateBinding = templateBinding;
|
|
2578
|
-
this.options = options;
|
|
2579
2953
|
this.source = null;
|
|
2580
2954
|
this.views = [];
|
|
2581
2955
|
this.items = null;
|
|
@@ -2583,9 +2957,9 @@ class RepeatBehavior {
|
|
|
2583
2957
|
this.context = void 0;
|
|
2584
2958
|
this.childContext = void 0;
|
|
2585
2959
|
this.bindView = bindWithoutPositioning;
|
|
2586
|
-
this.itemsBindingObserver =
|
|
2587
|
-
this.templateBindingObserver =
|
|
2588
|
-
if (options.positioning) {
|
|
2960
|
+
this.itemsBindingObserver = directive.dataBinding.createObserver(directive, this);
|
|
2961
|
+
this.templateBindingObserver = directive.templateBinding.createObserver(directive, this);
|
|
2962
|
+
if (directive.options.positioning) {
|
|
2589
2963
|
this.bindView = bindWithPositioning;
|
|
2590
2964
|
}
|
|
2591
2965
|
}
|
|
@@ -2623,15 +2997,18 @@ class RepeatBehavior {
|
|
|
2623
2997
|
* @param args - The details about what was changed.
|
|
2624
2998
|
*/
|
|
2625
2999
|
handleChange(source, args) {
|
|
2626
|
-
if (
|
|
3000
|
+
if (args === this.itemsBindingObserver) {
|
|
2627
3001
|
this.items = this.itemsBindingObserver.observe(this.source, this.context);
|
|
2628
3002
|
this.observeItems();
|
|
2629
3003
|
this.refreshAllViews();
|
|
2630
3004
|
}
|
|
2631
|
-
else if (
|
|
3005
|
+
else if (args === this.templateBindingObserver) {
|
|
2632
3006
|
this.template = this.templateBindingObserver.observe(this.source, this.context);
|
|
2633
3007
|
this.refreshAllViews(true);
|
|
2634
3008
|
}
|
|
3009
|
+
else if (!args[0]) {
|
|
3010
|
+
return;
|
|
3011
|
+
}
|
|
2635
3012
|
else if (args[0].reset) {
|
|
2636
3013
|
this.refreshAllViews();
|
|
2637
3014
|
}
|
|
@@ -2657,36 +3034,51 @@ class RepeatBehavior {
|
|
|
2657
3034
|
updateViews(splices) {
|
|
2658
3035
|
const views = this.views;
|
|
2659
3036
|
const childContext = this.childContext;
|
|
2660
|
-
const totalRemoved = [];
|
|
2661
3037
|
const bindView = this.bindView;
|
|
2662
|
-
let removeDelta = 0;
|
|
2663
|
-
for (let i = 0, ii = splices.length; i < ii; ++i) {
|
|
2664
|
-
const splice = splices[i];
|
|
2665
|
-
const removed = splice.removed;
|
|
2666
|
-
totalRemoved.push(...views.splice(splice.index + removeDelta, removed.length));
|
|
2667
|
-
removeDelta -= splice.addedCount;
|
|
2668
|
-
}
|
|
2669
3038
|
const items = this.items;
|
|
2670
3039
|
const template = this.template;
|
|
3040
|
+
const recycle = this.directive.options.recycle;
|
|
3041
|
+
const leftoverViews = [];
|
|
3042
|
+
let leftoverIndex = 0;
|
|
3043
|
+
let availableViews = 0;
|
|
2671
3044
|
for (let i = 0, ii = splices.length; i < ii; ++i) {
|
|
2672
3045
|
const splice = splices[i];
|
|
3046
|
+
const removed = splice.removed;
|
|
3047
|
+
let removeIndex = 0;
|
|
2673
3048
|
let addIndex = splice.index;
|
|
2674
3049
|
const end = addIndex + splice.addedCount;
|
|
3050
|
+
const removedViews = views.splice(splice.index, removed.length);
|
|
3051
|
+
availableViews = leftoverViews.length + removedViews.length;
|
|
2675
3052
|
for (; addIndex < end; ++addIndex) {
|
|
2676
3053
|
const neighbor = views[addIndex];
|
|
2677
3054
|
const location = neighbor ? neighbor.firstChild : this.location;
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
3055
|
+
let view;
|
|
3056
|
+
if (recycle && availableViews > 0) {
|
|
3057
|
+
if (removeIndex <= availableViews && removedViews.length > 0) {
|
|
3058
|
+
view = removedViews[removeIndex];
|
|
3059
|
+
removeIndex++;
|
|
3060
|
+
}
|
|
3061
|
+
else {
|
|
3062
|
+
view = leftoverViews[leftoverIndex];
|
|
3063
|
+
leftoverIndex++;
|
|
3064
|
+
}
|
|
3065
|
+
availableViews--;
|
|
3066
|
+
}
|
|
3067
|
+
else {
|
|
3068
|
+
view = template.create();
|
|
3069
|
+
}
|
|
2681
3070
|
views.splice(addIndex, 0, view);
|
|
2682
3071
|
bindView(view, items, addIndex, childContext);
|
|
2683
3072
|
view.insertBefore(location);
|
|
2684
3073
|
}
|
|
3074
|
+
if (removedViews[removeIndex]) {
|
|
3075
|
+
leftoverViews.push(...removedViews.slice(removeIndex));
|
|
3076
|
+
}
|
|
2685
3077
|
}
|
|
2686
|
-
for (let i =
|
|
2687
|
-
|
|
3078
|
+
for (let i = leftoverIndex, ii = leftoverViews.length; i < ii; ++i) {
|
|
3079
|
+
leftoverViews[i].dispose();
|
|
2688
3080
|
}
|
|
2689
|
-
if (this.options.positioning) {
|
|
3081
|
+
if (this.directive.options.positioning) {
|
|
2690
3082
|
for (let i = 0, ii = views.length; i < ii; ++i) {
|
|
2691
3083
|
views[i].context.updatePosition(i, ii);
|
|
2692
3084
|
}
|
|
@@ -2701,7 +3093,7 @@ class RepeatBehavior {
|
|
|
2701
3093
|
let itemsLength = items.length;
|
|
2702
3094
|
let views = this.views;
|
|
2703
3095
|
let viewsLength = views.length;
|
|
2704
|
-
if (itemsLength === 0 || templateChanged || !this.options.recycle) {
|
|
3096
|
+
if (itemsLength === 0 || templateChanged || !this.directive.options.recycle) {
|
|
2705
3097
|
// all views need to be removed
|
|
2706
3098
|
HTMLView.disposeContiguousBatch(views);
|
|
2707
3099
|
viewsLength = 0;
|
|
@@ -2751,17 +3143,19 @@ class RepeatBehavior {
|
|
|
2751
3143
|
class RepeatDirective {
|
|
2752
3144
|
/**
|
|
2753
3145
|
* Creates an instance of RepeatDirective.
|
|
2754
|
-
* @param
|
|
3146
|
+
* @param dataBinding - The binding that provides the array to render.
|
|
2755
3147
|
* @param templateBinding - The template binding used to obtain a template to render for each item in the array.
|
|
2756
3148
|
* @param options - Options used to turn on special repeat features.
|
|
2757
3149
|
*/
|
|
2758
|
-
constructor(
|
|
2759
|
-
this.
|
|
3150
|
+
constructor(dataBinding, templateBinding, options) {
|
|
3151
|
+
this.dataBinding = dataBinding;
|
|
2760
3152
|
this.templateBinding = templateBinding;
|
|
2761
3153
|
this.options = options;
|
|
3154
|
+
/**
|
|
3155
|
+
* The unique id of the factory.
|
|
3156
|
+
*/
|
|
3157
|
+
this.id = nextId();
|
|
2762
3158
|
ArrayObserver.enable();
|
|
2763
|
-
this.isItemsBindingVolatile = Observable.isVolatileBinding(itemsBinding);
|
|
2764
|
-
this.isTemplateBindingVolatile = Observable.isVolatileBinding(templateBinding);
|
|
2765
3159
|
}
|
|
2766
3160
|
/**
|
|
2767
3161
|
* Creates a placeholder string based on the directive's index within the template.
|
|
@@ -2775,23 +3169,22 @@ class RepeatDirective {
|
|
|
2775
3169
|
* @param target - The node instance to create the behavior for.
|
|
2776
3170
|
*/
|
|
2777
3171
|
createBehavior(targets) {
|
|
2778
|
-
return new RepeatBehavior(targets[this.nodeId]
|
|
3172
|
+
return new RepeatBehavior(this, targets[this.nodeId]);
|
|
2779
3173
|
}
|
|
2780
3174
|
}
|
|
2781
3175
|
HTMLDirective.define(RepeatDirective);
|
|
2782
3176
|
/**
|
|
2783
3177
|
* A directive that enables list rendering.
|
|
2784
|
-
* @param
|
|
2785
|
-
* @param
|
|
3178
|
+
* @param items - The array to render.
|
|
3179
|
+
* @param template - The template or a template binding used obtain a template
|
|
2786
3180
|
* to render for each item in the array.
|
|
2787
3181
|
* @param options - Options used to turn on special repeat features.
|
|
2788
3182
|
* @public
|
|
2789
3183
|
*/
|
|
2790
|
-
function repeat(
|
|
2791
|
-
const
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
return new RepeatDirective(itemsBinding, templateBinding, options);
|
|
3184
|
+
function repeat(items, template, options = defaultRepeatOptions) {
|
|
3185
|
+
const dataBinding = normalizeBinding(items);
|
|
3186
|
+
const templateBinding = normalizeBinding(template);
|
|
3187
|
+
return new RepeatDirective(dataBinding, templateBinding, Object.assign(Object.assign({}, defaultRepeatOptions), options));
|
|
2795
3188
|
}
|
|
2796
3189
|
|
|
2797
3190
|
const selectElements = (value) => value.nodeType === 1;
|
|
@@ -3176,19 +3569,15 @@ const fastElementRegistry = FAST.getById(4 /* KernelServiceId.elementRegistry */
|
|
|
3176
3569
|
* @public
|
|
3177
3570
|
*/
|
|
3178
3571
|
class FASTElementDefinition {
|
|
3179
|
-
/**
|
|
3180
|
-
* Creates an instance of FASTElementDefinition.
|
|
3181
|
-
* @param type - The type this definition is being created for.
|
|
3182
|
-
* @param nameOrConfig - The name of the element to define or a config object
|
|
3183
|
-
* that describes the element to define.
|
|
3184
|
-
*/
|
|
3185
3572
|
constructor(type, nameOrConfig = type.definition) {
|
|
3573
|
+
this.platformDefined = false;
|
|
3186
3574
|
if (isString(nameOrConfig)) {
|
|
3187
3575
|
nameOrConfig = { name: nameOrConfig };
|
|
3188
3576
|
}
|
|
3189
3577
|
this.type = type;
|
|
3190
3578
|
this.name = nameOrConfig.name;
|
|
3191
3579
|
this.template = nameOrConfig.template;
|
|
3580
|
+
const proto = type.prototype;
|
|
3192
3581
|
const attributes = AttributeDefinition.collect(type, nameOrConfig.attributes);
|
|
3193
3582
|
const observedAttributes = new Array(attributes.length);
|
|
3194
3583
|
const propertyLookup = {};
|
|
@@ -3198,9 +3587,13 @@ class FASTElementDefinition {
|
|
|
3198
3587
|
observedAttributes[i] = current.attribute;
|
|
3199
3588
|
propertyLookup[current.name] = current;
|
|
3200
3589
|
attributeLookup[current.attribute] = current;
|
|
3590
|
+
Observable.defineProperty(proto, current);
|
|
3201
3591
|
}
|
|
3592
|
+
Reflect.defineProperty(type, "observedAttributes", {
|
|
3593
|
+
value: observedAttributes,
|
|
3594
|
+
enumerable: true,
|
|
3595
|
+
});
|
|
3202
3596
|
this.attributes = attributes;
|
|
3203
|
-
this.observedAttributes = observedAttributes;
|
|
3204
3597
|
this.propertyLookup = propertyLookup;
|
|
3205
3598
|
this.attributeLookup = attributeLookup;
|
|
3206
3599
|
this.shadowOptions =
|
|
@@ -3213,20 +3606,14 @@ class FASTElementDefinition {
|
|
|
3213
3606
|
nameOrConfig.elementOptions === void 0
|
|
3214
3607
|
? defaultElementOptions
|
|
3215
3608
|
: Object.assign(Object.assign({}, defaultElementOptions), nameOrConfig.elementOptions);
|
|
3216
|
-
this.styles =
|
|
3217
|
-
|
|
3218
|
-
? void 0
|
|
3219
|
-
: Array.isArray(nameOrConfig.styles)
|
|
3220
|
-
? new ElementStyles(nameOrConfig.styles)
|
|
3221
|
-
: nameOrConfig.styles instanceof ElementStyles
|
|
3222
|
-
? nameOrConfig.styles
|
|
3223
|
-
: new ElementStyles([nameOrConfig.styles]);
|
|
3609
|
+
this.styles = ElementStyles.normalize(nameOrConfig.styles);
|
|
3610
|
+
fastElementRegistry.register(this);
|
|
3224
3611
|
}
|
|
3225
3612
|
/**
|
|
3226
3613
|
* Indicates if this element has been defined in at least one registry.
|
|
3227
3614
|
*/
|
|
3228
3615
|
get isDefined() {
|
|
3229
|
-
return
|
|
3616
|
+
return this.platformDefined;
|
|
3230
3617
|
}
|
|
3231
3618
|
/**
|
|
3232
3619
|
* Defines a custom element based on this definition.
|
|
@@ -3236,22 +3623,26 @@ class FASTElementDefinition {
|
|
|
3236
3623
|
*/
|
|
3237
3624
|
define(registry = customElements) {
|
|
3238
3625
|
const type = this.type;
|
|
3239
|
-
if (fastElementRegistry.register(this)) {
|
|
3240
|
-
const attributes = this.attributes;
|
|
3241
|
-
const proto = type.prototype;
|
|
3242
|
-
for (let i = 0, ii = attributes.length; i < ii; ++i) {
|
|
3243
|
-
Observable.defineProperty(proto, attributes[i]);
|
|
3244
|
-
}
|
|
3245
|
-
Reflect.defineProperty(type, "observedAttributes", {
|
|
3246
|
-
value: this.observedAttributes,
|
|
3247
|
-
enumerable: true,
|
|
3248
|
-
});
|
|
3249
|
-
}
|
|
3250
3626
|
if (!registry.get(this.name)) {
|
|
3627
|
+
this.platformDefined = true;
|
|
3251
3628
|
registry.define(this.name, type, this.elementOptions);
|
|
3252
3629
|
}
|
|
3253
3630
|
return this;
|
|
3254
3631
|
}
|
|
3632
|
+
/**
|
|
3633
|
+
* Creates an instance of FASTElementDefinition.
|
|
3634
|
+
* @param type - The type this definition is being created for.
|
|
3635
|
+
* @param nameOrDef - The name of the element to define or a config object
|
|
3636
|
+
* that describes the element to define.
|
|
3637
|
+
*/
|
|
3638
|
+
static compose(type, nameOrDef) {
|
|
3639
|
+
const found = fastElementRegistry.getByType(type);
|
|
3640
|
+
if (found) {
|
|
3641
|
+
return new FASTElementDefinition(class extends type {
|
|
3642
|
+
}, nameOrDef);
|
|
3643
|
+
}
|
|
3644
|
+
return new FASTElementDefinition(type, nameOrDef);
|
|
3645
|
+
}
|
|
3255
3646
|
}
|
|
3256
3647
|
/**
|
|
3257
3648
|
* Gets the element definition associated with the specified type.
|
|
@@ -3669,6 +4060,21 @@ function createFASTElement(BaseType) {
|
|
|
3669
4060
|
}
|
|
3670
4061
|
};
|
|
3671
4062
|
}
|
|
4063
|
+
function compose(type, nameOrDef) {
|
|
4064
|
+
if (isFunction(type)) {
|
|
4065
|
+
return FASTElementDefinition.compose(type, nameOrDef);
|
|
4066
|
+
}
|
|
4067
|
+
return FASTElementDefinition.compose(this, type);
|
|
4068
|
+
}
|
|
4069
|
+
function define(type, nameOrDef) {
|
|
4070
|
+
if (isFunction(type)) {
|
|
4071
|
+
return FASTElementDefinition.compose(type, nameOrDef).define().type;
|
|
4072
|
+
}
|
|
4073
|
+
return FASTElementDefinition.compose(this, type).define().type;
|
|
4074
|
+
}
|
|
4075
|
+
function from(BaseType) {
|
|
4076
|
+
return createFASTElement(BaseType);
|
|
4077
|
+
}
|
|
3672
4078
|
/**
|
|
3673
4079
|
* A minimal base class for FASTElements that also provides
|
|
3674
4080
|
* static helpers for working with FASTElements.
|
|
@@ -3680,26 +4086,19 @@ const FASTElement = Object.assign(createFASTElement(HTMLElement), {
|
|
|
3680
4086
|
* provided base type.
|
|
3681
4087
|
* @param BaseType - The base element type to inherit from.
|
|
3682
4088
|
*/
|
|
3683
|
-
from
|
|
3684
|
-
return createFASTElement(BaseType);
|
|
3685
|
-
},
|
|
4089
|
+
from,
|
|
3686
4090
|
/**
|
|
3687
4091
|
* Defines a platform custom element based on the provided type and definition.
|
|
3688
4092
|
* @param type - The custom element type to define.
|
|
3689
4093
|
* @param nameOrDef - The name of the element to define or a definition object
|
|
3690
4094
|
* that describes the element to define.
|
|
3691
4095
|
*/
|
|
3692
|
-
define
|
|
3693
|
-
return this.metadata(type, nameOrDef).define().type;
|
|
3694
|
-
},
|
|
4096
|
+
define,
|
|
3695
4097
|
/**
|
|
3696
4098
|
* Defines metadata for a FASTElement which can be used to later define the element.
|
|
3697
|
-
* IMPORTANT: This API will be renamed to "compose" in a future beta.
|
|
3698
4099
|
* @public
|
|
3699
4100
|
*/
|
|
3700
|
-
|
|
3701
|
-
return new FASTElementDefinition(type, nameOrDef);
|
|
3702
|
-
},
|
|
4101
|
+
compose,
|
|
3703
4102
|
});
|
|
3704
4103
|
/**
|
|
3705
4104
|
* Decorator: Defines a platform custom element based on `FASTElement`.
|
|
@@ -3710,8 +4109,8 @@ const FASTElement = Object.assign(createFASTElement(HTMLElement), {
|
|
|
3710
4109
|
function customElement(nameOrDef) {
|
|
3711
4110
|
/* eslint-disable-next-line @typescript-eslint/explicit-function-return-type */
|
|
3712
4111
|
return function (type) {
|
|
3713
|
-
|
|
4112
|
+
define(type, nameOrDef);
|
|
3714
4113
|
};
|
|
3715
4114
|
}
|
|
3716
4115
|
|
|
3717
|
-
export { AdoptedStyleSheetsStrategy, ArrayObserver, Aspect, AttributeDefinition,
|
|
4116
|
+
export { AdoptedStyleSheetsStrategy, ArrayObserver, Aspect, AttributeDefinition, Binding, BindingBehavior, CSSDirective, ChildrenDirective, Compiler, ContentBehavior, Controller, DOM, ElementStyles, EventBehavior, ExecutionContext, FAST, FASTElement, FASTElementDefinition, HTMLBindingDirective, HTMLDirective, HTMLView, Markup, NodeObservationDirective, Observable, Parser, PropertyChangeNotifier, RefDirective, RepeatBehavior, RepeatDirective, SlottedDirective, Splice, SpliceStrategy, SpliceStrategySupport, StatelessAttachedAttributeDirective, SubscriberSet, Updates, ViewTemplate, attr, bind, booleanConverter, children, createTypeRegistry, css, cssDirective, cssPartial, customElement, elements, emptyArray, html, htmlDirective, lengthOf, listener, normalizeBinding, nullableNumberConverter, observable, oneTime, ref, repeat, slotted, volatile, when };
|