@@ -58,6 +58,106 @@ function initCodeGroups() {
5858
5959initCodeGroups ( ) ;
6060
61+ function initReferenceFilter ( ) {
62+ const filter = document . querySelector ( "[data-reference-filter]" ) ;
63+ const input = filter ?. querySelector ( ".reference-filter-input" ) ;
64+ const clearButton = filter ?. querySelector ( ".reference-filter-clear" ) ;
65+ const content = filter ?. closest ( ".content" ) ;
66+ const empty = content ?. querySelector ( "[data-reference-filter-empty]" ) ;
67+ const kind = filter ?. dataset . referenceFilter ;
68+
69+ if (
70+ ! ( input instanceof HTMLInputElement ) ||
71+ ! ( clearButton instanceof HTMLButtonElement ) ||
72+ ! ( empty instanceof HTMLElement ) ||
73+ ! content ||
74+ ( kind !== "methods" && kind !== "types" )
75+ ) return ;
76+
77+ function normalize ( value ) {
78+ return value . normalize ( "NFKD" ) . toLocaleLowerCase ( ) . replace ( / [ \p{ P} \p{ S} \s ] + / gu, "" ) ;
79+ }
80+
81+ const groups = Array . from ( content . querySelectorAll ( ".descr-list" ) , ( list ) => {
82+ const heading = list . previousElementSibling ?. matches ( "h2" ) ? list . previousElementSibling : undefined ;
83+ const children = Array . from ( list . children ) ;
84+ const entries = [ ] ;
85+
86+ for ( let index = 0 ; index < children . length ; index ++ ) {
87+ const nameNode = children [ index ] ;
88+ const link = nameNode . matches ( "a[href]" ) ? nameNode : nameNode . matches ( "p" ) ? nameNode . querySelector ( ":scope > a[href]:only-child" ) : null ;
89+ const description = children [ index + 1 ] ;
90+ const divider = children [ index + 2 ] ;
91+ if ( ! link || ! description || ! divider ?. classList . contains ( "descr-list-border" ) ) continue ;
92+
93+ entries . push ( {
94+ nodes : [ nameNode , description , divider ] ,
95+ name : normalize ( link . textContent ) ,
96+ } ) ;
97+ index += 2 ;
98+ }
99+
100+ return { heading, list, entries } ;
101+ } ) . filter ( ( group ) => group . entries . length ) ;
102+ const total = groups . reduce ( ( sum , group ) => sum + group . entries . length , 0 ) ;
103+ const toc = document . querySelector ( ".toc" ) ;
104+ let updateFrame ;
105+
106+ if ( ! total ) {
107+ filter . hidden = true ;
108+ return ;
109+ }
110+
111+ function update ( ) {
112+ updateFrame = undefined ;
113+ const rawQuery = input . value . trim ( ) ;
114+ const terms = rawQuery . split ( / \s + / ) . map ( normalize ) . filter ( Boolean ) ;
115+ let matches = 0 ;
116+
117+ for ( const group of groups ) {
118+ let groupMatches = 0 ;
119+ for ( const entry of group . entries ) {
120+ const visible = terms . every ( ( term ) => entry . name . includes ( term ) ) ;
121+ for ( const node of entry . nodes ) node . hidden = ! visible ;
122+ if ( visible ) {
123+ matches ++ ;
124+ groupMatches ++ ;
125+ }
126+ }
127+
128+ const groupVisible = groupMatches > 0 ;
129+ group . list . hidden = ! groupVisible ;
130+ if ( group . heading ) group . heading . hidden = ! groupVisible ;
131+ }
132+
133+ clearButton . hidden = rawQuery . length === 0 ;
134+ empty . hidden = matches > 0 ;
135+ empty . textContent = matches ? "" : `No ${ kind } match “${ rawQuery } ”.` ;
136+ if ( toc ) toc . hidden = terms . length > 0 ;
137+ globalThis . dispatchEvent ( new Event ( "referencefilterchange" ) ) ;
138+ }
139+
140+ function scheduleUpdate ( ) {
141+ globalThis . cancelAnimationFrame ( updateFrame ) ;
142+ updateFrame = globalThis . requestAnimationFrame ( update ) ;
143+ }
144+
145+ input . addEventListener ( "input" , scheduleUpdate ) ;
146+ input . addEventListener ( "keydown" , ( event ) => {
147+ if ( event . key !== "Escape" || ! input . value ) return ;
148+ event . preventDefault ( ) ;
149+ input . value = "" ;
150+ update ( ) ;
151+ } ) ;
152+ clearButton . addEventListener ( "click" , ( ) => {
153+ input . value = "" ;
154+ update ( ) ;
155+ input . focus ( { preventScroll : true } ) ;
156+ } ) ;
157+
158+ update ( ) ;
159+ }
160+
61161function initIndexSubsections ( ) {
62162 const panels = Array . from ( document . querySelectorAll ( ".index-subsections" ) ) ;
63163 const content = panels [ 0 ] ?. closest ( ".content" ) ;
@@ -612,6 +712,7 @@ function initToc() {
612712 globalThis . addEventListener ( "resize" , relayout , { passive : true } ) ;
613713 globalThis . addEventListener ( "load" , relayout ) ;
614714 globalThis . addEventListener ( "hashchange" , onHashChange ) ;
715+ globalThis . addEventListener ( "referencefilterchange" , relayout ) ;
615716 globalThis . addEventListener ( "wheel" , releaseLockedEntry , { passive : true } ) ;
616717 globalThis . addEventListener ( "touchstart" , releaseLockedEntry , { passive : true } ) ;
617718 globalThis . addEventListener ( "pointerdown" , releaseLockedEntry , { passive : true } ) ;
@@ -627,4 +728,5 @@ function initToc() {
627728}
628729
629730initIndexSubsections ( ) ;
731+ initReferenceFilter ( ) ;
630732initToc ( ) ;
0 commit comments