feat: auto-save and multiple tracks
This commit is contained in:
@@ -7,9 +7,28 @@
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.vertical-mode .beat {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.vertical-mode .beat {
|
||||
height: inherit;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.beat-title {
|
||||
color: var(--color-title-light);
|
||||
text-align: center;
|
||||
width: fit-content;
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
.vertical-mode .beat-title {
|
||||
color: var(--color-title-light);
|
||||
text-align: center;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.beat-track-container {
|
||||
}
|
||||
@@ -4,21 +4,21 @@ import TrackView from "@/ui/Track/TrackView";
|
||||
import "./Beat.css";
|
||||
import ISubscriber from "@/Subscriber";
|
||||
import {ISubscription} from "@/Publisher";
|
||||
import EditableTextFieldView from "@/ui/Widgets/EditableTextFIeld/EditableTextFieldView";
|
||||
|
||||
export type BeatUINodeOptions = UINodeOptions & {
|
||||
title: string,
|
||||
beat: Beat,
|
||||
orientation?: "horizontal" | "vertical",
|
||||
};
|
||||
|
||||
const EventTypeSubscriptions = [
|
||||
BeatEvents.TrackListChanged
|
||||
];
|
||||
type EventTypeSubscriptions = FlatArray<typeof EventTypeSubscriptions, 1>;
|
||||
BeatEvents.TrackListChanged,
|
||||
] as const;
|
||||
type EventTypeSubscriptions = typeof EventTypeSubscriptions[number];
|
||||
|
||||
export default class BeatView extends UINode implements ISubscriber<EventTypeSubscriptions> {
|
||||
private title: string;
|
||||
private beat: Beat;
|
||||
private title: EditableTextFieldView;
|
||||
private trackViews: TrackView[] = [];
|
||||
private currentOrientation: "vertical" | "horizontal";
|
||||
private subscription: ISubscription;
|
||||
@@ -26,9 +26,13 @@ export default class BeatView extends UINode implements ISubscriber<EventTypeSub
|
||||
constructor(options: BeatUINodeOptions) {
|
||||
super(options);
|
||||
this.beat = options.beat;
|
||||
this.title = options.title;
|
||||
this.currentOrientation = options.orientation ?? "horizontal";
|
||||
this.subscription = this.beat.addSubscriber(this, EventTypeSubscriptions);
|
||||
this.title = new EditableTextFieldView({
|
||||
setter: (text: string) => this.beat.setName(text),
|
||||
noEmpty: true,
|
||||
initialText: this.beat.getName().val,
|
||||
});
|
||||
this.setupTrackViews();
|
||||
}
|
||||
|
||||
@@ -69,19 +73,37 @@ export default class BeatView extends UINode implements ISubscriber<EventTypeSub
|
||||
this.redraw();
|
||||
}
|
||||
|
||||
setBeat(newBeat: Beat): void {
|
||||
this.beat = newBeat;
|
||||
this.subscription.unbind();
|
||||
this.subscription = this.beat.addSubscriber(this, BeatEvents.TrackListChanged);
|
||||
private onNewBeat(): void {
|
||||
this.beat.getName().watch((newVal) => {
|
||||
this.title.setText(newVal);
|
||||
});
|
||||
this.title.setText(this.beat.getName().val);
|
||||
EventTypeSubscriptions.forEach(event => this.notify(this, event));
|
||||
this.setupTrackViews();
|
||||
this.redraw();
|
||||
}
|
||||
|
||||
setBeat(newBeat: Beat): void {
|
||||
this.beat = newBeat;
|
||||
this.subscription.unbind();
|
||||
this.subscription = this.beat.addSubscriber(this, BeatEvents.TrackListChanged);
|
||||
this.onNewBeat();
|
||||
}
|
||||
|
||||
build(): HTMLDivElement {
|
||||
return h("div", {
|
||||
classes: ["beat"],
|
||||
className: "beat",
|
||||
},[
|
||||
...this.trackViews
|
||||
h("h2", {
|
||||
className: "beat-title",
|
||||
}, [
|
||||
this.title,
|
||||
]),
|
||||
h("div", {
|
||||
className: "beat-track-container",
|
||||
}, [
|
||||
...this.trackViews,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ const EventTypeSubscriptions = [
|
||||
BeatEvents.LockingChanged,
|
||||
BeatEvents.AutoBeatSettingsChanged,
|
||||
];
|
||||
type EventTypeSubscriptions = FlatArray<typeof EventTypeSubscriptions, 1>;
|
||||
type EventTypeSubscriptions = typeof EventTypeSubscriptions[number];
|
||||
|
||||
export default class BeatSettingsView extends UINode implements ISubscriber<EventTypeSubscriptions> {
|
||||
private beat: Beat;
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -9,6 +9,7 @@
|
||||
--color-ui-neutral-dark-hover: #a1a1a1;
|
||||
--color-ui-neutral-dark-active: #c1c1c1;
|
||||
--color-bg-light: #464646;
|
||||
--color-bg-medium: #323232;
|
||||
--color-bg-dark: #282828;
|
||||
--color-p-light: #fafafa;
|
||||
--color-p-light-hover: #fafafa;
|
||||
@@ -45,7 +46,6 @@
|
||||
.root-settings {
|
||||
z-index: 1;
|
||||
width: 28em;
|
||||
padding: 0 0 0 2em;
|
||||
background-color: var(--color-bg-light);
|
||||
overflow: scroll;
|
||||
display: inline-block;
|
||||
@@ -97,7 +97,7 @@
|
||||
}
|
||||
|
||||
.vertical-mode .root-beat-stage {
|
||||
margin: 5em auto auto;
|
||||
margin: auto auto;
|
||||
padding-left: 3em;
|
||||
height: 100vh;
|
||||
}
|
||||
@@ -106,6 +106,39 @@
|
||||
max-width: calc(100vw - 30em);
|
||||
}
|
||||
|
||||
.root-sidebar-left-strip {
|
||||
text-align: right;
|
||||
writing-mode: sideways-lr;
|
||||
background-color: var(--color-bg-light);
|
||||
}
|
||||
|
||||
.root-sidebar-left-strip > * {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.root-sidebar-left-tab {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
padding: 8px 3px 8px 3px;
|
||||
}
|
||||
|
||||
.root-sidebar-left-tab.active {
|
||||
background-color: var(--color-bg-medium);
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.root-sidebar-add-beat {
|
||||
width: 100%;
|
||||
padding: 8px 3px 8px 3px;
|
||||
}
|
||||
|
||||
.root-sidebar-add-beat:hover,
|
||||
.root-sidebar-left-tab:hover:not(.active) {
|
||||
cursor: pointer;
|
||||
background-color: var(--color-ui-neutral-dark);
|
||||
transition: background-color 200ms;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 900px) {
|
||||
.sidebar-visible .root-sidebar {
|
||||
left: 0;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import UINode, {h, UINodeOptions} from "@/ui/UINode";
|
||||
import UINode, {h, q, UINodeOptions} from "@/ui/UINode";
|
||||
import BeatView from "@/ui/Beat/BeatView";
|
||||
import Beat from "@/Beat";
|
||||
import "./Root.css";
|
||||
import BeatSettingsView from "@/ui/BeatSettings/BeatSettingsView";
|
||||
import IconView from "@/ui/Widgets/Icon/IconView";
|
||||
import StageTitleBarView from "@/ui/StageTitleBar/StageTitleBarView";
|
||||
import Ref from "@/Ref";
|
||||
import BeatStore from "@/BeatStore";
|
||||
|
||||
export type RootUINodeOptions = UINodeOptions & {
|
||||
title: string,
|
||||
@@ -16,24 +16,34 @@ export type RootUINodeOptions = UINodeOptions & {
|
||||
export default class RootView extends UINode {
|
||||
private title: string;
|
||||
private beatView: BeatView;
|
||||
private focusedBeat: Beat;
|
||||
private beatStore: BeatStore;
|
||||
private activeBeat: Ref<Beat>;
|
||||
private beatSettingsView: BeatSettingsView;
|
||||
private currentOrientation: "horizontal" | "vertical";
|
||||
private stageTitleBarView: StageTitleBarView;
|
||||
private showHideSidebarButton: Ref<HTMLDivElement | null> = Ref.new<HTMLDivElement | null>(null);
|
||||
private sidebarActive = true;
|
||||
private sidebarLeftTabs: Ref<HTMLDivElement | null> = Ref.new<HTMLDivElement | null>(null);
|
||||
|
||||
constructor(options: RootUINodeOptions) {
|
||||
super(options);
|
||||
this.beatStore = new BeatStore({
|
||||
loadFromLocalStorage: true,
|
||||
autoSave: true,
|
||||
});
|
||||
this.currentOrientation = options.orientation ?? "horizontal";
|
||||
this.focusedBeat = options.mainBeat ?? RootView.defaultMainBeatGroup();
|
||||
this.activeBeat = this.beatStore.getActiveBeat();
|
||||
this.activeBeat.watch((newVal) => {
|
||||
this.beatSettingsView.setBeat(newVal);
|
||||
this.beatView.setBeat(newVal);
|
||||
});
|
||||
this.beatView = new BeatView({
|
||||
title: options.title,
|
||||
beat: this.focusedBeat,
|
||||
beat: this.activeBeat.val,
|
||||
orientation: this.currentOrientation,
|
||||
});
|
||||
this.stageTitleBarView = new StageTitleBarView({beat: this.focusedBeat});
|
||||
this.beatSettingsView = new BeatSettingsView({beat: this.focusedBeat});
|
||||
this.beatStore.onBeatChanges(() => {
|
||||
this.sidebarLeftTabs.val?.replaceChildren(...this.buildTabs());
|
||||
});
|
||||
this.beatSettingsView = new BeatSettingsView({beat: this.activeBeat.val});
|
||||
this.title = options.title;
|
||||
this.setOrientation(this.currentOrientation);
|
||||
this.openSidebarForDesktop();
|
||||
@@ -46,27 +56,6 @@ export default class RootView extends UINode {
|
||||
}
|
||||
}
|
||||
|
||||
static defaultMainBeatGroup(): Beat {
|
||||
const defaultSettings = {
|
||||
barCount: 2,
|
||||
isLooping: false,
|
||||
timeSigUp: 8,
|
||||
};
|
||||
const mainBeatGroup = new Beat(defaultSettings);
|
||||
mainBeatGroup.addTrack({name: "LF"});
|
||||
mainBeatGroup.addTrack({name: "LH"});
|
||||
mainBeatGroup.addTrack({name: "RH"});
|
||||
mainBeatGroup.addTrack({name: "RF"});
|
||||
return mainBeatGroup;
|
||||
}
|
||||
|
||||
setMainBeatGroup(beat: Beat): void {
|
||||
this.focusedBeat = beat;
|
||||
this.beatSettingsView.setBeat(this.focusedBeat);
|
||||
this.beatView.setBeat(this.focusedBeat);
|
||||
this.stageTitleBarView.setBeat(this.focusedBeat);
|
||||
}
|
||||
|
||||
toggleSidebar(): void {
|
||||
this.sidebarActive = !this.sidebarActive;
|
||||
this.showHideSidebarButton.val!.title = this.sidebarText();
|
||||
@@ -95,8 +84,40 @@ export default class RootView extends UINode {
|
||||
return `${this.sidebarActive ? "Hide" : "Show"} sidebar`;
|
||||
}
|
||||
|
||||
private buildSidebarStripLeft(): HTMLElement {
|
||||
return h("div", {
|
||||
className: "root-sidebar-left-strip",
|
||||
}, [
|
||||
h("div", {
|
||||
className: "root-sidebar-add-beat",
|
||||
onclick: () => this.beatStore.addNewBeat(),
|
||||
innerText: "+",
|
||||
}),
|
||||
h("div", {
|
||||
saveTo: this.sidebarLeftTabs
|
||||
}, this.buildTabs()),
|
||||
]);
|
||||
}
|
||||
|
||||
private buildSidebarStrip(): HTMLElement {
|
||||
private buildTabs(): HTMLElement[] {
|
||||
return this.beatStore.getBeats().map((beat) => {
|
||||
const node = h("div", {
|
||||
className: "root-sidebar-left-tab" + (beat === this.activeBeat.val ? " active" : ""),
|
||||
onclick: () => this.beatStore.setActiveBeat(beat),
|
||||
innerText: beat.getName(),
|
||||
});
|
||||
this.activeBeat.watch((newVal) => {
|
||||
if (beat === newVal) {
|
||||
node.classList.add("active");
|
||||
} else {
|
||||
node.classList.remove("active");
|
||||
}
|
||||
});
|
||||
return node;
|
||||
}).reverse();
|
||||
}
|
||||
|
||||
private buildSidebarQuickButtons(): HTMLElement {
|
||||
return h("div", {
|
||||
classes: ["root-sidebar-toggle"],
|
||||
}, [
|
||||
@@ -124,7 +145,7 @@ export default class RootView extends UINode {
|
||||
h("div", {
|
||||
classes: ["root-quick-access-button"],
|
||||
title: "Bake all tracks",
|
||||
onclick: () => this.focusedBeat.bakeLoops(),
|
||||
onclick: () => this.activeBeat.val.bakeLoops(),
|
||||
}, [
|
||||
new IconView({
|
||||
iconName: "snowflake",
|
||||
@@ -134,7 +155,7 @@ export default class RootView extends UINode {
|
||||
h("div", {
|
||||
classes: ["root-quick-access-button"],
|
||||
title: "Reset all",
|
||||
onclick: () => this.setMainBeatGroup(RootView.defaultMainBeatGroup()),
|
||||
onclick: () => this.beatStore.resetActiveBeat(),
|
||||
}, [
|
||||
new IconView({
|
||||
iconName: "trash",
|
||||
@@ -147,11 +168,12 @@ export default class RootView extends UINode {
|
||||
private buildSidebar(): HTMLElement {
|
||||
return (
|
||||
h("div", {classes: ["root-sidebar"]}, [
|
||||
this.buildSidebarStripLeft(),
|
||||
h("div", {classes: ["root-settings"]}, [
|
||||
h("h1", {classes: ["root-title"], innerText: this.title}),
|
||||
this.beatSettingsView,
|
||||
]),
|
||||
this.buildSidebarStrip(),
|
||||
this.buildSidebarQuickButtons(),
|
||||
])
|
||||
);
|
||||
}
|
||||
@@ -161,7 +183,6 @@ export default class RootView extends UINode {
|
||||
h("div", {classes: ["root", "sidebar-visible"]}, [
|
||||
this.buildSidebar(),
|
||||
h("div", {classes: ["root-beat-stage-container"]}, [
|
||||
this.stageTitleBarView,
|
||||
h("div", {classes: ["root-beat-stage"]}, [
|
||||
this.beatView,
|
||||
])
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
.stage-title-bar {
|
||||
position: absolute;
|
||||
background-color: var(--color-bg-light);
|
||||
padding: 15px;
|
||||
border-radius: 0 0 5px 5px;
|
||||
color: var(--color-title-light);
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.stage-title-bar * {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.stage-title-bar h2 {
|
||||
margin: 0;
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
import "./StageTitleBar.css";
|
||||
import UINode, {h, UINodeOptions} from "@/ui/UINode";
|
||||
import {ISubscription} from "@/Publisher";
|
||||
import Beat, {BeatEvents} from "@/Beat";
|
||||
import ISubscriber from "@/Subscriber";
|
||||
import EditableTextFieldView from "@/ui/Widgets/EditableTextFIeld/EditableTextFieldView";
|
||||
import DropdownView, {DropdownViewOption} from "@/ui/Widgets/Dropdown/DropdownView";
|
||||
import Ref from "@/Ref";
|
||||
|
||||
export type StageTitleBarViewOptions = UINodeOptions & {
|
||||
beat: Beat,
|
||||
};
|
||||
|
||||
const EventTypeSubscription = [BeatEvents.NameChanged];
|
||||
type EventTypeSubscription = FlatArray<typeof EventTypeSubscription, 1>;
|
||||
|
||||
export default class StageTitleBarView extends UINode implements ISubscriber<EventTypeSubscription> {
|
||||
private sub: ISubscription;
|
||||
private beat: Beat;
|
||||
private title: EditableTextFieldView;
|
||||
private options: Ref<DropdownViewOption[]>;
|
||||
|
||||
constructor(options: StageTitleBarViewOptions) {
|
||||
super(options);
|
||||
this.beat = options.beat;
|
||||
this.sub = options.beat.addSubscriber(this, EventTypeSubscription);
|
||||
this.title = new EditableTextFieldView({
|
||||
initialText: this.beat.getName(),
|
||||
setter: (text) => this.beat.setName(text),
|
||||
noEmpty: true,
|
||||
});
|
||||
this.options = Ref.new<DropdownViewOption[]>([]);
|
||||
}
|
||||
|
||||
notify(publisher: unknown, event: EventTypeSubscription): void {
|
||||
if (event === BeatEvents.NameChanged) {
|
||||
this.title.setText(this.beat.getName());
|
||||
}
|
||||
}
|
||||
|
||||
setBeat(beat: Beat): void {
|
||||
this.sub.unbind();
|
||||
this.beat = beat;
|
||||
this.sub = beat.addSubscriber(this, EventTypeSubscription);
|
||||
this.notify(this, BeatEvents.NameChanged);
|
||||
}
|
||||
|
||||
protected build(): HTMLElement {
|
||||
return h("div", {classes: ["stage-title-bar"]}, [
|
||||
h("h2", {}, [this.title]),
|
||||
new DropdownView({options: this.options})
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ const EventTypeSubscriptions = [
|
||||
TrackEvents.LoopLengthChanged,
|
||||
];
|
||||
|
||||
type EventTypeSubscriptions = FlatArray<typeof EventTypeSubscriptions, 1>;
|
||||
type EventTypeSubscriptions = typeof EventTypeSubscriptions[number];
|
||||
|
||||
export default class TrackView extends UINode implements ISubscriber<EventTypeSubscriptions> {
|
||||
private track!: Track;
|
||||
|
||||
@@ -17,7 +17,7 @@ const EventTypeSubscriptions = [
|
||||
TrackEvents.LoopLengthChanged,
|
||||
TrackEvents.DisplayTypeChanged,
|
||||
];
|
||||
type EventTypeSubscriptions = FlatArray<typeof EventTypeSubscriptions, 1>;
|
||||
type EventTypeSubscriptions = typeof EventTypeSubscriptions[number];
|
||||
|
||||
export default class TrackSettingsView extends UINode implements ISubscriber<EventTypeSubscriptions> {
|
||||
private track: Track;
|
||||
|
||||
@@ -13,7 +13,7 @@ const EventTypeSubscriptions = [
|
||||
TrackUnitEvent.Off,
|
||||
TrackUnitEvent.TypeChange,
|
||||
];
|
||||
type EventTypeSubscriptions = FlatArray<typeof EventTypeSubscriptions, 1>;
|
||||
type EventTypeSubscriptions = typeof EventTypeSubscriptions[number];
|
||||
|
||||
export default class TrackUnitView extends UINode implements ISubscriber<EventTypeSubscriptions> {
|
||||
private trackUnit: TrackUnit;
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import UINode, {h, 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";
|
||||
import Snowflake from "./svgs/snowflake.svg";
|
||||
import Ref from "@/Ref";
|
||||
import List from "assets/svgs/list.svg";
|
||||
import ArrowClockwise from "assets/svgs/arrow-clockwise.svg";
|
||||
import Trash from "assets/svgs/trash.svg";
|
||||
import Snowflake from "assets/svgs/snowflake.svg";
|
||||
|
||||
const IconUrlMap = {
|
||||
arrowClockwise: ArrowClockwise,
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
<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>
|
||||
|
Before Width: | Height: | Size: 352 B |
@@ -1,3 +0,0 @@
|
||||
<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>
|
||||
|
Before Width: | Height: | Size: 344 B |
@@ -1,3 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-snow2" viewBox="0 0 16 16">
|
||||
<path d="M8 16a.5.5 0 0 1-.5-.5v-1.293l-.646.647a.5.5 0 0 1-.707-.708L7.5 12.793v-1.086l-.646.647a.5.5 0 0 1-.707-.708L7.5 10.293V8.866l-1.236.713-.495 1.85a.5.5 0 1 1-.966-.26l.237-.882-.94.542-.496 1.85a.5.5 0 1 1-.966-.26l.237-.882-1.12.646a.5.5 0 0 1-.5-.866l1.12-.646-.884-.237a.5.5 0 1 1 .26-.966l1.848.495.94-.542-.882-.237a.5.5 0 1 1 .258-.966l1.85.495L7 8l-1.236-.713-1.849.495a.5.5 0 1 1-.258-.966l.883-.237-.94-.542-1.85.495a.5.5 0 0 1-.258-.966l.883-.237-1.12-.646a.5.5 0 1 1 .5-.866l1.12.646-.237-.883a.5.5 0 0 1 .966-.258l.495 1.849.94.542-.236-.883a.5.5 0 0 1 .966-.258l.495 1.849 1.236.713V5.707L6.147 4.354a.5.5 0 1 1 .707-.708l.646.647V3.207L6.147 1.854a.5.5 0 1 1 .707-.708l.646.647V.5a.5.5 0 0 1 1 0v1.293l.647-.647a.5.5 0 1 1 .707.708L8.5 3.207v1.086l.647-.647a.5.5 0 1 1 .707.708L8.5 5.707v1.427l1.236-.713.495-1.85a.5.5 0 1 1 .966.26l-.236.882.94-.542.495-1.85a.5.5 0 1 1 .966.26l-.236.882 1.12-.646a.5.5 0 0 1 .5.866l-1.12.646.883.237a.5.5 0 1 1-.26.966l-1.848-.495-.94.542.883.237a.5.5 0 1 1-.26.966l-1.848-.495L9 8l1.236.713 1.849-.495a.5.5 0 0 1 .259.966l-.883.237.94.542 1.849-.495a.5.5 0 0 1 .259.966l-.883.237 1.12.646a.5.5 0 0 1-.5.866l-1.12-.646.236.883a.5.5 0 1 1-.966.258l-.495-1.849-.94-.542.236.883a.5.5 0 0 1-.966.258L9.736 9.58 8.5 8.866v1.427l1.354 1.353a.5.5 0 0 1-.707.708l-.647-.647v1.086l1.354 1.353a.5.5 0 0 1-.707.708l-.647-.647V15.5a.5.5 0 0 1-.5.5z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -1,3 +0,0 @@
|
||||
<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>
|
||||
|
Before Width: | Height: | Size: 582 B |
@@ -76,26 +76,26 @@ body {
|
||||
font-family: 'DMSans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url(./DMSans-Regular.ttf) format('woff2');
|
||||
src: url(assets/fonts/DMSans-Regular.ttf) format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DMSans';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: url(./DMSans-Bold.ttf) format('woff2');
|
||||
src: url(assets/fonts/DMSans-Bold.ttf) format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DMSans';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: url(./DMSans-Italic.ttf) format('woff2');
|
||||
src: url(assets/fonts/DMSans-Italic.ttf) format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DMSans';
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
src: url(./DMSans-BoldItalic.ttf) format('woff2');
|
||||
src: url(assets/fonts/DMSans-BoldItalic.ttf) format('woff2');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user