- Delete old Vite+Svelte frontend - Initialize new SvelteKit project with TypeScript - Configure Tailwind CSS v4 + DaisyUI - Implement JWT authentication with auto-refresh - Create login page with form validation (Zod) - Add protected route guards - Update Docker configuration for single-stage build - Add E2E tests with Playwright (6/11 passing) - Fix Svelte 5 reactivity with $state() runes Known issues: - 5 E2E tests failing (timing/async issues) - Token refresh implementation needs debugging - Validation error display timing
30 lines
1.4 KiB
JavaScript
30 lines
1.4 KiB
JavaScript
// https://stackoverflow.com/a/7557433/70894
|
|
export const isElementInViewport = (el, topOffset = 0) => {
|
|
const rect = el.getBoundingClientRect();
|
|
return (rect.top >= topOffset &&
|
|
rect.left >= 0 &&
|
|
rect.bottom <=
|
|
(window.innerHeight || document.documentElement.clientHeight) /* or $(window).height() */ &&
|
|
rect.right <=
|
|
(window.innerWidth || document.documentElement.clientWidth) /* or $(window).width() */);
|
|
};
|
|
// https://stackoverflow.com/a/36499256/70894
|
|
export const scrollToAndCenter = (el, offset = 1.125, behavior = 'smooth') => {
|
|
const elementRect = el.getBoundingClientRect();
|
|
const absoluteElementTop = elementRect.top + window.pageYOffset;
|
|
const top = absoluteElementTop - window.innerHeight / (2 * offset);
|
|
window.scrollTo({ left: 0, top, behavior });
|
|
};
|
|
const immediateInputTypes = ['checkbox', 'radio', 'range', 'file'];
|
|
/**
|
|
* Information about a HTML element, for determining when to display errors.
|
|
*/
|
|
export function inputInfo(el) {
|
|
const immediate = !!el &&
|
|
(el instanceof HTMLSelectElement ||
|
|
(el instanceof HTMLInputElement && immediateInputTypes.includes(el.type)));
|
|
const multiple = !!el && el instanceof HTMLSelectElement && el.multiple;
|
|
const file = !!el && el instanceof HTMLInputElement && el.type == 'file';
|
|
return { immediate, multiple, file };
|
|
}
|