feat(stammbaum): land a fresh visit on the tree's top-left corner (#692)
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 2m35s
CI / OCR Service Tests (pull_request) Successful in 23s
CI / Backend Unit Tests (pull_request) Successful in 3m33s
CI / fail2ban Regex (pull_request) Successful in 45s
CI / Semgrep Security Scan (pull_request) Successful in 23s
CI / Compose Bucket Idempotency (pull_request) Successful in 1m5s
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 2m35s
CI / OCR Service Tests (pull_request) Successful in 23s
CI / Backend Unit Tests (pull_request) Successful in 3m33s
CI / fail2ban Regex (pull_request) Successful in 45s
CI / Semgrep Security Scan (pull_request) Successful in 23s
CI / Compose Bucket Idempotency (pull_request) Successful in 1m5s
At z=3 a pan of {0,0} centres on the tree midpoint; a fresh visit (no shared
?z) now anchors the viewBox to the tree's top-left corner via topLeftView
(the negative clamp limit), emitted on mount. Shared links still win.
Verified live: lands at cx<0, cy<0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { untrack } from 'svelte';
|
||||
import { untrack, onMount } from 'svelte';
|
||||
import { SvelteMap, SvelteSet } from 'svelte/reactivity';
|
||||
import type { components } from '$lib/generated/api';
|
||||
import {
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
type PanZoomState,
|
||||
clampZoom,
|
||||
recentreOn,
|
||||
topLeftView,
|
||||
ZOOM_STEP_KB
|
||||
} from '$lib/person/genealogy/panZoom';
|
||||
import { panZoomGestures } from '$lib/person/genealogy/panZoomGestures';
|
||||
@@ -32,6 +33,8 @@ interface Props {
|
||||
centreOnId?: string | null;
|
||||
/** Fired on the first pointer interaction with the canvas (affordance dismiss). */
|
||||
onActivity?: () => void;
|
||||
/** When true, the initial view is anchored to the tree's top-left corner. */
|
||||
anchorTopLeft?: boolean;
|
||||
onSelect: (id: string) => void;
|
||||
/**
|
||||
* Force-show or force-hide the generation gutter. When undefined, falls
|
||||
@@ -50,6 +53,7 @@ let {
|
||||
onPanZoom = () => {},
|
||||
centreOnId = null,
|
||||
onActivity,
|
||||
anchorTopLeft = false,
|
||||
onSelect,
|
||||
showGutter
|
||||
}: Props = $props();
|
||||
@@ -139,6 +143,12 @@ const railRows = $derived(
|
||||
.map((r) => ({ rank: r.rank, label: r.label, centerY: r.y + NODE_H / 2 }))
|
||||
);
|
||||
|
||||
// A fresh visit (no shared URL state) lands on the tree's top-left corner rather
|
||||
// than its centre (#692). Runs once after layout is available.
|
||||
onMount(() => {
|
||||
if (anchorTopLeft) onPanZoom(topLeftView(baseDims.w, baseDims.h, panZoom.z));
|
||||
});
|
||||
|
||||
const viewBox = $derived.by(() => {
|
||||
const w = baseDims.w / panZoom.z;
|
||||
const h = baseDims.h / panZoom.z;
|
||||
|
||||
Reference in New Issue
Block a user