@@ -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' ,
@@ -47,12 +46,12 @@ const moduleViewTypes = [
4746] as const
4847
4948debouncedWatch (
50- filters ,
49+ searchValue . value ,
5150 (f ) => {
5251 const query: any = {
5352 ... route .query ,
5453 search: f .search || undefined ,
55- file_types: f .file_types || undefined ,
54+ file_types: f .selected || undefined ,
5655 node_modules: f .node_modules || undefined ,
5756 }
5857 router .replace ({
@@ -72,6 +71,12 @@ const parsedPaths = computed(() => props.session.modulesList.map((mod) => {
7271 }
7372}))
7473
74+ const searchFilterTypes = computed (() => {
75+ return ModuleTypeRules .filter ((rule ) => {
76+ return parsedPaths .value .some (mod => rule .match .test (mod .mod .id ))
77+ })
78+ })
79+
7580// const allNodeModules = computed(() => {
7681// const nodeModules = new Set<string>()
7782// for (const mod of parsedPaths.value) {
@@ -81,45 +86,20 @@ const parsedPaths = computed(() => props.session.modulesList.map((mod) => {
8186// return nodeModules
8287// })
8388
84- const allFileTypes = computed (() => {
85- const fileTypes = new Set <string >()
86- for (const mod of parsedPaths .value ) {
87- fileTypes .add (mod .type .name )
88- }
89- return fileTypes
90- })
91-
9289const filtered = computed (() => {
9390 let modules = parsedPaths .value
94- if (filters .file_types ) {
95- modules = modules .filter (mod => filters .file_types ! .includes (mod .type .name ))
91+ if (searchValue .value .selected ) {
92+ modules = modules .filter ((mod ) => {
93+ const type = getFileTypeFromModuleId (mod .mod .id )
94+ return searchValue .value .selected ! .includes (type .name )
95+ })
9696 }
97- if (filters .node_modules ) {
98- modules = modules .filter (mod => mod .path .moduleName && filters .node_modules ! .includes (mod .path .moduleName ))
97+ if (searchValue . value .node_modules ) {
98+ modules = modules .filter (mod => mod .path .moduleName && searchValue . value .node_modules ! .includes (mod .path .moduleName ))
9999 }
100100 return modules .map (mod => ({ ... mod .mod , path: mod .path .path }))
101101})
102102
103- function isFileTypeSelected(type : string ) {
104- return filters .file_types == null || filters .file_types .includes (type )
105- }
106-
107- function toggleFileType(type : string ) {
108- if (filters .file_types == null ) {
109- filters .file_types = Array .from (allFileTypes .value )
110- }
111-
112- if (filters .file_types .includes (type )) {
113- filters .file_types = filters .file_types .filter (t => t !== type )
114- }
115- else {
116- filters .file_types .push (type )
117- }
118- if (filters .file_types .length === allFileTypes .value .size ) {
119- filters .file_types = null
120- }
121- }
122-
123103const fuse = computedWithControl (
124104 () => filtered .value ,
125105 () => new Fuse (filtered .value , {
@@ -131,11 +111,11 @@ const fuse = computedWithControl(
131111)
132112
133113const searched = computed (() => {
134- if (filters . search === ' ' ) {
114+ if (! searchValue . value . search ) {
135115 return filtered .value
136116 }
137117 return fuse .value
138- .search (filters .search )
118+ .search (searchValue . value .search )
139119 .map (r => r .item )
140120})
141121
@@ -149,51 +129,25 @@ function toggleDisplay(type: ClientSettings['moduleGraphViewType']) {
149129
150130<template >
151131 <div relative max-h-screen of-hidden >
152- <div flex =" col gap-2" absolute left-4 top-4 max-w-90vw border =" ~ base rounded-xl" bg-glass z-panel-nav >
153- <div border =" b base" >
154- <input
155- v-model =" filters.search"
156- p2 px4 w-full
157- style =" outline : none "
158- placeholder =" Search"
159- >
160- </div >
161- <div flex =" ~ gap-2 wrap" p2 >
162- <label
163- v-for =" type of allFileTypes"
164- :key =" type"
165- border =" ~ base rounded-md" px2 py1
166- flex =" ~ items-center gap-1"
167- select-none
168- :title =" type"
169- :class =" isFileTypeSelected(type) ? 'bg-active' : 'grayscale op50'"
170- >
171- <input
172- type =" checkbox"
173- :checked =" isFileTypeSelected(type)"
174- mr1
175- @change =" toggleFileType(type)"
132+ <div absolute left-4 top-4 z-panel-nav >
133+ <DataSearchPanel v-model =" searchValue" :rules =" searchFilterTypes" >
134+ <div flex =" ~ gap-2 items-center" p2 border =" t base" >
135+ <span op50 pl2 text-sm >View as</span >
136+ <button
137+ v-for =" viewType of moduleViewTypes"
138+ :key =" viewType.value"
139+ btn-action
140+ :class =" settings.moduleGraphViewType === viewType.value ? 'bg-active' : 'grayscale op50'"
141+ @click =" toggleDisplay(viewType.value)"
176142 >
177- <div :class =" getFileTypeFromName(type).icon" icon-catppuccin />
178- <div text-sm >{{ getFileTypeFromName(type).description }}</div >
179- </label >
180- </div >
181- <div flex =" ~ gap-2 items-center" p2 border =" t base" >
182- <span op50 pl2 text-sm >View as</span >
183- <button
184- v-for =" viewType of moduleViewTypes"
185- :key =" viewType.value"
186- btn-action
187- :class =" settings.moduleGraphViewType === viewType.value ? 'bg-active' : 'grayscale op50'"
188- @click =" toggleDisplay(viewType.value)"
189- >
190- <div :class =" viewType.icon" />
191- {{ viewType.label }}
192- </button >
193- </div >
194- <!-- TODO: should we add filters for node_modules? -->
195- <!-- {{ allNodeModules }} -->
143+ <div :class =" viewType.icon" />
144+ {{ viewType.label }}
145+ </button >
146+ </div >
147+ </DataSearchPanel >
196148 </div >
149+ <!-- TODO: should we add filters for node_modules? -->
150+ <!-- {{ allNodeModules }} -->
197151 <template v-if =" settings .moduleGraphViewType === ' list' " >
198152 <div of-auto h-screen pt-45 >
199153 <ModulesFlatList
0 commit comments