This commit is contained in:
Daniel Ledda
2024-05-31 17:27:04 +02:00
parent f76205d0db
commit ff6ffa57ce
14 changed files with 1071 additions and 562 deletions

1309
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
import { inject, type InjectionKey, ref, provide, getCurrentInstance } from "vue";
import { inject, type InjectionKey, ref, getCurrentInstance } from "vue";
import { Bound } from "./utils";
export type UITool =

View File

@@ -1,5 +1,5 @@
import { Beat, deserialise as deserialiseBeat, type BeatManager } from "@/Beat";
import { inject, computed, type InjectionKey, onScopeDispose, ref, shallowRef, triggerRef, watch, nextTick, readonly, provide, getCurrentInstance } from "vue";
import { Beat, deserialise as deserialiseBeat } from "@/Beat";
import { inject, computed, type InjectionKey, onScopeDispose, ref, shallowRef, triggerRef, watch, nextTick, getCurrentInstance } from "vue";
import { z } from "zod";
import { Bound } from "./utils";

2
src/globals.d.ts vendored
View File

@@ -2,7 +2,7 @@ import RootView from "@/ui/Root/RootView";
declare global {
interface Window {
appRoot?: RootView;
drumslayer?: Record<string, any>,
}
}

View File

@@ -5,8 +5,4 @@ import "@/ui/global.css";
const app = createApp(Root, { title: "Drum Slayer" });
app.mount("#app");
interface Window {
drumslayer?: Record<string, any>,
}

View File

@@ -28,7 +28,6 @@
<script setup lang="ts">
import TrackView from "@/ui/Track/Track.vue";
import EditableTextField from "@/ui/Widgets/EditableTextField/EditableTextField.vue";
import { useAppStateStore } from '@/AppState';
import { useBeatStore } from '@/BeatStore';
import { computed, ref } from "vue";
import Draggable from "vuedraggable";
@@ -40,7 +39,6 @@
orientation?: "horizontal" | "vertical",
}>();
const appState = useAppStateStore();
const { beats } = useBeatStore();
const beat = computed(() => beats.value[props.beatIndex] ?? null);
@@ -76,18 +74,10 @@
.beat {
padding: 1em;
overflow-x: scroll;
overflow-y: hidden;
overflow-y: visible;
display: flex;
width: inherit;
flex-direction: column;
}
.vertical-mode .beat {
padding-bottom: 2em;
align-items: center;
overflow-x: hidden;
overflow-y: scroll;
height: inherit;
width: 100%;
}
.beat-title {
@@ -97,39 +87,17 @@
margin-left: 16px;
}
.vertical-mode .beat-title {
color: var(--color-title-light);
text-align: center;
padding-left: 0;
}
.beat-track-container {
position: relative;
display: inline-block;
}
.beat-titles-container {
display: inline-flex;
flex-direction: column;
}
.vertical-mode .beat-main-container {
display: block;
}
.vertical-mode .beat-titles-container {
margin-bottom: 10px;
display: flex;
flex-direction: row;
overflow: visible;
}
.beat-main-container {
display: flex;
white-space: nowrap;
}
.beat-track-title {
.track-name {
height: 36px;
line-height: 36px;
margin: 0;
@@ -139,16 +107,6 @@
white-space: nowrap;
}
.vertical-mode .beat-track-title {
height: auto;
transform: rotate(330deg);
transform-origin: bottom;
width: 36px;
display: inline-block;
writing-mode: vertical-rl;
text-align: right;
}
.handle {
cursor: move;
color: var(--color-ui-neutral-dark);
@@ -164,7 +122,6 @@
flex-direction: row;
justify-content: flex-end;
align-items: center;
}
.dragging {
@@ -182,5 +139,45 @@
.ghost {
opacity: 0;
}
.vertical-mode {
.beat-title {
color: var(--color-title-light);
text-align: center;
padding-left: 0;
}
.beat-main-container {
display: block;
}
.track-name {
height: auto;
transform: rotate(330deg);
transform-origin: bottom;
display: inline-block;
writing-mode: vertical-rl;
text-align: right;
}
.beat {
padding-bottom: 2em;
align-items: center;
overflow-x: visible;
overflow-y: scroll;
height: inherit;
}
.beat-line {
flex-direction: column;
display: inline-block;
max-width: 36px;
}
.beat-track-container {
display: flex;
flex-direction: row;
}
}
</style>

View File

@@ -42,9 +42,6 @@
</script>
<style scoped lang="scss">
.beat-settings {
}
.beat-settings-options {
padding: 1em;
display: flex;

View File

@@ -1,8 +0,0 @@
<template>
</template>
<script setup lang="ts">
</script>
<style scoped lang="scss">
</style>

View File

@@ -342,11 +342,17 @@
padding-left: 3em;
}
&.vertical-mode .beat-stage {
&.vertical-mode {
.beat-stage {
margin: auto auto;
height: 100vh;
}
.beat-stage-container {
display: block;
}
}
.sidebar-left-strip {
writing-mode: vertical-rl;
background-color: var(--color-bg-medium);

View File

@@ -34,22 +34,11 @@
selectedTool,
activeStickingType,
activeTrackUnitType,
selectingUnits,
deselectingUnts,
} = useAppStateStore();
const { beats } = useBeatStore();
const beat = computed(() => beats.value[props.beatIndex] ?? null);
const track = computed(() => beat.value?.tracks.value[props.trackIndex] ?? null);
function swapUp() {
beat.value?.swapTracksByIndices(props.trackIndex + 1, props.trackIndex);
}
function swapDown() {
beat.value?.swapTracksByIndices(props.trackIndex, props.trackIndex - 1);
}
const trackUnits = computed(() => {
const units = [];
if (track.value) {
@@ -66,7 +55,7 @@
function toggle(index: number) {
if (!track.value) return;
track.value.toggleUnit(index);
if (track.value.getUnitByIndex(index).on) {
if (track.value.getUnitByIndex(index)?.on) {
applyCurrentToolToTrackUnit(index);
}
}
@@ -96,74 +85,72 @@
</script>
<style scoped lang="scss">
.vertical-mode .track {
height: 36px;
}
.vertical-mode .track {
height: auto;
}
.track > * {
padding-right: 1em;
padding-left: 1em;
}
.vertical-mode .track-unit.spaced {
margin-bottom: 1em;
margin-right: 0;
}
.track-unit.spaced {
.track-unit {
&.spaced {
margin-bottom: 0;
margin-right: 1em;
}
.vertical-mode .track > * {
padding-right: 0;
padding-left: 0;
}
.track-unit-block {
height: 2em;
}
.vertical-mode .track-unit-block {
height: auto;
width: 2em;
}
.track-spacer {
display: inline-block;
width: 1em;
height: 2em;
}
.vertical-mode .track-spacer {
display: block;
width: 2em;
height: 1em;
}
.track-main {
height: 36px;
}
.vertical-mode .track-main {
width: 2em;
margin-right: 4px;
display: block;
}
.track-settings-container {
display: flex;
}
.track {
width: max-content;
& > * {
padding-right: 1em;
padding-left: 1em;
}
}
.vertical-mode .track {
.vertical-mode {
.track-spacer {
display: block;
width: 2em;
height: 1em;
}
.track-unit-block {
height: auto;
width: 2em;
}
.track-main {
width: 2em;
margin-right: 4px;
display: block;
}
.track {
display: inline-block;
height: 36px;
& > * {
padding-right: 0;
padding-left: 0;
}
}
.track-unit {
&.spaced {
margin-bottom: 1em;
margin-right: 0;
}
}
}
</style>

View File

@@ -22,7 +22,7 @@
import ActionButton from "@/ui/Widgets/ActionButton/ActionButton.vue";
import EditableTextField from "@/ui/Widgets/EditableTextField/EditableTextField.vue";
import { useBeatStore } from "@/BeatStore";
import { computed, watch } from "vue";
import { computed } from "vue";
const props = defineProps<{
beatIndex: number,
@@ -35,14 +35,6 @@
</script>
<style scoped lang="scss">
.track-settings {
}
.track-settings-title-container {
}
.track-settings-title-container input {
min-width: 100%;
height: 2em;

View File

@@ -16,7 +16,7 @@
</template>
<script setup lang="ts">
import { type IconName } from "@/ui/Widgets/Icon/icons";
import type { IconName } from "@/ui/Widgets/Icon/icons";
import Icon from "@/ui/Widgets/Icon/Icon.vue";
withDefaults(defineProps<{

View File

@@ -1,80 +1,105 @@
<template>
<input
v-if="editing"
:value="modelValue"
<component
:is="nodeType"
class="static editable-text-field"
ref="inputField"
class="input editable-text-field-view"
type="text"
@keydown.enter.prevent="onEnter"
@input="onInput"
@blur="onBlur"
@keyup="onKeyUp"
/>
<component
v-else
:is="nodeType"
class="static editable-text-field-view"
@click="editing = true">
@click="onClick">
{{ modelValue }}
</component>
</template>
<script setup lang="ts">import { ref, watch } from 'vue';
<script setup lang="ts">
import { ref } from 'vue';
const props = withDefaults(defineProps<{
nodeType?: string,
modelValue: string,
noEmpty?: boolean,
}>(), {
nodeType: 'div',
noEmpty: true,
});
const emit = defineEmits<{
(e: 'update:modelValue', value: string): true,
}>();
let lastNonEmptyInput = "";
const editing = ref(false);
const inputField = ref<HTMLInputElement | null>(null);
let lastNonEmptyInput = props.modelValue ?? "";
const inputField = ref<HTMLElement | null>(null);
watch(inputField, (newVal) => newVal && newVal.focus());
function onClick() {
if (inputField.value) {
inputField.value.contentEditable = "true";
inputField.value.focus();
const selection = window.getSelection();
const firstChild = inputField.value.firstChild;
if (selection && firstChild) {
const range = document.createRange();
range.setStart(firstChild, 0);
range.setEnd(firstChild, inputField.value.textContent?.length ?? 1);
selection.removeAllRanges();
selection.addRange(range);
}
}
}
function onInput(event: Event) {
const input = (event.target as HTMLInputElement).value;
const input = (event.target as HTMLElement).textContent ?? "";
const inputToSet = props.noEmpty && input === "" ? lastNonEmptyInput : input;
emit('update:modelValue', inputToSet);
}
function onBlur(event: FocusEvent) {
if ((event.target as HTMLInputElement).value === "") {
function onBlur(event: Event) {
if ((event.target as HTMLElement).textContent === "") {
emit('update:modelValue', lastNonEmptyInput);
}
editing.value = false;
if (inputField.value) {
inputField.value.contentEditable = "false";
window.getSelection()?.removeAllRanges();
inputField.value.textContent = props.modelValue;
}
}
function onKeyUp(event: KeyboardEvent) {
if (event.key === "Enter") {
(event.target as HTMLInputElement).blur();
(event.target as HTMLElement).blur();
}
}
function onEnter(e: KeyboardEvent) {
onBlur(e);
}
</script>
<style scoped lang="scss">
.editable-text-field-view {
min-width: 3em;
.editable-text-field {
padding: 0.2em;
}
.input.editable-text-field-view {
input.input {
height: 100px;
color: black;
width: fit-content;
}
.static.editable-text-field-view {
.vertical-mode {
input.input {
height: 100px;
color: black;
}
}
.static {
transition: background-color 200ms;
width: fit-content;
cursor: pointer;
}
.static.editable-text-field-view:hover {
&:hover {
background-color: var(--color-ui-neutral-dark-hover);
}
}
</style>"

View File

@@ -19,7 +19,9 @@
"jsx": "react"
},
"include": [
"./src/**/*"
"./src/**/*",
"./prod.env.ts",
"./dev.env.ts"
],
"references": [
{