@microsoft/fast-element 2.0.0-beta.9 → 2.0.1

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 (142) hide show
  1. package/.eslintrc.json +1 -1
  2. package/CHANGELOG.json +518 -0
  3. package/CHANGELOG.md +181 -1
  4. package/README.md +1 -9
  5. package/api-extractor.context.json +14 -0
  6. package/api-extractor.di.json +14 -0
  7. package/dist/context/context.api.json +1068 -0
  8. package/dist/di/di.api.json +4929 -0
  9. package/dist/dts/binding/binding.d.ts +49 -0
  10. package/dist/dts/binding/normalize.d.ts +9 -0
  11. package/dist/dts/binding/one-time.d.ts +11 -0
  12. package/dist/dts/binding/one-way.d.ts +20 -0
  13. package/dist/dts/{templating/binding-signal.d.ts → binding/signal.d.ts} +19 -4
  14. package/dist/dts/{templating/binding-two-way.d.ts → binding/two-way.d.ts} +9 -5
  15. package/dist/dts/components/attributes.d.ts +7 -1
  16. package/dist/dts/components/element-controller.d.ts +104 -8
  17. package/dist/dts/components/element-hydration.d.ts +2 -0
  18. package/dist/dts/components/fast-definitions.d.ts +6 -0
  19. package/dist/dts/components/hydration.d.ts +56 -0
  20. package/dist/dts/components/install-hydration.d.ts +1 -0
  21. package/dist/dts/context.d.ts +29 -15
  22. package/dist/dts/di/di.d.ts +0 -5
  23. package/dist/dts/dom-policy.d.ts +83 -0
  24. package/dist/dts/dom.d.ts +100 -0
  25. package/dist/dts/hydration/target-builder.d.ts +63 -0
  26. package/dist/dts/index.d.ts +33 -26
  27. package/dist/dts/index.rollup.d.ts +0 -1
  28. package/dist/dts/index.rollup.debug.d.ts +0 -1
  29. package/dist/dts/interfaces.d.ts +32 -82
  30. package/dist/dts/metadata.d.ts +6 -5
  31. package/dist/dts/observation/arrays.d.ts +1 -1
  32. package/dist/dts/observation/observable.bench.d.ts +18 -0
  33. package/dist/dts/observation/observable.d.ts +5 -5
  34. package/dist/dts/pending-task.d.ts +19 -7
  35. package/dist/dts/platform.d.ts +11 -2
  36. package/dist/dts/polyfills.d.ts +0 -8
  37. package/dist/dts/styles/css-binding-directive.d.ts +60 -0
  38. package/dist/dts/styles/css.d.ts +9 -7
  39. package/dist/dts/styles/element-styles.d.ts +1 -14
  40. package/dist/dts/styles/host.d.ts +2 -5
  41. package/dist/dts/styles/style-strategy.d.ts +42 -0
  42. package/dist/dts/templating/compiler.d.ts +11 -13
  43. package/dist/dts/templating/{binding.d.ts → html-binding-directive.d.ts} +21 -41
  44. package/dist/dts/templating/html-directive.d.ts +44 -140
  45. package/dist/dts/templating/install-hydratable-view-templates.d.ts +1 -0
  46. package/dist/dts/templating/node-observation.d.ts +11 -1
  47. package/dist/dts/templating/ref.d.ts +4 -0
  48. package/dist/dts/templating/render.bench.d.ts +3 -0
  49. package/dist/dts/templating/render.d.ts +49 -9
  50. package/dist/dts/templating/repeat-basic-reverse.bench.d.ts +3 -0
  51. package/dist/dts/templating/repeat-basic-shift.bench.d.ts +3 -0
  52. package/dist/dts/templating/repeat.d.ts +31 -9
  53. package/dist/dts/templating/template.d.ts +97 -12
  54. package/dist/dts/templating/view.d.ts +146 -29
  55. package/dist/dts/templating/when-basic.bench.d.ts +3 -0
  56. package/dist/dts/templating/when-conditional.bench.d.ts +3 -0
  57. package/dist/dts/templating/when-switch.bench.d.ts +3 -0
  58. package/dist/dts/templating/when.d.ts +3 -1
  59. package/dist/dts/testing/fakes.d.ts +12 -1
  60. package/dist/dts/tsdoc-metadata.json +1 -1
  61. package/dist/dts/utilities.d.ts +55 -1
  62. package/dist/esm/binding/binding.js +18 -0
  63. package/dist/esm/binding/normalize.js +17 -0
  64. package/dist/esm/binding/one-time.js +21 -0
  65. package/dist/esm/binding/one-way.js +30 -0
  66. package/dist/esm/{templating/binding-signal.js → binding/signal.js} +22 -6
  67. package/dist/esm/{templating/binding-two-way.js → binding/two-way.js} +18 -12
  68. package/dist/esm/components/attributes.js +19 -6
  69. package/dist/esm/components/element-controller.js +319 -49
  70. package/dist/esm/components/element-hydration.js +2 -0
  71. package/dist/esm/components/fast-definitions.js +12 -4
  72. package/dist/esm/components/fast-element.js +3 -1
  73. package/dist/esm/components/hydration.js +104 -0
  74. package/dist/esm/components/install-hydration.js +3 -0
  75. package/dist/esm/context.js +26 -4
  76. package/dist/esm/debug.js +8 -2
  77. package/dist/esm/di/di.js +9 -12
  78. package/dist/esm/dom-policy.js +345 -0
  79. package/dist/esm/dom.js +101 -0
  80. package/dist/esm/hydration/target-builder.js +175 -0
  81. package/dist/esm/index.js +34 -25
  82. package/dist/esm/index.rollup.debug.js +3 -1
  83. package/dist/esm/index.rollup.js +3 -1
  84. package/dist/esm/interfaces.js +51 -3
  85. package/dist/esm/metadata.js +11 -8
  86. package/dist/esm/observation/arrays.js +1 -1
  87. package/dist/esm/observation/observable.bench.js +79 -0
  88. package/dist/esm/observation/observable.js +20 -15
  89. package/dist/esm/observation/update-queue.js +2 -2
  90. package/dist/esm/pending-task.js +13 -1
  91. package/dist/esm/platform.js +12 -2
  92. package/dist/esm/polyfills.js +3 -61
  93. package/dist/esm/styles/css-binding-directive.js +76 -0
  94. package/dist/esm/styles/css.js +14 -7
  95. package/dist/esm/styles/element-styles.js +0 -33
  96. package/dist/esm/styles/style-strategy.js +1 -0
  97. package/dist/esm/templating/children.js +8 -4
  98. package/dist/esm/templating/compiler.js +37 -44
  99. package/dist/esm/templating/html-binding-directive.js +218 -0
  100. package/dist/esm/templating/html-directive.js +25 -152
  101. package/dist/esm/templating/install-hydratable-view-templates.js +17 -0
  102. package/dist/esm/templating/node-observation.js +14 -8
  103. package/dist/esm/templating/ref.js +1 -1
  104. package/dist/esm/templating/render.bench.js +56 -0
  105. package/dist/esm/templating/render.js +74 -30
  106. package/dist/esm/templating/repeat-basic-reverse.bench.js +43 -0
  107. package/dist/esm/templating/repeat-basic-shift.bench.js +43 -0
  108. package/dist/esm/templating/repeat.js +116 -17
  109. package/dist/esm/templating/template.js +135 -60
  110. package/dist/esm/templating/view.js +254 -34
  111. package/dist/esm/templating/when-basic.bench.js +36 -0
  112. package/dist/esm/templating/when-conditional.bench.js +39 -0
  113. package/dist/esm/templating/when-switch.bench.js +68 -0
  114. package/dist/esm/templating/when.js +12 -5
  115. package/dist/esm/testing/fakes.js +32 -1
  116. package/dist/esm/testing/fixture.js +1 -1
  117. package/dist/esm/utilities.js +97 -1
  118. package/dist/fast-element.api.json +9789 -5667
  119. package/dist/fast-element.d.ts +813 -2392
  120. package/dist/fast-element.debug.js +2788 -974
  121. package/dist/fast-element.debug.min.js +3 -1
  122. package/dist/fast-element.js +2641 -833
  123. package/dist/fast-element.min.js +3 -1
  124. package/dist/fast-element.untrimmed.d.ts +662 -314
  125. package/docs/{api-report.md → api-report.api.md} +238 -151
  126. package/docs/context/api-report.api.md +69 -0
  127. package/docs/di/api-report.api.md +315 -0
  128. package/karma.conf.cjs +2 -1
  129. package/package.json +59 -47
  130. package/scripts/run-api-extractor.js +51 -0
  131. package/scripts/run-benchmarks.js +46 -0
  132. package/tensile.config.js +12 -0
  133. package/dist/dts/templating/dom.d.ts +0 -41
  134. package/dist/esm/templating/binding.js +0 -282
  135. package/dist/esm/templating/dom.js +0 -49
  136. package/docs/guide/declaring-templates.md +0 -230
  137. package/docs/guide/defining-elements.md +0 -214
  138. package/docs/guide/leveraging-css.md +0 -253
  139. package/docs/guide/next-steps.md +0 -13
  140. package/docs/guide/observables-and-state.md +0 -213
  141. package/docs/guide/using-directives.md +0 -576
  142. package/docs/guide/working-with-shadow-dom.md +0 -296
@@ -0,0 +1,218 @@
1
+ import { isHydratable } from "../components/hydration.js";
2
+ import { DOM, DOMAspect } from "../dom.js";
3
+ import "../interfaces.js";
4
+ import { ExecutionContext, } from "../observation/observable.js";
5
+ import { FAST } from "../platform.js";
6
+ import { HTMLDirective, } from "./html-directive.js";
7
+ import { Markup } from "./markup.js";
8
+ import { HydrationStage } from "./view.js";
9
+ function isContentTemplate(value) {
10
+ return value.create !== undefined;
11
+ }
12
+ function updateContent(target, aspect, value, controller) {
13
+ // If there's no actual value, then this equates to the
14
+ // empty string for the purposes of content bindings.
15
+ if (value === null || value === undefined) {
16
+ value = "";
17
+ }
18
+ // If the value has a "create" method, then it's a ContentTemplate.
19
+ if (isContentTemplate(value)) {
20
+ target.textContent = "";
21
+ let view = target.$fastView;
22
+ // If there's no previous view that we might be able to
23
+ // reuse then create a new view from the template.
24
+ if (view === void 0) {
25
+ if (isHydratable(controller) &&
26
+ isHydratable(value) &&
27
+ controller.bindingViewBoundaries[this.targetNodeId] !== undefined &&
28
+ controller.hydrationStage !== HydrationStage.hydrated) {
29
+ const viewNodes = controller.bindingViewBoundaries[this.targetNodeId];
30
+ view = value.hydrate(viewNodes.first, viewNodes.last);
31
+ }
32
+ else {
33
+ view = value.create();
34
+ }
35
+ }
36
+ else {
37
+ // If there is a previous view, but it wasn't created
38
+ // from the same template as the new value, then we
39
+ // need to remove the old view if it's still in the DOM
40
+ // and create a new view from the template.
41
+ if (target.$fastTemplate !== value) {
42
+ if (view.isComposed) {
43
+ view.remove();
44
+ view.unbind();
45
+ }
46
+ view = value.create();
47
+ }
48
+ }
49
+ // It's possible that the value is the same as the previous template
50
+ // and that there's actually no need to compose it.
51
+ if (!view.isComposed) {
52
+ view.isComposed = true;
53
+ view.bind(controller.source, controller.context);
54
+ view.insertBefore(target);
55
+ target.$fastView = view;
56
+ target.$fastTemplate = value;
57
+ }
58
+ else if (view.needsBindOnly) {
59
+ view.needsBindOnly = false;
60
+ view.bind(controller.source, controller.context);
61
+ }
62
+ }
63
+ else {
64
+ const view = target.$fastView;
65
+ // If there is a view and it's currently composed into
66
+ // the DOM, then we need to remove it.
67
+ if (view !== void 0 && view.isComposed) {
68
+ view.isComposed = false;
69
+ view.remove();
70
+ if (view.needsBindOnly) {
71
+ view.needsBindOnly = false;
72
+ }
73
+ else {
74
+ view.unbind();
75
+ }
76
+ }
77
+ target.textContent = value;
78
+ }
79
+ }
80
+ function updateTokenList(target, aspect, value) {
81
+ var _a;
82
+ const lookup = `${this.id}-t`;
83
+ const state = (_a = target[lookup]) !== null && _a !== void 0 ? _a : (target[lookup] = { v: 0, cv: Object.create(null) });
84
+ const classVersions = state.cv;
85
+ let version = state.v;
86
+ const tokenList = target[aspect];
87
+ // Add the classes, tracking the version at which they were added.
88
+ if (value !== null && value !== undefined && value.length) {
89
+ const names = value.split(/\s+/);
90
+ for (let i = 0, ii = names.length; i < ii; ++i) {
91
+ const currentName = names[i];
92
+ if (currentName === "") {
93
+ continue;
94
+ }
95
+ classVersions[currentName] = version;
96
+ tokenList.add(currentName);
97
+ }
98
+ }
99
+ state.v = version + 1;
100
+ // If this is the first call to add classes, there's no need to remove old ones.
101
+ if (version === 0) {
102
+ return;
103
+ }
104
+ // Remove classes from the previous version.
105
+ version -= 1;
106
+ for (const name in classVersions) {
107
+ if (classVersions[name] === version) {
108
+ tokenList.remove(name);
109
+ }
110
+ }
111
+ }
112
+ const sinkLookup = {
113
+ [DOMAspect.attribute]: DOM.setAttribute,
114
+ [DOMAspect.booleanAttribute]: DOM.setBooleanAttribute,
115
+ [DOMAspect.property]: (t, a, v) => (t[a] = v),
116
+ [DOMAspect.content]: updateContent,
117
+ [DOMAspect.tokenList]: updateTokenList,
118
+ [DOMAspect.event]: () => void 0,
119
+ };
120
+ /**
121
+ * A directive that applies bindings.
122
+ * @public
123
+ */
124
+ export class HTMLBindingDirective {
125
+ /**
126
+ * Creates an instance of HTMLBindingDirective.
127
+ * @param dataBinding - The binding configuration to apply.
128
+ */
129
+ constructor(dataBinding) {
130
+ this.dataBinding = dataBinding;
131
+ this.updateTarget = null;
132
+ /**
133
+ * The type of aspect to target.
134
+ */
135
+ this.aspectType = DOMAspect.content;
136
+ }
137
+ /**
138
+ * Creates HTML to be used within a template.
139
+ * @param add - Can be used to add behavior factories to a template.
140
+ */
141
+ createHTML(add) {
142
+ return Markup.interpolation(add(this));
143
+ }
144
+ /**
145
+ * Creates a behavior.
146
+ */
147
+ createBehavior() {
148
+ var _a;
149
+ if (this.updateTarget === null) {
150
+ const sink = sinkLookup[this.aspectType];
151
+ const policy = (_a = this.dataBinding.policy) !== null && _a !== void 0 ? _a : this.policy;
152
+ if (!sink) {
153
+ throw FAST.error(1205 /* Message.unsupportedBindingBehavior */);
154
+ }
155
+ this.data = `${this.id}-d`;
156
+ this.updateTarget = policy.protect(this.targetTagName, this.aspectType, this.targetAspect, sink);
157
+ }
158
+ return this;
159
+ }
160
+ /** @internal */
161
+ bind(controller) {
162
+ var _a;
163
+ const target = controller.targets[this.targetNodeId];
164
+ const isHydrating = isHydratable(controller) &&
165
+ controller.hydrationStage &&
166
+ controller.hydrationStage !== HydrationStage.hydrated;
167
+ switch (this.aspectType) {
168
+ case DOMAspect.event:
169
+ target[this.data] = controller;
170
+ target.addEventListener(this.targetAspect, this, this.dataBinding.options);
171
+ break;
172
+ case DOMAspect.content:
173
+ controller.onUnbind(this);
174
+ // intentional fall through
175
+ default:
176
+ const observer = (_a = target[this.data]) !== null && _a !== void 0 ? _a : (target[this.data] = this.dataBinding.createObserver(this, this));
177
+ observer.target = target;
178
+ observer.controller = controller;
179
+ if (isHydrating &&
180
+ (this.aspectType === DOMAspect.attribute ||
181
+ this.aspectType === DOMAspect.booleanAttribute)) {
182
+ observer.bind(controller);
183
+ // Skip updating target during bind for attributes
184
+ break;
185
+ }
186
+ this.updateTarget(target, this.targetAspect, observer.bind(controller), controller);
187
+ break;
188
+ }
189
+ }
190
+ /** @internal */
191
+ unbind(controller) {
192
+ const target = controller.targets[this.targetNodeId];
193
+ const view = target.$fastView;
194
+ if (view !== void 0 && view.isComposed) {
195
+ view.unbind();
196
+ view.needsBindOnly = true;
197
+ }
198
+ }
199
+ /** @internal */
200
+ handleEvent(event) {
201
+ const controller = event.currentTarget[this.data];
202
+ if (controller.isBound) {
203
+ ExecutionContext.setEvent(event);
204
+ const result = this.dataBinding.evaluate(controller.source, controller.context);
205
+ ExecutionContext.setEvent(null);
206
+ if (result !== true) {
207
+ event.preventDefault();
208
+ }
209
+ }
210
+ }
211
+ /** @internal */
212
+ handleChange(binding, observer) {
213
+ const target = observer.target;
214
+ const controller = observer.controller;
215
+ this.updateTarget(target, this.targetAspect, observer.bind(controller), controller);
216
+ }
217
+ }
218
+ HTMLDirective.define(HTMLBindingDirective, { aspected: true });
@@ -1,67 +1,6 @@
1
- import { ExecutionContext, } from "../observation/observable.js";
2
- import { createTypeRegistry } from "../platform.js";
3
- import { Markup, nextId } from "./markup.js";
4
- /**
5
- * Bridges between ViewBehaviors and HostBehaviors, enabling a host to
6
- * control ViewBehaviors.
7
- * @public
8
- */
9
- export const ViewBehaviorOrchestrator = Object.freeze({
10
- /**
11
- * Creates a ViewBehaviorOrchestrator.
12
- * @param source - The source to to associate behaviors with.
13
- * @returns A ViewBehaviorOrchestrator.
14
- */
15
- create(source) {
16
- const behaviors = [];
17
- const targets = {};
18
- let unbindables = null;
19
- let isConnected = false;
20
- return {
21
- source,
22
- context: ExecutionContext.default,
23
- targets,
24
- get isBound() {
25
- return isConnected;
26
- },
27
- addBehaviorFactory(factory, target) {
28
- const nodeId = factory.nodeId || (factory.nodeId = nextId());
29
- factory.id || (factory.id = nextId());
30
- this.addTarget(nodeId, target);
31
- this.addBehavior(factory.createBehavior());
32
- },
33
- addTarget(nodeId, target) {
34
- targets[nodeId] = target;
35
- },
36
- addBehavior(behavior) {
37
- behaviors.push(behavior);
38
- if (isConnected) {
39
- behavior.bind(this);
40
- }
41
- },
42
- onUnbind(unbindable) {
43
- if (unbindables === null) {
44
- unbindables = [];
45
- }
46
- unbindables.push(unbindable);
47
- },
48
- connectedCallback(controller) {
49
- if (!isConnected) {
50
- isConnected = true;
51
- behaviors.forEach(x => x.bind(this));
52
- }
53
- },
54
- disconnectedCallback(controller) {
55
- if (isConnected) {
56
- isConnected = false;
57
- if (unbindables !== null) {
58
- unbindables.forEach(x => x.unbind(this));
59
- }
60
- }
61
- },
62
- };
63
- },
64
- });
1
+ import { DOMAspect } from "../dom.js";
2
+ import { createTypeRegistry, makeSerializationNoop } from "../platform.js";
3
+ import { Markup } from "./markup.js";
65
4
  const registry = createTypeRegistry();
66
5
  /**
67
6
  * Instructs the template engine to apply behavior to a node.
@@ -89,67 +28,6 @@ export const HTMLDirective = Object.freeze({
89
28
  registry.register(options);
90
29
  return type;
91
30
  },
92
- });
93
- /**
94
- * Decorator: Defines an HTMLDirective.
95
- * @param options - Provides options that specify the directive's application.
96
- * @public
97
- */
98
- export function htmlDirective(options) {
99
- /* eslint-disable-next-line @typescript-eslint/explicit-function-return-type */
100
- return function (type) {
101
- HTMLDirective.define(type, options);
102
- };
103
- }
104
- /**
105
- * Captures a binding expression along with related information and capabilities.
106
- *
107
- * @public
108
- */
109
- export class Binding {
110
- /**
111
- * Creates a binding.
112
- * @param evaluate - Evaluates the binding.
113
- * @param isVolatile - Indicates whether the binding is volatile.
114
- */
115
- constructor(evaluate, isVolatile = false) {
116
- this.evaluate = evaluate;
117
- this.isVolatile = isVolatile;
118
- }
119
- }
120
- /**
121
- * The type of HTML aspect to target.
122
- * @public
123
- */
124
- export const Aspect = Object.freeze({
125
- /**
126
- * Not aspected.
127
- */
128
- none: 0,
129
- /**
130
- * An attribute.
131
- */
132
- attribute: 1,
133
- /**
134
- * A boolean attribute.
135
- */
136
- booleanAttribute: 2,
137
- /**
138
- * A property.
139
- */
140
- property: 3,
141
- /**
142
- * Content
143
- */
144
- content: 4,
145
- /**
146
- * A token list.
147
- */
148
- tokenList: 5,
149
- /**
150
- * An event.
151
- */
152
- event: 6,
153
31
  /**
154
32
  *
155
33
  * @param directive - The directive to assign the aspect to.
@@ -157,48 +35,46 @@ export const Aspect = Object.freeze({
157
35
  * @remarks
158
36
  * If a falsy value is provided, then the content aspect will be assigned.
159
37
  */
160
- assign(directive, value) {
38
+ assignAspect(directive, value) {
161
39
  if (!value) {
162
- directive.aspectType = Aspect.content;
40
+ directive.aspectType = DOMAspect.content;
163
41
  return;
164
42
  }
165
43
  directive.sourceAspect = value;
166
44
  switch (value[0]) {
167
45
  case ":":
168
46
  directive.targetAspect = value.substring(1);
169
- switch (directive.targetAspect) {
170
- case "innerHTML":
171
- directive.aspectType = Aspect.property;
172
- break;
173
- case "classList":
174
- directive.aspectType = Aspect.tokenList;
175
- break;
176
- default:
177
- directive.aspectType = Aspect.property;
178
- break;
179
- }
47
+ directive.aspectType =
48
+ directive.targetAspect === "classList"
49
+ ? DOMAspect.tokenList
50
+ : DOMAspect.property;
180
51
  break;
181
52
  case "?":
182
53
  directive.targetAspect = value.substring(1);
183
- directive.aspectType = Aspect.booleanAttribute;
54
+ directive.aspectType = DOMAspect.booleanAttribute;
184
55
  break;
185
56
  case "@":
186
57
  directive.targetAspect = value.substring(1);
187
- directive.aspectType = Aspect.event;
58
+ directive.aspectType = DOMAspect.event;
188
59
  break;
189
60
  default:
190
- if (value === "class") {
191
- directive.targetAspect = "className";
192
- directive.aspectType = Aspect.property;
193
- }
194
- else {
195
- directive.targetAspect = value;
196
- directive.aspectType = Aspect.attribute;
197
- }
61
+ directive.targetAspect = value;
62
+ directive.aspectType = DOMAspect.attribute;
198
63
  break;
199
64
  }
200
65
  },
201
66
  });
67
+ /**
68
+ * Decorator: Defines an HTMLDirective.
69
+ * @param options - Provides options that specify the directive's application.
70
+ * @public
71
+ */
72
+ export function htmlDirective(options) {
73
+ /* eslint-disable-next-line @typescript-eslint/explicit-function-return-type */
74
+ return function (type) {
75
+ HTMLDirective.define(type, options);
76
+ };
77
+ }
202
78
  /**
203
79
  * A base class used for attribute directives that don't need internal state.
204
80
  * @public
@@ -210,10 +86,6 @@ export class StatelessAttachedAttributeDirective {
210
86
  */
211
87
  constructor(options) {
212
88
  this.options = options;
213
- /**
214
- * The unique id of the factory.
215
- */
216
- this.id = nextId();
217
89
  }
218
90
  /**
219
91
  * Creates a placeholder string based on the directive's index within the template.
@@ -232,3 +104,4 @@ export class StatelessAttachedAttributeDirective {
232
104
  return this;
233
105
  }
234
106
  }
107
+ makeSerializationNoop(StatelessAttachedAttributeDirective);
@@ -0,0 +1,17 @@
1
+ import { Hydratable } from "../components/hydration.js";
2
+ import { ViewTemplate } from "./template.js";
3
+ import { HydrationView } from "./view.js";
4
+ // Configure ViewTemplate to be hydratable by attaching a symbol identifier
5
+ // and a hydrate method. Augmenting the hydration features is done by
6
+ // property assignment instead of class extension to better allow the
7
+ // hydration feature to be tree-shaken.
8
+ Object.defineProperties(ViewTemplate.prototype, {
9
+ [Hydratable]: { value: Hydratable, enumerable: false, configurable: false },
10
+ hydrate: {
11
+ value: function (firstChild, lastChild, hostBindingTarget) {
12
+ return new HydrationView(firstChild, lastChild, this, hostBindingTarget);
13
+ },
14
+ enumerable: true,
15
+ configurable: false,
16
+ },
17
+ });
@@ -16,9 +16,15 @@ export const elements = (selector) => selector
16
16
  * Internally used by the SlottedDirective and the ChildrenDirective.
17
17
  */
18
18
  export class NodeObservationDirective extends StatelessAttachedAttributeDirective {
19
- constructor() {
20
- super(...arguments);
21
- this.sourceProperty = `${this.id}-s`;
19
+ /**
20
+ * The unique id of the factory.
21
+ */
22
+ get id() {
23
+ return this._id;
24
+ }
25
+ set id(value) {
26
+ this._id = value;
27
+ this._controllerProperty = `${value}-c`;
22
28
  }
23
29
  /**
24
30
  * Bind this behavior to the source.
@@ -27,8 +33,8 @@ export class NodeObservationDirective extends StatelessAttachedAttributeDirectiv
27
33
  * @param targets - The targets that behaviors in a view can attach to.
28
34
  */
29
35
  bind(controller) {
30
- const target = controller.targets[this.nodeId];
31
- target[this.sourceProperty] = controller.source;
36
+ const target = controller.targets[this.targetNodeId];
37
+ target[this._controllerProperty] = controller;
32
38
  this.updateTarget(controller.source, this.computeNodes(target));
33
39
  this.observe(target);
34
40
  controller.onUnbind(this);
@@ -40,10 +46,10 @@ export class NodeObservationDirective extends StatelessAttachedAttributeDirectiv
40
46
  * @param targets - The targets that behaviors in a view can attach to.
41
47
  */
42
48
  unbind(controller) {
43
- const target = controller.targets[this.nodeId];
49
+ const target = controller.targets[this.targetNodeId];
44
50
  this.updateTarget(controller.source, emptyArray);
45
51
  this.disconnect(target);
46
- target[this.sourceProperty] = null;
52
+ target[this._controllerProperty] = null;
47
53
  }
48
54
  /**
49
55
  * Gets the data source for the target.
@@ -51,7 +57,7 @@ export class NodeObservationDirective extends StatelessAttachedAttributeDirectiv
51
57
  * @returns The source.
52
58
  */
53
59
  getSource(target) {
54
- return target[this.sourceProperty];
60
+ return target[this._controllerProperty].source;
55
61
  }
56
62
  /**
57
63
  * Updates the source property with the computed nodes.
@@ -9,7 +9,7 @@ export class RefDirective extends StatelessAttachedAttributeDirective {
9
9
  * @param controller - The view controller that manages the lifecycle of this behavior.
10
10
  */
11
11
  bind(controller) {
12
- controller.source[this.options] = controller.targets[this.nodeId];
12
+ controller.source[this.options] = controller.targets[this.targetNodeId];
13
13
  }
14
14
  }
15
15
  HTMLDirective.define(RefDirective);
@@ -0,0 +1,56 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { attr, css, FASTElement, html, oneTime, repeat } from "../index.js";
11
+ import { data } from "../__test__/utilities.js";
12
+ const xItemTemplate = html `
13
+ <div @click="${x => x.onClick}" class="item">${x => x.value}</div>
14
+ `;
15
+ const styles = css `
16
+ .item {
17
+ display: flex;
18
+ }
19
+ `;
20
+ class XItem extends FASTElement {
21
+ onClick(e) {
22
+ console.log(e.type);
23
+ }
24
+ }
25
+ __decorate([
26
+ attr,
27
+ __metadata("design:type", Object)
28
+ ], XItem.prototype, "value", void 0);
29
+ XItem.define({
30
+ name: "x-item",
31
+ template: xItemTemplate,
32
+ styles,
33
+ });
34
+ const xAppTemplate = html `
35
+ <div id="test-container">
36
+ ${repeat(x => x.items, html `
37
+ <x-item :value="${oneTime((x) => x.label)}"></x-item>
38
+ `)}
39
+ </div>
40
+ `;
41
+ class XApp extends FASTElement {
42
+ constructor() {
43
+ super(...arguments);
44
+ this.items = data;
45
+ }
46
+ }
47
+ XApp.define({
48
+ name: "x-app",
49
+ template: xAppTemplate,
50
+ });
51
+ const itemRenderer = () => {
52
+ const testRender = document.createElement("x-app");
53
+ return testRender;
54
+ };
55
+ export default itemRenderer;
56
+ export { tests } from "@tensile-perf/web-components";