refactor(GetFonts): centralize filterManager/sortStore → fontStore bridge
Move the duplicated $effect blocks that mapped filterManager and sortStore into fontStore params out of Search, FontSearch and FilterControls into a single $effect.root in features/GetFonts/model/state/bindings.svelte.ts. Consumers now bind to the manager/store directly; the bridge is installed once via a side-effect import from the feature barrel.
This commit is contained in:
@@ -29,6 +29,12 @@ export {
|
|||||||
filterManager,
|
filterManager,
|
||||||
} from './state/manager.svelte';
|
} from './state/manager.svelte';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Side-effect import: installs the global filterManager+sortStore → fontStore
|
||||||
|
* bridge on first import of this feature barrel. No exports.
|
||||||
|
*/
|
||||||
|
import './state/bindings.svelte';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sorting logic
|
* Sorting logic
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* Bridges feature-level UI state (filterManager + sortStore) to the
|
||||||
|
* entity-level fontStore query params.
|
||||||
|
*
|
||||||
|
* Centralizing this here means consumers (Search, FontSearch,
|
||||||
|
* FilterControls, etc.) bind to the manager/store directly without
|
||||||
|
* each repeating the same mapping effect. The bridge is a singleton
|
||||||
|
* concern — it tracks singleton state and writes to a singleton query
|
||||||
|
* observer, so it lives at module scope, not in any individual widget.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { fontStore } from '$entities/Font';
|
||||||
|
import { untrack } from 'svelte';
|
||||||
|
import { mapManagerToParams } from '../../lib/mapper/mapManagerToParams';
|
||||||
|
import { sortStore } from '../store/sortStore.svelte';
|
||||||
|
import { filterManager } from './manager.svelte';
|
||||||
|
|
||||||
|
$effect.root(() => {
|
||||||
|
/**
|
||||||
|
* Mirror filter selections + debounced search query into fontStore params.
|
||||||
|
* untrack the write so fontStore's internal $state reads don't feed back
|
||||||
|
* into this effect's dependency graph.
|
||||||
|
*/
|
||||||
|
$effect(() => {
|
||||||
|
const params = mapManagerToParams(filterManager);
|
||||||
|
untrack(() => fontStore.setParams(params));
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mirror sort selection into fontStore.
|
||||||
|
*/
|
||||||
|
$effect(() => {
|
||||||
|
const apiSort = sortStore.apiValue;
|
||||||
|
untrack(() => fontStore.setSort(apiSort));
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -4,16 +4,12 @@
|
|||||||
Sits below the filter list, separated by a top border.
|
Sits below the filter list, separated by a top border.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { fontStore } from '$entities/Font';
|
|
||||||
import type { ResponsiveManager } from '$shared/lib';
|
import type { ResponsiveManager } from '$shared/lib';
|
||||||
import { cn } from '$shared/lib';
|
import { cn } from '$shared/lib';
|
||||||
import { Button } from '$shared/ui';
|
import { Button } from '$shared/ui';
|
||||||
import { Label } from '$shared/ui';
|
import { Label } from '$shared/ui';
|
||||||
import RefreshCwIcon from '@lucide/svelte/icons/refresh-cw';
|
import RefreshCwIcon from '@lucide/svelte/icons/refresh-cw';
|
||||||
import {
|
import { getContext } from 'svelte';
|
||||||
getContext,
|
|
||||||
untrack,
|
|
||||||
} from 'svelte';
|
|
||||||
import {
|
import {
|
||||||
SORT_OPTIONS,
|
SORT_OPTIONS,
|
||||||
filterManager,
|
filterManager,
|
||||||
@@ -31,11 +27,6 @@ const {
|
|||||||
class: className,
|
class: className,
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
$effect(() => {
|
|
||||||
const apiSort = sortStore.apiValue;
|
|
||||||
untrack(() => fontStore.setSort(apiSort));
|
|
||||||
});
|
|
||||||
|
|
||||||
const responsive = getContext<ResponsiveManager>('responsive');
|
const responsive = getContext<ResponsiveManager>('responsive');
|
||||||
const isMobileOrTabletPortrait = $derived(responsive.isMobile || responsive.isTabletPortrait);
|
const isMobileOrTabletPortrait = $derived(responsive.isMobile || responsive.isTabletPortrait);
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
<!--
|
<!--
|
||||||
Component: Search
|
Component: Search
|
||||||
Typeface search input for the comparison view.
|
Typeface search input for the comparison view.
|
||||||
Updates the global filterManager query to filter the font list.
|
Writes through filterManager; the global bridge in $features/GetFonts
|
||||||
|
propagates the value into fontStore.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { fontStore } from '$entities/Font';
|
import { filterManager } from '$features/GetFonts';
|
||||||
import {
|
|
||||||
filterManager,
|
|
||||||
mapManagerToParams,
|
|
||||||
} from '$features/GetFonts';
|
|
||||||
import { SearchBar } from '$shared/ui';
|
import { SearchBar } from '$shared/ui';
|
||||||
import { untrack } from 'svelte';
|
|
||||||
|
|
||||||
$effect(() => {
|
|
||||||
const params = mapManagerToParams(filterManager);
|
|
||||||
untrack(() => fontStore.setParams(params));
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="p-6 border-b border-black/5">
|
<div class="p-6 border-b border-black/5">
|
||||||
|
|||||||
@@ -3,12 +3,10 @@
|
|||||||
Provides a search input and filtration for fonts
|
Provides a search input and filtration for fonts
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { fontStore } from '$entities/Font';
|
|
||||||
import {
|
import {
|
||||||
FilterControls,
|
FilterControls,
|
||||||
Filters,
|
Filters,
|
||||||
filterManager,
|
filterManager,
|
||||||
mapManagerToParams,
|
|
||||||
} from '$features/GetFonts';
|
} from '$features/GetFonts';
|
||||||
import { springySlideFade } from '$shared/lib';
|
import { springySlideFade } from '$shared/lib';
|
||||||
import {
|
import {
|
||||||
@@ -16,7 +14,6 @@ import {
|
|||||||
SearchBar,
|
SearchBar,
|
||||||
} from '$shared/ui';
|
} from '$shared/ui';
|
||||||
import SlidersHorizontalIcon from '@lucide/svelte/icons/sliders-horizontal';
|
import SlidersHorizontalIcon from '@lucide/svelte/icons/sliders-horizontal';
|
||||||
import { untrack } from 'svelte';
|
|
||||||
import { cubicOut } from 'svelte/easing';
|
import { cubicOut } from 'svelte/easing';
|
||||||
import {
|
import {
|
||||||
Tween,
|
Tween,
|
||||||
@@ -34,11 +31,6 @@ interface Props {
|
|||||||
|
|
||||||
let { showFilters = $bindable(true) }: Props = $props();
|
let { showFilters = $bindable(true) }: Props = $props();
|
||||||
|
|
||||||
$effect(() => {
|
|
||||||
const params = mapManagerToParams(filterManager);
|
|
||||||
untrack(() => fontStore.setParams(params));
|
|
||||||
});
|
|
||||||
|
|
||||||
const transform = new Tween(
|
const transform = new Tween(
|
||||||
{ scale: 1, rotate: 0 },
|
{ scale: 1, rotate: 0 },
|
||||||
{ duration: 250, easing: cubicOut },
|
{ duration: 250, easing: cubicOut },
|
||||||
|
|||||||
Reference in New Issue
Block a user