@material-ui/core/styles#MuiThemeProvider TypeScript Examples

The following examples show how to use @material-ui/core/styles#MuiThemeProvider. 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: index.tsx    From multisig-react with MIT License 6 votes vote down vote up
Root = (): React.ReactElement => (
  <ThemeProvider theme={styledTheme}>
    <Provider store={store}>
      <MuiThemeProvider theme={theme}>
        <ConnectedRouter history={history}>
          <Sentry.ErrorBoundary fallback={GlobalErrorBoundary}>
            <App>{wrapInSuspense(<AppRoutes />, <Loader />)}</App>
          </Sentry.ErrorBoundary>
        </ConnectedRouter>
      </MuiThemeProvider>
    </Provider>
  </ThemeProvider>
)
Example #2
Source File: index.tsx    From Insomniac-NextJS-boilerplate with MIT License 6 votes vote down vote up
WebApp = ({ Component, pageProps }: AppProps): JSX.Element => {
  const apolloClient = useApollo(pageProps.initialApolloState);

  React.useEffect(() => {
    // Remove the server-side injected CSS.
    const jssStyles = document.querySelector('#jss-server-side');

    if (jssStyles) {
      jssStyles.parentElement?.removeChild(jssStyles);
    }
  }, []);

  return (
    <ApolloProvider client={apolloClient}>
      <ThemeProvider theme={theme}>
        <MuiThemeProvider theme={theme}>
          <Component {...pageProps} />
        </MuiThemeProvider>
      </ThemeProvider>
    </ApolloProvider>
  );
}
Example #3
Source File: preview.tsx    From SQForm with MIT License 5 votes vote down vote up
withTheme = (storyFn: () => ThemeProviderProps['children']) => {
  return (
    <StylesProvider injectFirst>
      <LocalizationProvider dateAdapter={MomentAdapter} locale={'en'}>
        <MuiThemeProvider theme={muiTheme}>{storyFn()}</MuiThemeProvider>
      </LocalizationProvider>
    </StylesProvider>
  );
}
Example #4
Source File: Preferences.tsx    From Oratio with MIT License 5 votes vote down vote up
export default function Preferences() {
  const classes = useStyles();
  const { t } = useTranslation();
  return (
    <MuiThemeProvider theme={theme}>
      <div className={classes.root}>
        <div className={classes.content}>
          <form noValidate autoComplete="off">
            <Grid container direction="row" spacing={3}>
              <Grid item xs={6}>
                <AudioSelector />
              </Grid>
              <Grid item xs={6}>
                <VolumeSlider />
              </Grid>
              <Grid item xs={6}>
                <TextSpeedSlider />
              </Grid>
              <Grid item xs={6}>
                <FontSizeSlider />
              </Grid>
              <Grid item xs={6}>
                <FontBoldSlider />
              </Grid>
              <Grid item xs={6}>
                <LanguageSelector />
              </Grid>
              <Grid item xs={12}>
                <Link to="/emotes" className={classes.link}>
                  <Button
                    id="open-preferences"
                    variant="contained"
                    className={classes.button}
                    color="primary"
                  >
                    <InsertEmoticonIcon className={classes.emoteIcon} />
                    {t('Manage Emotes')}
                  </Button>
                </Link>
              </Grid>
              <Grid item xs={6}>
                <FontColorPicker />
              </Grid>
              <Grid item xs={6}>
                <BubbleBackgroundColorPicker />
              </Grid>
            </Grid>
            <Grid
              container
              direction="row"
              spacing={3}
              className={classes.bottomButtons}
            >
              <Grid item xs={4}>
                <Link to="/home" className={classes.link}>
                  <Button
                    id="open-preferences"
                    variant="contained"
                    className={classes.button}
                    color="primary"
                  >
                    {t('Back')}
                  </Button>
                </Link>
              </Grid>
            </Grid>
          </form>
        </div>
      </div>
    </MuiThemeProvider>
  );
}
Example #5
Source File: index.tsx    From Insomniac-NextJS-boilerplate with MIT License 5 votes vote down vote up
Providers: React.FunctionComponent = ({ children }) => {
  return (
    <ThemeProvider theme={theme}>
      <MuiThemeProvider theme={theme}>{children}</MuiThemeProvider>
    </ThemeProvider>
  );
}
Example #6
Source File: Emotes.tsx    From Oratio with MIT License 4 votes vote down vote up
export default function Emotes() {
  const classes = useStyles();
  const { t } = useTranslation();

  function openEmoteDirectory() {
    openExplorer(assetLoc);
  }

  if (!asyncLoadingFinished) {
    reloadEmotes();
  }

  const [, updateState] = React.useState<Record<string, never>>();
  const forceUpdate = React.useCallback(() => updateState({}), []);
  function reloadEmotesAndUpdate() {
    reloadEmotes();
    forceUpdate();
  }

  const [copyButtonTitle, setCopyButtonTitle] = React.useState<string>(
    t('Copy Code')
  );
  function copyEmoteScrapeScript() {
    navigator.clipboard.writeText(emoteScrapeScript);
    setCopyButtonTitle(t('Code Copied!'));
  }

  const [importState, setImportState] = React.useState<string>('');
  async function importEmotesFromClipboard() {
    try {
      setImportState('import started');
      const emoteGroups = JSON.parse(await navigator.clipboard.readText());
      const promises = await fetchEmotes(emoteGroups);
      if (promises.length === 0) {
        setImportState(
          'Did you forget step 3? JSON loaded but no emotes found.'
        );
        return;
      }
      let numFinished = 0;
      const progressUpdate = (message: string) => {
        setImportState(`[${numFinished}/${promises.length}] ${message}`);
      };
      progressUpdate('Started downloads...');
      await Promise.all(
        promises.map((p) =>
          p.then((filePathWithExtension: string) => {
            numFinished += 1;
            progressUpdate(filePathWithExtension);
            return null;
          })
        )
      );
      progressUpdate('Done!');
    } catch (err) {
      setImportState(`error: ${err}`);
      throw err;
    }
    reloadEmotesAndUpdate();
  }

  const element = (
    <MuiThemeProvider theme={theme}>
      <div className={classes.root}>
        <div className={classes.content}>
          <h2>Emote Tools</h2>

          <Button
            id="open-emote-directory"
            variant="contained"
            className={classes.button}
            color="primary"
            onClick={openEmoteDirectory}
          >
            {t('Open Emote Directory')}
          </Button>
          <Button
            id="reload-emotes"
            variant="contained"
            className={classes.button}
            color="primary"
            onClick={reloadEmotesAndUpdate}
          >
            {t('Reload emotes')}
          </Button>

          <h2>Importing emotes</h2>
          <div>
            You can import/manage emotes manually using the buttons above and
            placing images into that directory.
          </div>
          <div>
            To import existing Twitch/BTTV/FFZ emotes you can do the following:
            <ol>
              <li>
                Install BTTV in your browser if you haven&rsquo;t already.
              </li>
              <li> Open your twitch channel page with chat. </li>
              <li>
                {' '}
                Open the BTTV emote panel by clicking the button to the left of
                the &rdquo;Chat&rdquo; Button and scroll though to load all the
                emotes.{' '}
              </li>
              <li>
                Open the browser console: Browser menu &gt; More Tools &gt; Web
                Developer Tools &gt; &rdquo;Console&rdquo; tab
              </li>
              <li>
                Note that pasting code into the browser console is not normal
                and you should trust or verify the script. See{' '}
                <a
                  href="https://en.wikipedia.org/wiki/Self-XSS"
                  target="_blank"
                  rel="noreferrer"
                >
                  Self-XSS
                </a>{' '}
                for more info.
              </li>
              <li>
                Click this button to copy the script:
                <Button
                  id="script-copy"
                  variant="contained"
                  className={classes.button}
                  color="primary"
                  onClick={copyEmoteScrapeScript}
                >
                  {copyButtonTitle}
                </Button>
              </li>
              <li>
                If you trust the script, paste it in the console and hit enter.
              </li>
              <li>
                A &rdquo;Copy emotes&rdquo; button should have appeared on your
                twitch stream. Click it to copy a JSON string containing the
                emote data.
              </li>
              <li>
                Click this button to import the emotes:
                <Button
                  id="open-preferences"
                  variant="contained"
                  className={classes.button}
                  color="primary"
                  onClick={importEmotesFromClipboard}
                >
                  {t('Import Emotes')}
                </Button>
                <span>{importState}</span>
              </li>
            </ol>
          </div>

          <h2>Emote Previews</h2>
          <table>
            <tbody>
              {Object.keys(emoteNameToUrl)
                .sort()
                .map((name: string) => (
                  <tr key={name}>
                    <td>{name}</td>
                    <td>
                      <Emote emoteName={name} />
                    </td>
                  </tr>
                ))}
            </tbody>
          </table>
          <Grid
            container
            direction="row"
            spacing={3}
            className={classes.bottomButtons}
          >
            <Grid item xs={4}>
              <Link to="/preferences" className={classes.link}>
                <Button
                  id="open-preferences"
                  variant="contained"
                  className={classes.button}
                  color="primary"
                >
                  {t('Back')}
                </Button>
              </Link>
            </Grid>
          </Grid>
        </div>
      </div>
    </MuiThemeProvider>
  );
  return element;
}
Example #7
Source File: Home.tsx    From Oratio with MIT License 4 votes vote down vote up
export default function Home() {
  const classes = useStyles();
  const { t } = useTranslation();
  const socket = io(
    `http://localhost:${localStorage.getItem('serverPort') || '4563'}`
  );

  useEffect(() => {
    return () => {
      socket.disconnect();
    };
  });

  const textHistory: string[] = [];
  let textHistoryPos: number = textHistory.length;

  const addToHistory = (text: string) => {
    if (textHistory[textHistory.length - 1] !== text) {
      textHistory.push(text);
      if (textHistory.length >= 100) {
        textHistory.shift();
      }
      textHistoryPos = textHistory.length;
    }
  };

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const handleSpeechSendClicked = async (event: any) => {
    event.preventDefault();
    const { speech } = event.currentTarget.elements;
    if (speech.value.trim() === '') return;
    socket.emit('phraseSend', {
      phrase: speech.value,
      settings: {
        speed: parseInt(localStorage.getItem('textSpeed') || '75', 10),
        fontSize: parseInt(localStorage.getItem('fontSize') || '48', 10),
        fontColor: localStorage.getItem('fontColor') || '#ffffff',
        fontWeight: parseInt(localStorage.getItem('fontWeight') || '400', 10),
        soundFileName: localStorage.getItem('soundFileName'),
        volume: parseFloat(localStorage.getItem('volume') || '50') / 100,
        bubbleColor: localStorage.getItem('bubbleColor') || '#000',
        emoteNameToUrl: JSON.parse(
          localStorage.getItem('emoteNameToUrl') || ''
        ),
      },
    });
    if (win !== undefined) {
      win.webContents.send('speech', speech.value);
    }

    addToHistory(speech.value);
    speech.value = '';
  };

  // Tab-complete
  let tabCompleteStart = 0;
  let tabCompletePrefixLow = '';
  let tabCompleteOptions: string[] = [];
  let tabCompleteOptionIndex = 0;
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  async function handleTextBoxKeypress(event: any) {
    // Autocomplete
    if (event.key === 'Tab') {
      event.preventDefault(); // do not go to the next element.\
      const textField = event.target;
      const text = textField.value;
      const { selectionStart } = textField;
      const words = [...text.matchAll(/\w+/g)].filter(
        (word) => word.index < selectionStart
      );
      if (!words.length) {
        // console.log('northing to autocomplete');
        return;
      }

      const word = words[words.length - 1];
      const prefixLow = word[0].toLowerCase();
      if (
        // Is this a different tab-complete than before?
        !(
          word.index === tabCompleteStart &&
          tabCompletePrefixLow.length &&
          prefixLow.startsWith(tabCompletePrefixLow)
        )
      ) {
        tabCompleteStart = word.index;
        tabCompletePrefixLow = prefixLow;
        tabCompleteOptions = Object.entries(lowercaseToEmoteName)
          .filter(([emoteLow]) => emoteLow.startsWith(prefixLow))
          .map(([, emoteName]) => `${emoteName} `);
        if (tabCompleteOptions.length === 0) {
          // no prefix match found. try substring matching.
          tabCompleteOptions = Object.entries(lowercaseToEmoteName)
            .filter(([emoteLow]) => emoteLow.indexOf(prefixLow) !== -1)
            .map(([, emoteName]) => `${emoteName} `);
        }
        tabCompleteOptions.sort();
        tabCompleteOptionIndex = 0;
      } else {
        const optionCount = tabCompleteOptions.length;
        tabCompleteOptionIndex =
          (tabCompleteOptionIndex + (event.shiftKey ? -1 : 1) + optionCount) %
          optionCount;
      }

      if (tabCompleteOptions.length === 0) {
        // console.log('no matching autocomplete options for: ', prefixLow);
        return;
      }

      const option = tabCompleteOptions[tabCompleteOptionIndex];
      tabCompletePrefixLow = option.toLowerCase().slice(0, option.length - 1);
      textField.value =
        text.slice(0, tabCompleteStart) + option + text.slice(selectionStart);
      textField.selectionStart = tabCompleteStart + option.length;
    }

    if (event.key === 'ArrowUp') {
      event.preventDefault(); // do not go to the next element.
      if (textHistoryPos > 0) {
        textHistoryPos -= 1;
      }
      event.target.value = textHistory[textHistoryPos] || '';
    }

    if (event.key === 'ArrowDown') {
      event.preventDefault(); // do not go to the next element.

      if (textHistoryPos <= textHistory.length - 1) {
        textHistoryPos += 1;
      }
      event.target.value = textHistory[textHistoryPos] || '';
    }
  }

  return (
    <MuiThemeProvider theme={theme}>
      <div className={classes.root}>
        <div className={classes.content}>
          <form
            noValidate
            autoComplete="off"
            onSubmit={handleSpeechSendClicked}
          >
            <Grid container direction="row" spacing={3}>
              <Grid item xs={12}>
                <TextField
                  name="speech"
                  id="speech-input"
                  label={t('Speech')}
                  variant="outlined"
                  onKeyDown={handleTextBoxKeypress}
                  fullWidth
                  autoFocus
                />
              </Grid>
              <Grid container item xs={12} justify-content="flex-end">
                <Button
                  id="send-text"
                  variant="contained"
                  color="primary"
                  className={classes.button}
                  type="submit"
                  // disabled
                >
                  {t('Send')} <SendIcon className={classes.buttonIcon} />
                </Button>
              </Grid>
            </Grid>
          </form>
          <div>
            <div className={classes.hello}>
              <MicOffIcon className={classes.icon} />
            </div>
            <h1 className={classes.header}>Project Oratio</h1>
            <Grid
              container
              spacing={3}
              alignContent="flex-end"
              justify-content="flex-end"
              className={classes.bottomButtons}
            >
              {/* <Grid container item justify-content="flex-end" xs={12}> */}
              <div className={classes.browserSource}>
                Browser source running at:{' '}
                <a
                  href="http://localhost:4563"
                  target="_blank"
                  rel="noreferrer"
                >
                  http://localhost:4563
                </a>
              </div>
              <Link to="/preferences" className={classes.link}>
                <Button
                  id="open-preferences"
                  variant="outlined"
                  color="secondary"
                  className={`${classes.button} ${classes.preferences}`}
                >
                  <SettingsIcon className={classes.buttonIcon} />{' '}
                  {t('Preferences')}
                </Button>
              </Link>

              <Button
                id="open-obs"
                variant="contained"
                color="primary"
                className={classes.button}
                onClick={handleOpenObs}
              >
                {t('Open OBS Display')}
              </Button>
              {/* </Grid> */}
            </Grid>
          </div>
        </div>
      </div>
    </MuiThemeProvider>
  );
}
Example #8
Source File: Main.tsx    From clearflask with Apache License 2.0 4 votes vote down vote up
render() {
    const Router = (windowIso.isSsr ? StaticRouter : BrowserRouter) as React.ElementType;

    // Redirect www to homepage
    if (windowIso.location.hostname.startsWith('www.')) {
      return (<RedirectIso to={windowIso.location.origin.replace(`www.`, '')} />);
    }

    const isSelfHost = detectEnv() === Environment.PRODUCTION_SELF_HOST;
    const isParentDomain = windowIso.location.hostname === windowIso.parentDomain
      || (!isProd() && windowIso.location.hostname === 'localhost');

    const showSite = isParentDomain && !isSelfHost;
    const showProject = !showSite;
    const showDashboard = isParentDomain || isSelfHost;

    if (showSite || showDashboard) {
      trackingImplicitConsent();
    }

    return (
      <ErrorBoundary showDialog>
        <React.StrictMode>
          <I18nextProvider i18n={this.props.i18n}>
            <StylesProvider injectFirst>
              <MuiThemeProvider theme={this.theme}>
                <MuiSnackbarProvider notistackRef={notistackRef}>
                  <CssBaseline />
                  <ServerErrorNotifier />
                  <CaptchaChallenger />
                  <RemoveSsrCss />
                  <CrowdInInlineEditing />
                  <div style={{
                    minHeight: windowIso.isSsr ? undefined : this.theme.vh(100),
                    display: 'flex',
                    flexDirection: 'column',
                    background: this.theme.palette.background.default,
                  }}>
                    <Router
                      {...(windowIso.isSsr ? {
                        location: this.props.ssrLocation,
                        context: this.props.ssrStaticRouterContext,
                      } : {})}
                    >
                      <ScrollAnchor scrollOnNavigate />
                      <Route path='/' render={routeProps => {
                        trackingBlock(() => {
                          ReactGA.set({ page: routeProps.location.pathname + routeProps.location.search });
                          ReactGA.pageview(routeProps.location.pathname + routeProps.location.search);
                        });
                        return null;
                      }} />
                      <Route render={routeProps => routeProps.location.pathname.startsWith('/embed-status') ? null : (
                        <EnvironmentNotifier key='env-notifier' />
                      )} />
                      <Switch>
                        {[
                          (
                            <Route key='api-docs' path='/api' render={props => (
                              <NoSsr>
                                <ApiDocs />
                              </NoSsr>
                            )} />
                          ),
                          ...(!isProd() ? [(
                            <Route key='mock-oauth-provider-bathtub' path='/bathtub/authorize' render={props => (
                              <Provider store={ServerAdmin.get().getStore()}>
                                <BathtubOauthProvider />
                              </Provider>
                            )} />
                          )] : []),
                          ...(showDashboard ? [(
                            <Route key='dashboard' path="/dashboard/:path?/:subPath*" render={props => (
                              <Provider store={ServerAdmin.get().getStore()}>
                                <SentryIdentifyAccount />
                                <SetMaxAge val={0 /* If you want to cache, don't cache if auth is present in URL */} />
                                <NoSsr>
                                  <Dashboard {...props} />
                                </NoSsr>
                                <IntercomWrapperMain suppressBind />
                                <HotjarWrapperMain />
                              </Provider>
                            )} />
                          ), (
                            <Route key='invoice' path="/invoice/:invoiceId" render={props => (
                              <Provider store={ServerAdmin.get().getStore()}>
                                <SentryIdentifyAccount />
                                <SetMaxAge val={0} />
                                <Invoice invoiceId={props.match.params['invoiceId']} />
                              </Provider>
                            )} />
                          ), (
                            <Route key='enter' exact path='/:type(login|signup|invitation|coupon)/:id([a-z0-9]*)?' render={props => (
                              <Provider store={ServerAdmin.get().getStore()}>
                                <SetMaxAge val={0} />
                                <SetTitle title={props.match.params['type'] === 'login'
                                  ? 'Login'
                                  : (props.match.params['type'] === 'signup'
                                    ? 'Sign up'
                                    : (props.match.params['type'] === 'invitation'
                                      ? 'Invitation'
                                      : 'Coupon'))} />
                                <AccountEnterPage
                                  type={props.match.params['type']}
                                  invitationId={props.match.params['type'] === 'invitation' ? props.match.params['id'] : undefined}
                                  couponId={props.match.params['type'] === 'coupon' ? props.match.params['id'] : undefined}
                                />
                              </Provider>
                            )} />
                          )] : []),
                          ...(showProject ? [(
                            <Route key='embed-status' path="/embed-status/post/:postId" render={props => (
                              <>
                                <SetMaxAge val={24 * 60 * 60} />
                                <PostStatus
                                  {...props}
                                  postId={props.match.params['postId'] || ''}
                                />
                              </>
                            )} />
                          ), (
                            <Route key='app' path='/' render={props => (
                              <>
                                <SetMaxAge val={60} />
                                <App slug={windowIso.location.hostname} {...props} />
                              </>
                            )} />
                          )] : []),
                          ...(showSite ? [(
                            <Route key='site' path='/' render={props => (
                              <Provider store={ServerAdmin.get().getStore()}>
                                <SentryIdentifyAccount />
                                <SetMaxAge val={24 * 60 * 60} />
                                <Site {...props} />
                                <IntercomWrapperMain />
                                <HotjarWrapperMain />
                              </Provider>
                            )} />
                          )] : []),
                        ]}
                      </Switch>
                    </Router>
                  </div>
                </MuiSnackbarProvider>
              </MuiThemeProvider>
            </StylesProvider>
          </I18nextProvider>
        </React.StrictMode>
      </ErrorBoundary>
    );
  }
Example #9
Source File: AppThemeProvider.tsx    From clearflask with Apache License 2.0 4 votes vote down vote up
render() {
    var expressionGrayscale: number | undefined = undefined;
    switch (this.props.config && this.props.config.style.palette.expressionColor) {
      case Client.PaletteExpressionColorEnum.Gray:
        expressionGrayscale = 100;
        break;
      case Client.PaletteExpressionColorEnum.Washed:
        expressionGrayscale = 50;
        break;
    }
    var breakpoints;
    if (this.props.forceBreakpoint) {
      breakpoints = {};
      var bpSeen;
      ['xs', 'sm', 'md', 'lg', 'xl'].forEach(bp => {
        breakpoints[bp] = !bpSeen ? 0 : 10000;
        if (!bpSeen && bp === this.props.forceBreakpoint) {
          bpSeen = true;
        };
      })
    }
    var theme: Theme | undefined;
    if (this.props.config) {
      theme = createMuiTheme({
        disableTransitions: !this.props.config.style.animation.enableTransitions,
        funding: this.props.config.style.palette.funding
          || this.props.config.style.palette.primary,
        // Optional green color
        // || ( this.props.config.style.palette.darkMode ? '#6ca869' : '#89c586' ),
        isInsideContainer: !!this.props.isInsideContainer,
        expressionGrayscale: expressionGrayscale,
        explorerExpandTimeout: 500,
        vh,
        palette: {
          type: this.props.config.style.palette.darkMode ? 'dark' : 'light',
          primary: {
            main: this.props.config.style.palette.primary
              || (this.props.config.style.palette.darkMode ? '#2dbaa1' : '#218774'),
          },
          secondary: {
            main: this.props.config.style.palette.primary
              || (this.props.config.style.palette.darkMode ? '#2dbaa1' : '#218774'),
          },
          ...(this.props.config.style.palette.text ? {
            text: {
              primary: this.props.config.style.palette.text,
            }
          } : {}),
          background: {
            ...(this.props.config.style.palette.background ? { default: this.props.config.style.palette.background } : {}),
            ...(this.props.config.style.palette.backgroundPaper ? { paper: this.props.config.style.palette.backgroundPaper } : {}),
          },
        },
        typography: {
          // TODO sanitize input, currently you can inject custom css with "; inject: me"
          /* If changed, change in index.html, Main.tsx */
          fontFamily: this.props.config.style.typography.fontFamily || '"Inter", -apple-system-body, BlinkMacSystemFont, SFUI, HelveticaNeue, Helvetica, Arial, sans-serif',
          fontSize: this.props.config.style.typography.fontSize || 14,
        },
        transitions: {
          ...(this.props.config.style.animation.enableTransitions ? {} : {
            create: () => 'none',
            duration: {
              shortest: 0,
              shorter: 0,
              short: 0,
              standard: 0,
              complex: 0,
              enteringScreen: 0,
              leavingScreen: 0,
            },
          }),
        },
        breakpoints: {
          ...(breakpoints ? {
            values: breakpoints,
          } : {}),
        },
        props: {
          ...ComponentPropsOverrides,
          MuiDialog: {
            ...(!windowIso.isSsr ? {
              container: () => document.getElementById(this.props.appRootId)!,
            } : {}),
            ...(this.props.isInsideContainer ? {
              style: { position: 'absolute' },
              BackdropProps: { style: { position: 'absolute' } },
            } : {}),
          },
          MuiButtonBase: {
            ...(!this.props.config.style.animation.enableTransitions ? {
              disableRipple: true,
            } : {}),
          },
        },
      })
    } else {
      theme = createMuiTheme();
    }

    return (
      <StylesProvider injectFirst>
        <MuiThemeProvider theme={theme}>
          {!this.props.supressCssBaseline && (<CssBaseline />)}
          <div style={{
            height: '100%',
            ...(this.props.containerStyle?.(theme) || {}),
            background: theme.palette.background.default,
            color: theme.palette.text.primary,
          }}>
            {this.props.children}
          </div>
        </MuiThemeProvider>
      </StylesProvider>
    );
  }
Example #10
Source File: index.tsx    From multisig-react with MIT License 4 votes vote down vote up
MethodsDropdown = ({ onChange }: MethodsDropdownProps): React.ReactElement | null => {
  const classes = useDropdownStyles({ buttonWidth: MENU_WIDTH })
  const {
    input: { value: abi },
    meta: { valid },
  } = useField('abi', { subscription: { value: true, valid: true } })
  const {
    initialValues: { selectedMethod: selectedMethodByDefault },
  } = useFormState({ subscription: { initialValues: true } })
  const [selectedMethod, setSelectedMethod] = React.useState(selectedMethodByDefault ? selectedMethodByDefault : {})
  const [methodsList, setMethodsList] = React.useState<AbiItemExtended[]>([])
  const [methodsListFiltered, setMethodsListFiltered] = React.useState<AbiItemExtended[]>([])
  const [anchorEl, setAnchorEl] = React.useState(null)
  const [searchParams, setSearchParams] = React.useState('')

  React.useEffect(() => {
    if (abi) {
      try {
        setMethodsList(extractUsefulMethods(JSON.parse(abi)))
      } catch (e) {
        setMethodsList([])
      }
    }
  }, [abi])

  React.useEffect(() => {
    setMethodsListFiltered(methodsList.filter(({ name }) => name?.toLowerCase().includes(searchParams.toLowerCase())))
  }, [methodsList, searchParams])

  const handleClick = (event) => {
    setAnchorEl(event.currentTarget)
  }

  const handleClose = () => {
    setAnchorEl(null)
  }

  const onMethodSelectedChanged = (chosenMethod: AbiItem) => {
    setSelectedMethod(chosenMethod)
    onChange(chosenMethod)
    handleClose()
  }

  return !valid || !abi || abi === NO_CONTRACT ? null : (
    <Row margin="sm">
      <Col>
        <MuiThemeProvider theme={DropdownListTheme}>
          <>
            <button className={classes.button} onClick={handleClick} type="button">
              <span className={classNames(classes.buttonInner, anchorEl && classes.openMenuButton)}>
                {(selectedMethod as Record<string, string>).name}
              </span>
            </button>
            <Menu
              anchorEl={anchorEl}
              anchorOrigin={{
                horizontal: 'center',
                vertical: 'bottom',
              }}
              elevation={0}
              getContentAnchorEl={null}
              id="customizedMenu"
              keepMounted
              onClose={handleClose}
              open={!!anchorEl}
              PaperProps={{ style: { width: MENU_WIDTH } }}
              transformOrigin={{
                horizontal: 'center',
                vertical: 'top',
              }}
            >
              <MenuItem className={classes.listItemSearch} key="0">
                <div className={classes.search}>
                  <div className={classes.searchIcon}>
                    <SearchIcon />
                  </div>
                  <InputBase
                    classes={{
                      root: classes.inputRoot,
                      input: classes.inputInput,
                    }}
                    inputProps={{ 'aria-label': 'search' }}
                    onChange={(event) => setSearchParams(event.target.value)}
                    placeholder="Search…"
                    value={searchParams}
                  />
                </div>
              </MenuItem>
              <div className={classes.dropdownItemsScrollWrapper}>
                {methodsListFiltered.map((method) => {
                  const { action, name, signatureHash } = method

                  return (
                    <MenuItem
                      className={classes.listItem}
                      key={signatureHash}
                      onClick={() => onMethodSelectedChanged(method)}
                      value={signatureHash}
                    >
                      <ListItemText primary={name} />
                      <ListItemIcon className={classes.iconRight}>
                        {signatureHash === (selectedMethod as Record<string, string>).signatureHash ? (
                          <img alt="checked" src={CheckIcon} />
                        ) : (
                          <span />
                        )}
                      </ListItemIcon>
                      <ListItemIcon className={classes.iconRight}>
                        <div>{action}</div>
                      </ListItemIcon>
                    </MenuItem>
                  )
                })}
              </div>
            </Menu>
          </>
        </MuiThemeProvider>
      </Col>
    </Row>
  )
}
Example #11
Source File: index.tsx    From multisig-react with MIT License 4 votes vote down vote up
MethodsDropdown = ({ onChange }: MethodsDropdownProps): React.ReactElement | null => {
  const classes = useDropdownStyles({ buttonWidth: MENU_WIDTH })
  const {
    input: { value: abi },
    meta: { valid },
  } = useField('abi', { subscription: { value: true, valid: true } })
  const {
    initialValues: { selectedMethod: selectedMethodByDefault },
  } = useFormState({ subscription: { initialValues: true } })
  const [selectedMethod, setSelectedMethod] = React.useState(selectedMethodByDefault ? selectedMethodByDefault : {})
  const [methodsList, setMethodsList] = React.useState<AbiItemExtended[]>([])
  const [methodsListFiltered, setMethodsListFiltered] = React.useState<AbiItemExtended[]>([])
  const [anchorEl, setAnchorEl] = React.useState(null)
  const [searchParams, setSearchParams] = React.useState('')

  React.useEffect(() => {
    if (abi) {
      try {
        setMethodsList(extractUsefulMethods(JSON.parse(abi)))
      } catch (e) {
        setMethodsList([])
      }
    }
  }, [abi])

  React.useEffect(() => {
    setMethodsListFiltered(methodsList.filter(({ name }) => name?.toLowerCase().includes(searchParams.toLowerCase())))
  }, [methodsList, searchParams])

  const handleClick = (event) => {
    setAnchorEl(event.currentTarget)
  }

  const handleClose = () => {
    setAnchorEl(null)
  }

  const onMethodSelectedChanged = (chosenMethod: AbiItem) => {
    setSelectedMethod(chosenMethod)
    onChange(chosenMethod)
    handleClose()
  }

  return !valid || !abi || abi === NO_CONTRACT ? null : (
    <Row margin="sm">
      <Col>
        <MuiThemeProvider theme={DropdownListTheme}>
          <>
            <button
              className={classes.button}
              onClick={handleClick}
              type="button"
              style={{ height: '42px', padding: '8px 0 8px 0' }}
            >
              <span className={classNames(classes.buttonInner, anchorEl && classes.openMenuButton)}>
                {(selectedMethod as Record<string, string>).name}
              </span>
            </button>
            <Menu
              anchorEl={anchorEl}
              anchorOrigin={{
                horizontal: 'center',
                vertical: 'bottom',
              }}
              elevation={0}
              getContentAnchorEl={null}
              id="customizedMenu"
              keepMounted
              onClose={handleClose}
              open={!!anchorEl}
              PaperProps={{ style: { width: MENU_WIDTH } }}
              transformOrigin={{
                horizontal: 'center',
                vertical: 'top',
              }}
            >
              <MenuItem className={classes.listItemSearch} key="0">
                <div className={classes.search}>
                  <div className={classes.searchIcon}>
                    <SearchIcon />
                  </div>
                  <InputBase
                    classes={{
                      root: classes.inputRoot,
                      input: classes.inputInput,
                    }}
                    inputProps={{ 'aria-label': 'search' }}
                    onChange={(event) => setSearchParams(event.target.value)}
                    placeholder="Search…"
                    value={searchParams}
                  />
                </div>
              </MenuItem>
              <div className={classes.dropdownItemsScrollWrapper}>
                {methodsListFiltered.map((method) => {
                  const { action, name, signatureHash } = method

                  return (
                    <MenuItem
                      className={classes.listItem}
                      key={signatureHash}
                      onClick={() => onMethodSelectedChanged(method)}
                      value={signatureHash}
                    >
                      <ListItemText primary={name} />
                      <ListItemIcon className={classes.iconRight}>
                        {signatureHash === (selectedMethod as Record<string, string>).signatureHash ? (
                          <img alt="checked" src={CheckIcon} />
                        ) : (
                          <span />
                        )}
                      </ListItemIcon>
                      <ListItemIcon className={classes.iconRight}>
                        <div>{action}</div>
                      </ListItemIcon>
                    </MenuItem>
                  )
                })}
              </div>
            </Menu>
          </>
        </MuiThemeProvider>
      </Col>
    </Row>
  )
}
Example #12
Source File: index.tsx    From multisig-react with MIT License 4 votes vote down vote up
CurrencyDropdown = (): React.ReactElement | null => {
  const safeAddress = useSelector(safeParamAddressFromStateSelector) as string
  const dispatch = useDispatch()
  const [anchorEl, setAnchorEl] = useState(null)
  const selectedCurrency = useSelector(currentCurrencySelector)
  const [searchParams, setSearchParams] = useState('')

  const currenciesList = Object.values(AVAILABLE_CURRENCIES)
  const tokenImage = nativeCoin.logoUri
  const classes = useDropdownStyles({})
  const currenciesListFiltered = currenciesList.filter((currency) =>
    currency.toLowerCase().includes(searchParams.toLowerCase()),
  )

  const handleClick = (event) => {
    setAnchorEl(event.currentTarget)
  }

  const handleClose = () => {
    setAnchorEl(null)
  }

  const onCurrentCurrencyChangedHandler = (newCurrencySelectedName) => {
    dispatch(setSelectedCurrency(safeAddress, newCurrencySelectedName))
    handleClose()
  }

  if (!selectedCurrency) {
    return null
  }

  return (
    <MuiThemeProvider theme={DropdownListTheme}>
      <>
        <button className={classes.button} onClick={handleClick} type="button">
          <span className={classNames(classes.buttonInner, anchorEl && classes.openMenuButton)}>
            {selectedCurrency}
          </span>
        </button>
        <Menu
          anchorEl={anchorEl}
          anchorOrigin={{
            horizontal: 'center',
            vertical: 'bottom',
          }}
          elevation={0}
          getContentAnchorEl={null}
          id="customizedMenu"
          keepMounted
          onClose={handleClose}
          open={Boolean(anchorEl)}
          transformOrigin={{
            horizontal: 'center',
            vertical: 'top',
          }}
        >
          <MenuItem className={classes.listItemSearch} key="0">
            <div className={classes.search}>
              <div className={classes.searchIcon}>
                <SearchIcon />
              </div>
              <InputBase
                classes={{
                  root: classes.inputRoot,
                  input: classes.inputInput,
                }}
                inputProps={{ 'aria-label': 'search' }}
                onChange={(event) => setSearchParams(event.target.value)}
                placeholder="Search…"
                value={searchParams}
              />
            </div>
          </MenuItem>
          <div className={classes.dropdownItemsScrollWrapper}>
            {currenciesListFiltered.map((currencyName) => (
              <MenuItem
                className={classes.listItem}
                key={currencyName}
                onClick={() => onCurrentCurrencyChangedHandler(currencyName)}
                value={currencyName}
              >
                <ListItemIcon className={classes.iconLeft}>
                  {sameString(currencyName, nativeCoin.symbol) ? (
                    <Img
                      alt={nativeCoin.symbol.toLocaleLowerCase()}
                      onError={setImageToPlaceholder}
                      src={tokenImage}
                      className={classNames(classes.etherFlag)}
                    />
                  ) : (
                    <div
                      className={classNames(
                        classes.localFlag,
                        'currency-flag',
                        'currency-flag-lg',
                        `currency-flag-${currencyName.toLowerCase()}`,
                      )}
                    />
                  )}
                </ListItemIcon>
                <ListItemText primary={currencyName} />
                {currencyName === selectedCurrency ? (
                  <ListItemIcon className={classes.iconRight}>
                    <img alt="checked" src={CheckIcon} />
                  </ListItemIcon>
                ) : null}
              </MenuItem>
            ))}
          </div>
        </Menu>
      </>
    </MuiThemeProvider>
  )
}