UNPKG

@web-atoms/core

Version:
105 lines (89 loc) 2.85 kB
import type { AtomControl } from "../web/controls/AtomControl"; import { AtomBinder } from "./AtomBinder"; const cache = {}; function getSymbolKey(name: string) { return cache[name] ??= Symbol(name); } function refreshInherited(ac: AtomControl, key: any, storageKey: any) { const e = ac.element; if (!e) { // control is disposed !! return; } AtomBinder.refreshValue(ac, key); let start = e.firstElementChild as HTMLElement; if (!start) { return; } const stack = [start]; while (stack.length) { start = stack.pop(); while (start) { let firstChild = start.firstElementChild as HTMLElement; const childControl = start.atomControl; if (childControl) { if (childControl[storageKey] === undefined) { AtomBinder.refreshValue(childControl, key); } else { // we will not refresh this element firstChild = void 0; } } if (firstChild) { stack.push(firstChild); } start = start.nextElementSibling as HTMLElement; } } } export function getOwnInheritedProperty(target: any, key: string) { return target[getSymbolKey(key)]; } /** * Use this decorator only to watch property changes in `onPropertyChanged` method. * This decorator also makes enumerable property. * * Do not use this on anything except UI control * @param target control * @param key name of property */ export function InheritedProperty(target: any, key: string): any { // property value const iVal: any = target[key]; const keyName = getSymbolKey(key); target[keyName] = iVal; // property getter const getter: () => any = function(): any { let start = this; do { const p = start[keyName]; if (typeof p !== "undefined") { return p; } if (!start.element) { break; } start = start.parent; } while (start); return undefined; }; // property setter const setter: (v: any) => void = function(newVal: any): void { const oldValue = this[keyName]; if (oldValue && oldValue.dispose) { oldValue.dispose(); } this[keyName] = newVal; refreshInherited(this, key, keyName); }; // delete property if (delete target[key]) { // create new property with getter and setter Object.defineProperty(target, key, { get: getter, set: setter, enumerable: true, configurable: true }); } }