UNPKG

2.35 kBPlain TextView Raw
1/**
2@license
3Copyright (c) 2018 The Polymer Project Authors. All rights reserved.
4This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
5The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
6The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
7Code distributed by Google as part of the polymer project is also
8subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
9*/
10
11import { Store, Unsubscribe } from 'redux';
12
13type Constructor<T> = new(...args: any[]) => T;
14
15/**
16 By using this `CustomElement` interface instead of `HTMLElement`, we avoid
17 having the generated typings include most DOM API already provided by
18 TypeScript. This is particularly useful since different versions of
19 TypeScript may have different DOM API typings (e.g. TS 3.0.3 and TS 3.1.1).
20 The required `isConnected` property is included to avoid the following
21 TypeScript error:
22
23 Type 'HTMLElement' has no properties in common with type 'CustomElement'.
24*/
25interface CustomElement {
26 connectedCallback?(): void;
27 disconnectedCallback?(): void;
28 readonly isConnected: boolean;
29}
30
31/**
32 This is a JavaScript mixin that you can use to connect a Custom Element base
33 class to a Redux store. The `stateChanged(state)` method will be called when
34 the state is updated.
35
36 Example:
37
38 import { connect } from 'pwa-helpers/connect-mixin.js';
39
40 class MyElement extends connect(store)(HTMLElement) {
41 stateChanged(state) {
42 this.textContent = state.data.count.toString();
43 }
44 }
45*/
46export const connect =
47 <S>(store: Store<S>) =>
48 <T extends Constructor<CustomElement>>(baseElement: T) =>
49 class extends baseElement {
50 _storeUnsubscribe!: Unsubscribe;
51
52 connectedCallback() {
53 if (super.connectedCallback) {
54 super.connectedCallback();
55 }
56
57 this._storeUnsubscribe = store.subscribe(() => this.stateChanged(store.getState()));
58 this.stateChanged(store.getState());
59 }
60
61 disconnectedCallback() {
62 this._storeUnsubscribe();
63
64 if (super.disconnectedCallback) {
65 super.disconnectedCallback();
66 }
67 }
68
69 /**
70 * The `stateChanged(state)` method will be called when the state is updated.
71 */
72 stateChanged(_state: S) {}
73 };