Continuation of separting logic into domain specific composables

This commit is contained in:
2025-11-18 20:11:36 +01:00
parent d571cb51cb
commit 404ca9ce88
7 changed files with 942 additions and 560 deletions

View File

@@ -0,0 +1,85 @@
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,
};
}