@@ -20,7 +20,18 @@ export const VERSION_PRESETS = [
2020 { label : "≥ 1.0" , value : ">=1.0.0" } ,
2121 { label : "< 1.0" , value : "<1.0.0" }
2222] ;
23- export const FILTERS_NAME = new Set ( [ "package" , "version" , "flag" , "license" , "author" , "ext" , "builtin" , "size" , "highlighted" ] ) ;
23+ export const FILTERS_NAME = new Set ( [
24+ "package" ,
25+ "version" ,
26+ "flag" ,
27+ "license" ,
28+ "author" ,
29+ "ext" ,
30+ "builtin" ,
31+ "size" ,
32+ "highlighted" ,
33+ "dep"
34+ ] ) ;
2435export const PRESETS = [
2536 { id : "has_vulnerabilities" , filter : "flag" , value : "hasVulnerabilities" } ,
2637 { id : "has_scripts" , filter : "flag" , value : "hasScript" } ,
@@ -29,7 +40,7 @@ export const PRESETS = [
2940 { id : "large" , filter : "size" , value : ">100kb" }
3041] ;
3142// Filters that use a searchable text-based list (not a rich visual panel)
32- export const FILTER_HAS_HELPERS = new Set ( [ "license" , "ext" , "builtin" , "author" ] ) ;
43+ export const FILTER_HAS_HELPERS = new Set ( [ "license" , "ext" , "builtin" , "author" , "dep" ] ) ;
3344// Filters where the mode persists after selection (multi-select)
3445export const FILTER_MULTI_SELECT = new Set ( [ "flag" ] ) ;
3546// Filters that auto-confirm immediately on selection (no text input needed)
@@ -60,6 +71,18 @@ export function getFlagCounts(linker) {
6071 * @returns {Map<string, number> }
6172 */
6273export function getFilterValueCounts ( linker , filterName ) {
74+ if ( filterName === "dep" ) {
75+ const counts = new Map ( ) ;
76+ for ( const opt of linker . values ( ) ) {
77+ const dependentCount = Object . keys ( opt . usedBy ) . length ;
78+ if ( dependentCount > 0 ) {
79+ counts . set ( opt . name , ( counts . get ( opt . name ) ?? 0 ) + dependentCount ) ;
80+ }
81+ }
82+
83+ return counts ;
84+ }
85+
6386 const counts = new Map ( ) ;
6487 for ( const opt of linker . values ( ) ) {
6588 for ( const value of getValuesForCount ( opt , filterName ) ) {
@@ -155,6 +178,16 @@ export function getHelperValues(linker, filterName) {
155178 return { display : name , value : name } ;
156179 } ) ;
157180 }
181+ case "dep" : {
182+ const items = new Set ( ) ;
183+ for ( const { name } of linker . values ( ) ) {
184+ items . add ( name ) ;
185+ }
186+
187+ return [ ...items ] . sort ( ) . map ( ( name ) => {
188+ return { display : name , value : name } ;
189+ } ) ;
190+ }
158191 default :
159192 return [ ] ;
160193 }
@@ -169,6 +202,10 @@ export function getHelperValues(linker, filterName) {
169202 * @returns {Set<string> }
170203 */
171204export function computeMatches ( linker , filterName , inputValue ) {
205+ if ( filterName === "dep" ) {
206+ return computeDepMatches ( linker , inputValue ) ;
207+ }
208+
172209 const matchingIds = new Set ( ) ;
173210
174211 for ( const [ id , opt ] of linker ) {
@@ -180,6 +217,41 @@ export function computeMatches(linker, filterName, inputValue) {
180217 return matchingIds ;
181218}
182219
220+ /**
221+ * Collect packages that depend on package matching inputValue
222+ *
223+ * @param {Map<number, object> } linker
224+ * @param {string } inputValue
225+ * @returns {Set<string> }
226+ */
227+ function computeDepMatches ( linker , inputValue ) {
228+ const matchingIds = new Set ( ) ;
229+
230+ try {
231+ const regex = new RegExp ( inputValue , "i" ) ;
232+
233+ const dependentNames = new Set ( ) ;
234+ for ( const opt of linker . values ( ) ) {
235+ if ( regex . test ( opt . name ) ) {
236+ for ( const dependency of Object . keys ( opt . usedBy ) ) {
237+ dependentNames . add ( dependency ) ;
238+ }
239+ }
240+ }
241+
242+ for ( const [ id , opt ] of linker ) {
243+ if ( dependentNames . has ( opt . name ) ) {
244+ matchingIds . add ( String ( id ) ) ;
245+ }
246+ }
247+ }
248+ catch {
249+ // invalid regex
250+ }
251+
252+ return matchingIds ;
253+ }
254+
183255function matchesFilter ( opt , filterName , inputValue ) {
184256 switch ( filterName ) {
185257 case "package" : {
0 commit comments