Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/api-search-state-classes.md
Original file line number Diff line number Diff line change
@@ -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`)
18 changes: 9 additions & 9 deletions src/lib/ApiIndex.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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));
</script>

<svelte:head>
Expand All @@ -49,21 +49,21 @@
<section>
<p>{library.pkg_json.description}</p>

{#if search.modules.all.length + search.declarations.all.length > 1}
{#if search.modules.length + search.declarations.length > 1}
<DocsSearch
module_count={search.modules.all.length}
declaration_count={search.declarations.all.length}
filtered_module_count={search.query.trim() ? search.modules.filtered.length : undefined}
module_count={search.modules.length}
declaration_count={search.declarations.length}
filtered_module_count={search.query.trim() ? search.modules_filtered.length : undefined}
filtered_declaration_count={search.query.trim()
? search.declarations.filtered.length
? search.declarations_filtered.length
: undefined}
bind:search_query={search.query}
/>
{/if}
</section>

<ApiModulesList modules={search.modules.filtered} search_query={search.query} />
<ApiModulesList modules={search.modules_filtered} search_query={search.query} />

<ApiDeclarationList declarations={search.declarations.filtered} search_query={search.query} />
<ApiDeclarationList declarations={search.declarations_filtered} search_query={search.query} />
{/if}
</TomeContent>
8 changes: 4 additions & 4 deletions src/lib/ApiModule.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -117,11 +117,11 @@
<TomeSection>
<TomeSectionHeader text="Declarations" />

{#if search.all.length > 1}
{#if search.declarations.length > 1}
<section>
<DocsSearch
placeholder="search declarations in this module..."
declaration_count={search.all.length}
declaration_count={search.declarations.length}
filtered_declaration_count={search.query.trim() ? search.filtered.length : undefined}
bind:search_query={search.query}
/>
Expand Down
116 changes: 34 additions & 82 deletions src/lib/api_search.svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<Declaration>;
filtered: Array<Declaration>;
}

export interface ApiSearchState {
query: string;
modules: {
all: Array<Module>;
filtered: Array<Module>;
};
declarations: {
all: Array<Declaration>;
filtered: Array<Declaration>;
};
}

/**
* 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<Module> = $derived.by(() => this.library.modules_sorted);

readonly modules_filtered: Array<Module> = $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<Declaration> = $derived.by(() => this.library.declarations);

readonly declarations_filtered: Array<Declaration> = $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<Declaration>
): DeclarationSearchState => {
let query = $state.raw('');
export class DeclarationSearchState {
readonly declarations: Array<Declaration>;

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<Declaration> = $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();
Expand All @@ -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<Declaration>) {
this.declarations = declarations;
}
}