feat: more/improved styles, moved settings
This commit is contained in:
@@ -36,7 +36,7 @@ export default class Beat implements IPublisher<BeatEvents>, BeatLike {
|
|||||||
private looping: boolean;
|
private looping: boolean;
|
||||||
|
|
||||||
constructor(options?: BeatInitOptions) {
|
constructor(options?: BeatInitOptions) {
|
||||||
this.key = `Beat-${Beat.count}`;
|
this.key = `B-${Beat.count}`;
|
||||||
this.name = options?.name ?? this.key;
|
this.name = options?.name ?? this.key;
|
||||||
this.setTimeSignature({up: options?.timeSig?.up ?? 4, down: options?.timeSig?.down ?? 4});
|
this.setTimeSignature({up: options?.timeSig?.up ?? 4, down: options?.timeSig?.down ?? 4});
|
||||||
this.setBarCount(options?.bars ?? 4);
|
this.setBarCount(options?.bars ?? 4);
|
||||||
|
|||||||
@@ -3,26 +3,6 @@
|
|||||||
padding-left: 1em;
|
padding-left: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.beat-settings-btn {
|
|
||||||
cursor: pointer;
|
|
||||||
line-height: 2em;
|
|
||||||
display: inline-block;
|
|
||||||
height: 2em;
|
|
||||||
border: 1px solid grey;
|
|
||||||
border-radius: 1em;
|
|
||||||
user-select: none;
|
|
||||||
transition: background-color 150ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
.beat-settings-btn:hover {
|
|
||||||
background-color: #eaeaea;
|
|
||||||
}
|
|
||||||
|
|
||||||
.beat-settings-btn.active {
|
|
||||||
background-color: lightgrey;
|
|
||||||
transition: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.beat-unit-block {
|
.beat-unit-block {
|
||||||
height: 2em;
|
height: 2em;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import {IPublisher} from "../../../Publisher";
|
|||||||
import ISubscriber from "../../../Subscriber";
|
import ISubscriber from "../../../Subscriber";
|
||||||
import BeatUnitView from "./BeatUnit/BeatUnitView";
|
import BeatUnitView from "./BeatUnit/BeatUnitView";
|
||||||
import "./Beat.css";
|
import "./Beat.css";
|
||||||
import BeatSettingsView from "../../BeatSettings/BeatSettingsView";
|
|
||||||
|
|
||||||
export type BeatUINodeOptions = UINodeOptions & {
|
export type BeatUINodeOptions = UINodeOptions & {
|
||||||
beat: Beat,
|
beat: Beat,
|
||||||
@@ -13,8 +12,6 @@ export type BeatUINodeOptions = UINodeOptions & {
|
|||||||
export default class BeatView extends UINode implements ISubscriber {
|
export default class BeatView extends UINode implements ISubscriber {
|
||||||
private beat: Beat;
|
private beat: Beat;
|
||||||
private title!: HTMLHeadingElement;
|
private title!: HTMLHeadingElement;
|
||||||
private settingsView!: BeatSettingsView;
|
|
||||||
private settingsToggleButton!: HTMLDivElement;
|
|
||||||
private beatUnitViews: BeatUnitView[] = [];
|
private beatUnitViews: BeatUnitView[] = [];
|
||||||
private beatUnitViewBlock: HTMLElement | null = null;
|
private beatUnitViewBlock: HTMLElement | null = null;
|
||||||
private lastHoveredBeatUnitView: BeatUnitView | null = null;
|
private lastHoveredBeatUnitView: BeatUnitView | null = null;
|
||||||
@@ -45,15 +42,6 @@ export default class BeatView extends UINode implements ISubscriber {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private toggleSettings() {
|
|
||||||
this.settingsView.toggleVisible();
|
|
||||||
if (this.settingsView.isOpen()) {
|
|
||||||
this.settingsToggleButton.classList.add("active");
|
|
||||||
} else {
|
|
||||||
this.settingsToggleButton.classList.remove("active");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private rebuildBeatUnitViews() {
|
private rebuildBeatUnitViews() {
|
||||||
const beatUnitCount = this.beat.getBarCount() * this.beat.getTimeSigUp();
|
const beatUnitCount = this.beat.getBarCount() * this.beat.getTimeSigUp();
|
||||||
this.beatUnitViews.splice(beatUnitCount, this.beatUnitViews.length - beatUnitCount);
|
this.beatUnitViews.splice(beatUnitCount, this.beatUnitViews.length - beatUnitCount);
|
||||||
@@ -148,12 +136,6 @@ export default class BeatView extends UINode implements ISubscriber {
|
|||||||
if (!this.beatUnitViewBlock) {
|
if (!this.beatUnitViewBlock) {
|
||||||
throw new Error("Beat unit block setup failed!");
|
throw new Error("Beat unit block setup failed!");
|
||||||
}
|
}
|
||||||
this.settingsView = new BeatSettingsView({beat: this.beat});
|
|
||||||
this.settingsToggleButton = UINode.make("div", {
|
|
||||||
classes: ["beat-settings-btn"],
|
|
||||||
innerText: "Settings",
|
|
||||||
onclick: () => this.toggleSettings()
|
|
||||||
});
|
|
||||||
this.node = UINode.make("div", {
|
this.node = UINode.make("div", {
|
||||||
classes: ["beat"],
|
classes: ["beat"],
|
||||||
subs: [
|
subs: [
|
||||||
@@ -164,11 +146,6 @@ export default class BeatView extends UINode implements ISubscriber {
|
|||||||
this.beatUnitViewBlock,
|
this.beatUnitViewBlock,
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
this.settingsToggleButton,
|
|
||||||
UINode.make("div", {
|
|
||||||
classes: ["beat-settings-container"],
|
|
||||||
subs: [this.settingsView.render()],
|
|
||||||
}),
|
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
return this.node;
|
return this.node;
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import ISubscriber from "../../Subscriber";
|
|||||||
import BeatGroup, {BeatGroupEvents} from "../../BeatGroup";
|
import BeatGroup, {BeatGroupEvents} from "../../BeatGroup";
|
||||||
import {IPublisher} from "../../Publisher";
|
import {IPublisher} from "../../Publisher";
|
||||||
import {BeatEvents} from "../../Beat";
|
import {BeatEvents} from "../../Beat";
|
||||||
|
import BoolBoxView from "../Widgets/BoolBox/BoolBoxView";
|
||||||
|
import BeatSettingsView from "../BeatSettings/BeatSettingsView";
|
||||||
|
|
||||||
export type BeatGroupSettingsUINodeOptions = UINodeOptions & {
|
export type BeatGroupSettingsUINodeOptions = UINodeOptions & {
|
||||||
beatGroup: BeatGroup,
|
beatGroup: BeatGroup,
|
||||||
@@ -16,8 +18,8 @@ export default class BeatGroupSettingsView extends UINode implements ISubscriber
|
|||||||
private barCountInput!: NumberInputView;
|
private barCountInput!: NumberInputView;
|
||||||
private timeSigUpInput!: NumberInputView;
|
private timeSigUpInput!: NumberInputView;
|
||||||
private loopSettingsView!: BeatLikeLoopSettingsView;
|
private loopSettingsView!: BeatLikeLoopSettingsView;
|
||||||
private autoBeatLengthCheckbox!: HTMLInputElement;
|
private autoBeatLengthCheckbox!: BoolBoxView;
|
||||||
private forceFullBarsCheckbox!: HTMLInputElement;
|
private forceFullBarsCheckbox!: BoolBoxView;
|
||||||
private autoBeatOptions!: HTMLElement;
|
private autoBeatOptions!: HTMLElement;
|
||||||
|
|
||||||
constructor(options: BeatGroupSettingsUINodeOptions) {
|
constructor(options: BeatGroupSettingsUINodeOptions) {
|
||||||
@@ -58,19 +60,10 @@ export default class BeatGroupSettingsView extends UINode implements ISubscriber
|
|||||||
setter: (input: number) => this.beatGroup.setTimeSigUp(input),
|
setter: (input: number) => this.beatGroup.setTimeSigUp(input),
|
||||||
getter: () => this.beatGroup.getTimeSigUp(),
|
getter: () => this.beatGroup.getTimeSigUp(),
|
||||||
});
|
});
|
||||||
this.autoBeatLengthCheckbox = UINode.make("input", {
|
this.autoBeatLengthCheckbox = new BoolBoxView({
|
||||||
type: "checkbox",
|
label: "Auto beat length:",
|
||||||
checked: this.beatGroup.autoBeatLengthOn(),
|
value: this.beatGroup.autoBeatLengthOn(),
|
||||||
oninput: () => {
|
onInput: (isChecked: boolean) => this.beatGroup.setIsUsingAutoBeatLength(isChecked),
|
||||||
this.beatGroup.setIsUsingAutoBeatLength(this.autoBeatLengthCheckbox.checked);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
this.forceFullBarsCheckbox = UINode.make("input", {
|
|
||||||
type: "checkbox",
|
|
||||||
checked: this.beatGroup.forcesFullBars(),
|
|
||||||
oninput: () => {
|
|
||||||
this.beatGroup.setForcesFullBars(this.forceFullBarsCheckbox.checked);
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
this.autoBeatOptions = UINode.make("div", {
|
this.autoBeatOptions = UINode.make("div", {
|
||||||
classes: ["beat-group-settings-option-group"],
|
classes: ["beat-group-settings-option-group"],
|
||||||
@@ -78,19 +71,15 @@ export default class BeatGroupSettingsView extends UINode implements ISubscriber
|
|||||||
UINode.make("div", {
|
UINode.make("div", {
|
||||||
classes: ["beat-group-settings-autobeat-option", "beat-group-settings-option"],
|
classes: ["beat-group-settings-autobeat-option", "beat-group-settings-option"],
|
||||||
subs: [
|
subs: [
|
||||||
UINode.make("label", { innerText: "Auto beat length:"}),
|
this.autoBeatLengthCheckbox.render(),
|
||||||
this.autoBeatLengthCheckbox,
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
UINode.make("div", {
|
|
||||||
classes: ["beat-group-settings-autobeat-option", "beat-group-settings-option"],
|
|
||||||
subs: [
|
|
||||||
UINode.make("label", { innerText: "Force full bars:"}),
|
|
||||||
this.forceFullBarsCheckbox,
|
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
const beatSettingsViews = [];
|
||||||
|
for (let i = 0; i < this.beatGroup.getBeatCount(); i++) {
|
||||||
|
beatSettingsViews.push(new BeatSettingsView({ beat: this.beatGroup.getBeatByIndex(i) }));
|
||||||
|
}
|
||||||
this.node = UINode.make("div", {
|
this.node = UINode.make("div", {
|
||||||
classes: ["beat-group-settings"],
|
classes: ["beat-group-settings"],
|
||||||
subs: [
|
subs: [
|
||||||
@@ -114,7 +103,8 @@ export default class BeatGroupSettingsView extends UINode implements ISubscriber
|
|||||||
UINode.make("button", {
|
UINode.make("button", {
|
||||||
innerText: "New Track",
|
innerText: "New Track",
|
||||||
onclick: () => this.beatGroup.addBeat(),
|
onclick: () => this.beatGroup.addBeat(),
|
||||||
})
|
}),
|
||||||
|
...beatSettingsViews.map(view => view.render()),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -19,4 +19,8 @@
|
|||||||
.loop-settings-option {
|
.loop-settings-option {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loop-settings-option.hide {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,7 @@ import ISubscriber from "../../Subscriber";
|
|||||||
import UINode, {UINodeOptions} from "../UINode";
|
import UINode, {UINodeOptions} from "../UINode";
|
||||||
import {BeatEvents} from "../../Beat";
|
import {BeatEvents} from "../../Beat";
|
||||||
import {IPublisher} from "../../Publisher";
|
import {IPublisher} from "../../Publisher";
|
||||||
|
import BoolBoxView from "../Widgets/BoolBox/BoolBoxView";
|
||||||
|
|
||||||
export type BeatLikeLoopSettingsViewUINodeOptions = UINodeOptions & {
|
export type BeatLikeLoopSettingsViewUINodeOptions = UINodeOptions & {
|
||||||
beatLike: BeatLike,
|
beatLike: BeatLike,
|
||||||
@@ -13,7 +14,8 @@ export type BeatLikeLoopSettingsViewUINodeOptions = UINodeOptions & {
|
|||||||
export default class BeatLikeLoopSettingsView extends UINode implements ISubscriber {
|
export default class BeatLikeLoopSettingsView extends UINode implements ISubscriber {
|
||||||
private beatLike: BeatLike;
|
private beatLike: BeatLike;
|
||||||
private loopLengthInput!: NumberInputView;
|
private loopLengthInput!: NumberInputView;
|
||||||
private loopCheckbox!: HTMLInputElement;
|
private loopCheckbox!: BoolBoxView;
|
||||||
|
private loopLengthSection!: HTMLDivElement;
|
||||||
|
|
||||||
constructor(options: BeatLikeLoopSettingsViewUINodeOptions) {
|
constructor(options: BeatLikeLoopSettingsViewUINodeOptions) {
|
||||||
super(options);
|
super(options);
|
||||||
@@ -32,7 +34,12 @@ export default class BeatLikeLoopSettingsView extends UINode implements ISubscri
|
|||||||
if (event === BeatEvents.LoopLengthChanged) {
|
if (event === BeatEvents.LoopLengthChanged) {
|
||||||
this.loopLengthInput.setValue(this.beatLike.getLoopLength());
|
this.loopLengthInput.setValue(this.beatLike.getLoopLength());
|
||||||
} else if (event === BeatEvents.DisplayTypeChanged) {
|
} else if (event === BeatEvents.DisplayTypeChanged) {
|
||||||
this.loopCheckbox.checked = this.beatLike.isLooping();
|
this.loopCheckbox.setValue(this.beatLike.isLooping());
|
||||||
|
if (this.beatLike.isLooping()) {
|
||||||
|
this.loopLengthSection.classList.remove("hide");
|
||||||
|
} else {
|
||||||
|
this.loopLengthSection.classList.add("hide");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,34 +51,36 @@ export default class BeatLikeLoopSettingsView extends UINode implements ISubscri
|
|||||||
onIncrement: () => this.beatLike.setLoopLength(this.beatLike.getLoopLength() + 1),
|
onIncrement: () => this.beatLike.setLoopLength(this.beatLike.getLoopLength() + 1),
|
||||||
onNewInput: (input: number) => this.beatLike.setLoopLength(input),
|
onNewInput: (input: number) => this.beatLike.setLoopLength(input),
|
||||||
});
|
});
|
||||||
this.loopCheckbox = UINode.make("input", {
|
this.loopCheckbox = new BoolBoxView({
|
||||||
classes: ["loop-settings-loop-toggle"],
|
label: "On:",
|
||||||
type: "checkbox",
|
value: this.beatLike.isLooping(),
|
||||||
checked: this.beatLike.isLooping(),
|
onInput: (isChecked: boolean) => this.beatLike.setLooping(isChecked),
|
||||||
oninput: (event: Event) => {
|
|
||||||
this.beatLike.setLooping((event.target as HTMLInputElement).checked);
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
this.loopLengthSection = UINode.make("div", {
|
||||||
|
classes: ["loop-settings-option"],
|
||||||
|
subs: [
|
||||||
|
this.loopLengthInput.render(),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
if (this.beatLike.isLooping()) {
|
||||||
|
this.loopLengthSection.classList.remove("hide");
|
||||||
|
} else {
|
||||||
|
this.loopLengthSection.classList.add("hide");
|
||||||
|
}
|
||||||
this.node = UINode.make("div", {
|
this.node = UINode.make("div", {
|
||||||
classes: ["loop-settings"],
|
classes: ["loop-settings"],
|
||||||
subs: [
|
subs: [
|
||||||
UINode.make("p", {innerText: "Looping:"}),
|
UINode.make("p", {innerText: "Global looping settings:"}),
|
||||||
UINode.make("div", {
|
UINode.make("div", {
|
||||||
classes: ["loop-settings-option-group"],
|
classes: ["loop-settings-option-group"],
|
||||||
subs: [
|
subs: [
|
||||||
UINode.make("div", {
|
UINode.make("div", {
|
||||||
classes: ["loop-settings-option"],
|
classes: ["loop-settings-option"],
|
||||||
subs: [
|
subs: [
|
||||||
this.loopLengthInput.render(),
|
this.loopCheckbox.render(),
|
||||||
],
|
|
||||||
}),
|
|
||||||
UINode.make("div", {
|
|
||||||
classes: ["loop-settings-option"],
|
|
||||||
subs: [
|
|
||||||
UINode.make("label", {innerText: "On:"}),
|
|
||||||
this.loopCheckbox,
|
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
this.loopLengthSection,
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,13 +1,8 @@
|
|||||||
.beat-settings {
|
.beat-settings {
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
display: none;
|
|
||||||
text-align: center;
|
|
||||||
width: 40em;
|
|
||||||
justify-content: space-evenly;
|
|
||||||
}
|
|
||||||
|
|
||||||
.beat-settings.visible {
|
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
text-align: center;
|
||||||
|
justify-content: space-evenly;
|
||||||
}
|
}
|
||||||
|
|
||||||
.beat-settings-time-sig-up {
|
.beat-settings-time-sig-up {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import "./BeatSettings.css";
|
|||||||
import Beat, {BeatEvents} from "../../Beat";
|
import Beat, {BeatEvents} from "../../Beat";
|
||||||
import UINode, {UINodeOptions} from "../UINode";
|
import UINode, {UINodeOptions} from "../UINode";
|
||||||
import ISubscriber from "../../Subscriber";
|
import ISubscriber from "../../Subscriber";
|
||||||
import NumberInputView from "../Widgets/NumberInput/NumberInputView";
|
|
||||||
import BeatLikeLoopSettingsView from "../BeatLikeLoopSettings/BeatLikeLoopSettingsView";
|
import BeatLikeLoopSettingsView from "../BeatLikeLoopSettings/BeatLikeLoopSettingsView";
|
||||||
import {IPublisher} from "../../Publisher";
|
import {IPublisher} from "../../Publisher";
|
||||||
|
|
||||||
@@ -32,19 +31,6 @@ export default class BeatSettingsView extends UINode implements ISubscriber {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleVisible(): void {
|
|
||||||
this.visible = !this.visible;
|
|
||||||
if (this.visible) {
|
|
||||||
this.node?.classList.add("visible");
|
|
||||||
} else {
|
|
||||||
this.node?.classList.remove("visible");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isOpen(): boolean {
|
|
||||||
return this.visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
rebuild(): HTMLElement {
|
rebuild(): HTMLElement {
|
||||||
this.loopSettingsView = new BeatLikeLoopSettingsView({beatLike: this.beat});
|
this.loopSettingsView = new BeatLikeLoopSettingsView({beatLike: this.beat});
|
||||||
this.nameInput = UINode.make("input", {
|
this.nameInput = UINode.make("input", {
|
||||||
|
|||||||
@@ -49,52 +49,6 @@
|
|||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"] {
|
|
||||||
position: relative;
|
|
||||||
width: 2em;
|
|
||||||
height: 1em;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
-webkit-appearance: none;
|
|
||||||
-moz-appearance: none;
|
|
||||||
appearance: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="checkbox"]::before {
|
|
||||||
width: 2em;
|
|
||||||
height: 1em;
|
|
||||||
border-radius: 1em;
|
|
||||||
background-color: var(--color-ui-accent-dark);
|
|
||||||
display: block;
|
|
||||||
content: "";
|
|
||||||
z-index: 0;
|
|
||||||
position: absolute;
|
|
||||||
transition: background-color 200ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="checkbox"]:checked::before {
|
|
||||||
background-color: var(--color-ui-accent-light);
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="checkbox"]::after {
|
|
||||||
position: absolute;
|
|
||||||
width: 1em;
|
|
||||||
height: 1em;
|
|
||||||
border-radius: 1em;
|
|
||||||
border-color: var(--color-ui-neutral-dark);
|
|
||||||
border-width: 1px;
|
|
||||||
background-color: var(--color-ui-neutral-light);
|
|
||||||
display: block;
|
|
||||||
content: "";
|
|
||||||
z-index: 1;
|
|
||||||
right: 1em;
|
|
||||||
transition: right 200ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="checkbox"]:checked::after {
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
* {
|
* {
|
||||||
user-drag: none;
|
user-drag: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
|||||||
61
src/ui/Widgets/BoolBox/BoolBox.css
Normal file
61
src/ui/Widgets/BoolBox/BoolBox.css
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
.bool-box {
|
||||||
|
height: 1.1em;
|
||||||
|
margin: 0.5em;
|
||||||
|
line-height: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bool-box-label {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.bool-box-checkbox[type="checkbox"] {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
width: 2em;
|
||||||
|
height: 1em;
|
||||||
|
padding: 0;
|
||||||
|
top: 0.1em;
|
||||||
|
margin: 0;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.bool-box-checkbox[type="checkbox"]::before {
|
||||||
|
width: 2em;
|
||||||
|
height: 1em;
|
||||||
|
border-radius: 1em;
|
||||||
|
background-color: var(--color-ui-accent-dark);
|
||||||
|
display: inline-block;
|
||||||
|
content: "";
|
||||||
|
z-index: 0;
|
||||||
|
position: absolute;
|
||||||
|
transition: background-color 200ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.bool-box-checkbox[type="checkbox"]:checked::before {
|
||||||
|
background-color: var(--color-ui-accent-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
input.bool-box-checkbox[type="checkbox"]::after {
|
||||||
|
position: absolute;
|
||||||
|
width: 1.05em;
|
||||||
|
height: 1.05em;
|
||||||
|
border-radius: 1em;
|
||||||
|
border-color: var(--color-ui-neutral-dark);
|
||||||
|
border-width: 0.05em;
|
||||||
|
border-style: solid;
|
||||||
|
background-color: var(--color-ui-neutral-dark);
|
||||||
|
display: block;
|
||||||
|
content: "";
|
||||||
|
top: -0.075em;
|
||||||
|
z-index: 1;
|
||||||
|
left: -0.075em;
|
||||||
|
transition: left 200ms, background-color 200ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.bool-box-checkbox[type="checkbox"]:checked::after {
|
||||||
|
left: 0.925em;
|
||||||
|
background-color: var(--color-ui-neutral-light);
|
||||||
|
}
|
||||||
59
src/ui/Widgets/BoolBox/BoolBoxView.ts
Normal file
59
src/ui/Widgets/BoolBox/BoolBoxView.ts
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import "./BoolBox.css";
|
||||||
|
import UINode, {UINodeOptions} from "../../UINode";
|
||||||
|
|
||||||
|
export type BoolBoxUINodeOptions = UINodeOptions & {
|
||||||
|
label?: string,
|
||||||
|
value?: boolean,
|
||||||
|
onInput?: (isChecked: boolean) => void,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class BoolBoxView extends UINode {
|
||||||
|
private label: string | null;
|
||||||
|
private labelElement!: HTMLLabelElement;
|
||||||
|
private checkboxElement!: HTMLInputElement;
|
||||||
|
private onInput: (isChecked: boolean) => void;
|
||||||
|
|
||||||
|
constructor(options: BoolBoxUINodeOptions) {
|
||||||
|
super(options);
|
||||||
|
this.label = options.label ?? "";
|
||||||
|
this.onInput = options.onInput ?? (() => { /* dummy */ });
|
||||||
|
}
|
||||||
|
|
||||||
|
setLabel(newLabel: string | null): void {
|
||||||
|
if (newLabel !== null) {
|
||||||
|
this.label = newLabel;
|
||||||
|
this.labelElement.innerText = newLabel;
|
||||||
|
this.labelElement.classList.add("visible");
|
||||||
|
} else {
|
||||||
|
this.label = newLabel;
|
||||||
|
this.labelElement.innerText = "";
|
||||||
|
this.labelElement.classList.remove("visible");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setValue(isChecked: boolean): void {
|
||||||
|
this.checkboxElement.checked = isChecked;
|
||||||
|
}
|
||||||
|
|
||||||
|
rebuild(): HTMLDivElement {
|
||||||
|
this.labelElement = UINode.make("label", {
|
||||||
|
classes: ["bool-box-label"],
|
||||||
|
innerText: this.label ?? "",
|
||||||
|
});
|
||||||
|
if (this.label !== null) {
|
||||||
|
this.labelElement.classList.add("visible");
|
||||||
|
}
|
||||||
|
this.checkboxElement = UINode.make("input", {
|
||||||
|
type: "checkbox",
|
||||||
|
classes: ["bool-box-checkbox"],
|
||||||
|
oninput: (event: Event) => this.onInput((event.target as HTMLInputElement).checked),
|
||||||
|
});
|
||||||
|
return UINode.make("div", {
|
||||||
|
classes: ["bool-box"],
|
||||||
|
subs: [
|
||||||
|
this.labelElement,
|
||||||
|
this.checkboxElement,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,10 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.number-input-label {
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
input[type="number"].number-input-input {
|
input[type="number"].number-input-input {
|
||||||
-webkit-appearance: textfield;
|
-webkit-appearance: textfield;
|
||||||
-moz-appearance: textfield;
|
-moz-appearance: textfield;
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ export default class NumberInputView extends UINode {
|
|||||||
type: "number",
|
type: "number",
|
||||||
classes: ["number-input-input"],
|
classes: ["number-input-input"],
|
||||||
valueAsNumber: this.value,
|
valueAsNumber: this.value,
|
||||||
oninput: (event: Event) => {
|
onblur: (event: Event) => {
|
||||||
const input = (event.target as HTMLInputElement).valueAsNumber;
|
const input = (event.target as HTMLInputElement).valueAsNumber;
|
||||||
if (!isNaN(input)) {
|
if (!isNaN(input)) {
|
||||||
if (this.onNewInput) {
|
if (this.onNewInput) {
|
||||||
|
|||||||
Reference in New Issue
Block a user