content: import React from 'react';
  
  class XState
  {
      constructor(component = class extends XComponent {}, previous_state = undefined)
      {
          this.component = component;
          this.reducer = component.getReducer();
          if (previous_state) {
              this.data = previous_state.data;
              this.childStates = previous_state.childStates;
          }
          else {
              let temp_state = this.reducer(undefined, undefined);
              this.data = temp_state.data;
              this.childStates = temp_state.childStates;
          }
      }
  }
  
  class XAction
  {
      constructor(type = '', param = undefined, target = '.', path = [])
      {
          this.type = type;
          this.target = target;
          this.path = path;
          this.param = param;
          this.receiver = [];
      }
  }
  
  class XReducer
  {
      constructor(component = class extends XComponent {}, init_child_states = {})
      {
          this.component = component;
          this.initChildStates = init_child_states;
      }
  
      reducer(state, action)
      {
          let new_state = null;
          if (state
          && action
          && state.hasOwnProperty('data')
          && action.hasOwnProperty('receiver')) {
              let t = action.receiver.shift();
              if (t === '.') {
                  new_state = this.localReducer(state, action);
              }
              else {
                  new_state = Object.assign({}, state);
                  let state_keys = Object.keys(state.childStates);
                  new_state.childStates = state_keys.reduce(
                      (nextState, sk) => {
                          if (t !== sk) {
                              nextState[sk] = state.childStates[sk];
                          }
                          else {
                              nextState[sk] = state.childStates[sk].reducer(state.childStates[sk], action);
                          }
                          return nextState;
                      },
                      {}
                  );
              }
          }
          else {
              new_state = {
                  component: this.component,
                  reducer: this.component.getReducer(),
                  data: undefined,
                  childStates: {},
              };
              let keys = Object.keys(this.initChildStates);
              if (keys.length > 0) {
                  new_state.childStates = keys.reduce(
                      (nextState, sk) => {
                          nextState[sk] = this.initChildStates[sk].getReducer()(undefined, action);
                          return nextState;
                      },
                      {}
                  );
              }
              new_state = this.localReducer(new_state, action);
          }
  
          return new_state;
      }
  
      localReducer(state = new XState(this.component), action = new XAction())
      {
          return Object.assign({}, state);
      }
  
      static resolveTarget(action)
      {
          let act = new XAction();
          action = Object.assign(act, action);
  
          if (!action.hasOwnProperty('target')) {
              action.target = '.';
          }
  
          let target = action.target.trim().replace(/\/+$/, '');
          while (target.startsWith('./')) {
              target = target.substring(2);
          }
  
          if (target === '.' || target === '') {
              action.receiver = action.path.slice();
          }
          else if (target.startsWith('/')) {
              action.receiver = target.split('/');
              action.receiver.shift();
          }
          else {
              let path = action.path.slice();
              path.pop();
              while (target.startsWith('../')) {
                  path.pop();
                  target = target.substring(3);
              }
              let target_parts = target.split('/');
              action.receiver = path.concat(target_parts, ['.']);
          }
  
          return Object.assign({}, action);
      }
  }
  
  class XComponent extends React.Component
  {
      static getReducer()
      {
          if (!XComponent.reducer) {
              XComponent.reducer = new XReducer(XComponent);
          }
          return XComponent.reducer.reducer.bind(XComponent.reducer);
      }
  
      dispatch(action = {}, path = '.')
      {
          if (!action.path) {
              action.path = [];
          }
          action.path.unshift(path);
          console.log("dispatching:");
          console.log(JSON.parse(JSON.stringify(action)));
          this.props.dispatch(action);
      }
  }
  
  export { XAction, XState, XReducer, XComponent };
  