99 lines
1.8 KiB
JavaScript
99 lines
1.8 KiB
JavaScript
import * as I from 'immutable';
|
|
|
|
import {Resource} from '@avocado/resource';
|
|
|
|
export class Trait {
|
|
|
|
constructor(entity) {
|
|
this.entity = entity;
|
|
this.params = I.fromJS(this.constructor.defaultParams());
|
|
this.state = I.fromJS(this.constructor.defaultState());
|
|
// Attach listeners.
|
|
const listeners = this.listeners();
|
|
const traitType = this.constructor.type();
|
|
for (const type in this.listeners()) {
|
|
entity.on(`${type}.trait-${traitType}`, listeners[type]);
|
|
}
|
|
}
|
|
|
|
acceptStateChange(change) {
|
|
this.state = this.state.merge(change);
|
|
}
|
|
|
|
actions() {
|
|
return {};
|
|
}
|
|
|
|
destroy() {
|
|
this.entity.off(`.trait-${this.constructor.type()}`);
|
|
}
|
|
|
|
fromJSON({params = {}, state = {}}) {
|
|
this.params = I.fromJS(this.constructor.defaultParams()).merge(params);
|
|
this.state = I.fromJS(this.constructor.defaultState()).merge(state);
|
|
return this;
|
|
}
|
|
|
|
hooks() {
|
|
return {};
|
|
}
|
|
|
|
hydrate() {
|
|
return Promise.resolve();
|
|
}
|
|
|
|
label() {
|
|
return this.constructor.name;
|
|
}
|
|
|
|
listeners() {
|
|
return {};
|
|
}
|
|
|
|
toJSON() {
|
|
return {
|
|
params: this.params.toJS(),
|
|
state: this.state.toJS(),
|
|
};
|
|
}
|
|
|
|
static contextType() {
|
|
return {};
|
|
}
|
|
|
|
static defaultParams() {
|
|
return {};
|
|
}
|
|
|
|
static defaultState() {
|
|
return {};
|
|
}
|
|
|
|
static dependencies() {
|
|
return [];
|
|
}
|
|
|
|
static type() {
|
|
return this.name.toLowerCase();
|
|
}
|
|
|
|
}
|
|
|
|
export function simpleState(name) {
|
|
return (Superclass) => {
|
|
class SimpleState extends Superclass {}
|
|
// Add simple state handler.
|
|
Object.defineProperty(SimpleState.prototype, name, {
|
|
get() {
|
|
return this.state.get(name);
|
|
},
|
|
set(value) {
|
|
this.state = this.state.set(name, value);
|
|
},
|
|
enumerable: true,
|
|
configurable: true,
|
|
});
|
|
return SimpleState;
|
|
}
|
|
}
|