@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 |
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 |
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 |
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 |
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 |
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 |
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’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 ”Chat” Button and scroll though to load all the
emotes.{' '}
</li>
<li>
Open the browser console: Browser menu > More Tools > Web
Developer Tools > ”Console” 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 ”Copy emotes” 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 |
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 |
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 |
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 |
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 |
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 |
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>
)
}