@microsoft/fast-element 2.0.0-beta.3 → 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.
Files changed (50) hide show
  1. package/CHANGELOG.json +81 -0
  2. package/CHANGELOG.md +20 -1
  3. package/dist/dts/components/fast-definitions.d.ts +9 -8
  4. package/dist/dts/components/fast-element.d.ts +8 -4
  5. package/dist/dts/context.d.ts +1 -1
  6. package/dist/dts/di/di.d.ts +854 -0
  7. package/dist/dts/hooks.d.ts +2 -2
  8. package/dist/dts/interfaces.d.ts +38 -7
  9. package/dist/dts/observation/observable.d.ts +19 -13
  10. package/dist/dts/styles/element-styles.d.ts +6 -0
  11. package/dist/dts/templating/binding-signal.d.ts +10 -27
  12. package/dist/dts/templating/binding-two-way.d.ts +16 -41
  13. package/dist/dts/templating/binding.d.ts +79 -118
  14. package/dist/dts/templating/html-directive.d.ts +28 -2
  15. package/dist/dts/templating/render.d.ts +277 -0
  16. package/dist/dts/templating/repeat.d.ts +12 -16
  17. package/dist/dts/templating/template.d.ts +3 -3
  18. package/dist/dts/templating/when.d.ts +3 -3
  19. package/dist/dts/testing/exports.d.ts +2 -0
  20. package/dist/dts/testing/fixture.d.ts +90 -0
  21. package/dist/dts/testing/timeout.d.ts +7 -0
  22. package/dist/esm/components/fast-definitions.js +25 -27
  23. package/dist/esm/components/fast-element.js +16 -8
  24. package/dist/esm/context.js +5 -1
  25. package/dist/esm/debug.js +34 -4
  26. package/dist/esm/di/di.js +1349 -0
  27. package/dist/esm/observation/observable.js +4 -4
  28. package/dist/esm/platform.js +1 -1
  29. package/dist/esm/styles/element-styles.js +14 -0
  30. package/dist/esm/templating/binding-signal.js +56 -61
  31. package/dist/esm/templating/binding-two-way.js +51 -35
  32. package/dist/esm/templating/binding.js +137 -156
  33. package/dist/esm/templating/compiler.js +29 -7
  34. package/dist/esm/templating/html-directive.js +12 -1
  35. package/dist/esm/templating/render.js +392 -0
  36. package/dist/esm/templating/repeat.js +54 -40
  37. package/dist/esm/templating/template.js +8 -5
  38. package/dist/esm/templating/when.js +5 -4
  39. package/dist/esm/testing/exports.js +2 -0
  40. package/dist/esm/testing/fixture.js +88 -0
  41. package/dist/esm/testing/timeout.js +24 -0
  42. package/dist/fast-element.api.json +3257 -3151
  43. package/dist/fast-element.d.ts +210 -209
  44. package/dist/fast-element.debug.js +329 -248
  45. package/dist/fast-element.debug.min.js +1 -1
  46. package/dist/fast-element.js +295 -244
  47. package/dist/fast-element.min.js +1 -1
  48. package/dist/fast-element.untrimmed.d.ts +218 -214
  49. package/docs/api-report.md +83 -85
  50. package/package.json +13 -1
@@ -63,7 +63,7 @@ export const Observable = FAST.getById(2 /* KernelServiceId.observable */, () =>
63
63
  }
64
64
  }
65
65
  }
66
- class BindingObserverImplementation extends SubscriberSet {
66
+ class ExpressionNotifierImplementation extends SubscriberSet {
67
67
  constructor(binding, initialSubscriber, isVolatileBinding = false) {
68
68
  super(binding, initialSubscriber);
69
69
  this.binding = binding;
@@ -218,14 +218,14 @@ export const Observable = FAST.getById(2 /* KernelServiceId.observable */, () =>
218
218
  */
219
219
  getAccessors,
220
220
  /**
221
- * Creates a {@link BindingObserver} that can watch the
222
- * provided {@link Binding} for changes.
221
+ * Creates a {@link ExpressionNotifier} that can watch the
222
+ * provided {@link Expression} for changes.
223
223
  * @param binding - The binding to observe.
224
224
  * @param initialSubscriber - An initial subscriber to changes in the binding value.
225
225
  * @param isVolatileBinding - Indicates whether the binding's dependency list must be re-evaluated on every value evaluation.
226
226
  */
227
227
  binding(binding, initialSubscriber, isVolatileBinding = this.isVolatileBinding(binding)) {
228
- return new BindingObserverImplementation(binding, initialSubscriber, isVolatileBinding);
228
+ return new ExpressionNotifierImplementation(binding, initialSubscriber, isVolatileBinding);
229
229
  },
230
230
  /**
231
231
  * Determines whether a binding expression is volatile and needs to have its dependency list re-evaluated
@@ -26,7 +26,7 @@ if (FAST.error === void 0) {
26
26
  Object.assign(FAST, {
27
27
  warn() { },
28
28
  error(code) {
29
- return new Error(`Code ${code}`);
29
+ return new Error(`Error ${code}`);
30
30
  },
31
31
  addMessages() { },
32
32
  });
@@ -71,6 +71,20 @@ export class ElementStyles {
71
71
  static setDefaultStrategy(Strategy) {
72
72
  DefaultStyleStrategy = Strategy;
73
73
  }
74
+ /**
75
+ * Normalizes a set of composable style options.
76
+ * @param styles - The style options to normalize.
77
+ * @returns A singular ElementStyles instance or undefined.
78
+ */
79
+ static normalize(styles) {
80
+ return styles === void 0
81
+ ? void 0
82
+ : Array.isArray(styles)
83
+ ? new ElementStyles(styles)
84
+ : styles instanceof ElementStyles
85
+ ? styles
86
+ : new ElementStyles([styles]);
87
+ }
74
88
  }
75
89
  /**
76
90
  * Indicates whether the DOM supports the adoptedStyleSheets feature.
@@ -1,84 +1,79 @@
1
1
  import { isString } from "../interfaces.js";
2
- import { BindingMode, UpdateBinding } from "./binding.js";
3
- const signals = Object.create(null);
4
- /**
5
- * A binding behavior for signal bindings.
6
- * @public
7
- */
8
- export class SignalBinding extends UpdateBinding {
9
- constructor() {
10
- super(...arguments);
11
- this.handlerProperty = `${this.directive.id}-h`;
12
- }
13
- /**
14
- * Bind this behavior to the source.
15
- * @param source - The source to bind to.
16
- * @param context - The execution context that the binding is operating within.
17
- * @param targets - The targets that behaviors in a view can attach to.
18
- */
19
- bind(source, context, targets) {
20
- const directive = this.directive;
21
- const target = targets[directive.nodeId];
22
- const signal = this.getSignal(source, context);
23
- const handler = (target[this.handlerProperty] = () => {
24
- this.updateTarget(target, directive.targetAspect, directive.binding(source, context), source, context);
25
- });
26
- handler();
27
- const found = signals[signal];
2
+ import { Binding } from "./html-directive.js";
3
+ const subscribers = Object.create(null);
4
+ export const Signal = Object.freeze({
5
+ subscribe(signal, subscriber) {
6
+ const found = subscribers[signal];
28
7
  if (found) {
29
- Array.isArray(found)
30
- ? found.push(handler)
31
- : (signals[signal] = [found, handler]);
8
+ found instanceof Set
9
+ ? found.add(subscriber)
10
+ : (subscribers[signal] = new Set([found, subscriber]));
32
11
  }
33
12
  else {
34
- signals[signal] = handler;
13
+ subscribers[signal] = subscriber;
35
14
  }
36
- }
37
- /**
38
- * Unbinds this behavior from the source.
39
- * @param source - The source to unbind from.
40
- * @param context - The execution context that the binding is operating within.
41
- * @param targets - The targets that behaviors in a view can attach to.
42
- */
43
- unbind(source, context, targets) {
44
- const signal = this.getSignal(source, context);
45
- const found = signals[signal];
46
- if (found && Array.isArray(found)) {
47
- const directive = this.directive;
48
- const target = targets[directive.nodeId];
49
- const handler = target[this.handlerProperty];
50
- const index = found.indexOf(handler);
51
- if (index !== -1) {
52
- found.splice(index, 1);
53
- }
15
+ },
16
+ unsubscribe(signal, subscriber) {
17
+ const found = subscribers[signal];
18
+ if (found && found instanceof Set) {
19
+ found.delete(subscriber);
54
20
  }
55
21
  else {
56
- signals[signal] = void 0;
22
+ subscribers[signal] = void 0;
57
23
  }
58
- }
59
- getSignal(source, context) {
60
- const options = this.directive.options;
61
- return isString(options) ? options : options(source, context);
62
- }
24
+ },
63
25
  /**
64
26
  * Sends the specified signal to signaled bindings.
65
27
  * @param signal - The signal to send.
66
28
  * @public
67
29
  */
68
- static send(signal) {
69
- const found = signals[signal];
30
+ send(signal) {
31
+ const found = subscribers[signal];
70
32
  if (found) {
71
- Array.isArray(found) ? found.forEach(x => x()) : found();
33
+ found instanceof Set
34
+ ? found.forEach(x => x.handleChange(this, signal))
35
+ : found.handleChange(this, signal);
72
36
  }
37
+ },
38
+ });
39
+ class SignalObserver {
40
+ constructor(dataBinding, subscriber) {
41
+ this.dataBinding = dataBinding;
42
+ this.subscriber = subscriber;
43
+ }
44
+ observe(source, context) {
45
+ const signal = (this.signal = this.getSignal(source, context));
46
+ Signal.subscribe(signal, this);
47
+ return this.dataBinding.evaluate(source, context);
48
+ }
49
+ dispose() {
50
+ Signal.unsubscribe(this.signal, this);
51
+ }
52
+ handleChange() {
53
+ this.subscriber.handleChange(this.dataBinding.evaluate, this);
54
+ }
55
+ getSignal(source, context) {
56
+ const options = this.dataBinding.options;
57
+ return isString(options) ? options : options(source, context);
58
+ }
59
+ }
60
+ class SignalBinding extends Binding {
61
+ constructor(evaluate, options) {
62
+ super();
63
+ this.evaluate = evaluate;
64
+ this.options = options;
65
+ }
66
+ createObserver(directive, subscriber) {
67
+ return new SignalObserver(this, subscriber);
73
68
  }
74
69
  }
75
- const signalMode = BindingMode.define(SignalBinding);
76
70
  /**
77
71
  * Creates a signal binding configuration with the supplied options.
72
+ * @param binding - The binding to refresh when signaled.
78
73
  * @param options - The signal name or a binding to use to retrieve the signal name.
79
74
  * @returns A binding configuration.
80
75
  * @public
81
76
  */
82
- export const signal = (options) => {
83
- return { mode: signalMode, options };
84
- };
77
+ export function signal(binding, options) {
78
+ return new SignalBinding(binding, options);
79
+ }
@@ -1,49 +1,45 @@
1
- import "../interfaces.js";
1
+ import { isString } from "../interfaces.js";
2
+ import { Observable, } from "../observation/observable.js";
2
3
  import { FAST } from "../platform.js";
3
- import { BindingConfig, BindingMode, ChangeBinding, } from "./binding.js";
4
+ import { Binding } from "./html-directive.js";
5
+ const defaultOptions = {
6
+ fromView: v => v,
7
+ };
4
8
  let twoWaySettings = {
5
9
  determineChangeEvent() {
6
10
  return "change";
7
11
  },
8
12
  };
9
- /**
10
- * A binding behavior for bindings that update in two directions.
11
- * @public
12
- */
13
- export class TwoWayBinding extends ChangeBinding {
14
- /**
15
- * Bind this behavior to the source.
16
- * @param source - The source to bind to.
17
- * @param context - The execution context that the binding is operating within.
18
- * @param targets - The targets that behaviors in a view can attach to.
19
- */
20
- bind(source, context, targets) {
13
+ class TwoWayObserver {
14
+ constructor(directive, subscriber, dataBinding) {
15
+ this.directive = directive;
16
+ this.subscriber = subscriber;
17
+ this.dataBinding = dataBinding;
18
+ this.notifier = Observable.binding(dataBinding.evaluate, this, dataBinding.isVolatile);
19
+ }
20
+ observe(source, context) {
21
21
  var _a;
22
- super.bind(source, context, targets);
23
- const directive = this.directive;
24
- const target = targets[directive.nodeId];
25
22
  if (!this.changeEvent) {
26
23
  this.changeEvent =
27
- (_a = directive.options.changeEvent) !== null && _a !== void 0 ? _a : twoWaySettings.determineChangeEvent(directive, target);
24
+ (_a = this.dataBinding.options.changeEvent) !== null && _a !== void 0 ? _a : twoWaySettings.determineChangeEvent(this.directive, this.target);
28
25
  }
29
- target.addEventListener(this.changeEvent, this);
26
+ this.target.addEventListener(this.changeEvent, this);
27
+ return this.notifier.observe(source, context);
30
28
  }
31
- /**
32
- * Unbinds this behavior from the source.
33
- * @param source - The source to unbind from.
34
- * @param context - The execution context that the binding is operating within.
35
- * @param targets - The targets that behaviors in a view can attach to.
36
- */
37
- unbind(source, context, targets) {
38
- super.unbind(source, context, targets);
39
- targets[this.directive.nodeId].removeEventListener(this.changeEvent, this);
29
+ dispose() {
30
+ this.notifier.dispose();
31
+ this.target.removeEventListener(this.changeEvent, this);
32
+ }
33
+ /** @internal */
34
+ handleChange(subject, args) {
35
+ this.subscriber.handleChange(this.dataBinding.evaluate, this);
40
36
  }
41
37
  /** @internal */
42
38
  handleEvent(event) {
43
39
  const directive = this.directive;
44
40
  const target = event.currentTarget;
45
- const observer = this.getObserver(target);
46
- const last = observer.last; // using internal API!!!
41
+ const notifier = this.notifier;
42
+ const last = notifier.last; // using internal API!!!
47
43
  if (!last) {
48
44
  FAST.warn(1203 /* Message.twoWayBindingRequiresObservables */);
49
45
  return;
@@ -63,7 +59,21 @@ export class TwoWayBinding extends ChangeBinding {
63
59
  value = target[directive.targetAspect];
64
60
  break;
65
61
  }
66
- last.propertySource[last.propertyName] = directive.options.fromView(value);
62
+ last.propertySource[last.propertyName] = this.dataBinding.options.fromView(value);
63
+ }
64
+ }
65
+ class TwoWayBinding extends Binding {
66
+ constructor(evaluate, isVolatile, options = defaultOptions) {
67
+ super();
68
+ this.evaluate = evaluate;
69
+ this.isVolatile = isVolatile;
70
+ this.options = options;
71
+ if (!options.fromView) {
72
+ options.fromView = defaultOptions.fromView;
73
+ }
74
+ }
75
+ createObserver(directive, subscriber) {
76
+ return new TwoWayObserver(directive, subscriber, this);
67
77
  }
68
78
  /**
69
79
  * Configures two-way binding.
@@ -74,9 +84,15 @@ export class TwoWayBinding extends ChangeBinding {
74
84
  }
75
85
  }
76
86
  /**
77
- * The default twoWay binding configuration.
87
+ * Creates a default binding.
88
+ * @param binding - The binding to refresh when changed.
89
+ * @param isBindingVolatile - Indicates whether the binding is volatile or not.
90
+ * @returns A binding configuration.
78
91
  * @public
79
92
  */
80
- export const twoWay = BindingConfig.define(BindingMode.define(TwoWayBinding), {
81
- fromView: v => v,
82
- });
93
+ export function twoWay(binding, optionsOrChangeEvent, isBindingVolatile = Observable.isVolatileBinding(binding)) {
94
+ if (isString(optionsOrChangeEvent)) {
95
+ optionsOrChangeEvent = { changeEvent: optionsOrChangeEvent };
96
+ }
97
+ return new TwoWayBinding(binding, isBindingVolatile, optionsOrChangeEvent);
98
+ }