johnandersen777.bsky.social/knotless
git that lives in your Atmosphere account
Forked from chadtmiller.com/knotless
0
0
import type { Attachment } from 'svelte/attachments';
/**
* A row of tabs or chips that scrolls sideways when it is wider than the
* screen: the one picked brought into view, `at` naming it so a new pick
* brings that one, and the row marked `more-start` or `more-end` while
* there is more past either edge, which app.css fades.
*/
export function scrollRow(at: unknown): Attachment<HTMLElement> {
return (row) => {
void at;
const edges = () => {
row.classList.toggle('more-start', row.scrollLeft > 1);
row.classList.toggle('more-end', row.scrollLeft + row.clientWidth < row.scrollWidth - 1);
};
const picked = row.querySelector<HTMLElement>('[aria-current]');
if (picked && row.scrollWidth > row.clientWidth) {
const box = row.getBoundingClientRect();
const it = picked.getBoundingClientRect();
row.scrollLeft += it.left - box.left - (box.width - it.width) / 2;
}
edges();
row.addEventListener('scroll', edges, { passive: true });
const sized = new ResizeObserver(edges);
sized.observe(row);
return () => {
row.removeEventListener('scroll', edges);
sized.disconnect();
};
};
}
/**
* A list that scrolls within a box of its own, as a dialog's: marked
* `more-above` or `more-below` while there is more past its top or its
* bottom, which app.css fades, and again as what it holds changes.
*/
export const scrollFades: Attachment<HTMLElement> = (list) => {
const edges = () => {
list.classList.toggle('more-above', list.scrollTop > 1);
list.classList.toggle('more-below', list.scrollTop + list.clientHeight < list.scrollHeight - 1);
};
edges();
list.addEventListener('scroll', edges, { passive: true });
const sized = new ResizeObserver(edges);
sized.observe(list);
const changed = new MutationObserver(edges);
changed.observe(list, { childList: true, subtree: true });
return () => {
list.removeEventListener('scroll', edges);
sized.disconnect();
changed.disconnect();
};
};