element-vir 22.2.1 → 23.0.0

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 (137) hide show
  1. package/README.md +42 -36
  2. package/dist/declarative-element/custom-tag-name.d.ts +6 -0
  3. package/dist/declarative-element/declarative-element-init.d.ts +20 -14
  4. package/dist/declarative-element/declarative-element.d.ts +70 -24
  5. package/dist/declarative-element/declarative-element.js +34 -1
  6. package/dist/declarative-element/define-element-no-inputs.d.ts +31 -6
  7. package/dist/declarative-element/define-element-no-inputs.js +154 -257
  8. package/dist/declarative-element/define-element.d.ts +35 -7
  9. package/dist/declarative-element/define-element.js +26 -4
  10. package/dist/declarative-element/definition-options.d.ts +10 -0
  11. package/dist/declarative-element/definition-options.js +5 -0
  12. package/dist/declarative-element/directives/assign.directive.d.ts +8 -11
  13. package/dist/declarative-element/directives/assign.directive.js +6 -13
  14. package/dist/declarative-element/directives/async-prop.d.ts +19 -4
  15. package/dist/declarative-element/directives/async-prop.js +15 -4
  16. package/dist/declarative-element/directives/create-attribute-directive.d.ts +19 -4
  17. package/dist/declarative-element/directives/create-attribute-directive.js +18 -8
  18. package/dist/declarative-element/directives/directive-helpers.d.ts +19 -4
  19. package/dist/declarative-element/directives/directive-helpers.js +14 -2
  20. package/dist/declarative-element/directives/is-resolved.directive.d.ts +107 -1
  21. package/dist/declarative-element/directives/is-resolved.directive.js +107 -1
  22. package/dist/declarative-element/directives/listen.directive.d.ts +84 -10
  23. package/dist/declarative-element/directives/listen.directive.js +5 -15
  24. package/dist/declarative-element/directives/on-dom-created.directive.d.ts +37 -4
  25. package/dist/declarative-element/directives/on-dom-created.directive.js +32 -12
  26. package/dist/declarative-element/directives/on-dom-rendered.directive.d.ts +33 -3
  27. package/dist/declarative-element/directives/on-dom-rendered.directive.js +29 -6
  28. package/dist/declarative-element/directives/on-resize.directive.d.ts +37 -4
  29. package/dist/declarative-element/directives/on-resize.directive.js +37 -24
  30. package/dist/declarative-element/directives/render-async.directive.d.ts +44 -4
  31. package/dist/declarative-element/directives/render-async.directive.js +13 -3
  32. package/dist/declarative-element/directives/render-if.directive.d.ts +31 -0
  33. package/dist/declarative-element/directives/render-if.directive.js +32 -1
  34. package/dist/declarative-element/directives/test-id.directive.d.ts +48 -4
  35. package/dist/declarative-element/directives/test-id.directive.js +47 -2
  36. package/dist/declarative-element/has-declarative-element-parent.js +1 -1
  37. package/dist/declarative-element/is-declarative-element-definition.d.ts +15 -1
  38. package/dist/declarative-element/is-declarative-element-definition.js +21 -18
  39. package/dist/declarative-element/is-declarative-element.d.ts +5 -1
  40. package/dist/declarative-element/is-declarative-element.js +7 -3
  41. package/dist/declarative-element/properties/assign-inputs.js +1 -1
  42. package/dist/declarative-element/properties/css-properties.d.ts +11 -1
  43. package/dist/declarative-element/properties/css-properties.js +5 -0
  44. package/dist/declarative-element/properties/css-vars.d.ts +14 -4
  45. package/dist/declarative-element/properties/element-events.d.ts +61 -7
  46. package/dist/declarative-element/properties/element-events.js +40 -5
  47. package/dist/declarative-element/properties/element-properties.d.ts +15 -6
  48. package/dist/declarative-element/properties/element-properties.js +1 -21
  49. package/dist/declarative-element/properties/element-vir-state-setup.d.ts +43 -3
  50. package/dist/declarative-element/properties/element-vir-state-setup.js +17 -3
  51. package/dist/declarative-element/properties/host-classes.d.ts +25 -12
  52. package/dist/declarative-element/properties/host-classes.js +5 -0
  53. package/dist/declarative-element/properties/per-instance.d.ts +23 -2
  54. package/dist/declarative-element/properties/per-instance.js +24 -3
  55. package/dist/declarative-element/properties/property-proxy.d.ts +19 -4
  56. package/dist/declarative-element/properties/property-proxy.js +15 -4
  57. package/dist/declarative-element/properties/styles.d.ts +33 -8
  58. package/dist/declarative-element/properties/styles.js +12 -2
  59. package/dist/declarative-element/properties/tag-name.d.ts +5 -0
  60. package/dist/declarative-element/render-callback.d.ts +38 -11
  61. package/dist/declarative-element/render-callback.js +6 -0
  62. package/dist/declarative-element/slot-names.d.ts +10 -2
  63. package/dist/declarative-element/slot-names.js +5 -1
  64. package/dist/declarative-element/wrap-define-element.d.ts +38 -11
  65. package/dist/declarative-element/wrap-define-element.js +17 -2
  66. package/dist/index.d.ts +40 -40
  67. package/dist/index.js +40 -39
  68. package/dist/lit-exports/all-lit-exports.d.ts +2 -2
  69. package/dist/lit-exports/all-lit-exports.js +2 -2
  70. package/dist/lit-exports/lit-repeat-fix.d.ts +60 -4
  71. package/dist/lit-exports/lit-repeat-fix.js +35 -1
  72. package/dist/readme-examples/my-app.element.d.ts +1 -0
  73. package/dist/readme-examples/my-app.element.js +11 -0
  74. package/dist/readme-examples/my-custom-action.event.d.ts +1 -0
  75. package/dist/readme-examples/my-custom-action.event.js +2 -0
  76. package/dist/readme-examples/my-custom-define.d.ts +4 -0
  77. package/dist/readme-examples/my-custom-define.js +19 -0
  78. package/dist/readme-examples/my-simple.element.d.ts +1 -0
  79. package/dist/readme-examples/my-simple.element.js +9 -0
  80. package/dist/readme-examples/my-with-assignment.element.d.ts +1 -0
  81. package/dist/readme-examples/my-with-assignment.element.js +14 -0
  82. package/dist/readme-examples/my-with-async-prop.element.d.ts +9 -0
  83. package/dist/readme-examples/my-with-async-prop.element.js +46 -0
  84. package/dist/readme-examples/my-with-cleanup-callback.element.d.ts +3 -0
  85. package/dist/readme-examples/my-with-cleanup-callback.element.js +23 -0
  86. package/dist/readme-examples/my-with-css-vars.element.d.ts +1 -0
  87. package/dist/readme-examples/my-with-css-vars.element.js +24 -0
  88. package/dist/readme-examples/my-with-custom-events.element.d.ts +1 -0
  89. package/dist/readme-examples/my-with-custom-events.element.js +21 -0
  90. package/dist/readme-examples/my-with-event-listening.element.d.ts +3 -0
  91. package/dist/readme-examples/my-with-event-listening.element.js +22 -0
  92. package/dist/readme-examples/my-with-events.element.d.ts +4 -0
  93. package/dist/readme-examples/my-with-events.element.js +19 -0
  94. package/dist/readme-examples/my-with-host-class-definition.element.d.ts +3 -0
  95. package/dist/readme-examples/my-with-host-class-definition.element.js +39 -0
  96. package/dist/readme-examples/my-with-host-class-usage.element.d.ts +1 -0
  97. package/dist/readme-examples/my-with-host-class-usage.element.js +12 -0
  98. package/dist/readme-examples/my-with-inputs.element.d.ts +4 -0
  99. package/dist/readme-examples/my-with-inputs.element.js +9 -0
  100. package/dist/readme-examples/my-with-on-dom-created.element.d.ts +1 -0
  101. package/dist/readme-examples/my-with-on-dom-created.element.js +16 -0
  102. package/dist/readme-examples/my-with-on-resize.element.d.ts +1 -0
  103. package/dist/readme-examples/my-with-on-resize.element.js +17 -0
  104. package/dist/readme-examples/my-with-render-if.element.d.ts +3 -0
  105. package/dist/readme-examples/my-with-render-if.element.js +11 -0
  106. package/dist/readme-examples/my-with-styles-and-interpolated-selector.element.d.ts +1 -0
  107. package/dist/readme-examples/my-with-styles-and-interpolated-selector.element.js +15 -0
  108. package/dist/readme-examples/my-with-styles.element.d.ts +1 -0
  109. package/dist/readme-examples/my-with-styles.element.js +21 -0
  110. package/dist/readme-examples/my-with-update-state.element.d.ts +8 -0
  111. package/dist/readme-examples/my-with-update-state.element.js +23 -0
  112. package/dist/readme-examples/require-declarative-element.d.ts +1 -0
  113. package/dist/readme-examples/require-declarative-element.js +2 -0
  114. package/dist/require-declarative-element.d.ts +12 -0
  115. package/dist/require-declarative-element.js +12 -0
  116. package/dist/template-transforms/minimal-element-definition.d.ts +30 -2
  117. package/dist/template-transforms/minimal-element-definition.js +14 -3
  118. package/dist/template-transforms/nested-mapped-templates.d.ts +1 -1
  119. package/dist/template-transforms/nested-mapped-templates.js +4 -3
  120. package/dist/template-transforms/template-transform-type.d.ts +1 -1
  121. package/dist/template-transforms/transform-template.d.ts +1 -1
  122. package/dist/template-transforms/transform-template.js +17 -21
  123. package/dist/template-transforms/vir-css/css-transform.d.ts +3 -3
  124. package/dist/template-transforms/vir-css/css-transform.js +3 -2
  125. package/dist/template-transforms/vir-css/vir-css.d.ts +11 -2
  126. package/dist/template-transforms/vir-css/vir-css.js +11 -2
  127. package/dist/template-transforms/vir-html/html-interpolation.d.ts +9 -5
  128. package/dist/template-transforms/vir-html/html-transform.d.ts +3 -3
  129. package/dist/template-transforms/vir-html/html-transform.js +14 -12
  130. package/dist/template-transforms/vir-html/vir-html.d.ts +4 -2
  131. package/dist/template-transforms/vir-html/vir-html.js +4 -2
  132. package/dist/typed-event/typed-event.d.ts +42 -6
  133. package/dist/typed-event/typed-event.js +31 -28
  134. package/dist/util/lit-template.d.ts +6 -1
  135. package/dist/util/lit-template.js +10 -7
  136. package/dist/util/type.d.ts +5 -0
  137. package/package.json +35 -34
@@ -1,34 +1,50 @@
1
- var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
2
- if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
3
- return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
4
- };
1
+ /* eslint-disable @typescript-eslint/no-empty-object-type */
2
+ import { check } from '@augment-vir/assert';
5
3
  import { ensureErrorAndPrependMessage, extractErrorMessage, getObjectTypedKeys, kebabCaseToCamelCase, } from '@augment-vir/common';
6
4
  import { defineCssVars } from 'lit-css-vars';
7
- import { hasProperty, isRunTimeType } from 'run-time-assertions';
8
- import { css } from '../template-transforms/vir-css/vir-css';
9
- import { DeclarativeElement, } from './declarative-element';
10
- import { defaultDeclarativeElementDefinitionOptions, } from './definition-options';
11
- import { hasDeclarativeElementParent } from './has-declarative-element-parent';
12
- import { assignInputs } from './properties/assign-inputs';
13
- import { assertValidCssProperties } from './properties/css-properties';
14
- import { createEventDescriptorMap, } from './properties/element-events';
15
- import { createHostClassNamesMap } from './properties/host-classes';
16
- import { bindReactiveProperty, createElementPropertyProxy } from './properties/property-proxy';
17
- import { applyHostClasses, hostClassNamesToStylesInput } from './properties/styles';
18
- import { createRenderParams } from './render-callback';
19
- import { createSlotNamesMap } from './slot-names';
5
+ import { css } from '../template-transforms/vir-css/vir-css.js';
6
+ import { DeclarativeElement, } from './declarative-element.js';
7
+ import { defaultDeclarativeElementDefinitionOptions, } from './definition-options.js';
8
+ import { hasDeclarativeElementParent } from './has-declarative-element-parent.js';
9
+ import { assignInputs } from './properties/assign-inputs.js';
10
+ import { assertValidCssProperties } from './properties/css-properties.js';
11
+ import { createEventDescriptorMap, } from './properties/element-events.js';
12
+ import { createHostClassNamesMap } from './properties/host-classes.js';
13
+ import { bindReactiveProperty, createElementPropertyProxy } from './properties/property-proxy.js';
14
+ import { applyHostClasses, createStylesCallbackInput } from './properties/styles.js';
15
+ import { createRenderParams } from './render-callback.js';
16
+ import { createSlotNamesMap } from './slot-names.js';
17
+ /**
18
+ * Defines an element without any inputs.
19
+ *
20
+ * @category Element Definition
21
+ * @example
22
+ *
23
+ * ```ts
24
+ * import {defineElementNoInputs, html} from 'element-vir';
25
+ *
26
+ * const MyElement = defineElementNoInputs({
27
+ * tagName: 'my-element',
28
+ * render() {
29
+ * return html`
30
+ * <p>hi</p>
31
+ * `;
32
+ * },
33
+ * });
34
+ * ```
35
+ */
20
36
  export function defineElementNoInputs(initInput) {
21
- var _a;
22
37
  /** This as cast is safe only because of the following run-time type check. */
23
38
  const init = initInput;
24
- if (!isRunTimeType(init, 'object')) {
25
- throw new Error('Cannot define element with non-object init: ${init}');
39
+ if (!check.isObject(init)) {
40
+ throw new TypeError('Cannot define element with non-object init: ${init}');
26
41
  }
27
- if (!isRunTimeType(init.tagName, 'string')) {
28
- throw new Error('Missing valid tagName (expected a string).');
42
+ if (!check.isString(init.tagName)) {
43
+ throw new TypeError('Missing valid tagName (expected a string).');
29
44
  }
30
- if (!init.renderCallback || typeof init.renderCallback === 'string') {
31
- throw new Error(`Failed to define element '${init.tagName}': renderCallback is not a function`);
45
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
46
+ if (!init.render || typeof init.render === 'string') {
47
+ throw new Error(`Failed to define element '${init.tagName}': render is not a function`);
32
48
  }
33
49
  const elementOptions = {
34
50
  ...defaultDeclarativeElementDefinitionOptions,
@@ -51,9 +67,9 @@ export function defineElementNoInputs(initInput) {
51
67
  const cssVars = (init.cssVars ? defineCssVars(init.cssVars) : {});
52
68
  const slotNamesMap = createSlotNamesMap(init.slotNames);
53
69
  const calculatedStyles = typeof init.styles === 'function'
54
- ? init.styles(hostClassNamesToStylesInput({ hostClassNames, cssVars }))
70
+ ? init.styles(createStylesCallbackInput({ hostClassNames, cssVars }))
55
71
  : init.styles || css ``;
56
- const typedRenderCallback = init.renderCallback;
72
+ const typedRenderCallback = init.render;
57
73
  function typedAssignCallback(...[inputs]) {
58
74
  const wrappedDefinition = {
59
75
  _elementVirIsMinimalDefinitionWithInputs: true,
@@ -62,240 +78,127 @@ export function defineElementNoInputs(initInput) {
62
78
  };
63
79
  return wrappedDefinition;
64
80
  }
65
- const anonymousClass = (_a = class extends DeclarativeElement {
66
- createRenderParams() {
67
- return createRenderParams({ element: this, eventsMap, cssVars, slotNamesMap });
68
- }
69
- get instanceType() {
70
- throw new Error(`"instanceType" was called on ${init.tagName} as a value but it is only for types.`);
71
- }
72
- static get inputsType() {
73
- throw new Error(`"inputsType" was called on ${init.tagName} as a value but it is only for types.`);
74
- }
75
- static get stateType() {
76
- throw new Error(`"stateType" was called on ${init.tagName} as a value but it is only for types.`);
77
- }
78
- render() {
79
- this._internalRenderCount++;
80
- try {
81
- if (
82
- // This ignores elements at the root of a page, as they can't receive inputs from
83
- // other elements (cause they have no custom element ancestors).
84
- hasDeclarativeElementParent(this) &&
85
- !this._haveInputsBeenSet &&
86
- !elementOptions.ignoreUnsetInputs) {
87
- console.warn(this, `${init.tagName} got rendered before its input object was set. This was most likely caused by forgetting to use '.assign()' on its opening tag. If no inputs are intended, use '${defineElementNoInputs.name}' to define ${init.tagName}.`);
88
- }
89
- this._hasRendered = true;
90
- const renderParams = this.createRenderParams();
91
- if (!this._initCalled && init.initCallback) {
92
- this._initCalled = true;
93
- if (init.initCallback(renderParams) instanceof Promise) {
94
- throw new Error('initCallback cannot be asynchronous');
95
- }
96
- }
97
- const renderResult = typedRenderCallback(renderParams);
98
- if (renderResult instanceof Promise) {
99
- throw new Error('renderCallback cannot be asynchronous');
100
- }
101
- applyHostClasses({
102
- host: renderParams.host,
103
- hostClassesInit: init.hostClasses,
104
- hostClassNames,
105
- state: renderParams.state,
106
- inputs: renderParams.inputs,
107
- });
108
- this._lastRenderedProps = {
109
- inputs: { ...renderParams.inputs },
110
- state: { ...renderParams.state },
111
- };
112
- return renderResult;
113
- }
114
- catch (caught) {
115
- const error = ensureErrorAndPrependMessage(caught, `Failed to render ${init.tagName}`);
116
- console.error(error);
117
- this._lastRenderError = error;
118
- return extractErrorMessage(error);
81
+ const anonymousClass = class extends DeclarativeElement {
82
+ static elementOptions = elementOptions;
83
+ static tagName = init.tagName;
84
+ static styles = calculatedStyles;
85
+ _lastRenderError = undefined;
86
+ _internalRenderCount = 0;
87
+ createRenderParams() {
88
+ return createRenderParams({ element: this, eventsMap, cssVars, slotNamesMap });
89
+ }
90
+ static assign = typedAssignCallback;
91
+ static events = eventsMap;
92
+ static render = typedRenderCallback;
93
+ static hostClasses = hostClassNames;
94
+ static cssVars = cssVars;
95
+ static init = init;
96
+ static slotNames = slotNamesMap;
97
+ static stateInitStatic = init.stateInitStatic;
98
+ get instanceType() {
99
+ throw new Error(`"instanceType" was called on ${init.tagName} as a value but it is only for types.`);
100
+ }
101
+ static get inputsType() {
102
+ throw new Error(`"inputsType" was called on ${init.tagName} as a value but it is only for types.`);
103
+ }
104
+ static get stateType() {
105
+ throw new Error(`"stateType" was called on ${init.tagName} as a value but it is only for types.`);
106
+ }
107
+ _initCalled = false;
108
+ _hasRendered = false;
109
+ _lastRenderedProps = undefined;
110
+ _haveInputsBeenSet = false;
111
+ render() {
112
+ this._internalRenderCount++;
113
+ try {
114
+ if (
115
+ // This ignores elements at the root of a page, as they can't receive inputs from
116
+ // other elements (cause they have no custom element ancestors).
117
+ hasDeclarativeElementParent(this) &&
118
+ !this._haveInputsBeenSet &&
119
+ !elementOptions.ignoreUnsetInputs) {
120
+ console.warn(this, `${init.tagName} got rendered before its input object was set. This was most likely caused by forgetting to use '.assign()' on its opening tag. If no inputs are intended, use '${defineElementNoInputs.name}' to define ${init.tagName}.`);
119
121
  }
120
- }
121
- connectedCallback() {
122
- super.connectedCallback();
123
- if (this._hasRendered && !this._initCalled && init.initCallback) {
122
+ this._hasRendered = true;
123
+ const renderParams = this.createRenderParams();
124
+ if (!this._initCalled && init.init) {
124
125
  this._initCalled = true;
125
- const renderParams = this.createRenderParams();
126
- if (init.initCallback(renderParams) instanceof Promise) {
127
- throw new Error(`initCallback in '${init.tagName}' cannot be asynchronous`);
126
+ if (init.init(renderParams) instanceof Promise) {
127
+ throw new TypeError('init cannot be asynchronous');
128
128
  }
129
129
  }
130
- }
131
- destroy() {
132
- Object.values(this.instanceState).forEach((stateValue) => {
133
- if (hasProperty(stateValue, 'destroy') &&
134
- isRunTimeType(stateValue.destroy, 'function')) {
135
- stateValue.destroy();
136
- }
130
+ const renderResult = typedRenderCallback(renderParams);
131
+ if (renderResult instanceof Promise) {
132
+ throw new TypeError('render cannot be asynchronous');
133
+ }
134
+ applyHostClasses({
135
+ host: renderParams.host,
136
+ hostClassesInit: init.hostClasses,
137
+ hostClassNames,
138
+ state: renderParams.state,
139
+ inputs: renderParams.inputs,
137
140
  });
141
+ this._lastRenderedProps = {
142
+ inputs: { ...renderParams.inputs },
143
+ state: { ...renderParams.state },
144
+ };
145
+ return renderResult;
138
146
  }
139
- disconnectedCallback() {
140
- super.disconnectedCallback();
141
- if (init.cleanupCallback) {
142
- const renderParams = this.createRenderParams();
143
- if (init.cleanupCallback(renderParams) instanceof Promise) {
144
- throw new Error(`cleanupCallback in '${init.tagName}' cannot be asynchronous`);
145
- }
146
- }
147
- this.destroy();
148
- this._initCalled = false;
147
+ catch (caught) {
148
+ const error = ensureErrorAndPrependMessage(caught, `Failed to render ${init.tagName}`);
149
+ console.error(error);
150
+ this._lastRenderError = error;
151
+ return extractErrorMessage(error);
149
152
  }
150
- assignInputs(inputs) {
151
- assignInputs(this, inputs);
153
+ }
154
+ connectedCallback() {
155
+ super.connectedCallback();
156
+ if (this._hasRendered && !this._initCalled && init.init) {
157
+ this._initCalled = true;
158
+ const renderParams = this.createRenderParams();
159
+ if (init.init(renderParams) instanceof Promise) {
160
+ throw new TypeError(`init in '${init.tagName}' cannot be asynchronous`);
161
+ }
152
162
  }
153
- constructor() {
154
- super();
155
- Object.defineProperty(this, "_lastRenderError", {
156
- enumerable: true,
157
- configurable: true,
158
- writable: true,
159
- value: undefined
160
- });
161
- Object.defineProperty(this, "_internalRenderCount", {
162
- enumerable: true,
163
- configurable: true,
164
- writable: true,
165
- value: 0
166
- });
167
- Object.defineProperty(this, "_initCalled", {
168
- enumerable: true,
169
- configurable: true,
170
- writable: true,
171
- value: false
172
- });
173
- Object.defineProperty(this, "_hasRendered", {
174
- enumerable: true,
175
- configurable: true,
176
- writable: true,
177
- value: false
178
- });
179
- Object.defineProperty(this, "_lastRenderedProps", {
180
- enumerable: true,
181
- configurable: true,
182
- writable: true,
183
- value: undefined
184
- });
185
- Object.defineProperty(this, "_haveInputsBeenSet", {
186
- enumerable: true,
187
- configurable: true,
188
- writable: true,
189
- value: false
190
- });
191
- // this is set below in Object.defineProperties
192
- Object.defineProperty(this, "definition", {
193
- enumerable: true,
194
- configurable: true,
195
- writable: true,
196
- value: {}
197
- });
198
- Object.defineProperty(this, "observablePropertyListenerMap", {
199
- enumerable: true,
200
- configurable: true,
201
- writable: true,
202
- value: {}
203
- });
204
- Object.defineProperty(this, "instanceInputs", {
205
- enumerable: true,
206
- configurable: true,
207
- writable: true,
208
- value: createElementPropertyProxy(this, false)
209
- });
210
- Object.defineProperty(this, "instanceState", {
211
- enumerable: true,
212
- configurable: true,
213
- writable: true,
214
- value: createElementPropertyProxy(this, !elementOptions.allowPolymorphicState)
215
- });
216
- const stateInitStatic = init.stateInitStatic || {};
217
- getObjectTypedKeys(stateInitStatic).forEach((stateKey) => {
218
- bindReactiveProperty(this, stateKey);
219
- this.instanceState[stateKey] = stateInitStatic[stateKey];
220
- });
221
- this.definition = anonymousClass;
163
+ }
164
+ destroy() {
165
+ Object.values(this.instanceState).forEach((stateValue) => {
166
+ if (check.hasKey(stateValue, 'destroy') && check.isFunction(stateValue.destroy)) {
167
+ stateValue.destroy();
168
+ }
169
+ });
170
+ }
171
+ disconnectedCallback() {
172
+ super.disconnectedCallback();
173
+ if (init.cleanup) {
174
+ const renderParams = this.createRenderParams();
175
+ if (init.cleanup(renderParams) instanceof Promise) {
176
+ throw new TypeError(`cleanup in '${init.tagName}' cannot be asynchronous`);
177
+ }
222
178
  }
223
- },
224
- __setFunctionName(_a, "anonymousClass"),
225
- Object.defineProperty(_a, "elementOptions", {
226
- enumerable: true,
227
- configurable: true,
228
- writable: true,
229
- value: elementOptions
230
- }),
231
- Object.defineProperty(_a, "tagName", {
232
- enumerable: true,
233
- configurable: true,
234
- writable: true,
235
- value: init.tagName
236
- }),
237
- Object.defineProperty(_a, "styles", {
238
- enumerable: true,
239
- configurable: true,
240
- writable: true,
241
- value: calculatedStyles
242
- }),
243
- Object.defineProperty(_a, "assign", {
244
- enumerable: true,
245
- configurable: true,
246
- writable: true,
247
- value: typedAssignCallback
248
- }),
249
- // this gets set below in Object.defineProperties
250
- Object.defineProperty(_a, "isStrictInstance", {
251
- enumerable: true,
252
- configurable: true,
253
- writable: true,
254
- value: () => false
255
- }),
256
- Object.defineProperty(_a, "events", {
257
- enumerable: true,
258
- configurable: true,
259
- writable: true,
260
- value: eventsMap
261
- }),
262
- Object.defineProperty(_a, "renderCallback", {
263
- enumerable: true,
264
- configurable: true,
265
- writable: true,
266
- value: typedRenderCallback
267
- }),
268
- Object.defineProperty(_a, "hostClasses", {
269
- enumerable: true,
270
- configurable: true,
271
- writable: true,
272
- value: hostClassNames
273
- }),
274
- Object.defineProperty(_a, "cssVars", {
275
- enumerable: true,
276
- configurable: true,
277
- writable: true,
278
- value: cssVars
279
- }),
280
- Object.defineProperty(_a, "init", {
281
- enumerable: true,
282
- configurable: true,
283
- writable: true,
284
- value: init
285
- }),
286
- Object.defineProperty(_a, "slotNames", {
287
- enumerable: true,
288
- configurable: true,
289
- writable: true,
290
- value: slotNamesMap
291
- }),
292
- Object.defineProperty(_a, "stateInitStatic", {
293
- enumerable: true,
294
- configurable: true,
295
- writable: true,
296
- value: init.stateInitStatic
297
- }),
298
- _a);
179
+ this.destroy();
180
+ this._initCalled = false;
181
+ }
182
+ // this is set below in Object.defineProperties
183
+ definition = {};
184
+ assignInputs(inputs) {
185
+ assignInputs(this, inputs);
186
+ }
187
+ observablePropertyListenerMap = {};
188
+ instanceInputs = createElementPropertyProxy(this, false);
189
+ instanceState = createElementPropertyProxy(this, !elementOptions.allowPolymorphicState);
190
+ constructor() {
191
+ super();
192
+ const stateInitStatic =
193
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
194
+ init.stateInitStatic || {};
195
+ getObjectTypedKeys(stateInitStatic).forEach((stateKey) => {
196
+ bindReactiveProperty(this, stateKey);
197
+ this.instanceState[stateKey] = stateInitStatic[stateKey];
198
+ });
199
+ this.definition = anonymousClass;
200
+ }
201
+ };
299
202
  Object.defineProperties(anonymousClass, {
300
203
  name: {
301
204
  value: kebabCaseToCamelCase(init.tagName, {
@@ -303,12 +206,6 @@ export function defineElementNoInputs(initInput) {
303
206
  }),
304
207
  writable: true,
305
208
  },
306
- isStrictInstance: {
307
- value: (element) => {
308
- return element instanceof anonymousClass;
309
- },
310
- writable: false,
311
- },
312
209
  });
313
210
  if (window.customElements.get(init.tagName)) {
314
211
  console.warn(`Tried to define custom element '${init.tagName}' but it is already defined.`);
@@ -1,8 +1,36 @@
1
- import { CustomElementTagName } from './custom-tag-name';
2
- import { DeclarativeElementDefinition } from './declarative-element';
3
- import { VerifiedElementNoInputsInit } from './define-element-no-inputs';
4
- import { BaseCssPropertyName } from './properties/css-properties';
5
- import { EventsInitMap } from './properties/element-events';
6
- import { PropertyInitMapBase } from './properties/element-properties';
1
+ import { CustomElementTagName } from './custom-tag-name.js';
2
+ import { DeclarativeElementDefinition } from './declarative-element.js';
3
+ import { VerifiedElementNoInputsInit } from './define-element-no-inputs.js';
4
+ import { BaseCssPropertyName } from './properties/css-properties.js';
5
+ import { EventsInitMap } from './properties/element-events.js';
6
+ import { PropertyInitMapBase } from './properties/element-properties.js';
7
+ /**
8
+ * Verifies that the given {@link DeclarativeElementInit} for an element definition with inputs does
9
+ * not have any state or input properties that clash with built-in HTML element properties, or state
10
+ * / input properties that clash with each other.
11
+ *
12
+ * @category Internal
13
+ */
7
14
  export type VerifiedElementInit<TagName extends CustomElementTagName, Inputs extends PropertyInitMapBase, StateInit extends PropertyInitMapBase, EventsInit extends EventsInitMap, HostClassKeys extends BaseCssPropertyName<TagName>, CssVarKeys extends BaseCssPropertyName<TagName>, SlotNames extends ReadonlyArray<string>> = Extract<keyof StateInit, keyof Inputs> extends never ? Extract<keyof Inputs, keyof HTMLElement> extends never ? VerifiedElementNoInputsInit<TagName, Inputs, StateInit, EventsInit, HostClassKeys, CssVarKeys, SlotNames> : 'ERROR: Cannot define an element input property that clashes with native HTMLElement properties.' : "ERROR: Cannot define an element state property that clashes with the element's input properties.";
8
- export declare function defineElement<Inputs extends PropertyInitMapBase = {}>(): <const TagName extends `${string}-${string}`, StateInit extends PropertyInitMapBase = {}, EventsInit extends EventsInitMap = {}, const HostClassKeys extends `${TagName}-${string}` = `${TagName}-`, const CssVarKeys extends `${TagName}-${string}` = `${TagName}-`, const SlotNames extends readonly string[] = readonly []>(initInput: VerifiedElementInit<TagName, Inputs, StateInit, EventsInit, HostClassKeys, CssVarKeys, SlotNames>) => DeclarativeElementDefinition<TagName, Inputs, StateInit, EventsInit, HostClassKeys, CssVarKeys, SlotNames>;
15
+ /**
16
+ * Defines an element with inputs. If the element actually has no inputs, use
17
+ * {@link defineElementNoInputs} instead. Note that this function must be called twice, due to
18
+ * TypeScript type inference limitations.
19
+ *
20
+ * @category Element Definition
21
+ * @example
22
+ *
23
+ * ```ts
24
+ * import {defineElement, html} from 'element-vir';
25
+ *
26
+ * const MyElement = defineElement<{username: string}>()({
27
+ * tagName: 'my-element',
28
+ * render({inputs}) {
29
+ * return html`
30
+ * <p>hi: ${inputs.username}</p>
31
+ * `;
32
+ * },
33
+ * });
34
+ * ```
35
+ */
36
+ export declare function defineElement<Inputs extends PropertyInitMapBase = {}>(): <const TagName extends CustomElementTagName, StateInit extends PropertyInitMapBase = {}, EventsInit extends EventsInitMap = {}, const HostClassKeys extends BaseCssPropertyName<TagName> = `${TagName}-`, const CssVarKeys extends BaseCssPropertyName<TagName> = `${TagName}-`, const SlotNames extends ReadonlyArray<string> = readonly []>(initInput: VerifiedElementInit<TagName, Inputs, StateInit, EventsInit, HostClassKeys, CssVarKeys, SlotNames>) => DeclarativeElementDefinition<TagName, Inputs, StateInit, EventsInit, HostClassKeys, CssVarKeys, SlotNames>;
@@ -1,10 +1,32 @@
1
- import { isRunTimeType } from 'run-time-assertions';
2
- import { defineElementNoInputs } from './define-element-no-inputs';
1
+ /* eslint-disable @typescript-eslint/no-empty-object-type */
2
+ import { check } from '@augment-vir/assert';
3
+ import { defineElementNoInputs } from './define-element-no-inputs.js';
4
+ /**
5
+ * Defines an element with inputs. If the element actually has no inputs, use
6
+ * {@link defineElementNoInputs} instead. Note that this function must be called twice, due to
7
+ * TypeScript type inference limitations.
8
+ *
9
+ * @category Element Definition
10
+ * @example
11
+ *
12
+ * ```ts
13
+ * import {defineElement, html} from 'element-vir';
14
+ *
15
+ * const MyElement = defineElement<{username: string}>()({
16
+ * tagName: 'my-element',
17
+ * render({inputs}) {
18
+ * return html`
19
+ * <p>hi: ${inputs.username}</p>
20
+ * `;
21
+ * },
22
+ * });
23
+ * ```
24
+ */
3
25
  export function defineElement() {
4
26
  return (initInput) => {
5
27
  const init = initInput;
6
- if (!isRunTimeType(init, 'object')) {
7
- throw new Error('Cannot define element with non-object init: ${init}');
28
+ if (!check.isObject(init)) {
29
+ throw new TypeError('Cannot define element with non-object init: ${init}');
8
30
  }
9
31
  return defineElementNoInputs({
10
32
  ...init,
@@ -1,3 +1,8 @@
1
+ /**
2
+ * Extra options for defining elements. These should be used very rarely.
3
+ *
4
+ * @category Internal
5
+ */
1
6
  export type DeclarativeElementDefinitionOptions = {
2
7
  /** For internal use only. */
3
8
  ignoreUnsetInputs: boolean;
@@ -7,4 +12,9 @@ export type DeclarativeElementDefinitionOptions = {
7
12
  */
8
13
  allowPolymorphicState: boolean;
9
14
  };
15
+ /**
16
+ * Default values for {@link DeclarativeElementDefinitionOptions}.
17
+ *
18
+ * @internal
19
+ */
10
20
  export declare const defaultDeclarativeElementDefinitionOptions: DeclarativeElementDefinitionOptions;
@@ -1,3 +1,8 @@
1
+ /**
2
+ * Default values for {@link DeclarativeElementDefinitionOptions}.
3
+ *
4
+ * @internal
5
+ */
1
6
  export const defaultDeclarativeElementDefinitionOptions = {
2
7
  ignoreUnsetInputs: true,
3
8
  allowPolymorphicState: false,
@@ -1,5 +1,6 @@
1
- import { DirectiveResult } from '../../lit-exports/all-lit-exports';
2
- import { PropertyInitMapBase } from '../properties/element-properties';
1
+ import type { EmptyObject } from 'type-fest';
2
+ import { DirectiveResult } from '../../lit-exports/all-lit-exports.js';
3
+ import { PropertyInitMapBase } from '../properties/element-properties.js';
3
4
  export type ElementDefinitionWithInputsType<InputsType extends PropertyInitMapBase = PropertyInitMapBase> = {
4
5
  inputsType: InputsType;
5
6
  };
@@ -8,20 +9,16 @@ export type ElementDefinitionWithInputsType<InputsType extends PropertyInitMapBa
8
9
  *
9
10
  * @deprecated Instead of using this directive, assign inputs directly on the element's
10
11
  * interpolation opening tag interpolation.
11
- * @example
12
- * html`<${MyElement} ${assign(MyElement, {value: 1})}>...`
13
- * should be
14
- * html`<${MyElement.assign({value: 1})}>...`
12
+ * @example Html`<${MyElement} ${assign(MyElement, {value: 1})}>...` should be
13
+ * html`<${MyElement.assign({value: 1})}>...`
15
14
  */
16
- export declare function assign<const SpecificDeclarativeElement extends ElementDefinitionWithInputsType>(declarativeElement: SpecificDeclarativeElement, inputsObject: {} extends Required<SpecificDeclarativeElement['inputsType']> ? never : SpecificDeclarativeElement['inputsType']): DirectiveResult;
15
+ export declare function assign<const SpecificDeclarativeElement extends ElementDefinitionWithInputsType>(declarativeElement: SpecificDeclarativeElement, inputsObject: EmptyObject extends Required<SpecificDeclarativeElement['inputsType']> ? never : SpecificDeclarativeElement['inputsType']): DirectiveResult;
17
16
  /**
18
17
  * Assign an object matching an element's inputs to its inputs.
19
18
  *
20
19
  * @deprecated Instead of using this directive, assign inputs directly on the element's
21
20
  * interpolation opening tag interpolation.
22
- * @example
23
- * html`<${MyElement} ${assign(MyElement, {value: 1})}>...`
24
- * should be
25
- * html`<${MyElement.assign({value: 1})}>...`
21
+ * @example Html`<${MyElement} ${assign(MyElement, {value: 1})}>...` should be
22
+ * html`<${MyElement.assign({value: 1})}>...`
26
23
  */
27
24
  export declare function assign<const SpecificDeclarativeElement extends ElementDefinitionWithInputsType, const SpecificInput extends SpecificDeclarativeElement['inputsType']>(inputsObject: SpecificInput extends typeof HTMLElement ? never : SpecificInput): DirectiveResult;
@@ -1,15 +1,13 @@
1
- import { directive, Directive, noChange, } from '../../lit-exports/all-lit-exports';
2
- import { assignInputs } from '../properties/assign-inputs';
3
- import { extractElement } from './directive-helpers';
1
+ import { directive, Directive, noChange, } from '../../lit-exports/all-lit-exports.js';
2
+ import { assignInputs } from '../properties/assign-inputs.js';
3
+ import { extractElement } from './directive-helpers.js';
4
4
  /**
5
5
  * Assign an object matching an element's inputs to its inputs.
6
6
  *
7
7
  * @deprecated Instead of using this directive, assign inputs directly on the element's
8
8
  * interpolation opening tag interpolation.
9
- * @example
10
- * html`<${MyElement} ${assign(MyElement, {value: 1})}>...`
11
- * should be
12
- * html`<${MyElement.assign({value: 1})}>...`
9
+ * @example Html`<${MyElement} ${assign(MyElement, {value: 1})}>...` should be
10
+ * html`<${MyElement.assign({value: 1})}>...`
13
11
  */
14
12
  export function assign(declarativeElementOrInputs, inputsObject) {
15
13
  /**
@@ -24,14 +22,9 @@ export function assign(declarativeElementOrInputs, inputsObject) {
24
22
  }
25
23
  }
26
24
  const assignDirective = directive(class extends Directive {
25
+ element;
27
26
  constructor(partInfo) {
28
27
  super(partInfo);
29
- Object.defineProperty(this, "element", {
30
- enumerable: true,
31
- configurable: true,
32
- writable: true,
33
- value: void 0
34
- });
35
28
  this.element = extractElement(partInfo, 'assign');
36
29
  }
37
30
  render(elementDefinition, inputsObject) {