diff --git a/src/components/searchModes/fuzzyMode.tsx b/src/components/searchModes/fuzzyMode.tsx
new file mode 100644
index 0000000..5d78f47
--- /dev/null
+++ b/src/components/searchModes/fuzzyMode.tsx
@@ -0,0 +1,48 @@
+import * as React from 'react'
+import { ModeShape } from '.'
+import { Highlight } from '../Highlight'
+
+export const fuzzyMode: ModeShape = {
+ getSearchParams(searchKey) {
+ const matchNode = (node: TreeNode) => fuzzyMatch(searchKey, node.path)
+ return {
+ matchNode,
+ }
+ },
+ renderNodeLabelText(node, searchKey) {
+ const { name, path } = node
+ const indexes = fuzzyMatchIndexes(searchKey, path, path.length - name.length)
+ return (
+
+ (i === 0 ? `^.` : `(?<=^.{${i}}).`)).join('|'))}
+ text={name}
+ />
+
+ )
+ },
+}
+
+function fuzzyMatch(input: string, sample: string) {
+ let i = 0,
+ j = 0
+ while (i < input.length && j < sample.length) {
+ if (input[i] === sample[j]) i++
+ j++
+ }
+ return i === input.length
+}
+
+function fuzzyMatchIndexes(input: string, sample: string, shift: number = 0) {
+ const r: number[] = []
+ let i = 0,
+ j = 0
+ while (i < input.length && j < sample.length) {
+ if (input[i] === sample[j]) {
+ if (j >= shift) r.push(j - shift)
+ i++
+ }
+ j++
+ }
+ return r
+}
diff --git a/src/components/searchModes/index.tsx b/src/components/searchModes/index.tsx
new file mode 100644
index 0000000..e007e49
--- /dev/null
+++ b/src/components/searchModes/index.tsx
@@ -0,0 +1,16 @@
+import { ReactNode } from 'react'
+import { SearchParams } from 'utils/VisibleNodesGenerator'
+import { fuzzyMode } from './fuzzyMode'
+import { regexMode } from './regexMode'
+
+export type SearchMode = 'regex' | 'fuzzy'
+
+export type ModeShape = {
+ getSearchParams(searchKey: string): Pick | null
+ renderNodeLabelText(node: TreeNode, searchKey: string): ReactNode
+}
+
+export const searchModes: Record = {
+ regex: regexMode,
+ fuzzy: fuzzyMode,
+}
diff --git a/src/components/searchModes/regexMode.tsx b/src/components/searchModes/regexMode.tsx
new file mode 100644
index 0000000..dfed221
--- /dev/null
+++ b/src/components/searchModes/regexMode.tsx
@@ -0,0 +1,35 @@
+import * as React from 'react'
+import { cx } from 'utils/cx'
+import { isValidRegexpSource, searchKeyToRegexp } from 'utils/general'
+import { ModeShape } from '.'
+import { Highlight } from '../Highlight'
+
+export const regexMode: ModeShape = {
+ getSearchParams(searchKey) {
+ const regexp = searchKeyToRegexp(searchKey)
+ if (regexp) {
+ const matchNode = (node: TreeNode) => regexp.test(node.name)
+
+ return {
+ matchNode,
+ }
+ }
+
+ return null
+ },
+ renderNodeLabelText(node, searchKey) {
+ const regex =
+ searchKey && isValidRegexpSource(searchKey) ? new RegExp(searchKey, 'gi') : undefined
+ const { name } = node
+ return name.includes('/') ? (
+ name.split('/').map((chunk, index, arr) => (
+
+
+ {index + 1 !== arr.length && '/'}
+
+ ))
+ ) : (
+
+ )
+ },
+}