update
This commit is contained in:
1309
package-lock.json
generated
1309
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -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 =
|
||||
|
||||
@@ -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
2
src/globals.d.ts
vendored
@@ -2,7 +2,7 @@ import RootView from "@/ui/Root/RootView";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
appRoot?: RootView;
|
||||
drumslayer?: Record<string, any>,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,4 @@ import "@/ui/global.css";
|
||||
const app = createApp(Root, { title: "Drum Slayer" });
|
||||
app.mount("#app");
|
||||
|
||||
interface Window {
|
||||
drumslayer?: Record<string, any>,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -42,9 +42,6 @@
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.beat-settings {
|
||||
}
|
||||
|
||||
.beat-settings-options {
|
||||
padding: 1em;
|
||||
display: flex;
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
<template>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<{
|
||||
|
||||
@@ -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>"
|
||||
|
||||
@@ -19,7 +19,9 @@
|
||||
"jsx": "react"
|
||||
},
|
||||
"include": [
|
||||
"./src/**/*"
|
||||
"./src/**/*",
|
||||
"./prod.env.ts",
|
||||
"./dev.env.ts"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user