@@ -5,29 +5,28 @@ import { useRoute, useRouter } from '#app/composables/router'
55import { clearUndefined , toArray } from ' @antfu/utils'
66import { computedWithControl , debouncedWatch } from ' @vueuse/core'
77import Fuse from ' fuse.js'
8- import { computed , reactive } from ' vue'
8+ import { computed , ref } from ' vue'
99import { settings } from ' ~/state/settings'
1010import { parseReadablePath } from ' ~/utils/filepath'
11- import { getFileTypeFromModuleId , getFileTypeFromName } from ' ~/utils/icon'
11+ import { getFileTypeFromModuleId , ModuleTypeRules } from ' ~/utils/icon'
1212
1313const props = defineProps <{
1414 session: SessionContext
1515}>()
1616
17- interface Filters {
18- search: string
19- file_types: string [] | null
20- node_modules: string [] | null
21- }
22-
2317const route = useRoute ()
2418const router = useRouter ()
2519
26- const filters = reactive <Filters >({
20+ const searchValue = ref <{
21+ search: string
22+ selected: string [] | null
23+ [key : string ]: any
24+ }>({
2725 search: (route .query .search || ' ' ) as string ,
28- file_types : (route .query .file_types ? toArray (route .query .file_types ) : null ) as string [] | null ,
26+ selected : (route .query .file_types ? toArray (route .query .file_types ) : null ) as string [] | null ,
2927 node_modules: (route .query .node_modules ? toArray (route .query .node_modules ) : null ) as string [] | null ,
3028})
29+
3130const moduleViewTypes = [
3231 {
3332 label: ' List' ,
@@ -52,12 +51,12 @@ const moduleViewTypes = [
5251] as const
5352
5453debouncedWatch (
55- filters ,
54+ searchValue . value ,
5655 (f ) => {
5756 const query: any = {
5857 ... route .query ,
5958 search: f .search || undefined ,
60- file_types: f .file_types || undefined ,
59+ file_types: f .selected || undefined ,
6160 node_modules: f .node_modules || undefined ,
6261 }
6362 router .replace ({
@@ -77,6 +76,12 @@ const parsedPaths = computed(() => props.session.modulesList.map((mod) => {
7776 }
7877}))
7978
79+ const searchFilterTypes = computed (() => {
80+ return ModuleTypeRules .filter ((rule ) => {
81+ return parsedPaths .value .some (mod => rule .match .test (mod .mod .id ))
82+ })
83+ })
84+
8085// const allNodeModules = computed(() => {
8186// const nodeModules = new Set<string>()
8287// for (const mod of parsedPaths.value) {
@@ -86,45 +91,20 @@ const parsedPaths = computed(() => props.session.modulesList.map((mod) => {
8691// return nodeModules
8792// })
8893
89- const allFileTypes = computed (() => {
90- const fileTypes = new Set <string >()
91- for (const mod of parsedPaths .value ) {
92- fileTypes .add (mod .type .name )
93- }
94- return fileTypes
95- })
96-
9794const filtered = computed (() => {
9895 let modules = parsedPaths .value
99- if (filters .file_types ) {
100- modules = modules .filter (mod => filters .file_types ! .includes (mod .type .name ))
96+ if (searchValue .value .selected ) {
97+ modules = modules .filter ((mod ) => {
98+ const type = getFileTypeFromModuleId (mod .mod .id )
99+ return searchValue .value .selected ! .includes (type .name )
100+ })
101101 }
102- if (filters .node_modules ) {
103- modules = modules .filter (mod => mod .path .moduleName && filters .node_modules ! .includes (mod .path .moduleName ))
102+ if (searchValue . value .node_modules ) {
103+ modules = modules .filter (mod => mod .path .moduleName && searchValue . value .node_modules ! .includes (mod .path .moduleName ))
104104 }
105105 return modules .map (mod => ({ ... mod .mod , path: mod .path .path }))
106106})
107107
108- function isFileTypeSelected(type : string ) {
109- return filters .file_types == null || filters .file_types .includes (type )
110- }
111-
112- function toggleFileType(type : string ) {
113- if (filters .file_types == null ) {
114- filters .file_types = Array .from (allFileTypes .value )
115- }
116-
117- if (filters .file_types .includes (type )) {
118- filters .file_types = filters .file_types .filter (t => t !== type )
119- }
120- else {
121- filters .file_types .push (type )
122- }
123- if (filters .file_types .length === allFileTypes .value .size ) {
124- filters .file_types = null
125- }
126- }
127-
128108const fuse = computedWithControl (
129109 () => filtered .value ,
130110 () => new Fuse (filtered .value , {
@@ -136,11 +116,11 @@ const fuse = computedWithControl(
136116)
137117
138118const searched = computed (() => {
139- if (filters . search === ' ' ) {
119+ if (! searchValue . value . search ) {
140120 return filtered .value
141121 }
142122 return fuse .value
143- .search (filters .search )
123+ .search (searchValue . value .search )
144124 .map (r => r .item )
145125})
146126
@@ -154,51 +134,25 @@ function toggleDisplay(type: ClientSettings['moduleGraphViewType']) {
154134
155135<template >
156136 <div relative max-h-screen of-hidden >
157- <div flex =" col gap-2" absolute left-4 top-4 max-w-90vw border =" ~ base rounded-xl" bg-glass z-panel-nav >
158- <div border =" b base" >
159- <input
160- v-model =" filters.search"
161- p2 px4 w-full
162- style =" outline : none "
163- placeholder =" Search"
164- >
165- </div >
166- <div flex =" ~ gap-2 wrap" p2 >
167- <label
168- v-for =" type of allFileTypes"
169- :key =" type"
170- border =" ~ base rounded-md" px2 py1
171- flex =" ~ items-center gap-1"
172- select-none
173- :title =" type"
174- :class =" isFileTypeSelected(type) ? 'bg-active' : 'grayscale op50'"
175- >
176- <input
177- type =" checkbox"
178- :checked =" isFileTypeSelected(type)"
179- mr1
180- @change =" toggleFileType(type)"
137+ <div absolute left-4 top-4 z-panel-nav >
138+ <DataSearchPanel v-model =" searchValue " :rules =" searchFilterTypes " >
139+ <div flex =" ~ gap-2 items-center" p2 border =" t base" >
140+ <span op50 pl2 text-sm >View as</span >
141+ <button
142+ v-for =" viewType of moduleViewTypes"
143+ :key =" viewType.value"
144+ btn-action
145+ :class =" settings.moduleGraphViewType === viewType.value ? 'bg-active' : 'grayscale op50'"
146+ @click =" toggleDisplay(viewType.value)"
181147 >
182- <div :class =" getFileTypeFromName(type).icon" icon-catppuccin />
183- <div text-sm >{{ getFileTypeFromName(type).description }}</div >
184- </label >
185- </div >
186- <div flex =" ~ gap-2 items-center" p2 border =" t base" >
187- <span op50 pl2 text-sm >View as</span >
188- <button
189- v-for =" viewType of moduleViewTypes"
190- :key =" viewType.value"
191- btn-action
192- :class =" settings.moduleGraphViewType === viewType.value ? 'bg-active' : 'grayscale op50'"
193- @click =" toggleDisplay(viewType.value)"
194- >
195- <div :class =" viewType.icon" />
196- {{ viewType.label }}
197- </button >
198- </div >
199- <!-- TODO: should we add filters for node_modules? -->
200- <!-- {{ allNodeModules }} -->
148+ <div :class =" viewType.icon" />
149+ {{ viewType.label }}
150+ </button >
151+ </div >
152+ </DataSearchPanel >
201153 </div >
154+ <!-- TODO: should we add filters for node_modules? -->
155+ <!-- {{ allNodeModules }} -->
202156 <template v-if =" settings .moduleGraphViewType === ' list' " >
203157 <div of-auto h-screen pt-45 >
204158 <ModulesFlatList
0 commit comments