@mui/system#Box TypeScript Examples
The following examples show how to use
@mui/system#Box.
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: AboutPage.tsx From frontend with MIT License | 6 votes |
export default function AboutPage() {
const { t } = useTranslation()
return (
<Layout title={t('about:about.title')} metaDescription={t('about:about.description')}>
<PrinciplesThatUniteUs />
<HowEveryThingBegin />
<Box textAlign="center" m={6}>
<LinkButton color="primary" size="large" variant="contained" href={routes.support}>
{t('nav.about.support-us')}
</LinkButton>
</Box>
</Layout>
)
}
Example #2
Source File: StatFilterCard.tsx From genshin-optimizer with MIT License | 6 votes |
export default function StatFilterCard({ statFilters = {}, setStatFilters, disabled = false }:
{ statFilters: Dict<StatKey, number>, setStatFilters: (object: Dict<StatKey, number>) => void, disabled?: boolean }) {
const { t } = useTranslation("page_character")
const { data } = useContext(DataContext)
const statKeys: StatKey[] = ["atk", "hp", "def", "eleMas", "critRate_", "critDMG_", "heal_", "enerRech_"]
if (data.get(input.weaponType).value !== "catalyst") statKeys.push("physical_dmg_")
const charEle = data.get(input.charEle).value as ElementKey
statKeys.push(`${charEle}_dmg_`)
const remainingKeys = statKeys.filter(key => !(Object.keys(statFilters) as any).some(k => k === key))
const setFilter = useCallback((sKey, min) => setStatFilters({ ...statFilters, [sKey]: min }), [statFilters, setStatFilters],)
return <Box>
<CardLight>
<CardContent sx={{ display: "flex", gap: 1, justifyContent: "space-between" }}>
<Typography>{t`tabOptimize.constraintFilter.title`}</Typography>
<InfoTooltip title={<Typography>{t`tabOptimize.constraintFilter.tooltip`}</Typography>} />
</CardContent>
</CardLight>
<Box display="flex" flexDirection="column" gap={0.5}>
{Object.entries(statFilters).map(([statKey, min]) => {
return <StatFilterItem key={statKey} statKey={statKey} statKeys={remainingKeys} setFilter={setFilter} disabled={disabled} value={min} close={() => {
delete statFilters[statKey]
setStatFilters({ ...statFilters })
}} />
})}
<StatFilterItem value={undefined} close={undefined} statKeys={remainingKeys} setFilter={setFilter} disabled={disabled} />
</Box>
</Box>
}
Example #3
Source File: CheckBoxFilter.tsx From Tachidesk-WebUI with Mozilla Public License 2.0 | 6 votes |
export default function CheckBoxFilter(props: Props) {
const {
state,
name,
position,
group,
updateFilterValue,
update,
} = props;
const [val, setval] = React.useState(state);
const handleChange = (event: { target: { name: any; checked: any; }; }) => {
setval(event.target.checked);
const upd = update.filter((e: {
position: number; group: number | undefined;
}) => !(position === e.position && group === e.group));
updateFilterValue([...upd, { position, state: event.target.checked.toString(), group }]);
};
if (state !== undefined) {
return (
<Box sx={{ display: 'flex', flexDirection: 'column', minWidth: 120 }}>
<FormControlLabel
key={name}
control={(
<Checkbox
name={name}
checked={val}
onChange={handleChange}
/>
)}
label={name}
/>
</Box>
);
}
return (<></>);
}
Example #4
Source File: TabTeambuffs.tsx From genshin-optimizer with MIT License | 6 votes |
export default function TabTeambuffs() {
return <Box display="flex" flexDirection="column" gap={1} alignItems="stretch">
<Grid container spacing={1}>
<Grid item xs={12} md={6} lg={3} sx={{ display: "flex", flexDirection: "column", gap: 1 }}>
<TeamBuffDisplay />
<ResonanceDisplay />
</Grid>
{range(0, 2).map(i => <Grid item xs={12} md={6} lg={3} key={i}>
<TeammateDisplay index={i} />
</Grid>)}
</Grid>
</Box>
}
Example #5
Source File: PageNumber.tsx From Tachidesk-WebUI with Mozilla Public License 2.0 | 6 votes |
export default function PageNumber(props: IProps) {
const { settings, curPage, pageCount } = props;
return (
<Box sx={{
display: settings.showPageNumber ? 'block' : 'none',
position: 'fixed',
bottom: '50px',
right: settings.staticNav ? 'calc((100vw - 325px)/2)' : 'calc((100vw - 25px)/2)',
padding: '2px',
paddingLeft: '4px',
paddingRight: '4px',
textAlign: 'center',
backgroundColor: 'rgba(0, 0, 0, 0.3)',
borderRadius: '10px',
}}
>
{`${curPage + 1} / ${pageCount}`}
</Box>
);
}
Example #6
Source File: StatDisplayComponent.tsx From genshin-optimizer with MIT License | 6 votes |
export default function StatDisplayComponent() {
const { data } = useContext(DataContext)
const sections = getDisplaySections(data)
return <Box sx={{ mr: -1, mb: -1 }}>
<Masonry columns={{ xs: 1, sm: 2, md: 3, xl: 4 }} spacing={1}>
{sections.map(([key, Nodes]) =>
<Section key={key} displayNs={Nodes} sectionKey={key} />)}
</Masonry >
</Box>
}
Example #7
Source File: UpdateChecker.tsx From Tachidesk-WebUI with Mozilla Public License 2.0 | 6 votes |
function Progress({ progress }: IProgressProps) {
return (
<Box sx={{ display: 'grid', placeItems: 'center', position: 'relative' }}>
<CircularProgress variant="determinate" value={progress} />
<Box sx={{ position: 'absolute' }}>
<Typography fontSize="0.8rem">
{`${Math.round(progress)}%`}
</Typography>
</Box>
</Box>
);
}
Example #8
Source File: AdminAppBar.tsx From frontend with MIT License | 6 votes |
export function AdminAppBar({ isOpen, children }: Props) {
return (
<AppBar position="fixed" open={isOpen} sx={{ p: 0, display: 'flex' }}>
<Box
sx={{
display: 'flex',
width: 'calc(100% - 24px)',
position: 'relative',
paddingRight: '16px',
}}>
<Box
sx={{
width: drawerWidth,
height: 64,
position: 'absolute',
alignItems: 'center',
display: 'flex',
justifyContent: 'space-between',
padding: '0 19px 0 24px',
}}>
<Box sx={{ width: 150, display: 'flex' }}>
<Link href={routes.admin.index}>
<Image src={PictureLogo} width={40} height={40} />
</Link>
</Box>
</Box>
{children}
</Box>
</AppBar>
)
}
Example #9
Source File: Manga.tsx From Tachidesk-WebUI with Mozilla Public License 2.0 | 6 votes |
export default function Manga() {
const { setTitle } = useContext(NavbarContext);
useEffect(() => { setTitle('Manga'); }, []); // delegate setting topbar action to MangaDetails
const { id } = useParams<{ id: string }>();
const [manga, setManga] = useState<IManga>();
useEffect(() => {
if (manga === undefined || !manga.freshData) {
client.get(`/api/v1/manga/${id}/?onlineFetch=${manga !== undefined}`)
.then((response) => response.data)
.then((data: IManga) => {
setManga(data);
setTitle(data.title);
});
}
}, [manga]);
return (
<Box sx={{ display: { md: 'flex' }, overflow: 'hidden' }}>
<LoadingPlaceholder
shouldRender={manga !== undefined}
component={MangaDetails}
componentProps={{ manga }}
/>
<ChapterList id={id} />
</Box>
);
}
Example #10
Source File: Wallet.tsx From sapio-studio with Mozilla Public License 2.0 | 6 votes |
export function Wallet(props: { bitcoin_node_manager: BitcoinNodeManager }) {
const dispatch = useDispatch();
const idx = useSelector(selectWalletTab);
const handleChange = (_: any, idx: TabIndexes) => {
dispatch(switch_wallet_tab(idx));
};
return (
<div className="Wallet">
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
<Tabs
value={idx}
onChange={handleChange}
aria-label="basic tabs example"
>
<Tab label="Send"></Tab>
<Tab label="Send History"></Tab>
<Tab label="Workspaces"></Tab>
<Tab label="Contracts"></Tab>
</Tabs>
</Box>
<Box sx={{ overflowY: 'scroll', height: '100%' }}>
<WalletSend value={0} idx={idx} {...props}></WalletSend>
<WalletHistory value={1} idx={idx} {...props}></WalletHistory>
<Workspaces value={2} idx={idx}></Workspaces>
<ContractList value={3} idx={idx}></ContractList>
</Box>
</div>
);
}
Example #11
Source File: EmptyView.tsx From Tachidesk-WebUI with Mozilla Public License 2.0 | 6 votes |
export default function EmptyView({ message, messageExtra }: IProps) {
const theme = useTheme();
const isMobileWidth = useMediaQuery(theme.breakpoints.down('sm'));
return (
<Box sx={{
position: 'absolute',
left: `calc(50% + ${isMobileWidth ? '0px' : theme.spacing(8 / 2)})`,
top: '50%',
transform: 'translate(-50%, -50%)',
textAlign: 'center',
}}
>
<Typography variant="h3" gutterBottom>
{getRandomErrorFace()}
</Typography>
<Typography variant="h5">
{message}
</Typography>
{messageExtra}
</Box>
);
}
Example #12
Source File: hero.tsx From usehooks-ts with MIT License | 5 votes |
Root = styled(Box)(({ theme }) => ({
backgroundColor: theme.palette.background.default,
padding: theme.spacing(12, 0, 10),
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
}))
Example #13
Source File: BuildDisplayItem.tsx From genshin-optimizer with MIT License | 5 votes |
//for displaying each artifact build
export default function BuildDisplayItem({ index, compareBuild, extraButtons, disabled }: BuildDisplayItemProps) {
const { database } = useContext(DatabaseContext)
const dataContext = useContext(DataContext)
const { character, data, oldData, mainStatAssumptionLevel } = dataContext
const artifactSheets = usePromise(ArtifactSheet.getAll, [])
const [newOld, setNewOld] = useState(undefined as NewOld | undefined)
const close = useCallback(() => setNewOld(undefined), [setNewOld],)
const equipBuild = useCallback(() => {
if (!window.confirm("Do you want to equip this build to this character?")) return
const newBuild = Object.fromEntries(allSlotKeys.map(s => [s, data.get(input.art[s].id).value])) as Record<SlotKey, string>
database.equipArtifacts(character.key, newBuild)
database.setWeaponLocation(data.get(input.weapon.id).value!, character.key)
}, [character, data, database])
if (!character || !artifactSheets || !oldData) return null
const currentlyEquipped = allSlotKeys.every(slotKey => data.get(input.art[slotKey].id).value === oldData.get(input.art[slotKey].id).value) && data.get(input.weapon.id).value === oldData.get(input.weapon.id).value
const statProviderContext = { ...dataContext }
if (!compareBuild) statProviderContext.oldData = undefined
const setToSlots: Partial<Record<ArtifactSetKey, SlotKey[]>> = {}
allSlotKeys.forEach(slotKey => {
const set = data.get(input.art[slotKey].set).value as ArtifactSetKey | undefined
if (!set) return
if (setToSlots[set]) setToSlots[set]!.push(slotKey)
else setToSlots[set] = [slotKey]
})
return <CardLight>
<Suspense fallback={<Skeleton variant="rectangular" width="100%" height={600} />}>
{newOld && <CompareArtifactModal newOld={newOld} mainStatAssumptionLevel={mainStatAssumptionLevel} onClose={close} />}
<CardContent>
<Box display="flex" gap={1} sx={{ pb: 1 }} flexWrap="wrap">
{index !== undefined && <SqBadge color="info"><Typography><strong>#{index + 1}{currentlyEquipped ? " (Equipped)" : ""}</strong></Typography></SqBadge>}
{(Object.entries(setToSlots) as [ArtifactSetKey, SlotKey[]][]).sort(([k1, slotarr1], [k2, slotarr2]) => slotarr2.length - slotarr1.length).map(([key, slotarr]) =>
<Box key={key}><SqBadge color={currentlyEquipped ? "success" : "primary"} ><Typography >
{slotarr.map(slotKey => artifactSlotIcon(slotKey))} {artifactSheets?.[key].name ?? ""}
</Typography></SqBadge></Box>
)}
<Box sx={{ flexGrow: 1, display: "flex", justifyContent: "flex-end" }}>
</Box>
<Button size='small' color="success" onClick={equipBuild} disabled={disabled || currentlyEquipped}>Equip Build</Button>
{extraButtons}
</Box>
<Grid container spacing={1} sx={{ pb: 1 }}>
<Grid item xs={6} sm={4} md={3} lg={2}>
<WeaponCardNano showLocation weaponId={data.get(input.weapon.id).value} />
</Grid>
{allSlotKeys.map(slotKey =>
<Grid item xs={6} sm={4} md={3} lg={2} key={slotKey} >
<ArtifactCardNano showLocation slotKey={slotKey} artifactId={data.get(input.art[slotKey].id).value} mainStatAssumptionLevel={mainStatAssumptionLevel} onClick={() => {
const oldId = character.equippedArtifacts[slotKey]
const newId = data.get(input.art[slotKey].id).value!
setNewOld({ oldId: oldId !== newId ? oldId : undefined, newId })
}} />
</Grid>)}
</Grid>
<DataContext.Provider value={statProviderContext}>
<StatDisplayComponent />
</DataContext.Provider>
</CardContent>
</Suspense>
</CardLight>
}
Example #14
Source File: TriStateFilter.tsx From Tachidesk-WebUI with Mozilla Public License 2.0 | 5 votes |
export default function TriStateFilter(props: Props) {
const {
state,
name,
position,
group,
updateFilterValue,
update,
} = props;
const [val, setval] = React.useState({
[name]: state,
});
const handleChange = (checked: boolean | null | undefined) => {
const tmp = val;
if (checked !== undefined) {
tmp[name] = checked ? 1 : 2;
} else {
delete tmp[name];
}
setval({
...tmp,
});
const upd = update.filter((e: {
position: number; group: number | undefined;
}) => !(position === e.position && group === e.group));
updateFilterValue([...upd, {
position,
state: (tmp[name] === undefined ? 0 : tmp[name]).toString(),
group,
}]);
};
if (state !== undefined) {
let check;
if (val[name] !== 0) {
check = val[name] === 1;
} else {
check = undefined;
}
return (
<Box sx={{ marginLeft: 3 }}>
<FormControlLabel
key={name}
control={(
<ThreeStateCheckbox name="Unread" checked={check} onChange={(checked) => handleChange(checked)} />
)}
label={name}
/>
</Box>
);
}
return (<></>);
}
Example #15
Source File: thanks.tsx From usehooks-ts with MIT License | 5 votes |
Thanks = () => {
const [viewedCount, setViewedCount] = useLocalStorage(
'1k-stars-viewed-count',
0,
)
const [open, setOpen] = useState(viewedCount < 2)
const { width, height } = useWindowSize()
const handleClose = () => setOpen(false)
useEffect(() => {
if (open) setViewedCount(viewedCount + 1)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [open])
if (viewedCount > 1) {
return null
}
return (
<>
{open && (
<Box
position="absolute"
left="0"
top="0"
zIndex={1500}
onClick={handleClose}
>
<Confetti width={width} height={height} />
</Box>
)}
<Snackbar
open={open}
onClose={handleClose}
anchorOrigin={{
vertical: 'top',
horizontal: 'center',
}}
ContentProps={{
message: `1k+ Stargazers on usehooks-ts, thanks! ?`,
className: classes.content,
}}
action={
<IconButton
size="small"
aria-label="close"
color="inherit"
onClick={handleClose}
>
<CloseIcon fontSize="small" />
</IconButton>
}
/>
</>
)
}
Example #16
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 #17
Source File: PriceGranularityComponent.tsx From professor-prebid with Apache License 2.0 | 5 votes |
PriceGranularityComponent = ({ priceGranularity, customPriceBucket }: IPriceGranularityComponentProps) => {
const [type, setType] = React.useState<string>();
const [rows, setRows] = React.useState<IPrebidConfigPriceBucket[]>([]);
useEffect(() => {
const type = priceGranularity;
setType(type);
const rows = defaultBuckets[type] || customPriceBucket?.buckets || [];
setRows(rows);
}, [priceGranularity, customPriceBucket?.buckets]);
logger.log(`[PopUp][PriceGranularityComponent]: render `, type, rows);
return (
<Box sx={{ backgroundColor: 'text.disabled', p: 0.25, borderRadius: 1 }}>
<Grid container spacing={0.2}>
<Grid item xs={3}>
<Paper sx={{ height: 1, borderRadius: 1, display: 'flex', justifyContent: 'center' }}>
<Typography variant="h3">Bucket</Typography>
</Paper>
</Grid>
<Grid item xs={3}>
<Paper sx={{ height: 1, borderRadius: 1, display: 'flex', justifyContent: 'center' }}>
<Typography variant="h3">Precision</Typography>
</Paper>
</Grid>
<Grid item xs={2}>
<Paper sx={{ height: 1, borderRadius: 1, display: 'flex', justifyContent: 'center' }}>
<Typography variant="h3">Min</Typography>
</Paper>
</Grid>
<Grid item xs={2}>
<Paper sx={{ height: 1, borderRadius: 1, display: 'flex', justifyContent: 'center' }}>
<Typography variant="h3">Max</Typography>
</Paper>
</Grid>
<Grid item xs={2}>
<Paper sx={{ height: 1, borderRadius: 1, display: 'flex', justifyContent: 'center' }}>
<Typography variant="h3">Increment</Typography>
</Paper>
</Grid>
{rows.map((row, index) => {
return (
<React.Fragment key={index}>
<Grid xs={3} item>
<Paper sx={{ height: 1, borderRadius: 1, display: 'flex', justifyContent: 'center' }}>
<Typography variant="body1">
{type} #{index + 1}
</Typography>
</Paper>
</Grid>
<Grid xs={3} item>
<Paper sx={{ height: 1, borderRadius: 1, display: 'flex', justifyContent: 'center' }}>
<Typography variant="body1">{row.precision || 2}</Typography>
</Paper>
</Grid>
<Grid xs={2} item>
<Paper sx={{ height: 1, borderRadius: 1, display: 'flex', justifyContent: 'center' }}>
<Typography variant="body1">{row.min}</Typography>
</Paper>
</Grid>
<Grid xs={2} item>
<Paper sx={{ height: 1, borderRadius: 1, display: 'flex', justifyContent: 'center' }}>
<Typography variant="body1">{row.max}</Typography>
</Paper>
</Grid>
<Grid xs={2} item>
<Paper sx={{ height: 1, borderRadius: 1, display: 'flex', justifyContent: 'center' }}>
<Typography variant="body1">{row.increment}</Typography>
</Paper>
</Grid>
</React.Fragment>
);
})}
</Grid>
</Box>
);
}
Example #18
Source File: WalletSendForm.tsx From sapio-studio with Mozilla Public License 2.0 | 5 votes |
export function WalletSendForm(props: {
bitcoin_node_manager: BitcoinNodeManager;
set_params: (a: number, b: string) => void;
}) {
const [address, setAddress] = React.useState<string | null>(null);
const get_address = async () => {
try {
const address = await props.bitcoin_node_manager.get_new_address();
setAddress(address);
} catch (err) {
// console.error(err);
setAddress(null);
}
};
const handleSubmit: React.FormEventHandler<HTMLFormElement> = async (
event
) => {
event.preventDefault();
const amt = event.currentTarget.amount.value;
const to = event.currentTarget.address.value;
props.set_params(amt, to);
event.currentTarget.reset();
};
return (
<div className="WalletSpendInner">
<div></div>
<div>
<AvailableBalance
bitcoin_node_manager={props.bitcoin_node_manager}
/>
<Typography>{address && `New Address: ${address}`}</Typography>
<Button onClick={() => get_address()}>Get Address</Button>
<Box
component="form"
noValidate
autoComplete="off"
onSubmit={handleSubmit}
>
<TextField
label="Address"
name="address"
type="text"
required={true}
size="small"
/>
<TextField
label="Amount"
name="amount"
type="number"
required={true}
size="small"
/>
<Button type="submit">Send</Button>
</Box>
</div>
<div></div>
</div>
);
}
Example #19
Source File: SelectFilter.tsx From Tachidesk-WebUI with Mozilla Public License 2.0 | 5 votes |
function hasSelect(
values: Selected[],
name: string,
state: number,
position: number,
updateFilterValue: Function,
update: any,
group?: number,
) {
const [val, setval] = React.useState(state);
if (values) {
const handleChange = (event: { target: { name: any; value: any; }; }) => {
const vall = values.map((e) => e.displayname).indexOf(`${event.target.value}`);
setval(vall);
const upd = update.filter((e: {
position: number; group: number | undefined;
}) => !(position === e.position && group === e.group));
updateFilterValue([...upd, { position, state: vall.toString(), group }]);
};
const rett = values.map((e: Selected) => (
<MenuItem
key={`${name} ${e.displayname}`}
value={e.displayname}
>
{
e.displayname
}
</MenuItem>
));
return (
<Box key={name} sx={{ display: 'flex', flexDirection: 'column', minWidth: 120 }}>
<FormControl fullWidth>
<InputLabel sx={{ margin: '10px 0 10px 0' }}>
{name}
</InputLabel>
<Select
name={name}
value={values[val].displayname}
label={name}
onChange={handleChange}
autoWidth
sx={{ margin: '10px 0 10px 0' }}
>
{rett}
</Select>
</FormControl>
</Box>
);
}
return (<></>);
}
Example #20
Source File: GamDetailsComponent.tsx From professor-prebid with Apache License 2.0 | 4 votes |
GamDetailsComponent = ({ elementId, inPopOver }: IGamDetailComponentProps): JSX.Element => {
const [networktId, setNetworkId] = useState<string>(null);
const [slotElementId, setSlotElementId] = useState<string>(null);
const [creativeId, setCreativeId] = useState<number>(null);
const [lineItemId, setLineItemId] = useState<number>(null);
const [slotAdUnitPath, setSlotAdUnitPath] = useState<string>(null);
const [slotTargeting, setSlotTargeting] = useState<{ key: string; value: string; id: number }[]>(null);
const [slotResponseInfo, setSlotResponseInfo] = useState<googletag.ResponseInformation>(null);
useEffect(() => {
if (googletag && typeof googletag?.pubads === 'function') {
const pubads = googletag.pubads();
const slots = pubads.getSlots();
const slot = slots.find((slot) => slot.getSlotElementId() === elementId) || slots.find((slot) => slot.getAdUnitPath() === elementId);
if (slot) {
setSlotElementId(slot.getSlotElementId());
setSlotAdUnitPath(slot.getAdUnitPath());
setNetworkId(slot.getAdUnitPath()?.split('/')[1]);
setSlotTargeting((slot as any).getTargetingKeys().map((key: string, id: number) => ({ key, value: slot.getTargeting(key), id })));
setSlotResponseInfo(slot.getResponseInformation());
if (slotResponseInfo) {
const { creativeId, lineItemId, sourceAgnosticCreativeId, sourceAgnosticLineItemId } = slotResponseInfo as any;
setCreativeId(creativeId || sourceAgnosticCreativeId);
setLineItemId(lineItemId || sourceAgnosticLineItemId);
}
const eventHandler = (event: googletag.events.SlotRenderEndedEvent | googletag.events.SlotResponseReceived) => {
if (event.slot.getSlotElementId() === slot.getSlotElementId()) {
setSlotResponseInfo(slot.getResponseInformation());
}
};
pubads.addEventListener('slotResponseReceived', eventHandler);
pubads.addEventListener('slotRenderEnded', eventHandler);
return () => {
pubads.removeEventListener('slotResponseReceived', eventHandler);
pubads.removeEventListener('slotRenderEnded', eventHandler);
};
}
}
}, [elementId, inPopOver, slotResponseInfo]);
return (
<React.Fragment>
{lineItemId && (
<Grid item>
<Paper elevation={1} sx={{ p: inPopOver ? 1 : 0.5 }}>
<Typography component={'span'} variant="h4">
LineItem-ID:{' '}
</Typography>
<Typography component={'span'} variant="body1" sx={{ '& a': { color: 'secondary.main' } }}>
<a
href={`https://admanager.google.com/${networktId}#delivery/LineItemDetail/lineItemId=${lineItemId}`}
rel="noreferrer"
target="_blank"
>
{lineItemId}
</a>
</Typography>
</Paper>
</Grid>
)}
{creativeId && (
<Grid item>
<Paper elevation={1} sx={{ p: inPopOver ? 1 : 0.5 }}>
<Typography variant="h4" component={'span'}>
Creative-ID:{' '}
</Typography>
<Typography component={'span'} variant="body1" sx={{ '& a': { color: 'secondary.main' } }}>
<a
href={`https://admanager.google.com/${networktId}#delivery/CreativeDetail/creativeId=${creativeId}`}
rel="noreferrer"
target="_blank"
>
{creativeId}
</a>
</Typography>
</Paper>
</Grid>
)}
{slotAdUnitPath && (
<Grid item>
<Paper elevation={1} sx={{ p: inPopOver ? 1 : 0.5 }}>
<Typography variant="h4" component={'span'}>
AdUnit Path:{' '}
</Typography>
<Typography variant="body1" component={'span'}>
{slotAdUnitPath}
</Typography>
</Paper>
</Grid>
)}
{slotElementId && (
<Grid item>
<Paper elevation={1} sx={{ p: inPopOver ? 1 : 0.5 }}>
<Typography variant="h4" component={'span'}>
Element-ID:{' '}
</Typography>
<Typography variant="body1" component={'span'}>
{slotElementId}
</Typography>
</Paper>
</Grid>
)}
{inPopOver && (
<React.Fragment>
<Grid item xs={12}>
<Grid container direction={'column'} spacing={1}>
{slotResponseInfo && (
<Grid item>
<Paper elevation={1} sx={{ p: inPopOver ? 1 : 0.5 }}>
<Typography sx={{ fontWeight: 'bold' }}>Response-Info:</Typography>
<ReactJson
name={false}
src={slotResponseInfo}
collapsed={false}
enableClipboard={false}
displayObjectSize={true}
displayDataTypes={false}
sortKeys={false}
quotesOnKeys={false}
indentWidth={2}
collapseStringsAfterLength={100}
style={{
fontSize: '12px',
fontFamily: '"Roboto","Helvetica","Arial",sans-serif',
fontWeight: 400,
lineHeight: 1.5,
letterSpacing: '0.00938em',
borderRadius: '4px',
}}
/>
</Paper>
</Grid>
)}
{slotTargeting && (
<Grid item xs={12}>
<Paper elevation={1} sx={{ p: 1 }}>
<Typography sx={{ fontWeight: 'bold' }}>Targeting:</Typography>
<Box sx={{ display: 'flex', flexGrow: 1 }}>
<DataGrid
density="compact"
rows={slotTargeting}
columns={[
{ field: 'key', headerName: 'Key', align: 'left', width: 200 },
{ field: 'value', headerName: 'Value', align: 'left', width: 200 },
]}
disableSelectionOnClick
autoHeight
hideFooter
/>
</Box>
</Paper>
</Grid>
)}
</Grid>
</Grid>
</React.Fragment>
)}
</React.Fragment>
);
}
Example #21
Source File: ChapterCard.tsx From Tachidesk-WebUI with Mozilla Public License 2.0 | 4 votes |
export default function ChapterCard(props: IProps) {
const theme = useTheme();
const {
chapter, triggerChaptersUpdate, downloadStatusString, showChapterNumber,
} = props;
const dateStr = chapter.uploadDate && new Date(chapter.uploadDate).toLocaleDateString();
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
// prevent parent tags from getting the event
event.stopPropagation();
event.preventDefault();
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const sendChange = (key: string, value: any) => {
handleClose();
const formData = new FormData();
formData.append(key, value);
if (key === 'read') { formData.append('lastPageRead', '1'); }
client.patch(`/api/v1/manga/${chapter.mangaId}/chapter/${chapter.index}`, formData)
.then(() => triggerChaptersUpdate());
};
const downloadChapter = () => {
client.get(`/api/v1/download/${chapter.mangaId}/chapter/${chapter.index}`);
handleClose();
};
const deleteChapter = () => {
client.delete(`/api/v1/manga/${chapter.mangaId}/chapter/${chapter.index}`)
.then(() => triggerChaptersUpdate());
handleClose();
};
const readChapterColor = theme.palette.mode === 'dark' ? '#acacac' : '#b0b0b0';
return (
<>
<li>
<Card
sx={{
margin: '10px',
':hover': {
backgroundColor: 'action.hover',
transition: 'background-color 100ms cubic-bezier(0.4, 0, 0.2, 1) 0ms',
cursor: 'pointer',
},
':active': {
backgroundColor: 'action.selected',
transition: 'background-color 100ms cubic-bezier(0.4, 0, 0.2, 1) 0ms',
},
}}
>
<Link
to={`/manga/${chapter.mangaId}/chapter/${chapter.index}`}
style={{
textDecoration: 'none',
color: chapter.read ? readChapterColor : theme.palette.text.primary,
}}
>
<CardContent
sx={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
padding: 2,
}}
>
<Box sx={{ display: 'flex' }}>
<div style={{ display: 'flex', flexDirection: 'column' }}>
<Typography variant="h5" component="h2">
<span style={{ color: theme.palette.primary.dark }}>
{chapter.bookmarked && <BookmarkIcon />}
</span>
{ showChapterNumber ? `Chapter ${chapter.chapterNumber}` : chapter.name}
</Typography>
<Typography variant="caption" display="block" gutterBottom>
{chapter.scanlator}
{chapter.scanlator && ' '}
{dateStr}
{downloadStatusString}
</Typography>
</div>
</Box>
<IconButton aria-label="more" onClick={handleClick} size="large">
<MoreVertIcon />
</IconButton>
</CardContent>
</Link>
<Menu
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
{downloadStatusString.endsWith('Downloaded')
&& <MenuItem onClick={deleteChapter}>Delete</MenuItem>}
{downloadStatusString.length === 0
&& <MenuItem onClick={downloadChapter}>Download</MenuItem> }
<MenuItem onClick={() => sendChange('bookmarked', !chapter.bookmarked)}>
{chapter.bookmarked && 'Remove bookmark'}
{!chapter.bookmarked && 'Bookmark'}
</MenuItem>
<MenuItem onClick={() => sendChange('read', !chapter.read)}>
{`Mark as ${chapter.read ? 'unread' : 'read'}`}
</MenuItem>
<MenuItem onClick={() => sendChange('markPrevRead', true)}>
Mark previous as Read
</MenuItem>
</Menu>
</Card>
</li>
</>
);
}
Example #22
Source File: DonationTable.tsx From frontend with MIT License | 4 votes |
function DonationTable({ donations }: DonationTableProps) {
const { t, i18n } = useTranslation()
const [fromDate, setFromDate] = React.useState<Date | null>(null)
const [toDate, setToDate] = React.useState<Date | null>(null)
const [monthly, setMonthly] = React.useState(true)
const [oneTime, setOneTime] = React.useState(true)
const filteredByTypeDonations = useMemo(() => {
if (monthly && oneTime) {
return donations
}
if (!monthly && !oneTime) {
return []
}
if (monthly) {
return donations?.filter((d) => d.type !== 'donation')
}
if (oneTime) {
return donations?.filter((d) => d.type === 'donation')
}
return donations
}, [donations, monthly, oneTime])
const filteredDonations = useMemo(() => {
if (!fromDate && !toDate) {
return filteredByTypeDonations
}
if (fromDate && toDate) {
return filteredByTypeDonations?.filter((d) => {
const createdAtDate = parseISO(d.createdAt)
return isAfter(createdAtDate, fromDate) && isBefore(createdAtDate, toDate)
})
}
if (fromDate) {
return filteredByTypeDonations?.filter((d) => {
const createdAtDate = parseISO(d.createdAt)
return isAfter(createdAtDate, fromDate)
})
}
if (toDate) {
return filteredByTypeDonations?.filter((d) => {
const createdAtDate = parseISO(d.createdAt)
return isBefore(createdAtDate, toDate)
})
}
}, [filteredByTypeDonations, fromDate, toDate])
return (
<Card sx={{ padding: theme.spacing(2) }}>
<Grid container alignItems={'flex-start'} spacing={theme.spacing(2)}>
<Grid item xs={6} sm={3}>
<CheckboxLabel>{t('profile:donations.oneTime')}</CheckboxLabel>
<Checkbox
onChange={(e, checked) => setOneTime(checked)}
checked={oneTime}
name="oneTime"
/>
</Grid>
<Grid item xs={6} sm={3}>
<CheckboxLabel>{t('profile:donations.monthly')}</CheckboxLabel>
<Checkbox
onChange={(e, checked) => setMonthly(checked)}
checked={monthly}
name="monthly"
/>
</Grid>
<LocalizationProvider
locale={i18n.language === 'bg' ? bg : enUS}
dateAdapter={AdapterDateFns}>
<Grid item xs={12} sm={3}>
<DatePicker
label={t('profile:donations.fromDate')}
value={fromDate}
onChange={setFromDate}
renderInput={(params) => <TextField size="small" {...params} />}
/>
</Grid>
<Grid item xs={12} sm={3}>
<DatePicker
label={t('profile:donations.toDate')}
value={toDate}
onChange={setToDate}
renderInput={(params) => <TextField size="small" {...params} />}
/>
</Grid>
</LocalizationProvider>
</Grid>
{filteredDonations?.length ? (
<TableContainer>
<Table sx={{ minWidth: 650, backgroundColor: 'white' }} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>№</TableCell>
<TableCell>{t('profile:donations.date')}</TableCell>
<TableCell>{t('profile:donations.type')}</TableCell>
<TableCell>{t('profile:donations.cause')}</TableCell>
<TableCell>{t('profile:donations.amount')}</TableCell>
<TableCell>{t('profile:donations.certificate')}</TableCell>
</TableRow>
</TableHead>
<TableBody>
{filteredDonations.map((donation, index) => (
<TableRow key={index} sx={{ '&:last-child td, &:last-child th': { border: 0 } }}>
<TableCell component="th" scope="row">
{index + 1}
</TableCell>
<TableCell>
{format(parseISO(donation.createdAt), 'd.LL.yyyy', {
locale: i18n.language === 'bg' ? bg : enUS,
})}
</TableCell>
<TableCell>
<Avatar sx={{ background: darken(theme.palette.secondary.main, 0.175) }}>
<StarIcon />
</Avatar>
</TableCell>
<TableCell>{donation.targetVault.campaign.title}</TableCell>
<TableCell>{money(donation.amount)}</TableCell>
<TableCell>
<Button variant="outlined" disabled={donation.status != 'succeeded'}>
<Link target="_blank" href={routes.donation.viewCertificate(donation.id)}>
{t('profile:donations.download')} <ArrowForwardIcon />
</Link>
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
) : (
<Box sx={{ fontSize: 20, mt: 4 }}>Към момента няма направени дарения</Box>
)}
</Card>
)
}
Example #23
Source File: ChapterList.tsx From Tachidesk-WebUI with Mozilla Public License 2.0 | 4 votes |
export default function ChapterList(props: IProps) {
const { id } = props;
const [chapters, triggerChaptersUpdate, noChaptersFound] = useFetchChapters(id);
const [firstUnreadChapter, setFirstUnreadChapter] = useState<IChapter>();
const [filteredChapters, setFilteredChapters] = useState<IChapter[]>([]);
// eslint-disable-next-line max-len
const [options, optionsDispatch] = useReducerLocalStorage<ChapterListOptions, ChapterOptionsReducerAction>(
chapterOptionsReducer, `${id}filterOptions`, defaultChapterOptions,
);
const [, setWsClient] = useState<WebSocket>();
const [{ queue }, setQueueState] = useState<IQueue>(initialQueue);
useEffect(() => {
const wsc = new WebSocket(`${baseWebsocketUrl}/api/v1/downloads`);
wsc.onmessage = (e) => {
const data = JSON.parse(e.data) as IQueue;
setQueueState(data);
};
setWsClient(wsc);
return () => wsc.close();
}, []);
useEffect(() => {
triggerChaptersUpdate();
}, [queue.length]);
const downloadStatusStringFor = useCallback((chapter: IChapter) => {
let rtn = '';
if (chapter.downloaded) {
rtn = ' • Downloaded';
}
queue.forEach((q) => {
if (chapter.index === q.chapterIndex && chapter.mangaId === q.mangaId) {
rtn = ` • Downloading (${(q.progress * 100).toFixed(2)}%)`;
}
});
return rtn;
}, [queue]);
useEffect(() => {
const filtered = filterAndSortChapters(chapters, options);
setFilteredChapters(filtered);
setFirstUnreadChapter(findFirstUnreadChapter(filtered));
}, [options, chapters]);
useEffect(() => {
if (noChaptersFound) {
makeToast('No chapters found', 'warning');
}
}, [noChaptersFound]);
if (chapters.length === 0 || noChaptersFound) {
return (
<div style={{
margin: '10px auto',
display: 'flex',
justifyContent: 'center',
}}
>
<CircularProgress thickness={5} />
</div>
);
}
return (
<>
<Stack direction="column">
<Box sx={{
display: 'flex', justifyContent: 'space-between', px: 1.5, mt: 1,
}}
>
<Typography variant="h5">
{`${filteredChapters.length} Chapters`}
</Typography>
<ChapterOptions options={options} optionsDispatch={optionsDispatch} />
</Box>
<CustomVirtuoso
style={{ // override Virtuoso default values and set them with class
height: 'undefined',
// 900 is the md breakpoint in MUI
overflowY: window.innerWidth < 900 ? 'visible' : 'auto',
}}
totalCount={filteredChapters.length}
itemContent={(index:number) => (
<ChapterCard
showChapterNumber={options.showChapterNumber}
chapter={filteredChapters[index]}
downloadStatusString={downloadStatusStringFor(filteredChapters[index])}
triggerChaptersUpdate={triggerChaptersUpdate}
/>
)}
useWindowScroll={window.innerWidth < 900}
overscan={window.innerHeight * 0.5}
/>
</Stack>
{firstUnreadChapter && <ResumeFab chapter={firstUnreadChapter} mangaId={id} />}
</>
);
}
Example #24
Source File: WidgetsSidebar.tsx From fluttertemplates.dev with MIT License | 4 votes |
function SingleSubGroupRenderer(props: SingleSubGroupRendererProps) {
const theme = useTheme();
const [expanded, setExpanded] = useState(false);
const [isSelected, setIsSelected] = useState(false);
const handleChange = () => {
setExpanded(!expanded);
};
useEffect(() => {
setExpanded(props.selectedSubGroup?.id === props.subgroup.id);
setIsSelected(props.selectedSubGroup?.id === props.subgroup.id);
}, [props.selectedSubGroup]);
return (
<>
<Grid
container
style={{
borderRadius: `0 1rem 1rem 0`,
backgroundColor: isSelected
? `${theme.palette.secondary.main}10`
: "",
}}
>
<Box sx={{ flexGrow: 1 }}>
<Link
href={`/widgets/${props.subgroup.id}`}
replace
key={`sub_group_${props.subgroup.id}`}
>
<a>
<ListItem
button
style={{
borderRadius: "0 1rem 1rem 0",
}}
>
<Typography
variant="body2"
style={{
color: isSelected ? theme.palette.secondary.main : "",
}}
>
{props.subgroup.title}
</Typography>
</ListItem>
</a>
</Link>
</Box>
<Grid item>
<IconButton onClick={() => handleChange()}>
{expanded ? <ExpandLess /> : <ExpandMore />}
</IconButton>
</Grid>
</Grid>
<AnimatePresence initial={false}>
{expanded && (
<motion.section
key="content"
initial="collapsed"
animate="open"
exit="collapsed"
variants={{
open: { opacity: 1, height: "auto" },
collapsed: { opacity: 0, height: 0 },
}}
>
<div
style={{
marginLeft: "1rem",
borderRadius: "0 0 1rem 1rem",
}}
>
{props.subgroup.widgets.map((widget, index) => (
<Link
href={
isSelected
? `#${widget.id.split("/").slice(-1)[0]}`
: `/widgets/${props.subgroup.id}#${
widget.id.split("/").slice(-1)[0]
}`
}
replace={!isSelected}
scroll={true}
key={`sub_group_${props.subgroup.id}_widget_${index}`}
>
<a>
<ListItem
button
style={{
borderRadius: "1rem",
}}
>
<Typography variant="body2">
{index + 1}. {widget.title}
</Typography>
</ListItem>
</a>
</Link>
))}
</div>
</motion.section>
)}
</AnimatePresence>
</>
);
}
Example #25
Source File: Updates.tsx From Tachidesk-WebUI with Mozilla Public License 2.0 | 4 votes |
export default function Updates() {
const history = useHistory();
const { setTitle, setAction } = useContext(NavbarContext);
const [updateEntries, setUpdateEntries] = useState<IMangaChapter[]>([]);
const [hasNextPage, setHasNextPage] = useState(true);
const [fetched, setFetched] = useState(false);
const [lastPageNum, setLastPageNum] = useState(0);
const [serverAddress] = useLocalStorage<String>('serverBaseURL', '');
const [useCache] = useLocalStorage<boolean>('useCache', true);
const [, setWsClient] = useState<WebSocket>();
const [{ queue }, setQueueState] = useState<IQueue>(initialQueue);
useEffect(() => {
const wsc = new WebSocket(`${baseWebsocketUrl}/api/v1/downloads`);
wsc.onmessage = (e) => {
const data = JSON.parse(e.data) as IQueue;
setQueueState(data);
};
setWsClient(wsc);
return () => wsc.close();
}, []);
useEffect(() => {
setTitle('Updates');
setAction(<></>);
}, []);
useEffect(() => {
if (hasNextPage) {
client.get(`/api/v1/update/recentChapters/${lastPageNum}`)
.then((response) => response.data)
.then(({ hasNextPage: fetchedHasNextPage, page }: PaginatedList<IMangaChapter>) => {
setUpdateEntries([
...updateEntries,
...page,
]);
setHasNextPage(fetchedHasNextPage);
setFetched(true);
});
}
}, [lastPageNum]);
const lastEntry = useRef<HTMLDivElement>(null);
const scrollHandler = () => {
if (lastEntry.current) {
const rect = lastEntry.current.getBoundingClientRect();
if (((rect.y + rect.height) / window.innerHeight < 2) && hasNextPage) {
setLastPageNum(lastPageNum + 1);
}
}
};
useEffect(() => {
window.addEventListener('scroll', scrollHandler, true);
return () => {
window.removeEventListener('scroll', scrollHandler, true);
};
}, [hasNextPage, updateEntries]);
if (!fetched) { return <LoadingPlaceholder />; }
if (fetched && updateEntries.length === 0) { return <EmptyView message="You don't have any updates yet." />; }
const downloadStatusStringFor = (chapter: IChapter) => {
let rtn = '';
if (chapter.downloaded) {
rtn = ' • Downloaded';
}
queue.forEach((q) => {
if (chapter.index === q.chapterIndex && chapter.mangaId === q.mangaId) {
rtn = ` • Downloading (${(q.progress * 100).toFixed(2)}%)`;
}
});
return rtn;
};
const downloadChapter = (chapter: IChapter) => {
client.get(`/api/v1/download/${chapter.mangaId}/chapter/${chapter.index}`);
};
return (
<>
{groupByDate(updateEntries).map((dateGroup) => (
<div key={dateGroup[0]}>
<Typography
variant="h5"
sx={{
ml: 3,
my: 2,
fontWeight: 700,
}}
>
{dateGroup[0]}
</Typography>
{dateGroup[1].map(({ item: { chapter, manga }, globalIdx }) => (
<Card
ref={globalIdx === updateEntries.length - 1 ? lastEntry : undefined}
key={globalIdx}
sx={{
margin: '10px',
'&:hover': {
backgroundColor: 'action.hover',
transition: 'background-color 100ms cubic-bezier(0.4, 0, 0.2, 1) 0ms',
},
'&:active': {
backgroundColor: 'action.selected',
transition: 'background-color 100ms cubic-bezier(0.4, 0, 0.2, 1) 0ms',
},
}}
onClick={() => history.push(`/manga/${chapter.mangaId}/chapter/${chapter.index}`)}
>
<CardContent sx={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
padding: 2,
}}
>
<Box sx={{ display: 'flex' }}>
<Avatar
variant="rounded"
sx={{
width: 56,
height: 56,
flex: '0 0 auto',
marginRight: 2,
imageRendering: 'pixelated',
}}
src={`${serverAddress}${manga.thumbnailUrl}?useCache=${useCache}`}
/>
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
<Typography variant="h5" component="h2">
{manga.title}
</Typography>
<Typography variant="caption" display="block" gutterBottom>
{chapter.name}
{downloadStatusStringFor(chapter)}
</Typography>
</Box>
</Box>
{downloadStatusStringFor(chapter) === ''
&& (
<IconButton
onClick={(e) => {
downloadChapter(chapter);
// prevent parent tags from getting the event
e.stopPropagation();
}}
size="large"
>
<DownloadIcon />
</IconButton>
)}
</CardContent>
</Card>
))}
</div>
))}
</>
);
}