/**
* @summary decorators
* @version 3.0.0
* @since 3.0.0
* @author Arian Khosravi<arian.khosravi@aofl.com>
*/
import {storeInstance} from '@aofl/store';
import {get, has} from '@aofl/object-utils';
import {property as litProperty, customElement as litCustomElement} from 'lit-element/lib/decorators';
/**
* @memberof module:@aofl/element
* @private
* @type {Object}
*/
const MapStateDeclaration = {
store: storeInstance,
mapState: ''
};
/**
* extends lit-element's property decorator and adds support for map state to @aofl/store.
*
* @memberof module:@aofl/element
*
* @param {Object} options
* @param {Boolean|String} options.attribute
* @param {TypeHint} options.type
* @param {Function} options.converter
* @param {Boolean} options.reflect
* @param {Function} options.hasChanged
* @param {Boolean} options.noAccessor
* @param {Store} options.store,
* @param {String} options.mapState
* @return {Object}
*/
export function property(options = MapStateDeclaration) {
const _options = Object.assign({}, MapStateDeclaration, options);
return (protoOrDescriptor, name) => {
const propertyDecorator = litProperty(_options);
const descriptor = propertyDecorator(protoOrDescriptor, name);
return Object.assign({}, descriptor, {
initializer() {
/* istanbul ignore next */
if (typeof descriptor.initializer === 'function') {
descriptor.initializer.call(this);
}
/* istanbul ignore next */
if (_options.mapState !== '') {
const updateValue = () => {
const state = _options.store.state;
if (has(state, _options.mapState)) {
this[protoOrDescriptor.key] = get(state, _options.mapState);
} else {
this[protoOrDescriptor.key] = get(_options.store, _options.mapState);
}
};
updateValue();
const unsubscribe = _options.store.subscribe(updateValue);
this._observedPropertiesMap.set(protoOrDescriptor.key, unsubscribe);
}
}
});
};
}
/**
* extends lit-element's custom-element decorator and prevents an error being thrown when
* the element is already defined when hot module replacement is enabled.
*
* @memberof module:@aofl/element
* @param {String} tagName
* @return {Object}
*/
export function customElement(tagName) {
return (descriptor) => {
if (window.customElements.get(tagName) !== void 0) {
return descriptor;
}
return litCustomElement(tagName)(descriptor);
};
}