feat: improved event semantics, finally think i have a permanent solution to urls and file paths and dev servers....
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import UINode, {UINodeOptions} from "@/ui/UINode";
|
||||
import Beat, {BeatEvents} from "@/Beat";
|
||||
import {IPublisher} from "@/Publisher";
|
||||
import ISubscriber from "@/Subscriber";
|
||||
import BeatUnitView from "@/ui/BeatUnit/BeatUnitView";
|
||||
import "./Beat.css";
|
||||
@@ -9,7 +8,17 @@ export type BeatUINodeOptions = UINodeOptions & {
|
||||
beat: Beat,
|
||||
};
|
||||
|
||||
export default class BeatView extends UINode implements ISubscriber {
|
||||
const EventTypeSubscriptions = [
|
||||
BeatEvents.NewName,
|
||||
BeatEvents.NewTimeSig,
|
||||
BeatEvents.NewBarCount,
|
||||
BeatEvents.DisplayTypeChanged,
|
||||
BeatEvents.LoopLengthChanged,
|
||||
];
|
||||
|
||||
type EventTypeSubscriptions = FlatArray<typeof EventTypeSubscriptions, 1>;
|
||||
|
||||
export default class BeatView extends UINode implements ISubscriber<EventTypeSubscriptions> {
|
||||
private beat: Beat;
|
||||
private title!: HTMLHeadingElement;
|
||||
private beatUnitViews: BeatUnitView[] = [];
|
||||
@@ -34,20 +43,20 @@ export default class BeatView extends UINode implements ISubscriber {
|
||||
}
|
||||
|
||||
private setupBindings() {
|
||||
this.beat.addSubscriber(this, "all");
|
||||
this.beat.addSubscriber(this, EventTypeSubscriptions);
|
||||
}
|
||||
|
||||
notify<T extends string | number>(publisher: IPublisher<T>, event: "all" | T[] | T): void {
|
||||
if (event === BeatEvents.NewName) {
|
||||
notify(publisher: unknown, event: EventTypeSubscriptions): void {
|
||||
switch (event) {
|
||||
case BeatEvents.NewName:
|
||||
this.title.innerText = this.beat.getName();
|
||||
} else if (event === BeatEvents.NewTimeSig) {
|
||||
this.setupBeatUnits();
|
||||
} else if (event === BeatEvents.NewBarCount) {
|
||||
this.setupBeatUnits();
|
||||
} else if (event === BeatEvents.DisplayTypeChanged) {
|
||||
this.setupBeatUnits();
|
||||
} else if (event === BeatEvents.LoopLengthChanged) {
|
||||
break;
|
||||
case BeatEvents.NewTimeSig:
|
||||
case BeatEvents.NewBarCount:
|
||||
case BeatEvents.DisplayTypeChanged:
|
||||
case BeatEvents.LoopLengthChanged:
|
||||
this.setupBeatUnits();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,8 +100,9 @@ export default class BeatView extends UINode implements ISubscriber {
|
||||
} else {
|
||||
this.beatUnitViewBlock = UINode.make("div", {
|
||||
classes: ["beat-unit-block"],
|
||||
subs: [...beatUnitNodes],
|
||||
});
|
||||
}, [
|
||||
...beatUnitNodes
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,16 +150,14 @@ export default class BeatView extends UINode implements ISubscriber {
|
||||
}
|
||||
return UINode.make("div", {
|
||||
classes: ["beat"],
|
||||
subs: [
|
||||
UINode.make("div", {
|
||||
classes: ["beat-main"],
|
||||
subs: [
|
||||
this.title,
|
||||
this.beatUnitViewBlock,
|
||||
]
|
||||
}),
|
||||
],
|
||||
});
|
||||
}, [
|
||||
UINode.make("div", {
|
||||
classes: ["beat-main"],
|
||||
}, [
|
||||
this.title,
|
||||
this.beatUnitViewBlock,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,14 +3,18 @@ import BeatGroup, {BeatGroupEvents} from "@/BeatGroup";
|
||||
import BeatView from "@/ui/Beat/BeatView";
|
||||
import "./BeatGroup.css";
|
||||
import ISubscriber from "@/Subscriber";
|
||||
import {IPublisher} from "@/Publisher";
|
||||
|
||||
export type BeatGroupUINodeOptions = UINodeOptions & {
|
||||
title: string,
|
||||
beatGroup: BeatGroup,
|
||||
};
|
||||
|
||||
export default class BeatGroupView extends UINode implements ISubscriber {
|
||||
const EventTypeSubscriptions = [
|
||||
BeatGroupEvents.BeatListChanged
|
||||
];
|
||||
type EventTypeSubscriptions = FlatArray<typeof EventTypeSubscriptions, 1>;
|
||||
|
||||
export default class BeatGroupView extends UINode implements ISubscriber<EventTypeSubscriptions> {
|
||||
private title: string;
|
||||
private beatGroup: BeatGroup;
|
||||
private beatViews: BeatView[] = [];
|
||||
@@ -22,7 +26,7 @@ export default class BeatGroupView extends UINode implements ISubscriber {
|
||||
this.beatGroup.addSubscriber(this, BeatGroupEvents.BeatListChanged);
|
||||
}
|
||||
|
||||
notify<T extends string | number>(publisher: IPublisher<T>, event: "all" | T[] | T): void {
|
||||
notify(publisher: unknown, event: EventTypeSubscriptions): void {
|
||||
if (event === BeatGroupEvents.BeatListChanged) {
|
||||
this.redraw();
|
||||
}
|
||||
@@ -41,9 +45,8 @@ export default class BeatGroupView extends UINode implements ISubscriber {
|
||||
}
|
||||
return UINode.make("div", {
|
||||
classes: ["beat-group"],
|
||||
subs: [
|
||||
...this.beatViews.map(bv => bv.render())
|
||||
],
|
||||
});
|
||||
},[
|
||||
...this.beatViews.map(bv => bv.render())
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
import "./BeatGroupSettings.css";
|
||||
import UINode, {UINodeOptions} from "@/ui/UINode";
|
||||
import NumberInputView from "@/ui/Widgets/NumberInput/NumberInputView";
|
||||
import ISubscriber from "@/Subscriber";
|
||||
import ISubscriber, {SubscriptionEvent} from "@/Subscriber";
|
||||
import BeatGroup, {BeatGroupEvents} from "@/BeatGroup";
|
||||
import {IPublisher} from "@/Publisher";
|
||||
import {BeatEvents} from "@/Beat";
|
||||
import BoolBoxView from "@/ui/Widgets/BoolBox/BoolBoxView";
|
||||
import BeatSettingsView from "@/ui/BeatSettings/BeatSettingsView";
|
||||
@@ -13,21 +12,22 @@ export type BeatGroupSettingsUINodeOptions = UINodeOptions & {
|
||||
beatGroup: BeatGroup,
|
||||
};
|
||||
|
||||
export default class BeatGroupSettingsView extends UINode implements ISubscriber {
|
||||
const EventTypeSubscriptions = [
|
||||
BeatGroupEvents.BarCountChanged,
|
||||
BeatGroupEvents.TimeSigUpChanged,
|
||||
BeatEvents.DisplayTypeChanged,
|
||||
BeatGroupEvents.BeatListChanged,
|
||||
BeatGroupEvents.LockingChanged,
|
||||
BeatGroupEvents.AutoBeatSettingsChanged,
|
||||
];
|
||||
|
||||
export default class BeatGroupSettingsView extends UINode implements ISubscriber<typeof EventTypeSubscriptions> {
|
||||
private beatGroup: BeatGroup;
|
||||
private barCountInput!: NumberInputView;
|
||||
private timeSigUpInput!: NumberInputView;
|
||||
private autoBeatLengthCheckbox!: BoolBoxView;
|
||||
private beatSettingsViews: BeatSettingsView[] = [];
|
||||
private beatSettingsContainer!: HTMLDivElement;
|
||||
private static readonly EventTypeSubscriptions = [
|
||||
BeatGroupEvents.BarCountChanged,
|
||||
BeatGroupEvents.TimeSigUpChanged,
|
||||
BeatEvents.DisplayTypeChanged,
|
||||
BeatGroupEvents.BeatListChanged,
|
||||
BeatGroupEvents.LockingChanged,
|
||||
BeatGroupEvents.AutoBeatSettingsChanged,
|
||||
];
|
||||
|
||||
constructor(options: BeatGroupSettingsUINodeOptions) {
|
||||
super(options);
|
||||
@@ -38,14 +38,14 @@ export default class BeatGroupSettingsView extends UINode implements ISubscriber
|
||||
setBeatGroup(newBeatGroup: BeatGroup): void {
|
||||
this.beatGroup = newBeatGroup;
|
||||
this.setupBindings();
|
||||
BeatGroupSettingsView.EventTypeSubscriptions.forEach(eventType => this.notify(null, eventType));
|
||||
EventTypeSubscriptions.forEach(eventType => this.notify(null, eventType));
|
||||
}
|
||||
|
||||
setupBindings(): void {
|
||||
this.beatGroup.addSubscriber(this, BeatGroupSettingsView.EventTypeSubscriptions);
|
||||
this.beatGroup.addSubscriber(this, EventTypeSubscriptions);
|
||||
}
|
||||
|
||||
notify<T extends string | number>(publisher: IPublisher<T> | null, event: "all" | T[] | T): void {
|
||||
notify(publisher: unknown, event: SubscriptionEvent<typeof EventTypeSubscriptions>): void {
|
||||
switch(event) {
|
||||
case BeatGroupEvents.BarCountChanged:
|
||||
this.barCountInput.setValue(this.beatGroup.getBarCount());
|
||||
@@ -66,6 +66,8 @@ export default class BeatGroupSettingsView extends UINode implements ISubscriber
|
||||
case BeatGroupEvents.AutoBeatSettingsChanged:
|
||||
this.autoBeatLengthCheckbox.setValue(this.beatGroup.autoBeatLengthOn());
|
||||
break;
|
||||
case BeatEvents.DisplayTypeChanged:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,36 +111,32 @@ export default class BeatGroupSettingsView extends UINode implements ISubscriber
|
||||
this.remakeBeatSettingsViews();
|
||||
return UINode.make("div", {
|
||||
classes: ["beat-group-settings"],
|
||||
subs: [
|
||||
}, [
|
||||
UINode.make("div", {
|
||||
classes: ["beat-group-settings-options"],
|
||||
}, [
|
||||
UINode.make("div", {
|
||||
classes: ["beat-group-settings-options"],
|
||||
subs: [
|
||||
UINode.make("div", {
|
||||
classes: ["beat-group-settings-boxes", "beat-group-settings-option"],
|
||||
subs: [
|
||||
this.timeSigUpInput.render(),
|
||||
],
|
||||
}),
|
||||
UINode.make("div", {
|
||||
classes: ["beat-group-settings-bar-count", "beat-group-settings-option"],
|
||||
subs: [
|
||||
this.barCountInput.render(),
|
||||
],
|
||||
}),
|
||||
UINode.make("div", {
|
||||
classes: ["beat-group-settings-bar-count", "beat-group-settings-option"],
|
||||
subs: [
|
||||
this.autoBeatLengthCheckbox.render(),
|
||||
],
|
||||
}),
|
||||
new ActionButtonView({
|
||||
label: "New Track",
|
||||
onClick: () => this.beatGroup.addBeat(),
|
||||
}).render(),
|
||||
this.beatSettingsContainer,
|
||||
],
|
||||
}),
|
||||
],
|
||||
});
|
||||
classes: ["beat-group-settings-boxes", "beat-group-settings-option"],
|
||||
}, [
|
||||
this.timeSigUpInput.render(),
|
||||
]),
|
||||
UINode.make("div", {
|
||||
classes: ["beat-group-settings-bar-count", "beat-group-settings-option"]
|
||||
,
|
||||
}, [
|
||||
this.barCountInput.render(),
|
||||
]),
|
||||
UINode.make("div", {
|
||||
classes: ["beat-group-settings-bar-count", "beat-group-settings-option"],
|
||||
}, [
|
||||
this.autoBeatLengthCheckbox.render(),
|
||||
]),
|
||||
new ActionButtonView({
|
||||
label: "New Track",
|
||||
onClick: () => this.beatGroup.addBeat(),
|
||||
}).render(),
|
||||
this.beatSettingsContainer,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
import "./BeatSettings.css";
|
||||
import Beat, {BeatEvents} from "@/Beat";
|
||||
import UINode, {UINodeOptions} from "@/ui/UINode";
|
||||
import ISubscriber from "@/Subscriber";
|
||||
import {IPublisher, ISubscription} from "@/Publisher";
|
||||
import ISubscriber, {SubscriptionEvent} from "@/Subscriber";
|
||||
import {ISubscription} from "@/Publisher";
|
||||
import NumberInputView from "@/ui/Widgets/NumberInput/NumberInputView";
|
||||
import BoolBoxView from "@/ui/Widgets/BoolBox/BoolBoxView";
|
||||
import ActionButtonView from "@/ui/Widgets/ActionButton/ActionButtonView";
|
||||
@@ -11,7 +11,13 @@ export type BeatSettingsViewUINodeOptions = UINodeOptions & {
|
||||
beat: Beat,
|
||||
};
|
||||
|
||||
export default class BeatSettingsView extends UINode implements ISubscriber {
|
||||
const EventTypeSubscriptions = [
|
||||
BeatEvents.NewName,
|
||||
BeatEvents.LoopLengthChanged,
|
||||
BeatEvents.DisplayTypeChanged,
|
||||
];
|
||||
|
||||
export default class BeatSettingsView extends UINode implements ISubscriber<typeof EventTypeSubscriptions> {
|
||||
private beat: Beat;
|
||||
private loopLengthInput!: NumberInputView;
|
||||
private bakeButton!: ActionButtonView;
|
||||
@@ -37,18 +43,19 @@ export default class BeatSettingsView extends UINode implements ISubscriber {
|
||||
this.sub.unbind();
|
||||
this.beat = beat;
|
||||
this.setupBindings();
|
||||
this.notify(null, BeatEvents.NewName);
|
||||
this.notify(null, BeatEvents.LoopLengthChanged);
|
||||
this.notify(null, BeatEvents.DisplayTypeChanged);
|
||||
EventTypeSubscriptions.forEach(eventType => this.notify(null, eventType));
|
||||
}
|
||||
|
||||
notify<T extends string | number>(publisher: IPublisher<T> | null, event: "all" | T[] | T): void {
|
||||
if (event === BeatEvents.NewName) {
|
||||
notify(publisher: unknown, event: SubscriptionEvent<typeof EventTypeSubscriptions>): void {
|
||||
switch(event) {
|
||||
case BeatEvents.NewName:
|
||||
this.titleInput.value = this.beat.getName();
|
||||
this.titleDisplay.innerText = this.beat.getName();
|
||||
} else if (event === BeatEvents.LoopLengthChanged) {
|
||||
break;
|
||||
case BeatEvents.LoopLengthChanged:
|
||||
this.loopLengthInput.setValue(this.beat.getLoopLength());
|
||||
} else if (event === BeatEvents.DisplayTypeChanged) {
|
||||
break;
|
||||
case BeatEvents.DisplayTypeChanged:
|
||||
this.loopCheckbox.setValue(this.beat.isLooping());
|
||||
this.bakeButton.setDisabled(!this.beat.isLooping());
|
||||
if (this.beat.isLooping()) {
|
||||
@@ -56,6 +63,7 @@ export default class BeatSettingsView extends UINode implements ISubscriber {
|
||||
} else {
|
||||
this.loopLengthSection.classList.add("hide");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,10 +110,9 @@ export default class BeatSettingsView extends UINode implements ISubscriber {
|
||||
});
|
||||
this.loopLengthSection = UINode.make("div", {
|
||||
classes: ["loop-settings-option"],
|
||||
subs: [
|
||||
this.loopLengthInput.render(),
|
||||
],
|
||||
});
|
||||
}, [
|
||||
this.loopLengthInput.render(),
|
||||
]);
|
||||
if (this.beat.isLooping()) {
|
||||
this.loopLengthSection.classList.remove("hide");
|
||||
} else {
|
||||
@@ -113,28 +120,25 @@ export default class BeatSettingsView extends UINode implements ISubscriber {
|
||||
}
|
||||
return UINode.make("div", {
|
||||
classes: ["beat-settings"],
|
||||
subs: [
|
||||
this.titleDisplay,
|
||||
}, [
|
||||
this.titleDisplay,
|
||||
UINode.make("div", {
|
||||
classes: ["beat-settings-lower"],
|
||||
}, [
|
||||
this.bakeButton.render(),
|
||||
new ActionButtonView({
|
||||
icon: "trash",
|
||||
type: "secondary",
|
||||
alt: "Delete Track",
|
||||
onClick: () => this.beat.delete(),
|
||||
}).render(),
|
||||
UINode.make("div", {
|
||||
classes: ["beat-settings-lower"],
|
||||
subs: [
|
||||
this.bakeButton.render(),
|
||||
new ActionButtonView({
|
||||
icon: "trash",
|
||||
type: "secondary",
|
||||
alt: "Delete Track",
|
||||
onClick: () => this.beat.delete(),
|
||||
}).render(),
|
||||
UINode.make("div", {
|
||||
classes: ["loop-settings"],
|
||||
subs: [
|
||||
this.loopCheckbox.render(),
|
||||
]
|
||||
}),
|
||||
this.loopLengthSection,
|
||||
]
|
||||
}),
|
||||
],
|
||||
});
|
||||
classes: ["loop-settings"],
|
||||
}, [
|
||||
this.loopCheckbox.render(),
|
||||
]),
|
||||
this.loopLengthSection,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import BeatUnit, {BeatUnitEvents, BeatUnitType} from "@/BeatUnit";
|
||||
import BeatUnit, {BeatUnitEvent, BeatUnitType} from "@/BeatUnit";
|
||||
import ISubscriber from "@/Subscriber";
|
||||
import UINode, {UINodeOptions} from "@/ui/UINode";
|
||||
import {IPublisher, ISubscription, Publisher} from "@/Publisher";
|
||||
@@ -8,10 +8,17 @@ export type BeatUnitUINodeOptions = UINodeOptions & {
|
||||
beatUnit: BeatUnit,
|
||||
};
|
||||
|
||||
export default class BeatUnitView extends UINode implements ISubscriber {
|
||||
const EventTypeSubscriptions = [
|
||||
BeatUnitEvent.On,
|
||||
BeatUnitEvent.Off,
|
||||
BeatUnitEvent.TypeChange,
|
||||
];
|
||||
type EventTypeSubscriptions = FlatArray<typeof EventTypeSubscriptions, 1>;
|
||||
|
||||
export default class BeatUnitView extends UINode implements ISubscriber<EventTypeSubscriptions> {
|
||||
private beatUnit: BeatUnit;
|
||||
private subscription: ISubscription | null = null;
|
||||
private publisher: IPublisher<BeatUnitEvents> = new Publisher<BeatUnitEvents, BeatUnitView>(this);
|
||||
private publisher: IPublisher<BeatUnitEvent> = new Publisher<BeatUnitEvent, BeatUnitView>(this);
|
||||
private touchTimeout: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
|
||||
@@ -24,13 +31,13 @@ export default class BeatUnitView extends UINode implements ISubscriber {
|
||||
setUnit(beatUnit: BeatUnit): void {
|
||||
this.beatUnit = beatUnit;
|
||||
this.setupBindings();
|
||||
this.notify(this.publisher, beatUnit.isOn() ? BeatUnitEvents.On : BeatUnitEvents.Off);
|
||||
this.notify(this.publisher, BeatUnitEvents.TypeChange);
|
||||
this.notify(this.publisher, beatUnit.isOn() ? BeatUnitEvent.On : BeatUnitEvent.Off);
|
||||
this.notify(this.publisher, BeatUnitEvent.TypeChange);
|
||||
}
|
||||
|
||||
private setupBindings() {
|
||||
this.subscription?.unbind();
|
||||
this.subscription = this.beatUnit.addSubscriber(this, "all");
|
||||
this.subscription = this.beatUnit.addSubscriber(this, EventTypeSubscriptions);
|
||||
this.onMouseDown((ev: MouseEvent) => {
|
||||
if (ev.button === 1) {
|
||||
this.beatUnit.rotateType();
|
||||
@@ -40,7 +47,7 @@ export default class BeatUnitView extends UINode implements ISubscriber {
|
||||
this.touchTimeout = setTimeout(() => {
|
||||
this.beatUnit.rotateType();
|
||||
this.touchTimeout = null;
|
||||
}, 600);
|
||||
}, 400);
|
||||
});
|
||||
this.getNode().addEventListener("touchend", () => {
|
||||
if (this.touchTimeout) {
|
||||
@@ -62,12 +69,15 @@ export default class BeatUnitView extends UINode implements ISubscriber {
|
||||
this.beatUnit.setOn(false);
|
||||
}
|
||||
|
||||
notify<T extends string | number>(publisher: IPublisher<T>, event: "all" | T[] | T): void {
|
||||
if (event === BeatUnitEvents.On) {
|
||||
notify(publisher: unknown, event: EventTypeSubscriptions): void {
|
||||
switch (event) {
|
||||
case BeatUnitEvent.On:
|
||||
this.getNode().classList.add("beat-unit-on");
|
||||
} else if (event === BeatUnitEvents.Off) {
|
||||
break;
|
||||
case BeatUnitEvent.Off:
|
||||
this.getNode().classList.remove("beat-unit-on");
|
||||
} else if (event === BeatUnitEvents.TypeChange) {
|
||||
break;
|
||||
case BeatUnitEvent.TypeChange:
|
||||
switch (this.beatUnit.getType()) {
|
||||
case BeatUnitType.Normal:
|
||||
this.getNode().classList.remove("beat-unit-ghost");
|
||||
@@ -82,6 +92,7 @@ export default class BeatUnitView extends UINode implements ISubscriber {
|
||||
this.getNode().classList.add("beat-unit-accent");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,13 +15,13 @@ export default class RootView extends UINode {
|
||||
private beatGroupView: BeatGroupView;
|
||||
private mainBeatGroup: BeatGroup;
|
||||
private beatGroupSettingsView!: BeatGroupSettingsView;
|
||||
private sidebar!: HTMLDivElement;
|
||||
|
||||
|
||||
constructor(options: RootUINodeOptions) {
|
||||
super(options);
|
||||
this.mainBeatGroup = options.mainBeatGroup ?? RootView.defaultMainBeatGroup();
|
||||
this.beatGroupView = new BeatGroupView({title: options.title, beatGroup: this.mainBeatGroup});
|
||||
this.beatGroupSettingsView = new BeatGroupSettingsView({beatGroup: this.mainBeatGroup});
|
||||
this.title = options.title;
|
||||
}
|
||||
|
||||
@@ -47,68 +47,77 @@ export default class RootView extends UINode {
|
||||
this.getNode().classList.toggle("vertical-mode");
|
||||
}
|
||||
|
||||
build(): HTMLElement {
|
||||
this.beatGroupSettingsView = new BeatGroupSettingsView({beatGroup: this.mainBeatGroup});
|
||||
const sidebarMain = UINode.make("div", {
|
||||
classes: ["root-settings"],
|
||||
subs: [
|
||||
UINode.make("h1", {innerText: this.title, classes: ["root-title"]}),
|
||||
this.beatGroupSettingsView.render(),
|
||||
]
|
||||
});
|
||||
const sidebarStrip = UINode.make("div", {
|
||||
classes: ["root-sidebar-toggle"],
|
||||
subs: [
|
||||
UINode.make("div", {
|
||||
classes: ["root-quick-access-button"],
|
||||
subs: [new IconView({iconName: "list", color: "var(--color-ui-neutral-dark)"}).render()],
|
||||
onclick: () => this.toggleSidebar(),
|
||||
}),
|
||||
UINode.make("div", {
|
||||
classes: ["root-quick-access-button"],
|
||||
subs: [new IconView({iconName: "arrowClockwise", color: "var(--color-ui-neutral-dark)"}).render()],
|
||||
onclick: () => this.toggleOrientation(),
|
||||
}),
|
||||
UINode.make("div", {
|
||||
classes: ["root-quick-access-button"],
|
||||
subs: [new IconView({iconName: "snowflake", color: "var(--color-ui-neutral-dark)"}).render()],
|
||||
onclick: () => this.mainBeatGroup.bakeLoops(),
|
||||
}),
|
||||
UINode.make("div", {
|
||||
classes: ["root-quick-access-button"],
|
||||
title: "Reset all",
|
||||
subs: [new IconView({iconName: "trash", color: "var(--color-ui-neutral-dark)"}).render()],
|
||||
onclick: () => {
|
||||
this.mainBeatGroup = RootView.defaultMainBeatGroup();
|
||||
this.beatGroupSettingsView.setBeatGroup(this.mainBeatGroup);
|
||||
this.beatGroupView.setBeatGroup(this.mainBeatGroup);
|
||||
},
|
||||
}),
|
||||
]
|
||||
});
|
||||
this.sidebar = UINode.make("div", {
|
||||
classes: ["root-sidebar"],
|
||||
subs: [
|
||||
sidebarMain,
|
||||
sidebarStrip,
|
||||
]
|
||||
});
|
||||
private buildSidebarStrip(): HTMLElement {
|
||||
return UINode.make("div", {
|
||||
classes: ["root", "sidebar-visible"],
|
||||
subs: [
|
||||
this.sidebar,
|
||||
UINode.make("div", {
|
||||
classes: ["root-beat-stage-container"],
|
||||
subs: [
|
||||
UINode.make("div", {
|
||||
classes: ["root-beat-stage"],
|
||||
subs: [
|
||||
this.beatGroupView.render(),
|
||||
],
|
||||
})
|
||||
]
|
||||
})
|
||||
],
|
||||
});
|
||||
classes: ["root-sidebar-toggle"],
|
||||
}, [
|
||||
UINode.make("div", {
|
||||
classes: ["root-quick-access-button"],
|
||||
onclick: () => this.toggleSidebar(),
|
||||
}, [
|
||||
new IconView({
|
||||
iconName: "list",
|
||||
color: "var(--color-ui-neutral-dark)"
|
||||
}).render()
|
||||
]),
|
||||
UINode.make("div", {
|
||||
classes: ["root-quick-access-button"],
|
||||
onclick: () => this.toggleOrientation(),
|
||||
}, [
|
||||
new IconView({
|
||||
iconName: "arrowClockwise",
|
||||
color: "var(--color-ui-neutral-dark)"
|
||||
}).render(),
|
||||
]),
|
||||
UINode.make("div", {
|
||||
classes: ["root-quick-access-button"],
|
||||
onclick: () => this.mainBeatGroup.bakeLoops(),
|
||||
}, [
|
||||
new IconView({
|
||||
iconName: "snowflake",
|
||||
color: "var(--color-ui-neutral-dark)"
|
||||
}).render(),
|
||||
]),
|
||||
UINode.make("div", {
|
||||
classes: ["root-quick-access-button"],
|
||||
title: "Reset all",
|
||||
onclick: () => {
|
||||
this.mainBeatGroup = RootView.defaultMainBeatGroup();
|
||||
this.beatGroupSettingsView.setBeatGroup(this.mainBeatGroup);
|
||||
this.beatGroupView.setBeatGroup(this.mainBeatGroup);
|
||||
},
|
||||
}, [
|
||||
new IconView({
|
||||
iconName: "trash",
|
||||
color: "var(--color-ui-neutral-dark)"
|
||||
}).render()
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
private buildSidebar(): HTMLElement {
|
||||
return (
|
||||
UINode.make("div", {classes: ["root-sidebar"]}, [
|
||||
UINode.make("div", {classes: ["root-settings"]}, [
|
||||
UINode.make("h1", {classes: ["root-title"], innerText: this.title}, [
|
||||
this.beatGroupSettingsView.render(),
|
||||
]),
|
||||
this.buildSidebarStrip(),
|
||||
]),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
build(): HTMLElement {
|
||||
return (
|
||||
UINode.make("div", {classes: ["root", "sidebar-visible"]}, [
|
||||
this.buildSidebar(),
|
||||
UINode.make("div", {classes: ["root-beat-stage-container"]}, [
|
||||
UINode.make("div", {classes: ["root-beat-stage"]}, [
|
||||
this.beatGroupView.render(),
|
||||
])
|
||||
])
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -50,20 +50,22 @@ export default abstract class UINode {
|
||||
T extends keyof HTMLElementTagNameMap,
|
||||
K extends keyof HTMLElementTagNameMap[T]>(
|
||||
type: T,
|
||||
attributes: IRenderAttributes<T, K>
|
||||
attributes: IRenderAttributes<T, K>,
|
||||
subElements?: HTMLElement[],
|
||||
): HTMLElementTagNameMap[T] {
|
||||
const element = document.createElement(type);
|
||||
if (attributes) {
|
||||
for (const key in attributes) {
|
||||
if (key === "classes") {
|
||||
element.classList.add(...attributes[key]!);
|
||||
} else if (key === "subs") {
|
||||
element.append(...attributes.subs!);
|
||||
} else {
|
||||
element[key as keyof HTMLElementTagNameMap[T]] = (attributes as any)[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (subElements) {
|
||||
element.append(...subElements);
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user