@microsoft/fast-element 2.0.0-beta.1 → 2.0.0-beta.4
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 +11 -8
- package/dist/dts/components/fast-element.d.ts +13 -3
- package/dist/dts/context.d.ts +157 -0
- package/dist/dts/di/di.d.ts +854 -0
- package/dist/dts/hooks.d.ts +2 -2
- package/dist/dts/interfaces.d.ts +39 -7
- package/dist/dts/metadata.d.ts +25 -0
- package/dist/dts/observation/arrays.d.ts +1 -1
- package/dist/dts/observation/behavior.d.ts +4 -4
- package/dist/dts/observation/observable.d.ts +59 -72
- package/dist/dts/styles/element-styles.d.ts +6 -0
- package/dist/dts/templating/binding-signal.d.ts +21 -0
- package/dist/dts/templating/binding-two-way.d.ts +31 -0
- package/dist/dts/templating/binding.d.ts +74 -201
- package/dist/dts/templating/compiler.d.ts +1 -2
- 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 +13 -63
- package/dist/dts/templating/template.d.ts +11 -60
- package/dist/dts/templating/view.d.ts +9 -9
- 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/{tsdoc-metadata.json → dts/tsdoc-metadata.json} +0 -0
- package/dist/esm/components/fast-definitions.js +27 -27
- package/dist/esm/components/fast-element.js +20 -4
- package/dist/esm/context.js +163 -0
- package/dist/esm/debug.js +35 -4
- package/dist/esm/di/di.js +1349 -0
- package/dist/esm/metadata.js +60 -0
- package/dist/esm/observation/arrays.js +1 -1
- package/dist/esm/observation/observable.js +73 -21
- package/dist/esm/platform.js +1 -1
- package/dist/esm/styles/element-styles.js +14 -0
- package/dist/esm/templating/binding-signal.js +79 -0
- package/dist/esm/templating/binding-two-way.js +98 -0
- package/dist/esm/templating/binding.js +137 -313
- 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 +60 -38
- package/dist/esm/templating/template.js +9 -26
- 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 +8509 -10358
- package/dist/fast-element.d.ts +315 -522
- package/dist/fast-element.debug.js +417 -438
- package/dist/fast-element.debug.min.js +1 -1
- package/dist/fast-element.js +382 -434
- package/dist/fast-element.min.js +1 -1
- package/dist/fast-element.untrimmed.d.ts +324 -529
- package/docs/api-report.md +124 -232
- package/package.json +32 -4
package/dist/fast-element.js
CHANGED
|
@@ -112,7 +112,7 @@ if (FAST.error === void 0) {
|
|
|
112
112
|
Object.assign(FAST, {
|
|
113
113
|
warn() { },
|
|
114
114
|
error(code) {
|
|
115
|
-
return new Error(`
|
|
115
|
+
return new Error(`Error ${code}`);
|
|
116
116
|
},
|
|
117
117
|
addMessages() { },
|
|
118
118
|
});
|
|
@@ -449,7 +449,7 @@ const Observable = FAST.getById(2 /* KernelServiceId.observable */, () => {
|
|
|
449
449
|
}
|
|
450
450
|
}
|
|
451
451
|
}
|
|
452
|
-
class
|
|
452
|
+
class ExpressionNotifierImplementation extends SubscriberSet {
|
|
453
453
|
constructor(binding, initialSubscriber, isVolatileBinding = false) {
|
|
454
454
|
super(binding, initialSubscriber);
|
|
455
455
|
this.binding = binding;
|
|
@@ -604,14 +604,14 @@ const Observable = FAST.getById(2 /* KernelServiceId.observable */, () => {
|
|
|
604
604
|
*/
|
|
605
605
|
getAccessors,
|
|
606
606
|
/**
|
|
607
|
-
* Creates a {@link
|
|
608
|
-
* provided {@link
|
|
607
|
+
* Creates a {@link ExpressionNotifier} that can watch the
|
|
608
|
+
* provided {@link Expression} for changes.
|
|
609
609
|
* @param binding - The binding to observe.
|
|
610
610
|
* @param initialSubscriber - An initial subscriber to changes in the binding value.
|
|
611
611
|
* @param isVolatileBinding - Indicates whether the binding's dependency list must be re-evaluated on every value evaluation.
|
|
612
612
|
*/
|
|
613
613
|
binding(binding, initialSubscriber, isVolatileBinding = this.isVolatileBinding(binding)) {
|
|
614
|
-
return new
|
|
614
|
+
return new ExpressionNotifierImplementation(binding, initialSubscriber, isVolatileBinding);
|
|
615
615
|
},
|
|
616
616
|
/**
|
|
617
617
|
* Determines whether a binding expression is volatile and needs to have its dependency list re-evaluated
|
|
@@ -658,75 +658,127 @@ const contextEvent = FAST.getById(3 /* KernelServiceId.contextEvent */, () => {
|
|
|
658
658
|
},
|
|
659
659
|
};
|
|
660
660
|
});
|
|
661
|
-
|
|
661
|
+
/**
|
|
662
|
+
* Provides additional contextual information available to behaviors and expressions.
|
|
663
|
+
* @public
|
|
664
|
+
*/
|
|
665
|
+
class ExecutionContext {
|
|
662
666
|
constructor(parentSource = null, parentContext = null) {
|
|
667
|
+
/**
|
|
668
|
+
* The index of the current item within a repeat context.
|
|
669
|
+
*/
|
|
663
670
|
this.index = 0;
|
|
671
|
+
/**
|
|
672
|
+
* The length of the current collection within a repeat context.
|
|
673
|
+
*/
|
|
664
674
|
this.length = 0;
|
|
665
675
|
this.parent = parentSource;
|
|
666
676
|
this.parentContext = parentContext;
|
|
667
677
|
}
|
|
678
|
+
/**
|
|
679
|
+
* The current event within an event handler.
|
|
680
|
+
*/
|
|
668
681
|
get event() {
|
|
669
682
|
return contextEvent.get();
|
|
670
683
|
}
|
|
684
|
+
/**
|
|
685
|
+
* Indicates whether the current item within a repeat context
|
|
686
|
+
* has an even index.
|
|
687
|
+
*/
|
|
671
688
|
get isEven() {
|
|
672
689
|
return this.index % 2 === 0;
|
|
673
690
|
}
|
|
691
|
+
/**
|
|
692
|
+
* Indicates whether the current item within a repeat context
|
|
693
|
+
* has an odd index.
|
|
694
|
+
*/
|
|
674
695
|
get isOdd() {
|
|
675
696
|
return this.index % 2 !== 0;
|
|
676
697
|
}
|
|
698
|
+
/**
|
|
699
|
+
* Indicates whether the current item within a repeat context
|
|
700
|
+
* is the first item in the collection.
|
|
701
|
+
*/
|
|
677
702
|
get isFirst() {
|
|
678
703
|
return this.index === 0;
|
|
679
704
|
}
|
|
705
|
+
/**
|
|
706
|
+
* Indicates whether the current item within a repeat context
|
|
707
|
+
* is somewhere in the middle of the collection.
|
|
708
|
+
*/
|
|
680
709
|
get isInMiddle() {
|
|
681
710
|
return !this.isFirst && !this.isLast;
|
|
682
711
|
}
|
|
712
|
+
/**
|
|
713
|
+
* Indicates whether the current item within a repeat context
|
|
714
|
+
* is the last item in the collection.
|
|
715
|
+
*/
|
|
683
716
|
get isLast() {
|
|
684
717
|
return this.index === this.length - 1;
|
|
685
718
|
}
|
|
719
|
+
/**
|
|
720
|
+
* Returns the typed event detail of a custom event.
|
|
721
|
+
*/
|
|
686
722
|
eventDetail() {
|
|
687
723
|
return this.event.detail;
|
|
688
724
|
}
|
|
725
|
+
/**
|
|
726
|
+
* Returns the typed event target of the event.
|
|
727
|
+
*/
|
|
689
728
|
eventTarget() {
|
|
690
729
|
return this.event.target;
|
|
691
730
|
}
|
|
731
|
+
/**
|
|
732
|
+
* Updates the position/size on a context associated with a list item.
|
|
733
|
+
* @param index - The new index of the item.
|
|
734
|
+
* @param length - The new length of the list.
|
|
735
|
+
*/
|
|
692
736
|
updatePosition(index, length) {
|
|
693
737
|
this.index = index;
|
|
694
738
|
this.length = length;
|
|
695
739
|
}
|
|
740
|
+
/**
|
|
741
|
+
* Creates a new execution context descendent from the current context.
|
|
742
|
+
* @param source - The source for the context if different than the parent.
|
|
743
|
+
* @returns A child execution context.
|
|
744
|
+
*/
|
|
696
745
|
createChildContext(parentSource) {
|
|
697
|
-
return new
|
|
746
|
+
return new ExecutionContext(parentSource, this);
|
|
698
747
|
}
|
|
748
|
+
/**
|
|
749
|
+
* Creates a new execution context descent suitable for use in list rendering.
|
|
750
|
+
* @param item - The list item to serve as the source.
|
|
751
|
+
* @param index - The index of the item in the list.
|
|
752
|
+
* @param length - The length of the list.
|
|
753
|
+
*/
|
|
699
754
|
createItemContext(index, length) {
|
|
700
755
|
const childContext = Object.create(this);
|
|
701
756
|
childContext.index = index;
|
|
702
757
|
childContext.length = length;
|
|
703
758
|
return childContext;
|
|
704
759
|
}
|
|
705
|
-
}
|
|
706
|
-
Observable.defineProperty(DefaultExecutionContext.prototype, "index");
|
|
707
|
-
Observable.defineProperty(DefaultExecutionContext.prototype, "length");
|
|
708
|
-
/**
|
|
709
|
-
* The common execution context APIs.
|
|
710
|
-
* @public
|
|
711
|
-
*/
|
|
712
|
-
const ExecutionContext = Object.freeze({
|
|
713
|
-
default: new DefaultExecutionContext(),
|
|
714
760
|
/**
|
|
715
761
|
* Sets the event for the current execution context.
|
|
716
762
|
* @param event - The event to set.
|
|
717
763
|
* @internal
|
|
718
764
|
*/
|
|
719
|
-
setEvent(event) {
|
|
765
|
+
static setEvent(event) {
|
|
720
766
|
contextEvent.set(event);
|
|
721
|
-
}
|
|
767
|
+
}
|
|
722
768
|
/**
|
|
723
769
|
* Creates a new root execution context.
|
|
724
770
|
* @returns A new execution context.
|
|
725
771
|
*/
|
|
726
|
-
create() {
|
|
727
|
-
return new
|
|
728
|
-
}
|
|
729
|
-
}
|
|
772
|
+
static create() {
|
|
773
|
+
return new ExecutionContext();
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
/**
|
|
777
|
+
* The default execution context.
|
|
778
|
+
*/
|
|
779
|
+
ExecutionContext.default = new ExecutionContext();
|
|
780
|
+
Observable.defineProperty(ExecutionContext.prototype, "index");
|
|
781
|
+
Observable.defineProperty(ExecutionContext.prototype, "length");
|
|
730
782
|
|
|
731
783
|
/**
|
|
732
784
|
* A splice map is a representation of how a previous array of items
|
|
@@ -981,7 +1033,7 @@ const ArrayObserver = Object.freeze({
|
|
|
981
1033
|
* @returns The length of the array.
|
|
982
1034
|
* @public
|
|
983
1035
|
*/
|
|
984
|
-
function
|
|
1036
|
+
function lengthOf(array) {
|
|
985
1037
|
if (!array) {
|
|
986
1038
|
return 0;
|
|
987
1039
|
}
|
|
@@ -1065,6 +1117,20 @@ class ElementStyles {
|
|
|
1065
1117
|
static setDefaultStrategy(Strategy) {
|
|
1066
1118
|
DefaultStyleStrategy = Strategy;
|
|
1067
1119
|
}
|
|
1120
|
+
/**
|
|
1121
|
+
* Normalizes a set of composable style options.
|
|
1122
|
+
* @param styles - The style options to normalize.
|
|
1123
|
+
* @returns A singular ElementStyles instance or undefined.
|
|
1124
|
+
*/
|
|
1125
|
+
static normalize(styles) {
|
|
1126
|
+
return styles === void 0
|
|
1127
|
+
? void 0
|
|
1128
|
+
: Array.isArray(styles)
|
|
1129
|
+
? new ElementStyles(styles)
|
|
1130
|
+
: styles instanceof ElementStyles
|
|
1131
|
+
? styles
|
|
1132
|
+
: new ElementStyles([styles]);
|
|
1133
|
+
}
|
|
1068
1134
|
}
|
|
1069
1135
|
/**
|
|
1070
1136
|
* Indicates whether the DOM supports the adoptedStyleSheets feature.
|
|
@@ -1391,6 +1457,13 @@ function htmlDirective(options) {
|
|
|
1391
1457
|
HTMLDirective.define(type, options);
|
|
1392
1458
|
};
|
|
1393
1459
|
}
|
|
1460
|
+
/**
|
|
1461
|
+
* Captures a binding expression along with related information and capabilities.
|
|
1462
|
+
*
|
|
1463
|
+
* @public
|
|
1464
|
+
*/
|
|
1465
|
+
class Binding {
|
|
1466
|
+
}
|
|
1394
1467
|
/**
|
|
1395
1468
|
* The type of HTML aspect to target.
|
|
1396
1469
|
* @public
|
|
@@ -1428,12 +1501,15 @@ const Aspect = Object.freeze({
|
|
|
1428
1501
|
*
|
|
1429
1502
|
* @param directive - The directive to assign the aspect to.
|
|
1430
1503
|
* @param value - The value to base the aspect determination on.
|
|
1504
|
+
* @remarks
|
|
1505
|
+
* If a falsy value is provided, then the content aspect will be assigned.
|
|
1431
1506
|
*/
|
|
1432
1507
|
assign(directive, value) {
|
|
1433
|
-
directive.sourceAspect = value;
|
|
1434
1508
|
if (!value) {
|
|
1509
|
+
directive.aspectType = Aspect.content;
|
|
1435
1510
|
return;
|
|
1436
1511
|
}
|
|
1512
|
+
directive.sourceAspect = value;
|
|
1437
1513
|
switch (value[0]) {
|
|
1438
1514
|
case ":":
|
|
1439
1515
|
directive.targetAspect = value.substring(1);
|
|
@@ -1481,6 +1557,10 @@ class StatelessAttachedAttributeDirective {
|
|
|
1481
1557
|
*/
|
|
1482
1558
|
constructor(options) {
|
|
1483
1559
|
this.options = options;
|
|
1560
|
+
/**
|
|
1561
|
+
* The unique id of the factory.
|
|
1562
|
+
*/
|
|
1563
|
+
this.id = nextId();
|
|
1484
1564
|
}
|
|
1485
1565
|
/**
|
|
1486
1566
|
* Creates a behavior.
|
|
@@ -1509,99 +1589,28 @@ const createInnerHTMLBinding = globalThis.TrustedHTML
|
|
|
1509
1589
|
throw FAST.error(1202 /* Message.bindingInnerHTMLRequiresTrustedTypes */);
|
|
1510
1590
|
}
|
|
1511
1591
|
: (binding) => binding;
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
/**
|
|
1518
|
-
* Creates a binding mode based on the supplied behavior types.
|
|
1519
|
-
* @param UpdateType - The base behavior type used to update aspects.
|
|
1520
|
-
* @param EventType - The base behavior type used to respond to events.
|
|
1521
|
-
* @returns A new binding mode.
|
|
1522
|
-
*/
|
|
1523
|
-
define(UpdateType, EventType = EventBinding) {
|
|
1524
|
-
return Object.freeze({
|
|
1525
|
-
[1]: d => new UpdateType(d, DOM.setAttribute),
|
|
1526
|
-
[2]: d => new UpdateType(d, DOM.setBooleanAttribute),
|
|
1527
|
-
[3]: d => new UpdateType(d, (t, a, v) => (t[a] = v)),
|
|
1528
|
-
[4]: d => new (createContentBinding(UpdateType))(d, updateContentTarget),
|
|
1529
|
-
[5]: d => new UpdateType(d, updateTokenListTarget),
|
|
1530
|
-
[6]: d => new EventType(d),
|
|
1531
|
-
});
|
|
1532
|
-
},
|
|
1533
|
-
});
|
|
1534
|
-
/**
|
|
1535
|
-
* Describes the configuration for a binding expression.
|
|
1536
|
-
* @public
|
|
1537
|
-
*/
|
|
1538
|
-
const BindingConfig = Object.freeze({
|
|
1539
|
-
/**
|
|
1540
|
-
* Creates a binding configuration based on the provided mode and options.
|
|
1541
|
-
* @param mode - The mode to use for the configuration.
|
|
1542
|
-
* @param defaultOptions - The default options to use for the configuration.
|
|
1543
|
-
* @returns A new binding configuration.
|
|
1544
|
-
*/
|
|
1545
|
-
define(mode, defaultOptions) {
|
|
1546
|
-
const config = (options) => {
|
|
1547
|
-
return {
|
|
1548
|
-
mode: config.mode,
|
|
1549
|
-
options: Object.assign({}, defaultOptions, options),
|
|
1550
|
-
};
|
|
1551
|
-
};
|
|
1552
|
-
config.options = defaultOptions;
|
|
1553
|
-
config.mode = mode;
|
|
1554
|
-
return config;
|
|
1555
|
-
},
|
|
1556
|
-
});
|
|
1557
|
-
/**
|
|
1558
|
-
* A base binding behavior for DOM updates.
|
|
1559
|
-
* @public
|
|
1560
|
-
*/
|
|
1561
|
-
class UpdateBinding {
|
|
1562
|
-
/**
|
|
1563
|
-
* Creates an instance of UpdateBinding.
|
|
1564
|
-
* @param directive - The directive that has the configuration for this behavior.
|
|
1565
|
-
* @param updateTarget - The function used to update the target with the latest value.
|
|
1566
|
-
*/
|
|
1567
|
-
constructor(directive, updateTarget) {
|
|
1568
|
-
this.directive = directive;
|
|
1569
|
-
this.updateTarget = updateTarget;
|
|
1592
|
+
class OnChangeBinding extends Binding {
|
|
1593
|
+
constructor(evaluate, isVolatile) {
|
|
1594
|
+
super();
|
|
1595
|
+
this.evaluate = evaluate;
|
|
1596
|
+
this.isVolatile = isVolatile;
|
|
1570
1597
|
}
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
* @param source - The source to bind to.
|
|
1574
|
-
* @param context - The execution context that the binding is operating within.
|
|
1575
|
-
* @param targets - The targets that behaviors in a view can attach to.
|
|
1576
|
-
*/
|
|
1577
|
-
bind(source, context, targets) { }
|
|
1578
|
-
/**
|
|
1579
|
-
* Unbinds this behavior from the source.
|
|
1580
|
-
* @param source - The source to unbind from.
|
|
1581
|
-
* @param context - The execution context that the binding is operating within.
|
|
1582
|
-
* @param targets - The targets that behaviors in a view can attach to.
|
|
1583
|
-
*/
|
|
1584
|
-
unbind(source, context, targets) { }
|
|
1585
|
-
/**
|
|
1586
|
-
* Creates a behavior.
|
|
1587
|
-
* @param targets - The targets available for behaviors to be attached to.
|
|
1588
|
-
*/
|
|
1589
|
-
createBehavior(targets) {
|
|
1590
|
-
return this;
|
|
1598
|
+
createObserver(_, subscriber) {
|
|
1599
|
+
return Observable.binding(this.evaluate, subscriber, this.isVolatile);
|
|
1591
1600
|
}
|
|
1592
1601
|
}
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
}
|
|
1602
|
+
class OneTimeBinding extends Binding {
|
|
1603
|
+
constructor(evaluate) {
|
|
1604
|
+
super();
|
|
1605
|
+
this.evaluate = evaluate;
|
|
1606
|
+
}
|
|
1607
|
+
createObserver() {
|
|
1608
|
+
return this;
|
|
1609
|
+
}
|
|
1610
|
+
observe(source, context) {
|
|
1611
|
+
return this.evaluate(source, context);
|
|
1612
|
+
}
|
|
1613
|
+
dispose() { }
|
|
1605
1614
|
}
|
|
1606
1615
|
function updateContentTarget(target, aspect, value, source, context) {
|
|
1607
1616
|
// If there's no actual value, then this equates to the
|
|
@@ -1609,7 +1618,7 @@ function updateContentTarget(target, aspect, value, source, context) {
|
|
|
1609
1618
|
if (value === null || value === undefined) {
|
|
1610
1619
|
value = "";
|
|
1611
1620
|
}
|
|
1612
|
-
// If the value has a "create" method, then it's a
|
|
1621
|
+
// If the value has a "create" method, then it's a ContentTemplate.
|
|
1613
1622
|
if (value.create) {
|
|
1614
1623
|
target.textContent = "";
|
|
1615
1624
|
let view = target.$fastView;
|
|
@@ -1695,118 +1704,21 @@ function updateTokenListTarget(target, aspect, value) {
|
|
|
1695
1704
|
}
|
|
1696
1705
|
}
|
|
1697
1706
|
}
|
|
1698
|
-
/**
|
|
1699
|
-
* A binding behavior for one-time bindings.
|
|
1700
|
-
* @public
|
|
1701
|
-
*/
|
|
1702
|
-
class OneTimeBinding extends UpdateBinding {
|
|
1703
|
-
/**
|
|
1704
|
-
* Bind this behavior to the source.
|
|
1705
|
-
* @param source - The source to bind to.
|
|
1706
|
-
* @param context - The execution context that the binding is operating within.
|
|
1707
|
-
* @param targets - The targets that behaviors in a view can attach to.
|
|
1708
|
-
*/
|
|
1709
|
-
bind(source, context, targets) {
|
|
1710
|
-
const directive = this.directive;
|
|
1711
|
-
this.updateTarget(targets[directive.nodeId], directive.targetAspect, directive.binding(source, context), source, context);
|
|
1712
|
-
}
|
|
1713
|
-
}
|
|
1714
|
-
const signals = Object.create(null);
|
|
1715
|
-
/**
|
|
1716
|
-
* A binding behavior for signal bindings.
|
|
1717
|
-
* @public
|
|
1718
|
-
*/
|
|
1719
|
-
class SignalBinding extends UpdateBinding {
|
|
1720
|
-
constructor() {
|
|
1721
|
-
super(...arguments);
|
|
1722
|
-
this.handlerProperty = `${this.directive.id}-h`;
|
|
1723
|
-
}
|
|
1724
|
-
/**
|
|
1725
|
-
* Bind this behavior to the source.
|
|
1726
|
-
* @param source - The source to bind to.
|
|
1727
|
-
* @param context - The execution context that the binding is operating within.
|
|
1728
|
-
* @param targets - The targets that behaviors in a view can attach to.
|
|
1729
|
-
*/
|
|
1730
|
-
bind(source, context, targets) {
|
|
1731
|
-
const directive = this.directive;
|
|
1732
|
-
const target = targets[directive.nodeId];
|
|
1733
|
-
const signal = this.getSignal(source, context);
|
|
1734
|
-
const handler = (target[this.handlerProperty] = () => {
|
|
1735
|
-
this.updateTarget(target, directive.targetAspect, directive.binding(source, context), source, context);
|
|
1736
|
-
});
|
|
1737
|
-
handler();
|
|
1738
|
-
const found = signals[signal];
|
|
1739
|
-
if (found) {
|
|
1740
|
-
Array.isArray(found)
|
|
1741
|
-
? found.push(handler)
|
|
1742
|
-
: (signals[signal] = [found, handler]);
|
|
1743
|
-
}
|
|
1744
|
-
else {
|
|
1745
|
-
signals[signal] = handler;
|
|
1746
|
-
}
|
|
1747
|
-
}
|
|
1748
|
-
/**
|
|
1749
|
-
* Unbinds this behavior from the source.
|
|
1750
|
-
* @param source - The source to unbind from.
|
|
1751
|
-
* @param context - The execution context that the binding is operating within.
|
|
1752
|
-
* @param targets - The targets that behaviors in a view can attach to.
|
|
1753
|
-
*/
|
|
1754
|
-
unbind(source, context, targets) {
|
|
1755
|
-
const signal = this.getSignal(source, context);
|
|
1756
|
-
const found = signals[signal];
|
|
1757
|
-
if (found && Array.isArray(found)) {
|
|
1758
|
-
const directive = this.directive;
|
|
1759
|
-
const target = targets[directive.nodeId];
|
|
1760
|
-
const handler = target[this.handlerProperty];
|
|
1761
|
-
const index = found.indexOf(handler);
|
|
1762
|
-
if (index !== -1) {
|
|
1763
|
-
found.splice(index, 1);
|
|
1764
|
-
}
|
|
1765
|
-
}
|
|
1766
|
-
else {
|
|
1767
|
-
signals[signal] = void 0;
|
|
1768
|
-
}
|
|
1769
|
-
}
|
|
1770
|
-
getSignal(source, context) {
|
|
1771
|
-
const options = this.directive.options;
|
|
1772
|
-
return isString(options) ? options : options(source, context);
|
|
1773
|
-
}
|
|
1774
|
-
/**
|
|
1775
|
-
* Sends the specified signal to signaled bindings.
|
|
1776
|
-
* @param signal - The signal to send.
|
|
1777
|
-
* @public
|
|
1778
|
-
*/
|
|
1779
|
-
static send(signal) {
|
|
1780
|
-
const found = signals[signal];
|
|
1781
|
-
if (found) {
|
|
1782
|
-
Array.isArray(found) ? found.forEach(x => x()) : found();
|
|
1783
|
-
}
|
|
1784
|
-
}
|
|
1785
|
-
}
|
|
1786
1707
|
/**
|
|
1787
1708
|
* A binding behavior for bindings that change.
|
|
1788
1709
|
* @public
|
|
1789
1710
|
*/
|
|
1790
|
-
class
|
|
1711
|
+
class BindingBehavior {
|
|
1791
1712
|
/**
|
|
1792
1713
|
* Creates an instance of ChangeBinding.
|
|
1793
1714
|
* @param directive - The directive that has the configuration for this behavior.
|
|
1794
1715
|
* @param updateTarget - The function used to update the target with the latest value.
|
|
1795
1716
|
*/
|
|
1796
1717
|
constructor(directive, updateTarget) {
|
|
1797
|
-
|
|
1798
|
-
this.
|
|
1718
|
+
this.directive = directive;
|
|
1719
|
+
this.updateTarget = updateTarget;
|
|
1799
1720
|
this.observerProperty = `${directive.id}-o`;
|
|
1800
1721
|
}
|
|
1801
|
-
/**
|
|
1802
|
-
* Returns the binding observer used to update the node.
|
|
1803
|
-
* @param target - The target node.
|
|
1804
|
-
* @returns A BindingObserver.
|
|
1805
|
-
*/
|
|
1806
|
-
getObserver(target) {
|
|
1807
|
-
var _a;
|
|
1808
|
-
return ((_a = target[this.observerProperty]) !== null && _a !== void 0 ? _a : (target[this.observerProperty] = Observable.binding(this.directive.binding, this, this.isBindingVolatile)));
|
|
1809
|
-
}
|
|
1810
1722
|
/**
|
|
1811
1723
|
* Bind this behavior to the source.
|
|
1812
1724
|
* @param source - The source to bind to.
|
|
@@ -1843,12 +1755,49 @@ class ChangeBinding extends UpdateBinding {
|
|
|
1843
1755
|
const context = observer.context;
|
|
1844
1756
|
this.updateTarget(target, this.directive.targetAspect, observer.observe(source, context), source, context);
|
|
1845
1757
|
}
|
|
1758
|
+
/**
|
|
1759
|
+
* Returns the binding observer used to update the node.
|
|
1760
|
+
* @param target - The target node.
|
|
1761
|
+
* @returns A BindingObserver.
|
|
1762
|
+
*/
|
|
1763
|
+
getObserver(target) {
|
|
1764
|
+
var _a;
|
|
1765
|
+
return ((_a = target[this.observerProperty]) !== null && _a !== void 0 ? _a : (target[this.observerProperty] = this.directive.dataBinding.createObserver(this.directive, this)));
|
|
1766
|
+
}
|
|
1767
|
+
/**
|
|
1768
|
+
* Creates a behavior.
|
|
1769
|
+
* @param targets - The targets available for behaviors to be attached to.
|
|
1770
|
+
*/
|
|
1771
|
+
createBehavior(targets) {
|
|
1772
|
+
return this;
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
/**
|
|
1776
|
+
* A special binding behavior that can bind node content.
|
|
1777
|
+
* @public
|
|
1778
|
+
*/
|
|
1779
|
+
class ContentBehavior extends BindingBehavior {
|
|
1780
|
+
/**
|
|
1781
|
+
* Unbinds this behavior from the source.
|
|
1782
|
+
* @param source - The source to unbind from.
|
|
1783
|
+
* @param context - The execution context that the binding is operating within.
|
|
1784
|
+
* @param targets - The targets that behaviors in a view can attach to.
|
|
1785
|
+
*/
|
|
1786
|
+
unbind(source, context, targets) {
|
|
1787
|
+
super.unbind(source, context, targets);
|
|
1788
|
+
const target = targets[this.directive.nodeId];
|
|
1789
|
+
const view = target.$fastView;
|
|
1790
|
+
if (view !== void 0 && view.isComposed) {
|
|
1791
|
+
view.unbind();
|
|
1792
|
+
view.needsBindOnly = true;
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1846
1795
|
}
|
|
1847
1796
|
/**
|
|
1848
1797
|
* A binding behavior for handling events.
|
|
1849
1798
|
* @public
|
|
1850
1799
|
*/
|
|
1851
|
-
class
|
|
1800
|
+
class EventBehavior {
|
|
1852
1801
|
/**
|
|
1853
1802
|
* Creates an instance of EventBinding.
|
|
1854
1803
|
* @param directive - The directive that has the configuration for this behavior.
|
|
@@ -1869,7 +1818,7 @@ class EventBinding {
|
|
|
1869
1818
|
const target = targets[directive.nodeId];
|
|
1870
1819
|
target[this.sourceProperty] = source;
|
|
1871
1820
|
target[this.contextProperty] = context;
|
|
1872
|
-
target.addEventListener(directive.targetAspect, this, directive.options);
|
|
1821
|
+
target.addEventListener(directive.targetAspect, this, directive.dataBinding.options);
|
|
1873
1822
|
}
|
|
1874
1823
|
/**
|
|
1875
1824
|
* Unbinds this behavior from the source.
|
|
@@ -1881,7 +1830,7 @@ class EventBinding {
|
|
|
1881
1830
|
const directive = this.directive;
|
|
1882
1831
|
const target = targets[directive.nodeId];
|
|
1883
1832
|
target[this.sourceProperty] = target[this.contextProperty] = null;
|
|
1884
|
-
target.removeEventListener(directive.targetAspect, this, directive.options);
|
|
1833
|
+
target.removeEventListener(directive.targetAspect, this, directive.dataBinding.options);
|
|
1885
1834
|
}
|
|
1886
1835
|
/**
|
|
1887
1836
|
* Creates a behavior.
|
|
@@ -1896,110 +1845,13 @@ class EventBinding {
|
|
|
1896
1845
|
handleEvent(event) {
|
|
1897
1846
|
const target = event.currentTarget;
|
|
1898
1847
|
ExecutionContext.setEvent(event);
|
|
1899
|
-
const result = this.directive.
|
|
1848
|
+
const result = this.directive.dataBinding.evaluate(target[this.sourceProperty], target[this.contextProperty]);
|
|
1900
1849
|
ExecutionContext.setEvent(null);
|
|
1901
1850
|
if (result !== true) {
|
|
1902
1851
|
event.preventDefault();
|
|
1903
1852
|
}
|
|
1904
1853
|
}
|
|
1905
1854
|
}
|
|
1906
|
-
let twoWaySettings = {
|
|
1907
|
-
determineChangeEvent() {
|
|
1908
|
-
return "change";
|
|
1909
|
-
},
|
|
1910
|
-
};
|
|
1911
|
-
/**
|
|
1912
|
-
* A binding behavior for bindings that update in two directions.
|
|
1913
|
-
* @public
|
|
1914
|
-
*/
|
|
1915
|
-
class TwoWayBinding extends ChangeBinding {
|
|
1916
|
-
/**
|
|
1917
|
-
* Bind this behavior to the source.
|
|
1918
|
-
* @param source - The source to bind to.
|
|
1919
|
-
* @param context - The execution context that the binding is operating within.
|
|
1920
|
-
* @param targets - The targets that behaviors in a view can attach to.
|
|
1921
|
-
*/
|
|
1922
|
-
bind(source, context, targets) {
|
|
1923
|
-
var _a;
|
|
1924
|
-
super.bind(source, context, targets);
|
|
1925
|
-
const directive = this.directive;
|
|
1926
|
-
const target = targets[directive.nodeId];
|
|
1927
|
-
if (!this.changeEvent) {
|
|
1928
|
-
this.changeEvent =
|
|
1929
|
-
(_a = directive.options.changeEvent) !== null && _a !== void 0 ? _a : twoWaySettings.determineChangeEvent(directive, target);
|
|
1930
|
-
}
|
|
1931
|
-
target.addEventListener(this.changeEvent, this);
|
|
1932
|
-
}
|
|
1933
|
-
/**
|
|
1934
|
-
* Unbinds this behavior from the source.
|
|
1935
|
-
* @param source - The source to unbind from.
|
|
1936
|
-
* @param context - The execution context that the binding is operating within.
|
|
1937
|
-
* @param targets - The targets that behaviors in a view can attach to.
|
|
1938
|
-
*/
|
|
1939
|
-
unbind(source, context, targets) {
|
|
1940
|
-
super.unbind(source, context, targets);
|
|
1941
|
-
targets[this.directive.nodeId].removeEventListener(this.changeEvent, this);
|
|
1942
|
-
}
|
|
1943
|
-
/** @internal */
|
|
1944
|
-
handleEvent(event) {
|
|
1945
|
-
const directive = this.directive;
|
|
1946
|
-
const target = event.currentTarget;
|
|
1947
|
-
let value;
|
|
1948
|
-
switch (directive.aspectType) {
|
|
1949
|
-
case 1:
|
|
1950
|
-
value = target.getAttribute(directive.targetAspect);
|
|
1951
|
-
break;
|
|
1952
|
-
case 2:
|
|
1953
|
-
value = target.hasAttribute(directive.targetAspect);
|
|
1954
|
-
break;
|
|
1955
|
-
case 4:
|
|
1956
|
-
value = target.innerText;
|
|
1957
|
-
break;
|
|
1958
|
-
default:
|
|
1959
|
-
value = target[directive.targetAspect];
|
|
1960
|
-
break;
|
|
1961
|
-
}
|
|
1962
|
-
const observer = this.getObserver(target);
|
|
1963
|
-
const last = observer.last; // using internal API!!!
|
|
1964
|
-
last.propertySource[last.propertyName] = directive.options.fromView(value);
|
|
1965
|
-
}
|
|
1966
|
-
/**
|
|
1967
|
-
* Configures two-way binding.
|
|
1968
|
-
* @param settings - The settings to use for the two-way binding system.
|
|
1969
|
-
*/
|
|
1970
|
-
static configure(settings) {
|
|
1971
|
-
twoWaySettings = settings;
|
|
1972
|
-
}
|
|
1973
|
-
}
|
|
1974
|
-
/**
|
|
1975
|
-
* The default onChange binding configuration.
|
|
1976
|
-
* @public
|
|
1977
|
-
*/
|
|
1978
|
-
const onChange = BindingConfig.define(BindingMode.define(ChangeBinding), {});
|
|
1979
|
-
/**
|
|
1980
|
-
* The default twoWay binding configuration.
|
|
1981
|
-
* @public
|
|
1982
|
-
*/
|
|
1983
|
-
const twoWay = BindingConfig.define(BindingMode.define(TwoWayBinding), {
|
|
1984
|
-
fromView: v => v,
|
|
1985
|
-
});
|
|
1986
|
-
/**
|
|
1987
|
-
* The default onTime binding configuration.
|
|
1988
|
-
* @public
|
|
1989
|
-
*/
|
|
1990
|
-
const oneTime = BindingConfig.define(BindingMode.define(OneTimeBinding), {
|
|
1991
|
-
once: true,
|
|
1992
|
-
});
|
|
1993
|
-
const signalMode = BindingMode.define(SignalBinding);
|
|
1994
|
-
/**
|
|
1995
|
-
* Creates a signal binding configuration with the supplied options.
|
|
1996
|
-
* @param options - The signal name or a binding to use to retrieve the signal name.
|
|
1997
|
-
* @returns A binding configuration.
|
|
1998
|
-
* @public
|
|
1999
|
-
*/
|
|
2000
|
-
const signal = (options) => {
|
|
2001
|
-
return { mode: signalMode, options };
|
|
2002
|
-
};
|
|
2003
1855
|
/**
|
|
2004
1856
|
* A directive that applies bindings.
|
|
2005
1857
|
* @public
|
|
@@ -2007,15 +1859,15 @@ const signal = (options) => {
|
|
|
2007
1859
|
class HTMLBindingDirective {
|
|
2008
1860
|
/**
|
|
2009
1861
|
* Creates an instance of HTMLBindingDirective.
|
|
2010
|
-
* @param
|
|
2011
|
-
* @param mode - The binding mode to use when applying the binding.
|
|
2012
|
-
* @param options - The options to configure the binding with.
|
|
1862
|
+
* @param dataBinding - The binding configuration to apply.
|
|
2013
1863
|
*/
|
|
2014
|
-
constructor(
|
|
2015
|
-
this.
|
|
2016
|
-
this.mode = mode;
|
|
2017
|
-
this.options = options;
|
|
1864
|
+
constructor(dataBinding) {
|
|
1865
|
+
this.dataBinding = dataBinding;
|
|
2018
1866
|
this.factory = null;
|
|
1867
|
+
/**
|
|
1868
|
+
* The unique id of the factory.
|
|
1869
|
+
*/
|
|
1870
|
+
this.id = nextId();
|
|
2019
1871
|
/**
|
|
2020
1872
|
* The type of aspect to target.
|
|
2021
1873
|
*/
|
|
@@ -2035,26 +1887,78 @@ class HTMLBindingDirective {
|
|
|
2035
1887
|
createBehavior(targets) {
|
|
2036
1888
|
if (this.factory == null) {
|
|
2037
1889
|
if (this.targetAspect === "innerHTML") {
|
|
2038
|
-
this.
|
|
1890
|
+
this.dataBinding.evaluate = createInnerHTMLBinding(this.dataBinding.evaluate);
|
|
1891
|
+
}
|
|
1892
|
+
switch (this.aspectType) {
|
|
1893
|
+
case 1:
|
|
1894
|
+
this.factory = new BindingBehavior(this, DOM.setAttribute);
|
|
1895
|
+
break;
|
|
1896
|
+
case 2:
|
|
1897
|
+
this.factory = new BindingBehavior(this, DOM.setBooleanAttribute);
|
|
1898
|
+
break;
|
|
1899
|
+
case 3:
|
|
1900
|
+
this.factory = new BindingBehavior(this, (t, a, v) => (t[a] = v));
|
|
1901
|
+
break;
|
|
1902
|
+
case 4:
|
|
1903
|
+
this.factory = new ContentBehavior(this, updateContentTarget);
|
|
1904
|
+
break;
|
|
1905
|
+
case 5:
|
|
1906
|
+
this.factory = new BindingBehavior(this, updateTokenListTarget);
|
|
1907
|
+
break;
|
|
1908
|
+
case 6:
|
|
1909
|
+
this.factory = new EventBehavior(this);
|
|
1910
|
+
break;
|
|
1911
|
+
default:
|
|
1912
|
+
throw FAST.error(1205 /* Message.unsupportedBindingBehavior */);
|
|
2039
1913
|
}
|
|
2040
|
-
this.factory = this.mode[this.aspectType](this);
|
|
2041
1914
|
}
|
|
2042
1915
|
return this.factory.createBehavior(targets);
|
|
2043
1916
|
}
|
|
2044
1917
|
}
|
|
2045
1918
|
HTMLDirective.define(HTMLBindingDirective, { aspected: true });
|
|
2046
1919
|
/**
|
|
2047
|
-
* Creates
|
|
2048
|
-
* @param binding - The binding
|
|
2049
|
-
* @param
|
|
2050
|
-
* @returns A binding
|
|
1920
|
+
* Creates an standard binding.
|
|
1921
|
+
* @param binding - The binding to refresh when changed.
|
|
1922
|
+
* @param isVolatile - Indicates whether the binding is volatile or not.
|
|
1923
|
+
* @returns A binding configuration.
|
|
2051
1924
|
* @public
|
|
2052
1925
|
*/
|
|
2053
|
-
function bind(binding,
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
1926
|
+
function bind(binding, isVolatile = Observable.isVolatileBinding(binding)) {
|
|
1927
|
+
return new OnChangeBinding(binding, isVolatile);
|
|
1928
|
+
}
|
|
1929
|
+
/**
|
|
1930
|
+
* Creates a one time binding
|
|
1931
|
+
* @param binding - The binding to refresh when signaled.
|
|
1932
|
+
* @returns A binding configuration.
|
|
1933
|
+
* @public
|
|
1934
|
+
*/
|
|
1935
|
+
function oneTime(binding) {
|
|
1936
|
+
return new OneTimeBinding(binding);
|
|
1937
|
+
}
|
|
1938
|
+
/**
|
|
1939
|
+
* Creates an event listener binding.
|
|
1940
|
+
* @param binding - The binding to invoke when the event is raised.
|
|
1941
|
+
* @param options - Event listener options.
|
|
1942
|
+
* @returns A binding configuration.
|
|
1943
|
+
* @public
|
|
1944
|
+
*/
|
|
1945
|
+
function listener(binding, options) {
|
|
1946
|
+
const config = new OnChangeBinding(binding, false);
|
|
1947
|
+
config.options = options;
|
|
1948
|
+
return config;
|
|
1949
|
+
}
|
|
1950
|
+
/**
|
|
1951
|
+
* Normalizes the input value into a binding.
|
|
1952
|
+
* @param value - The value to create the default binding for.
|
|
1953
|
+
* @returns A binding configuration for the provided value.
|
|
1954
|
+
* @public
|
|
1955
|
+
*/
|
|
1956
|
+
function normalizeBinding(value) {
|
|
1957
|
+
return isFunction(value)
|
|
1958
|
+
? bind(value)
|
|
1959
|
+
: value instanceof Binding
|
|
1960
|
+
? value
|
|
1961
|
+
: oneTime(() => value);
|
|
2058
1962
|
}
|
|
2059
1963
|
|
|
2060
1964
|
function removeNodeSequence(firstNode, lastNode) {
|
|
@@ -2221,6 +2125,22 @@ const next = {
|
|
|
2221
2125
|
index: 0,
|
|
2222
2126
|
node: null,
|
|
2223
2127
|
};
|
|
2128
|
+
function tryWarn(name) {
|
|
2129
|
+
if (!name.startsWith("fast-")) {
|
|
2130
|
+
FAST.warn(1204 /* Message.hostBindingWithoutHost */, { name });
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
const warningHost = new Proxy(document.createElement("div"), {
|
|
2134
|
+
get(target, property) {
|
|
2135
|
+
tryWarn(property);
|
|
2136
|
+
const value = Reflect.get(target, property);
|
|
2137
|
+
return isFunction(value) ? value.bind(target) : value;
|
|
2138
|
+
},
|
|
2139
|
+
set(target, property, value) {
|
|
2140
|
+
tryWarn(property);
|
|
2141
|
+
return Reflect.set(target, property, value);
|
|
2142
|
+
},
|
|
2143
|
+
});
|
|
2224
2144
|
class CompilationContext {
|
|
2225
2145
|
constructor(fragment, directives) {
|
|
2226
2146
|
this.fragment = fragment;
|
|
@@ -2271,7 +2191,7 @@ class CompilationContext {
|
|
|
2271
2191
|
const fragment = this.fragment.cloneNode(true);
|
|
2272
2192
|
const targets = Object.create(this.proto);
|
|
2273
2193
|
targets.r = fragment;
|
|
2274
|
-
targets.h = hostBindingTarget !== null && hostBindingTarget !== void 0 ? hostBindingTarget :
|
|
2194
|
+
targets.h = hostBindingTarget !== null && hostBindingTarget !== void 0 ? hostBindingTarget : warningHost;
|
|
2275
2195
|
for (const id of this.nodeIds) {
|
|
2276
2196
|
targets[id]; // trigger locator
|
|
2277
2197
|
}
|
|
@@ -2288,7 +2208,7 @@ function compileAttributes(context, parentId, node, nodeId, nodeIndex, includeBa
|
|
|
2288
2208
|
let result = null;
|
|
2289
2209
|
if (parseResult === null) {
|
|
2290
2210
|
if (includeBasicValues) {
|
|
2291
|
-
result =
|
|
2211
|
+
result = new HTMLBindingDirective(oneTime(() => attrValue));
|
|
2292
2212
|
Aspect.assign(result, attr.name);
|
|
2293
2213
|
}
|
|
2294
2214
|
}
|
|
@@ -2325,6 +2245,7 @@ function compileContent(context, node, parentId, nodeId, nodeIndex) {
|
|
|
2325
2245
|
}
|
|
2326
2246
|
else {
|
|
2327
2247
|
currentNode.textContent = " ";
|
|
2248
|
+
Aspect.assign(currentPart);
|
|
2328
2249
|
context.addFactory(currentPart, parentId, nodeId, nodeIndex);
|
|
2329
2250
|
}
|
|
2330
2251
|
lastNode = currentNode;
|
|
@@ -2457,22 +2378,28 @@ const Compiler = {
|
|
|
2457
2378
|
return parts[0];
|
|
2458
2379
|
}
|
|
2459
2380
|
let sourceAspect;
|
|
2381
|
+
let binding;
|
|
2382
|
+
let isVolatile = false;
|
|
2460
2383
|
const partCount = parts.length;
|
|
2461
2384
|
const finalParts = parts.map((x) => {
|
|
2462
2385
|
if (isString(x)) {
|
|
2463
2386
|
return () => x;
|
|
2464
2387
|
}
|
|
2465
2388
|
sourceAspect = x.sourceAspect || sourceAspect;
|
|
2466
|
-
|
|
2389
|
+
binding = x.dataBinding || binding;
|
|
2390
|
+
isVolatile = isVolatile || x.dataBinding.isVolatile;
|
|
2391
|
+
return x.dataBinding.evaluate;
|
|
2467
2392
|
});
|
|
2468
|
-
const
|
|
2393
|
+
const expression = (scope, context) => {
|
|
2469
2394
|
let output = "";
|
|
2470
2395
|
for (let i = 0; i < partCount; ++i) {
|
|
2471
2396
|
output += finalParts[i](scope, context);
|
|
2472
2397
|
}
|
|
2473
2398
|
return output;
|
|
2474
2399
|
};
|
|
2475
|
-
|
|
2400
|
+
binding.evaluate = expression;
|
|
2401
|
+
binding.isVolatile = isVolatile;
|
|
2402
|
+
const directive = new HTMLBindingDirective(binding);
|
|
2476
2403
|
Aspect.assign(directive, sourceAspect);
|
|
2477
2404
|
return directive;
|
|
2478
2405
|
},
|
|
@@ -2552,12 +2479,12 @@ function html(strings, ...values) {
|
|
|
2552
2479
|
let definition;
|
|
2553
2480
|
html += currentString;
|
|
2554
2481
|
if (isFunction(currentValue)) {
|
|
2555
|
-
html += createAspectedHTML(bind(currentValue), currentString, add);
|
|
2482
|
+
html += createAspectedHTML(new HTMLBindingDirective(bind(currentValue)), currentString, add);
|
|
2556
2483
|
}
|
|
2557
2484
|
else if (isString(currentValue)) {
|
|
2558
2485
|
const match = lastAttributeNameRegex.exec(currentString);
|
|
2559
2486
|
if (match !== null) {
|
|
2560
|
-
const directive =
|
|
2487
|
+
const directive = new HTMLBindingDirective(oneTime(() => currentValue));
|
|
2561
2488
|
Aspect.assign(directive, match[2]);
|
|
2562
2489
|
html += directive.createHTML(add);
|
|
2563
2490
|
}
|
|
@@ -2565,8 +2492,11 @@ function html(strings, ...values) {
|
|
|
2565
2492
|
html += currentValue;
|
|
2566
2493
|
}
|
|
2567
2494
|
}
|
|
2495
|
+
else if (currentValue instanceof Binding) {
|
|
2496
|
+
html += createAspectedHTML(new HTMLBindingDirective(currentValue), currentString, add);
|
|
2497
|
+
}
|
|
2568
2498
|
else if ((definition = HTMLDirective.getForInstance(currentValue)) === void 0) {
|
|
2569
|
-
html += createAspectedHTML(
|
|
2499
|
+
html += createAspectedHTML(new HTMLBindingDirective(oneTime(() => currentValue)), currentString, add);
|
|
2570
2500
|
}
|
|
2571
2501
|
else {
|
|
2572
2502
|
if (definition.aspected) {
|
|
@@ -2579,26 +2509,6 @@ function html(strings, ...values) {
|
|
|
2579
2509
|
}
|
|
2580
2510
|
return new ViewTemplate(html + strings[strings.length - 1], factories);
|
|
2581
2511
|
}
|
|
2582
|
-
/**
|
|
2583
|
-
* Transforms a template literal string into a ChildViewTemplate.
|
|
2584
|
-
* @param strings - The string fragments that are interpolated with the values.
|
|
2585
|
-
* @param values - The values that are interpolated with the string fragments.
|
|
2586
|
-
* @remarks
|
|
2587
|
-
* The html helper supports interpolation of strings, numbers, binding expressions,
|
|
2588
|
-
* other template instances, and Directive instances.
|
|
2589
|
-
* @public
|
|
2590
|
-
*/
|
|
2591
|
-
const child = html;
|
|
2592
|
-
/**
|
|
2593
|
-
* Transforms a template literal string into an ItemViewTemplate.
|
|
2594
|
-
* @param strings - The string fragments that are interpolated with the values.
|
|
2595
|
-
* @param values - The values that are interpolated with the string fragments.
|
|
2596
|
-
* @remarks
|
|
2597
|
-
* The html helper supports interpolation of strings, numbers, binding expressions,
|
|
2598
|
-
* other template instances, and Directive instances.
|
|
2599
|
-
* @public
|
|
2600
|
-
*/
|
|
2601
|
-
const item = html;
|
|
2602
2512
|
|
|
2603
2513
|
/**
|
|
2604
2514
|
* The runtime behavior for template references.
|
|
@@ -2631,16 +2541,17 @@ const ref = (propertyName) => new RefDirective(propertyName);
|
|
|
2631
2541
|
|
|
2632
2542
|
/**
|
|
2633
2543
|
* A directive that enables basic conditional rendering in a template.
|
|
2634
|
-
* @param
|
|
2544
|
+
* @param condition - The condition to test for rendering.
|
|
2635
2545
|
* @param templateOrTemplateBinding - The template or a binding that gets
|
|
2636
2546
|
* the template to render when the condition is true.
|
|
2637
2547
|
* @public
|
|
2638
2548
|
*/
|
|
2639
|
-
function when(
|
|
2640
|
-
const
|
|
2549
|
+
function when(condition, templateOrTemplateBinding) {
|
|
2550
|
+
const dataBinding = isFunction(condition) ? condition : () => condition;
|
|
2551
|
+
const templateBinding = isFunction(templateOrTemplateBinding)
|
|
2641
2552
|
? templateOrTemplateBinding
|
|
2642
2553
|
: () => templateOrTemplateBinding;
|
|
2643
|
-
return (source, context) =>
|
|
2554
|
+
return (source, context) => dataBinding(source, context) ? templateBinding(source, context) : null;
|
|
2644
2555
|
}
|
|
2645
2556
|
|
|
2646
2557
|
const defaultRepeatOptions = Object.freeze({
|
|
@@ -2661,17 +2572,15 @@ class RepeatBehavior {
|
|
|
2661
2572
|
/**
|
|
2662
2573
|
* Creates an instance of RepeatBehavior.
|
|
2663
2574
|
* @param location - The location in the DOM to render the repeat.
|
|
2664
|
-
* @param
|
|
2575
|
+
* @param dataBinding - The array to render.
|
|
2665
2576
|
* @param isItemsBindingVolatile - Indicates whether the items binding has volatile dependencies.
|
|
2666
2577
|
* @param templateBinding - The template to render for each item.
|
|
2667
2578
|
* @param isTemplateBindingVolatile - Indicates whether the template binding has volatile dependencies.
|
|
2668
2579
|
* @param options - Options used to turn on special repeat features.
|
|
2669
2580
|
*/
|
|
2670
|
-
constructor(
|
|
2581
|
+
constructor(directive, location) {
|
|
2582
|
+
this.directive = directive;
|
|
2671
2583
|
this.location = location;
|
|
2672
|
-
this.itemsBinding = itemsBinding;
|
|
2673
|
-
this.templateBinding = templateBinding;
|
|
2674
|
-
this.options = options;
|
|
2675
2584
|
this.source = null;
|
|
2676
2585
|
this.views = [];
|
|
2677
2586
|
this.items = null;
|
|
@@ -2679,9 +2588,9 @@ class RepeatBehavior {
|
|
|
2679
2588
|
this.context = void 0;
|
|
2680
2589
|
this.childContext = void 0;
|
|
2681
2590
|
this.bindView = bindWithoutPositioning;
|
|
2682
|
-
this.itemsBindingObserver =
|
|
2683
|
-
this.templateBindingObserver =
|
|
2684
|
-
if (options.positioning) {
|
|
2591
|
+
this.itemsBindingObserver = directive.dataBinding.createObserver(directive, this);
|
|
2592
|
+
this.templateBindingObserver = directive.templateBinding.createObserver(directive, this);
|
|
2593
|
+
if (directive.options.positioning) {
|
|
2685
2594
|
this.bindView = bindWithPositioning;
|
|
2686
2595
|
}
|
|
2687
2596
|
}
|
|
@@ -2719,12 +2628,12 @@ class RepeatBehavior {
|
|
|
2719
2628
|
* @param args - The details about what was changed.
|
|
2720
2629
|
*/
|
|
2721
2630
|
handleChange(source, args) {
|
|
2722
|
-
if (
|
|
2631
|
+
if (args === this.itemsBindingObserver) {
|
|
2723
2632
|
this.items = this.itemsBindingObserver.observe(this.source, this.context);
|
|
2724
2633
|
this.observeItems();
|
|
2725
2634
|
this.refreshAllViews();
|
|
2726
2635
|
}
|
|
2727
|
-
else if (
|
|
2636
|
+
else if (args === this.templateBindingObserver) {
|
|
2728
2637
|
this.template = this.templateBindingObserver.observe(this.source, this.context);
|
|
2729
2638
|
this.refreshAllViews(true);
|
|
2730
2639
|
}
|
|
@@ -2753,36 +2662,51 @@ class RepeatBehavior {
|
|
|
2753
2662
|
updateViews(splices) {
|
|
2754
2663
|
const views = this.views;
|
|
2755
2664
|
const childContext = this.childContext;
|
|
2756
|
-
const totalRemoved = [];
|
|
2757
2665
|
const bindView = this.bindView;
|
|
2758
|
-
let removeDelta = 0;
|
|
2759
|
-
for (let i = 0, ii = splices.length; i < ii; ++i) {
|
|
2760
|
-
const splice = splices[i];
|
|
2761
|
-
const removed = splice.removed;
|
|
2762
|
-
totalRemoved.push(...views.splice(splice.index + removeDelta, removed.length));
|
|
2763
|
-
removeDelta -= splice.addedCount;
|
|
2764
|
-
}
|
|
2765
2666
|
const items = this.items;
|
|
2766
2667
|
const template = this.template;
|
|
2668
|
+
const recycle = this.directive.options.recycle;
|
|
2669
|
+
const leftoverViews = [];
|
|
2670
|
+
let leftoverIndex = 0;
|
|
2671
|
+
let availableViews = 0;
|
|
2767
2672
|
for (let i = 0, ii = splices.length; i < ii; ++i) {
|
|
2768
2673
|
const splice = splices[i];
|
|
2674
|
+
const removed = splice.removed;
|
|
2675
|
+
let removeIndex = 0;
|
|
2769
2676
|
let addIndex = splice.index;
|
|
2770
2677
|
const end = addIndex + splice.addedCount;
|
|
2678
|
+
const removedViews = views.splice(splice.index, removed.length);
|
|
2679
|
+
availableViews = leftoverViews.length + removedViews.length;
|
|
2771
2680
|
for (; addIndex < end; ++addIndex) {
|
|
2772
2681
|
const neighbor = views[addIndex];
|
|
2773
2682
|
const location = neighbor ? neighbor.firstChild : this.location;
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2683
|
+
let view;
|
|
2684
|
+
if (recycle && availableViews > 0) {
|
|
2685
|
+
if (removeIndex <= availableViews && removedViews.length > 0) {
|
|
2686
|
+
view = removedViews[removeIndex];
|
|
2687
|
+
removeIndex++;
|
|
2688
|
+
}
|
|
2689
|
+
else {
|
|
2690
|
+
view = leftoverViews[leftoverIndex];
|
|
2691
|
+
leftoverIndex++;
|
|
2692
|
+
}
|
|
2693
|
+
availableViews--;
|
|
2694
|
+
}
|
|
2695
|
+
else {
|
|
2696
|
+
view = template.create();
|
|
2697
|
+
}
|
|
2777
2698
|
views.splice(addIndex, 0, view);
|
|
2778
2699
|
bindView(view, items, addIndex, childContext);
|
|
2779
2700
|
view.insertBefore(location);
|
|
2780
2701
|
}
|
|
2702
|
+
if (removedViews[removeIndex]) {
|
|
2703
|
+
leftoverViews.push(...removedViews.slice(removeIndex));
|
|
2704
|
+
}
|
|
2781
2705
|
}
|
|
2782
|
-
for (let i =
|
|
2783
|
-
|
|
2706
|
+
for (let i = leftoverIndex, ii = leftoverViews.length; i < ii; ++i) {
|
|
2707
|
+
leftoverViews[i].dispose();
|
|
2784
2708
|
}
|
|
2785
|
-
if (this.options.positioning) {
|
|
2709
|
+
if (this.directive.options.positioning) {
|
|
2786
2710
|
for (let i = 0, ii = views.length; i < ii; ++i) {
|
|
2787
2711
|
views[i].context.updatePosition(i, ii);
|
|
2788
2712
|
}
|
|
@@ -2797,7 +2721,7 @@ class RepeatBehavior {
|
|
|
2797
2721
|
let itemsLength = items.length;
|
|
2798
2722
|
let views = this.views;
|
|
2799
2723
|
let viewsLength = views.length;
|
|
2800
|
-
if (itemsLength === 0 || templateChanged) {
|
|
2724
|
+
if (itemsLength === 0 || templateChanged || !this.directive.options.recycle) {
|
|
2801
2725
|
// all views need to be removed
|
|
2802
2726
|
HTMLView.disposeContiguousBatch(views);
|
|
2803
2727
|
viewsLength = 0;
|
|
@@ -2847,17 +2771,19 @@ class RepeatBehavior {
|
|
|
2847
2771
|
class RepeatDirective {
|
|
2848
2772
|
/**
|
|
2849
2773
|
* Creates an instance of RepeatDirective.
|
|
2850
|
-
* @param
|
|
2774
|
+
* @param dataBinding - The binding that provides the array to render.
|
|
2851
2775
|
* @param templateBinding - The template binding used to obtain a template to render for each item in the array.
|
|
2852
2776
|
* @param options - Options used to turn on special repeat features.
|
|
2853
2777
|
*/
|
|
2854
|
-
constructor(
|
|
2855
|
-
this.
|
|
2778
|
+
constructor(dataBinding, templateBinding, options) {
|
|
2779
|
+
this.dataBinding = dataBinding;
|
|
2856
2780
|
this.templateBinding = templateBinding;
|
|
2857
2781
|
this.options = options;
|
|
2782
|
+
/**
|
|
2783
|
+
* The unique id of the factory.
|
|
2784
|
+
*/
|
|
2785
|
+
this.id = nextId();
|
|
2858
2786
|
ArrayObserver.enable();
|
|
2859
|
-
this.isItemsBindingVolatile = Observable.isVolatileBinding(itemsBinding);
|
|
2860
|
-
this.isTemplateBindingVolatile = Observable.isVolatileBinding(templateBinding);
|
|
2861
2787
|
}
|
|
2862
2788
|
/**
|
|
2863
2789
|
* Creates a placeholder string based on the directive's index within the template.
|
|
@@ -2871,15 +2797,22 @@ class RepeatDirective {
|
|
|
2871
2797
|
* @param target - The node instance to create the behavior for.
|
|
2872
2798
|
*/
|
|
2873
2799
|
createBehavior(targets) {
|
|
2874
|
-
return new RepeatBehavior(targets[this.nodeId]
|
|
2800
|
+
return new RepeatBehavior(this, targets[this.nodeId]);
|
|
2875
2801
|
}
|
|
2876
2802
|
}
|
|
2877
2803
|
HTMLDirective.define(RepeatDirective);
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2804
|
+
/**
|
|
2805
|
+
* A directive that enables list rendering.
|
|
2806
|
+
* @param items - The array to render.
|
|
2807
|
+
* @param template - The template or a template binding used obtain a template
|
|
2808
|
+
* to render for each item in the array.
|
|
2809
|
+
* @param options - Options used to turn on special repeat features.
|
|
2810
|
+
* @public
|
|
2811
|
+
*/
|
|
2812
|
+
function repeat(items, template, options = defaultRepeatOptions) {
|
|
2813
|
+
const dataBinding = normalizeBinding(items);
|
|
2814
|
+
const templateBinding = normalizeBinding(template);
|
|
2815
|
+
return new RepeatDirective(dataBinding, templateBinding, options);
|
|
2883
2816
|
}
|
|
2884
2817
|
|
|
2885
2818
|
const selectElements = (value) => value.nodeType === 1;
|
|
@@ -3264,19 +3197,15 @@ const fastElementRegistry = FAST.getById(4 /* KernelServiceId.elementRegistry */
|
|
|
3264
3197
|
* @public
|
|
3265
3198
|
*/
|
|
3266
3199
|
class FASTElementDefinition {
|
|
3267
|
-
/**
|
|
3268
|
-
* Creates an instance of FASTElementDefinition.
|
|
3269
|
-
* @param type - The type this definition is being created for.
|
|
3270
|
-
* @param nameOrConfig - The name of the element to define or a config object
|
|
3271
|
-
* that describes the element to define.
|
|
3272
|
-
*/
|
|
3273
3200
|
constructor(type, nameOrConfig = type.definition) {
|
|
3201
|
+
this.platformDefined = false;
|
|
3274
3202
|
if (isString(nameOrConfig)) {
|
|
3275
3203
|
nameOrConfig = { name: nameOrConfig };
|
|
3276
3204
|
}
|
|
3277
3205
|
this.type = type;
|
|
3278
3206
|
this.name = nameOrConfig.name;
|
|
3279
3207
|
this.template = nameOrConfig.template;
|
|
3208
|
+
const proto = type.prototype;
|
|
3280
3209
|
const attributes = AttributeDefinition.collect(type, nameOrConfig.attributes);
|
|
3281
3210
|
const observedAttributes = new Array(attributes.length);
|
|
3282
3211
|
const propertyLookup = {};
|
|
@@ -3286,9 +3215,13 @@ class FASTElementDefinition {
|
|
|
3286
3215
|
observedAttributes[i] = current.attribute;
|
|
3287
3216
|
propertyLookup[current.name] = current;
|
|
3288
3217
|
attributeLookup[current.attribute] = current;
|
|
3218
|
+
Observable.defineProperty(proto, current);
|
|
3289
3219
|
}
|
|
3220
|
+
Reflect.defineProperty(type, "observedAttributes", {
|
|
3221
|
+
value: observedAttributes,
|
|
3222
|
+
enumerable: true,
|
|
3223
|
+
});
|
|
3290
3224
|
this.attributes = attributes;
|
|
3291
|
-
this.observedAttributes = observedAttributes;
|
|
3292
3225
|
this.propertyLookup = propertyLookup;
|
|
3293
3226
|
this.attributeLookup = attributeLookup;
|
|
3294
3227
|
this.shadowOptions =
|
|
@@ -3301,43 +3234,43 @@ class FASTElementDefinition {
|
|
|
3301
3234
|
nameOrConfig.elementOptions === void 0
|
|
3302
3235
|
? defaultElementOptions
|
|
3303
3236
|
: Object.assign(Object.assign({}, defaultElementOptions), nameOrConfig.elementOptions);
|
|
3304
|
-
this.styles =
|
|
3305
|
-
|
|
3306
|
-
? void 0
|
|
3307
|
-
: Array.isArray(nameOrConfig.styles)
|
|
3308
|
-
? new ElementStyles(nameOrConfig.styles)
|
|
3309
|
-
: nameOrConfig.styles instanceof ElementStyles
|
|
3310
|
-
? nameOrConfig.styles
|
|
3311
|
-
: new ElementStyles([nameOrConfig.styles]);
|
|
3237
|
+
this.styles = ElementStyles.normalize(nameOrConfig.styles);
|
|
3238
|
+
fastElementRegistry.register(this);
|
|
3312
3239
|
}
|
|
3313
3240
|
/**
|
|
3314
3241
|
* Indicates if this element has been defined in at least one registry.
|
|
3315
3242
|
*/
|
|
3316
3243
|
get isDefined() {
|
|
3317
|
-
return
|
|
3244
|
+
return this.platformDefined;
|
|
3318
3245
|
}
|
|
3319
3246
|
/**
|
|
3320
3247
|
* Defines a custom element based on this definition.
|
|
3321
3248
|
* @param registry - The element registry to define the element in.
|
|
3249
|
+
* @remarks
|
|
3250
|
+
* This operation is idempotent per registry.
|
|
3322
3251
|
*/
|
|
3323
3252
|
define(registry = customElements) {
|
|
3324
3253
|
const type = this.type;
|
|
3325
|
-
if (fastElementRegistry.register(this)) {
|
|
3326
|
-
const attributes = this.attributes;
|
|
3327
|
-
const proto = type.prototype;
|
|
3328
|
-
for (let i = 0, ii = attributes.length; i < ii; ++i) {
|
|
3329
|
-
Observable.defineProperty(proto, attributes[i]);
|
|
3330
|
-
}
|
|
3331
|
-
Reflect.defineProperty(type, "observedAttributes", {
|
|
3332
|
-
value: this.observedAttributes,
|
|
3333
|
-
enumerable: true,
|
|
3334
|
-
});
|
|
3335
|
-
}
|
|
3336
3254
|
if (!registry.get(this.name)) {
|
|
3255
|
+
this.platformDefined = true;
|
|
3337
3256
|
registry.define(this.name, type, this.elementOptions);
|
|
3338
3257
|
}
|
|
3339
3258
|
return this;
|
|
3340
3259
|
}
|
|
3260
|
+
/**
|
|
3261
|
+
* Creates an instance of FASTElementDefinition.
|
|
3262
|
+
* @param type - The type this definition is being created for.
|
|
3263
|
+
* @param nameOrDef - The name of the element to define or a config object
|
|
3264
|
+
* that describes the element to define.
|
|
3265
|
+
*/
|
|
3266
|
+
static compose(type, nameOrDef) {
|
|
3267
|
+
const found = fastElementRegistry.getByType(type);
|
|
3268
|
+
if (found) {
|
|
3269
|
+
return new FASTElementDefinition(class extends type {
|
|
3270
|
+
}, nameOrDef);
|
|
3271
|
+
}
|
|
3272
|
+
return new FASTElementDefinition(type, nameOrDef);
|
|
3273
|
+
}
|
|
3341
3274
|
}
|
|
3342
3275
|
/**
|
|
3343
3276
|
* Gets the element definition associated with the specified type.
|
|
@@ -3755,6 +3688,18 @@ function createFASTElement(BaseType) {
|
|
|
3755
3688
|
}
|
|
3756
3689
|
};
|
|
3757
3690
|
}
|
|
3691
|
+
function compose(type, nameOrDef) {
|
|
3692
|
+
if (isFunction(type)) {
|
|
3693
|
+
return FASTElementDefinition.compose(type, nameOrDef);
|
|
3694
|
+
}
|
|
3695
|
+
return FASTElementDefinition.compose(this, type);
|
|
3696
|
+
}
|
|
3697
|
+
function define(type, nameOrDef) {
|
|
3698
|
+
if (isFunction(type)) {
|
|
3699
|
+
return FASTElementDefinition.compose(type, nameOrDef).define().type;
|
|
3700
|
+
}
|
|
3701
|
+
return FASTElementDefinition.compose(this, type).define().type;
|
|
3702
|
+
}
|
|
3758
3703
|
/**
|
|
3759
3704
|
* A minimal base class for FASTElements that also provides
|
|
3760
3705
|
* static helpers for working with FASTElements.
|
|
@@ -3775,9 +3720,12 @@ const FASTElement = Object.assign(createFASTElement(HTMLElement), {
|
|
|
3775
3720
|
* @param nameOrDef - The name of the element to define or a definition object
|
|
3776
3721
|
* that describes the element to define.
|
|
3777
3722
|
*/
|
|
3778
|
-
define
|
|
3779
|
-
|
|
3780
|
-
|
|
3723
|
+
define,
|
|
3724
|
+
/**
|
|
3725
|
+
* Defines metadata for a FASTElement which can be used to later define the element.
|
|
3726
|
+
* @public
|
|
3727
|
+
*/
|
|
3728
|
+
compose,
|
|
3781
3729
|
});
|
|
3782
3730
|
/**
|
|
3783
3731
|
* Decorator: Defines a platform custom element based on `FASTElement`.
|
|
@@ -3788,8 +3736,8 @@ const FASTElement = Object.assign(createFASTElement(HTMLElement), {
|
|
|
3788
3736
|
function customElement(nameOrDef) {
|
|
3789
3737
|
/* eslint-disable-next-line @typescript-eslint/explicit-function-return-type */
|
|
3790
3738
|
return function (type) {
|
|
3791
|
-
|
|
3739
|
+
define(type, nameOrDef);
|
|
3792
3740
|
};
|
|
3793
3741
|
}
|
|
3794
3742
|
|
|
3795
|
-
export { AdoptedStyleSheetsStrategy, ArrayObserver, Aspect, AttributeDefinition,
|
|
3743
|
+
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 };
|