Refactor/reacrhitecture to fsd+ #49

Merged
ilia merged 70 commits from refactor/reacrhitecture-to-fsd+ into main 2026-06-03 09:55:47 +00:00
5 changed files with 28 additions and 6 deletions
Showing only changes of commit 839460726e - Show all commits
+1 -1
View File
@@ -26,8 +26,8 @@
*/ */
export { export {
getScrollBreadcrumbsStore,
type NavigationAction, type NavigationAction,
scrollBreadcrumbsStore,
} from './model'; } from './model';
export { export {
BreadcrumbHeader, BreadcrumbHeader,
@@ -167,6 +167,13 @@ class ScrollBreadcrumbsStore {
this.#detachScrollListener(); this.#detachScrollListener();
} }
/**
* Tears down the observer and scroll listener. Call on store disposal.
*/
destroy(): void {
this.#disconnect();
}
/** /**
* All tracked items sorted by index * All tracked items sorted by index
*/ */
@@ -272,7 +279,17 @@ export function createScrollBreadcrumbsStore(): ScrollBreadcrumbsStore {
return new ScrollBreadcrumbsStore(); return new ScrollBreadcrumbsStore();
} }
let _scrollBreadcrumbsStore: ScrollBreadcrumbsStore | undefined;
/** /**
* Singleton scroll breadcrumbs store instance * App-wide scroll breadcrumbs store, created on first access.
*/ */
export const scrollBreadcrumbsStore = createScrollBreadcrumbsStore(); export function getScrollBreadcrumbsStore(): ScrollBreadcrumbsStore {
return (_scrollBreadcrumbsStore ??= createScrollBreadcrumbsStore());
}
// test-only reset, so specs don't share observer/scroll state
export function __resetScrollBreadcrumbsStore() {
_scrollBreadcrumbsStore?.destroy();
_scrollBreadcrumbsStore = undefined;
}
@@ -14,9 +14,10 @@ import { cubicOut } from 'svelte/easing';
import { slide } from 'svelte/transition'; import { slide } from 'svelte/transition';
import { import {
type BreadcrumbItem, type BreadcrumbItem,
scrollBreadcrumbsStore, getScrollBreadcrumbsStore,
} from '../../model'; } from '../../model';
const scrollBreadcrumbsStore = getScrollBreadcrumbsStore();
const breadcrumbs = $derived(scrollBreadcrumbsStore.scrolledPastItems); const breadcrumbs = $derived(scrollBreadcrumbsStore.scrolledPastItems);
const responsive = getContext<ResponsiveManager>('responsive'); const responsive = getContext<ResponsiveManager>('responsive');
@@ -1,8 +1,10 @@
<script> <script>
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { scrollBreadcrumbsStore } from '../../model'; import { getScrollBreadcrumbsStore } from '../../model';
import BreadcrumbHeader from './BreadcrumbHeader.svelte'; import BreadcrumbHeader from './BreadcrumbHeader.svelte';
const scrollBreadcrumbsStore = getScrollBreadcrumbsStore();
const sections = [ const sections = [
{ index: 100, title: 'Introduction' }, { index: 100, title: 'Introduction' },
{ index: 101, title: 'Typography' }, { index: 101, title: 'Typography' },
@@ -6,9 +6,11 @@
import { type Snippet } from 'svelte'; import { type Snippet } from 'svelte';
import { import {
type NavigationAction, type NavigationAction,
scrollBreadcrumbsStore, getScrollBreadcrumbsStore,
} from '../../model'; } from '../../model';
const scrollBreadcrumbsStore = getScrollBreadcrumbsStore();
interface Props { interface Props {
/** /**
* Navigation index * Navigation index