src/TypesView.tsx (51 lines of code) (raw):

import { useState, useRef } from 'react'; import Container from 'react-bootstrap/Container'; import ListGroup from 'react-bootstrap/ListGroup'; import FloatingLabel from 'react-bootstrap/FloatingLabel'; import Form from 'react-bootstrap/Form'; import { NavLink, useParams } from 'react-router-dom'; import { useSchema, useSchemaContext } from './SchemaContext'; import Type from './Type'; import { BaseType } from './metamodel'; export default function TypesView() { const [search, setSearch] = useState(''); const searchInput = useRef<HTMLInputElement>(null); const schema = useSchema(); const { version } = useSchemaContext(); const { type } = useParams(); const searchChanged = () => { setSearch(searchInput.current?.value || ''); }; const filteredTypes = schema.types.filter(type => { const bt = type as BaseType; return `${bt.name.namespace}::${bt.name.name}`.match(new RegExp(search, "i")) != null; }); const selectedType = (!type) ? null : schema.types.filter(t => `${t.name.namespace}::${t.name.name}` === type)?.[0]; return ( <> <Container fluid className="TypesList"> <FloatingLabel controlId="floatingInput" label="Regex Filter" className="mb-3" > <Form.Control type="text" autoFocus ref={searchInput} onChange={searchChanged} /> </FloatingLabel> <ListGroup variant="flush"> {filteredTypes.map((type) => { const bt = type as BaseType; return <ListGroup.Item key={`${bt.name.namespace}::${bt.name.name}`} as={NavLink} action to={ `/${version}/types/${bt.name.namespace}::${bt.name.name}` }>{ `${bt.name.namespace}::${bt.name.name}` }</ListGroup.Item>; })} </ListGroup> </Container> <Container fluid className="TypesView"> {selectedType != null ? <> <h1>{ `${selectedType.name.namespace}::${selectedType.name.name}` }</h1> <Type type={selectedType} /> </> : <h4>← Select a type</h4> } </Container> </> ); }