Skip to content

Commit

Permalink
feat(item): dispatch events for focus changes
Browse files Browse the repository at this point in the history
refs: #4
  • Loading branch information
christoph-fricke committed Aug 17, 2022
1 parent 139df40 commit 2dbfbcb
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 3 deletions.
9 changes: 8 additions & 1 deletion src/components/item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { customElement, property } from "lit/decorators.js";
import { cameraProp } from "../controllers/camera-controller.js";
import { ItemInteractionsController } from "../controllers/item-interactions-controller.js";
import { MuttiDate } from "../core/date.js";
import { ActionEvent } from "../core/events.js";
import { ItemFocusEvent } from "../core/events.js";
import { varX } from "../core/properties.js";

/** Custom CSS property names that are related to items. */
Expand Down Expand Up @@ -53,6 +53,13 @@ export class MuttiItemElement extends LitElement {
);
@property({ type: Number, attribute: false }) subTrack = 1;

override focus(): void {
const shouldContinue = this.dispatchEvent(
new ItemFocusEvent(this.start, this.end)
);
if (shouldContinue) super.focus({ preventScroll: true });
}

protected override willUpdate(changedProperties: PropertyValues): void {
if (changedProperties.has("subTrack")) {
this.style.setProperty(itemProp.subTrack, this.subTrack.toString());
Expand Down
27 changes: 26 additions & 1 deletion src/controllers/item-interactions-controller.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import type { LitElement, ReactiveController } from "lit";
import { ActionEvent, DeleteEvent } from "../core/events.js";
import {
ActionEvent,
DeleteEvent,
FocusChangeEvent,
FocusChangeLocation,
} from "../core/events.js";

export class ItemInteractionsController implements ReactiveController {
constructor(private readonly host: LitElement) {
Expand All @@ -24,13 +29,33 @@ export class ItemInteractionsController implements ReactiveController {
case "Delete":
if (!e.repeat) this.delete();
break;
case "ArrowLeft":
e.preventDefault();
this.changeFocus("left");
break;
case "ArrowRight":
e.preventDefault();
this.changeFocus("right");
break;
case "ArrowUp":
e.preventDefault();
this.changeFocus("up");
break;
case "ArrowDown":
e.preventDefault();
this.changeFocus("down");
break;
}
};

private handleDoubleClick = () => {
this.action();
};

private changeFocus(where: FocusChangeLocation) {
this.host.dispatchEvent(new FocusChangeEvent(where));
}

private delete() {
this.host.dispatchEvent(new DeleteEvent());
}
Expand Down
37 changes: 37 additions & 0 deletions src/core/events.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { MuttiDate } from "./date.js";

abstract class MuttiEvent extends Event {
static match(_: Event): _ is MuttiEvent {
throw new TypeError(
Expand All @@ -10,6 +12,8 @@ declare global {
interface GlobalEventHandlersEventMap {
[ActionEvent.type]: ActionEvent;
[DeleteEvent.type]: DeleteEvent;
[FocusChangeEvent.type]: FocusChangeEvent;
[ItemFocusEvent.type]: ItemFocusEvent;
}
}

Expand All @@ -36,3 +40,36 @@ export class DeleteEvent extends MuttiEvent {
return e instanceof DeleteEvent;
}
}

export type FocusChangeLocation = "left" | "right" | "up" | "down";
export class FocusChangeEvent extends MuttiEvent {
static type = "focuschange" as const;

constructor(public readonly where: FocusChangeLocation) {
super(FocusChangeEvent.type, { bubbles: true });
}

static override match(e: Event): e is FocusChangeEvent {
return e instanceof FocusChangeEvent;
}
}

/**
* This event is dispatched before an item is focused via the keyboard.
* If the event is cancelled, the item will not be focussed and will
* not be moved into view.
*/
export class ItemFocusEvent extends MuttiEvent {
static type = "itemfocus" as const;

constructor(
public readonly start: MuttiDate,
public readonly end: MuttiDate
) {
super(ItemFocusEvent.type, { bubbles: true, cancelable: true });
}

static override match(e: Event): e is ItemFocusEvent {
return e instanceof ItemFocusEvent;
}
}
7 changes: 6 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,9 @@ export { MuttiLabelElement } from "./components/label.js";
export { MuttiTimelineElement } from "./components/timeline.js";
export { MuttiTrackElement } from "./components/track.js";

export { ActionEvent, DeleteEvent } from "./core/events.js";
export {
ActionEvent,
DeleteEvent,
FocusChangeEvent,
ItemFocusEvent,
} from "./core/events.js";

0 comments on commit 2dbfbcb

Please sign in to comment.