22// @ts-expect-error missing types
33import { RecycleScroller } from ' vue-virtual-scroller'
44import Fuse from ' fuse.js'
5+ import type { ModuleStaticInfo } from ' ../../src/types'
6+
7+ type SortingFunction <T > = (a : T , b : T ) => number
58
69const emit = defineEmits ([' close' ])
710
811const collection = useModulesList ()
912
13+ const sortingOptions = [' downloads' , ' stars' , ' updated' , ' created' ] as const
14+ const ascendingOrder = ref (false )
15+ const selectedSortingOption = ref <typeof sortingOptions [number ]>(sortingOptions [0 ])
16+
17+ const sortingFactors: Record <typeof sortingOptions [number ], SortingFunction <ModuleStaticInfo >> = {
18+ downloads : (a , b ) => a .stats .downloads - b .stats .downloads ,
19+ stars : (a , b ) => a .stats .stars - b .stats .stars ,
20+ created : (a , b ) => a .stats .createdAt - b .stats .createdAt ,
21+ updated : (a , b ) => a .stats .publishedAt - b .stats .publishedAt ,
22+ }
23+
24+ const sortedItems = computed (() => collection .value ?.slice ()
25+ .sort ((a , b ) => sortingFactors [selectedSortingOption .value ](a , b ) * (ascendingOrder .value ? 1 : - 1 )))
26+
1027const search = ref (' ' )
11- const fuse = computed (() => new Fuse (collection .value || [], {
28+ const fuse = computed (() => new Fuse (sortedItems .value || [], {
1229 keys: [
1330 ' name' ,
1431 ' description' ,
@@ -19,7 +36,7 @@ const fuse = computed(() => new Fuse(collection.value || [], {
1936
2037const items = computed (() => {
2138 if (! search .value )
22- return collection .value
39+ return sortedItems .value
2340 return fuse .value .search (search .value ).map (r => r .item )
2441})
2542 </script >
@@ -33,20 +50,51 @@ const items = computed(() => {
3350 text =" Install Module"
3451 />
3552
36- <NTextInput
37- v-model =" search"
38- :autofocus =" true"
39- placeholder =" Search..."
40- icon =" carbon-search" n =" primary"
41- mx6 px-5 py-2
42- />
53+ <NNavbar v-model:search =" search" no-padding px-6 pb-5 pt-2 >
54+ <template #actions >
55+ <NDropdown direction =" end" n =" sm primary" >
56+ <template #trigger =" { click } " >
57+ <div flex =" ~ items-center" >
58+ <NButton
59+ :icon =" ascendingOrder ? 'tabler:sort-ascending' : 'tabler:sort-descending'"
60+ h-full rounded-r-none
61+ @click =" ascendingOrder = !ascendingOrder"
62+ />
63+ <NButton
64+ flex =" ~ justify-between"
65+ min-w-30 border-l-0 rounded-l-none px-2 capitalize
66+ hover =" border-l-1"
67+ @click =" click()"
68+ >
69+ {{ selectedSortingOption }}
70+ <NIcon icon =" carbon:chevron-down" />
71+ </NButton >
72+ </div >
73+ </template >
74+ <div flex =" ~ col" w-30 of-auto >
75+ <NButton
76+ v-for =" item of sortingOptions"
77+ :key =" item"
78+ :border =" false" p2
79+ hover =" n-checkbox-hover text-green"
80+ @click =" selectedSortingOption = item"
81+ >
82+ <span flex =" ~ justify-between" w-full text-xs capitalize op75 >
83+ {{ item }}
84+ <NIcon v-if =" selectedSortingOption === item" icon =" carbon:checkmark" />
85+ </span >
86+ </NButton >
87+ </div >
88+ </NDropdown >
89+ </template >
90+ </NNavbar >
4391
4492 <div flex-auto of-auto flex =" ~ col gap-2" pl6 pr4 >
4593 <RecycleScroller
4694 v-slot =" { item }"
4795 class =" scroller"
4896 :items =" items"
49- :item-size =" 160 "
97+ :item-size =" 200 "
5098 key-field =" name"
5199 >
52100 <ModuleItemInstall :item =" item" @start =" emit('close')" />
0 commit comments