Skip to content

Instantly share code, notes, and snippets.

@colelawrence
Created December 28, 2023 14:26
Show Gist options
  • Save colelawrence/aa18d5eda4c90db656161f6b6c8687a6 to your computer and use it in GitHub Desktop.
Save colelawrence/aa18d5eda4c90db656161f6b6c8687a6 to your computer and use it in GitHub Desktop.
Qwik hook for searching items with Fuse.js
import type { NoSerialize, Signal } from "@builder.io/qwik";
import { noSerialize, useSignal, useVisibleTask$ } from "@builder.io/qwik";
import type { IFuseOptions } from "fuse.js";
import Fuse from "fuse.js";
export function useFuseSearch<T>(
config: {
items: Signal<T[]> | T[];
search: Signal<string> | string;
},
options?: Omit<IFuseOptions<T>, "getFn" | "sortFn" | "keys"> & {
keys: Array<NestedKeyOf<T> | { name: NestedKeyOf<T>; weight: number }>;
},
): Signal<T[]> {
const fuse = useSignal<NoSerialize<Fuse<T>>>();
const filtered = useSignal<T[]>(
Array.isArray(config.items) ? config.items : config.items.value,
);
// eslint-disable-next-line qwik/no-use-visible-task
useVisibleTask$(({ track }) => {
fuse.value = noSerialize(
new Fuse(
track(() =>
Array.isArray(config.items) ? config.items : config.items.value,
),
options,
),
);
});
// eslint-disable-next-line qwik/no-use-visible-task
useVisibleTask$(({ track }) => {
const searchValue = track(() =>
typeof config.search === "string" ? config.search : config.search.value,
);
const fuseValue = track(() => fuse.value);
if (searchValue && fuseValue) {
filtered.value = fuseValue
.search(searchValue)
.map((result) => ({ ...result.item }));
} else {
filtered.value = track(() =>
Array.isArray(config.items) ? config.items : config.items.value,
);
}
});
return filtered;
}
type NestedKeyOf<ObjectType> = {
[Key in keyof ObjectType & (number | string)]: ObjectType[Key] extends Array<
infer ArrayType
>
?
| `${Key}.${number}`
| `${Key}`
| (ArrayType extends object
? `${Key}.${number}.${NestedKeyOf<ArrayType>}`
: never)
: ObjectType[Key] extends object
? `${Key}.${NestedKeyOf<ObjectType[Key]>}` | `${Key}`
: `${Key}`;
}[keyof ObjectType & (number | string)];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment