Skip to content

Commit

Permalink
Update event component to be nicer to typescript. Next step to remove…
Browse files Browse the repository at this point in the history
… it in favour of the WebComponent base.
  • Loading branch information
Blaine Cook authored and blaine committed Sep 26, 2018
1 parent fc44cc8 commit 57ce661
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 42 deletions.
4 changes: 2 additions & 2 deletions packages/@atjson/editor/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Document, { Annotation } from '@atjson/document';
import WebComponentRenderer from '@atjson/renderer-webcomponent';
import events from './mixins/events';
import EventComponent from './mixins/events';
import './selection-toolbar';
import './text-input';
import TextSelection from './text-selection';
Expand All @@ -11,7 +11,7 @@ export interface Range {
end: number;
}

export default class OffsetEditor extends events(HTMLElement) {
export default class OffsetEditor extends EventComponent {

static template = '<text-input>' +
'<text-selection>' +
Expand Down
70 changes: 34 additions & 36 deletions packages/@atjson/editor/src/mixins/events.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
type Constructor<T = {}> = new (...args: any[]) => T;

export type EventCallback = (evt: Event) => boolean;

export interface EventHandlerDefinitions {
Expand Down Expand Up @@ -57,44 +55,44 @@ function getEventNameAndElement(element: HTMLElement, definition: string) {
* resizing, and selection events without using `addEventListener` /
* `removeEventListener`.
*/
export default function<HTMLElement extends Constructor>(Base: HTMLElement) {
return class extends Base {
static events: EventHandlerDefinitions | null;
private eventHandlers: EventHandlerReferences;
export default class EventComponent extends HTMLElement {
static events: EventHandlerDefinitions | null;
private eventHandlers: EventHandlerReferences;

constructor(...args: any[]) {
super(...args);
this.eventHandlers = {};
}
[key: string]: any;

constructor() {
super();
this.eventHandlers = {};
}

connectedCallback() {
let events: EventHandlerDefinitions = this.constructor.events || {};
Object.keys(events).forEach((definition: string) => {
let { eventName, element } = getEventNameAndElement(this, definition);
let method = events[definition];
connectedCallback() {
let ComponentClass = this.constructor as typeof EventComponent;
let events: EventHandlerDefinitions = ComponentClass.events || {};
Object.keys(events).forEach((definition: string) => {
let { eventName, element } = getEventNameAndElement(this, definition);
let method = events[definition];
this.eventHandlers[definition] = (evt): boolean | never => {
if (typeof method === 'string') {
this.eventHandlers[definition] = (evt): EventCallback | never => {
if (this[method]) {
return this[method](evt);
} else {
throw new Error(`😭 \`${method}\` was not defined on ${this.tagName}- did you misspell or forget to add it?`);
}
};
const eventHandler: (event: Event) => boolean | never = this[method];
if (eventHandler instanceof Function) {
return eventHandler.call(this, evt);
} else {
throw new Error(`😭 \`${method}\` was not defined on ${this.tagName}- did you misspell or forget to add it?`);
}
} else {
this.eventHandlers[definition] = (evt): EventCallback => {
return method.call(this, evt);
};
return method.call(this, evt);
}
element.addEventListener(eventName, this.eventHandlers[definition]);
});
}
};
element.addEventListener(eventName, this.eventHandlers[definition]);
});
}

disconnectedCallback() {
Object.keys(this.eventHandlers).forEach(definition => {
let { eventName, element } = getEventNameAndElement(this, definition);
element.removeEventListener(eventName, this.eventHandlers[definition]);
});
this.eventHandlers = {};
}
};
disconnectedCallback() {
Object.keys(this.eventHandlers).forEach(definition => {
let { eventName, element } = getEventNameAndElement(this, definition);
element.removeEventListener(eventName, this.eventHandlers[definition]);
});
this.eventHandlers = {};
}
}
4 changes: 2 additions & 2 deletions packages/@atjson/editor/src/text-input.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import events from './mixins/events';
import EventComponent from './mixins/events';

/* const supports = {
beforeinput: InputEvent.prototype.hasOwnProperty('inputType')
Expand Down Expand Up @@ -55,7 +55,7 @@ function getTextNodes(node: Node): Text[] {
* promise accuracy to the level of what is provided by the
* fidelity of the web API that's available for use in the browser.
*/
class TextInput extends events(HTMLElement) {
class TextInput extends EventComponent {
static events = {
'beforeinput': 'beforeinput',
'compositionend': 'compositionend',
Expand Down
4 changes: 2 additions & 2 deletions packages/@atjson/editor/src/text-selection.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import events from './mixins/events';
import EventComponent from './mixins/events';

const TEXT_NODE_TYPE = 3;
const DOCUMENT_POSITION_PRECEDING = 2;
Expand Down Expand Up @@ -69,7 +69,7 @@ function previousTextNode(node: Node): TextRangePoint {
* @emits CustomEvent#change - called when the text selection changes
* @emits CustomEvent#clear - called when the text selecton is cleared
*/
class TextSelection extends events(HTMLElement) {
class TextSelection extends EventComponent {

static observedAttributes = ['start', 'end'];
static events = {
Expand Down

0 comments on commit 57ce661

Please sign in to comment.