@mui/icons-material#Close TypeScript Examples
The following examples show how to use
@mui/icons-material#Close.
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: Message.tsx From your_spotify with GNU General Public License v3.0 | 6 votes |
Alert = React.forwardRef<HTMLDivElement, AlertProps>(
({ message, level, onClose }: AlertProps, ref) => {
return (
<div
ref={ref}
className={clsx({
[s.alert]: true,
[s[level]]: true,
})}>
<Text onDark>{message}</Text>
<IconButton size="small" onClick={onClose}>
<Close className={s.icon} fontSize="small" />
</IconButton>
</div>
);
},
)
Example #2
Source File: HelpModal.tsx From rewind with MIT License | 6 votes |
export function HelpBox(props: Pick<HelpModalProps, "onClose">) {
const { onClose } = props;
return (
<Paper sx={{ px: 2, py: 2, display: "flex", flexDirection: "column" }}>
{/*MenuBar could be reused*/}
<Stack sx={{ alignItems: "center" }} direction={"row"} gap={1}>
<Help />
<Typography fontWeight={"bolder"}>Help</Typography>
<Box flexGrow={1} />
<IconButton onClick={onClose}>
<Close />
</IconButton>
</Stack>
<Divider />
<PlaybarNavigationShortcuts />
{/*<OtherResources />*/}
{/*Footer*/}
<Divider />
<Stack sx={{ paddingTop: 1 }}>
<PromotionFooter />
</Stack>
</Paper>
);
}
Example #3
Source File: CompareBuildButton.tsx From genshin-optimizer with MIT License | 6 votes |
export default function CompareBuildButton({ artId, weaponId }: { artId?: string, weaponId?: string }) {
const { t } = useTranslation("page_character")
const [show, onShow, onHide] = useBoolState(false)
const { database } = useContext(DatabaseContext)
const { character, character: { key: characterKey, equippedArtifacts }, characterSheet, data: oldData, mainStatAssumptionLevel, characterDispatch } = useContext(DataContext)
const build = useMemo(() => {
const newArt = database._getArt(artId ?? "")
const artmap = objectMap(equippedArtifacts, (id, slot) => slot === newArt?.slotKey ? newArt : database._getArt(id))
return Object.values(artmap)
}, [database, equippedArtifacts, artId])
const teamData = useTeamData(characterKey, mainStatAssumptionLevel, build, weaponId ? database._getWeapon(weaponId) : undefined)
if (!teamData) return null
return <>
<ModalWrapper open={show} onClose={onHide} containerProps={{ maxWidth: "xl" }}>
<Suspense fallback={<Skeleton variant="rectangular" width="100%" height={600} />}>
<DataContext.Provider value={{ characterSheet, character, characterDispatch, mainStatAssumptionLevel, data: teamData[characterKey]!.target, teamData, oldData }}>
<BuildDisplayItem compareBuild={true} extraButtons={<><HitModeToggle size="small" /><ReactionToggle size="small" /><Button size='small' color="error" onClick={onHide} ><Close /></Button></>} />
</DataContext.Provider>
</Suspense>
</ModalWrapper>
<Tooltip title={<Typography>{t`tabEquip.compare`}</Typography>} placement="top" arrow>
<Button color="info" size="small" onClick={onShow} ><Difference /></Button>
</Tooltip>
</>
}
Example #4
Source File: BaseSettingsModal.tsx From rewind with MIT License | 5 votes |
export function BaseSettingsModal(props: SettingsProps) {
const { onClose, tabs, opacity, onOpacityChange, tabIndex, onTabIndexChange } = props;
const handleTabChange = (event: any, newValue: any) => {
onTabIndexChange(newValue);
};
const displayedTab = tabs[tabIndex].component;
return (
<Paper
sx={{
filter: `opacity(${opacity}%)`,
height: "100%",
display: "flex",
flexDirection: "column",
position: "relative",
}}
elevation={2}
>
<Stack sx={{ py: 1, px: 2, alignItems: "center" }} direction={"row"} gap={1}>
<SettingsIcon />
<Typography fontWeight={"bolder"}>Settings</Typography>
<Box flexGrow={1} />
<IconButton onClick={onClose}>
<Close />
</IconButton>
</Stack>
<Divider />
<Stack direction={"row"} sx={{ flexGrow: 1, overflow: "auto" }}>
{/*TODO: Holy moly, the CSS here needs to be changed a bit*/}
<Tabs
orientation="vertical"
variant="scrollable"
value={tabIndex}
onChange={handleTabChange}
sx={{ borderRight: 1, borderColor: "divider", position: "absolute" }}
>
{tabs.map(({ label }, index) => (
<Tab label={label} key={index} tabIndex={index} sx={{ textTransform: "none" }} />
))}
</Tabs>
<Box sx={{ marginLeft: "90px" }}>{displayedTab}</Box>
</Stack>
<Divider />
<Stack sx={{ px: 2, py: 1, flexDirection: "row", alignItems: "center" }}>
<PromotionFooter />
<Box flexGrow={1} />
<Stack direction={"row"} alignItems={"center"} gap={2}>
<IconButton onClick={() => onOpacityChange(MIN_OPACITY)}>
<VisibilityOff />
</IconButton>
<Slider
value={opacity}
onChange={(_, v) => onOpacityChange(v as number)}
step={5}
min={MIN_OPACITY}
max={MAX_OPACITY}
valueLabelFormat={(value: number) => `${value}%`}
sx={{ width: "12em" }}
valueLabelDisplay={"auto"}
/>
<IconButton onClick={() => onOpacityChange(MAX_OPACITY)}>
<Visibility />
</IconButton>
</Stack>
</Stack>
</Paper>
);
}
Example #5
Source File: dialog.tsx From Search-Next with GNU General Public License v3.0 | 5 votes |
Dialog: React.FC<DialogProps> = ({
open,
title,
onOk,
onCancel,
okText,
cancelText,
children,
container,
width = 520,
showFooter = true,
}) => {
const { t } = useTranslation();
return (
<MModal
aria-labelledby="transition-modal-title"
aria-describedby="transition-modal-description"
open={open}
onClose={onCancel}
closeAfterTransition
BackdropComponent={Backdrop}
BackdropProps={{
timeout: 500,
}}
container={container}
disableAutoFocus
>
<Fade in={open}>
<div
className={classnames(
'rounded transform mx-auto relative top-28',
css`
width: ${typeof width === 'number' ? width + 'px' : width};
max-width: calc(100vw - 32px);
background-color: rgba(255, 255, 255, 0.9);
backdrop-filter: blur(8px);
`,
)}
>
<div className="p-3 py-2 font-bold text-base flex justify-between items-center">
{title}
<IconButton size="small" onClick={onCancel}>
<Close />
</IconButton>
</div>
<div className="p-4">{children}</div>
{showFooter && (
<div className="p-2 flex justify-end gap-2">
<Button variant="text" onClick={onCancel}>
{cancelText ? cancelText : t('cancel')}
</Button>
<Button variant="text" onClick={onOk}>
{okText ? okText : t('submit')}
</Button>
</div>
)}
</div>
</Fade>
</MModal>
);
}
Example #6
Source File: CloseButton.tsx From genshin-optimizer with MIT License | 5 votes |
export default function CloseButton({ large = false, ...props }: CloseButtonProps) {
const { t } = useTranslation("ui")
if (large)
return <Button color="error" startIcon={<Close />} {...props} >{t`close`}</Button>
return <Button color="error" sx={{ p: 1, minWidth: 0 }} {...props} >
<Close />
</Button>
}
Example #7
Source File: UseEquipped.tsx From genshin-optimizer with MIT License | 5 votes |
function SelectItem({ characterKey, rank, maxRank, setRank, onRemove, numAbove }: {
characterKey: CharacterKey,
rank: number,
maxRank: number,
setRank: (r: number | undefined) => void,
onRemove: () => void,
numAbove: number,
}) {
const { t } = useTranslation("page_character")
const { database } = useContext(DatabaseContext)
const character = useCharacter(characterKey)
if (!character) return null
const { equippedWeapon, equippedArtifacts } = character
return <CardLight sx={{ p: 1 }} >
<Box sx={{ pb: 1, display: "flex", justifyContent: "space-between", gap: 1 }}>
<SqBadge color="info">
<Typography>#{rank}</Typography>
</SqBadge>
<SqBadge sx={{ flexGrow: 1 }} color={numAbove === (rank - 1) ? "warning" : (rank - 1) < numAbove ? "error" : "success"}>
<Typography>{numAbove === (rank - 1) ? <Trans t={t} i18nKey="tabOptimize.useEquipped.modal.status.curr">Current character</Trans>
: (rank - 1) < numAbove ? <Trans t={t} i18nKey="tabOptimize.useEquipped.modal.status.dont">Don't Use artifacts</Trans> :
<Trans t={t} i18nKey="tabOptimize.useEquipped.modal.status.use">Use artifacts</Trans>}</Typography>
</SqBadge>
<Box>
<ButtonGroup sx={{ flexGrow: 1 }} size="small">
<CustomNumberInputButtonGroupWrapper >
<CustomNumberInput onChange={setRank} value={rank}
// startAdornment="Rank:"
inputProps={{ min: 1, max: maxRank, sx: { textAlign: "center" } }}
sx={{ width: "100%", height: "100%", pl: 2 }} />
</CustomNumberInputButtonGroupWrapper>
<Button disabled={rank === 1} onClick={() => setRank(1)} >
<KeyboardDoubleArrowUp />
</Button>
<Button disabled={rank === 1} onClick={() => setRank(rank - 1)} >
<KeyboardArrowUp />
</Button>
<Button disabled={rank === maxRank} onClick={() => setRank(rank + 1)} >
<KeyboardArrowDown />
</Button>
<Button disabled={rank === maxRank} onClick={() => setRank(maxRank)} >
<KeyboardDoubleArrowDown />
</Button>
<Button color="error" onClick={onRemove}>
<Close />
</Button>
</ButtonGroup>
</Box>
</Box>
<Grid container columns={7} spacing={1}>
<Grid item xs={1} >
<CharacterCardPico characterKey={characterKey} />
</Grid>
<Grid item xs={1}><WeaponCardPico weaponId={equippedWeapon} /></Grid>
{Object.entries(equippedArtifacts).map(([slotKey, aId]) => <Grid item xs={1} key={slotKey} ><ArtifactCardPico slotKey={slotKey} artifactObj={database._getArt(aId)} /></Grid>)}
</Grid>
</CardLight>
}
Example #8
Source File: PersonDialog.tsx From frontend with MIT License | 5 votes |
export default function PersonDialog({ label, type, onSubmit }: Props) {
const { t } = useTranslation()
const [open, setOpen] = useState(false)
const handleClickOpen = () => setOpen(true)
const handleClose = () => setOpen(false)
return (
<>
<Button fullWidth variant="contained" color="info" onClick={handleClickOpen}>
{label}
</Button>
<Dialog
open={open}
onClose={(e, reason) => {
if (reason === 'backdropClick') return
handleClose()
}}
onBackdropClick={() => false}>
<DialogTitle>
{label}
<IconButton
aria-label="close"
onClick={handleClose}
sx={{
position: 'absolute',
right: 8,
top: 8,
color: (theme) => theme.palette.grey[500],
}}>
<Close />
</IconButton>
</DialogTitle>
<DialogContent>
<Box sx={{ mb: 2 }}>
{type === 'beneficiary' ? (
<Alert severity="info">
<AlertTitle>{t('campaigns:campaign.beneficiary.name')}</AlertTitle>
Лице, в чиято полза се организира кампанията. От юридическа гледна точка,
бенефициентът <strong>НЕ влиза</strong> във взаимоотношения с оператора при набиране
на средства в негова полза. Всички договори, изисквания, банкова сметка на
кампанията са на името на организатора. Възможно е бенефициентът по една кампания да
е и неговият организатор.
</Alert>
) : (
<Alert severity="warning">
<AlertTitle>{t('campaigns:campaign.coordinator.name')}</AlertTitle>
Организаторът е физическото или юридическо лице, с което се сключва договор за
набиране на средства, след като негова заявка за кампания е одобрена. Набраните
средства се прехвърлят в неговата банкова сметка, от него се изискват отчети за
разходените средства. Когато дадено лице иска да стане организатор на кампании,
преминава през процес на верификация, за да се избегнат измамите. Организаторът също
може да е и бенефициент по дадена кампания.
</Alert>
)}
</Box>
<PersonForm
{...type}
onSubmit={(...args) => {
onSubmit(...args)
handleClose()
}}
/>
</DialogContent>
</Dialog>
</>
)
}
Example #9
Source File: CloseModalButton.tsx From frontend with MIT License | 5 votes |
export default function CloseModalButton({
edge = 'end',
fontSize = 'small',
href = routes.index,
Icon = Close,
onClose,
...buttonProps
}: CloseModalButtonProps) {
if (typeof onClose === 'function') {
return (
<IconButton
onClick={onClose}
sx={(theme) => ({
position: 'absolute',
top: theme.spacing(1),
left: edge === 'start' ? theme.spacing(1) : undefined,
right: edge === 'end' ? theme.spacing(1) : undefined,
zIndex: theme.zIndex.drawer,
})}
{...buttonProps}
size="large">
<Icon fontSize={fontSize} />
</IconButton>
)
}
return (
<LinkIconButton
href={href}
sx={(theme) => ({
position: 'absolute',
top: theme.spacing(1),
left: edge === 'start' ? theme.spacing(1) : undefined,
right: edge === 'end' ? theme.spacing(1) : undefined,
zIndex: theme.zIndex.drawer,
})}
{...buttonProps}>
<Icon fontSize={fontSize} />
</LinkIconButton>
)
}
Example #10
Source File: index.tsx From Search-Next with GNU General Public License v3.0 | 4 votes |
OtherApis: React.FC<PageProps> = (props) => {
const { route, children } = props;
const [iconApi, setIconApi] = React.useState('');
const [apiStatus, setApiStatus] = React.useState<ApiStatus>({});
const init = () => {
const account = localStorage.getItem('account');
const data = getOtherIconApi({
userId: account ?? '',
type: 'icon',
});
setIconApi(data.apiId);
let map = {} as ApiStatus;
websiteIconApis.forEach((i) => {
map[i.id] = 'warning';
});
setApiStatus(map);
};
const onChange = (event: SelectChangeEvent<any>) => {
const select = event.target.value;
setIconApi(select);
const account = localStorage.getItem('account');
setOtherIconApi({
userId: account ?? '',
apiId: select,
type: 'icon',
});
};
const StatusChip = (status: string) => {
const statusMap = {
warning: (
<>
<PendingOutlined /> 等待响应
</>
),
success: (
<>
<Done /> 成功
</>
),
error: (
<>
<Close /> 失败
</>
),
};
return (
<Chip
size="small"
color={status as any}
label={
<div className="text-sm flex items-center gap-1">
{(statusMap as any)[status as any]}
</div>
}
/>
);
};
React.useEffect(() => {
init();
}, []);
return (
<div>
<ContentList>
<Alert severity="info">
<AlertTitle>提示</AlertTitle>
不同地区,不同网络下各API的表现可能不同,请选择最适合的API以提高使用体验。
</Alert>
<ItemAccordion
title="Website Icon API"
desc="设置获取网站图标的api"
action={
<Select
label="API"
value={iconApi}
size="small"
onChange={onChange}
options={websiteIconApis.map((i) => ({
label: i.name,
value: i.id,
}))}
/>
}
>
<div className="flex items-center text-sm gap-1 pb-2">
<PendingOutlined /> <span>等待响应</span>
<Done /> <span>成功</span>
<Close /> <span>失败</span> 状态仅作参考,具体以实际使用为准
</div>
{websiteIconApis.map((i) => {
return (
<AccordionDetailItem
key={i.id}
disabledRightPadding
title={i.name}
action={
<>
{StatusChip(apiStatus[i.id])}
<img
className={css`
display: none;
`}
src={`${i.url}google.com`}
alt={i.name}
onLoad={(v) => {
setApiStatus({ ...apiStatus, [i.id]: 'success' });
}}
onError={(err) => {
setApiStatus({ ...apiStatus, [i.id]: 'error' });
}}
/>
</>
}
/>
);
})}
</ItemAccordion>
</ContentList>
</div>
);
}
Example #11
Source File: EditableField.tsx From abrechnung with GNU Affero General Public License v3.0 | 4 votes |
export default function EditableField({
value,
onChange,
validate = undefined,
helperText = undefined,
onStopEdit = undefined,
canEdit = true,
...props
}) {
const [currentValue, setValue] = useState("");
const [editing, setEditing] = useState(false);
const [error, setError] = useState(false);
const classes = useStyles();
useEffect(() => {
setValue(value);
}, [value]);
const onSave = () => {
if (!error) {
onChange(currentValue);
setValue("");
setEditing(false);
}
};
const startEditing = () => {
setValue(value);
setEditing(true);
};
const stopEditing = () => {
setValue(value);
setEditing(false);
if (onStopEdit) {
onStopEdit();
}
};
const onValueChange = (event) => {
setValue(event.target.value);
if (validate) {
setError(!validate(event.target.value));
}
};
const onKeyUp = (key) => {
if (key.keyCode === 13) {
onSave();
}
};
return (
<div className={classes.root}>
<DisabledTextField
error={error}
value={currentValue}
disabled={!editing}
onChange={onValueChange}
className={classes.input}
helperText={error ? helperText : null}
onKeyUp={onKeyUp}
{...props}
/>
{canEdit &&
(editing ? (
<>
<IconButton color="primary" onClick={onSave}>
<Check />
</IconButton>
<IconButton color="secondary" onClick={stopEditing}>
<Close />
</IconButton>
</>
) : (
<IconButton color="primary" onClick={startEditing}>
<Edit />
</IconButton>
))}
</div>
);
}
Example #12
Source File: engineSelectPopper.tsx From Search-Next with GNU General Public License v3.0 | 4 votes |
EngineSelectPopper: FC<EngineSelectPopperProps> = (props) => {
const {
width = 300,
anchorEl,
open = false,
onBtnClick,
onEngineSelect,
engine,
} = props;
const [classifyEngineList, setClassifyEngineList] = useState<
SearchEngineClassifyWithChildren[]
>([]);
const [selected, setSelected] = useState<string>('');
const [engineList, setEngineList] = React.useState([] as SearchEngine[]);
const getClassifyEngine = () => {
getClassifyEngineListApi().then((res) => {
const current = {
...engine.engine,
classifyId: engine.engine?.classify?._id,
} as SearchEngine;
let filterEngines = res
.map((i) => i.children)
.flat()
.filter((u) => u._id !== engine.engine?._id)
.slice(0, engine.indexCount - 1);
if (engine.sortType === 'count') {
filterEngines = filterEngines.sort((r, t) => t.count - r.count);
}
setEngineList([current, ...filterEngines]);
setClassifyEngineList(res);
res.length > 0 && setSelected(res[0]._id);
});
};
useEffect(() => {
if (engine?.engine?.classify?._id) {
setSelected(engine?.engine?.classify?._id);
}
getClassifyEngine();
}, [engine]);
return (
<div className="mb-1">
<Popper open={open} anchorEl={anchorEl} placement="top">
{({ TransitionProps }) => (
<Card
{...TransitionProps}
style={{ width: `${anchorEl?.clientWidth}px` }}
className="mb-1"
>
<div className="p-2 flex gap-2 items-start">
<div className="max-h-20 overflow-y-auto pr-1">
{classifyEngineList.map((item) => (
<div
key={item._id}
onClick={() => {
setSelected(item._id);
}}
className={classnames(
'px-1.5 py-0.5 cursor-pointer rounded text-sm',
selected === item._id
? 'bg-primary text-white'
: 'bg-white',
)}
>
{item.name}
</div>
))}
</div>
<div className="flex gap-1 items-start justify-start flex-grow">
{classifyEngineList
.filter((i) => i._id === selected)?.[0]
?.children.map((i) => (
<div
className={classnames(
'px-1.5 py-0.5 cursor-pointer rounded text-sm',
engine?.engine?._id === i._id
? 'bg-primary text-white'
: 'bg-white border',
)}
onClick={() => {
onEngineSelect(i);
}}
>
{i.name}
</div>
))}
</div>
<IconButton
onClick={() => {
onBtnClick(false);
}}
size="small"
>
<Close />
</IconButton>
</div>
</Card>
)}
</Popper>
<div className="w-full text-left mb-1 flex justify-start items-center overflow-x-auto">
{engineList.map((i, j) => (
<Chip
key={j}
className={classnames(
'mx-1',
i._id === engine?.engine?._id
? 'bg-primary text-white'
: 'bg-gray-100',
)}
size="small"
label={i.name}
onClick={(e) => onEngineSelect(i)}
></Chip>
))}
{engine.mode === 'custom' && (
<Chip
onClick={(e: any) => {
onBtnClick(!open);
}}
className={classnames('mx-1', 'bg-gray-100')}
size="small"
label={
<div className="text-sm flex gap-1 items-center">
<Settings className="text-base" />
</div>
}
/>
)}
</div>
</div>
);
}
Example #13
Source File: index.tsx From genshin-optimizer with MIT License | 4 votes |
export default function TabBuild() {
const { character, character: { key: characterKey } } = useContext(DataContext)
const [{ tcMode }] = useDBState("GlobalSettings", initGlobalSettings)
const { database } = useContext(DatabaseContext)
const [generatingBuilds, setgeneratingBuilds] = useState(false)
const [generationProgress, setgenerationProgress] = useState(0)
const [generationDuration, setgenerationDuration] = useState(0)//in ms
const [generationSkipped, setgenerationSkipped] = useState(0)
const [chartData, setchartData] = useState(undefined as ChartData | undefined)
const [artsDirty, setArtsDirty] = useForceUpdate()
const [{ equipmentPriority, threads = defThreads }, setOptimizeDBState] = useOptimizeDBState()
const maxWorkers = threads > defThreads ? defThreads : threads
const setMaxWorkers = useCallback(threads => setOptimizeDBState({ threads }), [setOptimizeDBState],)
const characterDispatch = useCharacterReducer(characterKey)
const buildSettings = character?.buildSettings ?? initialBuildSettings()
const { plotBase, setFilters, statFilters, mainStatKeys, optimizationTarget, mainStatAssumptionLevel, useExcludedArts, useEquippedArts, builds, buildDate, maxBuildsToShow, levelLow, levelHigh } = buildSettings
const buildsArts = useMemo(() => builds.map(build => build.map(i => database._getArt(i)!)), [builds, database])
const teamData = useTeamData(characterKey, mainStatAssumptionLevel)
const { characterSheet, target: data } = teamData?.[characterKey as CharacterKey] ?? {}
const compareData = character?.compareData ?? false
const noArtifact = useMemo(() => !database._getArts().length, [database])
const buildSettingsDispatch = useCallback((action) =>
characterDispatch && characterDispatch({ buildSettings: buildSettingsReducer(buildSettings, action) })
, [characterDispatch, buildSettings])
const onChangeMainStatKey = useCallback((slotKey: SlotKey, mainStatKey?: MainStatKey) => {
if (mainStatKey === undefined) buildSettingsDispatch({ type: "mainStatKeyReset", slotKey })
else buildSettingsDispatch({ type: "mainStatKey", slotKey, mainStatKey })
}, [buildSettingsDispatch])
//register changes in artifact database
useEffect(() =>
database.followAnyArt(setArtsDirty),
[setArtsDirty, database])
const { split, setPerms, totBuildNumber } = useMemo(() => {
if (!characterKey) // Make sure we have all slotKeys
return { totBuildNumber: 0 }
let cantTakeList: CharacterKey[] = []
if (useEquippedArts) {
const index = equipmentPriority.indexOf(characterKey)
if (index < 0) cantTakeList = [...equipmentPriority]
else cantTakeList = equipmentPriority.slice(0, index)
}
const arts = database._getArts().filter(art => {
if (art.level < levelLow) return false
if (art.level > levelHigh) return false
const mainStats = mainStatKeys[art.slotKey]
if (mainStats?.length && !mainStats.includes(art.mainStatKey)) return false
// If its equipped on the selected character, bypass the check
if (art.location === characterKey) return true
if (art.exclude && !useExcludedArts) return false
if (art.location && !useEquippedArts) return false
if (art.location && useEquippedArts && cantTakeList.includes(art.location)) return false
return true
})
const split = compactArtifacts(arts, mainStatAssumptionLevel)
const setPerms = [...artSetPerm([setFilters.map(({ key, num }) => ({ key, min: num }))])]
const totBuildNumber = [...setPerms].map(perm => countBuilds(filterArts(split, perm))).reduce((a, b) => a + b, 0)
return artsDirty && { split, setPerms, totBuildNumber }
}, [characterKey, useExcludedArts, useEquippedArts, equipmentPriority, mainStatKeys, setFilters, levelLow, levelHigh, artsDirty, database, mainStatAssumptionLevel])
// Reset the Alert by setting progress to zero.
useEffect(() => {
setgenerationProgress(0)
}, [totBuildNumber])
// Provides a function to cancel the work
const cancelToken = useRef(() => { })
//terminate worker when component unmounts
useEffect(() => () => cancelToken.current(), [])
const generateBuilds = useCallback(async () => {
if (!characterKey || !optimizationTarget || !split || !setPerms) return
const teamData = await getTeamData(database, characterKey, mainStatAssumptionLevel, [])
if (!teamData) return
const workerData = uiDataForTeam(teamData.teamData, characterKey)[characterKey as CharacterKey]?.target.data![0]
if (!workerData) return
Object.assign(workerData, mergeData([workerData, dynamicData])) // Mark art fields as dynamic
let optimizationTargetNode = objPathValue(workerData.display ?? {}, optimizationTarget) as NumNode | undefined
if (!optimizationTargetNode) return
const targetNode = optimizationTargetNode
const valueFilter: { value: NumNode, minimum: number }[] = Object.entries(statFilters).map(([key, value]) => {
if (key.endsWith("_")) value = value / 100 // TODO: Conversion
return { value: input.total[key], minimum: value }
}).filter(x => x.value && x.minimum > -Infinity)
const t1 = performance.now()
setgeneratingBuilds(true)
setchartData(undefined)
setgenerationDuration(0)
setgenerationProgress(0)
setgenerationSkipped(0)
const cancelled = new Promise<void>(r => cancelToken.current = r)
let nodes = [...valueFilter.map(x => x.value), optimizationTargetNode], arts = split!
const origCount = totBuildNumber, minimum = [...valueFilter.map(x => x.minimum), -Infinity]
if (plotBase) {
nodes.push(input.total[plotBase])
minimum.push(-Infinity)
}
nodes = optimize(nodes, workerData, ({ path: [p] }) => p !== "dyn");
({ nodes, arts } = pruneAll(nodes, minimum, arts, maxBuildsToShow,
new Set(setFilters.map(x => x.key as ArtifactSetKey)), {
reaffine: true, pruneArtRange: true, pruneNodeRange: true, pruneOrder: true
}))
const plotBaseNode = plotBase ? nodes.pop() : undefined
optimizationTargetNode = nodes.pop()!
let wrap = {
buildCount: 0, failedCount: 0, skippedCount: origCount,
buildValues: Array(maxBuildsToShow).fill(0).map(_ => -Infinity)
}
setPerms.forEach(filter => wrap.skippedCount -= countBuilds(filterArts(arts, filter)))
const setPerm = splitFiltersBySet(arts, setPerms,
maxWorkers === 1
// Don't split for single worker
? Infinity
// 8 perms / worker, up to 1M builds / perm
: Math.min(origCount / maxWorkers / 4, 1_000_000))[Symbol.iterator]()
function fetchWork(): Request | undefined {
const { done, value } = setPerm.next()
return done ? undefined : {
command: "request",
threshold: wrap.buildValues[maxBuildsToShow - 1], filter: value,
}
}
const filters = nodes
.map((value, i) => ({ value, min: minimum[i] }))
.filter(x => x.min > -Infinity)
const finalizedList: Promise<FinalizeResult>[] = []
for (let i = 0; i < maxWorkers; i++) {
const worker = new Worker()
const setup: Setup = {
command: "setup",
id: `${i}`,
arts,
optimizationTarget: optimizationTargetNode,
plotBase: plotBaseNode,
maxBuilds: maxBuildsToShow,
filters
}
worker.postMessage(setup, undefined)
let finalize: (_: FinalizeResult) => void
const finalized = new Promise<FinalizeResult>(r => finalize = r)
worker.onmessage = async ({ data }: { data: WorkerResult }) => {
switch (data.command) {
case "interim":
wrap.buildCount += data.buildCount
wrap.failedCount += data.failedCount
wrap.skippedCount += data.skippedCount
if (data.buildValues) {
wrap.buildValues.push(...data.buildValues)
wrap.buildValues.sort((a, b) => b - a).splice(maxBuildsToShow)
}
break
case "request":
const work = fetchWork()
if (work) {
worker.postMessage(work)
} else {
const finalizeCommand: Finalize = { command: "finalize" }
worker.postMessage(finalizeCommand)
}
break
case "finalize":
worker.terminate()
finalize(data);
break
default: console.log("DEBUG", data)
}
}
cancelled.then(() => worker.terminate())
finalizedList.push(finalized)
}
const buildTimer = setInterval(() => {
setgenerationProgress(wrap.buildCount)
setgenerationSkipped(wrap.skippedCount)
setgenerationDuration(performance.now() - t1)
}, 100)
const results = await Promise.any([Promise.all(finalizedList), cancelled])
clearInterval(buildTimer)
cancelToken.current = () => { }
if (!results) {
setgenerationDuration(0)
setgenerationProgress(0)
setgenerationSkipped(0)
} else {
if (plotBase) {
const plotData = mergePlot(results.map(x => x.plotData!))
const plotBaseNode = input.total[plotBase] as NumNode
let data = Object.values(plotData)
if (KeyMap.unit(targetNode.info?.key) === "%")
data = data.map(({ value, plot }) => ({ value: value * 100, plot })) as Build[]
if (KeyMap.unit(plotBaseNode!.info?.key) === "%")
data = data.map(({ value, plot }) => ({ value, plot: (plot ?? 0) * 100 })) as Build[]
setchartData({
valueNode: targetNode,
plotNode: plotBaseNode,
data
})
}
const builds = mergeBuilds(results.map(x => x.builds), maxBuildsToShow)
if (process.env.NODE_ENV === "development") console.log("Build Result", builds)
buildSettingsDispatch({ builds: builds.map(build => build.artifactIds), buildDate: Date.now() })
const totalDuration = performance.now() - t1
setgenerationProgress(wrap.buildCount)
setgenerationSkipped(wrap.skippedCount)
setgenerationDuration(totalDuration)
}
setgeneratingBuilds(false)
}, [characterKey, database, totBuildNumber, mainStatAssumptionLevel, maxBuildsToShow, optimizationTarget, plotBase, setPerms, split, buildSettingsDispatch, setFilters, statFilters, maxWorkers])
const characterName = characterSheet?.name ?? "Character Name"
const setPlotBase = useCallback(plotBase => {
buildSettingsDispatch({ plotBase })
setchartData(undefined)
}, [buildSettingsDispatch])
const dataContext: dataContextObj | undefined = useMemo(() => {
return data && characterSheet && character && teamData && {
data,
characterSheet,
character,
mainStatAssumptionLevel,
teamData,
characterDispatch
}
}, [data, characterSheet, character, teamData, characterDispatch, mainStatAssumptionLevel])
return <Box display="flex" flexDirection="column" gap={1}>
{noArtifact && <Alert severity="warning" variant="filled"> Opps! It looks like you haven't added any artifacts to GO yet! You should go to the <Link component={RouterLink} to="/artifact">Artifacts</Link> page and add some!</Alert>}
{/* Build Generator Editor */}
{dataContext && <DataContext.Provider value={dataContext}>
<Grid container spacing={1} >
{/* 1*/}
<Grid item xs={12} sm={6} lg={3} display="flex" flexDirection="column" gap={1}>
{/* character card */}
<Box><CharacterCard characterKey={characterKey} /></Box>
</Grid>
{/* 2 */}
<Grid item xs={12} sm={6} lg={3}>
<CardLight>
<CardContent >
<Typography gutterBottom>Main Stat</Typography>
<BootstrapTooltip placement="top" title={<Typography><strong>Level Assumption</strong> changes mainstat value to be at least a specific level. Does not change substats.</Typography>}>
<Box>
<AssumeFullLevelToggle mainStatAssumptionLevel={mainStatAssumptionLevel} setmainStatAssumptionLevel={mainStatAssumptionLevel => buildSettingsDispatch({ mainStatAssumptionLevel })} disabled={generatingBuilds} />
</Box>
</BootstrapTooltip>
</CardContent>
{/* main stat selector */}
<MainStatSelectionCard
mainStatKeys={mainStatKeys}
onChangeMainStatKey={onChangeMainStatKey}
disabled={generatingBuilds}
/>
</CardLight>
</Grid>
{/* 3 */}
<Grid item xs={12} sm={6} lg={3} display="flex" flexDirection="column" gap={1}>
{/*Minimum Final Stat Filter */}
<StatFilterCard statFilters={statFilters} setStatFilters={sFs => buildSettingsDispatch({ statFilters: sFs })} disabled={generatingBuilds} />
<BonusStatsCard />
{/* use excluded */}
<UseExcluded disabled={generatingBuilds} useExcludedArts={useExcludedArts} buildSettingsDispatch={buildSettingsDispatch} artsDirty={artsDirty} />
{/* use equipped */}
<UseEquipped disabled={generatingBuilds} useEquippedArts={useEquippedArts} buildSettingsDispatch={buildSettingsDispatch} />
{ /* Level Filter */}
<CardLight>
<CardContent sx={{ py: 1 }}>
Artifact Level Filter
</CardContent>
<ArtifactLevelSlider levelLow={levelLow} levelHigh={levelHigh}
setLow={levelLow => buildSettingsDispatch({ levelLow })}
setHigh={levelHigh => buildSettingsDispatch({ levelHigh })}
setBoth={(levelLow, levelHigh) => buildSettingsDispatch({ levelLow, levelHigh })}
disabled={generatingBuilds}
/>
</CardLight>
</Grid>
{/* 4 */}
<Grid item xs={12} sm={6} lg={3} display="flex" flexDirection="column" gap={1}>
<ArtifactSetConditional disabled={generatingBuilds} />
{/* Artifact set pickers */}
{setFilters.map((setFilter, index) => (index <= setFilters.filter(s => s.key).length) && <ArtifactSetPicker key={index} index={index} setFilters={setFilters}
disabled={generatingBuilds} onChange={(index, key, num) => buildSettingsDispatch({ type: 'setFilter', index, key, num })} />)}
</Grid>
</Grid>
{/* Footer */}
<Grid container spacing={1}>
<Grid item flexGrow={1} >
<ButtonGroup>
<Button
disabled={!characterKey || generatingBuilds || !optimizationTarget || !totBuildNumber || !objPathValue(data?.getDisplay(), optimizationTarget)}
color={(characterKey && totBuildNumber <= warningBuildNumber) ? "success" : "warning"}
onClick={generateBuilds}
startIcon={<FontAwesomeIcon icon={faCalculator} />}
>Generate Builds</Button>
<DropdownButton disabled={generatingBuilds || !characterKey}
title={<span><b>{maxBuildsToShow}</b> {maxBuildsToShow === 1 ? "Build" : "Builds"}</span>}>
<MenuItem>
<Typography variant="caption" color="info.main">
Decreasing the number of generated build will decrease build calculation time for large number of builds.
</Typography>
</MenuItem>
<Divider />
{maxBuildsToShowList.map(v => <MenuItem key={v}
onClick={() => buildSettingsDispatch({ maxBuildsToShow: v })}>{v} {v === 1 ? "Build" : "Builds"}</MenuItem>)}
</DropdownButton>
<DropdownButton disabled={generatingBuilds || !characterKey}
title={<span><b>{maxWorkers}</b> {maxWorkers === 1 ? "Thread" : "Threads"}</span>}>
<MenuItem>
<Typography variant="caption" color="info.main">
Increasing the number of threads will speed up build time, but will use more CPU power.
</Typography>
</MenuItem>
<Divider />
{range(1, defThreads).reverse().map(v => <MenuItem key={v}
onClick={() => setMaxWorkers(v)}>{v} {v === 1 ? "Thread" : "Threads"}</MenuItem>)}
</DropdownButton>
<Button
disabled={!generatingBuilds}
color="error"
onClick={() => cancelToken.current()}
startIcon={<Close />}
>Cancel</Button>
</ButtonGroup>
</Grid>
<Grid item>
<span>Optimization Target: </span>
{<OptimizationTargetSelector
optimizationTarget={optimizationTarget}
setTarget={target => buildSettingsDispatch({ optimizationTarget: target })}
disabled={!!generatingBuilds}
/>}
</Grid>
</Grid>
{!!characterKey && <Box >
<BuildAlert {...{ totBuildNumber, generatingBuilds, generationSkipped, generationProgress, generationDuration, characterName, maxBuildsToShow }} />
</Box>}
{tcMode && <Box >
<ChartCard disabled={generatingBuilds} chartData={chartData} plotBase={plotBase} setPlotBase={setPlotBase} />
</Box>}
<CardLight>
<CardContent>
<Box display="flex" alignItems="center" gap={1} mb={1} >
<Typography sx={{ flexGrow: 1 }}>
{builds ? <span>Showing <strong>{builds.length}</strong> Builds generated for {characterName}. {!!buildDate && <span>Build generated on: <strong>{(new Date(buildDate)).toLocaleString()}</strong></span>}</span>
: <span>Select a character to generate builds.</span>}
</Typography>
<Button disabled={!builds.length} color="error" onClick={() => buildSettingsDispatch({ builds: [], buildDate: 0 })} >Clear Builds</Button>
</Box>
<Grid container display="flex" spacing={1}>
<Grid item><HitModeToggle size="small" /></Grid>
<Grid item><ReactionToggle size="small" /></Grid>
<Grid item flexGrow={1} />
<Grid item><SolidToggleButtonGroup exclusive value={compareData} onChange={(e, v) => characterDispatch({ compareData: v })} size="small">
<ToggleButton value={false} disabled={!compareData}>
<small>Show New artifact Stats</small>
</ToggleButton>
<ToggleButton value={true} disabled={compareData}>
<small>Compare against equipped artifacts</small>
</ToggleButton>
</SolidToggleButtonGroup></Grid>
</Grid>
</CardContent>
</CardLight>
<BuildList {...{ buildsArts, character, characterKey, characterSheet, data, compareData, mainStatAssumptionLevel, characterDispatch, disabled: !!generatingBuilds }} />
</DataContext.Provider>}
</Box>
}
Example #14
Source File: CodeBlock.tsx From fluttertemplates.dev with MIT License | 4 votes |
function CodeBlock(params: CodeBlockParams) {
const [code, setCode] = useState("");
const isDarkTheme = useTheme().palette.mode === "dark";
const [open, setOpen] = React.useState(false);
const handleClose = (
event: React.SyntheticEvent | Event,
reason?: string
) => {
if (reason === "clickaway") {
return;
}
setOpen(false);
};
useEffect(() => {
fetch(params.url)
.then((response) => response.text())
.then((textString) => {
setCode(textString);
});
}, [params.url]);
const _snackBarAction = (
<React.Fragment>
<IconButton
size="small"
aria-label="close"
color="inherit"
onClick={handleClose}
>
<Close fontSize="small" />
</IconButton>
</React.Fragment>
);
return (
<div>
<div
style={{
position: "relative",
}}
>
<SyntaxHighlighter
language="dart"
style={!isDarkTheme ? github : dracula}
showLineNumbers={false}
customStyle={{
maxHeight: `${params.height}`,
fontSize: "0.95rem",
}}
>
{code}
</SyntaxHighlighter>
<Button
aria-label="Copy"
size="medium"
variant="contained"
color="secondary"
disableElevation
style={{
position: "absolute",
top: "16px",
right: "20px",
borderRadius: "10rem",
}}
startIcon={<FileCopyRounded />}
onClick={() => {
copy(code);
setOpen(true);
}}
>
Copy
</Button>
</div>
{!code && (
<Grid
container
direction="column"
justifyContent="center"
alignItems="center"
style={{
minHeight: "40vh",
}}
>
<Grid item>
<CircularProgress size="1.5rem" thickness={8} color="secondary" />
</Grid>
</Grid>
)}
<Snackbar
open={open}
autoHideDuration={4000}
onClose={handleClose}
message="Code copied successfully!"
action={_snackBarAction}
TransitionComponent={SlideTransition}
/>
</div>
);
}
Example #15
Source File: AuthButton.tsx From multi-downloader-nx with MIT License | 4 votes |
AuthButton: React.FC = () => {
const snackbar = useSnackbar();
const [open, setOpen] = React.useState(false);
const [username, setUsername] = React.useState('');
const [password, setPassword] = React.useState('');
const [usernameError, setUsernameError] = React.useState(false);
const [passwordError, setPasswordError] = React.useState(false);
const messageChannel = React.useContext(messageChannelContext);
const [loading, setLoading] = React.useState(false);
const [error, setError] = React.useState<Error|undefined>(undefined);
const [authed, setAuthed] = React.useState(false);
const checkAuth = async () => {
console.log(await messageChannel?.checkToken());
setAuthed((await messageChannel?.checkToken())?.isOk ?? false);
}
React.useEffect(() => { checkAuth() }, []);
const handleSubmit = async () => {
if (!messageChannel)
throw new Error('Invalid state'); //The components to confirm only render if the messageChannel is not undefinded
if (username.trim().length === 0)
return setUsernameError(true);
if (password.trim().length === 0)
return setPasswordError(true);
setUsernameError(false);
setPasswordError(false);
setLoading(true);
const res = await messageChannel.auth({ username, password });
if (res.isOk) {
setOpen(false);
snackbar.enqueueSnackbar('Logged in', {
variant: 'success'
});
setUsername('');
setPassword('');
} else {
setError(res.reason);
}
await checkAuth();
setLoading(false);
}
return <Require value={messageChannel}>
<Dialog open={open}>
<Dialog open={!!error}>
<DialogTitle>Error during Authentication</DialogTitle>
<DialogContentText>
{error?.name}
{error?.message}
</DialogContentText>
<DialogActions>
<Button onClick={() => setError(undefined)}>Close</Button>
</DialogActions>
</Dialog>
<DialogTitle sx={{ flexGrow: 1 }}>Authentication</DialogTitle>
<DialogContent>
<DialogContentText>
Here, you need to enter your username (most likely your Email) and your password.<br />
These information are not stored anywhere and are only used to authenticate with the service once.
</DialogContentText>
<TextField
error={usernameError}
helperText={usernameError ? 'Please enter something before submiting' : undefined}
margin="dense"
id="username"
label="Username"
type="text"
fullWidth
variant="standard"
value={username}
onChange={(e) => setUsername(e.target.value)}
disabled={loading}
/>
<TextField
error={passwordError}
helperText={passwordError ? 'Please enter something before submiting' : undefined}
margin="dense"
id="password"
label="Password"
type="password"
fullWidth
variant="standard"
value={password}
onChange={(e) => setPassword(e.target.value)}
disabled={loading}
/>
</DialogContent>
<DialogActions>
{loading && <CircularProgress size={30}/>}
<Button disabled={loading} onClick={() => setOpen(false)}>Close</Button>
<Button disabled={loading} onClick={() => handleSubmit()}>Authenticate</Button>
</DialogActions>
</Dialog>
<Button startIcon={authed ? <Check />: <Close />} variant="contained" onClick={() => setOpen(true)}>Authenticate</Button>
</Require>
}
Example #16
Source File: SessionList.tsx From abrechnung with GNU Affero General Public License v3.0 | 4 votes |
export default function SessionList() {
// TODO: fix editing functions
const [editedSessions, setEditedSessions] = useState({});
const [sessionToDelete, setSessionToDelete] = useState({
show: false,
toDelete: null,
});
const user = useRecoilValue(userData);
const sessions = user.sessions;
useTitle("Abrechnung - Sessions");
const editSession = (id) => {
if (!editedSessions.hasOwnProperty(id)) {
const newSessions = {
...editedSessions,
[id]: sessions.find((session) => session.id === id)?.name,
};
setEditedSessions(newSessions);
}
};
const stopEditSession = (id) => {
if (editedSessions.hasOwnProperty(id)) {
let newEditedSessions = { ...editedSessions };
delete newEditedSessions[id];
setEditedSessions(newEditedSessions);
}
};
const closeDeleteSessionModal = () => {
setSessionToDelete({ show: false, toDelete: null });
};
const performRename = (id) => {
if (editedSessions.hasOwnProperty(id)) {
renameSession({
sessionID: id,
name: editedSessions[id],
}).catch((err) => {
toast.error(err);
});
stopEditSession(id);
}
};
const openDeleteSessionModal = (id) => {
setSessionToDelete({ show: true, toDelete: id });
};
const confirmDeleteSession = () => {
if (sessionToDelete.toDelete !== null) {
deleteSession({ sessionID: sessionToDelete.toDelete }).catch((err) => {
toast.error(err);
});
setSessionToDelete({ show: false, toDelete: null });
}
};
const handleEditChange = (id, value) => {
const newEditedSessions = { ...editedSessions, [id]: value };
setEditedSessions(newEditedSessions);
};
const onKeyUp = (id) => (key) => {
if (key.keyCode === 13) {
performRename(id);
}
};
return (
<MobilePaper>
<Typography component="h3" variant="h5">
Login Sessions
</Typography>
<List>
{sessions.map((session) => {
if (editedSessions.hasOwnProperty(session.id)) {
return (
<ListItem key={session.id}>
<TextField
margin="normal"
variant="standard"
fullWidth
onKeyUp={onKeyUp(session.id)}
value={editedSessions[session.id]}
onChange={(event) => handleEditChange(session.id, event.target.value)}
/>
<ListItemSecondaryAction>
<Button onClick={() => performRename(session.id)}>
<Check />
</Button>
<Button onClick={() => stopEditSession(session.id)}>
<Close />
</Button>
</ListItemSecondaryAction>
</ListItem>
);
} else {
return (
<ListItem key={session.id}>
<ListItemText
primary={session.name}
secondary={
<>
<span>
Valid until{" "}
{DateTime.fromISO(session.valid_until).toLocaleString(
DateTime.DATETIME_FULL
) && "indefinitely"}
,{" "}
</span>
<span>
Last seen on{" "}
{DateTime.fromISO(session.last_seen).toLocaleString(
DateTime.DATETIME_FULL
)}
</span>
</>
}
/>
<ListItemSecondaryAction>
<IconButton onClick={() => editSession(session.id)}>
<Edit />
</IconButton>
<IconButton onClick={() => openDeleteSessionModal(session.id)}>
<Delete />
</IconButton>
</ListItemSecondaryAction>
</ListItem>
);
}
})}
</List>
<Dialog open={sessionToDelete.show} onClose={closeDeleteSessionModal}>
<DialogTitle>Delete Session?</DialogTitle>
<DialogContent>
<DialogContentText>
{sessionToDelete.toDelete !== null
? `Are you sure you want to delete session ${
sessions.find((session) => session.id === sessionToDelete.toDelete)?.name
}`
: null}
</DialogContentText>
</DialogContent>
<DialogActions>
<Button color="secondary" onClick={confirmDeleteSession}>
Yes pls
</Button>
<Button color="primary" onClick={closeDeleteSessionModal}>
No
</Button>
</DialogActions>
</Dialog>
</MobilePaper>
);
}
Example #17
Source File: Vault.tsx From NekoMaid with MIT License | 1 votes |
PermissionDialog: React.FC<{ plugin: Plugin, id: string | undefined, isGroup: boolean, onClose: () => void }> = ({ plugin, id, onClose, isGroup }) => {
const [value, setValue] = useState('')
const [status, setStatus] = useState<boolean | undefined>(false)
const [options, setOptions] = useState<string[]>([])
useEffect(() => {
if (!id) return
setValue('')
setStatus(false)
plugin.emit('vault:getAllPermissions', (it: any) => setOptions(it.sort()))
}, [id])
const queryStatus = useMemo(() => throttle((value: string) => plugin.emit('vault:permission', setStatus, id, value, 0, isGroup), 500), [id, isGroup])
return <Dialog open={!!id} onClose={onClose}>
<DialogTitle>{lang.vault.editorTitle}</DialogTitle>
<DialogContent sx={{ overflow: 'hidden' }}>
<DialogContentText>{lang.vault.permissionInput}: <span className='bold' style={{ }}>
({isGroup ? lang.vault.permissionGroup : minecraft['entity.minecraft.player']}: {id})</span></DialogContentText>
<Autocomplete
freeSolo
options={options}
sx={{ marginTop: 1 }}
inputValue={value}
renderInput={params => <TextField {...params as any} label={lang.vault.permission} />}
onInputChange={(_, it) => {
setValue(it)
setStatus(undefined)
queryStatus(it)
}}
/>
<Box sx={{ display: 'flex', alignItems: 'center', marginTop: 1 }}>
{lang.status}:{status == null
? <CircularProgress size={20} sx={{ margin: '5px' }}/>
: status ? <Check color='success' /> : <Close color='error' />}
{status != null && <Button
disabled={!value}
variant='outlined'
size='small'
onClick={() => plugin.emit('vault:permission', (res: boolean) => {
action(res)
setStatus(undefined)
queryStatus(value)
}, id, value, status ? 2 : 1, isGroup)}
>{lang.vault[status ? 'removePermission' : 'addPermission']}</Button>}
</Box>
</DialogContent>
<DialogActions><Button onClick={onClose}>{minecraft['gui.back']}</Button></DialogActions>
</Dialog>
}