Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | 1x 1x 1x 1x 1x 1x 9x 1x 1x 5x 5x 5x 5x 5x 5x 4x 4x 4x 5x 5x 5x 30x | import { Close as CloseIcon } from '@mui/icons-material'; import { AppBar, Box, Container, Dialog, IconButton, Slide, SlideProps, Toolbar, Typography, useMediaQuery, useTheme, } from '@mui/material'; import React from 'react'; import { useTranslation } from 'react-i18next'; import { meta } from '@/constants'; export type PrivacyPolicyDialogProps = { open: boolean; closeAction: { (): void }; }; export type PrivacyPolicyDialogRef = { scrollTop: () => void; }; const Transition = React.forwardRef(function _(props: SlideProps & { children: React.ReactElement }, ref) { return <Slide ref={ref} direction="up" {...props} />; }); const titleKeys = ['acquisition', 'purpose', 'thirdParty', 'analysis', 'disclaimer', 'copyright']; export const PrivacyPolicyDialog = React.memo(function _(props: PrivacyPolicyDialogProps) { const dialogRef = React.useRef<HTMLDivElement>(null); const theme = useTheme(); const ltSm = useMediaQuery(theme.breakpoints.down('sm')); const [t] = useTranslation(); const handleClose = React.useCallback(() => props.closeAction && props.closeAction(), [props]); const scrollTop = React.useCallback(() => { // ダイアログを開く際にスクロール位置を先頭に戻す const element = dialogRef.current?.getElementsByClassName('MuiDialog-paperScrollPaper')[0] as Element; if (element) element.scrollTop = 0; /* istanbul ignore if */ if (process.env.NODE_ENV === 'test') console.debug('ScrollTop Completed.'); }, []); React.useEffect(() => { if (props.open) scrollTop(); }, [props.open, scrollTop]); return ( <Dialog ref={dialogRef} open={props.open} onClose={handleClose} TransitionComponent={Transition} keepMounted maxWidth={false} fullWidth={!ltSm} fullScreen={ltSm} sx={ltSm ? { maxHeight: '85vh', mt: '15vh' } : null} // モバイル端末時は Bottom Sheet 風の表示にする style={{ whiteSpace: 'pre-wrap' }} // 空白と改行を反映させる > <AppBar sx={{ position: 'sticky' }}> <Container maxWidth="xl"> <Toolbar sx={{ justifyContent: 'space-between' }} disableGutters> <Typography variant="h6" data-testid="PrivacyPolicyDialog__Title"> {t('privacyPolicy.title')} </Typography> <IconButton onClick={handleClose} data-testid="PrivacyPolicyDialog__Close"> <CloseIcon /> </IconButton> </Toolbar> </Container> </AppBar> <Container sx={{ pb: 10 }} data-testid="PrivacyPolicyDialog__Body"> <Box sx={{ my: 5 }}> <Typography variant="subtitle1">{t('privacyPolicy.summary', { title: meta.title })}</Typography> </Box> {titleKeys.map((key) => ( <Box key={`PrivacyPolicyDialog__Body--${key}`} sx={{ my: 5 }}> <Typography variant="h6" sx={{ fontWeight: 'bold' }}> {t('privacyPolicy.title', { context: key })} </Typography> <Typography variant="body1" sx={{ color: 'text.secondary', mt: 2 }}> {t('privacyPolicy.body', { context: key })} </Typography> </Box> ))} </Container> </Dialog> ); }); |