import { trigger , reactive } from '@vue/reactivity' ; import { mapObject , isObject } from '@kirei/shared' ; import { hyphenate } from '@vue/shared' ; import { setCurrentInstance , createComponentInstance , getComponentInstance } from './instance' ; import { exception } from '../warn' ; import { validateProp , normalizeProps } from './props' ; import { nextTick } from './queue' ; import type { TriggerOpTypes } from '@vue/reactivity' ; import type { IComponent , ComponentOptions , NormalizedComponentOptions } from '../types' ; param options returns private export function normalizeOptions ( options ) { const { styles , emits , directives } = options ; const props = options . props ? normalizeProps ( options . props ) : { } ; const normalized = options as NormalizedComponentOptions ; normalized . props = props ; normalized . setup = options . setup ?? null ; normalized . tag = hyphenate ( options . name ) ; normalized . attrs = mapObject ( ( key ) => [ hyphenate ( key ) , key ] , props ) ; normalized . attributes = Object . keys ( normalized . attrs ) ; if ( styles != null ) { normalized . styles = Array . isArray ( styles ) ? [ ... new Set ( styles ) ] : [ styles ] ; } if ( directives != null ) { normalized . directives = mapObject ( ( key , value ) => [ hyphenate ( key ) , value ] , directives ) ; } if ( Array . isArray ( emits ) ) { normalized . emits = mapObject ( ( key ) => [ key , null ] , emits ) ; } else { normalized . emits = isObject ( emits ) ? emits : { } ; } return normalized ; } /**
 * Element to use custom elements functionality, as it required a class
 */ export class Component extends HTMLElement implements IComponent { /**
     * Options for this element, used for creating Kirei instances
     */ static options : NormalizedComponentOptions ; static static get is ( ) : string { return this . options . tag ; } static static get observedAttributes ( ) : string [ ] { return this . options . attributes ; } /**
     * Constructs a new Component
     */ constructor ( ) { super ( ) ; const { options } = this . constructor as typeof Component ; const instance = createComponentInstance ( this , options ) ; const { props } = instance ; for ( const key of Object . keys ( options . props ) ) { if ( this . hasOwnProperty ( key ) ) { exception ( `Prop ${ key } is reserved, please use another.` ) ; } Object . defineProperty ( this , key , { get : ( ) => props [ key ] , set ( newValue ) { if ( newValue !== props [ key ] ) { try { setCurrentInstance ( instance ) ; const value = validateProp ( options . props [ key ] , key , newValue ) ; props [ key ] = isObject ( value ) ? reactive ( value ) : value ; trigger ( props , 'set' as TriggerOpTypes , key , newValue ) ; } catch ( ex ) { exception ( ex ) ; } finally { setCurrentInstance ( null ) ; } } } , } ) ; } } /**
     * Runs when mounted from DOM
     */ connectedCallback ( ) { const instance = getComponentInstance ( this ) ; nextTick ( ( ) => instance . mount ( ) ) ; } /**
     * Runs when unmounted from DOM
     */ disconnectedCallback ( ) { const instance = getComponentInstance ( this ) ; instance . unmount ( ) ; } /**
     * Observes attribute changes, triggers updates on props
     */ attributeChangedCallback ( attr , oldValue , newValue ) { if ( oldValue !== newValue ) { const { options } = this . constructor as typeof Component ; const key = options . attrs [ attr ] ; this [ key ] = newValue ; } } }