import type { Range } from "#lib/components/ui/RangeSelector.svelte";
export type RangeMode =
| "resize"
| "resize-top"
| "resize-top-push"
| "resize-bottom"
| "resize-bottom-push"
| "select-top"
| "select-bottom";
type Options = {
cur: Range;
minLength: number;
count: number;
/** which end of `cur` follows the pointer -- "resize" only */
moving: "start" | "end";
};
/** the span for pointing at row `at`, or null when it won't fit the list or `minLength` */
export function rangeFor(mode: RangeMode, at: number, o: Options): Range | null {
const { cur, minLength, count } = o;
const fit = (start: number, end: number) =>
start >= 0 && end < count && end - start + 1 >= minLength ? { start, end } : null;
switch (mode) {
case "resize": {
const fixed = o.moving === "start" ? cur.end : cur.start;
return fit(Math.min(at, fixed), Math.max(at, fixed));
}
// the sub-minLength span past the other handle is what keeps these one-sided
case "resize-top":
return fit(at, cur.end);
case "resize-bottom":
return fit(cur.start, at);
case "resize-top-push":
return fit(at, Math.max(cur.end, at + minLength - 1));
case "resize-bottom-push":
return fit(Math.min(cur.start, at - minLength + 1), at);
case "select-top":
return fit(at, at + minLength - 1);
case "select-bottom":
return fit(at - minLength + 1, at);
}
}