update
This commit is contained in:
33
src/Beat.ts
33
src/Beat.ts
@@ -44,6 +44,7 @@ export class Beat extends EffectScoped {
|
|||||||
barSettingsLocked: Ref<boolean>;
|
barSettingsLocked: Ref<boolean>;
|
||||||
name: Ref<string>;
|
name: Ref<string>;
|
||||||
saveDirty = ref(false);
|
saveDirty = ref(false);
|
||||||
|
displaySticking = ref(false);
|
||||||
|
|
||||||
constructor(opts: BeatGroupInitOptions) {
|
constructor(opts: BeatGroupInitOptions) {
|
||||||
super();
|
super();
|
||||||
@@ -112,19 +113,13 @@ export class Beat extends EffectScoped {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getTrackByIndex(trackIndex: number) {
|
|
||||||
const track = this.tracks.value[trackIndex];
|
|
||||||
if (!track) {
|
|
||||||
throw new Error(`Could not find the track with index: ${trackIndex}`);
|
|
||||||
}
|
|
||||||
return track;
|
|
||||||
}
|
|
||||||
|
|
||||||
insertAt(trackIndex: number, newIndex: number): void {
|
insertAt(trackIndex: number, newIndex: number): void {
|
||||||
const track = this.getTrackByIndex(trackIndex);
|
const track = this.tracks.value[trackIndex];
|
||||||
this.tracks.value.splice(trackIndex, 1);
|
if (track) {
|
||||||
this.tracks.value = this.tracks.value.slice(0, newIndex).concat([track]).concat(this.tracks.value.slice(newIndex));
|
this.tracks.value.splice(trackIndex, 1);
|
||||||
triggerRef(this.tracks);
|
this.tracks.value = this.tracks.value.slice(0, newIndex).concat([track]).concat(this.tracks.value.slice(newIndex));
|
||||||
|
triggerRef(this.tracks);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyChange() {
|
notifyChange() {
|
||||||
@@ -153,10 +148,12 @@ export class Beat extends EffectScoped {
|
|||||||
}
|
}
|
||||||
|
|
||||||
removeTrack(index: number): void {
|
removeTrack(index: number): void {
|
||||||
const track = this.getTrackByIndex(index);
|
const track = this.tracks.value[index];
|
||||||
this.tracks.value.splice(index, 1);
|
if (track) {
|
||||||
track.destroy();
|
this.tracks.value.splice(index, 1);
|
||||||
triggerRef(this.tracks);
|
track.destroy();
|
||||||
|
triggerRef(this.tracks);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bakeLoops(): void {
|
bakeLoops(): void {
|
||||||
@@ -166,6 +163,10 @@ export class Beat extends EffectScoped {
|
|||||||
this.tracks.value.forEach(track => track.bakeLoops());
|
this.tracks.value.forEach(track => track.bakeLoops());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getTracks(): Track[] {
|
||||||
|
return this.tracks.value;
|
||||||
|
}
|
||||||
|
|
||||||
serialise(): Readonly<BeatSerial> {
|
serialise(): Readonly<BeatSerial> {
|
||||||
return {
|
return {
|
||||||
tracks: this.tracks.value.map(track => track.serialise()),
|
tracks: this.tracks.value.map(track => track.serialise()),
|
||||||
|
|||||||
15
src/Track.ts
15
src/Track.ts
@@ -34,10 +34,7 @@ export type TrackSerial = z.infer<typeof TrackSerialSchema>;
|
|||||||
export const TrackUnitTypeList = [ "Normal", "GhostNote", "Accent", "GhostNoteAccent" ] as const;
|
export const TrackUnitTypeList = [ "Normal", "GhostNote", "Accent", "GhostNoteAccent" ] as const;
|
||||||
export type TrackUnitType = typeof TrackUnitTypeList[number];
|
export type TrackUnitType = typeof TrackUnitTypeList[number];
|
||||||
|
|
||||||
export const PaintableTrackUnitStickingTypeList = [ "lh", "rh", "lf", "rf" ] as const;
|
export const TrackUnitStickingTypeList = [ "none", "lh", "rh", "lf", "rf" ] as const;
|
||||||
export type PaintableTrackUnitStickingType = typeof PaintableTrackUnitStickingTypeList[number];
|
|
||||||
|
|
||||||
export const TrackUnitStickingTypeList = [ "lh", "rh", "lf", "rf" ] as const;
|
|
||||||
export type TrackUnitStickingType = typeof TrackUnitStickingTypeList[number];
|
export type TrackUnitStickingType = typeof TrackUnitStickingTypeList[number];
|
||||||
|
|
||||||
export function isValidTimeSigRange(sig: number): boolean {
|
export function isValidTimeSigRange(sig: number): boolean {
|
||||||
@@ -53,7 +50,7 @@ export function deserialise(serial: unknown, manager: BeatManager) {
|
|||||||
const units = beat.units.isOn.map((isOn, i) => ({
|
const units = beat.units.isOn.map((isOn, i) => ({
|
||||||
on: isOn,
|
on: isOn,
|
||||||
type: beat.units.type[i] ?? 0,
|
type: beat.units.type[i] ?? 0,
|
||||||
stickingType: beat.units.stickingType[i] ?? 0,
|
stickingType: beat.units.stickingType[i] ?? null,
|
||||||
}));
|
}));
|
||||||
return Track.asScoped({
|
return Track.asScoped({
|
||||||
manager,
|
manager,
|
||||||
@@ -79,10 +76,10 @@ export class Track extends EffectScoped {
|
|||||||
private loopLengthInternal: any;
|
private loopLengthInternal: any;
|
||||||
private timeSig: { up: number, down: number };
|
private timeSig: { up: number, down: number };
|
||||||
private manager: BeatManager;
|
private manager: BeatManager;
|
||||||
|
private unitRecord: ShallowRef<TrackUnit[]>;
|
||||||
name: Ref<string>;
|
name: Ref<string>;
|
||||||
timeSigUp: Ref<number>;
|
timeSigUp: Ref<number>;
|
||||||
timeSigDown: Ref<number>;
|
timeSigDown: Ref<number>;
|
||||||
unitRecord: ShallowRef<TrackUnit[]>;
|
|
||||||
barCount: Ref<number>;
|
barCount: Ref<number>;
|
||||||
loopLength: Ref<number>;
|
loopLength: Ref<number>;
|
||||||
looping: Ref<boolean>;
|
looping: Ref<boolean>;
|
||||||
@@ -140,6 +137,10 @@ export class Track extends EffectScoped {
|
|||||||
return this.unitRecord.value[index] ?? null;
|
return this.unitRecord.value[index] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unitCount() {
|
||||||
|
return this.unitRecord.value.length;
|
||||||
|
}
|
||||||
|
|
||||||
private updateTrackUnitLength() {
|
private updateTrackUnitLength() {
|
||||||
const newBarCount = this.barCount.value * this.timeSigUp.value;
|
const newBarCount = this.barCount.value * this.timeSigUp.value;
|
||||||
if (newBarCount < this.unitRecord.value.length) {
|
if (newBarCount < this.unitRecord.value.length) {
|
||||||
@@ -187,7 +188,7 @@ export class Track extends EffectScoped {
|
|||||||
return {
|
return {
|
||||||
on: false,
|
on: false,
|
||||||
type: 0,
|
type: 0,
|
||||||
stickingType: 0,
|
stickingType: null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
15
src/globals.d.ts
vendored
15
src/globals.d.ts
vendored
@@ -6,4 +6,19 @@ declare global {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module "*.gif" {
|
||||||
|
const value: string;
|
||||||
|
export = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module "*.png" {
|
||||||
|
const value: string;
|
||||||
|
export = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module "*.svg" {
|
||||||
|
const value: string;
|
||||||
|
export = value;
|
||||||
|
}
|
||||||
|
|
||||||
export {};
|
export {};
|
||||||
|
|||||||
@@ -3,7 +3,18 @@
|
|||||||
<editable-text-field node-type="h3" class="beat-title" v-model="beat.name.value" />
|
<editable-text-field node-type="h3" class="beat-title" v-model="beat.name.value" />
|
||||||
<div class="beat-main-container">
|
<div class="beat-main-container">
|
||||||
<div class="beat-track-container" :class="{ dragging }">
|
<div class="beat-track-container" :class="{ dragging }">
|
||||||
<draggable @start="dragging = true"
|
<template v-if="beat.displaySticking.value">
|
||||||
|
<div v-for="(_, type) in TrackUnitStickingTypeList.slice(1)"
|
||||||
|
class="beat-line">
|
||||||
|
<div class="track-name">{{ TrackUnitStickingTypeList[type + 1]?.toUpperCase() }}</div>
|
||||||
|
<span class="handle"><icon color="var(--color-ui-neutral-dark)" icon-name="list" /></span>
|
||||||
|
<sticking-track-view
|
||||||
|
:beat-index="beatIndex"
|
||||||
|
:sticking-type="type + 1" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<draggable v-else
|
||||||
|
@start="dragging = true"
|
||||||
@end="dragging = false"
|
@end="dragging = false"
|
||||||
animation="150"
|
animation="150"
|
||||||
ghost-class="ghost"
|
ghost-class="ghost"
|
||||||
@@ -27,11 +38,12 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import TrackView from "@/ui/Track/Track.vue";
|
import TrackView from "@/ui/Track/Track.vue";
|
||||||
|
import StickingTrackView from "@/ui/Track/StickingTrack.vue";
|
||||||
import EditableTextField from "@/ui/Widgets/EditableTextField/EditableTextField.vue";
|
import EditableTextField from "@/ui/Widgets/EditableTextField/EditableTextField.vue";
|
||||||
import { useBeatStore } from '@/BeatStore';
|
import { useBeatStore } from '@/BeatStore';
|
||||||
import { computed, ref } from "vue";
|
import { computed, ref } from "vue";
|
||||||
import Draggable from "vuedraggable";
|
import Draggable from "vuedraggable";
|
||||||
import type { Track } from "@/Track";
|
import { TrackUnitStickingTypeList, type Track } from "@/Track";
|
||||||
import Icon from "@/ui/Widgets/Icon/Icon.vue";
|
import Icon from "@/ui/Widgets/Icon/Icon.vue";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@@ -43,7 +55,7 @@
|
|||||||
const beat = computed(() => beats.value[props.beatIndex] ?? null);
|
const beat = computed(() => beats.value[props.beatIndex] ?? null);
|
||||||
|
|
||||||
const tracks = computed(() => {
|
const tracks = computed(() => {
|
||||||
const trackList = beat.value?.tracks.value ?? [];
|
const trackList = beat.value?.getTracks() ?? [];
|
||||||
const length = trackList.length;
|
const length = trackList.length;
|
||||||
const list: { index: number, track: Track }[] = [];
|
const list: { index: number, track: Track }[] = [];
|
||||||
for (let i = 0; i < length; i++) {
|
for (let i = 0; i < length; i++) {
|
||||||
|
|||||||
@@ -7,6 +7,9 @@
|
|||||||
<div class="beat-settings-bar-count beat-settings-option">
|
<div class="beat-settings-bar-count beat-settings-option">
|
||||||
<number-input label="Boxes per bar: " v-model="beat.timeSigUp.value" />
|
<number-input label="Boxes per bar: " v-model="beat.timeSigUp.value" />
|
||||||
</div>
|
</div>
|
||||||
|
<div class="beat-settings-bar-count beat-settings-option">
|
||||||
|
<bool-box label="Sticking mode: " v-model="beat.displaySticking.value" />
|
||||||
|
</div>
|
||||||
<div class="beat-settings-bar-count beat-settings-option">
|
<div class="beat-settings-bar-count beat-settings-option">
|
||||||
<bool-box label="Auto beat length: " v-model="beat.useAutoBeatLength.value" />
|
<bool-box label="Auto beat length: " v-model="beat.useAutoBeatLength.value" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
@click="selectedTool = 'track-unit-type'">
|
@click="selectedTool = 'track-unit-type'">
|
||||||
<track-unit-box
|
<track-unit-box
|
||||||
v-if="activeTrackUnitType !== null"
|
v-if="activeTrackUnitType !== null"
|
||||||
class="paint-button"
|
|
||||||
:sticking-type="null" :on="true" :type="activeTrackUnitType" />
|
:sticking-type="null" :on="true" :type="activeTrackUnitType" />
|
||||||
<icon v-else class="paint-button" icon-name="eraser" />
|
<icon v-else class="paint-button" icon-name="eraser" />
|
||||||
</div>
|
</div>
|
||||||
@@ -17,7 +16,7 @@
|
|||||||
:key="type ?? 'eraser'"
|
:key="type ?? 'eraser'"
|
||||||
class="toolbox-button track-unit-type"
|
class="toolbox-button track-unit-type"
|
||||||
:class="{ active: i === activeTrackUnitType || type === null && activeTrackUnitType === null }"
|
:class="{ active: i === activeTrackUnitType || type === null && activeTrackUnitType === null }"
|
||||||
@click="activeTrackUnitType = type === null ? null : i; selectedTool = 'track-unit-type'">
|
@click="activeTrackUnitType = (type === null ? null : i); selectedTool = 'track-unit-type'">
|
||||||
<track-unit-box v-if="type !== null" :sticking-type="null" :on="true" :type="i" />
|
<track-unit-box v-if="type !== null" :sticking-type="null" :on="true" :type="i" />
|
||||||
<icon v-else icon-name="eraser" />
|
<icon v-else icon-name="eraser" />
|
||||||
</div>
|
</div>
|
||||||
@@ -27,16 +26,16 @@
|
|||||||
<dropdown>
|
<dropdown>
|
||||||
<icon
|
<icon
|
||||||
class="toolbox-button"
|
class="toolbox-button"
|
||||||
:icon-name="activeStickingType ? (PaintableTrackUnitStickingTypeList[activeStickingType] ?? 'eraser') : 'eraser'"
|
:icon-name="activeStickingType ? StickingTypeIconMap[TrackUnitStickingTypeList[activeStickingType]!] : 'eraser'"
|
||||||
:class="{ active: selectedTool === 'sticking' }"
|
:class="{ active: selectedTool === 'sticking' }"
|
||||||
@click="selectedTool = 'sticking'" />
|
@click="selectedTool = 'sticking'" />
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="details">
|
<div class="details">
|
||||||
<div v-for="(stickingType, i) in PaintableTrackUnitStickingTypeList"
|
<div v-for="(stickingType, i) in TrackUnitStickingTypeList.slice(1)"
|
||||||
:key="stickingType"
|
:key="stickingType ?? 'none'"
|
||||||
class="toolbox-button"
|
class="toolbox-button"
|
||||||
:class="{ active: i === activeStickingType }"
|
:class="{ active: i + 1 === activeStickingType }"
|
||||||
@click="activeStickingType = i; selectedTool = 'sticking'">
|
@click="activeStickingType = i + 1; selectedTool = 'sticking'">
|
||||||
<icon :icon-name="StickingTypeIconMap[stickingType]" />
|
<icon :icon-name="StickingTypeIconMap[stickingType]" />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@@ -54,7 +53,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useAppStateStore } from "@/AppState";
|
import { useAppStateStore } from "@/AppState";
|
||||||
import { PaintableTrackUnitStickingTypeList, TrackUnitTypeList } from "@/Track";
|
import { TrackUnitStickingTypeList, TrackUnitTypeList } from "@/Track";
|
||||||
import { StickingTypeIconMap } from "@/ui/TrackUnit/trackUnit";
|
import { StickingTypeIconMap } from "@/ui/TrackUnit/trackUnit";
|
||||||
import Icon from "@/ui/Widgets/Icon/Icon.vue";
|
import Icon from "@/ui/Widgets/Icon/Icon.vue";
|
||||||
import Dropdown from '@/ui/Widgets/Dropdown/Dropdown.vue';
|
import Dropdown from '@/ui/Widgets/Dropdown/Dropdown.vue';
|
||||||
|
|||||||
@@ -1,32 +1,42 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="track">
|
<track-container>
|
||||||
<div class="track-main">
|
<template v-if="!locked">
|
||||||
<div class="track-unit-block">
|
<track-unit v-for="(trackUnit, i) in trackUnits"
|
||||||
<track-unit v-for="(trackUnit, i) in trackUnits"
|
:key="`tu${ trackIndex }${ i }`"
|
||||||
:key="`tu${ trackIndex }${ i }`"
|
:id="`tu${ trackIndex }${ i }`"
|
||||||
:id="`tu${ trackIndex }${ i }`"
|
class="track-unit"
|
||||||
class="track-unit"
|
:class="{ spaced: (i + 1) % beat!.timeSigUp.value === 0 }"
|
||||||
:class="{ spaced: (i + 1) % beat!.timeSigUp.value === 0 }"
|
:sticking-type="trackUnit.stickingType"
|
||||||
:sticking-type="trackUnit.stickingType"
|
:type="trackUnit.type"
|
||||||
:type="trackUnit.type"
|
:on="trackUnit.on"
|
||||||
:on="trackUnit.on"
|
@rotate-type="rotateTrackUnit(i)"
|
||||||
@rotate-type="rotateTrackUnit(i)"
|
@deactivate="deactivateUnit(i)"
|
||||||
@deactivate="deactivateUnit(i)"
|
@toggle="toggle(i)"
|
||||||
@toggle="toggle(i)"
|
@apply-tool="applyCurrentToolToTrackUnit(i)" />
|
||||||
@apply-tool="applyCurrentToolToTrackUnit(i)" />
|
</template>
|
||||||
</div>
|
<template v-else>
|
||||||
</div>
|
<track-unit v-for="(trackUnit, i) in trackUnits"
|
||||||
</div>
|
:key="`tu${ trackIndex }${ i }`"
|
||||||
|
:id="`tu${ trackIndex }${ i }`"
|
||||||
|
class="track-unit"
|
||||||
|
:class="{ spaced: (i + 1) % beat!.timeSigUp.value === 0 }"
|
||||||
|
:sticking-type="trackUnit.stickingType"
|
||||||
|
:type="trackUnit.type"
|
||||||
|
:on="trackUnit.on" />
|
||||||
|
</template>
|
||||||
|
</track-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import TrackUnit from "@/ui/TrackUnit/TrackUnit.vue";
|
import TrackUnit from "@/ui/TrackUnit/TrackUnit.vue";
|
||||||
|
import TrackContainer from "@/ui/Track/TrackContainer.vue";
|
||||||
import { useBeatStore } from "@/BeatStore";
|
import { useBeatStore } from "@/BeatStore";
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { useAppStateStore } from "@/AppState";
|
import { useAppStateStore } from "@/AppState";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
beatIndex: number,
|
beatIndex: number,
|
||||||
|
locked?: boolean,
|
||||||
trackIndex: number,
|
trackIndex: number,
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
@@ -35,6 +45,7 @@
|
|||||||
activeStickingType,
|
activeStickingType,
|
||||||
activeTrackUnitType,
|
activeTrackUnitType,
|
||||||
} = useAppStateStore();
|
} = useAppStateStore();
|
||||||
|
|
||||||
const { beats } = useBeatStore();
|
const { beats } = useBeatStore();
|
||||||
const beat = computed(() => beats.value[props.beatIndex] ?? null);
|
const beat = computed(() => beats.value[props.beatIndex] ?? null);
|
||||||
const track = computed(() => beat.value?.tracks.value[props.trackIndex] ?? null);
|
const track = computed(() => beat.value?.tracks.value[props.trackIndex] ?? null);
|
||||||
@@ -42,7 +53,7 @@
|
|||||||
const trackUnits = computed(() => {
|
const trackUnits = computed(() => {
|
||||||
const units = [];
|
const units = [];
|
||||||
if (track.value) {
|
if (track.value) {
|
||||||
for (let i = 0; i < track.value.unitRecord.value.length; i++) {
|
for (let i = 0; i < track.value.unitCount(); i++) {
|
||||||
const unit = track.value.getUnitByIndex(i);
|
const unit = track.value.getUnitByIndex(i);
|
||||||
if (unit) {
|
if (unit) {
|
||||||
units.push(unit);
|
units.push(unit);
|
||||||
@@ -90,61 +101,7 @@
|
|||||||
margin-right: 1em;
|
margin-right: 1em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.track-unit-block {
|
|
||||||
height: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.track-spacer {
|
|
||||||
display: inline-block;
|
|
||||||
width: 1em;
|
|
||||||
height: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.track-main {
|
|
||||||
height: 36px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.track-settings-container {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.track {
|
|
||||||
width: max-content;
|
|
||||||
& > * {
|
|
||||||
padding-right: 1em;
|
|
||||||
padding-left: 1em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.vertical-mode {
|
.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 {
|
.track-unit {
|
||||||
&.spaced {
|
&.spaced {
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import type { IconName } from "@/ui/Widgets/Icon/icons";
|
|||||||
export const TypeClasses = [ "Ghost", "Accent" ] as const;
|
export const TypeClasses = [ "Ghost", "Accent" ] as const;
|
||||||
|
|
||||||
export const StickingTypeIconMap = {
|
export const StickingTypeIconMap = {
|
||||||
|
none: null,
|
||||||
lf: 'lf',
|
lf: 'lf',
|
||||||
lh: 'lh',
|
lh: 'lh',
|
||||||
rf: 'rf',
|
rf: 'rf',
|
||||||
@@ -17,7 +18,7 @@ export const TrackUnitTypeClassMap = {
|
|||||||
"GhostNoteAccent": ["Ghost", "Accent"],
|
"GhostNoteAccent": ["Ghost", "Accent"],
|
||||||
} as const satisfies Record<TrackUnitType, Readonly<string[]>>;
|
} as const satisfies Record<TrackUnitType, Readonly<string[]>>;
|
||||||
|
|
||||||
export function getClasses(options: { on: boolean, stickingType: TrackUnitStickingType | null, type: TrackUnitType, highlightable?: boolean }) {
|
export function getClasses(options: { on: boolean, stickingType: TrackUnitStickingType, type: TrackUnitType, highlightable?: boolean }) {
|
||||||
const classes = ["track-unit"];
|
const classes = ["track-unit"];
|
||||||
if (options.on) {
|
if (options.on) {
|
||||||
classes.push("on");
|
classes.push("on");
|
||||||
|
|||||||
Reference in New Issue
Block a user