|
| 1 | +import React from 'react'; |
| 2 | +import { useServices } from '../../context/Services'; |
| 3 | +import { OSWebBook } from '../../../gateways/createOSWebLoader'; |
| 4 | +import { Book } from '../types'; |
| 5 | +import { HTMLDivElement } from '@openstax/types/lib.dom'; |
| 6 | +import styled from 'styled-components/macro'; |
| 7 | +import Button from '../../components/Button'; |
| 8 | +import Modal from './Modal'; |
| 9 | +import theme from '../../theme'; |
| 10 | +import Cookies from 'js-cookie'; |
| 11 | +import { useTrapTabNavigation } from '../../reactUtils'; |
| 12 | + |
| 13 | +// tslint:disable-next-line |
| 14 | +const WarningDiv = styled.div` |
| 15 | + display: flex; |
| 16 | + flex-direction: column; |
| 17 | + gap: 4rem; |
| 18 | + justify-content: center; |
| 19 | + align-items: center; |
| 20 | + font-size: 1.8rem; |
| 21 | + padding: 2rem; |
| 22 | + min-height: 50vh; |
| 23 | + top: 25vh; |
| 24 | + z-index: 4; |
| 25 | +
|
| 26 | + > div { |
| 27 | + max-width: 80rem; |
| 28 | + } |
| 29 | +`; |
| 30 | + |
| 31 | +function WarningDivWithTrap({ |
| 32 | + text, |
| 33 | + dismiss, |
| 34 | +}: { |
| 35 | + text: string; |
| 36 | + dismiss: () => void; |
| 37 | +}) { |
| 38 | + const ref = React.useRef<HTMLDivElement>(null); |
| 39 | + |
| 40 | + React.useEffect(() => ref.current?.focus(), []); |
| 41 | + |
| 42 | + useTrapTabNavigation(ref); |
| 43 | + |
| 44 | + return ( |
| 45 | + <WarningDiv tabIndex='-1' ref={ref}> |
| 46 | + <div>{text}</div> |
| 47 | + <Button type='button' onClick={dismiss}> |
| 48 | + Ok |
| 49 | + </Button> |
| 50 | + </WarningDiv> |
| 51 | + ); |
| 52 | +} |
| 53 | + |
| 54 | +export default function ContentWarning({ book }: { book: Book }) { |
| 55 | + const services = useServices(); |
| 56 | + const [bookInfo, setBookInfo] = React.useState<OSWebBook | undefined>(); |
| 57 | + const cookieKey = `content-warning-${bookInfo?.id}`; |
| 58 | + const dismiss = React.useCallback(() => { |
| 59 | + // This is only called when bookInfo is populated |
| 60 | + Cookies.set(cookieKey, 'true', { expires: 28 }); |
| 61 | + setBookInfo(undefined); |
| 62 | + }, [cookieKey]); |
| 63 | + |
| 64 | + React.useEffect(() => { |
| 65 | + services.osWebLoader.getBookFromId(book.id).then(setBookInfo); |
| 66 | + }, [book, services]); |
| 67 | + |
| 68 | + if (!bookInfo?.content_warning_text || Cookies.get(cookieKey)) { |
| 69 | + return null; |
| 70 | + } |
| 71 | + |
| 72 | + return ( |
| 73 | + <Modal |
| 74 | + ariaLabel='Content warning' |
| 75 | + tabIndex='-1' |
| 76 | + scrollLockProps={{ |
| 77 | + mediumScreensOnly: false, |
| 78 | + overlay: true, |
| 79 | + zIndex: theme.zIndex.highlightSummaryPopup, |
| 80 | + }} |
| 81 | + > |
| 82 | + <WarningDivWithTrap |
| 83 | + text={bookInfo.content_warning_text} |
| 84 | + dismiss={dismiss} |
| 85 | + /> |
| 86 | + </Modal> |
| 87 | + ); |
| 88 | +} |
0 commit comments