Files
spritesheet-generator/src/composables/useZoom.ts
2025-11-18 20:12:32 +01:00

84 lines
2.3 KiB
TypeScript

import { ref, computed } from 'vue';
export interface ZoomOptionsStep {
min: number;
max: number;
step: number;
initial?: number;
}
export interface ZoomOptionsAllowed {
allowedValues: number[];
initial?: number;
}
export type ZoomOptions = ZoomOptionsStep | ZoomOptionsAllowed;
function isStepOptions(options: ZoomOptions): options is ZoomOptionsStep {
return 'step' in options;
}
export function useZoom(options: ZoomOptions) {
const initial = options.initial ?? (isStepOptions(options) ? 1 : (options.allowedValues[1] ?? options.allowedValues[0]));
const zoom = ref(initial);
const zoomPercent = computed(() => Math.round(zoom.value * 100));
const increase = () => {
if (isStepOptions(options)) {
zoom.value = Math.min(options.max, zoom.value + options.step);
} else {
const currentIndex = options.allowedValues.indexOf(zoom.value);
if (currentIndex < options.allowedValues.length - 1) {
zoom.value = options.allowedValues[currentIndex + 1];
} else if (currentIndex === -1) {
// Find the nearest higher value
const higher = options.allowedValues.find(v => v > zoom.value);
if (higher !== undefined) {
zoom.value = higher;
}
}
}
};
const decrease = () => {
if (isStepOptions(options)) {
zoom.value = Math.max(options.min, zoom.value - options.step);
} else {
const currentIndex = options.allowedValues.indexOf(zoom.value);
if (currentIndex > 0) {
zoom.value = options.allowedValues[currentIndex - 1];
} else if (currentIndex === -1) {
// Find the nearest lower value
const lower = [...options.allowedValues].reverse().find(v => v < zoom.value);
if (lower !== undefined) {
zoom.value = lower;
}
}
}
};
const reset = () => {
zoom.value = initial;
};
const setZoom = (value: number) => {
if (isStepOptions(options)) {
zoom.value = Math.max(options.min, Math.min(options.max, value));
} else {
// Snap to nearest allowed value
const nearest = options.allowedValues.reduce((prev, curr) => (Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev));
zoom.value = nearest;
}
};
return {
zoom,
zoomPercent,
increase,
decrease,
reset,
setZoom,
};
}