github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/web/src/ResourceNameFilter.tsx (about)

     1  import { InputAdornment } from "@material-ui/core"
     2  import { InputProps as StandardInputProps } from "@material-ui/core/Input/Input"
     3  import React from "react"
     4  import styled from "styled-components"
     5  import { ReactComponent as CloseSvg } from "./assets/svg/close.svg"
     6  import { ReactComponent as SearchSvg } from "./assets/svg/search.svg"
     7  import {
     8    InstrumentedButton,
     9    InstrumentedTextField,
    10  } from "./instrumentedComponents"
    11  import { useResourceListOptions } from "./ResourceListOptionsContext"
    12  import {
    13    Color,
    14    Font,
    15    FontSize,
    16    mixinResetButtonStyle,
    17    SizeUnit,
    18  } from "./style-helpers"
    19  
    20  export function matchesResourceName(
    21    resourceName: string,
    22    filter: string
    23  ): boolean {
    24    filter = filter.trim()
    25    // this is functionally redundant but probably an important enough case to make its own thing
    26    if (filter === "") {
    27      return true
    28    }
    29    // a resource matches the query if the resource name contains all tokens in the query
    30    return filter
    31      .split(" ")
    32      .every((token) => resourceName.toLowerCase().includes(token.toLowerCase()))
    33  }
    34  
    35  export const ResourceNameFilterTextField = styled(InstrumentedTextField)`
    36    & .MuiOutlinedInput-root {
    37      border-radius: ${SizeUnit(0.5)};
    38      border: 1px solid ${Color.gray40};
    39      background-color: ${Color.gray30};
    40  
    41      & fieldset {
    42        border-color: 1px solid ${Color.gray40};
    43      }
    44      &:hover fieldset {
    45        border: 1px solid ${Color.gray40};
    46      }
    47      &.Mui-focused fieldset {
    48        border: 1px solid ${Color.gray40};
    49      }
    50      & .MuiOutlinedInput-input {
    51        padding: ${SizeUnit(0.2)};
    52      }
    53    }
    54  
    55    margin-top: ${SizeUnit(0.4)};
    56    margin-bottom: ${SizeUnit(0.4)};
    57    flex-grow: 1;
    58  
    59    & .MuiInputBase-input {
    60      font-family: ${Font.monospace};
    61      color: ${Color.offWhite};
    62      font-size: ${FontSize.small};
    63    }
    64  `
    65  
    66  export const ClearResourceNameFilterButton = styled(InstrumentedButton)`
    67    ${mixinResetButtonStyle};
    68    display: flex;
    69    align-items: center;
    70  `
    71  
    72  export function ResourceNameFilter(props: { className?: string }) {
    73    const {
    74      options: { resourceNameFilter },
    75      setOptions,
    76    } = useResourceListOptions()
    77  
    78    function setResourceNameFilter(newValue: string) {
    79      setOptions({ resourceNameFilter: newValue })
    80    }
    81  
    82    let inputProps: Partial<StandardInputProps> = {
    83      "aria-label": "Filter resources by name",
    84      startAdornment: (
    85        <InputAdornment position="start">
    86          <SearchSvg fill={Color.grayLightest} />
    87        </InputAdornment>
    88      ),
    89    }
    90  
    91    // only show the "x" to clear if there's any input to clear
    92    if (resourceNameFilter.length) {
    93      const onClearClick = () => setResourceNameFilter("")
    94  
    95      inputProps.endAdornment = (
    96        <InputAdornment position="end">
    97          <ClearResourceNameFilterButton
    98            onClick={onClearClick}
    99            analyticsName="ui.web.clearResourceNameFilter"
   100            aria-label="Clear name filter"
   101          >
   102            <CloseSvg role="presentation" fill={Color.grayLightest} />
   103          </ClearResourceNameFilterButton>
   104        </InputAdornment>
   105      )
   106    }
   107  
   108    return (
   109      <ResourceNameFilterTextField
   110        className={props.className}
   111        value={resourceNameFilter ?? ""}
   112        onChange={(e) => setResourceNameFilter(e.target.value)}
   113        placeholder="Filter resources by name"
   114        InputProps={inputProps}
   115        variant="outlined"
   116        analyticsName="ui.web.resourceNameFilter"
   117      />
   118    )
   119  }