element-vir 6.1.5 → 6.2.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.
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # element-vir
2
2
 
3
+ A wrapper for [lit-element](http://lit.dev) that adds type-safe custom element usage and I/O with declarative custom element definition.
4
+
3
5
  Heroic. Reactive. Declarative. Type safe. Web components without compromise.
4
6
 
5
7
  No need for an extra build step,<br>
@@ -11,8 +13,6 @@ _**It's just TypeScript.**_
11
13
 
12
14
  Uses the power of _native_ JavaScript custom web elements, _native_ JavaScript template literals, _native_ JavaScript functions<sup>\*</sup>, _native_ HTML, and [lit-element](http://lit.dev).
13
15
 
14
- In reality this is basically a [lit-element](http://lit.dev) wrapper that adds type-safe element tag usage and I/O with declarative style component definition.
15
-
16
16
  [Works in every major web browser except Internet Explorer.](https://caniuse.com/mdn-api_window_customelements)
17
17
 
18
18
  <sub>\*okay I hope it's obvious that functions are native</sub>
@@ -29,13 +29,13 @@ Make sure to install this as a normal dependency (not just a dev dependency) bec
29
29
 
30
30
  # Usage
31
31
 
32
- Most usage of this package is done through the [`defineElementNoInputs` function](https://github.com/electrovir/element-vir/blob/main/src/declarative-element/define-declarative-element.ts#L25-L30). See the [`DeclarativeElementInit` type](https://github.com/electrovir/element-vir/blob/main/src/declarative-element/declarative-element-init.ts#L7-L20) for that function's inputs. These inputs are also described below with examples.
32
+ Most usage of this package is done through the `defineElement` or `defineElementNoInputs` functions. See the `DeclarativeElementInit` type for that function's inputs. These inputs are also described below with examples.
33
33
 
34
34
  All of [`lit`](https://lit.dev)'s syntax and functionality is also available for use if you wish.
35
35
 
36
36
  ## Simple element definition
37
37
 
38
- Use `defineElementNoInputs` to define your element if you're not setting inputs (or just for now as you're getting started). It must be given an object with at least `tagName` and `renderCallback` properties (the types enforce this). Here is a bare-minimum example custom element:
38
+ Use `defineElementNoInputs` to define your element if it's not going to accept any inputs (or just for now as you're getting started). It must be given an object with at least `tagName` and `renderCallback` properties (the types enforce this). Here is a bare-minimum example custom element:
39
39
 
40
40
  <!-- example-link: src/readme-examples/my-simple.element.ts -->
41
41
 
@@ -201,6 +201,40 @@ export const MyAppWithAssignmentElement = defineElementNoInputs({
201
201
  });
202
202
  ```
203
203
 
204
+ ## Other callbacks
205
+
206
+ There are two other callbacks you can define that are sort of similar to lifecycle callbacks. They are much simpler than lifecycle callbacks however.
207
+
208
+ - `initCallback`: called right before the first render, has all state and inputs setup.
209
+ - `cleanupCallback`: called when an element is removed from the DOM. (This is the same as the `disconnectedCallback` in standard HTMLElement classes.)
210
+
211
+ <!-- example-link: src/readme-examples/my-app-with-cleanup-callback.element.ts -->
212
+
213
+ ```TypeScript
214
+ import {defineElementNoInputs, html} from 'element-vir';
215
+
216
+ export const MyAppWithAssignmentCleanupCallbackElement = defineElementNoInputs({
217
+ tagName: 'my-app-with-cleanup-callback',
218
+ stateInit: {
219
+ intervalId: undefined as undefined | number,
220
+ },
221
+ initCallback: ({updateState}) => {
222
+ updateState({
223
+ intervalId: window.setInterval(() => console.log('hi'), 1000),
224
+ });
225
+ },
226
+ renderCallback: () => html`
227
+ <h1>My App</h1>
228
+ `,
229
+ cleanupCallback: ({state, updateState}) => {
230
+ window.clearInterval(state.intervalId);
231
+ updateState({
232
+ intervalId: undefined,
233
+ });
234
+ },
235
+ });
236
+ ```
237
+
204
238
  ## Element events (outputs)
205
239
 
206
240
  Define events with `events` when defining a declarative element. Each event must be initialized with `defineElementEvent` and a type parameter. `defineElementEvent` accepts no inputs as it doesn't make sense for events to have default values.
@@ -29,5 +29,6 @@ export declare type DeclarativeElementInit<InputsGeneric extends PropertyInitMap
29
29
  /** Called as part of the first renderCallback call, before the first renderCallback call. */
30
30
  initCallback?: InitCallback<InputsGeneric, StateInit, EventsInitGeneric, HostClassKeys, CssVarKeys>;
31
31
  renderCallback: RenderCallback<InputsGeneric, StateInit, EventsInitGeneric, HostClassKeys, CssVarKeys>;
32
+ cleanupCallback?: InitCallback<InputsGeneric, StateInit, EventsInitGeneric, HostClassKeys, CssVarKeys>;
32
33
  options?: Partial<DeclarativeElementDefinitionOptions> | undefined;
33
34
  };
@@ -16,6 +16,7 @@ export declare abstract class DeclarativeElement<InputsGeneric extends PropertyI
16
16
  static readonly isStrictInstance: StaticDeclarativeElementProperties<PropertyInitMapBase, PropertyInitMapBase, EventsInitMap, string, string>['isStrictInstance'];
17
17
  static readonly renderCallback: StaticDeclarativeElementProperties<PropertyInitMapBase, PropertyInitMapBase, EventsInitMap, string, string>['renderCallback'];
18
18
  static readonly inputsType: StaticDeclarativeElementProperties<PropertyInitMapBase, PropertyInitMapBase, EventsInitMap, string, string>['inputsType'];
19
+ static readonly stateType: StaticDeclarativeElementProperties<PropertyInitMapBase, PropertyInitMapBase, EventsInitMap, string, string>['stateType'];
19
20
  static readonly events: StaticDeclarativeElementProperties<PropertyInitMapBase, PropertyInitMapBase, EventsInitMap, string, string>['events'];
20
21
  static readonly stateInit: StaticDeclarativeElementProperties<PropertyInitMapBase, PropertyInitMapBase, EventsInitMap, string, string>['stateInit'];
21
22
  static readonly init: StaticDeclarativeElementProperties<PropertyInitMapBase, PropertyInitMapBase, EventsInitMap, string, string>['init'];
@@ -30,14 +31,15 @@ export declare abstract class DeclarativeElement<InputsGeneric extends PropertyI
30
31
  abstract markInputsAsHavingBeenSet(): void;
31
32
  abstract readonly definition: DeclarativeElementDefinition<InputsGeneric, PropertyInitGeneric, EventsInitGeneric, HostClassKeys, CssVarKeys>;
32
33
  }
33
- export interface StaticDeclarativeElementProperties<InputsGeneric extends PropertyInitMapBase, PropertyInitGeneric extends PropertyInitMapBase, EventsInitGeneric extends EventsInitMap, HostClassKeys extends string, CssVarKeys extends string> {
34
+ export interface StaticDeclarativeElementProperties<InputsGeneric extends PropertyInitMapBase, StateInitGeneric extends PropertyInitMapBase, EventsInitGeneric extends EventsInitMap, HostClassKeys extends string, CssVarKeys extends string> {
34
35
  /** Pass through the render callback for direct unit testability */
35
- readonly renderCallback: RenderCallback<InputsGeneric, PropertyInitGeneric, EventsInitGeneric, HostClassKeys, CssVarKeys>;
36
+ readonly renderCallback: RenderCallback<InputsGeneric, StateInitGeneric, EventsInitGeneric, HostClassKeys, CssVarKeys>;
36
37
  events: EventDescriptorMap<EventsInitGeneric>;
37
- stateInit: ElementPropertyDescriptorMap<PropertyInitGeneric>;
38
- init: RequiredBy<DeclarativeElementInit<InputsGeneric, PropertyInitGeneric, EventsInitGeneric, HostClassKeys, CssVarKeys>, 'stateInit' | 'events'>;
38
+ stateInit: ElementPropertyDescriptorMap<StateInitGeneric>;
39
+ init: RequiredBy<DeclarativeElementInit<InputsGeneric, StateInitGeneric, EventsInitGeneric, HostClassKeys, CssVarKeys>, 'stateInit' | 'events'>;
39
40
  inputsType: InputsGeneric;
40
- isStrictInstance: (element: unknown) => element is DeclarativeElement<InputsGeneric, PropertyInitGeneric, EventsInitGeneric, HostClassKeys, CssVarKeys>;
41
+ stateType: StateInitGeneric;
42
+ isStrictInstance: (element: unknown) => element is DeclarativeElement<InputsGeneric, StateInitGeneric, EventsInitGeneric, HostClassKeys, CssVarKeys>;
41
43
  hostClasses: HostClassNamesMap<string, HostClassKeys>;
42
44
  cssVarNames: CssVarNameOrValueMap<CssVarKeys>;
43
45
  cssVarValues: CssVarNameOrValueMap<CssVarKeys>;
@@ -51,6 +51,9 @@ export function defineElementNoInputs(initInput) {
51
51
  static get inputsType() {
52
52
  throw new Error(`"inputsType" was called on ${initInput.tagName} as a value but it is only for types.`);
53
53
  }
54
+ static get stateType() {
55
+ throw new Error(`"stateType" was called on ${initInput.tagName} as a value but it is only for types.`);
56
+ }
54
57
  markInputsAsHavingBeenSet() {
55
58
  if (!this.haveInputsBeenSet) {
56
59
  this.haveInputsBeenSet = true;
@@ -80,6 +83,14 @@ export function defineElementNoInputs(initInput) {
80
83
  });
81
84
  return renderResult;
82
85
  }
86
+ disconnectedCallback() {
87
+ super.disconnectedCallback();
88
+ if (initInput.cleanupCallback) {
89
+ const renderParams = this.createRenderParams();
90
+ initInput.cleanupCallback(renderParams);
91
+ }
92
+ this.initCalled = false;
93
+ }
83
94
  assignInputs(inputs) {
84
95
  getObjectTypedKeys(inputs).forEach((key) => {
85
96
  property()(this, key);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "element-vir",
3
- "version": "6.1.5",
3
+ "version": "6.2.0",
4
4
  "keywords": [
5
5
  "custom",
6
6
  "web",
@@ -37,7 +37,7 @@
37
37
  },
38
38
  "dependencies": {
39
39
  "augment-vir": "2.5.0",
40
- "lit": "2.3.1"
40
+ "lit": "2.4.0"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@open-wc/testing": "3.1.6",