All checks were successful
SteamWarCI Build successful
- Introduced a new events collection in config.ts with schema validation. - Created a new event markdown file for the WarGear event. - Updated German translations to include new event-related strings. - Modified PageLayout to support a wide layout option. - Enhanced announcements page to improve tag filtering and post rendering. - Implemented dynamic event pages with detailed event information and fight plans. - Added an index page for events to list all upcoming events.
109 lines
4.0 KiB
Svelte
109 lines
4.0 KiB
Svelte
<script lang="ts">
|
|
import { fightConnector } from "./connections.svelte";
|
|
import { onMount, onDestroy } from "svelte";
|
|
|
|
let root: HTMLElement | null = null;
|
|
|
|
let refresh = $state(0);
|
|
|
|
function handleScroll() {
|
|
refresh++;
|
|
}
|
|
|
|
function getScrollableParent(el: HTMLElement | null): HTMLElement | null {
|
|
let node: HTMLElement | null = el?.parentElement ?? null;
|
|
while (node) {
|
|
const style = getComputedStyle(node);
|
|
const canScrollX = (style.overflowX === "auto" || style.overflowX === "scroll") && node.scrollWidth > node.clientWidth;
|
|
const canScrollY = (style.overflowY === "auto" || style.overflowY === "scroll") && node.scrollHeight > node.clientHeight;
|
|
if (canScrollX || canScrollY) return node;
|
|
node = node.parentElement;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
let cleanup: (() => void) | null = null;
|
|
|
|
onMount(() => {
|
|
const scrollParent = getScrollableParent(root);
|
|
const target: EventTarget | null = scrollParent ?? window;
|
|
|
|
target?.addEventListener("scroll", handleScroll, { passive: true } as AddEventListenerOptions);
|
|
window.addEventListener("resize", handleScroll, { passive: true });
|
|
|
|
cleanup = () => {
|
|
target?.removeEventListener?.("scroll", handleScroll as EventListener);
|
|
window.removeEventListener("resize", handleScroll as EventListener);
|
|
};
|
|
});
|
|
|
|
onDestroy(() => {
|
|
cleanup?.();
|
|
cleanup = null;
|
|
});
|
|
</script>
|
|
|
|
<div bind:this={root} class="connection-renderer-root">
|
|
{#key refresh}
|
|
{#each $fightConnector.showedConnections as connection}
|
|
{@const fromLeft = connection.fromElement.offsetLeft + connection.fromElement.offsetWidth}
|
|
{@const toLeft = connection.toElement.offsetLeft}
|
|
{@const fromTop = connection.fromElement.offsetTop + connection.fromElement.offsetHeight / 2}
|
|
{@const toTop = connection.toElement.offsetTop + connection.toElement.offsetHeight / 2}
|
|
{@const horizontalDistance = toLeft - fromLeft}
|
|
{@const verticalDistance = toTop - fromTop}
|
|
<!-- Apply horizontal offset only to the mid bridge and second segment fan-out; also shift vertical line to keep continuity -->
|
|
{@const midLeft = fromLeft + horizontalDistance / 2 + connection.offset}
|
|
{@const firstSegmentWidth = horizontalDistance / 2}
|
|
{@const secondSegmentWidth = horizontalDistance / 2}
|
|
|
|
<div
|
|
class="horizontal-line"
|
|
style="
|
|
background-color: {connection.color};
|
|
left: {fromLeft}px;
|
|
top: {fromTop + connection.offset / 4}px;
|
|
width: {firstSegmentWidth + connection.offset + 2}px;
|
|
"
|
|
></div>
|
|
<div
|
|
class="vertical-line"
|
|
style="
|
|
background-color: {connection.color};
|
|
left: {midLeft}px;
|
|
top: {Math.min(fromTop + connection.offset / 4, toTop + connection.offset / 4)}px;
|
|
height: {Math.abs(toTop + connection.offset / 4 - (fromTop + connection.offset / 4))}px;
|
|
"
|
|
></div>
|
|
<div
|
|
class="horizontal-line"
|
|
style="
|
|
background-color: {connection.color};
|
|
left: {midLeft}px;
|
|
top: {toTop + connection.offset / 4}px;
|
|
width: {secondSegmentWidth - connection.offset}px;
|
|
"
|
|
></div>
|
|
{/each}
|
|
{/key}
|
|
</div>
|
|
|
|
<style>
|
|
.connection-renderer-root {
|
|
position: static;
|
|
pointer-events: none;
|
|
}
|
|
.vertical-line {
|
|
position: absolute;
|
|
width: 2px;
|
|
z-index: -10;
|
|
pointer-events: none;
|
|
}
|
|
.horizontal-line {
|
|
position: absolute;
|
|
height: 2px;
|
|
z-index: -10;
|
|
pointer-events: none;
|
|
}
|
|
</style>
|