feature/comparison-slider #19
@@ -15,5 +15,5 @@ export { filterManager } from './model/state/manager.svelte';
|
|||||||
export {
|
export {
|
||||||
FilterControls,
|
FilterControls,
|
||||||
Filters,
|
Filters,
|
||||||
FontSearch,
|
SuggestedFonts,
|
||||||
} from './ui';
|
} from './ui';
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
<!--
|
|
||||||
Component: FontSearch
|
|
||||||
|
|
||||||
Combines search input with font list display
|
|
||||||
-->
|
|
||||||
<script lang="ts">
|
|
||||||
import { fontshareStore } from '$entities/Font';
|
|
||||||
import { SearchBar } from '$shared/ui';
|
|
||||||
import { onMount } from 'svelte';
|
|
||||||
import { mapManagerToParams } from '../../lib';
|
|
||||||
import { filterManager } from '../../model';
|
|
||||||
import SuggestedFonts from '../SuggestedFonts/SuggestedFonts.svelte';
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
/**
|
|
||||||
* The Pairing:
|
|
||||||
* We "plug" this manager into the global store.
|
|
||||||
* addBinding returns a function that removes this binding when the component unmounts.
|
|
||||||
*/
|
|
||||||
const unbind = fontshareStore.addBinding(() => mapManagerToParams(filterManager));
|
|
||||||
|
|
||||||
return unbind;
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<SearchBar
|
|
||||||
id="font-search"
|
|
||||||
class="w-full"
|
|
||||||
placeholder="Search fonts by name..."
|
|
||||||
bind:value={filterManager.queryValue}
|
|
||||||
>
|
|
||||||
<SuggestedFonts />
|
|
||||||
</SearchBar>
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import Filters from './Filters/Filters.svelte';
|
import Filters from './Filters/Filters.svelte';
|
||||||
import FilterControls from './FiltersControl/FilterControls.svelte';
|
import FilterControls from './FiltersControl/FilterControls.svelte';
|
||||||
import FontSearch from './FontSearch/FontSearch.svelte';
|
import SuggestedFonts from './SuggestedFonts/SuggestedFonts.svelte';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
FilterControls,
|
FilterControls,
|
||||||
Filters,
|
Filters,
|
||||||
FontSearch,
|
SuggestedFonts,
|
||||||
};
|
};
|
||||||
|
|||||||
1
src/widgets/FontSearch/index.ts
Normal file
1
src/widgets/FontSearch/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export { FontSearch } from './ui';
|
||||||
107
src/widgets/FontSearch/ui/FontSearch/FontSearch.svelte
Normal file
107
src/widgets/FontSearch/ui/FontSearch/FontSearch.svelte
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
<!--
|
||||||
|
Component: FontSearch
|
||||||
|
|
||||||
|
Combines search input with font list display
|
||||||
|
-->
|
||||||
|
<script lang="ts">
|
||||||
|
import { fontshareStore } from '$entities/Font';
|
||||||
|
import {
|
||||||
|
FilterControls,
|
||||||
|
Filters,
|
||||||
|
SuggestedFonts,
|
||||||
|
filterManager,
|
||||||
|
mapManagerToParams,
|
||||||
|
} from '$features/GetFonts';
|
||||||
|
import { springySlideFade } from '$shared/lib';
|
||||||
|
import { Button } from '$shared/shadcn/ui/button';
|
||||||
|
import { cn } from '$shared/shadcn/utils/shadcn-utils';
|
||||||
|
import { SearchBar } from '$shared/ui';
|
||||||
|
import FunnelIcon from '@lucide/svelte/icons/funnel';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import { cubicOut } from 'svelte/easing';
|
||||||
|
import {
|
||||||
|
Tween,
|
||||||
|
prefersReducedMotion,
|
||||||
|
} from 'svelte/motion';
|
||||||
|
import { type SlideParams } from 'svelte/transition';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
showFilters?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
let { showFilters = $bindable(false) }: Props = $props();
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
/**
|
||||||
|
* The Pairing:
|
||||||
|
* We "plug" this manager into the global store.
|
||||||
|
* addBinding returns a function that removes this binding when the component unmounts.
|
||||||
|
*/
|
||||||
|
const unbind = fontshareStore.addBinding(() => mapManagerToParams(filterManager));
|
||||||
|
|
||||||
|
return unbind;
|
||||||
|
});
|
||||||
|
|
||||||
|
const transform = new Tween(
|
||||||
|
{ scale: 1, rotate: 0 },
|
||||||
|
{ duration: 250, easing: cubicOut },
|
||||||
|
);
|
||||||
|
|
||||||
|
const slideConfig = $derived<SlideParams>({
|
||||||
|
duration: prefersReducedMotion.current ? 0 : 200,
|
||||||
|
easing: cubicOut,
|
||||||
|
axis: 'y',
|
||||||
|
});
|
||||||
|
|
||||||
|
function toggleFilters() {
|
||||||
|
showFilters = !showFilters;
|
||||||
|
|
||||||
|
transform.set({ scale: 0.9, rotate: 2 }).then(() => {
|
||||||
|
transform.set({ scale: 1, rotate: 0 });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex flex-col gap-2 relative">
|
||||||
|
<SearchBar
|
||||||
|
id="font-search"
|
||||||
|
class="w-full"
|
||||||
|
placeholder="Search fonts by name..."
|
||||||
|
bind:value={filterManager.queryValue}
|
||||||
|
>
|
||||||
|
<SuggestedFonts />
|
||||||
|
</SearchBar>
|
||||||
|
|
||||||
|
<div class="absolute right-5 top-10 translate-y-[-50%] pl-5 border-l-2">
|
||||||
|
<div style:transform="scale({transform.current.scale}) rotate({transform.current.rotate}deg)">
|
||||||
|
<Button
|
||||||
|
class={cn(
|
||||||
|
'cursor-pointer will-change-transform hover:bg-inherit hover:*:stroke-indigo-500',
|
||||||
|
showFilters ? 'hover:*:stroke-indigo-500/80' : 'hover:*:stroke-indigo-500',
|
||||||
|
)}
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
onclick={toggleFilters}
|
||||||
|
>
|
||||||
|
<FunnelIcon
|
||||||
|
class={cn(
|
||||||
|
'size-8 stroke-indigo-600/50 transition-all duration-150',
|
||||||
|
showFilters ? 'stroke-indigo-600' : 'stroke-indigo-600/50',
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if showFilters}
|
||||||
|
<div
|
||||||
|
transition:springySlideFade|local={slideConfig}
|
||||||
|
class="will-change-[height,opacity] contain-layout overflow-hidden"
|
||||||
|
>
|
||||||
|
<div class="grid gap-1 grid-cols-[repeat(auto-fit,minmax(8em,14em))]">
|
||||||
|
<Filters />
|
||||||
|
<FilterControls class="ml-auto py-1" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
3
src/widgets/FontSearch/ui/index.ts
Normal file
3
src/widgets/FontSearch/ui/index.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import FontSearch from './FontSearch/FontSearch.svelte';
|
||||||
|
|
||||||
|
export { FontSearch };
|
||||||
3
src/widgets/index.ts
Normal file
3
src/widgets/index.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export { ComparisonSlider } from './ComparisonSlider';
|
||||||
|
export { FontSearch } from './FontSearch';
|
||||||
|
export { TypographyMenu } from './TypographySettings';
|
||||||
Reference in New Issue
Block a user