@material-ui/core#Slider TypeScript Examples

The following examples show how to use @material-ui/core#Slider. 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: Settings.tsx    From firetable with Apache License 2.0 6 votes vote down vote up
export default function Settings({ handleChange, config }: ISettingsProps) {
  return (
    <>
      <Subheading>Maximum number of stars</Subheading>
      <Slider
        defaultValue={5}
        value={config.max}
        getAriaValueText={(v) => `${v} max stars`}
        aria-labelledby="max-slider"
        valueLabelDisplay="auto"
        onChange={(_, v) => {
          handleChange("max")(v);
        }}
        step={1}
        marks
        min={1}
        max={15}
      />
      <Subheading>Slider precision</Subheading>
      <Slider
        defaultValue={0.5}
        value={config.precision}
        getAriaValueText={(v) => `${v} rating step size`}
        aria-labelledby="precision-slider"
        valueLabelDisplay="auto"
        onChange={(_, v) => {
          handleChange("precision")(v);
        }}
        step={0.25}
        marks
        min={0.25}
        max={1}
      />
    </>
  );
}
Example #2
Source File: NumericFacet.tsx    From cognitive-search-static-web-apps-sample-ui with MIT License 6 votes vote down vote up
render(): JSX.Element {
        const state = this.props.state;
        var marks = null, step = null;

        // If the number of distinct values is too large, the slider's look becomes messy.
        // So we have to switch to a fixed step
        if (state.values.length > 200) {
            step = (state.maxValue - state.minValue) / 100;
        } else {
            marks = state.values.map(v => { return { value: v } });
        }

        return (<SliderDiv>
            <Slider
                disabled={this.props.inProgress}
                value={state.range}
                marks={marks}
                step={step}
                min={state.minValue}
                max={state.maxValue}
                onChange={(evt, newValue) => {
                    state.range = newValue as number[];
                }}
                onChangeCommitted={(evt, newValue) => {
                    state.range = newValue as number[];
                    state.apply()
                }}
                valueLabelDisplay="on"
            />
        </SliderDiv>);
    }
Example #3
Source File: Governance.tsx    From homebase-app with MIT License 6 votes vote down vote up
StyledSlider = withStyles({
  root: {
    textAlign: "center",
    width: "100%",
  },
  valueLabel: {
    textAlign: "center",
  },
  thumb: {
    height: 20,
    width: 20,
    top: "24.5%",
    backgroundColor: "#fff",
    border: "3px solid #fff",
  },
  track: {
    backgroundColor: "#4BCF93",
    borderRadius: "4px",
    height: 2,
  },
})(Slider)
Example #4
Source File: duration-slider.tsx    From backstage with Apache License 2.0 6 votes vote down vote up
export function DurationSlider(props: DurationSliderProps) {
  const { header, value, setValue } = props;

  const [curValue, setCurValue] = useState(value);

  const debouncedSetValue = useMemo(() => debounce(setValue, 1000), [setValue]);

  const onChange = useCallback(
    (_: any, index: number | number[]) => {
      const millis = marks[index as number].seconds * 1000;
      setCurValue(millis);
      debouncedSetValue(millis);
    },
    [debouncedSetValue],
  );

  const indexValue = useMemo(() => findMarkIndex(curValue / 1000), [curValue]);

  return (
    <>
      <Label>
        {header} {formatDuration(curValue)}
      </Label>
      <Slider
        value={indexValue}
        min={0}
        step={1}
        max={marks.length - 1}
        marks
        getAriaValueText={formatDurationFromIndex}
        valueLabelFormat={formatDurationFromIndex}
        onChange={onChange}
        valueLabelDisplay="auto"
        aria-labelledby="slider-hide-limit"
      />
    </>
  );
}
Example #5
Source File: VolumeSlider.tsx    From Oratio with MIT License 6 votes vote down vote up
export default function VolumeSlider() {
  const { t } = useTranslation();
  const [volume, setVolume] = React.useState<number>(
    parseInt(localStorage.getItem('volume') || '25', 10)
  );

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const handleVolumeChange = (_event: any, newValue: number | number[]) => {
    setVolume(newValue as number);
    localStorage.setItem('volume', newValue.toString());
  };

  return (
    <div>
      <Typography id="continuous-slider" gutterBottom>
        {t('Volume')}
      </Typography>
      <Grid container spacing={3}>
        <Grid item>
          <VolumeDown />
        </Grid>
        <Grid item xs>
          <Slider
            value={volume}
            onChange={handleVolumeChange}
            aria-labelledby="continuous-slider"
            valueLabelDisplay="on"
          />
        </Grid>
        <Grid item>
          <VolumeUp />
        </Grid>
      </Grid>
    </div>
  );
}
Example #6
Source File: TextSpeedSlider.tsx    From Oratio with MIT License 6 votes vote down vote up
export default function TextSpeedSlider() {
  const { t } = useTranslation();
  const [textSpeed, setTextSpeed] = React.useState<number>(
    parseInt(localStorage.getItem('textSpeed') || '75', 10)
  );

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const handleTextSpeedChange = (_event: any, newValue: number | number[]) => {
    setTextSpeed(newValue as number);
    localStorage.setItem('textSpeed', newValue.toString());
  };

  return (
    <div>
      <Typography id="continuous-slider" gutterBottom>
        {t('Text Speed')}
      </Typography>
      <Grid container spacing={3}>
        <Grid item>
          <SpeedIcon />
        </Grid>
        <Grid item xs>
          <Slider
            value={textSpeed}
            onChange={handleTextSpeedChange}
            aria-labelledby="continuous-slider"
            valueLabelDisplay="on"
            max={100}
          />
        </Grid>
      </Grid>
    </div>
  );
}
Example #7
Source File: FontSizeSlider.tsx    From Oratio with MIT License 6 votes vote down vote up
export default function FontSizeSlider() {
  const { t } = useTranslation();
  const [fontSize, setFontSize] = React.useState<number>(
    parseInt(localStorage.getItem('fontSize') || '48', 10)
  );

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const handleFontSizeChange = (_event: any, newValue: number | number[]) => {
    setFontSize(newValue as number);
    localStorage.setItem('fontSize', newValue.toString());
  };

  return (
    <div>
      <Typography id="continuous-slider" gutterBottom>
        {t('Text Size')}
      </Typography>
      <Grid container spacing={3}>
        <Grid item>
          <FormatSizeIcon />
        </Grid>
        <Grid item xs>
          <Slider
            value={fontSize}
            onChange={handleFontSizeChange}
            aria-labelledby="continuous-slider"
            valueLabelDisplay="on"
            max={200}
          />
        </Grid>
      </Grid>
    </div>
  );
}
Example #8
Source File: FontBoldSlider.tsx    From Oratio with MIT License 6 votes vote down vote up
export default function FontBoldSlider() {
  const { t } = useTranslation();
  const [fontWeight, setFontWeight] = React.useState<number>(
    parseInt(localStorage.getItem('fontWeight') || '400', 10)
  );

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const handleFontWeightChange = (_event: any, newValue: number | number[]) => {
    setFontWeight(newValue as number);
    localStorage.setItem('fontWeight', newValue.toString());
  };

  return (
    <div>
      <Typography id="continuous-slider" gutterBottom>
        {t('Text Boldness')}
      </Typography>
      <Grid container spacing={3}>
        <Grid item>
          <FormatBoldIcon />
        </Grid>
        <Grid item xs>
          <Slider
            value={fontWeight}
            onChange={handleFontWeightChange}
            aria-labelledby="continuous-slider"
            valueLabelDisplay="on"
            max={900}
            min={100}
            step={100}
            marks
          />
        </Grid>
      </Grid>
    </div>
  );
}
Example #9
Source File: VariationsTab.tsx    From prompts-ai with MIT License 5 votes vote down vote up
export default function VariationsTab() {
    const styles = useStyles();
    const dispatch = useDispatch();

    const maxCompletions = useSelector(selectMaxVariations);
    const handleMaxVariationsChange = (event: React.ChangeEvent<{}>, value: number | number[]) => {
        dispatch(editMaxVariations(value as number));
    }

    const showPrompt = useSelector(selectShowPromptForVariations);
    const handlePromptSwitchChange = (event: React.ChangeEvent<{}>, value: boolean) => {
        dispatch(updateShowPromptForVariations(value));
    }

    return <Box>
        <Box mb={1}>
            <Card className={styles.instructionCard}>
                <CardContent>
                    <Typography variant="subtitle1">Variations</Typography>
                    <Typography variant="body2">
                        This is a tool to generate multiple completions from the same prompt. Use it to explore the variety
                        of GPT-3 completions and impact of parameters on them. If you like a completion, add it to the prompt
                        and GPT-3 will generate more similar completions.
                    </Typography>
                    <Box mt={1}>
                        <Typography id="max-variations-slider" gutterBottom>
                            How many samples to generate (impacts processing time):
                        </Typography>
                        <Slider
                            defaultValue={10}
                            value={maxCompletions}
                            onChange={handleMaxVariationsChange}
                            aria-labelledby="max-variations-slider"
                            valueLabelDisplay="auto"
                            step={1}
                            marks={[{
                                value: 1,
                                label: '0',
                            }, {
                                value: 15,
                                label: '15',
                            }]}
                            min={1}
                            max={15}
                        />
                    </Box>

                    <Grid container spacing={1} alignItems="center">
                        <Grid item><FetchVariationsButton/></Grid>
                        <Grid item><Button
                            onClick={() => dispatch(cleanVariations())}
                        >Clean all</Button></Grid>
                    </Grid>
                    <Grid container spacing={1} alignItems="center">
                        <Grid item><FormControlLabel
                            control={<Switch checked={showPrompt} onChange={handlePromptSwitchChange}
                                             name="variations-prompt-switch" color="primary"/>}
                            label="Show prompt"
                        /></Grid>
                    </Grid>
                </CardContent>
            </Card>
        </Box>
        <VariationsCollection/>
    </Box>;
}
Example #10
Source File: SliderInput.tsx    From ow-mod-manager with MIT License 5 votes vote down vote up
SliderInput: FunctionComponent<Props> = ({
  value,
  onChange,
  label,
  disabled,
  tooltip = '',
}) => {
  const [displayValue, setDisplayValue] = useState(value);
  const styles = useStyles();
  const handleChangeCommitted = useCallback(
    (_: React.ChangeEvent<unknown>, changeValue: number | number[]) =>
      onChange(typeof changeValue === 'number' ? changeValue : changeValue[0]),
    [onChange]
  );

  const handleChange = useCallback(
    (_: React.ChangeEvent<unknown>, changeValue: number | number[]) =>
      setDisplayValue(
        typeof changeValue === 'number' ? changeValue : changeValue[0]
      ),
    []
  );

  useEffect(() => {
    debugConsole.log('useEffect: SliderInput setDisplayValue');
    setDisplayValue(value);
  }, [value]);

  return (
    <ListItem>
      <Typography>{label}</Typography>
      <Tooltip title={tooltip} placement="bottom">
        <Slider
          disabled={disabled}
          className={styles.slider}
          value={displayValue}
          onChangeCommitted={handleChangeCommitted}
          onChange={handleChange}
          step={10}
          min={10}
          max={200}
          valueLabelDisplay="auto"
          color="secondary"
          marks={[
            { value: 10, label: '10' },
            { value: 50, label: '50' },
            { value: 100, label: '100' },
            { value: 150, label: '150' },
            { value: 200, label: '200' },
          ]}
        />
      </Tooltip>
    </ListItem>
  );
}
Example #11
Source File: NotificationContent.tsx    From anchor-web-app with Apache License 2.0 5 votes vote down vote up
function NotificationContentBase({ className }: NotificationContentProps) {
  const { liquidationAlert, updateLiquidationAlert } = useJobs();

  const { focusVisible, ...switchClasses } = useSwitchStyle();
  const sliderClasses = useSliderStyle();

  const testNotifications = useCallback(() => {
    new Notification('Anchor Borrow Usage Notification', {
      body: 'Notifications have been enabled.',
    });
  }, []);

  return (
    <div className={className}>
      <h2>
        <NotificationsNone />
        <IconSpan>
          Notification{' '}
          <InfoTooltip>
            Currently notifications only support desktop browsers and require
            the webapp to be open in a tab
          </InfoTooltip>
        </IconSpan>
      </h2>

      <div className="switch">
        <p>Anchor Borrow Usage</p>
        <Switch
          focusVisibleClassName={focusVisible}
          classes={switchClasses}
          checked={liquidationAlert.enabled}
          onChange={({ target }: ChangeEvent<HTMLInputElement>) =>
            updateLiquidationAlert({
              ...liquidationAlert,
              enabled: target.checked,
            })
          }
        />
      </div>

      {liquidationAlert.enabled && (
        <Slider
          classes={sliderClasses}
          valueLabelDisplay="on"
          valueLabelFormat={valueLabelFormat}
          marks={sliderMarks}
          value={liquidationAlert.ratio * 100}
          min={notificationMin}
          max={notificationMax}
          onChange={(_: any, newValue: number) => {
            updateLiquidationAlert({
              ...liquidationAlert,
              ratio: newValue / 100,
            });
          }}
        />
      )}

      {liquidationAlert.enabled && (
        <ActionButton
          className="test-notifications"
          onClick={testNotifications}
        >
          Test Notifications
        </ActionButton>
      )}
    </div>
  );
}
Example #12
Source File: ThresholdsDialog.tsx    From SeeQR with MIT License 5 votes vote down vote up
ThresholdsDialog = ({
  thresholds,
  setThresholds,
  handleClose,
  open,
}: ThresholdsDialogProps) => {
  // Maintain local state with threshold value in order to control sliders without affecting debouncing
  const [durThres, setDurThres] = useState(thresholds.percentDuration);
  const [accThres, setAccThres] = useState(thresholds.percentDuration);

  const handlePercentChange = (_, newVal: number | number[]) => {
    if (Array.isArray(newVal)) return;
    setDurThres(newVal);
    updateThresholds(setThresholds, { ...thresholds, percentDuration: newVal });
  };

  const handleAccuracyChange = (_, newVal: number | number[]) => {
    if (Array.isArray(newVal)) return;
    setAccThres(newVal);
    updateThresholds(setThresholds, { ...thresholds, rowsAccuracy: newVal });
  };

  return (
    <Dialog open={open} onClose={handleClose}>
      <DialogTitle>Thresholds</DialogTitle>
      <DialogContent>
        <DialogContentText>
          Thresholds used to highlight nodes in the tree.
        </DialogContentText>
        <Typography gutterBottom>Percentage of total duration</Typography>
        <Slider
          ValueLabelComponent={ValueLabelComponent}
          aria-label="custom thumb label"
          value={durThres}
          onChange={handlePercentChange}
        />
        <Typography gutterBottom>Planner rows accuracy</Typography>
        <Slider
          ValueLabelComponent={ValueLabelComponent}
          aria-label="custom thumb label"
          value={accThres}
          onChange={handleAccuracyChange}
        />
      </DialogContent>
    </Dialog>
  );
}
Example #13
Source File: settings_button.tsx    From jupyter-extensions with Apache License 2.0 5 votes vote down vote up
render() {
    return (
      <React.Fragment>
        <IconButton
          title="Settings"
          color="inherit"
          onClick={() => this._onClick()}
        >
          <SettingsIcon fontSize="small" />
        </IconButton>

        <Dialog
          open={this.state.open}
          onClose={() => this._onClose()}
          fullWidth
        >
          <DialogTitle>Settings</DialogTitle>
          <DialogContent>
            <Grid container alignItems="center" spacing={2}>
              <Grid item xs={11}>
                <Typography id="input-slider">Sync Frequency</Typography>
              </Grid>
              <Grid item xs={1}>
                <Tooltip title="Time between each sync with remote repository. After each sync, the extension will wait before syncing again.">
                  <HelpOutlineIcon color="disabled" />
                </Tooltip>
              </Grid>
              <Grid item xs={1}>
                <TimerIcon />
              </Grid>
              <Grid item xs={7}>
                <Slider
                  value={
                    typeof this.state.value === 'number'
                      ? this.state.value / (this.maxInterval / 100)
                      : 0
                  }
                  onChange={(event, value) =>
                    this._onSliderChange(event, value)
                  }
                  aria-labelledby="sync-interval-slider"
                />
              </Grid>
              <Grid item xs={4}>
                <Input
                  value={this.state.value}
                  onChange={event => this._onInputChange(event)}
                  onBlur={() => this._onBlur()}
                  margin="dense"
                  inputProps={{
                    step: 1,
                    min: 0,
                    max: this.maxInterval,
                    type: 'number',
                    'aria-labelledby': 'sync-interval-slider',
                  }}
                  endAdornment={
                    <InputAdornment position="end">seconds</InputAdornment>
                  }
                />
              </Grid>
            </Grid>
          </DialogContent>
          <DialogActions>
            <Button onClick={() => this._onClose()} color="primary">
              Cancel
            </Button>
            <Button
              onClick={() => this._onSave()}
              color="primary"
              variant="contained"
            >
              Save
            </Button>
          </DialogActions>
        </Dialog>
      </React.Fragment>
    );
  }
Example #14
Source File: TextSize.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
StyledSlider = withStyles(theme => ({
  root: {
    height: 2,
    padding: '15px 0',
  },
  thumb: {
    height: 18,
    width: 18,
    backgroundColor: theme.palette.common.white,
    boxShadow: boxShadow,
    marginTop: -9,
    marginLeft: -9,
    '&:focus, &:hover, &$active': {
      boxShadow:
        '0 3px 1px rgba(0,0,0,0.1),0 4px 8px rgba(0,0,0,0.3),0 0 0 1px rgba(0,0,0,0.02)',
      // Reset on touch devices, it doesn't add specificity
      '@media (hover: none)': {
        boxShadow: boxShadow,
      },
    },
  },
  active: {},
  valueLabel: {
    top: '100%',
    left: '50%',
    transform: 'scale(1) translate(-50%, -5px) !important',
    '& *': {
      color: theme.palette.common.black,
      fontSize: theme.typography.caption.fontSize,
      background: 'transparent',
    },
  },
  track: {
    height: 2,
  },
  rail: {
    height: 2,
    opacity: 0.5,
  },
  mark: {
    height: 10,
    width: 1,
    marginTop: -4,
  },
  markActive: {
    opacity: 1,
    backgroundColor: 'currentColor',
  },
}))(Slider)
Example #15
Source File: Competitors.tsx    From clearflask with Apache License 2.0 5 votes vote down vote up
UserCountSlider = (props: {
  marks: Array<number>;
  totalUserActiveUserRatio: number;
  markIndex: number;
  markIndexChanged: (index: number) => void;
}) => {
  const classes = useStyles();
  const min = 0;
  const max = props.marks.length - 1;
  const bottom = `${props.markIndex / (max - min) * 100}%`;
  return (
    <div className={classes.sliderOuterContainer}>
      <div className={classes.sliderContainer}>
        <div className={classes.sliderFloatingInfo} style={{ bottom }}>
          <div className={classes.sliderValueHorizontal}>
            <Typography variant='h6' component='div'>{formatNumber(props.marks[props.markIndex])}</Typography>
          </div>
          <div className={classes.sliderValueHorizontal}>
            <Typography variant='caption' component='div'>Total users</Typography>
          </div>
        </div>
        <Slider
          value={props.markIndex}
          min={min}
          step={1}
          orientation='vertical'
          max={max}
          onChange={(e, val) => props.markIndexChanged(val as any as number)}
        />
        <div className={classes.sliderFloatingInfo} style={{ bottom }}>
          <div className={classes.sliderValueHorizontal}>
            <Typography variant='h6' component='div'>{formatNumber(props.marks[props.markIndex] * props.totalUserActiveUserRatio)}</Typography>
          </div>
          <div className={classes.sliderValueHorizontal}>
            <Typography variant='caption' component='div'>Active users *</Typography>
          </div>
        </div>
      </div>
      <div className={classes.sliderDisclaimer}>
        <Typography variant='caption' component='div' color='textSecondary'>*&nbsp;</Typography>
        <Typography variant='caption' component='div' color='textSecondary'>
          For comparison of different definitions of active users across platforms, we estimate {percTotalUsersAreTracked * 100}% of your total users will actively provide you with feedback.
        </Typography>
      </div>
    </div>
  );
}
Example #16
Source File: FundingControl.tsx    From clearflask with Apache License 2.0 4 votes vote down vote up
renderSlider(idea: Client.Idea, credits: Client.Credits, fundAmount: number) {
    const isSliding = this.state.sliderCurrentIdeaId === idea.ideaId;
    const min = 0;
    var max = fundAmount + this.props.balance;
    if (!isSliding) max -= (this.state.sliderFundAmountDiff || 0);
    const value = isSliding ? fundAmount + (this.state.sliderFundAmountDiff || 0) : fundAmount;
    const step = 1;
    const target = this.state.fixedTarget || this.state.maxTarget;
    const widthPerc = (100 * (max) / target)
    const transitionClassName = (this.state.sliderCurrentIdeaId && !this.state.sliderIsSubmitting) ? this.props.classes.sliderTransitionNone : this.props.classes.sliderTransitionSmooth
    const minMaxTitleOpacity = widthPerc > 25 ? 0.1 : 0;

    return (
      <div
        className={this.props.classes.sliderContainer}
      >
        {min === max && (
          <Typography
            className={classNames(this.props.classes.msg, this.props.classes.msgHover)}
            variant='overline'
            component='div'
          >
            You have no balance.&nbsp;
            {!!this.props.credits?.creditPurchase?.redirectUrl && (
              <MuiLink
                className={classNames(this.props.classes.link, this.props.classes.linkGetMore)}
                color='inherit'
                href={this.props.credits.creditPurchase.redirectUrl}
                target='_blank'
                underline='none'
                rel='noopener nofollow'
              >
                {this.props.credits.creditPurchase.buttonTitle || 'Get more'}
              </MuiLink>
            )}
          </Typography>
        )}
        <Slider
          className={classNames(this.props.classes.slider, (min === max) && this.props.classes.sliderHide)}
          style={{ width: widthPerc + '%' }}
          disabled={this.state.sliderIsSubmitting || min === max}
          min={min}
          max={max}
          step={step}
          value={value}
          onChange={(e, val) => {
            const newFundAmount = this.sticky(val as any as number, min, max, target, fundAmount, idea && idea.funded, idea.fundGoal ? idea.fundGoal : undefined);
            const fundAmountDiff = newFundAmount - fundAmount;
            this.setState({
              sliderFundAmountDiff: fundAmountDiff,
              ...(!isSliding ? {
                sliderCurrentIdeaId: idea.ideaId,
                fixedTarget: this.state.maxTarget,
              } : {}),
            });
          }}
          onChangeCommitted={e => {
            const sliderFundAmountDiff = this.state.sliderFundAmountDiff;
            if (sliderFundAmountDiff === undefined || sliderFundAmountDiff === 0) {
              this.setState({
                sliderCurrentIdeaId: undefined,
                fixedTarget: undefined,
                sliderFundAmountDiff: undefined,
              });
              return;
            }
            this.setState({
              sliderIsSubmitting: true,
            });
            this.props.updateVote(idea.ideaId, {
              fundDiff: minmax(-fundAmount, sliderFundAmountDiff, this.props.balance),
            })
              .finally(() => this.setState({
                sliderCurrentIdeaId: undefined,
                fixedTarget: undefined,
                sliderFundAmountDiff: undefined,
                sliderIsSubmitting: false,
              }));
          }}
          classes={{
            thumb: transitionClassName,
            track: transitionClassName,
            root: transitionClassName,
          }}
        />
        <div style={{
          position: 'relative',
        }}>
          <div style={{
            position: 'absolute',
            width: '100%',
            display: 'flex',
            alignItems: 'baseline',
          }}>
            <div style={{ flexGrow: target > 0 ? (value / target) : 0 }}></div>
            <div style={{ flexGrow: 0 }}>
              {(min !== max) && (
                <Typography variant='body1'>
                  <CreditView key='value' val={value} credits={credits} />
                </Typography>
              )}
            </div>
            <div style={{ flexGrow: target > 0 ? (1 - (value / target)) : 0 }}></div>
          </div>
          <div style={{
            position: 'absolute',
            width: '100%',
            display: 'flex',
            alignItems: 'baseline',
          }}>
            <div style={{ flexGrow: max / target }}></div>
            <div style={{ opacity: minMaxTitleOpacity }}>
              <Typography variant='body1'>
                <CreditView key='max' val={max} credits={credits} />
              </Typography>
            </div>
            <div style={{ flexGrow: 1 - (max / target) }}></div>
          </div>
          <div style={{ opacity: minMaxTitleOpacity }}>
            <Typography variant='body1'>
              <CreditView key='min' val={min} credits={credits} />
            </Typography>
          </div>
        </div>
      </div>
    );
  }
Example #17
Source File: useWhiteboardArea.tsx    From flect-chime-sdk-demo with Apache License 2.0 4 votes vote down vote up
useWhiteboardArea = () => {
    const { whiteboardClientState } = useAppState();
    const [_lastUpdateTime, setLastUpdateTime] = useState(0);

    const colorSelects = useMemo(() => {
        return colors.map((c) => {
            const selected = whiteboardClientState.whiteboardClient?.drawingMode === "DRAW" && whiteboardClientState.whiteboardClient.drawingStroke === c;
            return (
                <Tooltip title={c} key={c}>
                    <FiberManualRecord
                        style={{ color: c, border: selected ? "1px solid" : "" }}
                        onClick={() => {
                            if (whiteboardClientState.whiteboardClient) {
                                whiteboardClientState.whiteboardClient.drawingMode = "DRAW";
                                whiteboardClientState.whiteboardClient.drawingStroke = c;
                            }
                            setLastUpdateTime(new Date().getTime());
                        }}
                    />
                </Tooltip>
            );
        });
    }, [whiteboardClientState.whiteboardClient?.drawingMode, whiteboardClientState.whiteboardClient?.drawingStroke]);

    const eraseSelect = useMemo(() => {
        const selected = whiteboardClientState.whiteboardClient?.drawingMode === "ERASE";
        return (
            <Tooltip title="erase">
                <RadioButtonUnchecked
                    style={{ color: "black", border: selected ? "1px solid" : "" }}
                    onClick={() => {
                        if (whiteboardClientState.whiteboardClient) {
                            whiteboardClientState.whiteboardClient.drawingMode = "ERASE";
                        }
                        setLastUpdateTime(new Date().getTime());
                    }}
                />
            </Tooltip>
        );
    }, [whiteboardClientState.whiteboardClient?.drawingMode, whiteboardClientState.whiteboardClient?.drawingStroke]);

    const lineWidthSelect = useMemo(() => {
        return (
            <div style={{ display: "flex" }}>
                linewidth
                <Slider
                    value={whiteboardClientState.whiteboardClient?.lineWidth}
                    onChange={(e, v) => {
                        if (whiteboardClientState.whiteboardClient) {
                            whiteboardClientState.whiteboardClient.lineWidth = Array.isArray(v) ? v[0] : v;
                        }
                        setLastUpdateTime(new Date().getTime());
                    }}
                    min={1}
                    max={20}
                    step={1}
                />
            </div>
        );
    }, [whiteboardClientState.whiteboardClient?.lineWidth]);

    const clearButton = useMemo(() => {
        return (
            <Button
                variant="outlined"
                size="small"
                color="primary"
                onClick={() => {
                    const drawingData: DrawingData = {
                        drawingCmd: "CLEAR",
                        startXR: 0,
                        startYR: 0,
                        endXR: 0,
                        endYR: 0,
                        stroke: "black",
                        lineWidth: 2,
                    };
                    if (whiteboardClientState.whiteboardClient) {
                        whiteboardClientState.whiteboardClient.addDrawingData(drawingData);
                    } else {
                        console.log("[WhiteboardPanel] addDrawingData is undefined");
                    }
                    setLastUpdateTime(new Date().getTime());
                }}
            >
                Clear
            </Button>
        );
    }, []);

    const whiteboardArea = useMemo(() => {
        return (
            <div id="whiteboardArea" style={{ display: "flex", flexDirection: "column", width: "100%", maxHeight: "100%", wordBreak: "break-all", overflow: "auto", background: "#ffffffaa" }}>
                <div>{colorSelects}</div>
                <div>{eraseSelect}</div>
                <div>{lineWidthSelect}</div>
                <div>{clearButton}</div>
            </div>
        );
    }, [colorSelects, eraseSelect, lineWidthSelect, clearButton]);

    return { whiteboardArea };
}
Example #18
Source File: PromptEditor.tsx    From prompts-ai with MIT License 4 votes vote down vote up
export function PromptEditor() {
    const dispatch = useDispatch();
    const styles = useStyles();

    const prompt = useSelector(selectPrompt);
    const temperature = useSelector(selectTemperature);
    const topP = useSelector(selectTopP);
    const frequencyPenalty = useSelector(selectFrequencyPenalty);
    const presencePenalty = useSelector(selectPresencePenalty);
    const maxTokens = useSelector(selectMaxTokens);
    const stopSymbols = useSelector(selectStopSymbols);

    const availableModelNames = ['davinci', 'davinci-instruct-beta',
        'curie', 'curie-instruct-beta',
        'babbage',
        'ada'];
    const modelName = useSelector(selectModelName);

    const handlePromptChange = (event: React.FormEvent<HTMLTextAreaElement | HTMLInputElement>) => {
        dispatch(editPrompt(event.currentTarget.value));
    }
    const handleTemperatureChange = (event: React.ChangeEvent<{}>, value: number | number[]) => {
        dispatch(editTemperature(value as number));
    }
    const handleTopPChange = (event: React.ChangeEvent<{}>, value: number | number[]) => {
        dispatch(editTopP(value as number));
    }
    const handleFrequencyPenaltyChange = (event: React.ChangeEvent<{}>, value: number | number[]) => {
        dispatch(editFrequencyPenalty(value as number));
    }
    const handlePresencePenaltyChange = (event: React.ChangeEvent<{}>, value: number | number[]) => {
        dispatch(editPresencePenalty(value as number));
    }
    const handleMaxTokensChange = (event: React.ChangeEvent<{}>, value: number | number[]) => {
        dispatch(editMaxTokens(value as number));
    }
    const handleModelNameChange = (event: any) => {
        dispatch(editModelName(event.target.value));
    }

    return (
        <div>
            <Grid
                container
                direction="row"
                justify="flex-start"
                alignItems="flex-start"
                spacing={3}
            >
                <Grid item xs={12} sm={3} md={3}>
                    {/*<Box mb={1}>
                        <Card>
                            <CardContent>
                                <Box>
                                    <Grid container>
                                        <Grid item><Button
                                            onClick={() => dispatch(ActionCreators.undo())}
                                        >
                                            Undo
                                        </Button></Grid>
                                        <Grid item>
                                            <Button
                                                aria-label="Undo last change"
                                                onClick={() => dispatch(ActionCreators.redo())}
                                            >
                                                Redo
                                            </Button>
                                        </Grid>
                                        <Grid item>
                                            <Button
                                                aria-label="Save as a file"
                                                onClick={handleSaveAndDownload}
                                            >
                                                Save
                                            </Button>
                                        </Grid>
                                    </Grid>
                                </Box>
                                <hr/>
                                <Box mt={2}>
                                    <Grid container>
                                        <Grid item
                                              className={styles.fullWidth}>
                                            <TextField type="password"
                                                       variant="outlined"
                                                       label="API Key"
                                                       size={'small'}
                                                       value={apiKey}
                                                       onChange={(event: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>) => {
                                                           dispatch(editApiKey(event.currentTarget.value));
                                                       }}
                                                       inputProps={{
                                                           autoComplete: 'new-password',
                                                           form: {
                                                               autoComplete: 'off',
                                                           },
                                                       }}
                                                       className={styles.fullWidth}
                                            />
                                        </Grid>
                                    </Grid>
                                </Box>
                            </CardContent>
                        </Card>
                    </Box>*/}
                    <Box mb={1}>
                        <Card>
                            <CardContent>
                                <Typography gutterBottom>
                                    <strong>Workspace</strong>
                                </Typography>
                                <WorkspaceForm/>
                            </CardContent>
                        </Card>
                    </Box>
                    <Card>
                        <CardContent>
                            <Typography gutterBottom>
                                <strong>Parameters</strong>
                            </Typography>
                            <Tooltip title={'"Controls randomness: Lowering results in less random completions. As the temperature approaches zero, the model will become deterministic and repetitive."'}
                                     placement="left">
                                <Typography id="temperature-slider" gutterBottom>
                                    Temperature: <strong>{temperature}</strong>
                                </Typography>
                            </Tooltip>
                            <Slider
                                defaultValue={0.5}
                                value={temperature}
                                onChange={handleTemperatureChange}
                                aria-labelledby="temperature-slider"
                                valueLabelDisplay="auto"
                                step={0.01}
                                marks={[{
                                    value: 0,
                                    label: '0',
                                }, {
                                    value: 1,
                                    label: '1',
                                }]}
                                min={0}
                                max={1}
                            />
                            <Typography id="max-tokens-slider" gutterBottom>
                                Response length: <strong>{maxTokens}</strong>
                            </Typography>
                            <Slider
                                defaultValue={10}
                                aria-labelledby="max-tokens-slider"
                                valueLabelDisplay="auto"
                                value={maxTokens}
                                onChange={handleMaxTokensChange}
                                step={1}
                                marks={[{
                                    value: 1,
                                    label: '1',
                                }, {
                                    value: 512,
                                    label: '512',
                                }]}
                                min={1}
                                max={512}
                            />

                            <Tooltip title="On which symbols GPT-3 should stop generating text. Enter \n for a line break." placement="left">
                                <Typography gutterBottom>
                                    Stop sequences:
                                </Typography>
                            </Tooltip>
                            <ChipInput
                                value={stopSymbols}
                                onAdd={(chip) => dispatch(addStopSymbol(chip))}
                                onDelete={(deletedChip) => dispatch(deleteStopSymbol(deletedChip))}
                                onBeforeAdd={() => stopSymbols.length !== 4}
                                newChipKeys={['Tab']}
                                className={styles.fullWidth}
                            />
                        </CardContent>

                        <CardContent>
                            <Typography gutterBottom>
                                <strong>Advanced parameters</strong>
                            </Typography>
                            <Tooltip title={'"Controls diversity via nucleus sampling: 0.5 means half of all likelihood-weighted options are considered."'} placement="left">
                                <Typography id="top-p-slider" gutterBottom>
                                    Top P: <strong>{topP}</strong>
                                </Typography>
                            </Tooltip>
                            <Slider
                                defaultValue={0.5}
                                value={topP}
                                onChange={handleTopPChange}
                                aria-labelledby="top-p-slider"
                                valueLabelDisplay="auto"
                                step={0.01}
                                marks={[{
                                    value: 0,
                                    label: '0',
                                }, {
                                    value: 1,
                                    label: '1',
                                }]}
                                min={0}
                                max={1}
                            />
                            <Tooltip title={'"How much to penalize new tokens based on their existing frequency in the text so far. Decreases the model\'s likelihood to repeat the same line verbatim."'} placement="left">
                                <Typography id="frequency-penalty-slider" gutterBottom>
                                    Frequency Penalty: <strong>{frequencyPenalty}</strong>
                                </Typography>
                            </Tooltip>
                            <Slider
                                defaultValue={0.5}
                                value={frequencyPenalty}
                                onChange={handleFrequencyPenaltyChange}
                                aria-labelledby="frequency-penalty-slider"
                                valueLabelDisplay="auto"
                                step={0.01}
                                marks={[{
                                    value: 0,
                                    label: '0',
                                }, {
                                    value: 1,
                                    label: '1',
                                }]}
                                min={0}
                                max={1}
                            />
                            <Tooltip title={'"How much to penalize new tokens based on whether they appear in the text so far. Increases the model\'s likelihood to talk about new topics."'} placement="left">
                                <Typography id="presence-penalty-slider" gutterBottom>
                                    Presence Penalty: <strong>{presencePenalty}</strong>
                                </Typography>
                            </Tooltip>
                            <Slider
                                defaultValue={0.5}
                                value={presencePenalty}
                                onChange={handlePresencePenaltyChange}
                                aria-labelledby="presence-penalty-slider"
                                valueLabelDisplay="auto"
                                step={0.01}
                                marks={[{
                                    value: 0,
                                    label: '0',
                                }, {
                                    value: 1,
                                    label: '1',
                                }]}
                                min={0}
                                max={1}
                            />
                            <Typography id="model-name-typography" gutterBottom>
                                Model name:
                            </Typography>
                            <Select native id="model-name-select" name="modelName" value={modelName} onChange={handleModelNameChange} className={styles.fullWidth}>
                                {availableModelNames.map((modelName, ind) => (
                                    <option key={ind} value={modelName}>{modelName}</option>
                                ))}
                            </Select>
                        </CardContent>
                    </Card>
                </Grid>
                <Grid item xs={12} sm={9} md={9}>
                    <TextField
                        id="prompt-text"
                        label="A prompt"
                        multiline
                        rows={9}
                        rowsMax={100}
                        fullWidth={true}
                        onChange={handlePromptChange}
                        value={prompt}
                        variant="outlined"
                    />
                    <br/>
                    <br/>
                    <ModeTabs/>
                </Grid>

            </Grid>
        </div>
    );
}
Example #19
Source File: index.tsx    From synapse-extension with MIT License 4 votes vote down vote up
InnerForm = (props: any) => {
  const classes = useStyles();
  const intl = useIntl();
  const [contacts, setContacts] = React.useState([]);
  const [checkMsg, setCheckMsg] = React.useState('');
  const [unspentCapacity, setUnspentCapacity] = React.useState(-1);
  const [feeRate, setFeeRate] = React.useState(1000);
  const { values, touched, errors, handleChange, handleBlur, setFieldValue, setFieldError } = props;
  React.useEffect(() => {
    browser.storage.local.get('contacts').then((result) => {
      if (Array.isArray(result.contacts)) {
        setContacts(result.contacts);
      }
    });

    browser.storage.local.get('currentWallet').then(async (result) => {
      const lockHash = result.currentWallet?.lock;
      if (!lockHash) return;
      const unspentCapacityResult = await getUnspentCapacity(lockHash);
      setUnspentCapacity(unspentCapacityResult);
    });
  }, []);

  let errMsg = errors.capacity && touched.capacity && errors.capacity;
  if (errMsg === undefined) {
    if (checkMsg !== '') {
      errMsg = checkMsg;
    }
  }

  const handleBlurCapacity = async (event) => {
    if (errors.address) return;
    setCheckMsg('');
    handleBlur(event);

    const { address, typeHash, udt = 0, decimal } = values;

    // secp256k1
    const capacity = event.target.value;

    let toLockScript;

    try {
      toLockScript = addressToScript(address);
    } catch (error) {
      setFieldError('address', intl.formatMessage({ id: 'Invalid address' }));
      return;
    }
    const toLockType = getLockTypeByCodeHash(toLockScript.codeHash);
    if (!typeHash) {
      if (toLockType === LockType.Secp256k1) {
        // every cell's capacity gt 61
        if (Number(capacity) < Number(61)) {
          const checkMsgId = "The transaction's ckb capacity cannot be less than 61 CKB";
          const checkMsgI18n = intl.formatMessage({ id: checkMsgId });
          setCheckMsg(checkMsgI18n);
          return;
        }
      }
      // check anypay cell's capacity
      if (toLockType === LockType.AnyPay) {
        const toLockHash = scriptToHash(toLockScript);
        const liveCapacity = await getUnspentCapacity(toLockHash);
        if (!liveCapacity && Number(capacity) < Number(61)) {
          const checkMsgId = "The transaction's ckb capacity cannot be less than 61 CKB";
          const checkMsgI18n = intl.formatMessage({ id: checkMsgId });
          setCheckMsg(checkMsgI18n);
          return;
        }
      }

      if (unspentCapacity > 0) {
        if (unspentCapacity < Number(capacity) * CKB_TOKEN_DECIMALS) {
          const checkMsgId = 'lack of capacity, available capacity is';
          const checkMsgI18n = intl.formatMessage({ id: checkMsgId });
          setCheckMsg(` ${checkMsgI18n + shannonToCKBFormatter(unspentCapacity.toString())} CKB`);
          return;
        }
        const chargeCapacity = unspentCapacity - Number(capacity) * CKB_TOKEN_DECIMALS;
        if (chargeCapacity < 61 * CKB_TOKEN_DECIMALS) {
          const checkMsgId =
            'the remaining capacity is less than 61, if continue it will be destroyed, remaining capacity is';
          const checkMsgI18n = intl.formatMessage({ id: checkMsgId });
          setCheckMsg(` ${checkMsgI18n + shannonToCKBFormatter(chargeCapacity.toString())} CKB`);
        }
      }
    } else {
      if (!unspentCapacity) {
        const checkMsgId =
          'lack of capacity, ckb capacity cannot be less than 142 CKB, available capacity is';
        const checkMsgI18n = intl.formatMessage({ id: checkMsgId });
        setCheckMsg(`${checkMsgI18n + shannonToCKBFormatter('0')} CKB`);
      }

      if (ckbToshannon(capacity, decimal) > BigInt(udt)) {
        const checkMsgId = "The transaction's sudt amount cannot be more than have";
        const checkMsgI18n = intl.formatMessage({ id: checkMsgId });
        setCheckMsg(checkMsgI18n);
      }
      if (BigInt(unspentCapacity) < BigInt((SUDT_MIN_CELL_CAPACITY + 1) * CKB_TOKEN_DECIMALS)) {
        const checkMsgId =
          'lack of capacity, ckb capacity cannot be less than 142 CKB, available capacity is';
        const checkMsgI18n = intl.formatMessage({ id: checkMsgId });
        setCheckMsg(` ${checkMsgI18n + shannonToCKBFormatter(unspentCapacity.toString())} CKB`);
      }
    }
  };

  const { name, typeHash } = values;
  let sudtElem;
  let dataElem;
  if (!name && !typeHash) {
    dataElem = (
      <TextField
        size="small"
        label={intl.formatMessage({ id: 'Data' })}
        id="field-data"
        name="data"
        type="text"
        fullWidth
        value={values.data}
        onChange={handleChange}
        error={!!errors.data}
        helperText={errors.data && touched.data && errors.data}
        margin="normal"
        variant="outlined"
      />
    );
  }

  if (name === 'undefined' && typeHash === '') {
    sudtElem = null;
  } else if (name === 'undefined' && typeHash !== '') {
    // sudt show
    sudtElem = (
      <div>
        <ListItem>
          <ListItemText primary="UDT Hash" secondary={truncateHash(typeHash)} />
        </ListItem>
      </div>
    );
  } else if (name !== 'undefined' && typeHash !== '') {
    // sudt show
    sudtElem = (
      <div>
        <ListItem>
          <ListItemText primary="UDT Name" secondary={name} />
        </ListItem>
        <ListItem>
          <ListItemText primary="UDT Hash" secondary={truncateHash(typeHash)} />
        </ListItem>
      </div>
    );
  }

  const handleSliderChangeCommitted = async (event, feeRateValue) => {
    setFeeRate(feeRateValue);
    setFieldValue('feeRate', feeRateValue);
  };

  return (
    <>
      <div>{sudtElem}</div>

      <Autocomplete
        id="address"
        size="small"
        onChange={(event, newValue) => {
          setFieldValue('address', newValue.address);
        }}
        options={contacts}
        getOptionLabel={(option) => option.address}
        renderOption={(option) => (
          <>
            {`${option.name}: `}
            {truncateAddress(option.address)}
          </>
        )}
        freeSolo
        renderInput={(params) => (
          <TextField
            {...params}
            label={intl.formatMessage({ id: 'To' })}
            name="address"
            value={values.address}
            onChange={handleChange}
            margin="normal"
            InputProps={{ ...params.InputProps, type: 'search' }}
            variant="outlined"
            error={!!errors.address}
            helperText={errors.address && touched.address && errors.address}
          />
        )}
        style={{ width: 300 }}
      />
      <TextField
        size="small"
        label={intl.formatMessage({ id: 'Amount' })}
        name="capacity"
        type="text"
        placeholder={`Should be >= ${MIN_TRANSFER_CELL_CAPACITY}`}
        fullWidth
        value={values.capacity}
        onChange={handleChange}
        onBlur={handleBlurCapacity}
        error={!!errors.capacity}
        helperText={errMsg}
        margin="normal"
        variant="outlined"
        id="field-capacity"
      />
      {dataElem}
      <div className={classes.feeRate}>
        <Typography gutterBottom>
          <FormattedMessage id="Fee Rate" />
          <span>:&nbsp;</span>
          <span>{feeRate}</span>
          <span>&nbsp;Shn/KB</span>
        </Typography>

        <Grid container spacing={2}>
          <Grid item>
            <Typography gutterBottom>
              <FormattedMessage id="Slower" />
            </Typography>
          </Grid>
          <Grid item xs>
            <Slider
              name="feeRate"
              valueLabelDisplay="auto"
              step={1000}
              aria-label="feeRate"
              defaultValue={1000}
              min={1000}
              max={5000}
              onChangeCommitted={handleSliderChangeCommitted}
            />
          </Grid>
          <Grid item>
            <Typography gutterBottom>
              <FormattedMessage id="Faster" />
            </Typography>
          </Grid>
        </Grid>
      </div>
      <TextField
        size="small"
        label={intl.formatMessage({ id: 'Password' })}
        name="password"
        type="password"
        fullWidth
        value={values.password}
        onChange={handleChange}
        onBlur={handleBlur}
        error={!!errors.password}
        helperText={errors.password && touched.password && errors.password}
        margin="normal"
        variant="outlined"
        id="field-password"
      />
    </>
  );
}
Example #20
Source File: PricingSlider.tsx    From clearflask with Apache License 2.0 4 votes vote down vote up
render() {
    if (this.props.plans.length === 0) return null;

    const mauIndex = this.state.mauIndex;
    const mauMark = this.state.marks[mauIndex];
    const standardPlan = this.props.plans.slice()
      .reverse()
      .find(p => !!p.pricing)!;
    const price = mauMark.val;
    const min = 0;
    const max = this.state.marks.length - 1;
    const sliderPercentage = `${mauIndex / (max - min) * 100}%`;

    return (
      <PricingPlan
        plan={standardPlan}
        customPrice={(
          <div>
            <div className={this.props.classes.sliderContainer}>
              <div className={classNames(this.props.classes.floating, this.props.classes.info)}
                style={{
                  bottom: sliderPercentage,
                  ...(SliderHangs ? {} : {
                    transform: `translateY(${sliderPercentage})`,
                  }),
                }}>
                <div className={this.props.classes.valueHorizontal}>
                  <Typography component='div' variant='subtitle2' color='textSecondary' style={{ alignSelf: 'flex-start' }}>{'$'}</Typography>
                  <Typography component='div' variant='h4'>{this.formatNumber(price)}</Typography>
                  <Typography component='div' variant='subtitle2' color='textSecondary'>/&nbsp;mo</Typography>
                </div>
                <Typography component='div' variant='subtitle2' color='textSecondary'>Billed annually</Typography>
              </div>
              <Slider
                key='slider'
                className={this.props.classes.slider}
                value={mauIndex}
                min={min}
                step={1}
                orientation='vertical'
                max={max}
                onChange={(e, val) => {
                  this.setState({ mauIndex: (val as any as number) })
                }}
              />
            </div>
          </div>
        )}
        overridePerks={[
          { desc: 'Pay what you can afford' },
        ]}
        actionTitle={this.props.t('get-started') + '*'}
        remark={(
          <div className={this.props.classes.disclaimer}>
            <Typography variant='caption' component='div' color='textSecondary'>*&nbsp;</Typography>
            <Typography variant='caption' component='div' color='textSecondary'>
              Start a trial and we will approve<br />
              your price request shortly by email.
            </Typography>
          </div>
        )}
        actionOnClick={() => {
          trackingBlock(() => {
            ReactGA.event({
              category: 'pricing',
              action: 'click-plan',
              label: standardPlan.basePlanId,
              value: price,
            });
          });
        }}
        actionTo={(SIGNUP_PROD_ENABLED || !isProd())
          ? {
            pathname: '/signup',
            state: {
              [PRE_SELECTED_BASE_PLAN_ID]: standardPlan.basePlanId,
              [PRE_SELECTED_PLAN_PRICE]: price,
            },
          }
          : '/contact/sales'}

      />
    );
  }
Example #21
Source File: index.tsx    From rugenerous-frontend with MIT License 4 votes vote down vote up
function Calculator() {
  const isAppLoading = useSelector<IReduxState, boolean>(state => state.app.loading);
  const marketPrice = useSelector<IReduxState, number>(state => {
    return state.app.marketPrice;
  });
  const stakingAPY = useSelector<IReduxState, number>(state => {
    return state.app.stakingAPY;
  });
  const memoBalance = useSelector<IReduxState, string>(state => {
    return state.account.balances && state.account.balances.srug;
  });

  const trimmedStakingAPY = trim(stakingAPY * 100, 1);
  const trimmedMemoBalance = trim(Number(memoBalance), 6);
  const trimeMarketPrice = trim(marketPrice, 2);

  const [memoAmount, setMemoAmount] = useState(trimmedMemoBalance);
  const [rewardYield, setRewardYield] = useState(trimmedStakingAPY);
  const [priceAtPurchase, setPriceAtPurchase] = useState(trimeMarketPrice);
  const [futureMarketPrice, setFutureMarketPrice] = useState(trimeMarketPrice);
  const [days, setDays] = useState(30);

  const [rewardsEstimation, setRewardsEstimation] = useState("0");
  const [potentialReturn, setPotentialReturn] = useState("0");

  const calcInitialInvestment = () => {
    const srug = Number(memoAmount) || 0;
    const price = parseFloat(priceAtPurchase) || 0;
    const amount = srug * price;
    return trim(amount, 2);
  };

  const calcCurrentWealth = () => {
    const srug = Number(memoAmount) || 0;
    const price = parseFloat(trimeMarketPrice);
    const amount = srug * price;
    return trim(amount, 2);
  };

  const [initialInvestment, setInitialInvestment] = useState(calcInitialInvestment());

  useEffect(() => {
    const newInitialInvestment = calcInitialInvestment();
    setInitialInvestment(newInitialInvestment);
  }, [memoAmount, priceAtPurchase]);

  const calcNewBalance = () => {
    let value = parseFloat(rewardYield) / 100;
    value = Math.pow(value - 1, 1 / (365 * 3)) - 1 || 0;
    let balance = Number(memoAmount);
    for (let i = 0; i < days * 3; i++) {
      balance += balance * value;
    }
    return balance;
  };

  useEffect(() => {
    const newBalance = calcNewBalance();
    setRewardsEstimation(trim(newBalance, 6));
    const newPotentialReturn = newBalance * (parseFloat(futureMarketPrice) || 0);
    setPotentialReturn(trim(newPotentialReturn, 2));
  }, [days, rewardYield, futureMarketPrice, memoAmount]);

  return (
    <div className="calculator-view">
      <Zoom in={true}>
        <div className="calculator-card">
          <Grid className="calculator-card-grid" container direction="column" spacing={2}>
            <Grid item>
              <div className="calculator-card-header">
                <p className="calculator-card-header-title">Super Accurate Calculator</p>
                <p className="calculator-card-header-subtitle">Estimate how much you get rugged...</p>
              </div>
            </Grid>
            <Grid item>
              <div className="calculator-card-metrics">
                <Grid container spacing={2}>
                  <Grid item xs={12} sm={4} md={4} lg={4}>
                    <div className="calculator-card-apy">
                      <p className="calculator-card-metrics-title">RUG Price</p>
                      <p className="calculator-card-metrics-value">
                        {isAppLoading ? <Skeleton width="100px" /> : `$${trimeMarketPrice}`}
                      </p>
                    </div>
                  </Grid>
                  <Grid item xs={6} sm={4} md={4} lg={4}>
                    <div className="calculator-card-tvl">
                      <p className="calculator-card-metrics-title">Current APY</p>
                      <p className="calculator-card-metrics-value">
                        {isAppLoading ? (
                          <Skeleton width="100px" />
                        ) : (
                          <>{new Intl.NumberFormat("en-US").format(Number(trimmedStakingAPY))}%</>
                        )}
                      </p>
                    </div>
                  </Grid>
                  <Grid item xs={6} sm={4} md={4} lg={4}>
                    <div className="calculator-card-index">
                      <p className="calculator-card-metrics-title">Your RUGGED Balance</p>
                      <p className="calculator-card-metrics-value">
                        {isAppLoading ? <Skeleton width="100px" /> : <>{trimmedMemoBalance} RUGGED</>}
                      </p>
                    </div>
                  </Grid>
                </Grid>
              </div>
            </Grid>

            <div className="calculator-card-area">
              <div>
                <div className="calculator-card-action-area">
                  <Grid container spacing={3}>
                    <Grid item xs={12} sm={6}>
                      <div className="calculator-card-action-area-inp-wrap">
                        <p className="calculator-card-action-area-inp-wrap-title">RUGGED Amount</p>
                        <OutlinedInput
                          type="number"
                          placeholder="Amount"
                          className="calculator-card-action-input"
                          value={memoAmount}
                          onChange={e => setMemoAmount(e.target.value)}
                          labelWidth={0}
                          endAdornment={
                            <InputAdornment position="end">
                              <div
                                onClick={() => setMemoAmount(trimmedMemoBalance)}
                                className="stake-card-action-input-btn"
                              >
                                <p>Max</p>
                              </div>
                            </InputAdornment>
                          }
                        />
                      </div>
                    </Grid>
                    <Grid item xs={12} sm={6}>
                      <div className="calculator-card-action-area-inp-wrap">
                        <p className="calculator-card-action-area-inp-wrap-title">APY (%)</p>
                        <OutlinedInput
                          type="number"
                          placeholder="Amount"
                          className="calculator-card-action-input"
                          value={rewardYield}
                          onChange={e => setRewardYield(e.target.value)}
                          labelWidth={0}
                          endAdornment={
                            <InputAdornment position="end">
                              <div
                                onClick={() => setRewardYield(trimmedStakingAPY)}
                                className="stake-card-action-input-btn"
                              >
                                <p>Current</p>
                              </div>
                            </InputAdornment>
                          }
                        />
                      </div>
                    </Grid>
                    <Grid item xs={12} sm={6}>
                      <div className="calculator-card-action-area-inp-wrap">
                        <p className="calculator-card-action-area-inp-wrap-title">RUG price at purchase ($)</p>
                        <OutlinedInput
                          type="number"
                          placeholder="Amount"
                          className="calculator-card-action-input"
                          value={priceAtPurchase}
                          onChange={e => setPriceAtPurchase(e.target.value)}
                          labelWidth={0}
                          endAdornment={
                            <InputAdornment position="end">
                              <div
                                onClick={() => setPriceAtPurchase(trimeMarketPrice)}
                                className="stake-card-action-input-btn"
                              >
                                <p>Current</p>
                              </div>
                            </InputAdornment>
                          }
                        />
                      </div>
                    </Grid>
                    <Grid item xs={12} sm={6}>
                      <div className="calculator-card-action-area-inp-wrap">
                        <p className="calculator-card-action-area-inp-wrap-title">Future RUG market price ($)</p>
                        <OutlinedInput
                          type="number"
                          placeholder="Amount"
                          className="calculator-card-action-input"
                          value={futureMarketPrice}
                          onChange={e => setFutureMarketPrice(e.target.value)}
                          labelWidth={0}
                          endAdornment={
                            <InputAdornment position="end">
                              <div
                                onClick={() => setFutureMarketPrice(trimeMarketPrice)}
                                className="stake-card-action-input-btn"
                              >
                                <p>Current</p>
                              </div>
                            </InputAdornment>
                          }
                        />
                      </div>
                    </Grid>
                  </Grid>
                </div>
                <div className="calculator-days-slider-wrap">
                  <p className="calculator-days-slider-wrap-title">{`${days} day${days > 1 ? "s" : ""}`}</p>
                  <Slider
                    className="calculator-days-slider"
                    min={1}
                    max={365}
                    value={days}
                    onChange={(e, newValue: any) => setDays(newValue)}
                  />
                </div>
                <div className="calculator-user-data">
                  <div className="data-row">
                    <p className="data-row-name">Your initial investment</p>
                    <p className="data-row-value">
                      {isAppLoading ? <Skeleton width="80px" /> : <>${initialInvestment}</>}
                    </p>
                  </div>
                  <div className="data-row">
                    <p className="data-row-name">Current wealth</p>
                    <p className="data-row-value">
                      {isAppLoading ? <Skeleton width="80px" /> : <>${calcCurrentWealth()}</>}
                    </p>
                  </div>
                  <div className="data-row">
                    <p className="data-row-name">RUG rewards estimation</p>
                    <p className="data-row-value">
                      {isAppLoading ? <Skeleton width="80px" /> : <>{rewardsEstimation} RUG</>}
                    </p>
                  </div>
                  <div className="data-row">
                    <p className="data-row-name">Potential return</p>
                    <p className="data-row-value">
                      {isAppLoading ? <Skeleton width="80px" /> : <>${potentialReturn}</>}
                    </p>
                  </div>
                  <div className="data-row">
                    <p className="data-row-name">Potential number of lambos</p>
                    <p className="data-row-value">
                      {isAppLoading ? <Skeleton width="80px" /> : <>{Math.floor(Number(potentialReturn) / 220000)}</>}
                    </p>
                  </div>
                </div>
              </div>
            </div>
          </Grid>
        </div>
      </Zoom>
    </div>
  );
}
Example #22
Source File: index.tsx    From lobis-frontend with MIT License 4 votes vote down vote up
function LobisMeter() {
    const dispatch = useDispatch();
    const { provider, address, connect, chainID, checkWrongNetwork } = useWeb3Context();

    const [view, setView] = useState(0);
    const [quantity, setQuantity] = useState<string>("");
    const [rewardYield, setRewardYield] = useState<string>("");
    const [lobiPrice, setLobiPrice] = useState<string>("");
    const [days, setDays] = useState<number>(30);
    const [futureLobiPrice, setFutureLobiPrice] = useState<string>("");
    const [apy, setApy] = useState<string>("");
    const isAppLoading = useSelector<IReduxState, boolean>(state => state.app.loading);

    const sLobiBalance = useSelector<IReduxState, string>(state => {
        return state.account.balances && state.account.balances.sLobi;
    });

    const stakingRebase = useSelector<IReduxState, number>(state => {
        return state.app.stakingRebase;
    });
    const stakingAPY = useSelector<IReduxState, number>(state => {
        return state.app.stakingAPY;
    });

    const marketPrice = useSelector<IReduxState, number>(state => {
        return state.app.marketPrice;
    });
    const epoch = useSelector<IReduxState, any[]>(state => {
        return state.app.epoch;
    });

    const handleDays = (newValue: number | number[]) => {
        setDays(newValue as number);
    };
    const setMax = () => {
        setQuantity(sLobiBalance);
    };
    const handleAPY = (value: string) => {
        setApy(value);
        const newRewardYield = (Math.pow(Number(value) / 100, 1 / (365 * dailyRebaseAmounts)) - 1) * 100;
        setRewardYield(trim(newRewardYield, 4).toString());
        if (value === "") {
            setRewardYield("");
        }
    };
    const handleRewardYield = (value: string) => {
        setRewardYield(value);
        const newAPY = (Math.pow(1 + Number(value) / 100, 365 * dailyRebaseAmounts) - 1) * 100;
        setApy(trim(newAPY, 4).toString());
        if (value === "") {
            setApy("");
        }
    };
    const setCurrent = (type: string) => {
        switch (type) {
            case "rewardYield":
                setRewardYield(stakingRebasePercentage);
                const newAPY = (Math.pow(1 + Number(stakingRebasePercentage) / 100, 365 * dailyRebaseAmounts) - 1) * 100;
                setApy(trim(newAPY, 4).toString());
                break;
            case "setPrice":
                setLobiPrice(marketPrice.toString());
                break;
            case "futurePrice":
                setFutureLobiPrice(marketPrice.toString());
                break;
        }
    };

    const trimmedSLobiBalance = trim(Number(sLobiBalance), 6);
    const stakingRebasePercentage = trim(stakingRebase * 100, 4);
    const blockSecondLength = 13;
    const rebaseTimeInSeconds = epoch ? epoch[0] * blockSecondLength : 28800;
    const dailyRebaseAmounts = 86400 / rebaseTimeInSeconds;
    const totalReturn = (Math.pow(1 + Number(rewardYield) / 100, days * dailyRebaseAmounts) - 1) * Number(quantity);
    const initialInvestment = parseFloat(lobiPrice) * parseFloat(quantity);
    const potentialReturn = parseFloat(futureLobiPrice) * (totalReturn + Number(quantity)) - initialInvestment;
    const daysUntilTwoTimes = Math.log(2) / Math.log(1 + Number(rewardYield) / 100) / dailyRebaseAmounts;
    const daysUntilFiveTimes = Math.log(5) / Math.log(1 + Number(rewardYield) / 100) / dailyRebaseAmounts;
    const daysUntilTenTimes = Math.log(10) / Math.log(1 + Number(rewardYield) / 100) / dailyRebaseAmounts;
    return (
        <div className="stake-view">
            <Zoom in={true}>
                <div className="stake-card">
                    <Grid className="stake-card-grid" container direction="column" spacing={2}>
                        <Grid item>
                            <div className="stake-card-header">
                                <p className="stake-card-header-title">Calculator</p>
                                <p className="stake-card-header-description">Please fill the inputs to simulate your rewards</p>
                            </div>
                        </Grid>

                        <Grid item>
                            <div className="stake-card-metrics">
                                <Grid container spacing={2}>
                                    <Grid item lg={4} md={4} sm={4} xs={12}>
                                        <div className="stake-card-apy">
                                            <p className="stake-card-metrics-title">{TOKEN_NAME} Price</p>
                                            <p className="stake-card-metrics-value">{isAppLoading ? <Skeleton width="100px" /> : `$${trim(marketPrice, 2)}`}</p>
                                        </div>
                                    </Grid>

                                    <Grid item xs={12} sm={4} md={4} lg={4}>
                                        <div className="stake-card-tvl">
                                            <p className="stake-card-metrics-title">Current Reward Yield</p>
                                            <p className="stake-card-metrics-value">{isAppLoading ? <Skeleton width="80px" /> : <>{stakingRebasePercentage}%</>}</p>
                                        </div>
                                    </Grid>

                                    <Grid item xs={12} sm={4} md={4} lg={4}>
                                        <div className="stake-card-index">
                                            <p className="stake-card-metrics-title">Your {STAKING_TOKEN_NAME} Balance</p>
                                            <p className="stake-card-metrics-value">
                                                {isAppLoading ? (
                                                    <Skeleton width="80px" />
                                                ) : (
                                                    <>
                                                        {trimmedSLobiBalance} {STAKING_TOKEN_NAME}
                                                    </>
                                                )}
                                            </p>
                                        </div>
                                    </Grid>
                                </Grid>
                            </div>
                        </Grid>

                        <div className="stake-card-area">
                            {address && (
                                <div>
                                    <div className="stake-card-action-area">
                                        <div className="stake-card-action-row">
                                            <OutlinedInput
                                                type="number"
                                                placeholder={`${STAKING_TOKEN_NAME} amount`}
                                                className="stake-card-action-input"
                                                value={quantity}
                                                onChange={e => setQuantity(e.target.value)}
                                                labelWidth={0}
                                                endAdornment={
                                                    <InputAdornment position="end">
                                                        <div onClick={setMax} className="stake-card-action-input-btn">
                                                            <p>Max</p>
                                                        </div>
                                                    </InputAdornment>
                                                }
                                            />
                                        </div>
                                        <div className="stake-card-action-row">
                                            <OutlinedInput
                                                type="number"
                                                placeholder={`APY (%)`}
                                                className="stake-card-action-input"
                                                value={apy}
                                                onChange={e => handleAPY(e.target.value)}
                                                labelWidth={0}
                                                endAdornment={<InputAdornment position="end"></InputAdornment>}
                                            />
                                        </div>
                                        <div className="stake-card-action-row">
                                            <OutlinedInput
                                                type="number"
                                                placeholder={`Reward yield each rebase (%)`}
                                                className="stake-card-action-input"
                                                value={rewardYield}
                                                onChange={e => handleRewardYield(e.target.value)}
                                                labelWidth={0}
                                                endAdornment={
                                                    <InputAdornment position="end">
                                                        <div onClick={() => setCurrent("rewardYield")} className="stake-card-action-input-btn">
                                                            <p>Current</p>
                                                        </div>
                                                    </InputAdornment>
                                                }
                                            />
                                        </div>
                                        <div className="stake-card-action-row">
                                            <OutlinedInput
                                                type="number"
                                                placeholder={`${TOKEN_NAME} price at purchase ($) `}
                                                className="stake-card-action-input"
                                                value={lobiPrice}
                                                onChange={e => setLobiPrice(e.target.value)}
                                                labelWidth={0}
                                                endAdornment={
                                                    <InputAdornment position="end">
                                                        <div onClick={() => setCurrent("setPrice")} className="stake-card-action-input-btn">
                                                            <p>Current</p>
                                                        </div>
                                                    </InputAdornment>
                                                }
                                            />
                                        </div>
                                        <div className="stake-card-action-row">
                                            <OutlinedInput
                                                type="number"
                                                placeholder={`Future ${TOKEN_NAME} market price ($)`}
                                                className="stake-card-action-input"
                                                value={futureLobiPrice}
                                                onChange={e => setFutureLobiPrice(e.target.value)}
                                                labelWidth={0}
                                                endAdornment={
                                                    <InputAdornment position="end">
                                                        <div onClick={() => setCurrent("futurePrice")} className="stake-card-action-input-btn">
                                                            <p>Current</p>
                                                        </div>
                                                    </InputAdornment>
                                                }
                                            />
                                        </div>
                                        <div className="stake-card-action-row">
                                            <Slider className="slider" min={1} max={365} onChange={(e, val) => handleDays(val)} value={days} />{" "}
                                            <p className="days-text">
                                                {days} {days === 1 ? "Day" : "Days"}
                                            </p>
                                        </div>
                                    </div>

                                    <div className="stake-user-data">
                                        <div className="data-row">
                                            <p className="data-row-name">Your Initial Investment</p>
                                            <p className="data-row-value">
                                                {isAppLoading ? (
                                                    <Skeleton width="80px" />
                                                ) : (
                                                    <>
                                                        {initialInvestment > 0
                                                            ? new Intl.NumberFormat("en-US", {
                                                                  style: "currency",
                                                                  currency: "USD",
                                                                  maximumFractionDigits: 5,
                                                                  minimumFractionDigits: 0,
                                                              }).format(initialInvestment)
                                                            : new Intl.NumberFormat("en-US", {
                                                                  style: "currency",
                                                                  currency: "USD",
                                                                  maximumFractionDigits: 0,
                                                                  minimumFractionDigits: 0,
                                                              }).format(0)}
                                                    </>
                                                )}
                                            </p>
                                        </div>

                                        {/*<div className="data-row">
                                            <p className="data-row-name">Current Wealth</p>
                                            <p className="data-row-value">
                                                {
                                                    <>
                                                        {marketPrice * parseFloat(trimmedSLobiBalance) > 0
                                                            ? new Intl.NumberFormat("en-US", {
                                                                  style: "currency",
                                                                  currency: "USD",
                                                                  maximumFractionDigits: 5,
                                                                  minimumFractionDigits: 0,
                                                              }).format(marketPrice * parseFloat(trimmedSLobiBalance))
                                                            : new Intl.NumberFormat("en-US", {
                                                                  style: "currency",
                                                                  currency: "USD",
                                                                  maximumFractionDigits: 0,
                                                                  minimumFractionDigits: 0,
                                                              }).format(0)}
                                                    </>
                                                }
                                            </p>
                                            </div>*/}

                                        <div className="data-row">
                                            <p className="data-row-name">{`${TOKEN_NAME} rewards estimation`}</p>
                                            <p className="data-row-value">{totalReturn > 0 ? `${trim(totalReturn, 4)} ${TOKEN_NAME}` : `0 ${TOKEN_NAME}`}</p>
                                        </div>

                                        <div className="data-row">
                                            <p className="data-row-name">Total return</p>
                                            <p className="data-row-value">
                                                {!isNaN(potentialReturn)
                                                    ? new Intl.NumberFormat("en-US", {
                                                          style: "currency",
                                                          currency: "USD",
                                                          maximumFractionDigits: 5,
                                                          minimumFractionDigits: 0,
                                                      }).format(potentialReturn)
                                                    : "--"}
                                            </p>
                                        </div>
                                        {rewardYield !== "" && (
                                            <div style={{ width: "100%" }}>
                                                <Divider style={{ backgroundColor: " rgba(255, 255, 255, 0.2)" }} />
                                            </div>
                                        )}
                                    </div>
                                </div>
                            )}
                            {rewardYield !== "" && (
                                <div className="stake-user-data">
                                    <div className="data-row">
                                        <p className="data-row-name">Amount of days Until...</p>
                                        <p className="data-row-value"></p>
                                    </div>
                                    <div className="data-row">
                                        <p className="data-row-name">2x {STAKING_TOKEN_NAME}</p>
                                        <p className="data-row-value">
                                            {daysUntilTwoTimes.toFixed(1)} {daysUntilTwoTimes > 1 ? "Days" : "Day"}
                                        </p>
                                    </div>
                                    <div className="data-row">
                                        <p className="data-row-name">5x {STAKING_TOKEN_NAME}</p>
                                        <p className="data-row-value">
                                            {daysUntilFiveTimes.toFixed(1)} {daysUntilTwoTimes > 1 ? "Days" : "Day"}
                                        </p>
                                    </div>
                                    <div className="data-row">
                                        <p className="data-row-name">10x {STAKING_TOKEN_NAME}</p>
                                        <p className="data-row-value">
                                            {daysUntilTenTimes.toFixed(1)} {daysUntilTwoTimes > 1 ? "Days" : "Day"}
                                        </p>
                                    </div>
                                </div>
                            )}
                        </div>
                    </Grid>
                </div>
            </Zoom>
        </div>
    );
}
Example #23
Source File: index.tsx    From Lux-Viewer-2021 with Apache License 2.0 4 votes vote down vote up
Controller = ({
  turn,
  isReady,
  handleSliderChange,
  sliderConfigs,
  moveToTurn,
  setRunning,
  playbackSpeed,
  setPlaybackSpeed,
  handleUpload,
  fileInput,
  running,
}: ControllerProps) => {
  const isNightTime = turn % 40 >= 30 && turn !== 0;
  return (
    <div className="Controller">
      <div className="time-of-day">
        <img className="day-icon" src={isNightTime ? MoonSVG : DayTimeSVG} />
      </div>
      <div className="turn-label">
        <span>Turn {turn}</span>
      </div>
      <div className="time-display">
        <Slider
          className="slider"
          value={turn}
          onChange={handleSliderChange}
          aria-labelledby="continuous-slider"
          min={sliderConfigs.min}
          step={sliderConfigs.step}
          max={sliderConfigs.max}
        />
        {/* <div className="nighttime">
              <img className="night-icon" src={NightTimeSVG} />
              <span>Nighttime</span>
            </div> */}
      </div>
      <div className="replay-buttons">
        <IconButton
          aria-label="restart"
          onClick={() => {
            moveToTurn(0);
          }}
        >
          <img src={ReplayButtonSVG} />
        </IconButton>
        <IconButton
          aria-label="leftarrow"
          onClick={() => {
            setPlaybackSpeed(playbackSpeed / 2);
          }}
        >
          <img src={ArrowsSVG} />
        </IconButton>
        <IconButton
          aria-label="pause"
          className="pause-button"
          disabled={!isReady}
          onClick={() => {
            setRunning(!running);
          }}
        >
          <div className="pause-circle-2">
            <div className="pause-circle">
              {running ? (
                <img className="pause-icon" src={PauseButtonSVG} />
              ) : (
                <img className="play-icon" src={PlayButtonSVG} />
              )}
            </div>
          </div>
        </IconButton>
        <IconButton
          aria-label="rightarrow"
          onClick={() => {
            setPlaybackSpeed(playbackSpeed * 2);
          }}
        >
          <img className="right-arrow-icon" src={ArrowsSVG} />
        </IconButton>
        <div className="speed-display">{playbackSpeed}x</div>

        <input
          accept=".json, .luxr"
          type="file"
          style={{ display: 'none' }}
          onChange={handleUpload}
          ref={fileInput}
        />
        {/* <IconButton
          aria-label="upload"
          onClick={() => {
            fileInput.current.click();
          }}
        >
          <img className="upload-icon" src={UploadSVG} />
        </IconButton> */}
      </div>
    </div>
  );
}
Example #24
Source File: TransactionListAmountRangeFilter.tsx    From End-to-End-Web-Testing-with-Cypress with MIT License 4 votes vote down vote up
TransactionListAmountRangeFilter: React.FC<TransactionListAmountRangeFilterProps> = ({
  filterAmountRange,
  amountRangeFilters,
  resetAmountRange,
}) => {
  const classes = useStyles();
  const theme = useTheme();
  const xsBreakpoint = useMediaQuery(theme.breakpoints.only("xs"));

  const initialAmountRange = [0, 100];
  const [amountRangeValue, setAmountRangeValue] = React.useState<number[]>(initialAmountRange);

  const [amountRangeAnchorEl, setAmountRangeAnchorEl] = React.useState<HTMLDivElement | null>(null);

  const handleAmountRangeClick = (event: React.MouseEvent<HTMLDivElement>) => {
    setAmountRangeAnchorEl(event.currentTarget);
  };

  const handleAmountRangeClose = () => {
    setAmountRangeAnchorEl(null);
  };

  const handleAmountRangeChange = (_event: any, amountRange: number | number[]) => {
    filterAmountRange({
      amountMin: padAmountWithZeros(first(amountRange as number[]) as number),
      amountMax: padAmountWithZeros(last(amountRange as number[]) as number),
    });
    setAmountRangeValue(amountRange as number[]);
  };

  const amountRangeOpen = Boolean(amountRangeAnchorEl);
  const amountRangeId = amountRangeOpen ? "amount-range-popover" : undefined;

  const AmountRangeFilter = () => (
    <Grid
      data-test="transaction-list-filter-amount-range"
      container
      direction="column"
      justify="flex-start"
      alignItems="flex-start"
      spacing={1}
      className={classes.amountRangeRoot}
    >
      <Grid item>
        <Grid
          container
          direction="row"
          justify="space-between"
          alignItems="center"
          className={classes.amountRangeTitleRow}
        >
          <Grid item className={classes.amountRangeTitle}>
            <Typography color="textSecondary" data-test="transaction-list-filter-amount-range-text">
              Amount Range: {formatAmountRangeValues(amountRangeValue)}
            </Typography>
          </Grid>
          <Grid item>
            <Button
              data-test="transaction-list-filter-amount-clear-button"
              onClick={() => {
                setAmountRangeValue(initialAmountRange);
                resetAmountRange();
              }}
            >
              Clear
            </Button>
          </Grid>
        </Grid>
      </Grid>
      <Grid item>
        <Slider
          data-test="transaction-list-filter-amount-range-slider"
          className={classes.amountRangeSlider}
          value={amountRangeValue}
          min={0}
          max={100}
          onChange={handleAmountRangeChange}
          valueLabelDisplay="auto"
          aria-labelledby="range-slider"
          getAriaValueText={amountRangeValueText}
          valueLabelFormat={amountRangeValueTextLabel}
        />
      </Grid>
    </Grid>
  );

  return (
    <div>
      <Chip
        color="primary"
        variant="outlined"
        onClick={handleAmountRangeClick}
        data-test="transaction-list-filter-amount-range-button"
        label={`Amount: ${formatAmountRangeValues(amountRangeValue)}`}
        deleteIcon={<ArrowDropDownIcon />}
        onDelete={handleAmountRangeClick}
      />
      {!xsBreakpoint && (
        <Popover
          id={amountRangeId}
          open={amountRangeOpen}
          anchorEl={amountRangeAnchorEl}
          onClose={handleAmountRangeClose}
          anchorOrigin={{
            vertical: "bottom",
            horizontal: "left",
          }}
          transformOrigin={{
            vertical: "top",
            horizontal: "left",
          }}
        >
          <AmountRangeFilter />
        </Popover>
      )}
      {xsBreakpoint && (
        <Drawer
          id={amountRangeId}
          open={amountRangeOpen}
          ModalProps={{ onClose: handleAmountRangeClose }}
          anchor="bottom"
          data-test="amount-range-filter-drawer"
        >
          <Button
            data-test="amount-range-filter-drawer-close"
            onClick={() => handleAmountRangeClose()}
          >
            Close
          </Button>
          <AmountRangeFilter />
        </Drawer>
      )}
    </div>
  );
}
Example #25
Source File: ColoredSlider.tsx    From interface-v2 with GNU General Public License v3.0 4 votes vote down vote up
ColoredSlider = withStyles((theme: Theme) => ({
  root: {
    color: '#5294FF',
    height: 2,
    width: 'calc(100% - 16px)',
    padding: '13px 0',

    '& .MuiSlider-mark': {
      width: 4,
      height: '4px !important',
      bottom: 15,
      borderRadius: 4,
      backgroundColor: 'white',
      '&:hover': {
        '&::after': {
          backgroundColor: theme.palette.background.paper,
          border: `1px solid ${theme.palette.divider}`,
          height: '30px',
          width: '82px',
          borderRadius: '14px',
          bottom: '14px',
          color: theme.palette.text.primary,
          fontFamily: 'DM Sans',
          content: '"Cheaper gas"',
          display: 'flex',
          alignItems: 'center',
          marginLeft: '-50px',
          padding: '0.3em 1em',
          position: 'absolute',
          zIndex: 98,
        },
        '&::before': {
          backgroundColor: theme.palette.background.paper,
          border: `1px solid ${theme.palette.divider}`,
          height: '12px',
          width: '12px',
          bottom: '8px',
          borderBottom: 'transparent',
          borderLeft: 'transparent',
          color: theme.palette.text.primary,
          fontFamily: 'DM Sans',
          content: '""',
          display: 'flex',
          alignItems: 'center',
          marginLeft: '-4px',
          position: 'absolute',
          boxSizing: 'border-box',
          '-webkit-transform': 'rotate(135deg)',
          transform: 'rotate(135deg)',
          zIndex: 99,
        },
      },
    },
  },

  mark: {
    height: 8,
    backgroundColor: '#B4C2D5',
  },

  thumb: {
    height: 20,
    width: 20,
    backgroundColor: theme.palette.primary.main,
    marginTop: -9,
    marginLeft: 0,
    boxShadow: '0px 2px 5px rgba(0, 0, 0, 0.15)',

    '&:focus, &:hover, &$active': {
      boxShadow: 'inherit',
    },
  },

  valueLabel: {
    left: 'calc(-50% - 8px)',
    top: -18,
    fontSize: 12,
    '& > span': {
      color: 'transparent',
    },
    '& > span > span': {
      color: theme.palette.text.primary,
    },
  },

  track: {
    height: 2,
    background: '#4389fd',
    borderRadius: 4,
    paddingRight: 8,
  },

  rail: {
    height: 2,
    borderRadius: 4,
    background: theme.palette.background.paper,
    width: 'calc(100% + 16px)',
  },
}))(Slider)
Example #26
Source File: index.tsx    From wonderland-frontend with MIT License 4 votes vote down vote up
function Calculator() {
    const isAppLoading = useSelector<IReduxState, boolean>(state => state.app.loading);
    const marketPrice = useSelector<IReduxState, number>(state => {
        return state.app.marketPrice;
    });
    const stakingAPY = useSelector<IReduxState, number>(state => {
        return state.app.stakingAPY;
    });
    const memoBalance = useSelector<IReduxState, string>(state => {
        return state.account.balances && state.account.balances.memo;
    });

    const trimmedStakingAPY = trim(stakingAPY * 100, 1);
    const trimmedMemoBalance = trim(Number(memoBalance), 6);
    const trimeMarketPrice = trim(marketPrice, 2);

    const [memoAmount, setMemoAmount] = useState(trimmedMemoBalance);
    const [rewardYield, setRewardYield] = useState(trimmedStakingAPY);
    const [priceAtPurchase, setPriceAtPurchase] = useState(trimeMarketPrice);
    const [futureMarketPrice, setFutureMarketPrice] = useState(trimeMarketPrice);
    const [days, setDays] = useState(30);

    const [rewardsEstimation, setRewardsEstimation] = useState("0");
    const [potentialReturn, setPotentialReturn] = useState("0");

    const calcInitialInvestment = () => {
        const memo = Number(memoAmount) || 0;
        const price = parseFloat(priceAtPurchase) || 0;
        const amount = memo * price;
        return trim(amount, 2);
    };

    const calcCurrentWealth = () => {
        const memo = Number(memoAmount) || 0;
        const price = parseFloat(trimeMarketPrice);
        const amount = memo * price;
        return trim(amount, 2);
    };

    const [initialInvestment, setInitialInvestment] = useState(calcInitialInvestment());

    useEffect(() => {
        const newInitialInvestment = calcInitialInvestment();
        setInitialInvestment(newInitialInvestment);
    }, [memoAmount, priceAtPurchase]);

    const calcNewBalance = () => {
        let value = parseFloat(rewardYield) / 100;
        value = Math.pow(value - 1, 1 / (365 * 3)) - 1 || 0;
        let balance = Number(memoAmount);
        for (let i = 0; i < days * 3; i++) {
            balance += balance * value;
        }
        return balance;
    };

    useEffect(() => {
        const newBalance = calcNewBalance();
        setRewardsEstimation(trim(newBalance, 6));
        const newPotentialReturn = newBalance * (parseFloat(futureMarketPrice) || 0);
        setPotentialReturn(trim(newPotentialReturn, 2));
    }, [days, rewardYield, futureMarketPrice, memoAmount]);

    return (
        <div className="calculator-view">
            <Zoom in={true}>
                <div className="calculator-card">
                    <Grid className="calculator-card-grid" container direction="column" spacing={2}>
                        <Grid item>
                            <div className="calculator-card-header">
                                <p className="calculator-card-header-title">Calculator</p>
                                <p className="calculator-card-header-subtitle">Estimate your returns</p>
                            </div>
                        </Grid>
                        <Grid item>
                            <div className="calculator-card-metrics">
                                <Grid container spacing={2}>
                                    <Grid item xs={12} sm={4} md={4} lg={4}>
                                        <div className="calculator-card-apy">
                                            <p className="calculator-card-metrics-title">TIME Price</p>
                                            <p className="calculator-card-metrics-value">{isAppLoading ? <Skeleton width="100px" /> : `$${trimeMarketPrice}`}</p>
                                        </div>
                                    </Grid>
                                    <Grid item xs={6} sm={4} md={4} lg={4}>
                                        <div className="calculator-card-tvl">
                                            <p className="calculator-card-metrics-title">Current APY</p>
                                            <p className="calculator-card-metrics-value">
                                                {isAppLoading ? <Skeleton width="100px" /> : <>{new Intl.NumberFormat("en-US").format(Number(trimmedStakingAPY))}%</>}
                                            </p>
                                        </div>
                                    </Grid>
                                    <Grid item xs={6} sm={4} md={4} lg={4}>
                                        <div className="calculator-card-index">
                                            <p className="calculator-card-metrics-title">Your MEMO Balance</p>
                                            <p className="calculator-card-metrics-value">{isAppLoading ? <Skeleton width="100px" /> : <>{trimmedMemoBalance} MEMO</>}</p>
                                        </div>
                                    </Grid>
                                </Grid>
                            </div>
                        </Grid>

                        <div className="calculator-card-area">
                            <div>
                                <div className="calculator-card-action-area">
                                    <Grid container spacing={3}>
                                        <Grid item xs={12} sm={6}>
                                            <div className="calculator-card-action-area-inp-wrap">
                                                <p className="calculator-card-action-area-inp-wrap-title">MEMO Amount</p>
                                                <OutlinedInput
                                                    type="number"
                                                    placeholder="Amount"
                                                    className="calculator-card-action-input"
                                                    value={memoAmount}
                                                    onChange={e => setMemoAmount(e.target.value)}
                                                    labelWidth={0}
                                                    endAdornment={
                                                        <InputAdornment position="end">
                                                            <div onClick={() => setMemoAmount(trimmedMemoBalance)} className="stake-card-action-input-btn">
                                                                <p>Max</p>
                                                            </div>
                                                        </InputAdornment>
                                                    }
                                                />
                                            </div>
                                        </Grid>
                                        <Grid item xs={12} sm={6}>
                                            <div className="calculator-card-action-area-inp-wrap">
                                                <p className="calculator-card-action-area-inp-wrap-title">APY (%)</p>
                                                <OutlinedInput
                                                    type="number"
                                                    placeholder="Amount"
                                                    className="calculator-card-action-input"
                                                    value={rewardYield}
                                                    onChange={e => setRewardYield(e.target.value)}
                                                    labelWidth={0}
                                                    endAdornment={
                                                        <InputAdornment position="end">
                                                            <div onClick={() => setRewardYield(trimmedStakingAPY)} className="stake-card-action-input-btn">
                                                                <p>Current</p>
                                                            </div>
                                                        </InputAdornment>
                                                    }
                                                />
                                            </div>
                                        </Grid>
                                        <Grid item xs={12} sm={6}>
                                            <div className="calculator-card-action-area-inp-wrap">
                                                <p className="calculator-card-action-area-inp-wrap-title">TIME price at purchase ($)</p>
                                                <OutlinedInput
                                                    type="number"
                                                    placeholder="Amount"
                                                    className="calculator-card-action-input"
                                                    value={priceAtPurchase}
                                                    onChange={e => setPriceAtPurchase(e.target.value)}
                                                    labelWidth={0}
                                                    endAdornment={
                                                        <InputAdornment position="end">
                                                            <div onClick={() => setPriceAtPurchase(trimeMarketPrice)} className="stake-card-action-input-btn">
                                                                <p>Current</p>
                                                            </div>
                                                        </InputAdornment>
                                                    }
                                                />
                                            </div>
                                        </Grid>
                                        <Grid item xs={12} sm={6}>
                                            <div className="calculator-card-action-area-inp-wrap">
                                                <p className="calculator-card-action-area-inp-wrap-title">Future TIME market price ($)</p>
                                                <OutlinedInput
                                                    type="number"
                                                    placeholder="Amount"
                                                    className="calculator-card-action-input"
                                                    value={futureMarketPrice}
                                                    onChange={e => setFutureMarketPrice(e.target.value)}
                                                    labelWidth={0}
                                                    endAdornment={
                                                        <InputAdornment position="end">
                                                            <div onClick={() => setFutureMarketPrice(trimeMarketPrice)} className="stake-card-action-input-btn">
                                                                <p>Current</p>
                                                            </div>
                                                        </InputAdornment>
                                                    }
                                                />
                                            </div>
                                        </Grid>
                                    </Grid>
                                </div>
                                <div className="calculator-days-slider-wrap">
                                    <p className="calculator-days-slider-wrap-title">{`${days} day${days > 1 ? "s" : ""}`}</p>
                                    <Slider className="calculator-days-slider" min={1} max={365} value={days} onChange={(e, newValue: any) => setDays(newValue)} />
                                </div>
                                <div className="calculator-user-data">
                                    <div className="data-row">
                                        <p className="data-row-name">Your initial investment</p>
                                        <p className="data-row-value">{isAppLoading ? <Skeleton width="80px" /> : <>${initialInvestment}</>}</p>
                                    </div>
                                    <div className="data-row">
                                        <p className="data-row-name">Current wealth</p>
                                        <p className="data-row-value">{isAppLoading ? <Skeleton width="80px" /> : <>${calcCurrentWealth()}</>}</p>
                                    </div>
                                    <div className="data-row">
                                        <p className="data-row-name">TIME rewards estimation</p>
                                        <p className="data-row-value">{isAppLoading ? <Skeleton width="80px" /> : <>{rewardsEstimation} TIME</>}</p>
                                    </div>
                                    <div className="data-row">
                                        <p className="data-row-name">Potential return</p>
                                        <p className="data-row-value">{isAppLoading ? <Skeleton width="80px" /> : <>${potentialReturn}</>}</p>
                                    </div>
                                    <div className="data-row">
                                        <p className="data-row-name">Potential number of lambos</p>
                                        <p className="data-row-value">{isAppLoading ? <Skeleton width="80px" /> : <>{Math.floor(Number(potentialReturn) / 220000)}</>}</p>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </Grid>
                </div>
            </Zoom>
        </div>
    );
}
Example #27
Source File: index.tsx    From prism-frontend with MIT License 4 votes vote down vote up
// Children here is legendText
function LegendItem({
  classes,
  id,
  title,
  legend,
  type,
  opacity: initialOpacity,
  children,
  legendUrl,
  exposure,
  extent,
}: LegendItemProps) {
  const map = useSelector(mapSelector);
  const analysisResult = useSelector(analysisResultSelector);
  const dispatch = useDispatch();

  useEffect(() => {
    // should this be here? Or somewhere more related to analysis?
    if (analysisResult instanceof ExposedPopulationResult) {
      const tableData = convertToTableData(analysisResult);
      dispatch(addTableData(tableData));
    }
  }, [analysisResult, dispatch]);

  const [opacity, setOpacityValue] = useState<number | number[]>(
    initialOpacity || 0,
  );

  const handleChangeOpacity = (
    event: React.ChangeEvent<{}>,
    newValue: number | number[],
  ) => {
    // TODO: temporary solution for opacity adjustment, we hope to edit react-mapbox in the future to support changing props
    // because the whole map will be re-rendered if using state directly
    if (map) {
      const [layerId, opacityType] = ((
        layerType?: LayerType['type'],
      ): [string, string] => {
        switch (layerType) {
          case 'wms':
            return [`layer-${id}`, 'raster-opacity'];
          case 'impact':
          case 'admin_level_data':
            return [`layer-${id}-fill`, 'fill-opacity'];
          case 'point_data':
            return [`layer-${id}-circle`, 'circle-opacity'];
          // analysis layer type is undefined TODO we should try make analysis a layer to remove edge cases like this
          case undefined:
            return ['layer-analysis-fill', 'fill-opacity'];
          default:
            throw new Error('Unknown map layer type');
        }
      })(type);

      map.setPaintProperty(layerId, opacityType, newValue);
      setOpacityValue(newValue);
    }
  };

  const getLegendItemLabel = ({ label, value }: LegendDefinitionItem) => {
    if (typeof label === 'string') {
      return label;
    }
    if (typeof value === 'number') {
      return Math.round(value).toLocaleString('en-US');
    }
    return value;
  };

  return (
    <ListItem disableGutters dense>
      <Paper className={classes.paper}>
        <Grid container direction="column" spacing={1}>
          <Grid item style={{ display: 'flex' }}>
            <Typography style={{ flexGrow: 1 }} variant="h4">
              {title}
            </Typography>
            <LayerContentPreview layerId={id} />
          </Grid>
          <Divider />
          <Grid item className={classes.slider}>
            <Box px={1}>
              <Slider
                value={opacity}
                step={0.01}
                min={0}
                max={1}
                aria-labelledby="opacity-slider"
                onChange={handleChangeOpacity}
              />
            </Box>
          </Grid>

          {legend && (
            <Grid item>
              {legendUrl ? (
                <img src={legendUrl} alt={title} />
              ) : (
                legend.map((item: LegendDefinitionItem) => (
                  <ColorIndicator
                    key={item.value || item.label}
                    value={getLegendItemLabel(item)}
                    color={item.color as string}
                    opacity={opacity as number}
                  />
                ))
              )}
            </Grid>
          )}

          <Divider />

          {children && (
            <Grid item>
              <Typography variant="h5">{children}</Typography>
            </Grid>
          )}

          {exposure && (
            <ExposedPopulationAnalysis
              result={analysisResult as ExposedPopulationResult}
              id={id!}
              extent={extent!}
              exposure={exposure}
            />
          )}
        </Grid>
      </Paper>
    </ListItem>
  );
}
Example #28
Source File: LoadoutEditor.tsx    From project-tauntaun with GNU Lesser General Public License v3.0 4 votes vote down vote up
export function LoadoutEditor(props: LoadoutEditorProps) {
  const { dcsStaticData } = DcsStaticDataStateContainer.useContainer();
  const { setShowLoadoutEditor } = AppStateContainer.useContainer();
  const { mission } = MissionStateContainer.useContainer();

  const { selectedGroupId, selectedUnitId } = React.useContext(ModeContext);

  const { unit } = props;

  const unitData = dcsStaticData.planes[unit.type];
  const weaponsData = dcsStaticData.weapons;
  const flyingUnit = unit as FlyingUnit;

  const getWeaponByClsid = (clsid: string) => {
    return Object.keys(weaponsData)
      .filter(key => weaponsData[key].weapon_id === clsid)
      .map(key => ({ ...weaponsData[key], key: key }))
      .pop();
  };

  const c_EmptyOption = 'empty';
  const getUnitPylons = (): Dictionary<string> => {
    if (!unitData) return {};
    if (!flyingUnit.pylons) return {};

    return Object.entries(flyingUnit.pylons)
      .map(keyValue => {
        const [key, value] = keyValue;
        const weapon = getWeaponByClsid(value.CLSID)?.key;
        console.assert(weapon !== undefined);
        return {
          key: key,
          value: weapon ? weapon : c_EmptyOption
        };
      })
      .reduce((accumulator, currentValue) => ({ ...accumulator, [currentValue.key]: currentValue.value }), {});
  };

  const [pylons, setPylons] = useState(getUnitPylons());
  const [chaff, setChaff] = useState(unitData !== undefined ? flyingUnit.chaff : 0);
  const [flare, setFlare] = useState(unitData !== undefined ? flyingUnit.flare : 0);
  const [fuel, setFuel] = useState(unitData !== undefined ? flyingUnit.fuel : 0);
  const [gun, setGun] = useState(unitData !== undefined ? flyingUnit.gun : 0);

  const group = selectedGroupId ? findGroupById(mission, selectedGroupId) : undefined;
  const isSelectedUnitLeadOfFlight = isLeadOfFlight(selectedUnitId, group);

  const emptyOption = { value: c_EmptyOption, label: 'Empty' };
  let pylonOptions: any[] = [];
  if (unitData) {
    pylonOptions = Object.keys(unitData.pylons).map(key => {
      const pylonData = unitData.pylons[key];
      return {
        pylonNumber: key,
        options: [
          ...pylonData.map(value => {
            return { value: value, label: dcsStaticData.weapons[value].name };
          }),
          emptyOption
        ]
      };
    });
  }

  const onPylonWeaponSelected = (event: any, pylonNumber: number) => {
    const value = event.target.value;

    if (value === c_EmptyOption) {
      const newPylons: any = { ...pylons };
      delete newPylons[pylonNumber];
      setPylons(newPylons);
    } else {
      setPylons({
        ...pylons,
        [pylonNumber]: value
      });
    }
  };

  const chargeLeft = () => {
    const left = unitData.charge_total - chaff * unitData.chaff_charge_size - flare * unitData.flare_charge_size;
    return left < 0 ? 0 : left;
  };

  // eslint-disable-next-line @typescript-eslint/ban-types
  const onChaffChange = (event: object, value: number | number[]) => {
    const maxFreeCharges = chargeLeft();
    let newCharges = ((value as number) - chaff) * unitData.chaff_charge_size;
    if (newCharges > maxFreeCharges) newCharges = maxFreeCharges;
    setChaff(chaff + Math.floor(newCharges / unitData.chaff_charge_size));
  };

  // eslint-disable-next-line @typescript-eslint/ban-types
  const onFlareChange = (event: object, value: number | number[]) => {
    const maxFreeCharges = chargeLeft();
    let newCharges = ((value as number) - flare) * unitData.flare_charge_size;
    if (newCharges > maxFreeCharges) newCharges = maxFreeCharges;
    setFlare(flare + Math.floor(newCharges / unitData.flare_charge_size));
  };

  // eslint-disable-next-line @typescript-eslint/ban-types
  const onGunChange = (event: object, value: number | number[]) => setGun(value as number);

  // eslint-disable-next-line @typescript-eslint/ban-types
  const onFuelChange = (event: object, value: number | number[]) => setFuel(value as number);

  const convertPylonsForGameService = () => {
    const weaponsData = dcsStaticData.weapons;
    return Object.keys(pylons)
      .map(k => {
        return { [k]: weaponsData[pylons[k]].weapon_id };
      })
      .reduce((a, c) => {
        return { ...a, ...c };
      }, {});
  };

  const onSaveClicked = () => {
    console.log('Send new loadout.');
    setShowLoadoutEditor(false);
    gameService.sendUnitLoadoutUpdate(unit, convertPylonsForGameService(), chaff, flare, fuel, gun);
  };

  const onSaveForGroupClicked = () => {
    console.log('Send new loadout for group.');
    setShowLoadoutEditor(false);

    const group = getGroupOfUnit(mission, unit.id);
    const convertedPylons = convertPylonsForGameService();
    group?.units.forEach(u => gameService.sendUnitLoadoutUpdate(u, convertedPylons, chaff, flare, fuel, gun));
  };

  const renderPylonSelect = (pylonOption: any) => {
    const pylonNumber = pylonOption.pylonNumber as number;
    return (
      <div className="Pylon" key={pylonNumber}>
        <InputLabel id={'pylon-select-label-' + pylonNumber}>{pylonNumber}</InputLabel>
        <Select
          style={pylonStyle}
          labelId={'pylon-select-label-' + pylonNumber}
          id={'pylon-select-' + pylonNumber}
          value={pylons[pylonNumber] ? pylons[pylonNumber] : ''}
          onChange={(event: any) => onPylonWeaponSelected(event, pylonNumber)}
        >
          {pylonOption.options.map((v: SelectOptionType, i: number) => (
            <MenuItem key={`pylonOption${i}`} value={v.value}>
              {v.label}
            </MenuItem>
          ))}
        </Select>
      </div>
    );
  };

  const closeOnClick = () => setShowLoadoutEditor(false);

  if (unitData) {
    return (
      <div className="LoadoutEditor">
        <p>Unit type: {unit.type}</p>
        <div className="sliderContainer">
          <div className="singleSlider">
            <span>Chaff</span>
            <Slider
              defaultValue={chaff}
              value={chaff}
              min={0}
              max={unitData.charge_total / unitData.chaff_charge_size}
              valueLabelDisplay="auto"
              onChange={onChaffChange}
              onChangeCommitted={onChaffChange}
            />
          </div>
          <div className="singleSlider">
            <span>Flare</span>
            <Slider
              defaultValue={flare}
              value={flare}
              min={0}
              max={unitData.charge_total / unitData.flare_charge_size}
              valueLabelDisplay="auto"
              onChange={onFlareChange}
              onChangeCommitted={onFlareChange}
            />
          </div>
          <div className="singleSlider">
            <span>Gun</span>
            <Slider
              defaultValue={gun}
              step={1}
              min={0}
              max={100}
              valueLabelDisplay="auto"
              onChangeCommitted={onGunChange}
            />
          </div>
          <div className="singleSlider">
            <span>Fuel</span>
            <Slider
              defaultValue={fuel}
              step={1}
              min={0}
              max={unitData.fuel_max}
              valueLabelDisplay="auto"
              onChangeCommitted={onFuelChange}
            />
          </div>
        </div>
        <div className="pylonContainer">{pylonOptions.map(pylonOption => renderPylonSelect(pylonOption))}</div>
        <div className="buttonContainer">
          <button onClick={onSaveClicked}>Save</button>
          {isSelectedUnitLeadOfFlight && <button onClick={onSaveForGroupClicked}>Save for group</button>}
          <button onClick={closeOnClick}>Close</button>
        </div>
      </div>
    );
  } else {
    return <div>No unit data available for {unit.type}!</div>;
  }
}