|
export const customElement = (tagName, options) => (classOrDescriptor) => (typeof classOrDescriptor === 'function') ? |
|
legacyCustomElement(tagName, options, classOrDescriptor) : |
|
standardCustomElement(tagName, options, classOrDescriptor); |
|
|
|
const standardCustomElement = (tagName, options, descriptor) => { |
|
const { kind, elements } = descriptor; |
|
return { |
|
kind, |
|
elements, |
|
// This callback is called once the class is otherwise fully defined |
|
finisher(clazz) { |
|
window.customElements.define(tagName, clazz, options); |
|
} |
|
}; |
|
}; |
|
const legacyCustomElement = (tagName, options, clazz) => { |
|
window.customElements.define(tagName, clazz, options); |
|
return clazz; |
|
}; |
|
|
|
export function prop(options) { |
|
return (protoOrDescriptor, name) => (name !== undefined) ? |
|
legacyUpdate(options, protoOrDescriptor, name) : |
|
standardUpdate(options, protoOrDescriptor); |
|
} |
|
const standardProp = (options, element) => { |
|
if (element.kind === 'method' && element.descriptor && |
|
!('value' in element.descriptor)) { |
|
return Object.assign({}, element, { |
|
finisher(clazz) { |
|
createProp(clazz, element.key, options); |
|
} |
|
}); |
|
} |
|
else { |
|
return { |
|
kind: 'field', |
|
key: Symbol(), |
|
placement: 'own', |
|
descriptor: {}, |
|
initializer() { |
|
if (typeof element.initializer === 'function') { |
|
this[element.key] = element.initializer.call(this); |
|
} |
|
}, |
|
finisher(clazz) { |
|
createProp(clazz, element.key, options); |
|
} |
|
}; |
|
} |
|
}; |
|
const legacyProp = (options, proto, name) => { |
|
createProp(proto.constructor, name, options); |
|
}; |
|
|
|
|
|
function createProp(cls, prop, option) { |
|
let _prop = Symbol(prop) |
|
|
|
let planned |
|
|
|
Object.defineProperty(cls.prototype, prop, { |
|
get() { return this[_prop] }, |
|
set(value) { |
|
this[_prop] = value |
|
|
|
if (planned) return |
|
planned = queueMicrotask(() => { |
|
planned = null |
|
this.render() |
|
}) |
|
} |
|
}) |
|
} |