@mui/material#ToggleButtonGroup TypeScript Examples
The following examples show how to use
@mui/material#ToggleButtonGroup.
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: SolidToggleButtonGroup.tsx From genshin-optimizer with MIT License | 6 votes |
SolidToggleButtonGroup = styled(ToggleButtonGroup, {
shouldForwardProp: (prop) => prop !== "baseColor" && prop !== "selectedColor"
})<SolidToggleButtonGroupPropsPartial>(({ theme, baseColor = "secondary", selectedColor = "success" }) => ({
'& .MuiToggleButtonGroup-grouped': {
'&': {
backgroundColor: theme.palette[baseColor].main,
color: theme.palette[baseColor].contrastText,
},
'&:hover': {
backgroundColor: theme.palette[baseColor].dark,
transition: "background-color 0.25s ease",
},
'&.Mui-selected': {
backgroundColor: theme.palette[selectedColor].main,
color: theme.palette[selectedColor].contrastText,
},
'&.Mui-selected:hover': {
backgroundColor: theme.palette[selectedColor].dark,
},
'&.Mui-disabled': {
backgroundColor: theme.palette[baseColor].dark,
},
'&.Mui-selected.Mui-disabled': {
backgroundColor: theme.palette[selectedColor].dark,
},
},
}))
Example #2
Source File: HorizontalAlign.tsx From mui-toolpad with MIT License | 6 votes |
function HorizontalAlignPropEditor({
label,
value = 'start',
onChange,
disabled,
}: EditorProps<string>) {
const handleHorizontalAlign = (
event: React.MouseEvent<HTMLElement>,
newHorizontalAlign: string | null,
) => {
if (newHorizontalAlign) {
onChange(newHorizontalAlign);
}
};
return (
<Box>
<Typography>{label}:</Typography>
<ToggleButtonGroup
exclusive
disabled={disabled}
value={value}
onChange={handleHorizontalAlign}
aria-label="HorizontalAlign"
>
<ToggleButton value="start" aria-label="start">
<AlignHorizontalLeftIcon />
</ToggleButton>
<ToggleButton value="center" aria-label="center">
<AlignHorizontalCenterIcon />
</ToggleButton>
<ToggleButton value="end" aria-label="end">
<AlignHorizontalRightIcon />
</ToggleButton>
</ToggleButtonGroup>
</Box>
);
}
Example #3
Source File: VerticalAlign.tsx From mui-toolpad with MIT License | 6 votes |
function VerticalAlignPropEditor({
label,
value = 'start',
onChange,
disabled,
}: EditorProps<string>) {
const VerticalAlign = (event: React.MouseEvent<HTMLElement>, newVerticalAlign: string | null) => {
if (newVerticalAlign) {
onChange(newVerticalAlign);
}
};
return (
<Box>
<Typography>{label}:</Typography>
<ToggleButtonGroup
exclusive
disabled={disabled}
value={value}
onChange={VerticalAlign}
aria-label="VerticalAlign"
>
<ToggleButton value="start" aria-label="start">
<AlignverticalTopIcon />
</ToggleButton>
<ToggleButton value="center" aria-label="center">
<AlignVerticalCenterIcon />
</ToggleButton>
<ToggleButton value="end" aria-label="end">
<AlignVerticalBottomIcon />
</ToggleButton>
</ToggleButtonGroup>
</Box>
);
}
Example #4
Source File: ElementToggle.tsx From genshin-optimizer with MIT License | 5 votes |
export default function ElementToggle({ value, onChange, ...props }: ElementToggleProps) {
const cb = useCallback((e, newVal) => onChange(newVal || ""), [onChange])
return <ToggleButtonGroup exclusive onChange={cb} value={value || allElements} {...props}>
{allElements.map(ele => <SolidColoredToggleButton key={ele} value={ele} selectedColor={ele} >
<Box sx={{ fontSize: "2em", lineHeight: 1 }}>{uncoloredEleIcons[ele]}</Box>
</SolidColoredToggleButton>)}
</ToggleButtonGroup>
}
Example #5
Source File: ThemeEditor.tsx From mui-toolpad with MIT License | 5 votes |
export default function ComponentEditor({ className }: ComponentEditorProps) {
const dom = useDom();
const domApi = useDomApi();
const app = appDom.getApp(dom);
const { themes = [] } = appDom.getChildNodes(dom, app);
const theme = themes.length > 0 ? themes[0] : null;
const handleAddThemeClick = () => {
const newTheme = appDom.createNode(dom, 'theme', {
name: 'Theme',
theme: {},
attributes: {},
});
domApi.addNode(newTheme, app, 'themes');
};
return (
<div className={className}>
{theme ? (
<Stack spacing={2}>
<ToggleButtonGroup
size="small"
exclusive
value={appDom.fromConstPropValue(theme.theme['palette.mode']) || 'light'}
onChange={(event, newValue) => {
domApi.setNodeNamespacedProp(theme, 'theme', 'palette.mode', {
type: 'const',
value: newValue,
});
}}
aria-label="Mode"
>
<IconToggleButton value="light" aria-label="light">
<LightModeIcon />
Light
</IconToggleButton>
<IconToggleButton value="dark" aria-label="dark">
<DarkModeIcon />
Dark
</IconToggleButton>
</ToggleButtonGroup>
<PaletteColorPicker
name="primary"
value={appDom.fromConstPropValue(theme.theme['palette.primary.main']) || ''}
onChange={(newValue) => {
domApi.setNodeNamespacedProp(theme, 'theme', 'palette.primary.main', {
type: 'const',
value: newValue,
});
}}
/>
<PaletteColorPicker
name="secondary"
value={appDom.fromConstPropValue(theme.theme['palette.secondary.main']) || ''}
onChange={(newValue) =>
domApi.setNodeNamespacedProp(theme, 'theme', 'palette.secondary.main', {
type: 'const',
value: newValue,
})
}
/>
</Stack>
) : (
<Button onClick={handleAddThemeClick}>Add theme</Button>
)}
</div>
);
}
Example #6
Source File: SettingsDrawer.tsx From GTAV-NativeDB with MIT License | 4 votes |
export default function SettingsDrawer({ open, onClose }: SettingsDrawerProps) {
const smallDisplay = useIsSmallDisplay()
const settings = useSettings()
const dispatch = useDispatch()
const handleThemeChanged = useCallback((e: ReactMouseEvent<HTMLElement, MouseEvent>, value: any) => {
if (value !== null) {
dispatch(setTheme(value))
}
}, [dispatch])
const handleSourcesChanged = useCallback((e: ReactMouseEvent<HTMLElement, MouseEvent>, value: any) => {
dispatch(setSources(value))
}, [dispatch])
return (
<Drawer
anchor={smallDisplay ? 'bottom' : 'right' }
open={open}
onClose={onClose}
>
<Box
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
width: smallDisplay ? undefined : 400,
p: 2
}}
>
<Typography
variant="h5"
>
Settings
</Typography>
<IconButton aria-label="close settings" onClick={onClose}>
<CloseIcon fontSize="medium" />
</IconButton>
</Box>
<Divider variant="fullWidth" />
<Box sx={{ p: 2 }}>
<Stack spacing={2}>
<div>
<Typography variant="body1" gutterBottom>
Theme
</Typography>
<ToggleButtonGroup
color="primary"
value={settings.theme}
onChange={handleThemeChanged}
exclusive
fullWidth
>
<ToggleButton value="light">
<LightIcon sx={{ mr: 1 }} />
Light
</ToggleButton>
<ToggleButton value="system">
<SystemIcon sx={{ mr: 1 }} />
System
</ToggleButton>
<ToggleButton value="dark">
<DarkIcon sx={{ mr: 1 }} />
Dark
</ToggleButton>
</ToggleButtonGroup>
</div>
<div>
<Typography variant="body1" gutterBottom>
Sources
</Typography>
<ToggleButtonGroup
color="primary"
value={settings.sources}
onChange={handleSourcesChanged}
fullWidth
>
<ToggleButton value="alloc8or" disabled>
Alloc8or
</ToggleButton>
<ToggleButton value="dottiedot">
DottieDot
</ToggleButton>
<ToggleButton value="fivem">
FiveM
</ToggleButton>
</ToggleButtonGroup>
</div>
</Stack>
</Box>
</Drawer>
)
}
Example #7
Source File: Config.tsx From NekoMaid with MIT License | 4 votes |
configs.push({
title: lang.config.serverConfig,
component () {
const plugin = usePlugin()
const globalData = useGlobalData()
const [flag, update] = useState(0)
const [info, setInfo] = useState<Record<string, string>>({ })
const [open, setOpen] = useState(false)
const [canGetData, setCanGetData] = useState(true)
const [loading, setLoading] = useState(false)
const setValue = (field: string, value: any, isGlobal = true) => {
plugin.emit('server:set', field, value)
success()
if (isGlobal) {
(globalData as any)[field] = value
update(flag + 1)
location.reload()
}
}
const createEditButtom = (field: string, isGlobal?: boolean, isInt = true) => <IconButton
onClick={() => dialog(
{
content: lang.inputValue,
input: isInt
? {
error: true,
type: 'number',
helperText: lang.invalidValue,
validator: (it: string) => /^\d+$/.test(it) && +it >= 0
}
: { }
}).then(res => res != null && setValue(field, isInt ? parseInt(res as any) : (res || null), isGlobal))}
><Edit /></IconButton>
const infoElm: JSX.Element[] = []
for (const key in info) {
const name = (lang.config as any)[key]
infoElm.push(<ListItem key={key} sx={{ pl: 4 }}>
<ListItemText
primary={key === 'isAikarFlags' ? <Link href='https://mcflags.emc.gs' target='_blank' rel='noopener'>{name}</Link> : name}
secondary={info[key].toString()}
/>
</ListItem>)
}
return <List>
<CircularLoading loading={loading} />
<ListItem secondaryAction={globalData.canSetMaxPlayers
? createEditButtom('maxPlayers')
: undefined}>
<ListItemText primary={lang.config.maxPlayers + ': ' + globalData.maxPlayers} />
</ListItem>
<ListItem secondaryAction={createEditButtom('spawnRadius')}>
<ListItemText primary={lang.config.spawnRadius + ': ' + globalData.spawnRadius} />
</ListItem>
<ListItem secondaryAction={createEditButtom('motd', false, false)}>
<ListItemText primary={lang.config.motd} />
</ListItem>
<ListItem secondaryAction={<Switch checked={globalData.hasWhitelist} onChange={e => setValue('hasWhitelist', e.target.checked)} />}>
<ListItemText primary={lang.config.whitelist} />
</ListItem>
{canGetData && <>
<ListItemButton onClick={() => {
if (infoElm.length) setOpen(!open)
else {
setLoading(true)
plugin.emit('server:fetchInfo', (data: any) => {
setLoading(false)
if (!data) {
failed(lang.unsupported)
setCanGetData(false)
return
}
setInfo(data)
setOpen(true)
})
}
}}>
<ListItemIcon><Equalizer /></ListItemIcon>
<ListItemText primary={lang.info} />
{open ? <ExpandLess /> : <ExpandMore />}
</ListItemButton>
<Collapse in={open} timeout='auto' unmountOnExit>
<List component='div' dense disablePadding>{infoElm}</List>
</Collapse>
</>}
</List>
}
},
{
title: lang.history,
component () {
const [cur, update] = useState(0)
const list: ServerRecord[] = JSON.parse(localStorage.getItem('NekoMaid:servers') || '[]')
return <List>
{list.sort((a, b) => b.time - a.time).map(it => {
const i = it.address.indexOf('?')
return <ListItem
disablePadding
key={it.address}
secondaryAction={<IconButton edge='end' size='small' onClick={() => {
localStorage.setItem('NekoMaid:servers', JSON.stringify(list.filter(s => s.address !== it.address)))
success()
update(cur + 1)
}}><Delete /></IconButton>}
>
<ListItemButton onClick={() => {
location.hash = ''
location.search = it.address
}} dense>
<ListItemAvatar><Avatar src={it.icon} variant='rounded'><HelpOutline /></Avatar></ListItemAvatar>
<ListItemText primary={<Tooltip title={it.address.slice(i + 1)}>
<span>{it.address.slice(0, i)}</span></Tooltip>} secondary={dayjs(it.time).fromNow()} />
</ListItemButton>
</ListItem>
})}
</List>
}
},
{
title: lang.config.theme,
component () {
const color = localStorage.getItem('NekoMaid:color') || 'blue'
return <CardContent sx={{ textAlign: 'center' }}>
<Box>
<ToggleButtonGroup exclusive value={localStorage.getItem('NekoMaid:colorMode') || ''} onChange={(_, it) => {
localStorage.setItem('NekoMaid:colorMode', it)
location.reload()
}}>
<ToggleButton value='light'><Brightness7 /> {lang.config.light}</ToggleButton>
<ToggleButton value=''><SettingsBrightness /> {lang.config.system}</ToggleButton>
<ToggleButton value='dark'><Brightness4 /> {lang.config.dark}</ToggleButton>
</ToggleButtonGroup>
</Box>
<Paper sx={{ marginTop: 2, width: '176px', overflow: 'hidden', display: 'inline-block' }}>
{Object.keys(colors).slice(1, 17).map((key, i) => {
const checked = color === key
const elm = <Box
key={key}
onClick={() => {
localStorage.setItem('NekoMaid:color', key)
location.reload()
}}
sx={{
backgroundColor: (colors as any)[key][600],
width: '44px',
height: '44px',
display: 'inline-block',
cursor: 'pointer'
}}
><Check htmlColor='white' sx={{ top: '10px', position: 'relative', opacity: checked ? 1 : 0 }} /></Box>
return (i + 1) % 4 === 0 ? <React.Fragment key={key}>{elm}<br /></React.Fragment> : elm
})}
</Paper>
</CardContent>
}
})
Example #8
Source File: PlayerList.tsx From NekoMaid with MIT License | 4 votes |
Players: React.FC = () => {
const his = useHistory()
const plugin = usePlugin()
const [page, setPage] = useState(0)
const [loading, setLoading] = useState(true)
const [state, setState] = useState<number | null>(null)
const [activedPlayer, setActivedPlayer] = useState<PlayerData | null>(null)
const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement | null>(null)
const [data, setData] = useState<{ count: number, players: PlayerData[] }>(() => ({ count: 0, players: [] }))
const globalData = useGlobalData()
const { hasWhitelist } = globalData
const refresh = () => {
setLoading(true)
plugin.emit('playerList:fetchPage', (it: any) => {
if (it.players == null) it.players = []
setData(it)
setLoading(false)
}, page, state === 1 || state === 2 ? state : 0, null)
}
useMemo(refresh, [page, state])
const close = () => {
setAnchorEl(null)
setActivedPlayer(null)
}
return <Card>
<CardHeader
title={lang.playerList.title}
action={
<ToggleButtonGroup
size='small'
color={(state === 1 ? 'warning' : state === 2 ? 'error' : undefined) as any}
value={state}
exclusive
onChange={(_, it) => {
if (it === 3) return
setState(it)
if (state === 3) refresh()
}}
>
<ToggleButton disabled={loading} value={1}><Star /></ToggleButton>
<ToggleButton disabled={loading} value={2}><Block /></ToggleButton>
<ToggleButton disabled={loading} value={3} onClick={() => state !== 3 && dialog(lang.playerList.nameToSearch, lang.username)
.then(filter => {
if (filter == null) return
his.push('/NekoMaid/playerList/' + filter)
setState(3)
setLoading(true)
plugin.emit('playerList:fetchPage', (it: any) => {
if (it.players == null) it.players = []
setPage(0)
setData(it)
setLoading(false)
}, page, 0, filter.toLowerCase())
})}><Search /></ToggleButton>
</ToggleButtonGroup>
}
/>
<Divider />
<Box sx={{ position: 'relative' }}>
<CircularLoading loading={loading} />
<TableContainer>
<Table>
<TableHead>
<TableRow>
<TableCell padding='checkbox' />
<TableCell>{lang.username}</TableCell>
<TableCell align='right'>{minecraft['stat.minecraft.play_time']}</TableCell>
<TableCell align='right'>{lang.playerList.lastPlay}</TableCell>
<TableCell align='right'>{lang.operations}</TableCell>
</TableRow>
</TableHead>
<TableBody>
{data.players.map(it => <TableRow key={it.name}>
<TableCell sx={{ cursor: 'pointer', padding: theme => theme.spacing(1, 1, 1, 2) }} onClick={() => his.push('/NekoMaid/playerList/' + it.name)}>
<Avatar src={getSkin(globalData, it.name, true)} imgProps={{ crossOrigin: 'anonymous', style: { width: 40, height: 40 } }} variant='rounded' />
</TableCell>
<TableCell>{it.name}</TableCell>
<TableCell align='right'>{dayjs.duration(it.playTime / 20, 'seconds').humanize()}</TableCell>
<TableCell align='right'>{dayjs(it.lastOnline).fromNow()}</TableCell>
<TableCell align='right'>
{(state === 1 || hasWhitelist) && <Tooltip title={lang.playerList[it.whitelisted ? 'clickToRemoveWhitelist' : 'clickToAddWhitelist']}>
<IconButton onClick={() => whitelist(it.name, plugin, refresh, !it.whitelisted)}>
{it.whitelisted ? <Star color='warning' /> : <StarBorder />}
</IconButton>
</Tooltip>}
<Tooltip title={it.ban == null ? lang.playerList.clickToBan : lang.playerList.banned + ': ' + it.ban}>
<IconButton onClick={() => banPlayer(it.name, plugin, refresh, it.ban == null)}>
<Block color={it.ban == null ? undefined : 'error'} />
</IconButton>
</Tooltip>
{actions.length
? <IconButton onClick={e => {
setActivedPlayer(anchorEl ? null : it)
setAnchorEl(anchorEl ? null : e.currentTarget)
}}><MoreHoriz /></IconButton>
: null}
</TableCell>
</TableRow>)}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[]}
component='div'
count={data.count}
rowsPerPage={10}
page={page}
onPageChange={(_, it) => !loading && setPage(it)}
/>
</Box>
<Menu
anchorEl={anchorEl}
open={Boolean(anchorEl)}
onClose={() => setAnchorEl(null)}
>{actions.map((It, i) => <It key={i} onClose={close} player={activedPlayer} />)}</Menu>
</Card>
}
Example #9
Source File: Worlds.tsx From NekoMaid with MIT License | 4 votes |
Worlds: React.FC = () => {
const plugin = usePlugin()
const globalData = useGlobalData()
const [worlds, setWorlds] = useState<World[]>([])
const [selected, setSelected] = useState('')
const [open, setOpen] = useState(false)
const update = () => plugin.emit('worlds:fetch', (data: World[]) => {
setWorlds(data)
if (data.length) setSelected(old => data.some(it => it.id === old) ? old : '')
})
useEffect(() => {
const offUpdate = plugin.on('worlds:update', update)
update()
return () => { offUpdate() }
}, [])
const sw = worlds.find(it => it.id === selected)
const getSwitch = (name: string, configId = name) => sw
? <ListItem
secondaryAction={<Switch disabled={!globalData.hasMultiverse} checked={(sw as any)[name]}
onChange={e => {
plugin.emit('worlds:set', sw.id, configId, e.target.checked.toString())
success()
}}
/>}><ListItemText primary={(lang.worlds as any)[name]} /></ListItem>
: null
return <Box sx={{ minHeight: '100%', py: 3 }}>
<Toolbar />
<Container maxWidth={false}>
<Grid container spacing={3}>
<Grid item lg={8} md={12} xl={9} xs={12}>
<Card>
<CardHeader title={lang.worlds.title} />
<Divider />
<Box sx={{ position: 'relative' }}>
<TableContainer>
<Table>
<TableHead>
<TableRow>
<TableCell padding='checkbox' />
<TableCell>{lang.worlds.name}</TableCell>
{globalData.hasMultiverse && <TableCell>{lang.worlds.alias}</TableCell>}
<TableCell>{lang.worlds.players}</TableCell>
<TableCell>{lang.worlds.chunks}</TableCell>
<TableCell>{lang.worlds.entities}</TableCell>
<TableCell>{lang.worlds.tiles}</TableCell>
<TableCell>{lang.worlds.time}</TableCell>
<TableCell>{lang.worlds.weather}</TableCell>
</TableRow>
</TableHead>
<TableBody>
{worlds.map(it => <TableRow key={it.id}>
<TableCell padding='checkbox'><Checkbox checked={selected === it.id} onClick={() => setSelected(it.id)} /></TableCell>
<TableCell><Tooltip title={it.id}><span>{it.name}</span></Tooltip></TableCell>
{globalData.hasMultiverse && <TableCell>{it.alias}
<IconButton size='small' onClick={() => dialog(lang.inputValue, lang.worlds.alias).then(res => {
if (res == null) return
plugin.emit('worlds:set', it.id, 'alias', res)
success()
})}><Edit fontSize='small' /></IconButton>
</TableCell>}
<TableCell>{it.players}</TableCell>
<TableCell>{it.chunks}</TableCell>
<TableCell>{it.entities}</TableCell>
<TableCell>{it.tiles}</TableCell>
<TableCell><Countdown time={it.time} max={24000} interval={50} /></TableCell>
<TableCell><IconButton size='small' onClick={() => {
plugin.emit('worlds:weather', it.id)
success()
}}>
{React.createElement((it.weather === 1 ? WeatherRainy : it.weather === 2 ? WeatherLightningRainy : WbSunny) as any)}
</IconButton></TableCell>
</TableRow>)}
</TableBody>
</Table>
</TableContainer>
</Box>
</Card>
</Grid>
<Grid item lg={4} md={6} xl={3} xs={12}>
<Card>
<CardHeader
title={lang.operations}
sx={{ position: 'relative' }}
action={<Tooltip title={lang.worlds.save} placement='left'>
<IconButton
size='small'
onClick={() => {
if (!sw) return
plugin.emit('worlds:save', sw.id)
success()
}}
sx={cardActionStyles}
><Save /></IconButton>
</Tooltip>}
/>
<Divider />
<Box sx={{ position: 'relative' }}>
{sw
? <List sx={{ width: '100%' }} component='nav'>
<ListItem secondaryAction={<ToggleButtonGroup
exclusive
color='primary'
size='small'
value={sw.difficulty}
onChange={(_, value) => {
plugin.emit('worlds:difficulty', sw.id, value)
success()
}}
>
{difficulties.map(it => <ToggleButton value={it.toUpperCase()} key={it}>{minecraft['options.difficulty.' + it]}</ToggleButton>)}
</ToggleButtonGroup>}><ListItemText primary={minecraft['options.difficulty']} /></ListItem>
<ListItem secondaryAction={<Switch checked={sw.pvp} onChange={e => {
plugin.emit('worlds:pvp', sw.id, e.target.checked)
success()
}} />}><ListItemText primary='PVP' /></ListItem>
{getSwitch('allowAnimals', 'spawning.animals.spawn')}
{getSwitch('allowMonsters', 'spawning.monsters.spawn')}
{globalData.hasMultiverse && <>
{getSwitch('allowFlight')}
{getSwitch('autoHeal')}
{getSwitch('hunger')}
</>}
<ListItem secondaryAction={globalData.canSetViewDistance
? <IconButton
onClick={() => dialog({
content: lang.inputValue,
input: {
error: true,
type: 'number',
helperText: lang.invalidValue,
validator: (it: string) => /^\d+$/.test(it) && +it > 1 && +it < 33
}
}).then(res => {
if (!res) return
plugin.emit('worlds:viewDistance', sw.id, parseInt(res as any))
success()
})}
><Edit /></IconButton>
: undefined}>
<ListItemText primary={lang.worlds.viewDistance + ': ' + sw.viewDistance} />
</ListItem>
<ListItem><ListItemText primary={minecraft['selectWorld.enterSeed']} secondary={sw.seed} /></ListItem>
<ListItemButton onClick={() => setOpen(!open)}>
<ListItemText primary={minecraft['selectWorld.gameRules']} />
{open ? <ExpandLess /> : <ExpandMore />}
</ListItemButton>
<Collapse in={open} timeout="auto" unmountOnExit>
<List component='div' dense disablePadding>
{sw.rules.map(([key, value]) => {
const isTrue = value === 'true'
const isBoolean = isTrue || value === 'false'
const isNumber = /^\d+$/.test(value)
return <ListItem
key={key}
sx={{ pl: 4 }}
secondaryAction={isBoolean
? <Switch
checked={isTrue}
onChange={e => {
plugin.emit('worlds:rule', sw.id, key, e.target.checked.toString())
success()
}}
/>
: <IconButton
onClick={() => dialog({
content: lang.inputValue,
input: isNumber
? {
error: true,
type: 'number',
helperText: lang.invalidValue,
validator: (it: string) => /^\d+$/.test(it)
}
: { }
}).then(res => {
if (res == null) return
plugin.emit('worlds:rule', sw.id, key, res)
success()
})}
><Edit /></IconButton>}
>
<ListItemText primary={(minecraft['gamerule.' + key] || key) + (isBoolean ? '' : ': ' + value)} />
</ListItem>
})}
</List>
</Collapse>
</List>
: <CardContent><Empty /></CardContent>
}
</Box>
</Card>
</Grid>
</Grid>
</Container>
</Box>
}