Skip to content

Commit aac5335

Browse files
authored
refactor: split events logic to controller (#91)
1 parent 7b0770d commit aac5335

File tree

3 files changed

+78
-32
lines changed

3 files changed

+78
-32
lines changed

src/api-demo-knobs-mixin.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,12 @@ const getCustomKnobs = (tag: string, vid?: number): Knob<PropertyInfo>[] => {
126126
/* eslint-disable @typescript-eslint/no-explicit-any */
127127
export type Constructor<T = unknown> = new (...args: any[]) => T;
128128

129-
export interface ApiDemoKnobsInterface {
129+
export interface HasKnobs {
130+
getKnob(name: string): { knob: Knob<PropertyInfo>; custom?: boolean };
131+
syncKnob(component: Element, changed: Knob<PropertyInfo>): void;
132+
}
133+
134+
export interface ApiDemoKnobsInterface extends HasKnobs {
130135
tag: string;
131136
props: PropertyInfo[];
132137
propKnobs: Knob<PropertyInfo>[];
@@ -142,8 +147,6 @@ export interface ApiDemoKnobsInterface {
142147
setSlots(target: HTMLInputElement): void;
143148
setCss(target: HTMLInputElement): void;
144149
initKnobs(component: HTMLElement): void;
145-
getKnob(name: string): { knob: Knob<PropertyInfo>; custom?: boolean };
146-
syncKnob(component: Element, changed: Knob<PropertyInfo>): void;
147150
}
148151

149152
export const ApiDemoKnobsMixin = <T extends Constructor<LitElement>>(

src/api-viewer-demo.ts

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { LitElement, html, PropertyValues, TemplateResult } from 'lit';
1+
import { LitElement, html, TemplateResult } from 'lit';
22
import { property } from 'lit/decorators/property.js';
33
import { cache } from 'lit/directives/cache.js';
4+
import { EventsController } from './controllers/events-controller.js';
45
import { renderEvents } from './lib/demo-events.js';
56
import { renderSnippet } from './lib/demo-snippet.js';
67
import { renderer } from './lib/renderer.js';
@@ -23,11 +24,10 @@ class ApiViewerDemo extends ApiDemoKnobsMixin(LitElement) {
2324
@property({ attribute: false })
2425
events: EventInfo[] = [];
2526

26-
@property({ attribute: false })
27-
eventLog!: CustomEvent[];
28-
2927
private _whenDefined: Record<string, Promise<unknown>> = {};
3028

29+
private eventsController!: EventsController;
30+
3131
protected createRenderRoot(): this {
3232
return this;
3333
}
@@ -51,6 +51,7 @@ class ApiViewerDemo extends ApiDemoKnobsMixin(LitElement) {
5151
</div>
5252
`;
5353
}
54+
5455
const [noCss, noEvents, noSlots, noCustomKnobs, noProps] = [
5556
this.cssProps,
5657
this.events,
@@ -60,7 +61,7 @@ class ApiViewerDemo extends ApiDemoKnobsMixin(LitElement) {
6061
].map((arr) => arr.length === 0);
6162

6263
const id = this.vid as number;
63-
const log = this.eventLog;
64+
const log = this.eventsController?.log || [];
6465
const slots = this.processedSlots;
6566
const hideSlots = noSlots || hasTemplate(id, this.tag, TemplateTypes.SLOT);
6667

@@ -165,18 +166,9 @@ class ApiViewerDemo extends ApiDemoKnobsMixin(LitElement) {
165166
`;
166167
}
167168

168-
willUpdate(props: PropertyValues) {
169-
super.willUpdate(props);
170-
171-
// Reset state if tag changed
172-
if (props.has('tag')) {
173-
this.eventLog = [];
174-
}
175-
}
176-
177169
private _onLogClear(): void {
178-
this.eventLog = [];
179-
const tab = this.renderRoot.querySelector('#events') as HTMLElement;
170+
this.eventsController.clear();
171+
const tab = this.querySelector('#events') as HTMLElement;
180172
if (tab) {
181173
tab.focus();
182174
}
@@ -211,21 +203,19 @@ class ApiViewerDemo extends ApiDemoKnobsMixin(LitElement) {
211203
private onRendered(e: CustomEvent): void {
212204
const { component } = e.detail;
213205

214-
this.initKnobs(e.detail.component);
206+
this.initKnobs(component);
215207

216-
this.events.forEach((event) => {
217-
component.addEventListener(event.name, ((evt: CustomEvent) => {
218-
const s = '-changed';
219-
if (event.name.endsWith(s)) {
220-
const { knob } = this.getKnob(event.name.replace(s, ''));
221-
if (knob) {
222-
this.syncKnob(component, knob);
223-
}
224-
}
208+
this.initEvents(component);
209+
}
210+
211+
private initEvents(component: HTMLElement) {
212+
const controller = this.eventsController;
213+
if (controller) {
214+
controller.clear();
215+
this.removeController(controller);
216+
}
225217

226-
this.eventLog = [...this.eventLog, evt];
227-
}) as EventListener);
228-
});
218+
this.eventsController = new EventsController(this, component, this.events);
229219
}
230220

231221
private _onCssChanged(e: CustomEvent): void {

src/controllers/events-controller.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { ReactiveController, ReactiveControllerHost } from 'lit';
2+
import { EventInfo } from '../lib/types.js';
3+
import { HasKnobs } from '../api-demo-knobs-mixin.js';
4+
5+
type EventsHost = HTMLElement & ReactiveControllerHost & HasKnobs;
6+
7+
export class EventsController implements ReactiveController {
8+
host: EventsHost;
9+
10+
private _log: CustomEvent[] = [];
11+
12+
get log(): CustomEvent[] {
13+
return this._log;
14+
}
15+
16+
set log(log: CustomEvent[]) {
17+
this._log = log;
18+
19+
if (this.host.isConnected) {
20+
this.host.requestUpdate();
21+
}
22+
}
23+
24+
constructor(
25+
host: ReactiveControllerHost,
26+
component: HTMLElement,
27+
events: EventInfo[]
28+
) {
29+
(this.host = host as EventsHost).addController(this);
30+
31+
events.forEach(({ name }) => {
32+
component.addEventListener(name, ((evt: CustomEvent) => {
33+
const s = '-changed';
34+
if (name.endsWith(s)) {
35+
const { knob } = this.host.getKnob(name.replace(s, ''));
36+
if (knob) {
37+
this.host.syncKnob(component, knob);
38+
}
39+
}
40+
41+
this.log = [...this.log, evt];
42+
}) as EventListener);
43+
});
44+
}
45+
46+
clear() {
47+
this.log = [];
48+
}
49+
50+
hostDisconnected() {
51+
this.clear();
52+
}
53+
}

0 commit comments

Comments
 (0)