73 lines
2.7 KiB
Vue
73 lines
2.7 KiB
Vue
<template>
|
|
<Modal :is-open="isOpen" @close="close" title="Copy sprite to frame" :initialWidth="380" :initialHeight="320">
|
|
<div class="p-4 flex flex-col h-full">
|
|
<div class="space-y-4 flex-1">
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Target frame</label>
|
|
<select v-model.number="targetFrame" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500">
|
|
<option v-for="i in maxFrameCount" :key="i" :value="i - 1">Frame {{ i }}</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Target layer</label>
|
|
<select v-model="targetLayerId" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500">
|
|
<option v-for="layer in layers" :key="layer.id" :value="layer.id">{{ layer.name }}</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="flex justify-end gap-3 mt-6 pt-4 border-t border-gray-100 dark:border-gray-700">
|
|
<button @click="close" class="px-4 py-2 text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors font-medium text-sm">Cancel</button>
|
|
<button @click="confirm" class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors font-medium text-sm">Copy</button>
|
|
</div>
|
|
</div>
|
|
</Modal>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, computed, watch } from 'vue';
|
|
import Modal from './Modal.vue';
|
|
import type { Layer } from '@/types/sprites';
|
|
|
|
const props = defineProps<{
|
|
isOpen: boolean;
|
|
layers: Layer[];
|
|
initialLayerId?: string;
|
|
}>();
|
|
|
|
const emit = defineEmits<{
|
|
(e: 'close'): void;
|
|
(e: 'copy', targetLayerId: string, targetFrameIndex: number): void;
|
|
}>();
|
|
|
|
const targetFrame = ref(0);
|
|
const targetLayerId = ref('');
|
|
|
|
const maxFrameCount = computed(() => {
|
|
const maxLen = Math.max(1, ...props.layers.map(l => l.sprites.length));
|
|
return maxLen + 1; // Allow copying to one frame beyond current max
|
|
});
|
|
|
|
watch(
|
|
() => props.isOpen,
|
|
isOpen => {
|
|
if (isOpen) {
|
|
targetFrame.value = 0;
|
|
targetLayerId.value = props.initialLayerId || (props.layers.length > 0 ? props.layers[0].id : '');
|
|
}
|
|
}
|
|
);
|
|
|
|
const close = () => {
|
|
emit('close');
|
|
};
|
|
|
|
const confirm = () => {
|
|
if (targetLayerId.value) {
|
|
emit('copy', targetLayerId.value, targetFrame.value);
|
|
close();
|
|
}
|
|
};
|
|
</script>
|