/** * Copyright (c) 2020 Dorian Cortes, Gary Valverde * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * */ import { contextConsumer } from "../lib/context-consumer"; import { MapFn } from "../types/context"; /** * @param providerTag Provider tag name * @param mapFn Function to map provider value */ export type Constructor = { // tslint:disable-next-line:no-any new(...args: any[]): T }; // From the TC39 Decorators proposal interface ClassDescriptor { kind: 'class'; elements: ClassElement[]; finisher?: (clazz: Constructor) => undefined | Constructor; } // From the TC39 Decorators proposal interface ClassElement { kind: 'field' | 'method'; key: PropertyKey; placement: 'static' | 'prototype' | 'own'; initializer?: Function; extras?: ClassElement[]; finisher?: (clazz: Constructor) => undefined | Constructor; descriptor?: PropertyDescriptor; } export const consume = (providerTag: string, mapFn?: MapFn) => (classOrDescriptor: Constructor | ClassDescriptor) => (typeof classOrDescriptor === 'function') ? legacyCustomElement(classOrDescriptor, providerTag, mapFn) : standardCustomElement(classOrDescriptor, providerTag, mapFn); const legacyCustomElement = (classConstructor: Constructor, providerTag: string, mapFn?: MapFn) => { const consumer = (consumer: HTMLElement, mapFn?: MapFn) => contextConsumer(providerTag, consumer, mapFn); return class extends classConstructor { connectedCallback() { super.connectedCallback(); consumer(this, mapFn); } } as any }; const standardCustomElement = (classConstructor: ClassDescriptor, providerTag: string, mapFn?: MapFn) => { const { kind, elements } = classConstructor; const consumer = (consumer: HTMLElement, mapFn?: MapFn) => contextConsumer(providerTag, consumer, mapFn); return { kind, elements, finisher(clazz: Constructor) { clazz.prototype.__litContextConnectedCallback = clazz.prototype.connectedCallback; clazz.prototype.connectedCallback = function connectedCallbackHandler() { this.__litContextConnectedCallback(); consumer(this, mapFn); }; } }; };