@mui/icons-material#Send TypeScript Examples

The following examples show how to use @mui/icons-material#Send. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Terminal.tsx    From NekoMaid with MIT License 4 votes vote down vote up
Terminal: React.FC = () => {
  const logs = useMemo<JSX.Element[]>(() => [], [])
  const ref = useRef<HTMLDivElement | null>(null)
  const plugin = usePlugin()
  const [, update] = useState(0)
  const [open, setOpen] = useState(false)
  const [command, setCommand] = useState('')
  const [suggestions, setSuggestions] = useState<Array<[string, boolean] | [string]>>([])
  const getSuggestions = useMemo(() => throttle(
    (it: string) => {
      let cmd = it.substr(0, it.lastIndexOf(' '))
      if (cmd) cmd += ' '
      return plugin.emit('console:complete', (data: string[] = []) => {
        setSuggestions(JSON.parse(localStorage.getItem(`NekoMaid:${address}:commandHistory`) || '[]').concat(data.map(c => [cmd + c] as [string])))
      }, it)
    },
    500
  ), [])
  const scrollToEnd = useMemo(() => throttle(
    (elm: HTMLDivElement) => {
      const select = (window.getSelection || document.getSelection)()
      if (select && !select.isCollapsed) {
        let node = select?.anchorNode
        while (node && node !== document) {
          if (node === elm) return
          node = node.parentNode
        }
      }
      if (elm) elm.lastElementChild?.scrollIntoView()
    },
    300
  ), [])
  const execCommand = () => {
    if (!command) return
    plugin.emit('console:run', action, command)
    const arr = JSON.parse(localStorage.getItem(`NekoMaid:${address}:commandHistory`) || '[]').filter((it: [string]) => it[0] !== command)
    if (arr.length === 5) arr.pop()
    arr.unshift([command, true])
    localStorage.setItem(`NekoMaid:${address}:commandHistory`, JSON.stringify(arr))
    setCommand('')
  }

  useEffect(() => {
    const runCommand = (it: string) => plugin.emit('console:run', action, it)
    let lastLog: Log = {} as any
    const onLog = (data: Log) => {
      if (lastLog.logger === data.logger && (lastLog.time / 100 | 0) === (data.time / 100 | 0) &&
        lastLog.level === data.level && (!lastLog.components === !data.components)) {
        logs.pop()
        if (data.components) {
          lastLog.components!.push(null as any)
          lastLog.components = lastLog.components!.concat(data.components)
        } else lastLog.msg += '\n' + data.msg
        data = lastLog
      } else lastLog = data
      logs.push(parseLog(data, runCommand, setCommand))
      update(++i)
    }
    const offLogs = plugin.on('console:logs', (it: Log[]) => {
      logs.length = 0
      it.forEach(onLog)
    })
    const offLog = plugin.on('console:log', onLog)
    plugin.switchPage('console')
    return () => {
      offLogs()
      offLog()
    }
  }, [])

  useEffect(() => { ref.current && scrollToEnd(ref.current) }, [logs[logs.length - 1]])

  return <Box sx={{
    width: '100%',
    height: '100vh',
    overflow: 'hidden',
    display: 'flex',
    fontSize: '0.91rem',
    flexDirection: 'column',
    fontFamily: '"Roboto Mono","Helvetica","Arial",sans-serif',
    '& p': {
      margin: 0,
      whiteSpace: 'pre-wrap',
      wordBreak: 'break-word',
      display: 'flex',
      '& .msg': {
        flex: '1'
      },
      '& .logger': {
        color: theme => theme.palette.secondary.main,
        fontStyle: 'italic'
      },
      '& .level': {
        userSelect: 'none',
        height: 'fit-content',
        fontWeight: 'bolder',
        cursor: 'pointer',
        color: theme => theme.palette.primary.main
      },
      '& .white': {
        textShadow: theme => theme.palette.mode === 'light' ? '#000 1px 0 0, #000 0 1px 0, #000 -1px 0 0, #000 0 -1px 0' : undefined
      },
      '& .black': {
        textShadow: theme => theme.palette.mode === 'dark' ? '#fff 1px 0 0, #fff 0 1px 0, #fff -1px 0 0, #fff 0 -1px 0' : undefined
      },
      '& .more': {
        color: theme => theme.palette.secondary.main,
        marginRight: '4px',
        cursor: 'pointer',
        textDecoration: 'underline'
      }
    },
    '& .warn, & .warn .level': {
      color: theme => theme.palette.warning.main
    },
    '& .error, & .error .level': {
      color: theme => theme.palette.error.main
    }
  }}>
    <Toolbar />
    <Box
      ref={ref}
      sx={{
        height: '100%',
        overflow: 'hidden scroll',
        backgroundColor: theme => theme.palette.background.default,
        padding: theme => theme.spacing(1)
      }}>
      {logs}
    </Box>
    <Paper sx={{
      display: 'flex',
      borderRadius: '4px 4px 0 0',
      padding: theme => theme.spacing(1),
      zIndex: 2
    }}>
      <Autocomplete
        freeSolo
        open={open}
        inputValue={command}
        options={suggestions}
        onOpen={() => setOpen(true)}
        onClose={() => setOpen(false)}
        onFocus={() => getSuggestions(command)}
        onKeyUp={(e: any) => e.key === 'Enter' && (!open || !suggestions.length) && execCommand()}
        sx={{ flex: '1' }}
        classes={{ popper: 'command-popper' }}
        renderInput={params => <TextField {...params as any} label={lang.terminal.command} />}
        getOptionLabel={it => typeof it === 'string' ? it : it[0]}
        groupBy={it => it[1] ? lang.history : lang.terminal.command}
        onInputChange={(_, it) => {
          getSuggestions(it)
          setCommand(it)
        }}
      />
      <IconButton
        color='primary'
        disabled={!command}
        onClick={execCommand}
        sx={{ margin: theme => theme.spacing('auto', 0, 'auto', 1) }}
      ><Send /></IconButton>
    </Paper>
  </Box>
}