diff --git a/.changeset/api-search-state-classes.md b/.changeset/api-search-state-classes.md new file mode 100644 index 000000000..9817e890b --- /dev/null +++ b/.changeset/api-search-state-classes.md @@ -0,0 +1,5 @@ +--- +'@fuzdev/fuz_ui': minor +--- + +refactor: replace the `create_api_search`/`create_module_declaration_search` getter/setter factories with `ApiSearchState`/`DeclarationSearchState` classes — nested `modules`/`declarations` `{all, filtered}` objects flatten to `modules`, `modules_filtered`, `declarations`, `declarations_filtered` (and `all` → `declarations` on `DeclarationSearchState`) diff --git a/src/lib/ApiIndex.svelte b/src/lib/ApiIndex.svelte index 793c733d5..7dad669a4 100644 --- a/src/lib/ApiIndex.svelte +++ b/src/lib/ApiIndex.svelte @@ -6,7 +6,7 @@ import DocsSearch from './DocsSearch.svelte'; import ApiModulesList from './ApiModulesList.svelte'; import ApiDeclarationList from './ApiDeclarationList.svelte'; - import { create_api_search } from './api_search.svelte.ts'; + import { ApiSearchState } from './api_search.svelte.ts'; const { library: library_prop, @@ -33,7 +33,7 @@ const get_library = set_library_context_with_fallback(() => library_prop, 'ApiIndex'); const library = $derived(get_library()); - const search = $derived(create_api_search(library)); + const search = $derived(new ApiSearchState(library)); @@ -49,21 +49,21 @@

{library.pkg_json.description}

- {#if search.modules.all.length + search.declarations.all.length > 1} + {#if search.modules.length + search.declarations.length > 1} {/if}
- + - + {/if} diff --git a/src/lib/ApiModule.svelte b/src/lib/ApiModule.svelte index d3ece3917..77cfe7760 100644 --- a/src/lib/ApiModule.svelte +++ b/src/lib/ApiModule.svelte @@ -17,7 +17,7 @@ import DocsLink from './DocsLink.svelte'; import DeclarationLink from './DeclarationLink.svelte'; import ApiDeclarationList from './ApiDeclarationList.svelte'; - import { create_module_declaration_search } from './api_search.svelte.ts'; + import { DeclarationSearchState } from './api_search.svelte.ts'; const { module_path: module_path_param, @@ -64,7 +64,7 @@ module?.path || (directory_modules ? module_path : '[missing module]') ); - const search = $derived(create_module_declaration_search(module?.declarations ?? [])); + const search = $derived(new DeclarationSearchState(module?.declarations ?? [])); // GitHub source URL for the module const source_url = $derived(module?.url_github); @@ -117,11 +117,11 @@ - {#if search.all.length > 1} + {#if search.declarations.length > 1}
diff --git a/src/lib/api_search.svelte.ts b/src/lib/api_search.svelte.ts index cc3243585..81734131c 100644 --- a/src/lib/api_search.svelte.ts +++ b/src/lib/api_search.svelte.ts @@ -2,94 +2,57 @@ import type { Declaration } from './declaration.svelte.ts'; import type { Library } from './library.svelte.ts'; import type { Module } from './module.svelte.ts'; -export interface DeclarationSearchState { - query: string; - all: Array; - filtered: Array; -} - -export interface ApiSearchState { - query: string; - modules: { - all: Array; - filtered: Array; - }; - declarations: { - all: Array; - filtered: Array; - }; -} - /** - * Creates unified search state for the API index page (modules and declarations). + * Unified search state for the API index page (modules and declarations). */ -export const create_api_search = (library: Library): ApiSearchState => { - let query = $state.raw(''); +export class ApiSearchState { + readonly library: Library; + + query: string = $state(''); - // Module filtering - const all_modules = $derived(library.modules_sorted); - const filtered_modules = $derived.by(() => { - if (!query.trim()) return all_modules; - const terms = query.trim().toLowerCase().split(/\s+/); - return all_modules.filter((m) => { + readonly modules: Array = $derived.by(() => this.library.modules_sorted); + + readonly modules_filtered: Array = $derived.by(() => { + if (!this.query.trim()) return this.modules; + const terms = this.query.trim().toLowerCase().split(/\s+/); + return this.modules.filter((m) => { const path_lower = m.path.toLowerCase(); const comment_lower = m.module_comment?.toLowerCase() ?? ''; return terms.every((term) => path_lower.includes(term) || comment_lower.includes(term)); }); }); - // Declaration filtering - const all_declarations = $derived(library.declarations); - const filtered_declarations = $derived.by(() => { - const items = query.trim() ? library.search_declarations(query) : all_declarations; + readonly declarations: Array = $derived.by(() => this.library.declarations); + + readonly declarations_filtered: Array = $derived.by(() => { + const items = this.query.trim() + ? this.library.search_declarations(this.query) + : this.declarations; // spread before sort — `items` may be the shared source array return [...items].sort((a, b) => a.name.localeCompare(b.name)); }); - return { - get query() { - return query; - }, - set query(v: string) { - query = v; - }, - modules: { - get all() { - return all_modules; - }, - get filtered() { - return filtered_modules; - } - }, - declarations: { - get all() { - return all_declarations; - }, - get filtered() { - return filtered_declarations; - } - } - }; -}; + constructor(library: Library) { + this.library = library; + } +} /** - * Creates search state for module-specific declaration lists. + * Search state for a module-specific declaration list. */ -export const create_module_declaration_search = ( - declarations: Array -): DeclarationSearchState => { - let query = $state.raw(''); +export class DeclarationSearchState { + readonly declarations: Array; - const all = $derived(declarations); + query: string = $state(''); - const filtered = $derived.by(() => { - const trimmed_query = query.trim(); - // spread before sort — `all` is the shared source array - if (!trimmed_query) return [...all].sort((a, b) => a.name.localeCompare(b.name)); + readonly filtered: Array = $derived.by(() => { + const trimmed_query = this.query.trim(); + // spread before sort — `declarations` is the shared source array + if (!trimmed_query) return [...this.declarations].sort((a, b) => a.name.localeCompare(b.name)); const terms = trimmed_query.toLowerCase().split(/\s+/); - const items = all.filter((d) => { + const items = this.declarations.filter((d) => { const name_lower = d.name.toLowerCase(); const kind_lower = d.kind.toLowerCase(); const module_path_lower = d.module_path.toLowerCase(); @@ -103,18 +66,7 @@ export const create_module_declaration_search = ( return items.sort((a, b) => a.name.localeCompare(b.name)); }); - return { - get query() { - return query; - }, - set query(v: string) { - query = v; - }, - get all() { - return all; - }, - get filtered() { - return filtered; - } - }; -}; + constructor(declarations: Array) { + this.declarations = declarations; + } +}