@mui/material#Collapse TypeScript Examples

The following examples show how to use @mui/material#Collapse. 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: GroupFilter.tsx    From Tachidesk-WebUI with Mozilla Public License 2.0 6 votes vote down vote up
export default function GroupFilter(props: Props) {
    const {
        state,
        name,
        position,
        updateFilterValue,
        update,
    } = props;

    const [open, setOpen] = React.useState(false);

    const handleClick = () => {
        setOpen(!open);
    };

    return (
        <>
            <ListItemButton onClick={handleClick}>
                <ListItemText primary={name} />
                {open ? <ExpandLess /> : <ExpandMore />}
            </ListItemButton>
            <Collapse in={open}>
                <List disablePadding>
                    <Options
                        sourceFilter={state}
                        group={position}
                        updateFilterValue={updateFilterValue}
                        update={update}
                    />
                </List>
            </Collapse>
        </>
    );
}
Example #2
Source File: ErrorAlert.tsx    From mui-toolpad with MIT License 6 votes vote down vote up
export default function ErrorAlert({ error }: ErrorAlertProps) {
  const message: string =
    typeof (error as any)?.message === 'string' ? (error as any).message : String(error);
  const stack: string | null =
    typeof (error as any)?.stack === 'string' ? (error as any).stack : null;

  const [expanded, setExpanded] = React.useState(false);
  const toggleExpanded = React.useCallback(() => setExpanded((actual) => !actual), []);
  return (
    <Alert
      severity="error"
      sx={{
        // The content of the Alert doesn't overflow nicely
        // TODO: does this need to go in core?
        '& .MuiAlert-message': { minWidth: 0 },
      }}
      action={
        stack ? (
          <IconButton color="inherit" onClick={toggleExpanded}>
            {expanded ? <ExpandLessIcon /> : <ExpandMoreIcon />}
          </IconButton>
        ) : null
      }
    >
      <AlertTitle>{message}</AlertTitle>
      <Collapse in={expanded}>
        <Box sx={{ overflow: 'auto' }}>
          <pre>{stack}</pre>
        </Box>
      </Collapse>
    </Alert>
  );
}
Example #3
Source File: index.tsx    From genshin-optimizer with MIT License 6 votes vote down vote up
function FeatureCard({ image, title, content, t }) {
  const [expanded, setExpanded] = useState(false);

  return <CardLight >
    <CardContent sx={{ p: 1, pb: 0 }}>
      <Box component="img" src={image} alt="test" sx={{ width: "100%", height: "auto" }} />
    </CardContent>
    <CardHeader
      action={
        <ExpandButton
          expand={expanded}
          onClick={() => setExpanded(!expanded)}
          aria-expanded={expanded}
          aria-label="show more"
        >
          <ExpandMore />
        </ExpandButton>
      }
      titleTypographyProps={{ variant: "subtitle1" }}
      title={title(t)}
    />
    <Collapse in={expanded} timeout="auto" unmountOnExit>
      <CardContent sx={{ pt: 0 }}>
        {content(t)}
      </CardContent>
    </Collapse>
  </CardLight >
}
Example #4
Source File: index.tsx    From genshin-optimizer with MIT License 6 votes vote down vote up
function FormulaCalcCard() {
  const { t } = useTranslation("page_character")
  const [expanded, setexpanded] = useState(false)
  const toggle = useCallback(() => setexpanded(!expanded), [setexpanded, expanded])
  return <CardLight>
    <CardContent sx={{ display: "flex", gap: 1 }}>
      <Grid container spacing={1}>
        <Grid item><HitModeToggle size="small" /></Grid>
        <Grid item><InfusionAuraDropdown /></Grid>
        <Grid item><ReactionToggle size="small" /></Grid>
      </Grid>
      <Box display="flex" gap={1} >
        <Box>
          <Typography variant='subtitle2' >{t("formulas")} {"&"}</Typography>
          <Typography variant='subtitle2' >{t("calculations")}</Typography>
        </Box>
        <ExpandButton
          expand={expanded}
          onClick={toggle}
          aria-expanded={expanded}
          aria-label="show more"
          size="small"
          sx={{ p: 0 }}
        >
          <ExpandMore />
        </ExpandButton>
      </Box>
    </CardContent>
    <Collapse in={expanded} timeout="auto" unmountOnExit>
      <CardContent sx={{ pt: 0 }}>
        <CalculationDisplay />
      </CardContent>
    </Collapse>
  </CardLight>
}
Example #5
Source File: Collapsible.tsx    From GTAV-NativeDB with MIT License 6 votes vote down vote up
Collapsible: FunctionComponent<CollapsibleProps> = ({ children, label, variant, fullWidth }) => {
  const [open, setOpen] = useState(false)

  const toggle = useCallback(() => {
    setOpen(!open)
  }, [open, setOpen])

  return (
    <Fragment>
      <Button 
        variant={variant} 
        fullWidth={fullWidth} 
        onClick={toggle}
      >
        {label}
      </Button>
      <Collapse in={open}>
        {children}
      </Collapse>
    </Fragment>
  )
}
Example #6
Source File: ExpandableListItem.tsx    From frontend with MIT License 6 votes vote down vote up
ExpandableListItem = ({ header, content }: Props) => {
  const [open, setOpen] = useState(false)

  return (
    <List
      sx={{
        my: 0,
        mx: { xs: 0, md: 3 },
        cursor: 'pointer',
      }}>
      <Paper elevation={1} sx={{ borderRadius: 2 }}>
        <Box
          sx={{ display: 'flex', alignItems: 'center', px: 3, py: 1 }}
          onClick={() => setOpen(!open)}>
          <ListItemText
            primary={header}
            primaryTypographyProps={{
              variant: 'subtitle1',
              color: `${withAccentColor(open)}`,
            }}
          />
          {open ? (
            <ExpandLess sx={{ color: `${withAccentColor(open)}` }} />
          ) : (
            <ExpandMore sx={{ color: `${withAccentColor(open)}` }} />
          )}
        </Box>
        <Collapse in={open}>
          <List>
            <Box sx={{ pl: { xs: 3, md: 6 }, pb: 2, pr: 2 }}>{content}</Box>
          </List>
        </Collapse>
      </Paper>
    </List>
  )
}
Example #7
Source File: CategoryItem.tsx    From Cromwell with MIT License 6 votes vote down vote up
function TransitionComponent(props: TransitionProps & { children: React.ReactNode }) {
    const style = useSpring({
        from: { opacity: 0, transform: 'translate3d(20px,0,0)' },
        to: { opacity: props.in ? 1 : 0, transform: `translate3d(${props.in ? 0 : 20}px,0,0)` },
    });

    return (
        <animated.div style={style}>
            <Collapse {...props} />
        </animated.div>
    );
}
Example #8
Source File: Settings.tsx    From Cromwell with MIT License 5 votes vote down vote up
private makeCategory = (props: {
        title: string;
        component: (props: TTabProps) => JSX.Element;
        icon: JSX.Element;
        link?: string;
    }) => {
        const isExpanded = !!this.state.expandedItems[props.title];

        return (
            <div className={styles.category} key={props.title}>
                <div className={styles.categoryHeaderWrapper}
                    onClick={() => this.setState(prevState => {
                        return {
                            expandedItems: {
                                ...prevState.expandedItems,
                                [props.title]: !prevState.expandedItems[props.title],
                            }
                        }
                    })}
                >
                    <div className={styles.categoryLeft}>
                        <IconButton
                            className={clsx(styles.expand, {
                                [styles.expandOpen]: isExpanded,
                            })}
                            aria-expanded={isExpanded}
                        >
                            <ExpandMoreIcon />
                        </IconButton>
                        <div className={styles.categoryIcon}>
                            {props.icon}
                        </div>
                        <p className={styles.categoryTitle}>{props.title}</p>
                    </div>
                    <div>
                        {props.link && (
                            <Tooltip title="Documentation">
                                <IconButton
                                    onClick={() => window.open(props.link, '_blank')}>
                                    <HelpOutlineIcon />
                                </IconButton>
                            </Tooltip>
                        )}
                    </div>
                </div>
                <Collapse in={isExpanded} timeout="auto" unmountOnExit>
                    <div className={styles.categoryContent}>
                        <props.component
                            settings={this.state?.settings}
                            handleTextFieldChange={this.handleTextFieldChange}
                            changeSettings={this.changeSettings}
                        />
                    </div>
                </Collapse>
            </div >
        )
    }
Example #9
Source File: WalletDialog.tsx    From wallet-adapter with Apache License 2.0 5 votes vote down vote up
WalletDialog: FC<WalletDialogProps> = ({
    title = 'Select your wallet',
    featuredWallets = 3,
    onClose,
    ...props
}) => {
    const { wallets, select } = useWallet();
    const { open, setOpen } = useWalletDialog();
    const [expanded, setExpanded] = useState(false);

    const [featured, more] = useMemo(
        () => [wallets.slice(0, featuredWallets), wallets.slice(featuredWallets)],
        [wallets, featuredWallets]
    );

    const handleClose = useCallback(
        (event: SyntheticEvent, reason?: 'backdropClick' | 'escapeKeyDown') => {
            if (onClose) onClose(event, reason!);
            if (!event.defaultPrevented) setOpen(false);
        },
        [setOpen, onClose]
    );

    const handleWalletClick = useCallback(
        (event: SyntheticEvent, walletName: WalletName) => {
            select(walletName);
            handleClose(event);
        },
        [select, handleClose]
    );

    const handleExpandClick = useCallback(() => setExpanded(!expanded), [setExpanded, expanded]);

    return (
        <RootDialog open={open} onClose={handleClose} {...props}>
            <DialogTitle>
                {title}
                <IconButton onClick={handleClose} size="large">
                    <CloseIcon />
                </IconButton>
            </DialogTitle>
            <DialogContent>
                <List>
                    {featured.map((wallet) => (
                        <WalletListItem
                            key={wallet.adapter.name}
                            onClick={(event) => handleWalletClick(event, wallet.adapter.name)}
                            wallet={wallet}
                        />
                    ))}
                    {more.length ? (
                        <>
                            <Collapse in={expanded} timeout="auto" unmountOnExit>
                                <List>
                                    {more.map((wallet) => (
                                        <WalletListItem
                                            key={wallet.adapter.name}
                                            onClick={(event) => handleWalletClick(event, wallet.adapter.name)}
                                            wallet={wallet}
                                        />
                                    ))}
                                </List>
                            </Collapse>
                            <ListItem>
                                <Button onClick={handleExpandClick}>
                                    {expanded ? 'Less' : 'More'} options
                                    {expanded ? <CollapseIcon /> : <ExpandIcon />}
                                </Button>
                            </ListItem>
                        </>
                    ) : null}
                </List>
            </DialogContent>
        </RootDialog>
    );
}
Example #10
Source File: SortFilter.tsx    From Tachidesk-WebUI with Mozilla Public License 2.0 5 votes vote down vote up
export default function SortFilter(props: Props) {
    const {
        values,
        name,
        state,
        position,
        group,
        updateFilterValue,
        update,
    } = props;
    const [val, setval] = React.useState(state);

    const [open, setOpen] = React.useState(false);

    const handleClick = () => {
        setOpen(!open);
    };

    if (values) {
        const handleChange = (event:
        React.MouseEvent<HTMLDivElement, MouseEvent>, index: number) => {
            const tmp = val;
            if (tmp.index === index) {
                tmp.ascending = !tmp.ascending;
            } else {
                tmp.ascending = true;
            }
            tmp.index = index;
            setval(tmp);
            const upd = update.filter((e: {
                position: number; group: number | undefined;
            }) => !(position === e.position && group === e.group));
            updateFilterValue([...upd, { position, state: JSON.stringify(tmp), group }]);
        };

        const ret = (
            <FormControl fullWidth>
                <ListItemButton onClick={handleClick}>
                    <ListItemText primary={name} />
                    {open ? <ExpandLess /> : <ExpandMore />}
                </ListItemButton>
                <Collapse in={open}>
                    <List>
                        {values.map((value: string, index: number) => {
                            let icon;
                            if (val.index === index) {
                                icon = val.ascending ? (<ArrowUpwardIcon color="primary" />)
                                    : (<ArrowDownwardIcon color="primary" />);
                            }
                            return (
                                <ListItem disablePadding key={`${name} ${value}`}>
                                    <ListItemButton
                                        onClick={(event) => handleChange(event, index)}
                                    >
                                        <ListItemIcon>
                                            {icon}
                                        </ListItemIcon>
                                        <ListItemText primary={value} />
                                    </ListItemButton>
                                </ListItem>
                            );
                        })}
                    </List>
                </Collapse>
            </FormControl>
        );
        return (
            <Box key={name} sx={{ display: 'flex', flexDirection: 'column', minWidth: 120 }}>
                {ret}
            </Box>
        );
    }
    return (<></>);
}
Example #11
Source File: EnemyEditor.tsx    From genshin-optimizer with MIT License 5 votes vote down vote up
export function EnemyExpandCard() {
  const { data } = useContext(DataContext)
  const [expanded, setexpanded] = useState(false)
  const toggle = useCallback(() => setexpanded(!expanded), [setexpanded, expanded])
  const eLvlNode = data.get(input.enemy.level)
  const eDefRed = data.get(input.enemy.defRed)
  const eDefIgn = data.get(input.enemy.defIgn)
  return <CardLight>
    <CardContent>
      <Grid container>
        <Grid item flexGrow={1} alignItems="center">
          <Grid container spacing={1}>
            <Grid item>
              <Chip size="small" color="success" label={<span>{KeyMap.get(eLvlNode.info.key)} <strong>{eLvlNode.value}</strong></span>} />
            </Grid>
            {allElementsWithPhy.map(element => <Grid item key={element}>
              <Typography key={element} ><EnemyResText element={element} /></Typography>
            </Grid>)}
            <Grid item>
              <Typography>DEF Reduction {valueString(eDefRed.value, eDefRed.unit)}</Typography>
            </Grid>
            <Grid item>
              <Typography>DEF Ignore {valueString(eDefIgn.value, eDefIgn.unit)}</Typography>
            </Grid>
          </Grid>
        </Grid>
        <Grid item>
          <ExpandButton
            expand={expanded}
            onClick={toggle}
            aria-expanded={expanded}
            aria-label="show more"
            size="small"
            sx={{ p: 0 }}
          >
            <ExpandMore />
          </ExpandButton>
        </Grid>
      </Grid>
    </CardContent>
    <Collapse in={expanded} timeout="auto" unmountOnExit>
      <CardContent sx={{ pt: 0 }}>
        <EnemyEditor />
      </CardContent>
    </Collapse>
  </CardLight>
}
Example #12
Source File: App.tsx    From sapio-studio with Mozilla Public License 2.0 5 votes vote down vote up
function ContractViewer(props: {
    model: DiagramModel;
    engine: DiagramEngine;
    current_contract: ContractModel;
}) {
    const dispatch = useDispatch();
    const entity_id: EntityType = useSelector(selectEntityToView);
    const show = useSelector(selectShouldViewEntity);
    const theme = useTheme();
    const timing_simulator_enabled = useSelector(selectSimIsShowing);
    const details = entity_id[0] !== 'NULL' && show;
    const { model, engine, current_contract } = props;
    React.useEffect(() => {
        if (entity_id[0] === 'TXN')
            jump_to_entity(
                model,
                engine,
                TXIDAndWTXIDMap.get_by_txid_s(
                    current_contract.txid_map,
                    entity_id[1]
                ) ?? null
            );
        else if (entity_id[0] === 'UTXO')
            jump_to_entity(
                model,
                engine,
                TXIDAndWTXIDMap.get_by_txid_s(
                    current_contract.txid_map,
                    entity_id[1].hash
                )?.utxo_models[entity_id[1].nIn] ?? null
            );
    }, [entity_id]);

    return (
        <>
            <div className="main-container">
                <DemoCanvasWidget
                    engine={engine}
                    model={model}
                    background={theme.palette.background.paper}
                    color={theme.palette.divider}
                >
                    <CanvasWidget engine={engine as any} key={'main'} />
                </DemoCanvasWidget>
            </div>
            <Collapse in={details}>
                <CurrentlyViewedEntity current_contract={current_contract} />
            </Collapse>
            <div className="area-overlays">
                <Collapse in={timing_simulator_enabled}>
                    <SimulationController
                        contract={current_contract}
                        engine={engine}
                        hide={() => dispatch(toggle_showing())}
                    />
                </Collapse>
            </div>
        </>
    );
}
Example #13
Source File: UpdateInfoCard.tsx    From Cromwell with MIT License 5 votes vote down vote up
export default function UpdateInfoCard(props: {
    updateInfo: TUpdateInfo;
    currentVersion?: string;
    onStartUpdate: () => void;
}) {
    const { updateInfo, currentVersion } = props;
    const [changelogCollapsed, setChangelogCollapsed] = useState(true);

    const toggleChangelog = () => {
        setChangelogCollapsed(!changelogCollapsed)
    }

    return (
        <Grid item container xs={12} className={styles.update}>
            <h3 className={styles.updateTitle}>
                <UpdateIcon style={{ marginRight: '7px' }} />
                                Update available</h3>
            <p>{currentVersion ?? ''} {'>'} {updateInfo.version}</p>
            <div className={styles.changelogTitle}>
                <p onClick={toggleChangelog}>See changelog</p>
                <ExpandMoreIcon
                    className={clsx(styles.expand, !changelogCollapsed && styles.expandOpen)}
                    onClick={toggleChangelog}
                />
            </div>
            {updateInfo.onlyManualUpdate && (
                <div className={styles.warning}>
                    <WarningRoundedIcon />
                    <p style={{ margin: '0 0 0 5px' }}>Cannot launch automatic update. Please update using
                    <span className={styles.command}>yarn upgrade @cromwell/cms@{updateInfo.packageVersion} --exact</span>
                    command and restart CMS</p>
                </div>
            )}
            <Collapse in={!changelogCollapsed} timeout="auto" unmountOnExit>
                <div className={styles.changelogList}
                    dangerouslySetInnerHTML={{ __html: updateInfo.changelog }}></div>
            </Collapse>
            <Button
                disabled={updateInfo.onlyManualUpdate}
                color="primary"
                variant="contained"
                onClick={props.onStartUpdate}
            >Update</Button>
        </Grid>
    )
}
Example #14
Source File: Filter.tsx    From Cromwell with MIT License 5 votes vote down vote up
private getFilterItem = (props: {
    title: string;
    key: string;
    content: JSX.Element;
  }) => {
    const { collapsedItems } = this.state;
    if (collapsedItems[props.key] === undefined) {
      collapsedItems[props.key] = this.collapsedByDefault;
    }
    const isExpanded = !collapsedItems[props.key];

    return (
      <Card className="productFilter_card">
        <div className="productFilter_headerWrapper"
          onClick={() => this.setState(prev => ({
            collapsedItems: {
              ...prev.collapsedItems,
              [props.key]: !prev.collapsedItems[props.key]
            }
          }))}
        >
          <Typography gutterBottom style={{
            fontSize: '14px',
            margin: '0 0 0 15px'
          }}>{props.title}</Typography>
          <IconButton
            className={clsx('productFilter_expand', {
              'productFilter_expandOpen': isExpanded,
            })}
            aria-expanded={isExpanded}
            aria-label={`Toggle ${props.title} filter visibility`}
          >
            <ExpandMoreIcon />
          </IconButton>
        </div>
        <Collapse in={isExpanded} timeout="auto" unmountOnExit>
          {props.content}
        </Collapse>
      </Card >
    )
  }
Example #15
Source File: More.tsx    From NekoMaid with MIT License 5 votes vote down vote up
C: any = Collapse
Example #16
Source File: LoginForm.tsx    From frontend with MIT License 5 votes vote down vote up
function LoginForm() {
  const { t } = useTranslation('one-time-donation')
  const formik = useFormikContext<OneTimeDonation>()
  return (
    <Collapse in={!formik.values.anonymousDonation} timeout="auto">
      <Grid sx={{ marginBottom: theme.spacing(4) }} container rowSpacing={3}>
        <Grid item xs={12}>
          <Typography fontWeight={'bold'} fontSize={16} color="#343434">
            {t('second-step.login')}
          </Typography>
        </Grid>
        <Grid item xs={12}>
          <FormTextField name="personsEmail" type="text" label="Email" fullWidth size="medium" />
        </Grid>
        <Grid item xs={12}>
          <FormTextField
            name="personsPassword"
            type="password"
            label={t('second-step.password')}
            fullWidth
            size="medium"
          />
        </Grid>
        <Box display={'flex'} justifyContent="space-between" width="100%" alignItems="center">
          <FormControlLabel
            control={<Checkbox />}
            label={t('second-step.checkbox-label') as string}
          />
          <Box sx={{ opacity: 0.85 }}>
            <Typography display="inline" color="GrayText">
              Don&apos;t have an account?
            </Typography>{' '}
            <Link color={theme.palette.primary.dark} href="#">
              Sign up
            </Link>
          </Box>
        </Box>
        <Button color="info" variant="contained" fullWidth sx={{ marginTop: theme.spacing(3) }}>
          {t('second-step.btn-login')}
        </Button>
        <Button
          size="large"
          color="primary"
          variant="outlined"
          fullWidth
          sx={{ marginTop: theme.spacing(3) }}>
          <Box display="inline-flex" alignItems="center" marginRight={theme.spacing(2)}>
            <Google />
          </Box>
          Log in with Google
        </Button>
      </Grid>
    </Collapse>
  )
}
Example #17
Source File: AnonymousForm.tsx    From frontend with MIT License 5 votes vote down vote up
export default function AnonymousForm() {
  const [field] = useField('anonymousDonation')
  const { t } = useTranslation('one-time-donation')
  return (
    <>
      <CircleCheckboxField
        label={
          <Typography
            fontSize={16}
            display="inline-flex"
            alignItems="center"
            component="span"
            color="#343434"
            fontWeight="bold">
            {t('anonymous-menu.checkbox-label')}
            {field.value ? <ExpandLess /> : <ExpandMore />}
          </Typography>
        }
        name="anonymousDonation"
      />
      <Collapse in={field.value} timeout="auto" unmountOnExit>
        <Grid container columnSpacing={3} rowSpacing={3}>
          <Grid item xs={12} color="#343434" sx={{ opacity: 0.9 }}>
            <Typography>{t('anonymous-menu.info-start')}</Typography>
          </Grid>
          <Grid item xs={12} md={6}>
            <FormTextField
              name="personsFirstName"
              type="text"
              label={t('anonymous-menu.firstName')}
              fullWidth
            />
          </Grid>
          <Grid item xs={12} md={6}>
            <FormTextField
              name="personsLastName"
              type="text"
              label={t('anonymous-menu.lastName')}
              fullWidth
            />
          </Grid>
          <Grid item xs={12} md={6}>
            <FormTextField name="personsEmail" type="text" label="Email" fullWidth />
          </Grid>
          <Grid item xs={12} md={6}>
            <FormTextField
              name="personsPhone"
              type="text"
              label={t('anonymous-menu.phone')}
              fullWidth
            />
          </Grid>
          <Grid item xs={12} color="GrayText">
            <Typography>* {t('anonymous-menu.info-end')}</Typography>
          </Grid>
        </Grid>
      </Collapse>
    </>
  )
}
Example #18
Source File: Worlds.tsx    From NekoMaid with MIT License 4 votes vote down vote up
Worlds: React.FC = () => {
  const plugin = usePlugin()
  const globalData = useGlobalData()
  const [worlds, setWorlds] = useState<World[]>([])
  const [selected, setSelected] = useState('')
  const [open, setOpen] = useState(false)
  const update = () => plugin.emit('worlds:fetch', (data: World[]) => {
    setWorlds(data)
    if (data.length) setSelected(old => data.some(it => it.id === old) ? old : '')
  })
  useEffect(() => {
    const offUpdate = plugin.on('worlds:update', update)
    update()
    return () => { offUpdate() }
  }, [])
  const sw = worlds.find(it => it.id === selected)
  const getSwitch = (name: string, configId = name) => sw
    ? <ListItem
      secondaryAction={<Switch disabled={!globalData.hasMultiverse} checked={(sw as any)[name]}
      onChange={e => {
        plugin.emit('worlds:set', sw.id, configId, e.target.checked.toString())
        success()
      }}
    />}><ListItemText primary={(lang.worlds as any)[name]} /></ListItem>
    : null

  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}>
        <Card>
          <CardHeader title={lang.worlds.title} />
          <Divider />
          <Box sx={{ position: 'relative' }}>
            <TableContainer>
              <Table>
                <TableHead>
                  <TableRow>
                    <TableCell padding='checkbox' />
                    <TableCell>{lang.worlds.name}</TableCell>
                    {globalData.hasMultiverse && <TableCell>{lang.worlds.alias}</TableCell>}
                    <TableCell>{lang.worlds.players}</TableCell>
                    <TableCell>{lang.worlds.chunks}</TableCell>
                    <TableCell>{lang.worlds.entities}</TableCell>
                    <TableCell>{lang.worlds.tiles}</TableCell>
                    <TableCell>{lang.worlds.time}</TableCell>
                    <TableCell>{lang.worlds.weather}</TableCell>
                  </TableRow>
                </TableHead>
                <TableBody>
                  {worlds.map(it => <TableRow key={it.id}>
                    <TableCell padding='checkbox'><Checkbox checked={selected === it.id} onClick={() => setSelected(it.id)} /></TableCell>
                    <TableCell><Tooltip title={it.id}><span>{it.name}</span></Tooltip></TableCell>
                    {globalData.hasMultiverse && <TableCell>{it.alias}
                      <IconButton size='small' onClick={() => dialog(lang.inputValue, lang.worlds.alias).then(res => {
                        if (res == null) return
                        plugin.emit('worlds:set', it.id, 'alias', res)
                        success()
                      })}><Edit fontSize='small' /></IconButton>
                      </TableCell>}
                    <TableCell>{it.players}</TableCell>
                    <TableCell>{it.chunks}</TableCell>
                    <TableCell>{it.entities}</TableCell>
                    <TableCell>{it.tiles}</TableCell>
                    <TableCell><Countdown time={it.time} max={24000} interval={50} /></TableCell>
                    <TableCell><IconButton size='small' onClick={() => {
                      plugin.emit('worlds:weather', it.id)
                      success()
                    }}>
                      {React.createElement((it.weather === 1 ? WeatherRainy : it.weather === 2 ? WeatherLightningRainy : WbSunny) as any)}
                    </IconButton></TableCell>
                  </TableRow>)}
                </TableBody>
              </Table>
            </TableContainer>
          </Box>
        </Card>
        </Grid>
        <Grid item lg={4} md={6} xl={3} xs={12}>
          <Card>
            <CardHeader
              title={lang.operations}
              sx={{ position: 'relative' }}
              action={<Tooltip title={lang.worlds.save} placement='left'>
                <IconButton
                  size='small'
                  onClick={() => {
                    if (!sw) return
                    plugin.emit('worlds:save', sw.id)
                    success()
                  }}
                  sx={cardActionStyles}
                ><Save /></IconButton>
              </Tooltip>}
            />
            <Divider />
            <Box sx={{ position: 'relative' }}>
              {sw
                ? <List sx={{ width: '100%' }} component='nav'>
                  <ListItem secondaryAction={<ToggleButtonGroup
                    exclusive
                    color='primary'
                    size='small'
                    value={sw.difficulty}
                    onChange={(_, value) => {
                      plugin.emit('worlds:difficulty', sw.id, value)
                      success()
                    }}
                  >
                    {difficulties.map(it => <ToggleButton value={it.toUpperCase()} key={it}>{minecraft['options.difficulty.' + it]}</ToggleButton>)}
                  </ToggleButtonGroup>}><ListItemText primary={minecraft['options.difficulty']} /></ListItem>
                  <ListItem secondaryAction={<Switch checked={sw.pvp} onChange={e => {
                    plugin.emit('worlds:pvp', sw.id, e.target.checked)
                    success()
                  }} />}><ListItemText primary='PVP' /></ListItem>
                  {getSwitch('allowAnimals', 'spawning.animals.spawn')}
                  {getSwitch('allowMonsters', 'spawning.monsters.spawn')}
                  {globalData.hasMultiverse && <>
                    {getSwitch('allowFlight')}
                    {getSwitch('autoHeal')}
                    {getSwitch('hunger')}
                  </>}
                  <ListItem secondaryAction={globalData.canSetViewDistance
                    ? <IconButton
                      onClick={() => dialog({
                        content: lang.inputValue,
                        input: {
                          error: true,
                          type: 'number',
                          helperText: lang.invalidValue,
                          validator: (it: string) => /^\d+$/.test(it) && +it > 1 && +it < 33
                        }
                      }).then(res => {
                        if (!res) return
                        plugin.emit('worlds:viewDistance', sw.id, parseInt(res as any))
                        success()
                      })}
                    ><Edit /></IconButton>
                    : undefined}>
                    <ListItemText primary={lang.worlds.viewDistance + ': ' + sw.viewDistance} />
                  </ListItem>
                  <ListItem><ListItemText primary={minecraft['selectWorld.enterSeed']} secondary={sw.seed} /></ListItem>
                  <ListItemButton onClick={() => setOpen(!open)}>
                    <ListItemText primary={minecraft['selectWorld.gameRules']} />
                    {open ? <ExpandLess /> : <ExpandMore />}
                  </ListItemButton>
                  <Collapse in={open} timeout="auto" unmountOnExit>
                    <List component='div' dense disablePadding>
                      {sw.rules.map(([key, value]) => {
                        const isTrue = value === 'true'
                        const isBoolean = isTrue || value === 'false'
                        const isNumber = /^\d+$/.test(value)
                        return <ListItem
                          key={key}
                          sx={{ pl: 4 }}
                          secondaryAction={isBoolean
                            ? <Switch
                              checked={isTrue}
                              onChange={e => {
                                plugin.emit('worlds:rule', sw.id, key, e.target.checked.toString())
                                success()
                              }}
                            />
                            : <IconButton
                              onClick={() => dialog({
                                content: lang.inputValue,
                                input: isNumber
                                  ? {
                                      error: true,
                                      type: 'number',
                                      helperText: lang.invalidValue,
                                      validator: (it: string) => /^\d+$/.test(it)
                                    }
                                  : { }
                              }).then(res => {
                                if (res == null) return
                                plugin.emit('worlds:rule', sw.id, key, res)
                                success()
                              })}
                            ><Edit /></IconButton>}
                        >
                          <ListItemText primary={(minecraft['gamerule.' + key] || key) + (isBoolean ? '' : ': ' + value)} />
                        </ListItem>
                      })}
                    </List>
                  </Collapse>
                </List>
                : <CardContent><Empty /></CardContent>
              }
            </Box>
          </Card>
        </Grid>
      </Grid>
    </Container>
  </Box>
}
Example #19
Source File: index.tsx    From metaplex with Apache License 2.0 4 votes vote down vote up
Settings = ({ narrow }: { narrow: boolean }) => {
  const { disconnect, publicKey } = useWallet();
  const { setEndpoint, env, endpoint } = useConnectionConfig();
  const { setVisible } = useWalletModal();
  const open = React.useCallback(() => setVisible(true), [setVisible]);
  const { setModal } = useModal();
  const theme = useTheme();
  const colorModeCtx = useColorMode();

  const handleConnect = React.useCallback(() => {
    setModal(ModalEnum.WALLET);
    setVisible(true);
  }, [setModal, setVisible]);

  const connectedActions = [
    {
      click: async () => {
        if (publicKey) {
          await navigator.clipboard.writeText(publicKey.toBase58());
          notify({
            message: 'Wallet update',
            description: 'Address copied to clipboard',
          });
        }
      },
      innerNarrow: () =>
        `Copy Address (${publicKey && shortenAddress(publicKey.toBase58())})`,
      inner: function ConnectedWalletCopyC() {
        return (
          <React.Fragment>
            <CopyOutlined />
            {publicKey && shortenAddress(publicKey.toBase58())}
          </React.Fragment>
        );
      },
    },
    {
      click: open,
      inner: () => 'Change\u00A0Wallet',
    },
    {
      click: () => disconnect().catch(),
      inner: () => `Disconnect\u00A0(${env})`,
      expandedExtra: {
        // these are interepreted as props. TODO: specific types
        color: 'error' as any,
        variant: 'contained' as any,
      },
    },
  ];

  const [drawerOpen, setDrawerOpen] = React.useState(false);
  const [envCollapseOpen, setEnvCollapseOpen] = React.useState(false);

  const hackySkipSet = 'hackySkipSet';
  const toggleDrawer = open => event => {
    if (
      event.type === 'keydown' &&
      (event.key === 'Tab' || event.key === 'Shift')
    ) {
      return;
    }

    if (event.target.classList.contains(hackySkipSet)) {
      return;
    }

    setDrawerOpen(open);
  };

  const drawerC = inner => {
    return (
      <React.Fragment>
        <Button onClick={toggleDrawer(true)}>
          <AccountBalanceWalletIcon />
        </Button>
        <Drawer anchor="right" open={drawerOpen} onClose={toggleDrawer(false)}>
          <Box
            sx={{ width: 250 }}
            role="presentation"
            onClick={toggleDrawer(false)}
            onKeyDown={toggleDrawer(false)}
          >
            {inner}
          </Box>
        </Drawer>
      </React.Fragment>
    );
  };

  const themeSwitch = (
    <Button
      sx={{ ml: 1 }}
      onClick={colorModeCtx.toggleColorMode}
      color="inherit"
    >
      {theme.palette.mode === 'dark' ? (
        <Brightness7Icon />
      ) : (
        <Brightness4Icon />
      )}
    </Button>
  );

  if (narrow) {
    const listHead = (
      <ListItem>
        <ListItemText
          primary="Wallet"
          primaryTypographyProps={{
            fontSize: '1.2rem',
            fontWeight: 'medium',
            letterSpacing: 0,
          }}
        />
      </ListItem>
    );
    return (
      <React.Fragment>
        {!publicKey &&
          drawerC(
            <List>
              {listHead}
              <Divider />
              <ListItemButton
                onClick={() => setEnvCollapseOpen(!envCollapseOpen)}
                className={hackySkipSet}
              >
                Change Network
                {envCollapseOpen ? <ExpandLess /> : <ExpandMore />}
              </ListItemButton>
              <Collapse in={envCollapseOpen} timeout="auto" unmountOnExit>
                <List component="div" disablePadding>
                  {ENDPOINTS.map(p => (
                    <ListItemButton
                      selected={endpoint === p.endpoint}
                      onClick={() => setEndpoint(p.endpoint)}
                      key={p.name}
                      sx={{ pl: 4 }}
                      className={hackySkipSet}
                    >
                      {p.name}
                    </ListItemButton>
                  ))}
                </List>
              </Collapse>
              <ListItemButton onClick={handleConnect}>Connect</ListItemButton>
            </List>,
          )}
        {publicKey &&
          drawerC(
            <List>
              {listHead}
              <Divider />
              {connectedActions.map((a, idx) => {
                return (
                  <ListItemButton onClick={a.click} key={idx}>
                    {(a.innerNarrow && a.innerNarrow()) || a.inner()}
                  </ListItemButton>
                );
              })}
            </List>,
          )}
        {themeSwitch}
      </React.Fragment>
    );
  } else {
    return (
      <Stack
        direction="row"
        spacing={2}
        sx={{
          display: 'flex',
          justifyContent: 'flex-end',
          alignItems: 'center',
          marginRight: '36px',
        }}
      >
        {!publicKey && (
          <React.Fragment>
            <FormControl variant="standard" style={{ minWidth: '10ch' }}>
              <Select
                id="connected-env-select"
                onChange={e => {
                  setEndpoint(e.target.value);
                }}
                value={endpoint}
              >
                {ENDPOINTS.map(({ name, endpoint }) => (
                  <MenuItem key={name} value={endpoint}>
                    {name}
                  </MenuItem>
                ))}
              </Select>
            </FormControl>
            <Link underline="none">
              <Button variant="contained" onClick={handleConnect}>
                Connect
              </Button>
            </Link>
          </React.Fragment>
        )}
        {publicKey &&
          connectedActions.map((a, idx) => {
            return (
              <Button
                key={idx}
                variant="outlined"
                onClick={a.click}
                {...a.expandedExtra}
              >
                {a.inner()}
              </Button>
            );
          })}
        {themeSwitch}
      </Stack>
    );
  }
}
Example #20
Source File: FirstStep.tsx    From frontend with MIT License 4 votes vote down vote up
export default function FirstStep() {
  const { data: prices } = useSinglePriceList()
  const { t } = useTranslation('one-time-donation')
  const mobile = useMediaQuery('(max-width:568px)')
  const options = [
    { value: 'card', label: t('third-step.card') },
    { value: 'bank', label: t('third-step.bank-payment') },
  ]

  const [paymentField] = useField('payment')
  const [amount] = useField('amount')
  const { campaign } = useContext(StepsContext)
  const bankAccountInfo = {
    owner: t('third-step.owner'),
    bank: t('third-step.bank'),
    iban: ibanNumber,
  }
  return (
    <Root>
      <Typography variant="h4">{t('third-step.title')}</Typography>
      <Box marginTop={theme.spacing(4)}>
        <RadioButtonGroup name="payment" options={options} />
      </Box>
      <Collapse in={paymentField.value === 'bank'} timeout="auto">
        <List component="div" disablePadding>
          <Typography marginTop={theme.spacing(8)} variant="h6">
            {t('third-step.bank-details')}
          </Typography>
          <Divider className={classes.divider} />
          <Grid container justifyContent="center">
            <Grid my={2} item display="flex" justifyContent="space-between" xs={9}>
              <Typography>{bankAccountInfo.owner}</Typography>
              <CopyTextButton
                label={t('third-step.btn-copy')}
                text={bankAccountInfo.owner}
                variant="contained"
                size="small"
                color="info"
              />
            </Grid>
            <Grid my={2} item display="flex" justifyContent="space-between" xs={9}>
              <Typography>{bankAccountInfo.bank}</Typography>
              <CopyTextButton
                label={t('third-step.btn-copy')}
                text={bankAccountInfo.bank}
                variant="contained"
                size="small"
                color="info"
              />
            </Grid>
            <Grid my={2} item display="flex" justifyContent="space-between" xs={9}>
              <Typography>{ibanNumber}</Typography>
              <CopyTextButton
                label={t('third-step.btn-copy')}
                text={bankAccountInfo.iban}
                variant="contained"
                size="small"
                color="info"
              />
            </Grid>
          </Grid>

          <Typography my={2} variant="h6">
            {t('third-step.reason-donation')}
          </Typography>
          <Divider className={classes.divider} />
          <Grid container justifyContent="center">
            <Grid my={3} item display="flex" justifyContent="space-between" xs={9}>
              <Alert severity="warning">
                <Typography fontWeight="bold">{campaign.bankHash}</Typography>
              </Alert>
              <CopyTextButton
                text={campaign.title}
                variant="contained"
                color="info"
                size="small"
                label={t('third-step.btn-copy')}
              />
            </Grid>
          </Grid>

          <Typography>{t('third-step.message-warning')}</Typography>
        </List>
      </Collapse>
      <Collapse in={paymentField.value === 'card'} timeout="auto">
        <Typography variant="h4" sx={{ marginTop: theme.spacing(8) }}>
          {t('first-step.amount')}
        </Typography>
        <Box marginTop={theme.spacing(4)}>
          <RadioButtonGroup
            name="amount"
            options={
              prices
                ?.sort((a, b) => Number(a.unit_amount) - Number(b.unit_amount))
                .map((v) => ({
                  label: money(Number(v.unit_amount)),
                  value: v.id,
                }))
                .concat({ label: 'Other', value: 'other' }) || []
            }
          />
          <Collapse in={amount.value === 'other'} timeout="auto">
            <Grid
              style={
                !mobile
                  ? {
                      float: 'right',
                      marginTop: theme.spacing(-10),
                      width: '49%',
                    }
                  : { marginTop: theme.spacing(2) }
              }>
              <FormTextField
                name="otherAmount"
                type="number"
                label={t('first-step.amount')}
                InputProps={{
                  style: { fontSize: 20, padding: 16 },
                  endAdornment: (
                    <InputAdornment variant="filled" position="end">
                      Лв.
                    </InputAdornment>
                  ),
                }}
              />
            </Grid>
          </Collapse>
        </Box>
      </Collapse>
    </Root>
  )
}
Example #21
Source File: WalletMultiButton.tsx    From wallet-adapter with Apache License 2.0 4 votes vote down vote up
WalletMultiButton: FC<ButtonProps> = ({
    color = 'primary',
    variant = 'contained',
    type = 'button',
    children,
    ...props
}) => {
    const { publicKey, wallet, disconnect } = useWallet();
    const { setOpen } = useWalletDialog();
    const [anchor, setAnchor] = useState<HTMLElement>();

    const base58 = useMemo(() => publicKey?.toBase58(), [publicKey]);
    const content = useMemo(() => {
        if (children) return children;
        if (!wallet || !base58) return null;
        return base58.slice(0, 4) + '..' + base58.slice(-4);
    }, [children, wallet, base58]);

    if (!wallet) {
        return (
            <WalletDialogButton color={color} variant={variant} type={type} {...props}>
                {children}
            </WalletDialogButton>
        );
    }
    if (!base58) {
        return (
            <WalletConnectButton color={color} variant={variant} type={type} {...props}>
                {children}
            </WalletConnectButton>
        );
    }

    return (
        <>
            <Button
                color={color}
                variant={variant}
                type={type}
                startIcon={<WalletIcon wallet={wallet} />}
                onClick={(event) => setAnchor(event.currentTarget)}
                aria-controls="wallet-menu"
                aria-haspopup="true"
                {...props}
            >
                {content}
            </Button>
            <StyledMenu
                id="wallet-menu"
                anchorEl={anchor}
                open={!!anchor}
                onClose={() => setAnchor(undefined)}
                marginThreshold={0}
                TransitionComponent={Fade}
                transitionDuration={250}
                keepMounted
                anchorOrigin={{
                    vertical: 'top',
                    horizontal: 'left',
                }}
            >
                <WalletMenuItem onClick={() => setAnchor(undefined)}>
                    <Button
                        color={color}
                        variant={variant}
                        type={type}
                        startIcon={<WalletIcon wallet={wallet} />}
                        onClick={(event) => setAnchor(undefined)}
                        fullWidth
                        {...props}
                    >
                        {wallet.adapter.name}
                    </Button>
                </WalletMenuItem>
                <Collapse in={!!anchor}>
                    <WalletActionMenuItem
                        onClick={async () => {
                            setAnchor(undefined);
                            await navigator.clipboard.writeText(base58);
                        }}
                    >
                        <ListItemIcon>
                            <CopyIcon />
                        </ListItemIcon>
                        Copy address
                    </WalletActionMenuItem>
                    <WalletActionMenuItem
                        onClick={() => {
                            setAnchor(undefined);
                            setOpen(true);
                        }}
                    >
                        <ListItemIcon>
                            <SwitchIcon />
                        </ListItemIcon>
                        Change wallet
                    </WalletActionMenuItem>
                    <WalletActionMenuItem
                        onClick={() => {
                            setAnchor(undefined);
                            // eslint-disable-next-line @typescript-eslint/no-empty-function
                            disconnect().catch(() => {
                                // Silently catch because any errors are caught by the context `onError` handler
                            });
                        }}
                    >
                        <ListItemIcon>
                            <DisconnectIcon />
                        </ListItemIcon>
                        Disconnect
                    </WalletActionMenuItem>
                </Collapse>
            </StyledMenu>
        </>
    );
}
Example #22
Source File: ItemRow.tsx    From yearn-watch-legacy with GNU Affero General Public License v3.0 4 votes vote down vote up
ItemRow = <T extends GenericListItem>(props: ItemRowProps<T>) => {
    const [open, setOpen] = useState(false);
    const { item, index, headCells } = props;
    const labelId = `enhanced-table-checkbox-${index}`;
    const shouldCollapse = props.collapse !== undefined;

    const itemRow = headCells.map((headCell, headIndex) => {
        const itemRowKey = `${labelId}-${headIndex}`;
        const itemIdValue = headCell.id ? item[headCell.id] : '';
        const position = {
            rowNumber: index + 1,
            columnNumber: headIndex + 1,
        };
        const cellStyle = headCell.getStyle
            ? headCell.getStyle(item, position)
            : undefined;
        return (
            <TableCell
                component="th"
                id={labelId}
                scope="row"
                padding="normal"
                key={itemRowKey}
                align={headCell.align}
                style={cellStyle}
            >
                {headCell.format
                    ? headCell.format(item, itemIdValue, position)
                    : itemIdValue}
            </TableCell>
        );
    });
    const collapseButton = shouldCollapse ? (
        <TableCell
            component="th"
            id={`collapse-${index}`}
            scope="row"
            padding="normal"
            key={`collapse-${index}`}
            align="center"
        >
            <IconButton
                aria-label="expand row"
                size="small"
                onClick={() => setOpen(!open)}
            >
                {open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
            </IconButton>
        </TableCell>
    ) : (
        ''
    );
    const collapseRow = shouldCollapse ? (
        <TableRow>
            <TableCell
                style={{ paddingBottom: 0, paddingTop: 0 }}
                colSpan={headCells.length}
            >
                <Collapse in={open} timeout="auto" unmountOnExit>
                    <Box margin={1}>
                        {props.collapse ? props.collapse(index, item) : ''}
                    </Box>
                </Collapse>
            </TableCell>
        </TableRow>
    ) : (
        ''
    );
    return (
        <>
            <TableRow
                hover
                role="checkbox"
                tabIndex={-1}
                key={item.key}
                style={
                    props.getRowStyle
                        ? props.getRowStyle(index, item)
                        : undefined
                }
            >
                {collapseButton}
                {itemRow}
            </TableRow>
            {collapseRow}
        </>
    );
}
Example #23
Source File: PlayerList.tsx    From NekoMaid with MIT License 4 votes vote down vote up
PlayerInfo: React.FC<{ name?: string }> = React.memo(({ name }) => {
  const plugin = usePlugin()
  const globalData = useGlobalData()
  const [open, setOpen] = useState(false)
  const [info, setInfo] = useState<IPlayerInfo | undefined>()
  const refresh = () => plugin.emit('playerList:query', setInfo, name)
  useEffect(() => {
    setInfo(undefined)
    if (name) refresh()
  }, [name])

  return name && info
    ? <>
      <Divider />
      <List
        sx={{ width: '100%' }}
        component='nav'
        subheader={<ListSubheader component='div' sx={{ backgroundColor: 'inherit' }}>{lang.playerList.details}</ListSubheader>}
      >
        <ListItem>
          <ListItemIcon><AssignmentInd /></ListItemIcon>
          <ListItemText primary={globalData.onlineMode
            ? <Link underline='hover' rel='noopener' target='_blank' href={'https://namemc.com/profile/' + info.id}>{info.id}</Link>
            : info.id
          } />
        </ListItem>
        {!info.hasPlayedBefore && <ListItem>
          <ListItemIcon><ErrorOutline color='error' /></ListItemIcon>
          <ListItemText primary={lang.playerList.hasNotPlayed} />
        </ListItem>}
        {info.ban != null && <ListItem>
          <ListItemIcon><Block color='error' /></ListItemIcon>
          <ListItemText primary={lang.playerList.banned + (info.ban ? ': ' + info.ban : '')} />
        </ListItem>}
        {info.whitelisted && <ListItem>
          <ListItemIcon><Star color='warning' /></ListItemIcon>
          <ListItemText primary={lang.playerList.whitelisted} />
        </ListItem>}
        {info.isOP && <ListItem>
          <ListItemIcon><Security color='primary' /></ListItemIcon>
          <ListItemText primary={lang.playerList.op} />
          </ListItem>}
        {info.hasPlayedBefore && <>
            <ListItemButton onClick={() => setOpen(!open)}>
            <ListItemIcon><Equalizer /></ListItemIcon>
            <ListItemText primary={minecraft['gui.stats']} />
            {open ? <ExpandLess /> : <ExpandMore />}
          </ListItemButton>
          <Collapse in={open} timeout="auto" unmountOnExit>
            <List component='div' dense disablePadding>
              {[
                minecraft['stat.minecraft.play_time'] + ': ' + dayjs.duration(info.playTime / 20, 'seconds').humanize(),
                lang.playerList.firstPlay + ': ' + dayjs(info.firstPlay).fromNow(),
                lang.playerList.lastPlay + ': ' + dayjs(info.lastOnline).fromNow(),
                minecraft['stat.minecraft.leave_game'] + ': ' + info.quit,
                minecraft['stat.minecraft.deaths'] + ': ' + info.death,
                minecraft['stat.minecraft.player_kills'] + ': ' + info.playerKill,
                minecraft['stat.minecraft.mob_kills'] + ': ' + info.entityKill,
                lang.playerList.tnt + ': ' + info.tnt
              ].map((it, i) => <ListItem key={i} sx={{ pl: 4 }}>
                <ListItemIcon>{icons[i]}</ListItemIcon>
                <ListItemText primary={it} />
              </ListItem>)}
            </List>
          </Collapse>
        </>}
      </List>
      <CardActions disableSpacing sx={{ justifyContent: 'flex-end' }}>
        <Tooltip title={lang.playerList[info.whitelisted ? 'clickToRemoveWhitelist' : 'clickToAddWhitelist']}>
          <IconButton onClick={() => whitelist(name, plugin, refresh, !info.whitelisted)}>
            {info.whitelisted ? <Star color='warning' /> : <StarBorder />}
          </IconButton>
        </Tooltip>
        <Tooltip title={lang.playerList[info.ban == null ? 'clickToBan' : 'clickToPardon']}>
          <IconButton onClick={() => banPlayer(name, plugin, refresh, info.ban == null)}>
            <Block color={info.ban == null ? undefined : 'error'} />
          </IconButton>
        </Tooltip>
      </CardActions>
    </>
    : <></>
})
Example #24
Source File: Config.tsx    From NekoMaid with MIT License 4 votes vote down vote up
configs.push({
  title: lang.config.serverConfig,
  component () {
    const plugin = usePlugin()
    const globalData = useGlobalData()
    const [flag, update] = useState(0)
    const [info, setInfo] = useState<Record<string, string>>({ })
    const [open, setOpen] = useState(false)
    const [canGetData, setCanGetData] = useState(true)
    const [loading, setLoading] = useState(false)
    const setValue = (field: string, value: any, isGlobal = true) => {
      plugin.emit('server:set', field, value)
      success()
      if (isGlobal) {
        (globalData as any)[field] = value
        update(flag + 1)
        location.reload()
      }
    }
    const createEditButtom = (field: string, isGlobal?: boolean, isInt = true) => <IconButton
      onClick={() => dialog(
        {
          content: lang.inputValue,
          input: isInt
            ? {
                error: true,
                type: 'number',
                helperText: lang.invalidValue,
                validator: (it: string) => /^\d+$/.test(it) && +it >= 0
              }
            : { }
        }).then(res => res != null && setValue(field, isInt ? parseInt(res as any) : (res || null), isGlobal))}
    ><Edit /></IconButton>

    const infoElm: JSX.Element[] = []
    for (const key in info) {
      const name = (lang.config as any)[key]
      infoElm.push(<ListItem key={key} sx={{ pl: 4 }}>
        <ListItemText
          primary={key === 'isAikarFlags' ? <Link href='https://mcflags.emc.gs' target='_blank' rel='noopener'>{name}</Link> : name}
          secondary={info[key].toString()}
        />
      </ListItem>)
    }

    return <List>
      <CircularLoading loading={loading} />
      <ListItem secondaryAction={globalData.canSetMaxPlayers
        ? createEditButtom('maxPlayers')
        : undefined}>
        <ListItemText primary={lang.config.maxPlayers + ': ' + globalData.maxPlayers} />
      </ListItem>
      <ListItem secondaryAction={createEditButtom('spawnRadius')}>
        <ListItemText primary={lang.config.spawnRadius + ': ' + globalData.spawnRadius} />
      </ListItem>
      <ListItem secondaryAction={createEditButtom('motd', false, false)}>
        <ListItemText primary={lang.config.motd} />
      </ListItem>
      <ListItem secondaryAction={<Switch checked={globalData.hasWhitelist} onChange={e => setValue('hasWhitelist', e.target.checked)} />}>
        <ListItemText primary={lang.config.whitelist} />
      </ListItem>
      {canGetData && <>
        <ListItemButton onClick={() => {
          if (infoElm.length) setOpen(!open)
          else {
            setLoading(true)
            plugin.emit('server:fetchInfo', (data: any) => {
              setLoading(false)
              if (!data) {
                failed(lang.unsupported)
                setCanGetData(false)
                return
              }
              setInfo(data)
              setOpen(true)
            })
          }
        }}>
        <ListItemIcon><Equalizer /></ListItemIcon>
          <ListItemText primary={lang.info} />
          {open ? <ExpandLess /> : <ExpandMore />}
        </ListItemButton>
        <Collapse in={open} timeout='auto' unmountOnExit>
          <List component='div' dense disablePadding>{infoElm}</List>
        </Collapse>
      </>}
    </List>
  }
},
{
  title: lang.history,
  component () {
    const [cur, update] = useState(0)
    const list: ServerRecord[] = JSON.parse(localStorage.getItem('NekoMaid:servers') || '[]')
    return <List>
      {list.sort((a, b) => b.time - a.time).map(it => {
        const i = it.address.indexOf('?')
        return <ListItem
          disablePadding
          key={it.address}
          secondaryAction={<IconButton edge='end' size='small' onClick={() => {
            localStorage.setItem('NekoMaid:servers', JSON.stringify(list.filter(s => s.address !== it.address)))
            success()
            update(cur + 1)
          }}><Delete /></IconButton>}
        >
          <ListItemButton onClick={() => {
            location.hash = ''
            location.search = it.address
          }} dense>
            <ListItemAvatar><Avatar src={it.icon} variant='rounded'><HelpOutline /></Avatar></ListItemAvatar>
            <ListItemText primary={<Tooltip title={it.address.slice(i + 1)}>
              <span>{it.address.slice(0, i)}</span></Tooltip>} secondary={dayjs(it.time).fromNow()} />
          </ListItemButton>
        </ListItem>
      })}
    </List>
  }
},
{
  title: lang.config.theme,
  component () {
    const color = localStorage.getItem('NekoMaid:color') || 'blue'
    return <CardContent sx={{ textAlign: 'center' }}>
      <Box>
        <ToggleButtonGroup exclusive value={localStorage.getItem('NekoMaid:colorMode') || ''} onChange={(_, it) => {
          localStorage.setItem('NekoMaid:colorMode', it)
          location.reload()
        }}>
          <ToggleButton value='light'><Brightness7 /> {lang.config.light}</ToggleButton>
          <ToggleButton value=''><SettingsBrightness /> {lang.config.system}</ToggleButton>
          <ToggleButton value='dark'><Brightness4 /> {lang.config.dark}</ToggleButton>
        </ToggleButtonGroup>
      </Box>
      <Paper sx={{ marginTop: 2, width: '176px', overflow: 'hidden', display: 'inline-block' }}>
        {Object.keys(colors).slice(1, 17).map((key, i) => {
          const checked = color === key
          const elm = <Box
            key={key}
            onClick={() => {
              localStorage.setItem('NekoMaid:color', key)
              location.reload()
            }}
            sx={{
              backgroundColor: (colors as any)[key][600],
              width: '44px',
              height: '44px',
              display: 'inline-block',
              cursor: 'pointer'
            }}
          ><Check htmlColor='white' sx={{ top: '10px', position: 'relative', opacity: checked ? 1 : 0 }} /></Box>
          return (i + 1) % 4 === 0 ? <React.Fragment key={key}>{elm}<br /></React.Fragment> : elm
        })}
      </Paper>
    </CardContent>
  }
})
Example #25
Source File: ComponentCatalog.tsx    From mui-toolpad with MIT License 4 votes vote down vote up
export default function ComponentCatalog({ className }: ComponentCatalogProps) {
  const api = usePageEditorApi();
  const dom = useDom();

  const [openStart, setOpenStart] = React.useState(0);

  const closeTimeoutRef = React.useRef<NodeJS.Timeout>();
  const openDrawer = React.useCallback(() => {
    if (closeTimeoutRef.current) {
      clearTimeout(closeTimeoutRef.current);
    }
    setOpenStart(Date.now());
  }, []);

  const closeDrawer = React.useCallback(
    (delay?: number) => {
      const timeOpen = Date.now() - openStart;
      const defaultDelay = timeOpen > 750 ? 500 : 0;
      closeTimeoutRef.current = setTimeout(() => setOpenStart(0), delay ?? defaultDelay);
    },
    [openStart],
  );

  const handleDragStart = (componentType: string) => (event: React.DragEvent<HTMLElement>) => {
    event.dataTransfer.dropEffect = 'copy';
    const newNode = appDom.createElement(dom, componentType, {});
    api.deselect();
    api.newNodeDragStart(newNode);
    closeDrawer(0);
  };

  const toolpadComponents = useToolpadComponents(dom);

  const handleMouseEnter = React.useCallback(() => openDrawer(), [openDrawer]);
  const handleMouseLeave = React.useCallback(() => closeDrawer(), [closeDrawer]);

  return (
    <ComponentCatalogRoot
      className={className}
      onMouseEnter={handleMouseEnter}
      onMouseLeave={handleMouseLeave}
    >
      <Box
        sx={{
          display: 'flex',
          flexDirection: 'row',
          position: 'absolute',
          top: 0,
          bottom: 0,
          backgroundColor: 'background.default',
          borderRight: 1,
          borderColor: 'divider',
        }}
      >
        <Collapse in={!!openStart} orientation="horizontal" timeout={200} sx={{ height: '100%' }}>
          <Box sx={{ width: 300, height: '100%', overflow: 'auto' }}>
            <Box display="grid" gridTemplateColumns="1fr" gap={1} padding={1}>
              {Object.entries(toolpadComponents)
                .filter(([componentId]) => componentId !== PAGE_ROW_COMPONENT_ID)
                .map(([componentId, componentType]) => {
                  if (!componentType) {
                    throw new Error(
                      `Invariant: Component definition for "${componentId}" is undefined`,
                    );
                  }
                  return (
                    <ComponentCatalogItem
                      key={componentId}
                      draggable
                      onDragStart={handleDragStart(componentId)}
                    >
                      <DragIndicatorIcon color="inherit" />
                      {componentType.displayName}
                    </ComponentCatalogItem>
                  );
                })}
            </Box>
          </Box>
        </Collapse>
        <Box
          sx={{
            display: 'flex',
            flexDirection: 'column',
            alignItems: 'center',
            width: WIDTH_COLLAPSED,
          }}
        >
          <Box sx={{ mt: 2 }}>{openStart ? <ChevronLeftIcon /> : <ChevronRightIcon />}</Box>
          <Box position="relative">
            <Typography
              sx={{
                position: 'absolute',
                top: 0,
                display: 'flex',
                alignItems: 'center',
                fontSize: 20,
                transform: 'rotate(90deg) translate(-10px, 0)',
                transformOrigin: '0 50%',
              }}
            >
              Components
            </Typography>
          </Box>
        </Box>
      </Box>
    </ComponentCatalogRoot>
  );
}
Example #26
Source File: MenuItem.tsx    From console with GNU Affero General Public License v3.0 4 votes vote down vote up
MenuItem = ({
  page,
  stateClsName = "",
  onExpand,
  selectedMenuItem,
  pathValue = "",
  expandedGroup = "",
  setSelectedMenuItem,
  id = `${Math.random()}`,
  setPreviewMenuGroup,
  previewMenuGroup,
}: {
  page: any;
  stateClsName?: string;
  setSelectedMenuItem: (value: string) => void;
  selectedMenuItem?: any;
  pathValue?: string;
  onExpand: (id: any) => void;
  expandedGroup?: string;
  id?: string;
  setPreviewMenuGroup: (value: string) => void;
  previewMenuGroup: string;
}) => {
  const childrenMenuList = page?.children?.filter(
    (item: any) =>
      ((item.customPermissionFnc
        ? item.customPermissionFnc()
        : hasPermission(CONSOLE_UI_RESOURCE, IAM_PAGES_PERMISSIONS[item.to])) ||
        item.forceDisplay) &&
      !item.fsHidden
  );

  let hasChildren = childrenMenuList?.length;

  const expandCollapseHandler = useCallback(
    (e: any) => {
      e.preventDefault();
      if (previewMenuGroup === page.id) {
        setPreviewMenuGroup("");
      } else if (page.id !== selectedMenuItem) {
        setPreviewMenuGroup(page.id);
        onExpand("");
      }

      if (page.id === selectedMenuItem && selectedMenuItem === expandedGroup) {
        onExpand(null);
      } else if (page.id === selectedMenuItem) {
        onExpand(selectedMenuItem);
        setPreviewMenuGroup("");
      }
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [page, selectedMenuItem, previewMenuGroup, expandedGroup]
  );

  const selectMenuHandler = useCallback(
    (e: any) => {
      onExpand(page.id);
      setSelectedMenuItem(page.id);
      page.onClick && page.onClick(e);
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [page]
  );

  const onClickHandler = hasChildren
    ? expandCollapseHandler
    : selectMenuHandler;

  const isActiveGroup = expandedGroup === page.id;
  const activeClsName =
    pathValue.includes(selectedMenuItem) && page.id === selectedMenuItem
      ? "active"
      : "";

  return (
    <React.Fragment>
      <ListItem
        key={page.to}
        button
        onClick={(e: any) => {
          onClickHandler(e);
          setSelectedMenuItem(selectedMenuItem);
        }}
        component={page.component}
        to={page.to}
        id={id}
        className={`${activeClsName} ${stateClsName} main-menu-item `}
        disableRipple
        sx={{
          ...menuItemContainerStyles,
          marginTop: "5px",
          ...menuItemMiniStyles,

          "& .expanded-icon": {
            border: "1px solid #35393c",
          },
        }}
      >
        {page.icon && (
          <Tooltip title={`${page.name}`} placement="right">
            <ListItemIcon
              sx={{ ...menuItemIconStyles }}
              className={`${
                isActiveGroup && hasChildren ? "expanded-icon" : ""
              }`}
            >
              <Suspense fallback={<div>...</div>}>
                <page.icon />
              </Suspense>
            </ListItemIcon>
          </Tooltip>
        )}
        {page.name && (
          <ListItemText
            className={stateClsName}
            sx={{ ...menuItemTextStyles }}
            primary={page.name}
          />
        )}

        {hasChildren ? (
          isActiveGroup || previewMenuGroup === page.id ? (
            <MenuCollapsedIcon
              height={15}
              width={15}
              className="group-icon"
              style={{ color: "white" }}
            />
          ) : (
            <MenuExpandedIcon
              height={15}
              width={15}
              className="group-icon"
              style={{ color: "white" }}
            />
          )
        ) : null}
      </ListItem>

      {(isActiveGroup || previewMenuGroup === page.id) && hasChildren ? (
        <Collapse
          key={page.id}
          id={`${page.id}-children`}
          in={true}
          timeout="auto"
          unmountOnExit
        >
          <List
            component="div"
            disablePadding
            key={page.id}
            sx={{
              marginLeft: "15px",
              "&.mini": {
                marginLeft: "0px",
              },
            }}
            className={`${stateClsName}`}
          >
            {childrenMenuList.map((item: any) => {
              return (
                <ListItem
                  key={item.to}
                  button
                  component={item.component}
                  to={item.to}
                  onClick={(e: any) => {
                    if (page.id) {
                      setPreviewMenuGroup("");
                      setSelectedMenuItem(page.id);
                    }
                  }}
                  disableRipple
                  sx={{
                    ...menuItemStyle,
                    ...menuItemMiniStyles,
                  }}
                  className={`${stateClsName}`}
                >
                  {item.icon && (
                    <Tooltip title={`${item.name}`} placement="right">
                      <ListItemIcon
                        sx={{
                          background: "#00274D",
                          display: "flex",
                          alignItems: "center",
                          justifyContent: "center",

                          "& svg": {
                            fill: "#fff",
                            minWidth: "12px",
                            maxWidth: "12px",
                          },
                        }}
                        className="menu-icon"
                      >
                        <Suspense fallback={<div>...</div>}>
                          <item.icon />
                        </Suspense>
                      </ListItemIcon>
                    </Tooltip>
                  )}
                  {item.name && (
                    <ListItemText
                      className={stateClsName}
                      sx={{ ...menuItemTextStyles, marginLeft: "16px" }}
                      primary={item.name}
                    />
                  )}
                </ListItem>
              );
            })}
          </List>
        </Collapse>
      ) : null}
    </React.Fragment>
  );
}
Example #27
Source File: MenuItem.tsx    From Cromwell with MIT License 4 votes vote down vote up
Item = (props: {
    data: TMainMenuItem;
    itemProps?: {
        items: TMainMenuItem[];
        canReorder: boolean;
        refreshList: () => void;
    }
}) => {
    const { refreshList, items, canReorder } = props.itemProps ?? {};
    const item = props.data;

    const forceUpdate = useForceUpdate();
    const classes = useStyles();
    const [_expanded, setExpanded] = React.useState(false);
    const expanded = _expanded && !canReorder;

    if (!item) return null;

    const handleExpandClick = () => {
        if (canReorder) return;
        setExpanded(!_expanded);
    };

    const handleChange = (prop: keyof TMainMenuItem, val: string) => {
        (item as any)[prop] = val;
        forceUpdate();
    }

    const handleRemove = (event) => {
        event.stopPropagation();
        if (items) {
            items.splice(items.indexOf(item), 1);
            refreshList?.();
        }
    }

    return (
        <div className={`${classes.card} PluginMainMenu-paper`}>
            <CardActionArea
                className={classes.cardHeader}
                onClick={handleExpandClick}
            >
                <p className={classes.cardTitle}>{item.title}</p>
                <CardActions disableSpacing className={classes.cardActions}>
                    {!canReorder && (
                        <IconButton
                            className={clsx(classes.expand, {
                                [classes.expandOpen]: expanded,
                            })}
                            aria-expanded={expanded}
                            aria-label="show more"
                        >
                            <ExpandMoreIcon />
                        </IconButton>
                    )}
                    <IconButton onClick={handleRemove}>
                        <HighlightOffIcon />
                    </IconButton>
                </CardActions>
            </CardActionArea>
            <Collapse in={expanded} timeout="auto" unmountOnExit>
                <div className={classes.cardContent}>
                    <TextField label="Title" variant="outlined"
                        value={item.title}
                        className={classes.field}
                        onChange={(e) => { handleChange('title', e.target.value) }}
                    />
                    <TextField label="Link" variant="outlined"
                        value={item.href}
                        className={classes.field}
                        onChange={(e) => { handleChange('href', e.target.value) }}
                    />
                    <TextField label="Columns" variant="outlined"
                        value={item.sublinkCols}
                        className={classes.field}
                        onChange={(e) => { handleChange('sublinkCols', e.target.value) }}
                    />
                    <TextField label="Width in px" variant="outlined"
                        value={item.width}
                        className={classes.field}
                        onChange={(e) => { handleChange('width', e.target.value) }}
                    />
                    <TextField
                        value={item.html}
                        label="Custom HTML"
                        multiline
                        rows={4}
                        variant="outlined"
                        className={classes.field}
                        onChange={(e) => { handleChange('html', e.target.value) }}
                    />
                    <div className={classes.sublinksList}>
                        <h3 className={classes.sublinksTitle}>Sublinks</h3>
                        {item.sublinks && item.sublinks.map((sl, slIndex) => {
                            return (
                                <div className={`${classes.sublinkItem} PluginMainMenu-paper`} >
                                    <TextField label="Sublink title" variant="outlined"
                                        value={sl.title}
                                        className={classes.subField}
                                        onChange={(e) => { if (item.sublinks) item.sublinks[slIndex].title = e.target.value; forceUpdate(); }}
                                    />
                                    <TextField label="Sublink href" variant="outlined"
                                        value={sl.href}
                                        className={classes.subField}
                                        onChange={(e) => { if (item.sublinks) item.sublinks[slIndex].href = e.target.value; forceUpdate(); }}
                                    />
                                    <IconButton onClick={(e) => {
                                        e.stopPropagation();
                                        if (item.sublinks) item.sublinks.splice(slIndex, 1);
                                        refreshList?.();
                                    }}>
                                        <HighlightOffIcon />
                                    </IconButton>
                                </div>
                            )
                        })}
                        <div className={`PluginMainMenu-paper ${classes.card}`}>
                            <MenuItem
                                className={classes.addBtn}
                                onClick={() => {
                                    if (!item.sublinks) item.sublinks = [];
                                    item.sublinks.push({});
                                    forceUpdate();
                                }}>
                                <AddIcon />
                            </MenuItem>
                        </div>
                    </div>
                </div>
            </Collapse>
        </div>
    )
}
Example #28
Source File: ChartCard.tsx    From genshin-optimizer with MIT License 4 votes vote down vote up
export default function ChartCard({ chartData, plotBase, setPlotBase, disabled = false }: ChartCardProps) {
  const [showDownload, setshowDownload] = useState(false)
  const [showMin, setshowMin] = useState(true)
  const { data } = useContext(DataContext)
  const statKeys = ["atk", "hp", "def", "eleMas", "critRate_", "critDMG_", "heal_", "enerRech_"]
  if (data.get(input.weaponType).value !== "catalyst") statKeys.push("physical_dmg_")
  statKeys.push(`${data.get(input.charEle).value}_dmg_`)

  const { displayData, downloadData } = useMemo(() => {
    if (!chartData) return { displayData: null, downloadData: null }
    const points = chartData.data.map(({ value: y, plot: x }) => ({ x, y })) as Point[]
    const increasingX: Point[] = points.sort((a, b) => a.x - b.x)
    const minimumData: Point[] = []
    for (const point of increasingX) {
      let last: Point | undefined
      while ((last = minimumData.pop())) {
        if (last.y > point.y) {
          minimumData.push(last)
          break
        }
      }
      minimumData.push(point)
    }

    // Note:
    // We can also just use `minimumData` if the plotter supports multiple data sources.
    // It could be faster too since there're no empty entries in `minimumData`.
    if (minimumData[0]?.x !== increasingX[0]?.x)
      increasingX[0].min = minimumData[0].y
    minimumData.forEach(x => { x.min = x.y })

    const downloadData = {
      minimum: minimumData.map(({ x, y }) => [x, y]),
      allData: increasingX.map(({ x, y }) => [x, y]),
    }
    return { displayData: increasingX, downloadData }
  }, [chartData])

  return <CardLight>
    <CardContent>
      <Grid container spacing={1} alignItems="center">
        <Grid item>
          <Typography variant="h6" >Optimization Target vs</Typography>
        </Grid>
        <Grid item>
          <DropdownButton title={plotBase ? KeyMap.get(plotBase) : "Not Selected"}
            color={plotBase ? "success" : "primary"}
            disabled={disabled}
          >
            <MenuItem onClick={() => { setPlotBase("") }}>Unselect</MenuItem>
            <Divider />
            {statKeys.map(sKey => <MenuItem key={sKey} onClick={() => { setPlotBase(sKey as any) }}>{KeyMap.get(sKey)}</MenuItem>)}
          </DropdownButton>
        </Grid>
        <Grid item flexGrow={1}>
          <Tooltip placement="top" title="Using data from the builder, this will generate a graph to visualize Optimization Target vs. a selected stat. The graph will show the maximum Optimization Target value per 0.01 of the selected stat.">
            <Info />
          </Tooltip>
        </Grid>
        {!!downloadData && <Grid item>
          <Button startIcon={showMin ? <CheckBox /> : <CheckBoxOutlineBlank />}
            color={showMin ? "success" : "secondary"}
            onClick={() => setshowMin(!showMin)}>Show Min Stat Threshold</Button>
        </Grid>}
        {!!downloadData && <Grid item>
          <Button color="info" startIcon={<Download />} onClick={() => setshowDownload(!showDownload)}>Download Data</Button>
        </Grid>}
      </Grid>
    </CardContent>
    {!!displayData && <Divider />}
    {chartData && !!displayData && <CardContent>
      <Collapse in={!!downloadData && showDownload}>
        <CardDark sx={{ mb: 2 }}>
          <CardContent>
            <Typography>Min Data</Typography>
            <DataDisplay data={downloadData?.minimum} />
            <Typography>All Data</Typography>
            <DataDisplay data={downloadData?.allData} />
          </CardContent>
        </CardDark>
      </Collapse>
      <Chart displayData={displayData} plotNode={chartData.plotNode} valueNode={chartData.valueNode} showMin={showMin} />
    </CardContent>}
  </CardLight >
}
Example #29
Source File: latest-frontend-dependencies.tsx    From Cromwell with MIT License 4 votes vote down vote up
export default function FrontendDependencies() {

    const [expanded, setExpanded] = React.useState(false);
    const [versionsLoading, setVersionsLoading] = React.useState(false);
    const [cmsVersions, setCmsVersions] = React.useState<string[]>([]);
    const [pickedVersion, setPickedVersion] = React.useState<string | undefined>();
    const [dependencies, setDependencies] = useState<{
        name: string;
        version: string;
    }[]>([]);

    const handleExpandClick = () => {
        setExpanded(!expanded);
    };

    useEffect(() => {
        (async () => {
            setVersionsLoading(true);
            const versions = (await apiClient.getFrontendDependenciesBindings())
                .filter(compareVersions.validate)
                .sort(compareVersions).reverse();

            setCmsVersions(versions);
            const latest = versions[0];
            setPickedVersion(latest);

            await getDependencies(latest);
        })();
    }, []);


    const getDependencies = async (version: string) => {
        setVersionsLoading(true);
        const deps = await apiClient.getFrontendDependenciesList(version);
        setDependencies(Object.keys(deps?.latestVersions ?? {}).map(pckg => ({
            name: pckg,
            version: (deps?.latestVersions ?? {})[pckg],
        })));
        setVersionsLoading(false);
    }

    const getDepName = (option) => `${option.name}: "${option.version}"`;

    const changeCmsVersion = async (version: string) => {
        setPickedVersion(version);
        setDependencies([]);
        await getDependencies(version);
    }

    return (
        <Layout
            title='Hello from'
            description=""
        >
            <div className={styles.content}>
                <h1 className={styles.title}>Latest Frontend dependencies</h1>
                <Link
                    style={{ marginBottom: '25px' }}
                    href="/docs/development/frontend-dependencies">Documentation</Link>
                <div className={styles.searchBox} >
                    <Autocomplete
                        id="cms-versions"
                        options={cmsVersions ?? ['']}
                        value={pickedVersion ?? ''}
                        onChange={(event, value) => changeCmsVersion(value)}
                        getOptionLabel={ver => ver}
                        style={{ width: 300 }}
                        renderInput={(params) =>
                            <TextField {...params}
                                label="Pick CMS version"
                                variant="outlined"
                            />}
                    />
                </div>
                <div className={styles.searchBox}>
                    {versionsLoading ? (
                        <CircularProgress />
                    ) : (
                        <Autocomplete
                            id="dependencies-versions"
                            options={dependencies}
                            getOptionLabel={getDepName}
                            style={{ width: 300 }}
                            renderInput={(params) =>
                                <TextField {...params}
                                    label="Search dependencies..."
                                    variant="outlined"
                                />}
                        />
                    )}
                </div>
                <div className={styles.listHeader} onClick={handleExpandClick}>
                    <h3 className={styles.expandTitle}>Expand all</h3>
                    <IconButton >
                        <ExpandMoreIcon
                            style={{ transform: expanded ? 'rotate(180deg)' : '' }}
                        />
                    </IconButton>
                </div>
                <Collapse in={expanded} timeout="auto" unmountOnExit>
                    {dependencies.map(dep => {
                        return (
                            <div key={dep.name}>{getDepName(dep)}</div>
                        )
                    })}
                </Collapse>

            </div>
        </Layout>
    )
}