import { isPlainObject, toObject } from './flatTool'; 
 | 
import { canUseVirtualHost } from '../version'; 
 | 
const RawLifeCycles = ['Created', 'Attached', 'Ready', 'Moved', 'Detached', 'Error']; 
 | 
const NativeLifeCycles = RawLifeCycles.map((k) => k.toLowerCase()); 
 | 
const ComponentNativeProps = [ 
 | 
    'properties', 
 | 
    'data', 
 | 
    'observers', 
 | 
    'methods', 
 | 
    'behaviors', 
 | 
    ...NativeLifeCycles, 
 | 
    'relations', 
 | 
    'externalClasses', 
 | 
    'options', 
 | 
    'lifetimes', 
 | 
    'pageLifeTimes', 
 | 
    'definitionFilter', 
 | 
]; 
 | 
export const toComponent = function toComponent(options) { 
 | 
    const { relations, behaviors = [], externalClasses = [] } = options; 
 | 
    if (options.properties) { 
 | 
        Object.keys(options.properties).forEach((k) => { 
 | 
            let opt = options.properties[k]; 
 | 
            if (!isPlainObject(opt)) { 
 | 
                opt = { type: opt }; 
 | 
            } 
 | 
            options.properties[k] = opt; 
 | 
        }); 
 | 
        const ariaProps = [ 
 | 
            { key: 'ariaHidden', type: Boolean }, 
 | 
            { key: 'ariaRole', type: String }, 
 | 
            { key: 'ariaLabel', type: String }, 
 | 
            { key: 'ariaLabelledby', type: String }, 
 | 
            { key: 'ariaDescribedby', type: String }, 
 | 
            { key: 'ariaBusy', type: Boolean }, 
 | 
        ]; 
 | 
        ariaProps.forEach(({ key, type }) => { 
 | 
            options.properties[key] = { 
 | 
                type, 
 | 
            }; 
 | 
        }); 
 | 
        options.properties.style = { type: String, value: '' }; 
 | 
        options.properties.customStyle = { type: String, value: '' }; 
 | 
    } 
 | 
    if (!options.methods) 
 | 
        options.methods = {}; 
 | 
    if (!options.lifetimes) 
 | 
        options.lifetimes = {}; 
 | 
    const inits = {}; 
 | 
    if (relations) { 
 | 
        const getRelations = (relation, path) => Behavior({ 
 | 
            created() { 
 | 
                Object.defineProperty(this, `$${relation}`, { 
 | 
                    get: () => { 
 | 
                        const nodes = this.getRelationNodes(path) || []; 
 | 
                        return relation === 'parent' ? nodes[0] : nodes; 
 | 
                    }, 
 | 
                }); 
 | 
            }, 
 | 
        }); 
 | 
        const map = {}; 
 | 
        Object.keys(relations).forEach((path) => { 
 | 
            const comp = relations[path]; 
 | 
            const relation = ['parent', 'ancestor'].includes(comp.type) ? 'parent' : 'children'; 
 | 
            const mixin = getRelations(relation, path); 
 | 
            map[relation] = mixin; 
 | 
        }); 
 | 
        behaviors.push(...Object.keys(map).map((key) => map[key])); 
 | 
    } 
 | 
    options.behaviors = [...behaviors]; 
 | 
    options.externalClasses = ['class', ...externalClasses]; 
 | 
    Object.getOwnPropertyNames(options).forEach((k) => { 
 | 
        const desc = Object.getOwnPropertyDescriptor(options, k); 
 | 
        if (!desc) 
 | 
            return; 
 | 
        if (NativeLifeCycles.indexOf(k) < 0 && typeof desc.value === 'function') { 
 | 
            Object.defineProperty(options.methods, k, desc); 
 | 
            delete options[k]; 
 | 
        } 
 | 
        else if (ComponentNativeProps.indexOf(k) < 0) { 
 | 
            inits[k] = desc; 
 | 
        } 
 | 
        else if (NativeLifeCycles.indexOf(k) >= 0) { 
 | 
            options.lifetimes[k] = options[k]; 
 | 
        } 
 | 
    }); 
 | 
    if (Object.keys(inits).length) { 
 | 
        const oldCreated = options.lifetimes.created; 
 | 
        const oldAttached = options.lifetimes.attached; 
 | 
        const { controlledProps = [] } = options; 
 | 
        options.lifetimes.created = function (...args) { 
 | 
            Object.defineProperties(this, inits); 
 | 
            if (oldCreated) 
 | 
                oldCreated.apply(this, args); 
 | 
        }; 
 | 
        options.lifetimes.attached = function (...args) { 
 | 
            if (oldAttached) 
 | 
                oldAttached.apply(this, args); 
 | 
            controlledProps.forEach(({ key }) => { 
 | 
                const defaultKey = `default${key.replace(/^(\w)/, (m, m1) => m1.toUpperCase())}`; 
 | 
                const props = this.properties; 
 | 
                if (props[key] == null) { 
 | 
                    this._selfControlled = true; 
 | 
                } 
 | 
                if (props[key] == null && props[defaultKey] != null) { 
 | 
                    this.setData({ 
 | 
                        [key]: props[defaultKey], 
 | 
                    }); 
 | 
                } 
 | 
            }); 
 | 
        }; 
 | 
        options.methods._trigger = function (evtName, detail, opts) { 
 | 
            const target = controlledProps.find((item) => item.event == evtName); 
 | 
            if (target) { 
 | 
                const { key } = target; 
 | 
                if (this._selfControlled) { 
 | 
                    this.setData({ 
 | 
                        [key]: detail[key], 
 | 
                    }); 
 | 
                } 
 | 
            } 
 | 
            this.triggerEvent(evtName, detail, opts); 
 | 
        }; 
 | 
    } 
 | 
    return options; 
 | 
}; 
 | 
export const wxComponent = function wxComponent() { 
 | 
    return function (constructor) { 
 | 
        class WxComponent extends constructor { 
 | 
        } 
 | 
        const current = new WxComponent(); 
 | 
        current.options = current.options || {}; 
 | 
        if (current.options.addGlobalClass === undefined) { 
 | 
            current.options.addGlobalClass = true; 
 | 
        } 
 | 
        if (canUseVirtualHost()) { 
 | 
            current.options.virtualHost = true; 
 | 
        } 
 | 
        const obj = toComponent(toObject(current)); 
 | 
        Component(obj); 
 | 
    }; 
 | 
}; 
 |