@awcrotwell/motion
Version:
Motion allows you to build reactive, real-time frontend UI components in your Amber application using pure Crystal that are reusable, testable & encapsulated. For brevity, we will call them MotionComponents.
72 lines (71 loc) • 2.86 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const dispatchEvent_1 = __importDefault(require("./dispatchEvent"));
const serializeEvent_1 = __importDefault(require("./serializeEvent"));
const reconcile_1 = __importDefault(require("./reconcile"));
class Component {
constructor(client, element) {
this.client = client;
this.element = element;
this._beforeConnect();
this._subscription = this.client.consumer.subscriptions.create({
channel: `motion:${this.generateTopic()}`,
// TODO:
version: '0.2.0',
state: this.element.getAttribute(this.client.stateAttribute),
}, {
connected: () => this._connect(),
rejected: () => this._connectFailed(),
disconnected: () => this._disconnect(),
received: (newState) => this._render(newState),
});
}
processMotion(name, event = null) {
if (!this._subscription) {
this.client.log('Dropped motion', name, 'on', this.element);
return;
}
this.client.log('Processing motion', name, 'on', this.element);
const extraDataForEvent = event && this.client.getExtraDataForEvent(event);
this._subscription.perform({
name,
event: event && serializeEvent_1.default(event, extraDataForEvent),
});
}
shutdown() {
this._subscription.unsubscribe();
delete this._subscription;
this._disconnect();
}
_beforeConnect() {
this.client.log('Connecting component', this.element);
dispatchEvent_1.default(this.element, 'motion:before-connect');
}
_connect() {
// debugger
this.client.log('Component connected', this.element);
dispatchEvent_1.default(this.element, 'motion:connect');
}
_connectFailed() {
this.client.log('Failed to connect component', this.element);
dispatchEvent_1.default(this.element, 'motion:connect-failed');
}
_disconnect() {
this.client.log('Component disconnected', this.element);
dispatchEvent_1.default(this.element, 'motion:disconnect');
}
_render(newState) {
dispatchEvent_1.default(this.element, 'motion:before-render');
reconcile_1.default(this.element, newState, this.client.keyAttribute);
this.client.log('Component rendered', this.element);
dispatchEvent_1.default(this.element, 'motion:render');
}
// eslint-disable-next-line class-methods-use-this
generateTopic() {
return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
}
}
exports.default = Component;