@microsoft/fast-element 2.0.0-beta.21 → 2.0.0-beta.22

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 (56) hide show
  1. package/CHANGELOG.json +33 -0
  2. package/CHANGELOG.md +12 -1
  3. package/dist/dts/binding/binding.d.ts +49 -0
  4. package/dist/dts/binding/normalize.d.ts +9 -0
  5. package/dist/dts/binding/one-time.d.ts +11 -0
  6. package/dist/dts/binding/one-way.d.ts +20 -0
  7. package/dist/dts/{templating/binding-signal.d.ts → binding/signal.d.ts} +1 -1
  8. package/dist/dts/{templating/binding-two-way.d.ts → binding/two-way.d.ts} +3 -4
  9. package/dist/dts/components/element-controller.d.ts +20 -5
  10. package/dist/dts/context.d.ts +20 -7
  11. package/dist/dts/index.d.ts +6 -2
  12. package/dist/dts/interfaces.d.ts +4 -4
  13. package/dist/dts/metadata.d.ts +1 -0
  14. package/dist/dts/platform.d.ts +9 -1
  15. package/dist/dts/styles/css-binding-directive.d.ts +60 -0
  16. package/dist/dts/styles/css.d.ts +9 -2
  17. package/dist/dts/styles/host.d.ts +2 -5
  18. package/dist/dts/templating/{binding.d.ts → html-binding-directive.d.ts} +3 -34
  19. package/dist/dts/templating/html-directive.d.ts +3 -35
  20. package/dist/dts/templating/render.d.ts +19 -5
  21. package/dist/dts/templating/repeat.d.ts +3 -2
  22. package/dist/dts/templating/template.d.ts +2 -6
  23. package/dist/dts/templating/view.d.ts +16 -6
  24. package/dist/dts/testing/fakes.d.ts +2 -1
  25. package/dist/esm/binding/binding.js +18 -0
  26. package/dist/esm/binding/normalize.js +17 -0
  27. package/dist/esm/binding/one-time.js +21 -0
  28. package/dist/esm/binding/one-way.js +30 -0
  29. package/dist/esm/{templating/binding-signal.js → binding/signal.js} +5 -8
  30. package/dist/esm/{templating/binding-two-way.js → binding/two-way.js} +11 -15
  31. package/dist/esm/components/element-controller.js +33 -8
  32. package/dist/esm/context.js +22 -1
  33. package/dist/esm/index.js +8 -2
  34. package/dist/esm/interfaces.js +3 -3
  35. package/dist/esm/metadata.js +3 -1
  36. package/dist/esm/observation/observable.js +3 -6
  37. package/dist/esm/platform.js +9 -0
  38. package/dist/esm/styles/css-binding-directive.js +76 -0
  39. package/dist/esm/styles/css.js +14 -2
  40. package/dist/esm/templating/compiler.js +2 -1
  41. package/dist/esm/templating/{binding.js → html-binding-directive.js} +3 -70
  42. package/dist/esm/templating/html-directive.js +2 -25
  43. package/dist/esm/templating/render.js +25 -12
  44. package/dist/esm/templating/repeat.js +3 -3
  45. package/dist/esm/templating/template.js +9 -10
  46. package/dist/esm/templating/view.js +2 -6
  47. package/dist/esm/testing/fakes.js +1 -1
  48. package/dist/fast-element.api.json +1127 -342
  49. package/dist/fast-element.d.ts +125 -41
  50. package/dist/fast-element.debug.js +217 -117
  51. package/dist/fast-element.debug.min.js +1 -1
  52. package/dist/fast-element.js +217 -117
  53. package/dist/fast-element.min.js +1 -1
  54. package/dist/fast-element.untrimmed.d.ts +132 -80
  55. package/docs/api-report.md +52 -51
  56. package/package.json +5 -5
@@ -1,6 +1,12 @@
1
- import { isString } from "../interfaces.js";
1
+ import { isFunction, isString } from "../interfaces.js";
2
+ import { Binding } from "../binding/binding.js";
3
+ import { oneWay } from "../binding/one-way.js";
2
4
  import { CSSDirective } from "./css-directive.js";
3
5
  import { ElementStyles } from "./element-styles.js";
6
+ import { CSSBindingDirective } from "./css-binding-directive.js";
7
+ const marker = `${Math.random().toString(36).substring(2, 8)}`;
8
+ let varId = 0;
9
+ const nextCSSVariable = () => `--v${marker}${++varId}`;
4
10
  function collectStyles(strings, values) {
5
11
  const styles = [];
6
12
  let cssString = "";
@@ -11,7 +17,13 @@ function collectStyles(strings, values) {
11
17
  for (let i = 0, ii = strings.length - 1; i < ii; ++i) {
12
18
  cssString += strings[i];
13
19
  let value = values[i];
14
- if (CSSDirective.getForInstance(value) !== void 0) {
20
+ if (isFunction(value)) {
21
+ value = new CSSBindingDirective(oneWay(value), nextCSSVariable()).createCSS(add);
22
+ }
23
+ else if (value instanceof Binding) {
24
+ value = new CSSBindingDirective(value, nextCSSVariable()).createCSS(add);
25
+ }
26
+ else if (CSSDirective.getForInstance(value) !== void 0) {
15
27
  value = value.createCSS(add);
16
28
  }
17
29
  if (value instanceof ElementStyles || value instanceof CSSStyleSheet) {
@@ -1,8 +1,9 @@
1
1
  import { isFunction, isString } from "../interfaces.js";
2
2
  import { FAST } from "../platform.js";
3
3
  import { DOM } from "../dom.js";
4
+ import { oneTime } from "../binding/one-time.js";
4
5
  import { nextId, Parser } from "./markup.js";
5
- import { HTMLBindingDirective, oneTime } from "./binding.js";
6
+ import { HTMLBindingDirective } from "./html-binding-directive.js";
6
7
  import { HTMLDirective, } from "./html-directive.js";
7
8
  import { HTMLView } from "./view.js";
8
9
  const targetIdFrom = (parentId, nodeIndex) => `${parentId}.${nodeIndex}`;
@@ -1,30 +1,9 @@
1
- import { isFunction, noop } from "../interfaces.js";
2
- import { ExecutionContext, Observable, } from "../observation/observable.js";
1
+ import "../interfaces.js";
2
+ import { ExecutionContext, } from "../observation/observable.js";
3
3
  import { FAST } from "../platform.js";
4
4
  import { DOM, DOMAspect } from "../dom.js";
5
- import { Binding, HTMLDirective, } from "./html-directive.js";
5
+ import { HTMLDirective, } from "./html-directive.js";
6
6
  import { Markup } from "./markup.js";
7
- class OnChangeBinding extends Binding {
8
- createObserver(_, subscriber) {
9
- return Observable.binding(this.evaluate, subscriber, this.isVolatile);
10
- }
11
- }
12
- class OneTimeBinding extends Binding {
13
- constructor() {
14
- super(...arguments);
15
- /**
16
- * Opts out of JSON stringification.
17
- * @internal
18
- */
19
- this.toJSON = noop;
20
- }
21
- createObserver() {
22
- return this;
23
- }
24
- bind(controller) {
25
- return this.evaluate(controller.source, controller.context);
26
- }
27
- }
28
7
  function updateContent(target, aspect, value, controller) {
29
8
  // If there's no actual value, then this equates to the
30
9
  // empty string for the purposes of content bindings.
@@ -213,49 +192,3 @@ export class HTMLBindingDirective {
213
192
  }
214
193
  }
215
194
  HTMLDirective.define(HTMLBindingDirective, { aspected: true });
216
- /**
217
- * Creates an standard binding.
218
- * @param expression - The binding to refresh when changed.
219
- * @param policy - The security policy to associate with th binding.
220
- * @param isVolatile - Indicates whether the binding is volatile or not.
221
- * @returns A binding configuration.
222
- * @public
223
- */
224
- export function bind(expression, policy, isVolatile = Observable.isVolatileBinding(expression)) {
225
- return new OnChangeBinding(expression, policy, isVolatile);
226
- }
227
- /**
228
- * Creates a one time binding
229
- * @param expression - The binding to refresh when signaled.
230
- * @param policy - The security policy to associate with th binding.
231
- * @returns A binding configuration.
232
- * @public
233
- */
234
- export function oneTime(expression, policy) {
235
- return new OneTimeBinding(expression, policy);
236
- }
237
- /**
238
- * Creates an event listener binding.
239
- * @param expression - The binding to invoke when the event is raised.
240
- * @param options - Event listener options.
241
- * @returns A binding configuration.
242
- * @public
243
- */
244
- export function listener(expression, options) {
245
- const config = new OnChangeBinding(expression);
246
- config.options = options;
247
- return config;
248
- }
249
- /**
250
- * Normalizes the input value into a binding.
251
- * @param value - The value to create the default binding for.
252
- * @returns A binding configuration for the provided value.
253
- * @public
254
- */
255
- export function normalizeBinding(value) {
256
- return isFunction(value)
257
- ? bind(value)
258
- : value instanceof Binding
259
- ? value
260
- : oneTime(() => value);
261
- }
@@ -1,6 +1,5 @@
1
1
  import { DOMAspect } from "../dom.js";
2
- import { noop } from "../interfaces.js";
3
- import { createTypeRegistry } from "../platform.js";
2
+ import { createTypeRegistry, makeSerializationNoop } from "../platform.js";
4
3
  import { Markup } from "./markup.js";
5
4
  const registry = createTypeRegistry();
6
5
  /**
@@ -76,24 +75,6 @@ export function htmlDirective(options) {
76
75
  HTMLDirective.define(type, options);
77
76
  };
78
77
  }
79
- /**
80
- * Captures a binding expression along with related information and capabilities.
81
- *
82
- * @public
83
- */
84
- export class Binding {
85
- /**
86
- * Creates a binding.
87
- * @param evaluate - Evaluates the binding.
88
- * @param policy - The security policy to associate with this binding.
89
- * @param isVolatile - Indicates whether the binding is volatile.
90
- */
91
- constructor(evaluate, policy, isVolatile = false) {
92
- this.evaluate = evaluate;
93
- this.policy = policy;
94
- this.isVolatile = isVolatile;
95
- }
96
- }
97
78
  /**
98
79
  * A base class used for attribute directives that don't need internal state.
99
80
  * @public
@@ -105,11 +86,6 @@ export class StatelessAttachedAttributeDirective {
105
86
  */
106
87
  constructor(options) {
107
88
  this.options = options;
108
- /**
109
- * Opts out of JSON stringification.
110
- * @internal
111
- */
112
- this.toJSON = noop;
113
89
  }
114
90
  /**
115
91
  * Creates a placeholder string based on the directive's index within the template.
@@ -128,3 +104,4 @@ export class StatelessAttachedAttributeDirective {
128
104
  return this;
129
105
  }
130
106
  }
107
+ makeSerializationNoop(StatelessAttachedAttributeDirective);
@@ -1,7 +1,10 @@
1
1
  import { FASTElementDefinition } from "../components/fast-definitions.js";
2
2
  import { isFunction, isString } from "../interfaces.js";
3
- import { bind, normalizeBinding, oneTime, } from "./binding.js";
4
- import { Binding, HTMLDirective, } from "./html-directive.js";
3
+ import { Binding } from "../binding/binding.js";
4
+ import { oneTime } from "../binding/one-time.js";
5
+ import { oneWay } from "../binding/one-way.js";
6
+ import { normalizeBinding } from "../binding/normalize.js";
7
+ import { HTMLDirective, } from "./html-directive.js";
5
8
  import { Markup } from "./markup.js";
6
9
  import { html, ViewTemplate, } from "./template.js";
7
10
  /**
@@ -19,8 +22,8 @@ export class RenderBehavior {
19
22
  this.controller = null;
20
23
  this.view = null;
21
24
  this.data = null;
22
- this.dataBindingObserver = directive.dataBinding.createObserver(directive, this);
23
- this.templateBindingObserver = directive.templateBinding.createObserver(directive, this);
25
+ this.dataBindingObserver = directive.dataBinding.createObserver(this, directive);
26
+ this.templateBindingObserver = directive.templateBinding.createObserver(this, directive);
24
27
  }
25
28
  /**
26
29
  * Bind this behavior.
@@ -141,12 +144,13 @@ function instructionToTemplate(def) {
141
144
  }
142
145
  return def.template;
143
146
  }
144
- function createElementTemplate(tagName, attributes, content, policy) {
147
+ function createElementTemplate(tagName, options) {
145
148
  const markup = [];
146
149
  const values = [];
150
+ const { attributes, directives, content, policy } = options !== null && options !== void 0 ? options : {};
151
+ markup.push(`<${tagName}`);
147
152
  if (attributes) {
148
153
  const attrNames = Object.getOwnPropertyNames(attributes);
149
- markup.push(`<${tagName}`);
150
154
  for (let i = 0, ii = attrNames.length; i < ii; ++i) {
151
155
  const name = attrNames[i];
152
156
  if (i === 0) {
@@ -157,11 +161,17 @@ function createElementTemplate(tagName, attributes, content, policy) {
157
161
  }
158
162
  values.push(attributes[name]);
159
163
  }
160
- markup.push(`">`);
164
+ markup.push(`"`);
161
165
  }
162
- else {
163
- markup.push(`<${tagName}>`);
166
+ if (directives) {
167
+ markup[markup.length - 1] += " ";
168
+ for (let i = 0, ii = directives.length; i < ii; ++i) {
169
+ const directive = directives[i];
170
+ markup.push(i > 0 ? "" : " ");
171
+ values.push(directive);
172
+ }
164
173
  }
174
+ markup[markup.length - 1] += ">";
165
175
  if (content && isFunction(content.create)) {
166
176
  values.push(content);
167
177
  markup.push(`</${tagName}>`);
@@ -173,7 +183,7 @@ function createElementTemplate(tagName, attributes, content, policy) {
173
183
  return ViewTemplate.create(markup, values, policy);
174
184
  }
175
185
  function create(options) {
176
- var _a, _b;
186
+ var _a;
177
187
  const name = (_a = options.name) !== null && _a !== void 0 ? _a : defaultViewName;
178
188
  let template;
179
189
  if (isElementRenderOptions(options)) {
@@ -187,7 +197,10 @@ function create(options) {
187
197
  throw new Error("Invalid element for model rendering.");
188
198
  }
189
199
  }
190
- template = createElementTemplate(tagName, (_b = options.attributes) !== null && _b !== void 0 ? _b : defaultAttributes, options.content, options.policy);
200
+ if (!options.attributes) {
201
+ options.attributes = defaultAttributes;
202
+ }
203
+ template = createElementTemplate(tagName, options);
191
204
  }
192
205
  else {
193
206
  template = options.template;
@@ -357,7 +370,7 @@ export function render(value, template) {
357
370
  });
358
371
  }
359
372
  else if (isFunction(template)) {
360
- templateBinding = bind((s, c) => {
373
+ templateBinding = oneWay((s, c) => {
361
374
  var _a;
362
375
  let result = template(s, c);
363
376
  if (isString(result)) {
@@ -1,10 +1,10 @@
1
1
  import { Observable } from "../observation/observable.js";
2
2
  import { emptyArray } from "../platform.js";
3
3
  import { ArrayObserver } from "../observation/arrays.js";
4
+ import { normalizeBinding } from "../binding/normalize.js";
4
5
  import { Markup } from "./markup.js";
5
6
  import { HTMLDirective, } from "./html-directive.js";
6
7
  import { HTMLView } from "./view.js";
7
- import { normalizeBinding } from "./binding.js";
8
8
  const defaultRepeatOptions = Object.freeze({
9
9
  positioning: false,
10
10
  recycle: true,
@@ -42,8 +42,8 @@ export class RepeatBehavior {
42
42
  this.bindView = bindWithoutPositioning;
43
43
  /** @internal */
44
44
  this.views = [];
45
- this.itemsBindingObserver = directive.dataBinding.createObserver(directive, this);
46
- this.templateBindingObserver = directive.templateBinding.createObserver(directive, this);
45
+ this.itemsBindingObserver = directive.dataBinding.createObserver(this, directive);
46
+ this.templateBindingObserver = directive.templateBinding.createObserver(this, directive);
47
47
  if (directive.options.positioning) {
48
48
  this.bindView = bindWithPositioning;
49
49
  }
@@ -1,8 +1,11 @@
1
- import { isFunction, isString, noop } from "../interfaces.js";
2
- import { FAST } from "../platform.js";
3
- import { bind, HTMLBindingDirective, oneTime } from "./binding.js";
1
+ import { isFunction, isString } from "../interfaces.js";
2
+ import { Binding } from "../binding/binding.js";
3
+ import { FAST, makeSerializationNoop } from "../platform.js";
4
+ import { oneWay } from "../binding/one-way.js";
5
+ import { oneTime } from "../binding/one-time.js";
6
+ import { HTMLBindingDirective } from "./html-binding-directive.js";
4
7
  import { Compiler } from "./compiler.js";
5
- import { Binding, HTMLDirective, } from "./html-directive.js";
8
+ import { HTMLDirective, } from "./html-directive.js";
6
9
  import { nextId } from "./markup.js";
7
10
  // Much thanks to LitHTML for working this out!
8
11
  const lastAttributeNameRegex =
@@ -62,11 +65,6 @@ export class ViewTemplate {
62
65
  constructor(html, factories = {}, policy) {
63
66
  this.policy = policy;
64
67
  this.result = null;
65
- /**
66
- * Opts out of JSON stringification.
67
- * @internal
68
- */
69
- this.toJSON = noop;
70
68
  this.html = html;
71
69
  this.factories = factories;
72
70
  }
@@ -145,7 +143,7 @@ export class ViewTemplate {
145
143
  let definition;
146
144
  html += currentString;
147
145
  if (isFunction(currentValue)) {
148
- currentValue = new HTMLBindingDirective(bind(currentValue));
146
+ currentValue = new HTMLBindingDirective(oneWay(currentValue));
149
147
  }
150
148
  else if (currentValue instanceof Binding) {
151
149
  currentValue = new HTMLBindingDirective(currentValue);
@@ -159,6 +157,7 @@ export class ViewTemplate {
159
157
  return new ViewTemplate(html + strings[strings.length - 1], factories, policy);
160
158
  }
161
159
  }
160
+ makeSerializationNoop(ViewTemplate);
162
161
  /**
163
162
  * Transforms a template literal string into a ViewTemplate.
164
163
  * @param strings - The string fragments that are interpolated with the values.
@@ -1,5 +1,5 @@
1
- import { noop } from "../interfaces.js";
2
1
  import { ExecutionContext, Observable, SourceLifetime, } from "../observation/observable.js";
2
+ import { makeSerializationNoop } from "../platform.js";
3
3
  function removeNodeSequence(firstNode, lastNode) {
4
4
  const parent = firstNode.parentNode;
5
5
  let current = firstNode;
@@ -51,11 +51,6 @@ export class HTMLView {
51
51
  * The length of the current collection within a repeat context.
52
52
  */
53
53
  this.length = 0;
54
- /**
55
- * Opts out of JSON stringification.
56
- * @internal
57
- */
58
- this.toJSON = noop;
59
54
  this.firstChild = fragment.firstChild;
60
55
  this.lastChild = fragment.lastChild;
61
56
  }
@@ -236,5 +231,6 @@ export class HTMLView {
236
231
  }
237
232
  }
238
233
  }
234
+ makeSerializationNoop(HTMLView);
239
235
  Observable.defineProperty(HTMLView.prototype, "index");
240
236
  Observable.defineProperty(HTMLView.prototype, "length");
@@ -1,5 +1,5 @@
1
- import { ExecutionContext, } from "../index.js";
2
1
  import { noop } from "../interfaces.js";
2
+ import { ExecutionContext } from "../observation/observable.js";
3
3
  export const Fake = Object.freeze({
4
4
  executionContext(parent, parentContext) {
5
5
  return {