@mui/material#Toolbar TypeScript Examples

The following examples show how to use @mui/material#Toolbar. 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: GridAppbar.tsx    From frontend with MIT License 6 votes vote down vote up
export default function GridAppbar() {
  const router = useRouter()
  const { t } = useTranslation()

  return (
    <Toolbar
      sx={{
        background: 'white',
        borderTop: '1px solid lightgrey',
        display: 'flex',
        justifyContent: 'space-between',
        height: '72px',
      }}>
      <Box sx={{ height: '64px', display: 'flex', alignItems: 'start', pt: 1 }}>
        <Typography>{t('countries:headings.countries')}</Typography>
      </Box>
      <Box sx={{ height: '64px', display: 'flex', alignItems: 'flex-end', pb: 1 }}>
        <Box sx={{ display: 'flex', alignItems: 'center' }}>
          <Tooltip title={t('countries:tooltips.add') || ''}>
            <AddIcon
              sx={addIconStyles}
              fontSize="large"
              onClick={() => router.push(routes.admin.countries.create)}
            />
          </Tooltip>
        </Box>
      </Box>
    </Toolbar>
  )
}
Example #2
Source File: toast.tsx    From NekoMaid with MIT License 6 votes vote down vote up
Snackbars: React.FC = () => {
  const [, updateF] = useState<number>(0)
  useEffect(() => {
    update = updateF
    return () => { update = undefined as any }
  })

  return <Box sx={{
    position: 'fixed',
    top: 12,
    right: 44,
    zIndex: theme => theme.zIndex.modal + 1,
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'flex-end',
    pointerEvents: 'none'
  }}><Toolbar sx={{ padding: '0!important' }} />{Object.values(toasts).map(it => React.createElement(Snackbar, it))}</Box>
}
Example #3
Source File: InfoRequestBottomAppBar.tsx    From frontend with MIT License 6 votes vote down vote up
export default function InfoRequestBottomAppBar() {
  return (
    <Toolbar
      sx={{
        background: 'white',
        borderTop: '1px solid lightgrey',
        display: 'flex',
        justifyContent: 'space-between',
        height: '72px',
      }}>
      <Box sx={{ height: '64px', display: 'flex', alignItems: 'start', pt: 1 }}>
        <Typography>Всички заявки за контакт</Typography>
      </Box>
      <Box sx={{ height: '64px', display: 'flex', alignItems: 'flex-end', pb: 1 }}>
        <Box sx={{ display: 'flex', alignItems: 'center' }}>
          <Tooltip title="Преглед">
            <EventNoteIcon sx={iconStyles} fontSize="medium" color="action" />
          </Tooltip>
          <Tooltip title="Запази">
            <SaveIcon sx={iconStyles} fontSize="medium" color="action" />
          </Tooltip>
          <Tooltip title="Принт">
            <PrintIcon sx={iconStyles} fontSize="medium" color="action" />
          </Tooltip>
          <Tooltip title="Сподели">
            <ShareIcon sx={iconStyles} fontSize="medium" color="action" />
          </Tooltip>
          <Tooltip title="Добави">
            <AddIcon sx={addIconStyles} fontSize="large" />
          </Tooltip>
        </Box>
      </Box>
    </Toolbar>
  )
}
Example #4
Source File: PlayerList.tsx    From NekoMaid with MIT License 6 votes vote down vote up
PlayerList: React.FC = () => {
  return <Box sx={{ minHeight: '100%', py: 3 }}>
    <Toolbar />
    <Container maxWidth={false}>
      <Grid container spacing={3}>
        <Grid item lg={8} md={12} xl={9} xs={12}><Players /></Grid>
        <Grid item lg={4} md={6} xl={3} xs={12}><PlayerActions /></Grid>
      </Grid>
    </Container>
  </Box>
}
Example #5
Source File: GridAppbar.tsx    From frontend with MIT License 6 votes vote down vote up
export default function GridAppbar() {
  const router = useRouter()
  const { t } = useTranslation('benefactor')
  return (
    <Toolbar
      sx={{
        background: 'white',
        borderTop: '1px solid lightgrey',
        display: 'flex',
        justifyContent: 'space-between',
        height: '72px',
      }}>
      <Box sx={{ height: '64px', display: 'flex', alignItems: 'start', pt: 1 }}>
        <Typography>{t('benefactor')}</Typography>
      </Box>
      <Box sx={{ height: '64px', display: 'flex', alignItems: 'flex-end', pb: 1 }}>
        <Box sx={{ display: 'flex', alignItems: 'center' }}>
          <Tooltip title={t('cta.add') || ''}>
            <AddIcon
              sx={addIconStyles}
              fontSize="large"
              onClick={() => router.push(routes.admin.benefactor.add)}
            />
          </Tooltip>
        </Box>
      </Box>
    </Toolbar>
  )
}
Example #6
Source File: Config.tsx    From NekoMaid with MIT License 6 votes vote down vote up
Config: React.FC = () => {
  return <Box sx={{ minHeight: '100%', py: 3 }}>
    <Toolbar />
    <Container maxWidth={false}>
      <Grid container spacing={3}>
        {configs.map((it, i) => <Grid key={i} item lg={4} md={12} xl={6} xs={12}>
          <Card>
            <CardHeader title={it.title} />
            <Divider />
            <it.component />
          </Card>
        </Grid>)}
      </Grid>
    </Container>
  </Box>
}
Example #7
Source File: GridAppbar.tsx    From frontend with MIT License 6 votes vote down vote up
export default function GridAppbar() {
  const router = useRouter()

  return (
    <Toolbar
      sx={{
        background: 'white',
        borderTop: '1px solid lightgrey',
        display: 'flex',
        justifyContent: 'space-between',
        height: '72px',
      }}>
      <Box sx={{ height: '64px', display: 'flex', alignItems: 'start', pt: 1 }}>
        <Typography>Всички градове</Typography>
      </Box>
      <Box sx={{ height: '64px', display: 'flex', alignItems: 'flex-end', pb: 1 }}>
        <Box sx={{ display: 'flex', alignItems: 'center' }}>
          <Tooltip title="Добави">
            <AddIcon
              sx={addIconStyles}
              fontSize="large"
              onClick={() => {
                router.push(routes.admin.cities.create)
              }}
            />
          </Tooltip>
        </Box>
      </Box>
    </Toolbar>
  )
}
Example #8
Source File: client.tsx    From mui-toolpad with MIT License 6 votes vote down vote up
function ConnectionParamsInput({ value, onChange }: ConnectionEditorProps<MoviesConnectionParams>) {
  const { handleSubmit, register, formState, reset } = useForm({
    defaultValues: withDefaults(value),
  });
  React.useEffect(() => reset(withDefaults(value)), [reset, value]);

  const doSubmit = handleSubmit((connectionParams) => onChange(connectionParams));

  return (
    <Stack direction="column" gap={1}>
      <Toolbar disableGutters>
        <Button onClick={doSubmit} disabled={!formState.isDirty || !formState.isValid}>
          Save
        </Button>
      </Toolbar>
      <TextField
        label="API key"
        {...register('apiKey', { required: true })}
        {...validation(formState, 'apiKey')}
      />
    </Stack>
  );
}
Example #9
Source File: GridAppbar.tsx    From frontend with MIT License 6 votes vote down vote up
export default function GridAppbar() {
  const router = useRouter()
  const { t } = useTranslation()

  return (
    <Toolbar
      sx={{
        background: 'white',
        borderTop: '1px solid lightgrey',
        display: 'flex',
        justifyContent: 'space-between',
        height: '72px',
      }}>
      <Box sx={{ height: '64px', display: 'flex', alignItems: 'start', pt: 1 }}>
        <Typography>{t('documents:all')}</Typography>
      </Box>
      <Box sx={{ height: '64px', display: 'flex', alignItems: 'flex-end', pb: 1 }}>
        <Box sx={{ display: 'flex', alignItems: 'center' }}>
          <Tooltip title={t('documents:cta:add') || ''}>
            <AddIcon
              sx={addIconStyles}
              fontSize="large"
              onClick={() => router.push(routes.admin.documents.create)}
            />
          </Tooltip>
        </Box>
      </Box>
    </Toolbar>
  )
}
Example #10
Source File: app-bar.component.tsx    From master-frontend-lemoncode with MIT License 6 votes vote down vote up
AppBarComponent: React.FunctionComponent = () => {
  return (
    <AppBar position="static">
      <Toolbar variant="dense" className={classes.root}>
        <img className={classes.logo} src={logo} />
      </Toolbar>
    </AppBar>
  );
}
Example #11
Source File: Header.tsx    From mojito_pdm with Creative Commons Attribution Share Alike 4.0 International 6 votes vote down vote up
Header: React.FC = () => {
    const [colorMode, setColorMode] = useRecoilState(GlobalState.theme)
    const {setVisible} = useVisibility()

    const handleExit = async () => {
        try {
            await fetchNui("exit")
            setVisible(false);
        } catch (e) {
            console.error(e)
        }
    }

    const handleThemeswitch = () => {
        colorMode === "light" ? setColorMode("dark") : setColorMode("light")
    }

    return (
        <AppBar position="sticky">
            <Toolbar sx={{backgroundColor: "primary.dark"}}>
                <Typography sx={{flex: 1}}>
                    <img src={logo} height="100px" alt=""/>
                </Typography>

                <CategorySelect/>
                <IconButton sx={{ml: 1}} onClick={handleThemeswitch} color="inherit">
                    {colorMode === 'dark' ? <Brightness7Icon/> : <Brightness4Icon/>}
                </IconButton>
                <IconButton sx={{ml: 1}} onClick={handleExit} color="inherit">
                    <CloseIcon/>
                </IconButton>
            </Toolbar>
        </AppBar>
    )
}
Example #12
Source File: GridAppbar.tsx    From frontend with MIT License 6 votes vote down vote up
export default function GridAppbar() {
  const router = useRouter()
  const { t } = useTranslation()

  return (
    <Toolbar
      sx={{
        background: 'white',
        borderTop: '1px solid lightgrey',
        display: 'flex',
        justifyContent: 'space-between',
        height: '72px',
      }}>
      <Box sx={{ height: '64px', display: 'flex', alignItems: 'start', pt: 1 }}>
        <Typography>{t('vaults:all')}</Typography>
      </Box>
      <Box sx={{ height: '64px', display: 'flex', alignItems: 'flex-end', pb: 1 }}>
        <Box sx={{ display: 'flex', alignItems: 'center' }}>
          <Tooltip title={t('vaults:cta:add') || ''}>
            <AddIcon
              sx={addIconStyles}
              fontSize="large"
              onClick={() => router.push(routes.admin.vaults.create)}
            />
          </Tooltip>
        </Box>
      </Box>
    </Toolbar>
  )
}
Example #13
Source File: DetailFrame.tsx    From airmessage-web with Apache License 2.0 6 votes vote down vote up
DetailFrame = React.forwardRef<HTMLDivElement, Props>((props, ref) => {
	return (
		<div className={styles.root} ref={ref}>
			<Toolbar>
				<Typography className={styles.title} variant="h6" noWrap>{props.title}</Typography>
				
				{props.showCall && (
					<IconButton
						size="large"
						onClick={props.onClickCall}>
						<VideocamOutlined />
					</IconButton>
				)}
			</Toolbar>
			<SoftDivider />
			{props.children}
		</div>
	);
})
Example #14
Source File: GridAppbar.tsx    From frontend with MIT License 6 votes vote down vote up
export default function GridAppbar() {
  const router = useRouter()
  const { t } = useTranslation()

  return (
    <Toolbar
      sx={{
        background: 'white',
        borderTop: '1px solid lightgrey',
        display: 'flex',
        justifyContent: 'space-between',
        height: '72px',
      }}>
      <Box sx={{ height: '64px', display: 'flex', alignItems: 'start', pt: 1 }}>
        <Typography>{t('withdrawals:all')}</Typography>
      </Box>
      <Box sx={{ display: 'flex', alignItems: 'flex-end', pb: 1 }}>
        <Box sx={{ display: 'flex', alignItems: 'center' }}>
          <Tooltip title={t('withdrawals:cta:add') || ''}>
            <AddIcon
              sx={addIconStyles}
              fontSize="large"
              onClick={() => router.push(routes.admin.withdrawals.create)}
            />
          </Tooltip>
        </Box>
      </Box>
    </Toolbar>
  )
}
Example #15
Source File: header.tsx    From example with MIT License 6 votes vote down vote up
export function Header() {
	return (
		<AppBar position={"static"}>
			<Container maxWidth={"xl"} disableGutters>
			<Toolbar>
					<Typography variant="h6" noWrap component="div" sx={{ flexGrow: 1 }}>
						Rarible SDK Example
					</Typography>
					<ConnectionStatus/>
			</Toolbar>
			</Container>
		</AppBar>
	)
}
Example #16
Source File: GridAppbar.tsx    From frontend with MIT License 6 votes vote down vote up
export default function GridAppbar() {
  const router = useRouter()

  return (
    <Toolbar
      sx={{
        background: 'white',
        borderTop: '1px solid lightgrey',
        display: 'flex',
        justifyContent: 'space-between',
        height: '72px',
      }}>
      <Box sx={{ height: '64px', display: 'flex', alignItems: 'start', pt: 1 }}>
        <Typography>Всички разходи</Typography>
      </Box>
      <Box sx={{ height: '64px', display: 'flex', alignItems: 'flex-end', pb: 1 }}>
        <Box sx={{ display: 'flex', alignItems: 'center' }}>
          <Tooltip title="Добави">
            <AddIcon
              sx={addIconStyles}
              fontSize="large"
              onClick={() => router.push(routes.admin.expenses.create)}
            />
          </Tooltip>
        </Box>
      </Box>
    </Toolbar>
  )
}
Example #17
Source File: EnhancedTableToolbar.tsx    From yearn-watch-legacy with GNU Affero General Public License v3.0 6 votes vote down vote up
EnhancedTableToolbar = (props: EnhancedTableToolbarProps) => {
    const classes = useToolbarStyles();
    return (
        <Toolbar className={clsx(classes.root)}>
            <Typography
                className={classes.title}
                variant="h6"
                id="tableTitle"
                component="div"
                align="center"
            >
                {props.title}
            </Typography>
        </Toolbar>
    );
}
Example #18
Source File: GridAppbar.tsx    From frontend with MIT License 5 votes vote down vote up
export default function GridAppbar() {
  const router = useRouter()
  return (
    <Toolbar
      sx={{
        background: 'white',
        borderTop: '1px solid lightgrey',
        display: 'flex',
        justifyContent: 'space-between',
        height: '72px',
      }}>
      <Box sx={{ height: '64px', display: 'flex', alignItems: 'start', pt: 1 }}>
        <Typography>Всички банкови сметки</Typography>
      </Box>
      <Box sx={{ height: '64px', display: 'flex', alignItems: 'flex-end', pb: 1 }}>
        <Box sx={{ display: 'flex', alignItems: 'center' }}>
          <Tooltip title="Преглед">
            <EventNoteIcon sx={iconStyles} fontSize="medium" color="action" />
          </Tooltip>
          <Tooltip title="Запази">
            <SaveIcon sx={iconStyles} fontSize="medium" color="action" />
          </Tooltip>
          <Tooltip title="Принт">
            <PrintIcon sx={iconStyles} fontSize="medium" color="action" />
          </Tooltip>
          <Tooltip title="Сподели">
            <ShareIcon sx={iconStyles} fontSize="medium" color="action" />
          </Tooltip>
          <Tooltip title="Добави">
            <AddIcon
              sx={addIconStyles}
              fontSize="large"
              onClick={() => {
                router.push(routes.admin.bankaccounts.add)
              }}
            />
          </Tooltip>
        </Box>
      </Box>
    </Toolbar>
  )
}
Example #19
Source File: Profiler.tsx    From NekoMaid with MIT License 5 votes vote down vote up
Profiler: React.FC = () => {
  const plugin = usePlugin()
  const theme = useTheme()
  const globalData = useGlobalData()
  const [tab, setTab] = useState(0)
  const [key, setTKey] = useState(0)
  const [status, setStatus] = useState(!!globalData.profilerStarted)
  useEffect(() => {
    const off = plugin.on('profiler:status', setStatus)
    return () => { off() }
  }, [])

  const transitionDuration = {
    enter: theme.transitions.duration.enteringScreen,
    exit: theme.transitions.duration.leavingScreen
  }
  const Elm = components[tab]

  const createFab = (onClick: any, children: any, show: boolean) => <Zoom
    in={show}
    timeout={transitionDuration}
    style={{ transitionDelay: (show ? transitionDuration.exit : 0) + 'ms' }}
    unmountOnExit
  >
    <Fab
      color='primary'
      sx={{ position: 'fixed', bottom: { xs: 16, sm: 40 }, right: { xs: 16, sm: 40 }, zIndex: 3 }}
      onClick={onClick}
    >{children}</Fab>
  </Zoom>

  return <Box sx={{ minHeight: status || !tab ? '100%' : undefined }}>
    <Toolbar />
    <Paper square variant='outlined' sx={{ margin: '0 -1px', position: 'fixed', width: 'calc(100% + 1px)', zIndex: 3 }}>
      <Tabs value={tab} onChange={(_, it) => setTab(it)} variant='scrollable' scrollButtons='auto'>
        <Tab label={lang.profiler.summary} />
        <Tab label='Timings' disabled={!globalData.hasTimings} />
        <Tab label={lang.profiler.plugins} />
        <Tab label={lang.profiler.carbageCollection} />
        <Tab label={lang.profiler.entities} />
        <Tab label={lang.profiler.heap} />
        <Tab label={lang.profiler.threads} />
      </Tabs>
    </Paper>
    <Tabs />
    {tab < 4 && !status ? <Box sx={{ textAlign: 'center', marginTop: '40vh' }}>{lang.profiler.notStarted}</Box> : Elm && <Elm key={key} />}
    {createFab(() => plugin.emit('profiler:status', !status), status ? <Stop /> : <PlayArrow />, tab < 4)}
    {createFab(() => setTKey(key + 1), <Refresh />, tab >= 4)}
  </Box>
}
Example #20
Source File: BitcoinStatusBar.tsx    From sapio-studio with Mozilla Public License 2.0 5 votes vote down vote up
export function BitcoinStatusBar(props: BitcoinStatusBarProps) {
    const theme = useTheme();
    const freq = useSelector(selectNodePollFreq);
    const [balance, setBalance] = React.useState<number>(0);
    const [blockchaininfo, setBlockchaininfo] = React.useState<any>(null);
    React.useEffect(() => {
        let next: ReturnType<typeof setTimeout> | null = null;
        let mounted = true;
        const periodic_update_stats = async () => {
            next = null;
            try {
                const balance = await props.api.check_balance();
                setBalance(balance);
            } catch (err) {
                console.error(err);
                setBalance(0);
            }

            try {
                const info = await props.api.blockchaininfo();
                console.log(balance);
                setBlockchaininfo(info);
            } catch (err) {
                console.error(err);
                setBlockchaininfo(null);
            }

            if (mounted) {
                let prefs = freq;
                prefs = clamp(prefs ?? 0, 5, 5 * 60);
                console.log('StatusBar', 'NEXT PERIODIC CHECK IN ', prefs);
                next = setTimeout(periodic_update_stats, prefs * 1000);
            }
        };

        let prefs = freq;
        prefs = clamp(prefs ?? 0, 5, 5 * 60);
        next = setTimeout(periodic_update_stats, prefs * 1000);
        return () => {
            mounted = false;
            if (next !== null) clearTimeout(next);
        };
    }, []);

    const network = blockchaininfo?.chain ?? 'disconnected';
    const headers = blockchaininfo?.headers ?? '?';
    const blocks = blockchaininfo?.headers ?? '?';
    return (
        <Paper
            square={true}
            sx={{
                top: 'auto',
                bottom: 0,
            }}
            className="BitcoinStatusBar Draggable"
            style={{
                background: theme.palette.background.default,
                color: theme.palette.info.main,
            }}
        >
            <Toolbar variant="dense">
                <Typography variant="h6" color="inherit" component="div">
                    <div>chain: {network}</div>
                </Typography>
                <Typography variant="h6" color="inherit" component="div">
                    <div style={{ marginLeft: '0.5em' }}>
                        balance: {balance} BTC
                    </div>
                </Typography>
                <Typography variant="h6" color="inherit" component="div">
                    <div style={{ marginLeft: '0.5em' }}>
                        processed: {blocks}/{headers}
                    </div>
                </Typography>
            </Toolbar>
        </Paper>
    );
}
Example #21
Source File: Navbar.tsx    From website with Apache License 2.0 5 votes vote down vote up
StyledToolbar = styled(Toolbar)<{ scrollPos: number }>`
  box-shadow: ${({ scrollPos }) => (scrollPos > 10 ? "initial" : "unset")};
`
Example #22
Source File: client.tsx    From mui-toolpad with MIT License 5 votes vote down vote up
function ConnectionParamsInput({
  value,
  onChange,
}: ConnectionEditorProps<PostgresConnectionParams>) {
  const { handleSubmit, register, formState, reset } = useForm({
    defaultValues: withDefaults(value),
    reValidateMode: 'onChange',
    mode: 'all',
  });
  React.useEffect(() => reset(withDefaults(value)), [reset, value]);

  const doSubmit = handleSubmit((connectionParams) => onChange(connectionParams));

  return (
    <Stack direction="column" gap={1}>
      <Toolbar disableGutters>
        <Button onClick={doSubmit} disabled={!formState.isDirty || !formState.isValid}>
          Save
        </Button>
      </Toolbar>
      <TextField
        label="host"
        {...register('host', { required: true })}
        {...validation(formState, 'host')}
      />
      <TextField
        label="port"
        {...register('port', { required: true })}
        {...validation(formState, 'port')}
      />
      <TextField
        label="user"
        {...register('user', { required: true })}
        {...validation(formState, 'user')}
      />
      <TextField
        label="password"
        type="password"
        {...register('password', { required: true })}
        {...validation(formState, 'password')}
      />
      <TextField
        label="database"
        {...register('database', { required: true })}
        {...validation(formState, 'database')}
      />
    </Stack>
  );
}
Example #23
Source File: GridAppbar.tsx    From frontend with MIT License 5 votes vote down vote up
export default function GridAppbar() {
  const router = useRouter()

  return (
    <Toolbar
      sx={{
        background: 'white',
        borderTop: '1px solid lightgrey',
        display: 'flex',
        justifyContent: 'space-between',
        height: '72px',
      }}>
      <Box sx={{ height: '64px', display: 'flex', alignItems: 'start', pt: 1 }}>
        <Typography>Всички координатори</Typography>
      </Box>
      <Box sx={{ height: '64px', display: 'flex', alignItems: 'flex-end', pb: 1 }}>
        <Box sx={{ display: 'flex', alignItems: 'center' }}>
          <Tooltip title="Преглед">
            <EventNoteIcon sx={iconStyles} fontSize="medium" color="action" />
          </Tooltip>
          <Tooltip title="Запази">
            <SaveIcon sx={iconStyles} fontSize="medium" color="action" />
          </Tooltip>
          <Tooltip title="Принт">
            <PrintIcon sx={iconStyles} fontSize="medium" color="action" />
          </Tooltip>
          <Tooltip title="Сподели">
            <ShareIcon sx={iconStyles} fontSize="medium" color="action" />
          </Tooltip>
          <Tooltip title="Добави">
            <AddIcon
              sx={addIconStyles}
              fontSize="large"
              onClick={() => router.push(routes.admin.coordinators.add)}
            />
          </Tooltip>
        </Box>
      </Box>
    </Toolbar>
  )
}
Example #24
Source File: MessageAttachmentImage.tsx    From airmessage-web with Apache License 2.0 5 votes vote down vote up
export default function MessageAttachmentImage(props: {data: ArrayBuffer | Blob, name: string, type: string, partProps: MessagePartProps, tapbacks?: TapbackItem[], stickers?: StickerItem[]}) {
	const [imageURL, setImageURL] = useState<string | undefined>(undefined);
	const [previewOpen, setPreviewOpen] = useState(false);
	
	const theme = createTheme({
		palette: {
			mode: "dark",
			messageIncoming: undefined,
			messageOutgoing: undefined,
			messageOutgoingTextMessage: undefined
		}
	});
	
	useEffect(() => {
		//Creating a new image URL
		const imageURL = URL.createObjectURL(props.data instanceof Blob ? props.data : new Blob([props.data], {type: props.type}));
		
		//Setting the image URL
		setImageURL(imageURL);
		
		//Cleaning up the URL
		return () => URL.revokeObjectURL(imageURL);
	}, [props.data, props.type, setImageURL]);
	
	function downloadFile(event: React.MouseEvent<HTMLButtonElement, MouseEvent>) {
		//So that we don't dismiss the backdrop
		event.stopPropagation();
		
		if(!imageURL) return;
		downloadURL(imageURL, props.type, props.name);
	}
	
	//All of the styles, without the border radius
	const buttonStyle: Partial<MessagePartProps> = {...props.partProps};
	delete buttonStyle["borderRadius"];
	
	return (
		<React.Fragment>
			<ThemeProvider theme={theme}>
				<Backdrop className={stylesImage.lightboxBackdrop} open={previewOpen} onClick={() => setPreviewOpen(false)}>
					<Toolbar className={stylesImage.lightboxToolbar}>
						<IconButton edge="start">
							<ArrowBack />
						</IconButton>
						<Typography variant="h6" color="textPrimary" style={{flexGrow: 1}}>{props.name}</Typography>
						<Tooltip title="Save">
							<IconButton onClick={downloadFile}>
								<SaveAlt />
							</IconButton>
						</Tooltip>
					</Toolbar>
					<div className={stylesImage.lightboxContainer}>
						<div style={{width: "100%", height: "100%", backgroundImage: `url("${imageURL}")`, backgroundPosition: "center", backgroundRepeat: "no-repeat", backgroundSize: "contain"}} />
					</div>
				</Backdrop>
			</ThemeProvider>
			
			<DecorativeMessageBubble element={ButtonBase} className={styles.contentBubble} style={props.partProps} onClick={() => setPreviewOpen(true)} tapbacks={props.tapbacks} stickers={props.stickers}>
				<img src={imageURL} style={{borderRadius: props.partProps.borderRadius}} alt="" />
			</DecorativeMessageBubble>
			
			{/*<ButtonBase className={styles.contentBubble} style={props.partProps} onClick={() => setPreviewOpen(true)}>*/}
			{/*	<img src={imageURL} style={{borderRadius: props.partProps.borderRadius}} alt="" />*/}
			{/*</ButtonBase>*/}
		</React.Fragment>
	);
}
Example #25
Source File: Header.tsx    From genshin-optimizer with MIT License 5 votes vote down vote up
function MobileHeader({ anchor, currentTab }) {
  const [mobileOpen, setMobileOpen] = useState(false);

  const handleDrawerToggle = () => {
    setMobileOpen(!mobileOpen);
  };


  const { t } = useTranslation("ui")
  return <>
    <AppBar position="fixed" sx={{ bgcolor: "#343a40" }} elevation={0}  >
      <Drawer
        anchor="right"
        variant="temporary"
        open={mobileOpen}
        onClose={handleDrawerToggle}
        ModalProps={{
          keepMounted: true, // Better open performance on mobile.
        }}
      >
        <List>
          <ListItemButton key="home" component={RouterLink} to={'/'} selected={currentTab === ""} disabled={currentTab === ""} onClick={handleDrawerToggle} >
            <ListItemText>{t("pageTitle")}</ListItemText>
          </ListItemButton >
          {content.map(({ i18Key, value, to, svg }) =>
            <ListItemButton key={value} component={RouterLink} to={to} selected={currentTab === value} disabled={currentTab === value} onClick={handleDrawerToggle} >
              <ListItemIcon><FontAwesomeIcon icon={svg} /></ListItemIcon>
              <ListItemText>{t(i18Key)}</ListItemText>
            </ListItemButton >)}
        </List>
        <Divider />
        <List>
          {links.map(({ i18Key, href, svg, label }) =>
            <ListItemButton key={label} component="a" href={href} target="_blank" onClick={e => ReactGA.outboundLink({ label }, () => { })} >
              <ListItemIcon><FontAwesomeIcon icon={svg} /></ListItemIcon>
              <ListItemText>{t(i18Key)}</ListItemText>
            </ListItemButton >)}
        </List>
      </Drawer>
      <Toolbar>
        <Button variant="text" sx={{ color: "white" }} component={RouterLink} to="/">
          <Typography variant="h6" noWrap component="div">
            <Trans t={t} i18nKey="pageTitle">Genshin Optimizer</Trans>
          </Typography>
        </Button>
        <Box flexGrow={1} />
        <IconButton
          color="inherit"
          aria-label="open drawer"
          edge="end"
          onClick={handleDrawerToggle}
        >
          <MenuIcon />
        </IconButton>
      </Toolbar>
    </AppBar>
    {/* add a blank toolbar to keep space and provide a scroll anchor */}
    <Toolbar id={anchor} />
  </>
}
Example #26
Source File: AppNavBar.tsx    From frontend with MIT License 4 votes vote down vote up
export default function AppNavBar({ navMenuToggle }: AppBarDeckProps) {
  const { locale } = useRouter()
  const { status } = useSession()
  const shrink = useScrollTrigger()
  return (
    <AppBar
      position="fixed"
      className={clsx({ shrink })}
      sx={(theme) => ({
        overflow: 'hidden',
        transition: 'height .5s, background-color .5s ease 0s',
        height: theme.spacing(14),
        lineHeight: theme.spacing(14),
        [theme.breakpoints.down('md')]: {
          height: theme.spacing(10),
        },
        '&.shrink': {
          height: theme.spacing(10),
          lineHeight: theme.spacing(10),
          backgroundColor: 'hsla(0,0%,100%,0.85)',
          backdropFilter: 'saturate(180%) blur(5px)',
        },
        backgroundColor: theme.palette.common.white,
      })}>
      <Toolbar
        sx={{
          height: '100%',
          display: 'flex',
          justifyContent: 'space-between',
        }}>
        <Link href={routes.index} passHref>
          <ButtonBase
            component="a"
            className={clsx({ shrink })}
            sx={(theme) => ({
              transition: 'height .5s',
              height: theme.spacing(7.5),
              minWidth: theme.spacing(15),
              marginLeft: theme.spacing(5),
              [theme.breakpoints.up('lg')]: {
                marginLeft: theme.spacing(10),
              },
              [theme.breakpoints.down('md')]: {
                marginLeft: 0,
                width: '100%',
                height: '50%',
              },
              '&.shrink': {
                height: '50%',
              },
              '& > svg': {
                display: 'block',
                height: '100%',
              },
            })}>
            <PodkrepiLogo locale={locale} variant="adaptive" />
          </ButtonBase>
        </Link>
        <Hidden mdDown>
          <Grid
            container
            wrap="nowrap"
            direction="row"
            justifyContent="flex-end"
            sx={(theme) => ({
              marginLeft: theme.spacing(2),
              marginRight: theme.spacing(5),
              [theme.breakpoints.up('lg')]: {
                marginRight: theme.spacing(10),
              },
            })}>
            <Grid item>
              <MainNavMenu>
                {status === 'authenticated' ? <PrivateMenu /> : <PublicMenu />}
                <Grid item>
                  <LocaleButton />
                </Grid>
              </MainNavMenu>
            </Grid>
          </Grid>
        </Hidden>
        <Hidden mdUp>
          <IconButton
            size="small"
            edge="end"
            onClick={navMenuToggle}
            aria-labelledby="navigation menu">
            <Menu fontSize="large" />
          </IconButton>
        </Hidden>
      </Toolbar>
    </AppBar>
  )
}
Example #27
Source File: Files.tsx    From NekoMaid with MIT License 4 votes vote down vote up
Files: React.FC = () => {
  const plugin = usePlugin()
  const theme = useTheme()
  const his = useHistory()
  const loc = useLocation()
  const drawerWidth = useDrawerWidth()
  const tree = useRef<HTMLHRElement | null>(null)
  const editor = useRef<UnControlled | null>(null)
  const prevExpanded = useRef<string[]>([])
  const dirs = useRef<Record<string, boolean>>({ })
  // eslint-disable-next-line func-call-spacing
  const loading = useRef<Record<string, () => Promise<void>> & { '!#LOADING'?: boolean }>({ })
  const [id, setId] = useState(0)
  const [curPath, setCurPath] = useState('')
  const [progress, setProgress] = useState(-1)
  const [copyPath, setCopyPath] = useState('')
  const [expanded, setExpanded] = useState<string[]>([])
  const [compressFile, setCompressFile] = useState<string | null>(null)
  const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement | null>(null)

  const isDir = !!dirs.current[curPath]
  const dirPath = isDir ? curPath : curPath.substring(0, curPath.lastIndexOf('/'))

  const spacing = theme.spacing(3)
  const refresh = () => {
    loading.current = { }
    dirs.current = { }
    prevExpanded.current = []
    setCurPath('')
    setExpanded([])
    setId(id + 1)
  }

  useEffect(() => {
    if (!tree.current) return
    const resize = () => {
      if (!tree.current) return
      const height = tree.current.style.maxHeight = (window.innerHeight - tree.current.offsetTop - parseInt(spacing)) + 'px'
      const style = (editor as any).current?.editor?.display?.wrapper?.style
      if (style) style.height = height
    }
    resize()
    window.addEventListener('resize', resize)
    return window.removeEventListener('resize', resize)
  }, [tree.current, spacing])

  return <Box sx={{ height: '100vh', py: 3 }}>
    <Toolbar />
    <Container maxWidth={false}>
      <Grid container spacing={3} sx={{ width: { sm: `calc(100vw - ${drawerWidth}px - ${theme.spacing(3)})` } }}>
        <Grid item lg={4} md={12} xl={3} xs={12}>
          <Card sx={{ minHeight: 400 }}>
            <CardHeader
              title={lang.files.filesList}
              sx={{ position: 'relative' }}
              action={<Box sx={{ position: 'absolute', right: theme.spacing(1), top: '50%', transform: 'translateY(-50%)' }}
            >
              <Tooltip title={lang.files.delete}><span>
                <IconButton
                  disabled={!curPath}
                  size='small'
                  onClick={() => dialog({
                    okButton: { color: 'error' },
                    content: <>{lang.files.confirmDelete(<span className='bold'>{curPath}</span>)}&nbsp;
                      <span className='bold' style={{ color: theme.palette.error.main }}>({lang.unrecoverable})</span></>
                  }).then(it => it && plugin.emit('files:update', (res: boolean) => {
                    action(res)
                    if (!res) return
                    refresh()
                    if (loc.pathname.replace(/^\/NekoMaid\/files\/?/, '') === curPath) his.push('/NekoMaid/files')
                  }, curPath))}
                ><DeleteForever /></IconButton>
              </span></Tooltip>
              <Tooltip title={lang.files.createFile}>
                <IconButton size='small' onClick={() => fileNameDialog(lang.files.createFile, curPath)
                  .then(it => it != null && his.push(`/NekoMaid/files/${dirPath ? dirPath + '/' : ''}${it}`))}>
              <Description /></IconButton></Tooltip>
              <Tooltip title={lang.files.createFolder}>
                <IconButton size='small' onClick={() => fileNameDialog(lang.files.createFolder, curPath)
                  .then(it => it != null && plugin.emit('files:createDirectory', (res: boolean) => {
                    action(res)
                    if (res) refresh()
                  }, dirPath + '/' + it))}><CreateNewFolder /></IconButton></Tooltip>
              <Tooltip title={lang.more}>
                <IconButton size='small' onClick={e => setAnchorEl(anchorEl ? null : e.currentTarget)}><MoreHoriz /></IconButton>
              </Tooltip>
            </Box>} />
            <Divider />
            <TreeView
              ref={tree}
              defaultCollapseIcon={<ArrowDropDown />}
              defaultExpandIcon={<ArrowRight />}
              sx={{ flexGrow: 1, width: '100%', overflowY: 'auto' }}
              expanded={expanded}
              onNodeToggle={(_: any, it: string[]) => {
                const l = loading.current
                if (it.length < prevExpanded.current.length || !l[it[0]]) {
                  setExpanded(it)
                  prevExpanded.current = it
                  return
                }
                l[it[0]]().then(() => {
                  prevExpanded.current.unshift(it[0])
                  setExpanded([...prevExpanded.current])
                  delete l[it[0]]
                })
                delete l[it[0]]
              }}
              onNodeSelect={(_: any, it: string) => {
                setCurPath(it[0] === '/' ? it.slice(1) : it)
                if (dirs.current[it] || loading.current['!#LOADING']) return
                if (it.startsWith('/')) it = it.slice(1)
                his.push('/NekoMaid/files/' + it)
              }}
            >
              <Item plugin={plugin} path='' loading={loading.current} dirs={dirs.current} key={id} />
            </TreeView>
          </Card>
        </Grid>
        <Grid item lg={8} md={12} xl={9} xs={12} sx={{ maxWidth: `calc(100vw - ${theme.spacing(1)})`, paddingBottom: 3 }}>
          <Editor plugin={plugin} editorRef={editor} loading={loading.current} dirs={dirs.current} refresh={refresh} />
        </Grid>
      </Grid>
    </Container>
    <Menu
      anchorEl={anchorEl}
      open={Boolean(anchorEl)}
      onClose={() => setAnchorEl(null)}
      anchorOrigin={anchorOrigin}
      transformOrigin={anchorOrigin}
    >
      <MenuItem onClick={() => {
        refresh()
        setAnchorEl(null)
      }}><ListItemIcon><Refresh /></ListItemIcon>{lang.refresh}</MenuItem>
      <MenuItem disabled={!curPath} onClick={() => {
        setAnchorEl(null)
        fileNameDialog(lang.files.rename, curPath).then(it => it != null && plugin.emit('files:rename', (res: boolean) => {
          action(res)
          if (res) refresh()
        }, curPath, dirPath + '/' + it))
      }}><ListItemIcon><DriveFileRenameOutline /></ListItemIcon>{lang.files.rename}</MenuItem>
      <MenuItem disabled={!curPath} onClick={() => {
        setAnchorEl(null)
        setCopyPath(curPath)
      }}>
        <ListItemIcon><FileCopy /></ListItemIcon>{lang.files.copy}
      </MenuItem>
      <MenuItem disabled={!copyPath} onClick={() => {
        setAnchorEl(null)
        toast(lang.files.pasting)
        plugin.emit('files:copy', (res: boolean) => {
          action(res)
          refresh()
        }, copyPath, dirPath)
      }}>
        <ListItemIcon><ContentPaste /></ListItemIcon>{lang.files.paste}
      </MenuItem>
      <MenuItem disabled={progress !== -1} component='label' htmlFor='NekoMaid-files-upload-input' onClick={() => setAnchorEl(null)}>
        <ListItemIcon><Upload /></ListItemIcon>{progress === -1 ? lang.files.upload : `${lang.files.uploading} (${progress.toFixed(2)}%)`}
      </MenuItem>
      <MenuItem disabled={isDir} onClick={() => {
        setAnchorEl(null)
        toast(lang.files.downloading)
        plugin.emit('files:download', (res: ArrayBuffer | null) => {
          if (res) window.open(address! + 'Download/' + res, '_blank')
          else failed()
        }, curPath)
      }}><ListItemIcon><Download /></ListItemIcon>{lang.files.download}</MenuItem>
      <MenuItem onClick={() => {
        setAnchorEl(null)
        setCompressFile(curPath)
      }}><ListItemIcon><Inbox /></ListItemIcon>{lang.files.compress}</MenuItem>
      <MenuItem onClick={() => {
        setAnchorEl(null)
        toast(lang.files.uncompressing)
        plugin.emit('files:compress', (res: boolean) => {
          action(res)
          refresh()
        }, curPath)
      }}><ListItemIcon><Outbox /></ListItemIcon>{lang.files.decompress}</MenuItem>
    </Menu>
    <Input id='NekoMaid-files-upload-input' type='file' sx={{ display: 'none' }} onChange={e => {
      const elm = e.target as HTMLInputElement
      const file = elm.files?.[0]
      elm.value = ''
      if (!file) return
      const size = file.size
      if (size > 128 * 1024 * 1024) return failed(lang.files.uploadTooBig)
      toast(lang.files.uploading)
      const name = dirPath + '/' + file.name
      if (dirs.current[name] != null) return failed(lang.files.exists)
      plugin.emit('files:upload', (res: string | null) => {
        if (!res) return failed(lang.files.exists)
        const formdata = new FormData()
        formdata.append('file', file)
        const xhr = new XMLHttpRequest()
        setProgress(0)
        xhr.open('put', address! + 'Upload/' + res)
        xhr.onreadystatechange = () => {
          if (xhr.readyState !== 4) return
          setProgress(-1)
          action(xhr.status === 200)
          refresh()
        }
        xhr.upload.onprogress = e => e.lengthComputable && setProgress(e.loaded / e.total * 100)
        xhr.send(formdata)
      }, name[0] === '/' ? name.slice(1) : name)
    }} />
    <CompressDialog file={compressFile} path={dirPath} dirs={dirs.current} onClose={() => setCompressFile(null)} refresh={refresh} plugin={plugin} />
  </Box>
}
Example #28
Source File: index.tsx    From mui-toolpad with MIT License 4 votes vote down vote up
function ApiEditorContent<Q>({ appId, className, apiNode }: ApiEditorContentProps<Q>) {
  const domApi = useDomApi();
  const dom = useDom();

  const [apiQuery, setApiQuery] = React.useState<Q>(apiNode.attributes.query.value);
  const savedQuery = React.useRef(apiNode.attributes.query.value);

  const [transformEnabled, setTransformEnabled] = React.useState<boolean>(
    apiNode.attributes.transformEnabled?.value ?? false,
  );
  const savedTransformEnabled = React.useRef(apiNode.attributes.transformEnabled?.value);

  const [transform, setTransform] = React.useState<string>(
    apiNode.attributes.transform?.value ?? '(data) => { return data }',
  );
  const savedTransform = React.useRef(apiNode.attributes.transform?.value);

  const conectionId = apiNode.attributes.connectionId.value as NodeId;
  const connection = appDom.getMaybeNode(dom, conectionId, 'connection');
  const dataSourceName = apiNode.attributes.dataSource.value;
  const dataSource = dataSources[dataSourceName] || null;

  const previewApi: appDom.ApiNode<Q> = React.useMemo(() => {
    return {
      ...apiNode,
      attributes: {
        ...apiNode.attributes,
        query: appDom.createConst(apiQuery),
        transformEnabled: appDom.createConst(transformEnabled),
        transform: appDom.createConst(transform),
      },
    };
  }, [apiNode, apiQuery, transformEnabled, transform]);

  const debouncedPreviewApi = useDebounced(previewApi, 250);

  const previewQuery = useQuery(['api', debouncedPreviewApi], async () =>
    client.query.execApi(appId, debouncedPreviewApi, {}),
  );

  const handleConnectionChange = React.useCallback(
    (newConnectionId) => {
      if (apiNode) {
        domApi.setNodeNamespacedProp(
          apiNode,
          'attributes',
          'connectionId',
          appDom.createConst(newConnectionId),
        );
      }
    },
    [apiNode, domApi],
  );

  const handleTransformFnChange = React.useCallback((newValue: string) => {
    setTransform(newValue);
  }, []);

  const handleTransformEnabledChange = React.useCallback(
    (event: React.ChangeEvent<HTMLInputElement>) => {
      setTransformEnabled(event.target.checked);
    },
    [],
  );

  const handleSave = React.useCallback(() => {
    (Object.keys(apiQuery) as (keyof Q)[]).forEach((propName) => {
      if (typeof propName !== 'string' || !apiQuery[propName]) {
        return;
      }
      domApi.setNodeNamespacedProp(apiNode, 'attributes', 'query', appDom.createConst(apiQuery));
      domApi.setNodeNamespacedProp(
        apiNode,
        'attributes',
        'transform',
        appDom.createConst(transform),
      );
      domApi.setNodeNamespacedProp(
        apiNode,
        'attributes',
        'transformEnabled',
        appDom.createConst(transformEnabled),
      );
    });
    savedQuery.current = apiQuery;
    savedTransform.current = transform;
    savedTransformEnabled.current = transformEnabled;
  }, [apiNode, apiQuery, domApi, transform, transformEnabled]);

  useShortcut({ code: 'KeyS', metaKey: true }, handleSave);

  const allChangesAreCommitted =
    savedQuery.current === apiQuery &&
    savedTransformEnabled.current === transformEnabled &&
    savedTransform.current === transform;

  usePrompt(
    'Your API has unsaved changes. Are you sure you want to navigate away? All changes will be discarded.',
    !allChangesAreCommitted,
  );

  if (!dataSource) {
    return (
      <NotFoundEditor className={className} message={`DataSource "${dataSourceName}" not found`} />
    );
  }

  const previewIsInvalid: boolean = !connection && !previewQuery.isError;

  return (
    <Box sx={{ width: '100%', height: '100%' }}>
      <SplitPane
        split="horizontal"
        allowResize
        defaultSize="60%"
        paneStyle={{
          width: '100%',
          overflowY: 'auto',
          display: 'block',
        }}
      >
        <Stack sx={{ width: '100%', p: 3 }}>
          <Stack direction="row" gap={2}>
            <NodeNameEditor node={apiNode} />
            <ConnectionSelect
              dataSource={dataSourceName}
              value={connection?.id ?? null}
              onChange={handleConnectionChange}
            />
          </Stack>
          <Toolbar disableGutters>
            <Button onClick={handleSave} disabled={allChangesAreCommitted}>
              Update
            </Button>
          </Toolbar>
          <Stack spacing={2}>
            {connection ? (
              <dataSource.QueryEditor
                appId={appId}
                connectionId={connection.id}
                // TODO: Add disabled mode to QueryEditor
                // disabled={!connection}
                value={apiQuery}
                onChange={(newApiQuery) => setApiQuery(newApiQuery)}
                globalScope={{}}
              />
            ) : null}
            <Stack>
              <FormControlLabel
                label="Transform API response"
                control={
                  <Checkbox
                    checked={transformEnabled}
                    onChange={handleTransformEnabledChange}
                    inputProps={{ 'aria-label': 'controlled' }}
                  />
                }
              />
            </Stack>
            {transformEnabled ? (
              <JsExpressionEditor
                globalScope={{}}
                value={transform}
                onChange={handleTransformFnChange}
              />
            ) : null}
          </Stack>
        </Stack>
        {previewQuery.isLoading || (previewIsInvalid && previewQuery.isFetching) ? (
          <LinearProgress />
        ) : null}
        <Box sx={{ p: 2 }}>
          {previewQuery.isError ? (
            <Alert severity="error">{(previewQuery.error as Error).message}</Alert>
          ) : null}
          {!previewIsInvalid && previewQuery.isSuccess ? (
            <JsonView src={previewQuery.data} />
          ) : null}
        </Box>
      </SplitPane>
    </Box>
  );
}
Example #29
Source File: Layout.tsx    From Cromwell with MIT License 4 votes vote down vote up
function Layout() {
  const forceUpdate = useForceUpdate();
  setStoreItem('forceUpdatePage', forceUpdate);

  onStoreChange('userInfo', (user) => {
    if (user && user.role !== userRole) {
      userRole = user.role;
      forceUpdate();
    }
  });

  useEffect(() => {
    store.setStateProp({
      prop: 'forceUpdateApp',
      payload: forceUpdate,
    });
  }, []);

  const darkMode = getStoreItem('theme')?.mode === 'dark';

  document.body.classList.remove('modeDark', 'modeLight');
  document.body.classList.add(darkMode ? 'modeDark' : 'modeLight');

  const theme = createTheme(darkMode ? {
    palette: {
      primary: {
        main: '#9747d3',
        light: '#9747d3',
        dark: '#8228c5',
      },
      secondary: {
        main: '#910081',
        light: '#910081',
        dark: '#910081',
      }
    },
  } : {
    palette: {
      primary: {
        main: '#8228c5',
        light: '#8561c5',
        dark: '#482880',
      },
      secondary: {
        main: '#910081',
        light: '#910081',
        dark: '#910081',
      }
    },
  });

  return (
    <ThemeProvider theme={theme}>
      <div className={clsx(styles.Layout)}>
        <BrowserRouter basename={'admin'}>
          <div className={styles.sidebar}>
            <Sidebar />
          </div>
          <div className={styles.main}>
            <Toolbar className={styles.dummyToolbar} />
            <Switch>
              {getPageInfos().map(page => {
                if (page.roles && !page.roles.includes(getStoreItem('userInfo')?.role))
                  return null;
                return (
                  <Route exact={!page.baseRoute}
                    path={page.route}
                    key={page.name}
                    component={(props: RouteComponentProps) => {
                      return (
                        <PageErrorBoundary>
                          <Suspense fallback={/*<LoadBox />*/<></>}>
                            <page.component {...props} />
                          </Suspense>
                        </PageErrorBoundary>
                      )
                    }}
                  />
                )
              })}
              <Route key={'404'} >
                <Page404 />
              </Route>
            </Switch>
          </div>
        </BrowserRouter>
        {document?.body && ReactDOM.createPortal(
          <div className={styles.toastContainer} ><ToastContainer /></div>, document.body)}
        <FileManager />
        <ConfirmPrompt />
        <LayoutPortal />
      </div>
    </ThemeProvider>
  );
}