added root path alias, icons, improved framework semantics
This commit is contained in:
10
src/Beat.ts
10
src/Beat.ts
@@ -1,8 +1,8 @@
|
|||||||
import BeatUnit from "./BeatUnit";
|
import BeatUnit from "@/BeatUnit";
|
||||||
import {IPublisher, Publisher} from "./Publisher";
|
import {IPublisher, Publisher} from "@/Publisher";
|
||||||
import ISubscriber from "./Subscriber";
|
import ISubscriber from "@/Subscriber";
|
||||||
import BeatLike from "./BeatLike";
|
import BeatLike from "@/BeatLike";
|
||||||
import {isPosInt} from "./utils";
|
import {isPosInt} from "@/utils";
|
||||||
|
|
||||||
export type BeatInitOptions = {
|
export type BeatInitOptions = {
|
||||||
timeSig?: {
|
timeSig?: {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import Beat, {BeatEvents, BeatInitOptions} from "./Beat";
|
import Beat, {BeatEvents, BeatInitOptions} from "@/Beat";
|
||||||
import {IPublisher, Publisher} from "./Publisher";
|
import {IPublisher, Publisher} from "@/Publisher";
|
||||||
import ISubscriber from "./Subscriber";
|
import ISubscriber from "@/Subscriber";
|
||||||
import BeatLike from "./BeatLike";
|
import BeatLike from "@/BeatLike";
|
||||||
import {greatestCommonDivisor, isPosInt} from "./utils";
|
import {greatestCommonDivisor, isPosInt} from "@/utils";
|
||||||
|
|
||||||
type BeatGroupInitOptions = {
|
type BeatGroupInitOptions = {
|
||||||
barCount: number;
|
barCount: number;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import BeatGroup from "./BeatGroup";
|
import BeatGroup from "@/BeatGroup";
|
||||||
import RootView from "./ui/Root/RootView";
|
import RootView from "@/ui/Root/RootView";
|
||||||
import "./ui/global.css";
|
import "@/ui/global.css";
|
||||||
|
|
||||||
const defaultSettings = {
|
const defaultSettings = {
|
||||||
barCount: 2,
|
barCount: 2,
|
||||||
|
|||||||
12
src/types.d.ts
vendored
Normal file
12
src/types.d.ts
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
declare module "*.gif" {
|
||||||
|
const value: string;
|
||||||
|
export = value;
|
||||||
|
}
|
||||||
|
declare module "*.png" {
|
||||||
|
const value: string;
|
||||||
|
export = value;
|
||||||
|
}
|
||||||
|
declare module "*.svg" {
|
||||||
|
const value: string;
|
||||||
|
export = value;
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import BeatUnit, {BeatUnitEvents, BeatUnitType} from "../../../../BeatUnit";
|
import BeatUnit, {BeatUnitEvents, BeatUnitType} from "@/BeatUnit";
|
||||||
import ISubscriber from "../../../../Subscriber";
|
import ISubscriber from "@/Subscriber";
|
||||||
import UINode, {UINodeOptions} from "../../../UINode";
|
import UINode, {UINodeOptions} from "@/ui/UINode";
|
||||||
import {IPublisher, ISubscription, Publisher} from "../../../../Publisher";
|
import {IPublisher, ISubscription, Publisher} from "@/Publisher";
|
||||||
import "./BeatUnit.css";
|
import "./BeatUnit.css";
|
||||||
|
|
||||||
export type BeatUnitUINodeOptions = UINodeOptions & {
|
export type BeatUnitUINodeOptions = UINodeOptions & {
|
||||||
@@ -29,6 +29,12 @@ export default class BeatUnitView extends UINode implements ISubscriber {
|
|||||||
private setupBindings() {
|
private setupBindings() {
|
||||||
this.subscription?.unbind();
|
this.subscription?.unbind();
|
||||||
this.subscription = this.beatUnit.addSubscriber(this, "all");
|
this.subscription = this.beatUnit.addSubscriber(this, "all");
|
||||||
|
this.onMouseUp((ev: MouseEvent) => {
|
||||||
|
if (ev.button === 1) {
|
||||||
|
const currentType = this.beatUnit.getType();
|
||||||
|
this.beatUnit.setType(currentType === BeatUnitType.GhostNote ? BeatUnitType.Normal : BeatUnitType.GhostNote);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
toggle(): void {
|
toggle(): void {
|
||||||
@@ -59,22 +65,15 @@ export default class BeatUnitView extends UINode implements ISubscriber {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rebuild(): HTMLElement {
|
build(): HTMLElement {
|
||||||
const classes = ["beat-unit"];
|
const classes = ["beat-unit"];
|
||||||
if (this.beatUnit.isOn()) {
|
if (this.beatUnit.isOn()) {
|
||||||
classes.push("beat-unit-on");
|
classes.push("beat-unit-on");
|
||||||
}
|
}
|
||||||
this.node = UINode.make("div", {
|
return UINode.make("div", {
|
||||||
classes: classes,
|
classes: classes,
|
||||||
oncontextmenu: () => false,
|
oncontextmenu: () => false,
|
||||||
});
|
});
|
||||||
this.onMouseUp((ev: MouseEvent) => {
|
|
||||||
if (ev.button === 1) {
|
|
||||||
const currentType = this.beatUnit.getType();
|
|
||||||
this.beatUnit.setType(currentType === BeatUnitType.GhostNote ? BeatUnitType.Normal : BeatUnitType.GhostNote);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return this.node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onHover(cb: () => void): void {
|
onHover(cb: () => void): void {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import UINode, {UINodeOptions} from "../../UINode";
|
import UINode, {UINodeOptions} from "@/ui/UINode";
|
||||||
import Beat, {BeatEvents} from "../../../Beat";
|
import Beat, {BeatEvents} from "@/Beat";
|
||||||
import {IPublisher} from "../../../Publisher";
|
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";
|
||||||
|
|
||||||
@@ -129,7 +129,7 @@ export default class BeatView extends UINode implements ISubscriber {
|
|||||||
this.respaceBeatUnits();
|
this.respaceBeatUnits();
|
||||||
}
|
}
|
||||||
|
|
||||||
rebuild(): HTMLElement {
|
build(): HTMLElement {
|
||||||
this.title = UINode.make("h3", {
|
this.title = UINode.make("h3", {
|
||||||
innerText: this.beat.getName(),
|
innerText: this.beat.getName(),
|
||||||
classes: ["beat-title"],
|
classes: ["beat-title"],
|
||||||
@@ -138,7 +138,7 @@ 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.node = UINode.make("div", {
|
return UINode.make("div", {
|
||||||
classes: ["beat"],
|
classes: ["beat"],
|
||||||
subs: [
|
subs: [
|
||||||
UINode.make("div", {
|
UINode.make("div", {
|
||||||
@@ -150,7 +150,6 @@ export default class BeatView extends UINode implements ISubscriber {
|
|||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
return this.node;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import UINode, {UINodeOptions} from "../UINode";
|
import UINode, {UINodeOptions} from "@/ui/UINode";
|
||||||
import BeatGroup, {BeatGroupEvents} from "../../BeatGroup";
|
import BeatGroup, {BeatGroupEvents} from "@/BeatGroup";
|
||||||
import BeatView from "./Beat/BeatView";
|
import BeatView from "./Beat/BeatView";
|
||||||
import "./BeatGroup.css";
|
import "./BeatGroup.css";
|
||||||
import ISubscriber from "../../Subscriber";
|
import ISubscriber from "@/Subscriber";
|
||||||
import {IPublisher} from "../../Publisher";
|
import {IPublisher} from "@/Publisher";
|
||||||
|
|
||||||
export type BeatGroupUINodeOptions = UINodeOptions & {
|
export type BeatGroupUINodeOptions = UINodeOptions & {
|
||||||
title: string,
|
title: string,
|
||||||
@@ -28,7 +28,7 @@ export default class BeatGroupView extends UINode implements ISubscriber {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rebuild(): HTMLDivElement {
|
build(): HTMLDivElement {
|
||||||
this.beatViews = [];
|
this.beatViews = [];
|
||||||
for (let i = 0; i < this.beatGroup.getBeatCount(); i++) {
|
for (let i = 0; i < this.beatGroup.getBeatCount(); i++) {
|
||||||
this.beatViews.push(new BeatView({beat: this.beatGroup.getBeatByIndex(i)}));
|
this.beatViews.push(new BeatView({beat: this.beatGroup.getBeatByIndex(i)}));
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import "./BeatGroupSettings.css";
|
import "./BeatGroupSettings.css";
|
||||||
import UINode, {UINodeOptions} from "../UINode";
|
import UINode, {UINodeOptions} from "@/ui/UINode";
|
||||||
import NumberInputView from "../Widgets/NumberInput/NumberInputView";
|
import NumberInputView from "@/ui/Widgets/NumberInput/NumberInputView";
|
||||||
import ISubscriber from "../../Subscriber";
|
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 BoolBoxView from "@/ui/Widgets/BoolBox/BoolBoxView";
|
||||||
import BeatSettingsView from "../BeatSettings/BeatSettingsView";
|
import BeatSettingsView from "@/ui/BeatSettings/BeatSettingsView";
|
||||||
import ActionButtonView from "../Widgets/ActionButton/ActionButtonView";
|
import ActionButtonView from "@/ui/Widgets/ActionButton/ActionButtonView";
|
||||||
|
|
||||||
export type BeatGroupSettingsUINodeOptions = UINodeOptions & {
|
export type BeatGroupSettingsUINodeOptions = UINodeOptions & {
|
||||||
beatGroup: BeatGroup,
|
beatGroup: BeatGroup,
|
||||||
@@ -71,7 +71,7 @@ export default class BeatGroupSettingsView extends UINode implements ISubscriber
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rebuild(): HTMLElement {
|
build(): HTMLElement {
|
||||||
this.barCountInput = new NumberInputView({
|
this.barCountInput = new NumberInputView({
|
||||||
label: "Bars:",
|
label: "Bars:",
|
||||||
initialValue: this.beatGroup.getBarCount(),
|
initialValue: this.beatGroup.getBarCount(),
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import "./BeatLikeLoopSettings.css";
|
import "./BeatLikeLoopSettings.css";
|
||||||
import BeatLike from "../../BeatLike";
|
import BeatLike from "@/BeatLike";
|
||||||
import NumberInputView from "../Widgets/NumberInput/NumberInputView";
|
import NumberInputView from "@/ui/Widgets/NumberInput/NumberInputView";
|
||||||
import ISubscriber from "../../Subscriber";
|
import ISubscriber from "@/Subscriber";
|
||||||
import UINode, {UINodeOptions} from "../UINode";
|
import UINode, {UINodeOptions} from "@/ui/UINode";
|
||||||
import {BeatEvents} from "../../Beat";
|
import {BeatEvents} from "@/Beat";
|
||||||
import {IPublisher} from "../../Publisher";
|
import {IPublisher} from "@/Publisher";
|
||||||
import BoolBoxView from "../Widgets/BoolBox/BoolBoxView";
|
import BoolBoxView from "@/ui/Widgets/BoolBox/BoolBoxView";
|
||||||
|
|
||||||
export type BeatLikeLoopSettingsViewUINodeOptions = UINodeOptions & {
|
export type BeatLikeLoopSettingsViewUINodeOptions = UINodeOptions & {
|
||||||
beatLike: BeatLike,
|
beatLike: BeatLike,
|
||||||
@@ -52,7 +52,7 @@ export default class BeatLikeLoopSettingsView extends UINode implements ISubscri
|
|||||||
this.notify(null, BeatEvents.DisplayTypeChanged);
|
this.notify(null, BeatEvents.DisplayTypeChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
rebuild(): HTMLElement {
|
build(): HTMLElement {
|
||||||
this.loopLengthInput = new NumberInputView({
|
this.loopLengthInput = new NumberInputView({
|
||||||
initialValue: this.beatLike.getLoopLength(),
|
initialValue: this.beatLike.getLoopLength(),
|
||||||
label: "Length:",
|
label: "Length:",
|
||||||
@@ -76,7 +76,7 @@ export default class BeatLikeLoopSettingsView extends UINode implements ISubscri
|
|||||||
} else {
|
} else {
|
||||||
this.loopLengthSection.classList.add("hide");
|
this.loopLengthSection.classList.add("hide");
|
||||||
}
|
}
|
||||||
this.node = UINode.make("div", {
|
return UINode.make("div", {
|
||||||
classes: ["loop-settings"],
|
classes: ["loop-settings"],
|
||||||
subs: [
|
subs: [
|
||||||
UINode.make("p", {innerText: this.title}),
|
UINode.make("p", {innerText: this.title}),
|
||||||
@@ -94,6 +94,5 @@ export default class BeatLikeLoopSettingsView extends UINode implements ISubscri
|
|||||||
}),
|
}),
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
return this.node;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import "./BeatSettings.css";
|
import "./BeatSettings.css";
|
||||||
import Beat, {BeatEvents} from "../../Beat";
|
import Beat, {BeatEvents} from "@/Beat";
|
||||||
import UINode, {UINodeOptions} from "../UINode";
|
import UINode, {UINodeOptions} from "@/ui/UINode";
|
||||||
import ISubscriber from "../../Subscriber";
|
import ISubscriber from "@/Subscriber";
|
||||||
import {IPublisher, ISubscription} from "../../Publisher";
|
import {IPublisher, ISubscription} from "@/Publisher";
|
||||||
import NumberInputView from "../Widgets/NumberInput/NumberInputView";
|
import NumberInputView from "@/ui/Widgets/NumberInput/NumberInputView";
|
||||||
import BoolBoxView from "../Widgets/BoolBox/BoolBoxView";
|
import BoolBoxView from "@/ui/Widgets/BoolBox/BoolBoxView";
|
||||||
import ActionButtonView from "../Widgets/ActionButton/ActionButtonView";
|
import ActionButtonView from "@/ui/Widgets/ActionButton/ActionButtonView";
|
||||||
|
|
||||||
export type BeatSettingsViewUINodeOptions = UINodeOptions & {
|
export type BeatSettingsViewUINodeOptions = UINodeOptions & {
|
||||||
beat: Beat,
|
beat: Beat,
|
||||||
@@ -54,7 +54,7 @@ export default class BeatSettingsView extends UINode implements ISubscriber {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rebuild(): HTMLElement {
|
build(): HTMLElement {
|
||||||
this.nameInput = UINode.make("input", {
|
this.nameInput = UINode.make("input", {
|
||||||
value: this.beat.getName(),
|
value: this.beat.getName(),
|
||||||
classes: ["beat-settings-name-field"],
|
classes: ["beat-settings-name-field"],
|
||||||
@@ -62,7 +62,7 @@ export default class BeatSettingsView extends UINode implements ISubscriber {
|
|||||||
oninput: (event: Event) => this.beat.setName((event.target as HTMLInputElement).value),
|
oninput: (event: Event) => this.beat.setName((event.target as HTMLInputElement).value),
|
||||||
});
|
});
|
||||||
this.deleteButton = new ActionButtonView({
|
this.deleteButton = new ActionButtonView({
|
||||||
label: "Delete",
|
icon: "trash",
|
||||||
type: "secondary",
|
type: "secondary",
|
||||||
onClick: () => this.beat.delete(),
|
onClick: () => this.beat.delete(),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -64,28 +64,11 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.root-hamburger {
|
.root-hamburger, .root-switch-mode {
|
||||||
right: 0;
|
right: 0;
|
||||||
width: 2em;
|
width: 2em;
|
||||||
height: 2em;
|
height: 2em;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
-webkit-mask-image: url(./drawing.svg);
|
|
||||||
mask-image: url(./drawing.svg);
|
|
||||||
-webkit-mask-size: 2em;
|
|
||||||
mask-size: 2em;
|
|
||||||
background-color: var(--color-ui-neutral-dark);
|
|
||||||
}
|
|
||||||
|
|
||||||
.root-switch-mode {
|
|
||||||
right: 0;
|
|
||||||
width: 2em;
|
|
||||||
height: 2em;
|
|
||||||
cursor: pointer;
|
|
||||||
-webkit-mask-image: url(./rotate.svg);
|
|
||||||
mask-image: url(./rotate.svg);
|
|
||||||
-webkit-mask-size: 2em;
|
|
||||||
mask-size: 2em;
|
|
||||||
background-color: var(--color-ui-neutral-dark);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.root-beat-stage-container {
|
.root-beat-stage-container {
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import UINode, {UINodeOptions} from "../UINode";
|
import UINode, {UINodeOptions} from "@/ui/UINode";
|
||||||
import BeatGroupView from "../BeatGroup/BeatGroupView";
|
import BeatGroupView from "@/ui/BeatGroup/BeatGroupView";
|
||||||
import BeatGroup from "../../BeatGroup";
|
import BeatGroup from "@/BeatGroup";
|
||||||
import "./Root.css";
|
import "./Root.css";
|
||||||
import BeatGroupSettingsView from "../BeatGroupSettings/BeatGroupSettingsView";
|
import BeatGroupSettingsView from "@/ui/BeatGroupSettings/BeatGroupSettingsView";
|
||||||
|
import IconView from "@/ui/Widgets/Icon/IconView";
|
||||||
|
|
||||||
export type RootUINodeOptions = UINodeOptions & {
|
export type RootUINodeOptions = UINodeOptions & {
|
||||||
title: string,
|
title: string,
|
||||||
@@ -20,7 +21,7 @@ export default class RootView extends UINode {
|
|||||||
constructor(options: RootUINodeOptions) {
|
constructor(options: RootUINodeOptions) {
|
||||||
super(options);
|
super(options);
|
||||||
this.mainBeatGroup = options.mainBeatGroup;
|
this.mainBeatGroup = options.mainBeatGroup;
|
||||||
this.beatGroupView = new BeatGroupView({title: "THE BEAT", beatGroup: this.mainBeatGroup});
|
this.beatGroupView = new BeatGroupView({title: options.title, beatGroup: this.mainBeatGroup});
|
||||||
this.title = options.title;
|
this.title = options.title;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,7 +33,7 @@ export default class RootView extends UINode {
|
|||||||
this.getNode().classList.toggle("vertical-mode");
|
this.getNode().classList.toggle("vertical-mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
rebuild(): HTMLElement {
|
build(): HTMLElement {
|
||||||
this.beatGroupSettingsView = new BeatGroupSettingsView({beatGroup: this.mainBeatGroup});
|
this.beatGroupSettingsView = new BeatGroupSettingsView({beatGroup: this.mainBeatGroup});
|
||||||
const sidebarMain = UINode.make("div", {
|
const sidebarMain = UINode.make("div", {
|
||||||
classes: ["root-settings"],
|
classes: ["root-settings"],
|
||||||
@@ -41,15 +42,17 @@ export default class RootView extends UINode {
|
|||||||
this.beatGroupSettingsView.render(),
|
this.beatGroupSettingsView.render(),
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
const sidebarToggle = UINode.make("div", {
|
const sidebarStrip = UINode.make("div", {
|
||||||
classes: ["root-sidebar-toggle"],
|
classes: ["root-sidebar-toggle"],
|
||||||
subs: [
|
subs: [
|
||||||
UINode.make("div", {
|
UINode.make("div", {
|
||||||
classes: ["root-hamburger"],
|
classes: ["root-hamburger"],
|
||||||
|
subs: [new IconView({iconName: "list"}).render()],
|
||||||
onclick: () => this.toggleSidebar(),
|
onclick: () => this.toggleSidebar(),
|
||||||
}),
|
}),
|
||||||
UINode.make("div", {
|
UINode.make("div", {
|
||||||
classes: ["root-switch-mode"],
|
classes: ["root-switch-mode"],
|
||||||
|
subs: [new IconView({iconName: "arrowClockwise"}).render()],
|
||||||
onclick: () => this.toggleOrientation(),
|
onclick: () => this.toggleOrientation(),
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
@@ -58,10 +61,10 @@ export default class RootView extends UINode {
|
|||||||
classes: ["root-sidebar"],
|
classes: ["root-sidebar"],
|
||||||
subs: [
|
subs: [
|
||||||
sidebarMain,
|
sidebarMain,
|
||||||
sidebarToggle,
|
sidebarStrip,
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
this.node = UINode.make("div", {
|
return UINode.make("div", {
|
||||||
classes: ["root", "sidebar-visible"],
|
classes: ["root", "sidebar-visible"],
|
||||||
subs: [
|
subs: [
|
||||||
this.sidebar,
|
this.sidebar,
|
||||||
@@ -78,6 +81,5 @@ export default class RootView extends UINode {
|
|||||||
})
|
})
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
return this.node;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
width="64"
|
|
||||||
height="64"
|
|
||||||
viewBox="0 0 16.933333 16.933333"
|
|
||||||
version="1.1"
|
|
||||||
id="svg5"
|
|
||||||
inkscape:version="1.1 (ce6663b3b7, 2021-05-25)"
|
|
||||||
sodipodi:docname="drawing.svg"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg">
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="namedview7"
|
|
||||||
pagecolor="#505050"
|
|
||||||
bordercolor="#eeeeee"
|
|
||||||
borderopacity="1"
|
|
||||||
inkscape:pageshadow="0"
|
|
||||||
inkscape:pageopacity="0"
|
|
||||||
inkscape:pagecheckerboard="0"
|
|
||||||
inkscape:document-units="mm"
|
|
||||||
showgrid="true"
|
|
||||||
inkscape:zoom="6.0150393"
|
|
||||||
inkscape:cx="24.355618"
|
|
||||||
inkscape:cy="41.562488"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1043"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="0"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
width="64mm"
|
|
||||||
units="px">
|
|
||||||
<inkscape:grid
|
|
||||||
type="xygrid"
|
|
||||||
id="grid25"
|
|
||||||
empspacing="4" />
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<defs
|
|
||||||
id="defs2" />
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1">
|
|
||||||
<rect
|
|
||||||
style="fill:#1a1a1a;fill-rule:evenodd;stroke-width:0.634;stop-color:#000000"
|
|
||||||
id="rect49"
|
|
||||||
width="12.7"
|
|
||||||
height="2.1166666"
|
|
||||||
x="2.1166666"
|
|
||||||
y="3.1750002"
|
|
||||||
ry="1.0583333" />
|
|
||||||
<rect
|
|
||||||
style="fill:#1a1a1a;fill-rule:evenodd;stroke-width:0.634;stop-color:#000000"
|
|
||||||
id="rect49-3"
|
|
||||||
width="12.7"
|
|
||||||
height="2.1166666"
|
|
||||||
x="2.1166666"
|
|
||||||
y="7.4083338"
|
|
||||||
ry="1.0583333" />
|
|
||||||
<rect
|
|
||||||
style="fill:#1a1a1a;fill-rule:evenodd;stroke-width:0.634;stop-color:#000000"
|
|
||||||
id="rect49-6"
|
|
||||||
width="12.7"
|
|
||||||
height="2.1166666"
|
|
||||||
x="2.1166668"
|
|
||||||
y="11.641666"
|
|
||||||
ry="1.0583333" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 2.0 KiB |
@@ -1,78 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
width="64"
|
|
||||||
height="64"
|
|
||||||
viewBox="0 0 16.933333 16.933334"
|
|
||||||
version="1.1"
|
|
||||||
id="svg5"
|
|
||||||
inkscape:version="1.1 (ce6663b3b7, 2021-05-25)"
|
|
||||||
sodipodi:docname="rotate.svg"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg">
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="namedview7"
|
|
||||||
pagecolor="#505050"
|
|
||||||
bordercolor="#eeeeee"
|
|
||||||
borderopacity="1"
|
|
||||||
inkscape:pageshadow="0"
|
|
||||||
inkscape:pageopacity="0"
|
|
||||||
inkscape:pagecheckerboard="0"
|
|
||||||
inkscape:document-units="mm"
|
|
||||||
showgrid="true"
|
|
||||||
units="px"
|
|
||||||
width="64px"
|
|
||||||
inkscape:snap-bbox="true"
|
|
||||||
inkscape:zoom="6.0150393"
|
|
||||||
inkscape:cx="26.433743"
|
|
||||||
inkscape:cy="34.330615"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1016"
|
|
||||||
inkscape:window-x="1920"
|
|
||||||
inkscape:window-y="27"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:current-layer="layer1">
|
|
||||||
<inkscape:grid
|
|
||||||
type="xygrid"
|
|
||||||
id="grid113"
|
|
||||||
empspacing="4"
|
|
||||||
snapvisiblegridlinesonly="true"
|
|
||||||
visible="true"
|
|
||||||
enabled="true" />
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<defs
|
|
||||||
id="defs2" />
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1">
|
|
||||||
<g
|
|
||||||
id="g1725"
|
|
||||||
transform="rotate(-39.669761,8.2863595,8.2940605)">
|
|
||||||
<path
|
|
||||||
id="path217"
|
|
||||||
style="fill:#000000;fill-rule:evenodd;stroke-width:0.55878;stop-color:#000000"
|
|
||||||
d="M 8.2923774,2.0552887 A 6.5293784,6.5293784 0 0 0 1.762999,8.5846671 6.5293784,6.5293784 0 0 0 8.2923774,15.114045 6.5293784,6.5293784 0 0 0 12.031194,13.937153 L 11.496948,13.171992 A 5.5966101,5.5966101 0 0 1 8.2923774,14.181277 5.5966101,5.5966101 0 0 1 2.6957673,8.5846671 5.5966101,5.5966101 0 0 1 8.2923774,2.988057 5.5966101,5.5966101 0 0 1 13.888988,8.5846671 h 0.932768 A 6.5293784,6.5293784 0 0 0 8.2923774,2.0552887 Z m 6.5293786,6.5293784 a 6.5293784,6.5293784 0 0 1 -0.05967,0.8649058 6.5293784,6.5293784 0 0 0 0.05967,-0.8649058 z m -0.06558,0.9136394 a 6.5293784,6.5293784 0 0 1 -0.173077,0.8284685 6.5293784,6.5293784 0 0 0 0.173073,-0.8284685 z m -0.18947,0.8863115 a 6.5293784,6.5293784 0 0 1 -0.286936,0.802964 6.5293784,6.5293784 0 0 0 0.286936,-0.802964 z m -0.300599,0.832113 a 6.5293784,6.5293784 0 0 1 -0.393967,0.755597 6.5293784,6.5293784 0 0 0 0.393967,-0.755597 z m -0.412641,0.787478 a 6.5293784,6.5293784 0 0 1 -0.493255,0.694567 6.5293784,6.5293784 0 0 0 0.493255,-0.694567 z m -0.529237,0.738746 a 6.5293784,6.5293784 0 0 1 -0.583435,0.619417 6.5293784,6.5293784 0 0 0 0.583435,-0.619417 z m -0.614862,0.647654 a 6.5293784,6.5293784 0 0 1 -0.667238,0.538801 6.5293784,6.5293784 0 0 0 0.667238,-0.538801 z" />
|
|
||||||
<path
|
|
||||||
sodipodi:type="star"
|
|
||||||
style="fill:#000000;fill-rule:evenodd;stroke-width:2.39622;stop-color:#000000"
|
|
||||||
id="path1641"
|
|
||||||
inkscape:flatsided="true"
|
|
||||||
sodipodi:sides="3"
|
|
||||||
sodipodi:cx="47"
|
|
||||||
sodipodi:cy="50"
|
|
||||||
sodipodi:r1="7"
|
|
||||||
sodipodi:r2="3.5"
|
|
||||||
sodipodi:arg1="1.5707963"
|
|
||||||
sodipodi:arg2="2.6179939"
|
|
||||||
inkscape:rounded="0"
|
|
||||||
inkscape:randomized="0"
|
|
||||||
d="m 47,57 -6.062178,-10.5 12.124356,0 z"
|
|
||||||
transform="matrix(0.23319209,0,0,0.23319209,3.3953438,-2.6085529)"
|
|
||||||
inkscape:transform-center-y="0.40808613" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 3.5 KiB |
@@ -17,7 +17,7 @@ export default abstract class UINode {
|
|||||||
|
|
||||||
render(): HTMLElement {
|
render(): HTMLElement {
|
||||||
if (!this.node) {
|
if (!this.node) {
|
||||||
this.node = this.rebuild();
|
this.node = this.build();
|
||||||
}
|
}
|
||||||
return this.node;
|
return this.node;
|
||||||
}
|
}
|
||||||
@@ -37,12 +37,14 @@ export default abstract class UINode {
|
|||||||
}
|
}
|
||||||
const parent = this.node.parentElement;
|
const parent = this.node.parentElement;
|
||||||
if (parent) {
|
if (parent) {
|
||||||
this.node = this.rebuild();
|
this.node = this.build();
|
||||||
parent.replaceChild(this.node, oldNode);
|
parent.replaceChild(this.node, oldNode);
|
||||||
|
} else {
|
||||||
|
this.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract rebuild(): HTMLElement;
|
protected abstract build(): HTMLElement;
|
||||||
|
|
||||||
static make<
|
static make<
|
||||||
T extends keyof HTMLElementTagNameMap,
|
T extends keyof HTMLElementTagNameMap,
|
||||||
@@ -64,4 +66,16 @@ export default abstract class UINode {
|
|||||||
}
|
}
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static q(text: string): Text {
|
||||||
|
return document.createTextNode(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
static frag(subs?: Node[]): DocumentFragment {
|
||||||
|
const frag = document.createDocumentFragment();
|
||||||
|
if (subs) {
|
||||||
|
frag.append(...subs);
|
||||||
|
}
|
||||||
|
return frag;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,39 +1,48 @@
|
|||||||
import "./ActionButton.css";
|
import "./ActionButton.css";
|
||||||
import UINode, {UINodeOptions} from "../../UINode";
|
import UINode, {UINodeOptions} from "@/ui/UINode";
|
||||||
|
import IconView, {IconName} from "@/ui/Widgets/Icon/IconView";
|
||||||
|
|
||||||
export type ActionButtonUINodeOptions = UINodeOptions & {
|
export type ActionButtonUINodeOptions = UINodeOptions & {
|
||||||
label: string,
|
|
||||||
type?: "primary" | "secondary",
|
type?: "primary" | "secondary",
|
||||||
onClick?: (isChecked: boolean) => void,
|
onClick?: (isChecked: boolean) => void,
|
||||||
};
|
} & ({
|
||||||
|
icon: IconName,
|
||||||
|
label?: never,
|
||||||
|
} | {
|
||||||
|
label: string,
|
||||||
|
icon?: never,
|
||||||
|
});
|
||||||
|
|
||||||
export default class ActionButtonView extends UINode {
|
export default class ActionButtonView extends UINode {
|
||||||
private label: string | null;
|
private label: string | null = null;
|
||||||
|
private icon: IconName | null = null;
|
||||||
private buttonElement!: HTMLButtonElement;
|
private buttonElement!: HTMLButtonElement;
|
||||||
private onClick: (isChecked: boolean) => void;
|
private onClick: (isChecked: boolean) => void;
|
||||||
private type: "primary" | "secondary";
|
private type: "primary" | "secondary";
|
||||||
|
|
||||||
constructor(options: ActionButtonUINodeOptions) {
|
constructor(options: ActionButtonUINodeOptions) {
|
||||||
super(options);
|
super(options);
|
||||||
this.label = options.label ?? "";
|
if (typeof options.icon !== "undefined") {
|
||||||
|
this.icon = options.icon;
|
||||||
|
} else if (typeof options.label !== "undefined") {
|
||||||
|
this.label = options.label;
|
||||||
|
}
|
||||||
this.type = options.type ?? "primary";
|
this.type = options.type ?? "primary";
|
||||||
this.onClick = options.onClick ?? (() => { /* dummy */ });
|
this.onClick = options.onClick ?? (() => { /* dummy */ });
|
||||||
}
|
}
|
||||||
|
|
||||||
setLabel(newLabel: string | null): void {
|
protected build(): HTMLButtonElement {
|
||||||
if (newLabel !== null) {
|
|
||||||
this.buttonElement.innerText = newLabel;
|
|
||||||
} else {
|
|
||||||
this.buttonElement.innerText = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rebuild(): HTMLButtonElement {
|
|
||||||
this.buttonElement = UINode.make("button", {
|
this.buttonElement = UINode.make("button", {
|
||||||
classes: ["action-button", `action-button-${this.type}`],
|
classes: ["action-button", `action-button-${this.type}`],
|
||||||
innerText: this.label ?? "",
|
|
||||||
onclick: this.onClick,
|
onclick: this.onClick,
|
||||||
|
subs: [
|
||||||
|
this.icon !== null ? new IconView({
|
||||||
|
iconName: this.icon
|
||||||
|
}).render() : UINode.make("span", {
|
||||||
|
innerText: this.label ?? ""
|
||||||
|
}),
|
||||||
|
],
|
||||||
});
|
});
|
||||||
return this.buttonElement;
|
return this.buttonElement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import "./BoolBox.css";
|
import "./BoolBox.css";
|
||||||
import UINode, {UINodeOptions} from "../../UINode";
|
import UINode, {UINodeOptions} from "@/ui/UINode";
|
||||||
|
|
||||||
export type BoolBoxUINodeOptions = UINodeOptions & {
|
export type BoolBoxUINodeOptions = UINodeOptions & {
|
||||||
label?: string,
|
label?: string,
|
||||||
@@ -35,7 +35,7 @@ export default class BoolBoxView extends UINode {
|
|||||||
this.checkboxElement.checked = isChecked;
|
this.checkboxElement.checked = isChecked;
|
||||||
}
|
}
|
||||||
|
|
||||||
rebuild(): HTMLDivElement {
|
build(): HTMLDivElement {
|
||||||
this.labelElement = UINode.make("label", {
|
this.labelElement = UINode.make("label", {
|
||||||
classes: ["bool-box-label"],
|
classes: ["bool-box-label"],
|
||||||
innerText: this.label ?? "",
|
innerText: this.label ?? "",
|
||||||
|
|||||||
8
src/ui/Widgets/Icon/Icon.css
Normal file
8
src/ui/Widgets/Icon/Icon.css
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
.icon-view {
|
||||||
|
width: 2em;
|
||||||
|
height: 2em;
|
||||||
|
-webkit-mask-size: 2em;
|
||||||
|
mask-size: 2em;
|
||||||
|
display: inline-block;
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
34
src/ui/Widgets/Icon/IconView.ts
Normal file
34
src/ui/Widgets/Icon/IconView.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import UINode, {UINodeOptions} from "@/ui/UINode";
|
||||||
|
import "./Icon.css";
|
||||||
|
import List from "./svgs/list.svg";
|
||||||
|
import ArrowClockwise from "./svgs/arrow-clockwise.svg";
|
||||||
|
import Trash from "./svgs/trash.svg";
|
||||||
|
|
||||||
|
const IconUrlMap = {
|
||||||
|
arrowClockwise: ArrowClockwise,
|
||||||
|
list: List,
|
||||||
|
trash: Trash,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type IconName = keyof typeof IconUrlMap;
|
||||||
|
|
||||||
|
export type IconViewOptions = UINodeOptions & {
|
||||||
|
iconName: IconName,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class IconView extends UINode {
|
||||||
|
private iconUrl: string;
|
||||||
|
|
||||||
|
constructor(options: IconViewOptions) {
|
||||||
|
super(options);
|
||||||
|
this.iconUrl = IconUrlMap[options.iconName];
|
||||||
|
}
|
||||||
|
|
||||||
|
build(): HTMLSpanElement {
|
||||||
|
const icon = UINode.make("div", {
|
||||||
|
classes: ["icon-view"],
|
||||||
|
});
|
||||||
|
icon.style.cssText = `-webkit-mask-image: url(${this.iconUrl}); mask-image: url(${this.iconUrl});`;
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
}
|
||||||
4
src/ui/Widgets/Icon/svgs/arrow-clockwise.svg
Normal file
4
src/ui/Widgets/Icon/svgs/arrow-clockwise.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-clockwise" viewBox="0 0 16 16">
|
||||||
|
<path fill-rule="evenodd" d="M8 3a5 5 0 1 0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2v1z"/>
|
||||||
|
<path d="M8 4.466V.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384L8.41 4.658A.25.25 0 0 1 8 4.466z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 352 B |
3
src/ui/Widgets/Icon/svgs/list.svg
Normal file
3
src/ui/Widgets/Icon/svgs/list.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-list" viewBox="0 0 16 16">
|
||||||
|
<path fill-rule="evenodd" d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 344 B |
3
src/ui/Widgets/Icon/svgs/trash.svg
Normal file
3
src/ui/Widgets/Icon/svgs/trash.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-trash3-fill" viewBox="0 0 16 16">
|
||||||
|
<path d="M11 1.5v1h3.5a.5.5 0 0 1 0 1h-.538l-.853 10.66A2 2 0 0 1 11.115 16h-6.23a2 2 0 0 1-1.994-1.84L2.038 3.5H1.5a.5.5 0 0 1 0-1H5v-1A1.5 1.5 0 0 1 6.5 0h3A1.5 1.5 0 0 1 11 1.5Zm-5 0v1h4v-1a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 0-.5.5ZM4.5 5.029l.5 8.5a.5.5 0 1 0 .998-.06l-.5-8.5a.5.5 0 1 0-.998.06Zm6.53-.528a.5.5 0 0 0-.528.47l-.5 8.5a.5.5 0 0 0 .998.058l.5-8.5a.5.5 0 0 0-.47-.528ZM8 4.5a.5.5 0 0 0-.5.5v8.5a.5.5 0 0 0 1 0V5a.5.5 0 0 0-.5-.5Z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 582 B |
@@ -1,4 +1,4 @@
|
|||||||
import UINode, { UINodeOptions } from "../../UINode";
|
import UINode, { UINodeOptions } from "@/ui/UINode";
|
||||||
import "./NumberInput.css";
|
import "./NumberInput.css";
|
||||||
|
|
||||||
type NumberInputUINodeOptionsBase = UINodeOptions & {
|
type NumberInputUINodeOptionsBase = UINodeOptions & {
|
||||||
@@ -27,7 +27,6 @@ export type NumberInputUINodeOptions = NumberInputUINodeOptionsGetSet | NumberIn
|
|||||||
|
|
||||||
export default class NumberInputView extends UINode {
|
export default class NumberInputView extends UINode {
|
||||||
private labelElement!: HTMLLabelElement;
|
private labelElement!: HTMLLabelElement;
|
||||||
private mainElement!: HTMLDivElement;
|
|
||||||
private inputElement!: HTMLInputElement;
|
private inputElement!: HTMLInputElement;
|
||||||
private labelPosition: "top" | "left";
|
private labelPosition: "top" | "left";
|
||||||
private value: number;
|
private value: number;
|
||||||
@@ -63,12 +62,12 @@ export default class NumberInputView extends UINode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
disable(): void {
|
disable(): void {
|
||||||
this.mainElement.classList.add("disabled");
|
this.node?.classList.add("disabled");
|
||||||
this.inputElement.disabled = true;
|
this.inputElement.disabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
enable(): void {
|
enable(): void {
|
||||||
this.mainElement.classList.remove("disabled");
|
this.node?.classList.remove("disabled");
|
||||||
this.inputElement.disabled = false;
|
this.inputElement.disabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +76,7 @@ export default class NumberInputView extends UINode {
|
|||||||
this.inputElement.valueAsNumber = value;
|
this.inputElement.valueAsNumber = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
rebuild(): HTMLDivElement {
|
build(): HTMLDivElement {
|
||||||
this.labelElement = UINode.make("label", {
|
this.labelElement = UINode.make("label", {
|
||||||
classes: ["number-input-label", this.labelPosition],
|
classes: ["number-input-label", this.labelPosition],
|
||||||
innerText: this.label ?? "",
|
innerText: this.label ?? "",
|
||||||
@@ -100,7 +99,7 @@ export default class NumberInputView extends UINode {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
this.mainElement = UINode.make("div", {
|
return UINode.make("div", {
|
||||||
classes: ["number-input"],
|
classes: ["number-input"],
|
||||||
subs: [
|
subs: [
|
||||||
this.labelElement,
|
this.labelElement,
|
||||||
@@ -129,6 +128,5 @@ export default class NumberInputView extends UINode {
|
|||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
return this.mainElement;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,11 @@
|
|||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"moduleResolution": "Node",
|
"moduleResolution": "Node",
|
||||||
"resolveJsonModule": true
|
"resolveJsonModule": true,
|
||||||
|
"baseUrl": "./",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["src/*"]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"include": ["./src/**/*"]
|
"include": ["./src/**/*"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ const webpackConfig = {
|
|||||||
test: /\.(ts|tsx)$/,
|
test: /\.(ts|tsx)$/,
|
||||||
loader: "ts-loader",
|
loader: "ts-loader",
|
||||||
include: [path.resolve(__dirname, "src")],
|
include: [path.resolve(__dirname, "src")],
|
||||||
exclude: [/node_modules/]
|
exclude: [/node_modules/],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /.css$/,
|
test: /.css$/,
|
||||||
@@ -30,18 +30,21 @@ const webpackConfig = {
|
|||||||
}
|
}
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// test: /\.(png|jpe?g|gif|ttf|woff2?|eot|svg)$/i,
|
test: /\.(png|jpe?g|gif|ttf|woff2?|eot|svg)$/i,
|
||||||
// use: [
|
use: [
|
||||||
// {
|
{
|
||||||
// loader: "file-loader",
|
loader: "file-loader",
|
||||||
// },
|
},
|
||||||
// ],
|
],
|
||||||
// }
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
resolve: {
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
"@": path.resolve(__dirname, "./src"),
|
||||||
|
},
|
||||||
extensions: [".tsx", ".ts", ".js"]
|
extensions: [".tsx", ".ts", ".js"]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user