@microsoft/fast-element 2.0.0-beta.2 → 2.0.0-beta.20

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 (113) hide show
  1. package/CHANGELOG.json +488 -0
  2. package/CHANGELOG.md +180 -1
  3. package/dist/dts/components/attributes.d.ts +15 -0
  4. package/dist/dts/components/{controller.d.ts → element-controller.d.ts} +74 -28
  5. package/dist/dts/components/fast-definitions.d.ts +41 -9
  6. package/dist/dts/components/fast-element.d.ts +14 -26
  7. package/dist/dts/components/hydration.d.ts +14 -0
  8. package/dist/{esm/observation/behavior.js → dts/components/install-hydration.d.ts} +0 -0
  9. package/dist/dts/context.d.ts +1 -1
  10. package/dist/dts/di/di.d.ts +894 -0
  11. package/dist/dts/dom-policy.d.ts +68 -0
  12. package/dist/dts/dom.d.ts +100 -0
  13. package/dist/dts/index.d.ts +5 -4
  14. package/dist/dts/index.rollup.d.ts +0 -1
  15. package/dist/dts/index.rollup.debug.d.ts +0 -1
  16. package/dist/dts/interfaces.d.ts +60 -79
  17. package/dist/dts/observation/observable.d.ts +99 -54
  18. package/dist/dts/pending-task.d.ts +20 -0
  19. package/dist/dts/platform.d.ts +7 -0
  20. package/dist/dts/polyfills.d.ts +0 -8
  21. package/dist/dts/state/exports.d.ts +3 -0
  22. package/dist/dts/state/reactive.d.ts +8 -0
  23. package/dist/dts/state/state.d.ts +141 -0
  24. package/dist/dts/state/visitor.d.ts +6 -0
  25. package/dist/dts/state/watch.d.ts +10 -0
  26. package/dist/dts/styles/css-directive.d.ts +2 -2
  27. package/dist/dts/styles/css.d.ts +0 -5
  28. package/dist/dts/styles/element-styles.d.ts +10 -17
  29. package/dist/dts/styles/host.d.ts +68 -0
  30. package/dist/dts/styles/style-strategy.d.ts +42 -0
  31. package/dist/dts/templating/binding-signal.d.ts +12 -27
  32. package/dist/dts/templating/binding-two-way.d.ts +22 -37
  33. package/dist/dts/templating/binding.d.ts +76 -208
  34. package/dist/dts/templating/children.d.ts +1 -1
  35. package/dist/dts/templating/compiler.d.ts +11 -13
  36. package/dist/dts/templating/html-directive.d.ts +91 -97
  37. package/dist/dts/templating/node-observation.d.ts +15 -6
  38. package/dist/dts/templating/ref.d.ts +7 -11
  39. package/dist/dts/templating/render.d.ts +296 -0
  40. package/dist/dts/templating/repeat.d.ts +23 -34
  41. package/dist/dts/templating/slotted.d.ts +1 -1
  42. package/dist/dts/templating/template.d.ts +92 -14
  43. package/dist/dts/templating/view.d.ts +81 -11
  44. package/dist/dts/templating/when.d.ts +3 -3
  45. package/dist/dts/testing/exports.d.ts +3 -0
  46. package/dist/dts/testing/fakes.d.ts +14 -0
  47. package/dist/dts/testing/fixture.d.ts +84 -0
  48. package/dist/dts/testing/timeout.d.ts +7 -0
  49. package/dist/dts/utilities.d.ts +53 -18
  50. package/dist/esm/components/attributes.js +28 -5
  51. package/dist/esm/components/{controller.js → element-controller.js} +239 -137
  52. package/dist/esm/components/fast-definitions.js +38 -30
  53. package/dist/esm/components/fast-element.js +27 -16
  54. package/dist/esm/components/hydration.js +35 -0
  55. package/dist/esm/components/install-hydration.js +2 -0
  56. package/dist/esm/context.js +5 -1
  57. package/dist/esm/debug.js +40 -5
  58. package/dist/esm/di/di.js +1430 -0
  59. package/dist/esm/dom-policy.js +337 -0
  60. package/dist/esm/dom.js +101 -0
  61. package/dist/esm/index.js +4 -2
  62. package/dist/esm/index.rollup.debug.js +3 -1
  63. package/dist/esm/index.rollup.js +3 -1
  64. package/dist/esm/interfaces.js +52 -0
  65. package/dist/esm/observation/arrays.js +303 -2
  66. package/dist/esm/observation/observable.js +88 -142
  67. package/dist/esm/observation/update-queue.js +2 -2
  68. package/dist/esm/pending-task.js +16 -0
  69. package/dist/esm/platform.js +27 -2
  70. package/dist/esm/polyfills.js +3 -61
  71. package/dist/esm/state/exports.js +3 -0
  72. package/dist/esm/state/reactive.js +34 -0
  73. package/dist/esm/state/state.js +148 -0
  74. package/dist/esm/state/visitor.js +28 -0
  75. package/dist/esm/state/watch.js +36 -0
  76. package/dist/esm/styles/css.js +4 -9
  77. package/dist/esm/styles/element-styles.js +14 -33
  78. package/dist/esm/styles/host.js +1 -0
  79. package/dist/esm/styles/style-strategy.js +1 -0
  80. package/dist/esm/templating/binding-signal.js +67 -62
  81. package/dist/esm/templating/binding-two-way.js +72 -39
  82. package/dist/esm/templating/binding.js +142 -286
  83. package/dist/esm/templating/children.js +8 -4
  84. package/dist/esm/templating/compiler.js +59 -43
  85. package/dist/esm/templating/html-directive.js +56 -75
  86. package/dist/esm/templating/node-observation.js +20 -13
  87. package/dist/esm/templating/ref.js +4 -12
  88. package/dist/esm/templating/render.js +402 -0
  89. package/dist/esm/templating/repeat.js +88 -75
  90. package/dist/esm/templating/template.js +132 -60
  91. package/dist/esm/templating/view.js +113 -29
  92. package/dist/esm/templating/when.js +5 -4
  93. package/dist/esm/testing/exports.js +3 -0
  94. package/dist/esm/testing/fakes.js +107 -0
  95. package/dist/esm/testing/fixture.js +86 -0
  96. package/dist/esm/testing/timeout.js +24 -0
  97. package/dist/esm/utilities.js +95 -95
  98. package/dist/fast-element.api.json +9487 -8326
  99. package/dist/fast-element.d.ts +847 -644
  100. package/dist/fast-element.debug.js +1993 -1166
  101. package/dist/fast-element.debug.min.js +1 -1
  102. package/dist/fast-element.js +1903 -1111
  103. package/dist/fast-element.min.js +1 -1
  104. package/dist/fast-element.untrimmed.d.ts +911 -701
  105. package/docs/api-report.md +329 -252
  106. package/package.json +38 -16
  107. package/dist/dts/hooks.d.ts +0 -20
  108. package/dist/dts/observation/behavior.d.ts +0 -19
  109. package/dist/dts/observation/splice-strategies.d.ts +0 -13
  110. package/dist/dts/templating/dom.d.ts +0 -41
  111. package/dist/esm/hooks.js +0 -32
  112. package/dist/esm/observation/splice-strategies.js +0 -400
  113. package/dist/esm/templating/dom.js +0 -49
@@ -1,5 +1,6 @@
1
- import { Binding, ExecutionContext } from "../observation/observable.js";
2
- import { HTMLDirective, ViewBehaviorFactory } from "./html-directive.js";
1
+ import type { DOMPolicy } from "../dom.js";
2
+ import type { Expression } from "../observation/observable.js";
3
+ import { AddViewBehaviorFactory, Binding, HTMLDirective, ViewBehaviorFactory } from "./html-directive.js";
3
4
  import type { ElementView, HTMLView, SyntheticView } from "./view.js";
4
5
  /**
5
6
  * A template capable of creating views specifically for rendering custom elements.
@@ -20,6 +21,13 @@ export interface ElementViewTemplate<TSource = any, TParent = any> {
20
21
  */
21
22
  render(source: TSource, host: Node, hostBindingTarget?: Element): ElementView<TSource, TParent>;
22
23
  }
24
+ /**
25
+ * A marker interface used to capture types when interpolating Directive helpers
26
+ * into templates.
27
+ * @public
28
+ */
29
+ export interface CaptureType<TSource, TParent> {
30
+ }
23
31
  /**
24
32
  * A template capable of rendering views not specifically connected to custom elements.
25
33
  * @public
@@ -29,6 +37,10 @@ export interface SyntheticViewTemplate<TSource = any, TParent = any> {
29
37
  * Creates a SyntheticView instance based on this template definition.
30
38
  */
31
39
  create(): SyntheticView<TSource, TParent>;
40
+ /**
41
+ * Returns a directive that can inline the template.
42
+ */
43
+ inline(): CaptureType<TSource, TParent>;
32
44
  }
33
45
  /**
34
46
  * The result of a template compilation operation.
@@ -41,11 +53,39 @@ export interface HTMLTemplateCompilationResult<TSource = any, TParent = any> {
41
53
  */
42
54
  createView(hostBindingTarget?: Element): HTMLView<TSource, TParent>;
43
55
  }
56
+ /**
57
+ * Represents the types of values that can be interpolated into a template.
58
+ * @public
59
+ */
60
+ export declare type TemplateValue<TSource, TParent = any> = Expression<TSource, any, TParent> | Binding<TSource, any, TParent> | HTMLDirective | CaptureType<TSource, TParent>;
61
+ /**
62
+ * Inlines a template into another template.
63
+ * @public
64
+ */
65
+ export declare class InlineTemplateDirective implements HTMLDirective {
66
+ private html;
67
+ private factories;
68
+ /**
69
+ * An empty template partial.
70
+ */
71
+ static readonly empty: InlineTemplateDirective;
72
+ /**
73
+ * Creates an instance of InlineTemplateDirective.
74
+ * @param template - The template to inline.
75
+ */
76
+ constructor(html: string, factories?: Record<string, ViewBehaviorFactory>);
77
+ /**
78
+ * Creates HTML to be used within a template.
79
+ * @param add - Can be used to add behavior factories to a template.
80
+ */
81
+ createHTML(add: AddViewBehaviorFactory): string;
82
+ }
44
83
  /**
45
84
  * A template capable of creating HTMLView instances or rendering directly to DOM.
46
85
  * @public
47
86
  */
48
87
  export declare class ViewTemplate<TSource = any, TParent = any> implements ElementViewTemplate<TSource, TParent>, SyntheticViewTemplate<TSource, TParent> {
88
+ private policy?;
49
89
  private result;
50
90
  /**
51
91
  * The html representing what this template will
@@ -60,13 +100,27 @@ export declare class ViewTemplate<TSource = any, TParent = any> implements Eleme
60
100
  * Creates an instance of ViewTemplate.
61
101
  * @param html - The html representing what this template will instantiate, including placeholders for directives.
62
102
  * @param factories - The directives that will be connected to placeholders in the html.
103
+ * @param policy - The security policy to use when compiling this template.
63
104
  */
64
- constructor(html: string | HTMLTemplateElement, factories: Record<string, ViewBehaviorFactory>);
105
+ constructor(html: string | HTMLTemplateElement, factories?: Record<string, ViewBehaviorFactory>, policy?: DOMPolicy | undefined);
65
106
  /**
66
107
  * Creates an HTMLView instance based on this template definition.
67
108
  * @param hostBindingTarget - The element that host behaviors will be bound to.
68
109
  */
69
110
  create(hostBindingTarget?: Element): HTMLView<TSource, TParent>;
111
+ /**
112
+ * Returns a directive that can inline the template.
113
+ */
114
+ inline(): CaptureType<TSource, TParent>;
115
+ /**
116
+ * Sets the DOMPolicy for this template.
117
+ * @param policy - The policy to associated with this template.
118
+ * @returns The modified template instance.
119
+ * @remarks
120
+ * The DOMPolicy can only be set once for a template and cannot be
121
+ * set after the template is compiled.
122
+ */
123
+ withPolicy(policy: DOMPolicy): this;
70
124
  /**
71
125
  * Creates an HTMLView from this template, binds it to the source, and then appends it to the host.
72
126
  * @param source - The data source to bind the template to.
@@ -74,20 +128,44 @@ export declare class ViewTemplate<TSource = any, TParent = any> implements Eleme
74
128
  * @param hostBindingTarget - An HTML element to target the host bindings at if different from the
75
129
  * host that the template is being attached to.
76
130
  */
77
- render(source: TSource, host: Node, hostBindingTarget?: Element, context?: ExecutionContext): HTMLView<TSource, TParent>;
78
- }
79
- /**
80
- * A marker interface used to capture types when interpolating Directive helpers
81
- * into templates.
82
- * @public
83
- */
84
- export interface CaptureType<TSource> {
131
+ render(source: TSource, host: Node, hostBindingTarget?: Element): HTMLView<TSource, TParent>;
132
+ /**
133
+ * Opts out of JSON stringification.
134
+ * @internal
135
+ */
136
+ toJSON: () => undefined;
137
+ /**
138
+ * Creates a template based on a set of static strings and dynamic values.
139
+ * @param strings - The static strings to create the template with.
140
+ * @param values - The dynamic values to create the template with.
141
+ * @param policy - The DOMPolicy to associated with the template.
142
+ * @returns A ViewTemplate.
143
+ * @remarks
144
+ * This API should not be used directly under normal circumstances because constructing
145
+ * a template in this way, if not done properly, can open up the application to XSS
146
+ * attacks. When using this API, provide a strong DOMPolicy that can properly sanitize
147
+ * and also be sure to manually sanitize all static strings particularly if they can
148
+ * come from user input.
149
+ */
150
+ static create<TSource = any, TParent = any>(strings: string[], values: TemplateValue<TSource, TParent>[], policy?: DOMPolicy): ViewTemplate<TSource, TParent>;
85
151
  }
86
152
  /**
87
- * Represents the types of values that can be interpolated into a template.
153
+ * Transforms a template literal string into a ViewTemplate.
154
+ * @param strings - The string fragments that are interpolated with the values.
155
+ * @param values - The values that are interpolated with the string fragments.
156
+ * @remarks
157
+ * The html helper supports interpolation of strings, numbers, binding expressions,
158
+ * other template instances, and Directive instances.
88
159
  * @public
89
160
  */
90
- export declare type TemplateValue<TSource, TParent = any> = Binding<TSource, any, TParent> | HTMLDirective | CaptureType<TSource>;
161
+ export declare type HTMLTemplateTag = (<TSource = any, TParent = any>(strings: TemplateStringsArray, ...values: TemplateValue<TSource, TParent>[]) => ViewTemplate<TSource, TParent>) & {
162
+ /**
163
+ * Transforms a template literal string into partial HTML.
164
+ * @param html - The HTML string fragment to interpolate.
165
+ * @public
166
+ */
167
+ partial(html: string): InlineTemplateDirective;
168
+ };
91
169
  /**
92
170
  * Transforms a template literal string into a ViewTemplate.
93
171
  * @param strings - The string fragments that are interpolated with the values.
@@ -97,4 +175,4 @@ export declare type TemplateValue<TSource, TParent = any> = Binding<TSource, any
97
175
  * other template instances, and Directive instances.
98
176
  * @public
99
177
  */
100
- export declare function html<TSource = any, TParent = any>(strings: TemplateStringsArray, ...values: TemplateValue<TSource, TParent>[]): ViewTemplate<TSource, TParent>;
178
+ export declare const html: HTMLTemplateTag;
@@ -1,6 +1,6 @@
1
- import type { Disposable } from "../interfaces.js";
2
- import type { ExecutionContext } from "../observation/observable.js";
3
- import type { ViewBehaviorFactory, ViewBehaviorTargets } from "./html-directive.js";
1
+ import { Disposable } from "../interfaces.js";
2
+ import { ExecutionContext, SourceLifetime } from "../observation/observable.js";
3
+ import type { CompiledViewBehaviorFactory, ViewBehaviorTargets, ViewController } from "./html-directive.js";
4
4
  /**
5
5
  * Represents a collection of DOM nodes which can be bound to a data source.
6
6
  * @public
@@ -9,7 +9,7 @@ export interface View<TSource = any, TParent = any> extends Disposable {
9
9
  /**
10
10
  * The execution context the view is running within.
11
11
  */
12
- readonly context: ExecutionContext<TParent> | null;
12
+ readonly context: ExecutionContext<TParent>;
13
13
  /**
14
14
  * The data that the view is bound to.
15
15
  */
@@ -17,9 +17,8 @@ export interface View<TSource = any, TParent = any> extends Disposable {
17
17
  /**
18
18
  * Binds a view's behaviors to its binding source.
19
19
  * @param source - The binding source for the view's binding behaviors.
20
- * @param context - The execution context to run the view within.
21
20
  */
22
- bind(source: TSource, context: ExecutionContext<TParent>): void;
21
+ bind(source: TSource, context?: ExecutionContext<TParent>): void;
23
22
  /**
24
23
  * Unbinds a view's behaviors from its binding source and context.
25
24
  */
@@ -64,19 +63,81 @@ export interface SyntheticView<TSource = any, TParent = any> extends View<TSourc
64
63
  * The standard View implementation, which also implements ElementView and SyntheticView.
65
64
  * @public
66
65
  */
67
- export declare class HTMLView<TSource = any, TParent = any> implements ElementView<TSource, TParent>, SyntheticView<TSource, TParent> {
66
+ export declare class HTMLView<TSource = any, TParent = any> implements ElementView<TSource, TParent>, SyntheticView<TSource, TParent>, ExecutionContext<TParent> {
68
67
  private fragment;
69
68
  private factories;
70
- private targets;
69
+ readonly targets: ViewBehaviorTargets;
71
70
  private behaviors;
71
+ private unbindables;
72
72
  /**
73
73
  * The data that the view is bound to.
74
74
  */
75
75
  source: TSource | null;
76
+ /**
77
+ * Indicates whether the controller is bound.
78
+ */
79
+ isBound: boolean;
80
+ /**
81
+ * Indicates how the source's lifetime relates to the controller's lifetime.
82
+ */
83
+ readonly sourceLifetime: SourceLifetime;
76
84
  /**
77
85
  * The execution context the view is running within.
78
86
  */
79
- context: ExecutionContext<TParent> | null;
87
+ context: ExecutionContext<TParent>;
88
+ /**
89
+ * The index of the current item within a repeat context.
90
+ */
91
+ index: number;
92
+ /**
93
+ * The length of the current collection within a repeat context.
94
+ */
95
+ length: number;
96
+ /**
97
+ * The parent data source within a nested context.
98
+ */
99
+ readonly parent: TParent;
100
+ /**
101
+ * The parent execution context when in nested context scenarios.
102
+ */
103
+ readonly parentContext: ExecutionContext<TParent>;
104
+ /**
105
+ * The current event within an event handler.
106
+ */
107
+ get event(): Event;
108
+ /**
109
+ * Indicates whether the current item within a repeat context
110
+ * has an even index.
111
+ */
112
+ get isEven(): boolean;
113
+ /**
114
+ * Indicates whether the current item within a repeat context
115
+ * has an odd index.
116
+ */
117
+ get isOdd(): boolean;
118
+ /**
119
+ * Indicates whether the current item within a repeat context
120
+ * is the first item in the collection.
121
+ */
122
+ get isFirst(): boolean;
123
+ /**
124
+ * Indicates whether the current item within a repeat context
125
+ * is somewhere in the middle of the collection.
126
+ */
127
+ get isInMiddle(): boolean;
128
+ /**
129
+ * Indicates whether the current item within a repeat context
130
+ * is the last item in the collection.
131
+ */
132
+ get isLast(): boolean;
133
+ /**
134
+ * Returns the typed event detail of a custom event.
135
+ */
136
+ eventDetail<TDetail>(): TDetail;
137
+ /**
138
+ * Returns the typed event target of the event.
139
+ */
140
+ eventTarget<TTarget extends EventTarget>(): TTarget;
80
141
  /**
81
142
  * The first DOM node in the range of nodes that make up the view.
82
143
  */
@@ -90,7 +151,7 @@ export declare class HTMLView<TSource = any, TParent = any> implements ElementVi
90
151
  * @param fragment - The html fragment that contains the nodes for this view.
91
152
  * @param behaviors - The behaviors to be applied to this view.
92
153
  */
93
- constructor(fragment: DocumentFragment, factories: ReadonlyArray<ViewBehaviorFactory>, targets: ViewBehaviorTargets);
154
+ constructor(fragment: DocumentFragment, factories: ReadonlyArray<CompiledViewBehaviorFactory>, targets: ViewBehaviorTargets);
94
155
  /**
95
156
  * Appends the view's DOM nodes to the referenced node.
96
157
  * @param node - The parent node to append the view's DOM nodes to.
@@ -111,16 +172,25 @@ export declare class HTMLView<TSource = any, TParent = any> implements ElementVi
111
172
  * Once a view has been disposed, it cannot be inserted or bound again.
112
173
  */
113
174
  dispose(): void;
175
+ onUnbind(behavior: {
176
+ unbind(controller: ViewController<TSource, TParent>): any;
177
+ }): void;
114
178
  /**
115
179
  * Binds a view's behaviors to its binding source.
116
180
  * @param source - The binding source for the view's binding behaviors.
117
181
  * @param context - The execution context to run the behaviors within.
118
182
  */
119
- bind(source: TSource, context: ExecutionContext<TParent>): void;
183
+ bind(source: TSource, context?: ExecutionContext<TParent>): void;
120
184
  /**
121
185
  * Unbinds a view's behaviors from its binding source.
122
186
  */
123
187
  unbind(): void;
188
+ /**
189
+ * Opts out of JSON stringification.
190
+ * @internal
191
+ */
192
+ toJSON: () => undefined;
193
+ private evaluateUnbindables;
124
194
  /**
125
195
  * Efficiently disposes of a contiguous range of synthetic view instances.
126
196
  * @param views - A contiguous range of views to be disposed.
@@ -1,10 +1,10 @@
1
- import type { Binding } from "../observation/observable.js";
1
+ import type { Expression } from "../observation/observable.js";
2
2
  import type { CaptureType, SyntheticViewTemplate } from "./template.js";
3
3
  /**
4
4
  * A directive that enables basic conditional rendering in a template.
5
- * @param binding - The condition to test for rendering.
5
+ * @param condition - The condition to test for rendering.
6
6
  * @param templateOrTemplateBinding - The template or a binding that gets
7
7
  * the template to render when the condition is true.
8
8
  * @public
9
9
  */
10
- export declare function when<TSource = any, TReturn = any>(binding: Binding<TSource, TReturn>, templateOrTemplateBinding: SyntheticViewTemplate | Binding<TSource, SyntheticViewTemplate>): CaptureType<TSource>;
10
+ export declare function when<TSource = any, TReturn = any, TParent = any>(condition: Expression<TSource, TReturn, TParent> | boolean, templateOrTemplateBinding: SyntheticViewTemplate<TSource, TParent> | Expression<TSource, SyntheticViewTemplate<TSource, TParent>, TParent>): CaptureType<TSource, TParent>;
@@ -0,0 +1,3 @@
1
+ export { timeout } from "./timeout.js";
2
+ export * from "./fixture.js";
3
+ export * from "./fakes.js";
@@ -0,0 +1,14 @@
1
+ import { ExecutionContext, ViewBehavior, ViewBehaviorTargets } from "../index.js";
2
+ export declare const Fake: Readonly<{
3
+ executionContext<TParent = any>(parent?: TParent | undefined, parentContext?: ExecutionContext<TParent> | undefined): ExecutionContext<TParent>;
4
+ viewController<TSource = any, TParent_1 = any>(targets?: ViewBehaviorTargets, ...behaviors: ViewBehavior<TSource, TParent_1>[]): {
5
+ isBound: boolean;
6
+ context: ExecutionContext<TParent_1>;
7
+ onUnbind(object: any): void;
8
+ source: TSource;
9
+ targets: ViewBehaviorTargets;
10
+ toJSON: () => undefined;
11
+ bind(source: TSource, context?: ExecutionContext<TParent_1>): void;
12
+ unbind(): void;
13
+ };
14
+ }>;
@@ -0,0 +1,84 @@
1
+ import type { Constructable } from "../interfaces.js";
2
+ import { ViewTemplate } from "../templating/template.js";
3
+ import type { HTMLView } from "../templating/view.js";
4
+ /**
5
+ * Options used to customize the creation of the test fixture.
6
+ * @public
7
+ */
8
+ export interface FixtureOptions {
9
+ /**
10
+ * The document to run the fixture in.
11
+ * @defaultValue `globalThis.document`
12
+ */
13
+ document?: Document;
14
+ /**
15
+ * The parent element to append the fixture to.
16
+ * @defaultValue An instance of `HTMLDivElement`.
17
+ */
18
+ parent?: HTMLElement;
19
+ /**
20
+ * The data source to bind the HTML to.
21
+ * @defaultValue An empty object.
22
+ */
23
+ source?: any;
24
+ }
25
+ /**
26
+ * A test fixture.
27
+ * @public
28
+ */
29
+ export interface Fixture<TElement = HTMLElement> {
30
+ /**
31
+ * The document the fixture is running in.
32
+ */
33
+ document: Document;
34
+ /**
35
+ * The template the fixture was created from.
36
+ */
37
+ template: ViewTemplate;
38
+ /**
39
+ * The view that was created from the fixture's template.
40
+ */
41
+ view: HTMLView;
42
+ /**
43
+ * The parent element that the view was appended to.
44
+ * @remarks
45
+ * This element will be appended to the DOM only
46
+ * after {@link Fixture.connect} has been called.
47
+ */
48
+ parent: HTMLElement;
49
+ /**
50
+ * The first element in the {@link Fixture.view}.
51
+ */
52
+ element: TElement;
53
+ /**
54
+ * Adds the {@link Fixture.parent} to the DOM, causing the
55
+ * connect lifecycle to begin.
56
+ * @remarks
57
+ * Yields control to the caller one Microtask later, in order to
58
+ * ensure that the DOM has settled.
59
+ */
60
+ connect: () => Promise<void>;
61
+ /**
62
+ * Removes the {@link Fixture.parent} from the DOM, causing the
63
+ * disconnect lifecycle to begin.
64
+ * @remarks
65
+ * Yields control to the caller one Microtask later, in order to
66
+ * ensure that the DOM has settled.
67
+ */
68
+ disconnect: () => Promise<void>;
69
+ }
70
+ /**
71
+ * Creates a random, unique name suitable for use as a Custom Element name.
72
+ * @public
73
+ */
74
+ export declare function uniqueElementName(prefix?: string): string;
75
+ /**
76
+ * Creates a test fixture suitable for testing custom elements, templates, and bindings.
77
+ * @param templateNameOrType An HTML template or single element name to create the fixture for.
78
+ * @param options Enables customizing fixture creation behavior.
79
+ * @remarks
80
+ * Yields control to the caller one Microtask later, in order to
81
+ * ensure that the DOM has settled.
82
+ * @public
83
+ */
84
+ export declare function fixture<TElement = HTMLElement>(templateNameOrType: ViewTemplate | string | Constructable<TElement>, options?: FixtureOptions): Promise<Fixture<TElement>>;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * A timeout helper for use in tests.
3
+ * @param timeout The length of the timeout.
4
+ * @returns A promise that resolves once the configured time has elapsed.
5
+ * @public
6
+ */
7
+ export declare function timeout(timeout?: number): Promise<void>;
@@ -1,21 +1,5 @@
1
- import { Disposable } from "./interfaces.js";
2
- import type { Subscriber } from "./observation/notifier.js";
3
- /**
4
- * Converts a plain object to an observable object.
5
- * @param object - The object to make observable.
6
- * @param deep - Indicates whether or not to deeply convert the oject.
7
- * @returns The converted object.
8
- * @beta
9
- */
10
- export declare function makeObservable<T>(object: T, deep?: boolean): T;
11
- /**
12
- * Deeply subscribes to changes in existing observable objects.
13
- * @param object - The observable object to watch.
14
- * @param subscriber - The handler to call when changes are made to the object.
15
- * @returns A disposable that can be used to unsubscribe from change updates.
16
- * @beta
17
- */
18
- export declare function watch(object: any, subscriber: Subscriber | ((subject: any, args: any) => void)): Disposable;
1
+ import type { HostBehavior } from "./styles/host.js";
2
+ import type { ViewBehavior, ViewBehaviorFactory, ViewController } from "./templating/html-directive.js";
19
3
  /**
20
4
  * Retrieves the "composed parent" element of a node, ignoring DOM tree boundaries.
21
5
  * When the parent of a node is a shadow-root, it will return the host
@@ -38,3 +22,54 @@ export declare function composedParent<T extends HTMLElement>(element: T): HTMLE
38
22
  * @public
39
23
  */
40
24
  export declare function composedContains(reference: HTMLElement, test: HTMLElement): boolean;
25
+ /**
26
+ * @internal
27
+ */
28
+ export declare class UnobservableMutationObserver extends MutationObserver {
29
+ private readonly callback;
30
+ private observedNodes;
31
+ /**
32
+ * An extension of MutationObserver that supports unobserving nodes.
33
+ * @param callback - The callback to invoke when observed nodes are changed.
34
+ */
35
+ constructor(callback: MutationCallback);
36
+ observe(target: Node, options?: MutationObserverInit | undefined): void;
37
+ unobserve(target: Node): void;
38
+ }
39
+ /**
40
+ * Bridges between ViewBehaviors and HostBehaviors, enabling a host to
41
+ * control ViewBehaviors.
42
+ * @public
43
+ */
44
+ export interface ViewBehaviorOrchestrator<TSource = any, TParent = any> extends ViewController<TSource, TParent>, HostBehavior<TSource> {
45
+ /**
46
+ *
47
+ * @param nodeId - The structural id of the DOM node to which a behavior will apply.
48
+ * @param target - The DOM node associated with the id.
49
+ */
50
+ addTarget(nodeId: string, target: Node): void;
51
+ /**
52
+ * Adds a behavior.
53
+ * @param behavior - The behavior to add.
54
+ */
55
+ addBehavior(behavior: ViewBehavior): void;
56
+ /**
57
+ * Adds a behavior factory.
58
+ * @param factory - The behavior factory to add.
59
+ * @param target - The target the factory will create behaviors for.
60
+ */
61
+ addBehaviorFactory(factory: ViewBehaviorFactory, target: Node): void;
62
+ }
63
+ /**
64
+ * Bridges between ViewBehaviors and HostBehaviors, enabling a host to
65
+ * control ViewBehaviors.
66
+ * @public
67
+ */
68
+ export declare const ViewBehaviorOrchestrator: Readonly<{
69
+ /**
70
+ * Creates a ViewBehaviorOrchestrator.
71
+ * @param source - The source to to associate behaviors with.
72
+ * @returns A ViewBehaviorOrchestrator.
73
+ */
74
+ create<TSource = any, TParent = any>(source: TSource): ViewBehaviorOrchestrator<TSource, TParent>;
75
+ }>;
@@ -1,9 +1,20 @@
1
1
  import { Observable } from "../observation/observable.js";
2
2
  import { isString } from "../interfaces.js";
3
3
  import { Updates } from "../observation/update-queue.js";
4
- import { DOM } from "../templating/dom.js";
4
+ import { DOM } from "../dom.js";
5
+ import { createMetadataLocator } from "../platform.js";
5
6
  const booleanMode = "boolean";
6
7
  const reflectMode = "reflect";
8
+ /**
9
+ * Metadata used to configure a custom attribute's behavior.
10
+ * @public
11
+ */
12
+ export const AttributeConfiguration = Object.freeze({
13
+ /**
14
+ * Locates all attribute configurations associated with a type.
15
+ */
16
+ locate: createMetadataLocator(),
17
+ });
7
18
  /**
8
19
  * A {@link ValueConverter} that converts to and from `boolean` values.
9
20
  * @remarks
@@ -24,6 +35,20 @@ export const booleanConverter = {
24
35
  : true;
25
36
  },
26
37
  };
38
+ /**
39
+ * A {@link ValueConverter} that converts to and from `boolean` values. `null`, `undefined`, `""`, and `void` values are converted to `null`.
40
+ * @public
41
+ */
42
+ export const nullableBooleanConverter = {
43
+ toView(value) {
44
+ return typeof value === "boolean" ? value.toString() : "";
45
+ },
46
+ fromView(value) {
47
+ return [null, undefined, void 0].includes(value)
48
+ ? null
49
+ : booleanConverter.fromView(value);
50
+ },
51
+ };
27
52
  function toNumber(value) {
28
53
  if (value === null || value === undefined) {
29
54
  return null;
@@ -141,7 +166,7 @@ export class AttributeDefinition {
141
166
  */
142
167
  static collect(Owner, ...attributeLists) {
143
168
  const attributes = [];
144
- attributeLists.push(Owner.attributes);
169
+ attributeLists.push(AttributeConfiguration.locate(Owner));
145
170
  for (let i = 0, ii = attributeLists.length; i < ii; ++i) {
146
171
  const list = attributeLists[i];
147
172
  if (list === void 0) {
@@ -171,9 +196,7 @@ export function attr(configOrTarget, prop) {
171
196
  // - @attr({...opts})
172
197
  config.property = $prop;
173
198
  }
174
- const attributes = $target.constructor.attributes ||
175
- ($target.constructor.attributes = []);
176
- attributes.push(config);
199
+ AttributeConfiguration.locate($target.constructor).push(config);
177
200
  }
178
201
  if (arguments.length > 1) {
179
202
  // Non invocation: