Compare commits
3 Commits
ac41f324b1
...
b0afa0145d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b0afa0145d | ||
|
|
e01a746460 | ||
|
|
53baacf05a |
@@ -1,7 +0,0 @@
|
|||||||
import { FONT_CATEGORIES } from './model/state';
|
|
||||||
import { categoryFilterStore } from './store/categoryFilterStore';
|
|
||||||
|
|
||||||
export {
|
|
||||||
categoryFilterStore,
|
|
||||||
FONT_CATEGORIES,
|
|
||||||
};
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
import type {
|
|
||||||
FilterModel,
|
|
||||||
Property,
|
|
||||||
} from '$shared/store/createFilterStore';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Model of state for CategoryFilter
|
|
||||||
*/
|
|
||||||
export type CategoryFilterModel = FilterModel;
|
|
||||||
|
|
||||||
export const FONT_CATEGORIES: Property[] = [
|
|
||||||
{
|
|
||||||
id: 'serif',
|
|
||||||
name: 'Serif',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'sans-serif',
|
|
||||||
name: 'Sans-serif',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'display',
|
|
||||||
name: 'Display',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'handwriting',
|
|
||||||
name: 'Handwriting',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'monospace',
|
|
||||||
name: 'Monospace',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'script',
|
|
||||||
name: 'Script',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'slab',
|
|
||||||
name: 'Slab',
|
|
||||||
},
|
|
||||||
] as const;
|
|
||||||
5
src/features/FilterFonts/index.ts
Normal file
5
src/features/FilterFonts/index.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export { categoryFilterStore } from './model/stores/categoryFilterStore';
|
||||||
|
export { providersFilterStore } from './model/stores/providersFilterStore';
|
||||||
|
export { subsetsFilterStore } from './model/stores/subsetsFilterStore';
|
||||||
|
|
||||||
|
export { clearAllFilters } from './model/services/clearAllFilters/clearAllFilters';
|
||||||
70
src/features/FilterFonts/model/const/const.ts
Normal file
70
src/features/FilterFonts/model/const/const.ts
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import type { Property } from '$shared/store/createFilterStore';
|
||||||
|
|
||||||
|
export const FONT_CATEGORIES: Property[] = [
|
||||||
|
{
|
||||||
|
id: 'serif',
|
||||||
|
name: 'Serif',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'sans-serif',
|
||||||
|
name: 'Sans-serif',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'display',
|
||||||
|
name: 'Display',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'handwriting',
|
||||||
|
name: 'Handwriting',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'monospace',
|
||||||
|
name: 'Monospace',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'script',
|
||||||
|
name: 'Script',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'slab',
|
||||||
|
name: 'Slab',
|
||||||
|
},
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export const FONT_PROVIDERS: Property[] = [
|
||||||
|
{
|
||||||
|
id: 'google',
|
||||||
|
name: 'Google Fonts',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'fontshare',
|
||||||
|
name: 'Fontshare',
|
||||||
|
},
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export const FONT_SUBSETS: Property[] = [
|
||||||
|
{
|
||||||
|
id: 'latin',
|
||||||
|
name: 'Latin',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'latin-ext',
|
||||||
|
name: 'Latin Extended',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'cyrillic',
|
||||||
|
name: 'Cyrillic',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'greek',
|
||||||
|
name: 'Greek',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'arabic',
|
||||||
|
name: 'Arabic',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'devanagari',
|
||||||
|
name: 'Devanagari',
|
||||||
|
},
|
||||||
|
] as const;
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { categoryFilterStore } from '../../stores/categoryFilterStore';
|
||||||
|
import { providersFilterStore } from '../../stores/providersFilterStore';
|
||||||
|
import { subsetsFilterStore } from '../../stores/subsetsFilterStore';
|
||||||
|
|
||||||
|
export function clearAllFilters() {
|
||||||
|
categoryFilterStore.deselectAllProperties();
|
||||||
|
providersFilterStore.deselectAllProperties();
|
||||||
|
subsetsFilterStore.deselectAllProperties();
|
||||||
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
import { createFilterStore } from '$shared/store/createFilterStore';
|
|
||||||
import {
|
import {
|
||||||
type CategoryFilterModel,
|
type FilterModel,
|
||||||
FONT_CATEGORIES,
|
createFilterStore,
|
||||||
} from '../model/state';
|
} from '$shared/store/createFilterStore';
|
||||||
|
import { FONT_CATEGORIES } from '../const/const';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initial state for CategoryFilter
|
* Initial state for CategoryFilter
|
||||||
*/
|
*/
|
||||||
export const initialState: CategoryFilterModel = {
|
export const initialState: FilterModel = {
|
||||||
searchQuery: '',
|
searchQuery: '',
|
||||||
properties: FONT_CATEGORIES,
|
properties: FONT_CATEGORIES,
|
||||||
};
|
};
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
import { createFilterStore } from '$shared/store/createFilterStore';
|
|
||||||
import {
|
import {
|
||||||
FONT_PROVIDERS,
|
type FilterModel,
|
||||||
type ProvidersFilterModel,
|
createFilterStore,
|
||||||
} from '../model/state';
|
} from '$shared/store/createFilterStore';
|
||||||
|
import { FONT_PROVIDERS } from '../const/const';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initial state for ProvidersFilter
|
* Initial state for ProvidersFilter
|
||||||
*/
|
*/
|
||||||
export const initialState: ProvidersFilterModel = {
|
export const initialState: FilterModel = {
|
||||||
searchQuery: '',
|
searchQuery: '',
|
||||||
properties: FONT_PROVIDERS,
|
properties: FONT_PROVIDERS,
|
||||||
};
|
};
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
import { createFilterStore } from '$shared/store/createFilterStore';
|
|
||||||
import {
|
import {
|
||||||
FONT_SUBSETS,
|
type FilterModel,
|
||||||
type SubsetsFilterModel,
|
createFilterStore,
|
||||||
} from '../model/state';
|
} from '$shared/store/createFilterStore';
|
||||||
|
import { FONT_SUBSETS } from '../const/const';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initial state for SubsetsFilter
|
* Initial state for SubsetsFilter
|
||||||
*/
|
*/
|
||||||
export const initialState: SubsetsFilterModel = {
|
const initialState: FilterModel = {
|
||||||
searchQuery: '',
|
searchQuery: '',
|
||||||
properties: FONT_SUBSETS,
|
properties: FONT_SUBSETS,
|
||||||
};
|
};
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { FONT_PROVIDERS } from './model/state';
|
|
||||||
import { providersFilterStore } from './store/providersFilterStore';
|
|
||||||
|
|
||||||
export {
|
|
||||||
FONT_PROVIDERS,
|
|
||||||
providersFilterStore,
|
|
||||||
};
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
import type {
|
|
||||||
FilterModel,
|
|
||||||
Property,
|
|
||||||
} from '$shared/store/createFilterStore';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Model of state for ProvidersFilter
|
|
||||||
*/
|
|
||||||
export type ProvidersFilterModel = FilterModel;
|
|
||||||
|
|
||||||
export const FONT_PROVIDERS: Property[] = [
|
|
||||||
{
|
|
||||||
id: 'google',
|
|
||||||
name: 'Google Fonts',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'fontshare',
|
|
||||||
name: 'Fontshare',
|
|
||||||
},
|
|
||||||
] as const;
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { FONT_SUBSETS } from './model/state';
|
|
||||||
import { subsetsFilterStore } from './store/subsetsFilterStore';
|
|
||||||
|
|
||||||
export {
|
|
||||||
FONT_SUBSETS,
|
|
||||||
subsetsFilterStore,
|
|
||||||
};
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
import type {
|
|
||||||
FilterModel,
|
|
||||||
Property,
|
|
||||||
} from '$shared/store/createFilterStore';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Model of state for SubsetsFilter
|
|
||||||
*/
|
|
||||||
export type SubsetsFilterModel = FilterModel;
|
|
||||||
|
|
||||||
export const FONT_SUBSETS: Property[] = [
|
|
||||||
{
|
|
||||||
id: 'latin',
|
|
||||||
name: 'Latin',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'latin-ext',
|
|
||||||
name: 'Latin Extended',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'cyrillic',
|
|
||||||
name: 'Cyrillic',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'greek',
|
|
||||||
name: 'Greek',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'arabic',
|
|
||||||
name: 'Arabic',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'devanagari',
|
|
||||||
name: 'Devanagari',
|
|
||||||
},
|
|
||||||
] as const;
|
|
||||||
@@ -84,6 +84,16 @@ const hasSelection = $derived(selectedCount > 0);
|
|||||||
>
|
>
|
||||||
<h4 class="text-sm font-semibold">{displayedLabel}</h4>
|
<h4 class="text-sm font-semibold">{displayedLabel}</h4>
|
||||||
|
|
||||||
|
<!-- Badge only appears when items are selected to avoid clutter -->
|
||||||
|
{#if hasSelection}
|
||||||
|
<Badge
|
||||||
|
variant="secondary"
|
||||||
|
class="mr-auto h-5 min-w-5 px-1.5 text-xs font-medium tabular-nums"
|
||||||
|
>
|
||||||
|
{selectedCount}
|
||||||
|
</Badge>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<!-- Chevron rotates based on open state for visual feedback -->
|
<!-- Chevron rotates based on open state for visual feedback -->
|
||||||
<div
|
<div
|
||||||
class="shrink-0 transition-transform duration-200 ease-out"
|
class="shrink-0 transition-transform duration-200 ease-out"
|
||||||
@@ -91,15 +101,6 @@ const hasSelection = $derived(selectedCount > 0);
|
|||||||
>
|
>
|
||||||
<ChevronDownIcon class="h-4 w-4" />
|
<ChevronDownIcon class="h-4 w-4" />
|
||||||
</div>
|
</div>
|
||||||
<!-- Badge only appears when items are selected to avoid clutter -->
|
|
||||||
{#if hasSelection}
|
|
||||||
<Badge
|
|
||||||
variant="secondary"
|
|
||||||
class="ml-auto h-5 min-w-5 px-1.5 text-xs font-medium tabular-nums"
|
|
||||||
>
|
|
||||||
{selectedCount}
|
|
||||||
</Badge>
|
|
||||||
{/if}
|
|
||||||
</Collapsible.Trigger>
|
</Collapsible.Trigger>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -10,11 +10,12 @@
|
|||||||
* Buttons are equally sized (flex-1) for balanced layout. Note:
|
* Buttons are equally sized (flex-1) for balanced layout. Note:
|
||||||
* Functionality not yet implemented - wire up to filter stores.
|
* Functionality not yet implemented - wire up to filter stores.
|
||||||
*/
|
*/
|
||||||
|
import { clearAllFilters } from '$features/FilterFonts';
|
||||||
import { Button } from '$shared/shadcn/ui/button';
|
import { Button } from '$shared/shadcn/ui/button';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex flex-row gap-2">
|
<div class="flex flex-row gap-2">
|
||||||
<Button variant="outline" class="flex-1 cursor-pointer">
|
<Button variant="outline" class="flex-1 cursor-pointer" onclick={clearAllFilters}>
|
||||||
Reset
|
Reset
|
||||||
</Button>
|
</Button>
|
||||||
<Button class="flex-1 cursor-pointer">
|
<Button class="flex-1 cursor-pointer">
|
||||||
|
|||||||
@@ -12,9 +12,9 @@
|
|||||||
* Uses $derived for reactive access to filter states, ensuring UI updates
|
* Uses $derived for reactive access to filter states, ensuring UI updates
|
||||||
* when selections change through any means (sidebar, programmatically, etc.).
|
* when selections change through any means (sidebar, programmatically, etc.).
|
||||||
*/
|
*/
|
||||||
import { categoryFilterStore } from '$features/CategoryFilter';
|
import { categoryFilterStore } from '$features/FilterFonts';
|
||||||
import { providersFilterStore } from '$features/ProvidersFilter';
|
import { providersFilterStore } from '$features/FilterFonts';
|
||||||
import { subsetsFilterStore } from '$features/SubsetsFilter';
|
import { subsetsFilterStore } from '$features/FilterFonts';
|
||||||
import CheckboxFilter from '$shared/ui/CheckboxFilter/CheckboxFilter.svelte';
|
import CheckboxFilter from '$shared/ui/CheckboxFilter/CheckboxFilter.svelte';
|
||||||
|
|
||||||
/** Reactive properties from providers filter store */
|
/** Reactive properties from providers filter store */
|
||||||
|
|||||||
Reference in New Issue
Block a user