feat(FontStore): implement lifecycle, param management, async methods, shortcuts, pagination, category getters, singleton — all tests green
This commit is contained in:
@@ -102,54 +102,105 @@ export class FontStore {
|
|||||||
|
|
||||||
// -- Lifecycle --
|
// -- Lifecycle --
|
||||||
|
|
||||||
destroy(): void {}
|
destroy() {
|
||||||
|
this.#unsubscribe();
|
||||||
|
this.#observer.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
// -- Param management --
|
// -- Param management --
|
||||||
|
|
||||||
setParams(_updates: Partial<FontStoreParams>): void {}
|
setParams(updates: Partial<FontStoreParams>) {
|
||||||
invalidate(): void {}
|
this.#params = { ...this.#params, ...updates };
|
||||||
|
this.#observer.setOptions(this.buildOptions());
|
||||||
|
}
|
||||||
|
invalidate() {
|
||||||
|
this.#qc.invalidateQueries({ queryKey: this.buildQueryKey(this.#params) });
|
||||||
|
}
|
||||||
|
|
||||||
// -- Async operations --
|
// -- Async operations --
|
||||||
|
|
||||||
async refetch(): Promise<void> {}
|
async refetch() {
|
||||||
async prefetch(_params: FontStoreParams): Promise<void> {}
|
this.#observer.setOptions(this.buildOptions());
|
||||||
cancel(): void {}
|
await this.#observer.refetch();
|
||||||
getCachedData(): UnifiedFont[] | undefined {
|
}
|
||||||
return undefined;
|
|
||||||
|
async prefetch(params: FontStoreParams) {
|
||||||
|
await this.#qc.prefetchInfiniteQuery(this.buildOptions(params));
|
||||||
|
}
|
||||||
|
|
||||||
|
cancel() {
|
||||||
|
this.#qc.cancelQueries({ queryKey: this.buildQueryKey(this.#params) });
|
||||||
|
}
|
||||||
|
|
||||||
|
getCachedData(): UnifiedFont[] | undefined {
|
||||||
|
const data = this.#qc.getQueryData<InfiniteData<FontPage, PageParam>>(
|
||||||
|
this.buildQueryKey(this.#params),
|
||||||
|
);
|
||||||
|
if (!data) return undefined;
|
||||||
|
return data.pages.flatMap(p => p.fonts);
|
||||||
|
}
|
||||||
|
|
||||||
|
setQueryData(updater: (old: UnifiedFont[] | undefined) => UnifiedFont[]) {
|
||||||
|
this.#qc.setQueryData<InfiniteData<FontPage, PageParam>>(
|
||||||
|
this.buildQueryKey(this.#params),
|
||||||
|
old => {
|
||||||
|
const flatFonts = old?.pages.flatMap(p => p.fonts);
|
||||||
|
const newFonts = updater(flatFonts);
|
||||||
|
const template = old?.pages[0] ?? { total: newFonts.length, limit: newFonts.length, offset: 0 };
|
||||||
|
return {
|
||||||
|
pages: [{ ...template, fonts: newFonts }],
|
||||||
|
pageParams: [{ offset: 0 } as PageParam],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
setQueryData(_updater: (old: UnifiedFont[] | undefined) => UnifiedFont[]): void {}
|
|
||||||
|
|
||||||
// -- Filter shortcuts --
|
// -- Filter shortcuts --
|
||||||
|
|
||||||
setProviders(_v: ProxyFontsParams['providers']): void {}
|
setProviders(v: ProxyFontsParams['providers']) {
|
||||||
setCategories(_v: ProxyFontsParams['categories']): void {}
|
this.setParams({ providers: v });
|
||||||
setSubsets(_v: ProxyFontsParams['subsets']): void {}
|
}
|
||||||
setSearch(_v: string): void {}
|
setCategories(v: ProxyFontsParams['categories']) {
|
||||||
setSort(_v: ProxyFontsParams['sort']): void {}
|
this.setParams({ categories: v });
|
||||||
|
}
|
||||||
|
setSubsets(v: ProxyFontsParams['subsets']) {
|
||||||
|
this.setParams({ subsets: v });
|
||||||
|
}
|
||||||
|
setSearch(v: string) {
|
||||||
|
this.setParams({ q: v || undefined });
|
||||||
|
}
|
||||||
|
setSort(v: ProxyFontsParams['sort']) {
|
||||||
|
this.setParams({ sort: v });
|
||||||
|
}
|
||||||
|
|
||||||
// -- Pagination navigation --
|
// -- Pagination navigation --
|
||||||
|
|
||||||
async nextPage(): Promise<void> {}
|
async nextPage(): Promise<void> {
|
||||||
prevPage(): void {} // no-op: infinite scroll only loads forward
|
await this.#observer.fetchNextPage();
|
||||||
|
}
|
||||||
|
prevPage(): void {} // no-op: infinite scroll accumulates forward only; method kept for API compatibility
|
||||||
goToPage(_page: number): void {} // no-op
|
goToPage(_page: number): void {} // no-op
|
||||||
setLimit(_limit: number): void {}
|
|
||||||
|
setLimit(limit: number) {
|
||||||
|
this.setParams({ limit });
|
||||||
|
}
|
||||||
|
|
||||||
// -- Category views --
|
// -- Category views --
|
||||||
|
|
||||||
get sansSerifFonts(): UnifiedFont[] {
|
get sansSerifFonts() {
|
||||||
return [];
|
return this.fonts.filter(f => f.category === 'sans-serif');
|
||||||
}
|
}
|
||||||
get serifFonts(): UnifiedFont[] {
|
get serifFonts() {
|
||||||
return [];
|
return this.fonts.filter(f => f.category === 'serif');
|
||||||
}
|
}
|
||||||
get displayFonts(): UnifiedFont[] {
|
get displayFonts() {
|
||||||
return [];
|
return this.fonts.filter(f => f.category === 'display');
|
||||||
}
|
}
|
||||||
get handwritingFonts(): UnifiedFont[] {
|
get handwritingFonts() {
|
||||||
return [];
|
return this.fonts.filter(f => f.category === 'handwriting');
|
||||||
}
|
}
|
||||||
get monospaceFonts(): UnifiedFont[] {
|
get monospaceFonts() {
|
||||||
return [];
|
return this.fonts.filter(f => f.category === 'monospace');
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- Private helpers (TypeScript-private so tests can spy via `as any`) --
|
// -- Private helpers (TypeScript-private so tests can spy via `as any`) --
|
||||||
@@ -207,3 +258,5 @@ export class FontStore {
|
|||||||
export function createFontStore(params: FontStoreParams = {}): FontStore {
|
export function createFontStore(params: FontStoreParams = {}): FontStore {
|
||||||
return new FontStore(params);
|
return new FontStore(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const fontStore = new FontStore({ limit: 50 });
|
||||||
|
|||||||
Reference in New Issue
Block a user