import { define , Store } from 'type-r' ; import { StateMixin , UpdateOnNestedChangesMixin } from './state' ; import { ComponentClass } from './common' ; export interface StoreDefinition { store ? : typeof Store | Store | object ; Store ? : typeof Store ; } export interface StoreProto { store ? : Store ; Store ? : typeof Store ; } export default function onDefine ( this , definition , BaseClass ) { let { store , Store : StoreClass } = definition ; if ( store && store instanceof Store ) { this . prototype . store = store ; this . mixins . merge ( [ ExternalStoreMixin , ExposeStoreMixin ] ) ; } else if ( store || definition . Store ) { if ( typeof store === 'function' ) { StoreClass = store ; store = void 0 ; } if ( store ) { const BaseClass = StoreClass || this . prototype . Store || Store ; @ define class InternalStore extends BaseClass { static attrbutes = store ; } ; this . prototype . Store = InternalStore ; } else if ( StoreClass ) { this . prototype . Store = StoreClass ; } this . mixins . merge ( [ InternalStoreMixin , UpdateOnNestedChangesMixin , ExposeStoreMixin ] ) ; } } /**
 * Attached whenever the store declaration of any form is present in the component.
 */ const ExposeStoreMixin = { childContext : { _nestedStore : Store } , getChildContext ( ) { return { _nestedStore : this . store } ; } , getStore ( ) { return this . store ; } , get ( key ) { const store = StateMixin . getStore . call ( this , key ) ; return store && store . get ( key ) ; } } ; /**
 * External store must just track the changes and trigger render.
 * TBD: don't use it yet.
 */ const ExternalStoreMixin = { componentDidMount ( ) { this . listenTo ( this . store , 'change' , this . asyncUpdate ) ; } } ; const InternalStoreMixin = { componentWillMount ( ) { var store = this . store = new this . Store ( ) ; store . _owner = this ; store . _ownerKey = 'store' ; } , componentWillUnmount ( ) { this . store . _ownerKey = this . store . _owner = void 0 ; this . store . dispose ( ) ; this . store = void 0 ; } } ;