diff --git a/package-lock.json b/package-lock.json index ddbdb4f..6f1eb66 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "expo-status-bar": "1.12.1", "expo-system-ui": "3.0.4", "expo-web-browser": "13.0.3", + "fuse.js": "7.0.0", "immer": "10.1.1", "lottie-react-native": "6.7.0", "react": "18.2.0", @@ -14240,6 +14241,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/fuse.js": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.0.0.tgz", + "integrity": "sha512-14F4hBIxqKvD4Zz/XjDc3y94mNZN6pRv3U13Udo0lNLCWRBUsrMv2xwcF/y/Z5sV6+FQW+/ow68cHpm4sunt8Q==", + "engines": { + "node": ">=10" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", diff --git a/package.json b/package.json index 4a68399..fcfd25c 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "expo-status-bar": "1.12.1", "expo-system-ui": "3.0.4", "expo-web-browser": "13.0.3", + "fuse.js": "7.0.0", "immer": "10.1.1", "lottie-react-native": "6.7.0", "react": "18.2.0", diff --git a/presentation/react-native/components/HabitForm/IconSelectorModal.tsx b/presentation/react-native/components/HabitForm/IconSelectorModal.tsx index d130c8b..e28d2a6 100644 --- a/presentation/react-native/components/HabitForm/IconSelectorModal.tsx +++ b/presentation/react-native/components/HabitForm/IconSelectorModal.tsx @@ -4,6 +4,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-native-fontawesome" import { memo, useCallback, useEffect, useState, useTransition } from "react" import { Modal, ScrollView, View } from "react-native" import { Button, List, Text, TextInput } from "react-native-paper" +import Fuse from "fuse.js" import { IconsList } from "./IconsList" @@ -30,12 +31,19 @@ const iconNames = Object.keys(fas).map((key) => { return fas[key]?.iconName ?? key }) +const fuseOptions = { + keys: ["iconName"], + threshold: 0.4, +} + +const fuse = new Fuse(iconNames, fuseOptions) + const findIconsInLibrary = (icon: string): string[] => { - return iconNames - .filter((name, index, self) => { - return name.includes(icon) && self.indexOf(name) === index - }) - .slice(0, 50) + const results = fuse.search(icon).map((result) => { + return result.item + }) + const uniqueResults = Array.from(new Set(results)) + return uniqueResults.slice(0, 50) } export const IconSelectorModal: React.FC = ({