1- import React , { useContext } from "react" ;
1+ import React , { useContext , useMemo } from "react" ;
2+ import { Link } from "react-router-dom" ;
23import styled from "styled-components" ;
34import * as api from "./api" ;
45import { SchemaTypeView , MetadataTags } from "./SchemaType" ;
56import { ReferencedBy } from "./ReferencedBy" ;
67import { KindIcon } from "./utils/components" ;
78import { DeclarationsContext } from "./DeclarationsContext" ;
9+ import { useSearchWords } from "./utils/filtering" ;
810import {
911 CommonGroupMembers ,
1012 CommonGroupSignature ,
@@ -14,7 +16,7 @@ import {
1416} from "./utils/styles" ;
1517
1618const ClassExtendsWrapper = styled . span `
17- font-size: 14px ;
19+ font-size: 16px ;
1820 font-weight: normal;
1921 color: ${ ( props ) => props . theme . textDim } ;
2022
@@ -24,23 +26,33 @@ const ClassExtendsWrapper = styled.span`
2426` ;
2527
2628const ClassMembers = styled ( CommonGroupMembers ) `
27- padding: 6px 10px 6px 12px;
28-
2929 > :not(:last-child) {
3030 margin-bottom: 6px;
3131 }
3232` ;
3333
34- const FieldRow = styled . div `
35- padding: 5px 8px ;
36- background-color: ${ ( props ) => props . theme . group } ;
34+ const FieldRow = styled . div < { $highlighted ?: boolean } > `
35+ padding: 6px 10px ;
36+ background-color: ${ ( props ) => props . $highlighted ? props . theme . searchHighlight : props . theme . group } ;
3737 border: 1px solid ${ ( props ) => props . theme . groupBorder } ;
38- border-radius: 6px ;
38+ border-radius: 8px ;
3939` ;
4040
4141const FieldSignature = styled . div `
4242 font-weight: 600;
43+ font-size: 16px;
44+ ` ;
45+
46+ const CollapsedFieldsLink = styled ( Link ) `
47+ display: block;
48+ padding: 4px 8px;
4349 font-size: 14px;
50+ color: ${ ( props ) => props . theme . textDim } ;
51+ text-decoration: none;
52+
53+ &:hover {
54+ text-decoration: underline;
55+ }
4456` ;
4557
4658export const ModuleBadge : React . FC < { module : string } > = ( { module } ) => (
@@ -53,18 +65,36 @@ const StyledModuleBadge = styled.span`
5365 color: ${ ( props ) => props . theme . textDim } ;
5466 background-color: ${ ( props ) => props . theme . groupMembers } ;
5567 border: 1px solid ${ ( props ) => props . theme . groupBorder } ;
56- padding: 1px 6px ;
57- border-radius: 4px ;
68+ padding: 2px 8px ;
69+ border-radius: 6px ;
5870 margin-left: 8px;
5971 vertical-align: middle;
6072` ;
6173
74+ export function matchesWords ( name : string , words : string [ ] ) : boolean {
75+ const lower = name . toLowerCase ( ) ;
76+ return words . every ( ( w ) => lower . includes ( w ) ) ;
77+ }
78+
6279export const SchemaClassView : React . FC < {
6380 className ?: string ;
6481 style ?: React . CSSProperties ;
6582 declaration : api . SchemaClass ;
6683} > = ( { className, style, declaration } ) => {
6784 const { root } = useContext ( DeclarationsContext ) ;
85+ const searchWords = useSearchWords ( ) ;
86+
87+ const nameMatches = searchWords . length === 0 || matchesWords ( declaration . name , searchWords ) ;
88+ const collapseNonMatching = searchWords . length > 0 && ! nameMatches ;
89+
90+ const { matchingFields, hiddenCount } = useMemo ( ( ) => {
91+ if ( ! collapseNonMatching ) {
92+ return { matchingFields : declaration . fields , hiddenCount : 0 } ;
93+ }
94+ const matching = declaration . fields . filter ( ( f ) => matchesWords ( f . name , searchWords ) ) ;
95+ return { matchingFields : matching , hiddenCount : declaration . fields . length - matching . length } ;
96+ } , [ declaration . fields , searchWords , collapseNonMatching ] ) ;
97+
6898 return (
6999 < CommonGroupWrapper className = { className } style = { style } >
70100 < DeclarationHeader >
@@ -87,21 +117,26 @@ export const SchemaClassView: React.FC<{
87117 </ CommonGroupSignature >
88118 </ DeclarationHeader >
89119 < MetadataTags metadata = { declaration . metadata } />
90- { declaration . fields . length > 0 && (
120+ { ( matchingFields . length > 0 || hiddenCount > 0 ) && (
91121 < ClassMembers >
92- { declaration . fields . map ( ( field ) => (
93- < SchemaFieldView key = { field . name } field = { field } />
122+ { matchingFields . map ( ( field ) => (
123+ < SchemaFieldView key = { field . name } field = { field } highlighted = { searchWords . length > 0 && matchesWords ( field . name , searchWords ) } />
94124 ) ) }
125+ { hiddenCount > 0 && (
126+ < CollapsedFieldsLink to = { `${ root } /${ declaration . name } ` } >
127+ { hiddenCount } more field{ hiddenCount !== 1 ? "s" : "" } …
128+ </ CollapsedFieldsLink >
129+ ) }
95130 </ ClassMembers >
96131 ) }
97- < ReferencedBy name = { declaration . name } />
132+ { ! collapseNonMatching && < ReferencedBy name = { declaration . name } /> }
98133 </ CommonGroupWrapper >
99134 ) ;
100135} ;
101136
102- function SchemaFieldView ( { field } : { field : api . SchemaField } ) {
137+ function SchemaFieldView ( { field, highlighted } : { field : api . SchemaField ; highlighted : boolean } ) {
103138 return (
104- < FieldRow >
139+ < FieldRow $highlighted = { highlighted } >
105140 < FieldSignature >
106141 < KindIcon kind = "field" size = "small" />
107142 { field . name } : < SchemaTypeView type = { field . type } />
0 commit comments