81717-439d79fc25140a59.js.map 36 KB

1
  1. {"version":3,"file":"static/chunks/81717-439d79fc25140a59.js","mappings":"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","sources":["webpack://_N_E/./src/components/DataFetcher/index.tsx","webpack://_N_E/./public/icons/retry.svg","webpack://_N_E/./src/components/Error/index.tsx","webpack://_N_E/./src/components/NextSeoWrapper.tsx","webpack://_N_E/./src/components/QuranReader/TranslationView/TranslationText/FootnoteText.tsx","webpack://_N_E/./src/components/QuranReader/TranslationView/TranslationText/index.tsx","webpack://_N_E/./src/components/QuranReader/VerseTextPreview/index.tsx","webpack://_N_E/./src/hooks/useQcfFont.ts","webpack://_N_E/./src/pages/_error.tsx","webpack://_N_E/./src/utils/string.ts","webpack://_N_E/./src/components/Error/Error.module.scss","webpack://_N_E/./src/components/QuranReader/TranslationView/TranslationText/FootnoteText.module.scss","webpack://_N_E/./src/components/QuranReader/TranslationView/TranslationText/TranslationText.module.scss","webpack://_N_E/./src/pages/_error.module.scss","webpack://_N_E/./src/pages/index.module.scss"],"sourcesContent":["import React, { memo } from 'react';\n\nimport useSWRImmutable from 'swr/immutable';\n\nimport Error from '@/components/Error';\nimport Spinner from '@/dls/Spinner/Spinner';\nimport { fetcher } from 'src/api';\nimport { BaseResponse } from 'types/ApiResponses';\n\ninterface Props {\n queryKey: string;\n render: (data: BaseResponse) => JSX.Element;\n renderError?: (error: any) => JSX.Element | undefined;\n initialData?: BaseResponse;\n loading?: () => JSX.Element;\n fetcher?: (queryKey: string) => Promise<BaseResponse>;\n showSpinnerOnRevalidate?: boolean;\n onFetchSuccess?: (data: BaseResponse) => void;\n}\n\n/**\n * Data fetcher is a dynamic component that serves as a container for a component\n * that depends on data from a remote API to render. This component handles:\n * 1. Calling the API.\n * 2. Caching the response (due to using useSwr).\n * 3. Handling errors if any by showing an error message.\n * 4. Handling when the user is offline while trying to fetch the API response.\n * 5. Dynamically passing the response data through render-props to the parent.\n *\n * @param {Props} props\n * @returns {JSX.Element}\n */\nconst DataFetcher: React.FC<Props> = ({\n queryKey,\n render,\n renderError,\n initialData,\n loading = () => <Spinner />,\n fetcher: dataFetcher = fetcher,\n showSpinnerOnRevalidate = true,\n onFetchSuccess,\n}: Props): JSX.Element => {\n const { data, error, isValidating, mutate } = useSWRImmutable(\n queryKey,\n () =>\n dataFetcher(queryKey)\n .then((res) => {\n onFetchSuccess?.(res);\n return Promise.resolve(res);\n })\n .catch((err) => Promise.reject(err)),\n {\n fallbackData: initialData,\n },\n );\n\n // if showSpinnerOnRevalidate is true, we should show the spinner if we are revalidating the data.\n // otherwise, we should only show the spinner on initial loads.\n if (showSpinnerOnRevalidate ? isValidating : isValidating && !data) {\n return loading();\n }\n\n const onRetryClicked = () => {\n mutate();\n };\n\n /**\n * if we haven't fetched the data yet and the device is not online (because we don't want to show an offline message if the data already exists).\n * or if we had an error when calling the API.\n */\n if (error) {\n // if there is a custom error renderer, use it.\n if (renderError) {\n const errorComponent = renderError(error);\n // if the custom error renderer returns false, it means that it doesn't want to render anything special.\n if (typeof errorComponent !== 'undefined') {\n return errorComponent;\n }\n }\n return <Error onRetryClicked={onRetryClicked} error={error} />;\n }\n\n return render(data);\n};\n\nexport default memo(DataFetcher);\n","var _path;\nfunction _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }\nimport * as React from \"react\";\nvar SvgRetry = function SvgRetry(props) {\n return /*#__PURE__*/React.createElement(\"svg\", _extends({\n width: 15,\n height: 15,\n viewBox: \"0 0 15 15\",\n fill: \"none\",\n xmlns: \"http://www.w3.org/2000/svg\"\n }, props), _path || (_path = /*#__PURE__*/React.createElement(\"path\", {\n d: \"M1.85 7.5c0-2.835 2.21-5.65 5.65-5.65 2.778 0 4.152 2.056 4.737 3.15H10.5a.5.5 0 0 0 0 1h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-1 0v1.813C12.296 3.071 10.666.85 7.5.85 3.437.85.85 4.185.85 7.5c0 3.315 2.587 6.65 6.65 6.65 1.944 0 3.562-.77 4.714-1.942a6.77 6.77 0 0 0 1.428-2.167.5.5 0 1 0-.925-.38 5.77 5.77 0 0 1-1.216 1.846c-.971.99-2.336 1.643-4.001 1.643-3.44 0-5.65-2.815-5.65-5.65Z\",\n fill: \"currentColor\",\n fillRule: \"evenodd\",\n clipRule: \"evenodd\"\n })));\n};\nexport default SvgRetry;","import React from 'react';\n\nimport useTranslation from 'next-translate/useTranslation';\n\nimport styles from './Error.module.scss';\n\nimport Button, { ButtonSize, ButtonType } from '@/dls/Button/Button';\nimport RetryIcon from '@/icons/retry.svg';\nimport { OFFLINE_ERROR } from 'src/api';\n\ninterface Props {\n onRetryClicked: () => void;\n error: Error;\n}\n\nconst Error: React.FC<Props> = ({ onRetryClicked, error }) => {\n const { t } = useTranslation('common');\n return (\n <div className={styles.container}>\n <p className={styles.text}>\n {error.message !== OFFLINE_ERROR ? t('error.general') : t('error.offline')}\n </p>\n <Button\n prefix={<RetryIcon />}\n size={ButtonSize.Small}\n type={ButtonType.Secondary}\n onClick={onRetryClicked}\n >\n {t('retry')}\n </Button>\n </div>\n );\n};\n\nexport default Error;\n","import React from 'react';\n\nimport { NextSeo } from 'next-seo';\n\nimport { SEOProps } from '@/utils/seo';\nimport { truncateString } from '@/utils/string';\n\ninterface Props extends SEOProps {\n url?: string;\n image?: string;\n imageAlt?: string;\n imageWidth?: number;\n imageHeight?: number;\n}\n\nconst NextSeoWrapper: React.FC<Props> = (props) => {\n const { url, image, imageAlt, imageHeight, imageWidth, openGraph, description, ...rest } = props;\n const openGraphParams = {\n ...(openGraph && { openGraph }),\n ...(url && { url }),\n ...(image && {\n images: [{ url: image, width: imageWidth, height: imageHeight, alt: imageAlt }],\n }),\n };\n const params = {\n ...rest,\n ...(description && { description: truncateString(description, 150) }),\n };\n return <NextSeo {...params} openGraph={openGraphParams} />;\n};\n\nexport default NextSeoWrapper;\n","/* eslint-disable react/no-danger */\n\nimport React, { MouseEvent } from 'react';\n\nimport classNames from 'classnames';\nimport useTranslation from 'next-translate/useTranslation';\n\nimport styles from './FootnoteText.module.scss';\nimport transStyles from './TranslationText.module.scss';\n\nimport Button, { ButtonSize, ButtonShape, ButtonVariant } from '@/dls/Button/Button';\nimport Spinner from '@/dls/Spinner/Spinner';\nimport CloseIcon from '@/icons/close.svg';\nimport { getLanguageDataById, findLanguageIdByLocale } from '@/utils/locale';\nimport Footnote from 'types/Footnote';\n\ninterface FootnoteTextProps {\n footnoteName?: string; // can be a number or a string (e.g. \"sg\" or \"pl\")\n footnote: Footnote;\n onCloseClicked: () => void;\n onTextClicked?: (event: MouseEvent, isSubFootnote?: boolean) => void;\n isLoading?: boolean;\n}\n\nconst FootnoteText: React.FC<FootnoteTextProps> = ({\n footnoteName,\n footnote,\n onCloseClicked,\n onTextClicked,\n isLoading,\n}) => {\n const { t, lang } = useTranslation('quran-reader');\n\n const languageId = footnote?.languageId || findLanguageIdByLocale(lang);\n const landData = getLanguageDataById(languageId);\n\n return (\n <div className={styles.footnoteContainer}>\n <div className={styles.header}>\n <p>\n {t('footnote')} {footnoteName ? `- ${footnoteName}` : null}\n </p>\n <Button\n size={ButtonSize.Small}\n variant={ButtonVariant.Ghost}\n shape={ButtonShape.Circle}\n onClick={onCloseClicked}\n >\n <CloseIcon />\n </Button>\n </div>\n {isLoading ? (\n <Spinner />\n ) : (\n <div\n className={classNames(\n styles.text,\n transStyles[landData.direction],\n transStyles[landData.font],\n )}\n dangerouslySetInnerHTML={{ __html: footnote.text }}\n {...(onTextClicked && { onClick: onTextClicked })}\n />\n )}\n </div>\n );\n};\n\nexport default FootnoteText;\n","/* eslint-disable react-func/max-lines-per-function */\n/* eslint-disable jsx-a11y/no-static-element-interactions */\n/* eslint-disable jsx-a11y/click-events-have-key-events */\n/* eslint-disable react/no-danger */\n\nimport React, { MouseEvent, useState } from 'react';\n\nimport classNames from 'classnames';\nimport useTranslation from 'next-translate/useTranslation';\n\nimport FootnoteText from './FootnoteText';\nimport styles from './TranslationText.module.scss';\n\nimport { logButtonClick } from '@/utils/eventLogger';\nimport { getLanguageDataById } from '@/utils/locale';\nimport { getFootnote } from 'src/api';\nimport Footnote from 'types/Footnote';\n\ninterface Props {\n translationFontScale: number;\n text: string;\n resourceName?: string;\n languageId: number;\n}\n\nconst TranslationText: React.FC<Props> = ({\n translationFontScale,\n text,\n languageId,\n resourceName,\n}) => {\n const { t } = useTranslation('quran-reader');\n const [isLoading, setIsLoading] = useState(false);\n const [showFootnote, setShowFootnote] = useState(true);\n const [footnote, setFootnote] = useState<Footnote>(null);\n const [activeFootnoteName, setActiveFootnoteName] = useState<string | null>(null);\n const [activeSubFootnoteName, setActiveSubFootnoteName] = useState<string | null>(null);\n const [subFootnote, setSubFootnote] = useState<Footnote>(null);\n\n const PRE_DEFINED_FOOTNOTES = {\n sg: t('footnote-sg'),\n pl: t('footnote-pl'),\n dl: t('footnote-dl'),\n };\n\n const resetFootnote = () => {\n setFootnote(null);\n setSubFootnote(null);\n setIsLoading(false);\n setActiveFootnoteName(null);\n setActiveSubFootnoteName(null);\n };\n\n const resetSubFootnote = () => {\n setSubFootnote(null);\n setActiveSubFootnoteName(null);\n };\n\n /**\n * Handle when the translation text is clicked. This is needed to handle when a footnote\n * is clicked since we receive the translation text as HTML from BE. Any footnote will\n * be inside an <sup>...</sup> element. so when the translation container is clicked\n * we check whether the clicked element is of tag name SUP and if so, we handle showing the\n * footnote as following:\n *\n * 1. If it's not a sub-footnote (a footnote inside a footnote) which is all translations\n * except Bridge's Foundation translation:\n * 1. check if the sup element has foot_note attribute (the ID) and if it has:\n * 1. Check if we already have a footnote in the local state with the same ID:\n * 1. if yes, it means this is the second time the user clicks on the\n * footnote so we should close the footnote.\n * 2. if no, it means we need to call BE to fetch the footnote text by its ID.\n * 2. if not, it means it's a pre-defined footnote and in this case, we access the text\n * inside the element and check if it's in the list of pre-defined footnotes and if it\n * is, we get the value from the pre-defined footnotes and assign it as the footnote\n * text without having to call BE (only happens with Bridge's Foundation translation)\n * 2. If it's a sub-footnote it will only have pre-defined footnotes so we handle it the same\n * way as above (only happens with Bridge's Foundation translation, ex: Surah 30, Verse 11).\n *\n * @param {MouseEvent} event\n * @param {boolean} isSubFootnote whether we are handling a footnote or a sub-footnote (only happens\n * with Bridge's Foundation translation).\n */\n const onTextClicked = (event: MouseEvent, isSubFootnote = false) => {\n const target = event.target as HTMLElement;\n\n // if we just clicked on anything other than a footnote element, return early.\n if (target.tagName !== 'SUP') {\n return;\n }\n // we get the text inside the sup element and trim the extra spaces.\n const footnoteText = target.innerText.trim();\n\n // if it's the main footnote and not the sub footnote.\n if (!isSubFootnote) {\n const footNoteId = target.getAttribute('foot_note');\n\n // Set the activeFootnoteNumber to the current number of the footnote from the <sup> innerHTML\n setActiveFootnoteName(footnoteText);\n\n // if it's the normal case that needs us to call BE and not a fixed footnote like the ones found for Bridge's translation.\n if (footNoteId) {\n // if this is the second time to click the footnote, close it\n if (showFootnote && footnote && footnote.id === Number(footNoteId)) {\n logButtonClick('translation_footnote_double_click_to_close');\n resetFootnote();\n } else {\n logButtonClick('translation_show_footnote');\n resetSubFootnote();\n setShowFootnote(true);\n setIsLoading(true);\n getFootnote(footNoteId)\n .then((res) => {\n if (res.status !== 500) {\n setFootnote(res.footNote);\n }\n })\n .finally(() => {\n setIsLoading(false);\n });\n }\n } else if (footnote && footnote.id === footnoteText) {\n // if this is the second time we are clicking on the footnote, we close it.\n logButtonClick('translation_pre_defined_footnote_double_click_to_close');\n resetFootnote();\n } else if (PRE_DEFINED_FOOTNOTES[footnoteText]) {\n logButtonClick('translation_pre_defined_footnote');\n resetSubFootnote();\n setFootnote({\n id: footnoteText,\n text: PRE_DEFINED_FOOTNOTES[footnoteText],\n });\n }\n } else {\n // Set the activeSubFootnoteNumber to the current number of the footnote from the <sup> innerHTML\n setActiveSubFootnoteName(footnoteText);\n\n const subFootnoteId = `${footnote.id} - ${footnoteText}`;\n // if this is the second time we are clicking on the sub footnote, we close it.\n if (subFootnote && subFootnote.id === subFootnoteId) {\n logButtonClick('translation_sub_footnote_double_click_to_close');\n resetSubFootnote();\n } else if (PRE_DEFINED_FOOTNOTES[footnoteText]) {\n logButtonClick('translation_show_sub_footnote');\n setSubFootnote({\n id: subFootnoteId,\n text: PRE_DEFINED_FOOTNOTES[footnoteText],\n });\n }\n }\n };\n const hideFootnote = () => setShowFootnote(false);\n const langData = getLanguageDataById(languageId);\n\n const shouldShowFootnote = showFootnote && (footnote || isLoading);\n return (\n <div className={styles[`translation-font-size-${translationFontScale}`]}>\n <div\n onClick={(event) => onTextClicked(event)}\n className={classNames(styles.text, styles[langData.direction], styles[langData.font])}\n dangerouslySetInnerHTML={{ __html: text }}\n />\n {shouldShowFootnote && (\n <FootnoteText\n footnoteName={activeFootnoteName || undefined}\n footnote={footnote}\n isLoading={isLoading}\n onCloseClicked={() => {\n logButtonClick('translation_footnote_close');\n if (isLoading) {\n hideFootnote();\n } else {\n resetFootnote();\n }\n }}\n onTextClicked={(event) => onTextClicked(event, true)}\n />\n )}\n {subFootnote && (\n <FootnoteText\n footnoteName={activeSubFootnoteName || undefined}\n footnote={subFootnote}\n onCloseClicked={resetSubFootnote}\n />\n )}\n {resourceName && (\n <p\n className={classNames(\n styles.translationName,\n styles[langData.direction],\n styles[langData.font],\n )}\n // eslint-disable-next-line i18next/no-literal-string\n >\n — {resourceName}\n </p>\n )}\n </div>\n );\n};\n\nexport default TranslationText;\n","import React, { useMemo } from 'react';\n\nimport { shallowEqual, useSelector } from 'react-redux';\n\nimport PlainVerseText from '@/components/Verse/PlainVerseText';\nimport useQcfFont from '@/hooks/useQcfFont';\nimport { selectQuranReaderStyles } from '@/redux/slices/QuranReader/styles';\nimport { getVerseWords } from '@/utils/verse';\nimport Verse from 'types/Verse';\n\ninterface Props {\n verses: Verse[];\n fontScale?: number;\n}\n\nconst VerseTextPreview: React.FC<Props> = ({ verses, fontScale }) => {\n const { quranFont } = useSelector(selectQuranReaderStyles, shallowEqual);\n const tafsirVerses = useMemo(\n () =>\n Object.values(verses).map((verse) => ({\n ...verse,\n pageNumber: verse.words[0].pageNumber,\n })),\n [verses],\n );\n useQcfFont(quranFont, tafsirVerses);\n const words = useMemo(() => verses.map((verse) => getVerseWords(verse)).flat(), [verses]);\n return <PlainVerseText fontScale={fontScale} words={words} />;\n};\n\nexport default VerseTextPreview;\n","import { useEffect, useCallback, useRef } from 'react';\n\nimport { useDispatch, useSelector } from 'react-redux';\n\nimport { selectLoadedFontFaces, addLoadedFontFace } from '@/redux/slices/QuranReader/font-faces';\nimport { removeItemFromArray } from '@/utils/array';\nimport {\n getFontFaceNameForPage,\n getV1OrV2FontFaceSource,\n getPagesByVerses,\n isQCFFont,\n} from '@/utils/fontFaceHelper';\nimport { QuranFont } from 'types/QuranReader';\nimport Verse from 'types/Verse';\n\n/**\n * This hook manually request the browser to download the font for each page\n * of QCF's V1 and V2 Mushafs. After each resource has been downloaded, we\n * store it in redux so that VerseText can use it to determine whether the fallback\n * text and font should be font or not.\n *\n * Notes, loaded font is reset every time the user switch the font\n * see src/components/Navbar/SettingsDrawer/QuranFontSection.tsx\n *\n * @param {QuranFont} quranFont\n * @param {Verse[]} verses\n */\nconst useQcfFont = (quranFont: QuranFont, verses: Verse[]) => {\n const currentlyFetchingFonts = useRef([]);\n const dispatch = useDispatch();\n const isFontQCF = isQCFFont(quranFont);\n const loadedFonts = useSelector(selectLoadedFontFaces);\n const onFontLoaded = useCallback(\n (fontFace: string) => {\n dispatch(addLoadedFontFace(fontFace));\n },\n [dispatch],\n );\n\n // listen to changes in verses (this is due to infinite scrolling fetching more verses).\n useEffect(() => {\n if (isFontQCF && verses.length > 0) {\n // loop through unique page numbers of the current verses\n getPagesByVerses(verses).forEach((pageNumber) => {\n const isV1 = quranFont === QuranFont.MadaniV1;\n const fontFaceName = getFontFaceNameForPage(isV1, pageNumber);\n const fontFace = new FontFace(fontFaceName, getV1OrV2FontFaceSource(isV1, pageNumber));\n // we only want to load fonts that were not loaded and also are not currently being loaded\n if (\n !currentlyFetchingFonts.current.includes(fontFaceName) &&\n !loadedFonts.includes(fontFaceName)\n ) {\n currentlyFetchingFonts.current = [...currentlyFetchingFonts.current, fontFaceName];\n fontFace.display = 'block';\n document.fonts.add(fontFace);\n // load the font-face programmatically\n fontFace\n .load()\n .then(() => {\n // store the font face in Redux slice\n onFontLoaded(fontFaceName);\n })\n .finally(() => {\n // whether we failed or succeeded to fetch the fontFace, we remove it from currently fetching array\n currentlyFetchingFonts.current = removeItemFromArray(\n fontFaceName,\n currentlyFetchingFonts.current,\n );\n });\n }\n });\n }\n }, [quranFont, verses, loadedFonts, isFontQCF, currentlyFetchingFonts, onFontLoaded]);\n};\n\nexport default useQcfFont;\n","/* eslint-disable jsx-a11y/anchor-is-valid */\nimport classNames from 'classnames';\nimport { useRouter } from 'next/router';\nimport useTranslation from 'next-translate/useTranslation';\n\nimport styles from './_error.module.scss';\n\nimport Button from '@/dls/Button/Button';\nimport Link, { LinkVariant } from '@/dls/Link/Link';\n\n// reference: https://nextjs.org/docs/advanced-features/custom-error-page#more-advanced-error-page-customizing\ntype ErrorProps = {\n statusCode?: number;\n hasFullWidth?: boolean;\n};\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nconst Error = ({ statusCode, hasFullWidth = true }: ErrorProps) => {\n const { t } = useTranslation('error');\n const router = useRouter();\n\n // if previous page url exist, go back, otherwise go to home\n const onBackButtonClicked = () => {\n if (document && document.referrer) {\n router.back();\n return;\n }\n router.push('/'); // go to home\n };\n return (\n <div\n className={classNames(styles.container, {\n [styles.withFullWidth]: hasFullWidth,\n })}\n >\n <h1 className={styles.title}>{t('title')}</h1>\n <div className={styles.goBack}>\n <Button onClick={onBackButtonClicked}>{t('go-back')}</Button>\n </div>\n <p className={styles.reportBug}>\n {t('if-persist')}{' '}\n <Link href=\"https://feedback.quran.com/\" variant={LinkVariant.Highlight}>\n {t('report-cta')}\n </Link>\n </p>\n </div>\n );\n};\n\nexport default Error;\n","/**\n * Shorten a text by setting the maximum number of characters\n * by the value of the parameter and adding \"...\" at the end.\n *\n * @param {string} rawString\n * @param {number} length\n * @param {string} suffix\n * @returns {string}\n */\nexport const truncateString = (rawString: string, length: number, suffix = '...'): string => {\n const characters = rawString.split('', length);\n let shortenedText = '';\n for (let index = 0; index < characters.length; index += 1) {\n const character = characters[index];\n if (shortenedText.length === length - 1) {\n shortenedText = `${shortenedText}${character}${suffix}`;\n break;\n }\n shortenedText = `${shortenedText}${character}`;\n }\n return shortenedText;\n};\n\n/**\n * Strip HTML tags from a string.\n *\n * @param {string} rawString\n * @returns {string}\n */\nexport const stripHTMLTags = (rawString: string): string => rawString.replace(/(<([^>]+)>)/gi, '');\n\n/**\n * Convert a slugified collection id to collection id only after\n * removing the slug.\n *\n * @param {string} slugifiedCollectionId\n * @returns {string}\n */\nexport const slugifiedCollectionIdToCollectionId = (slugifiedCollectionId: string): string => {\n if (!slugifiedCollectionId) {\n return '';\n }\n const splits = slugifiedCollectionId.split('-');\n // if there is no slug in the url (collections with a name that cannot be slugified e.g. emoticons)\n if (splits.length === 1) {\n return splits[0];\n }\n return splits[splits.length - 1];\n};\n","// extracted by mini-css-extract-plugin\nmodule.exports = {\"container\":\"Error_container__1m9XV\",\"text\":\"Error_text__yg4kD\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"footnoteContainer\":\"FootnoteText_footnoteContainer__2GrJa\",\"text\":\"FootnoteText_text__o_c03\",\"header\":\"FootnoteText_header__M_Q2C\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"text\":\"TranslationText_text__4atf8\",\"translation-font-size-1\":\"TranslationText_translation-font-size-1__TqSPj\",\"translation-font-size-2\":\"TranslationText_translation-font-size-2__AW2i1\",\"translation-font-size-3\":\"TranslationText_translation-font-size-3__ww3t4\",\"translation-font-size-4\":\"TranslationText_translation-font-size-4__TKdKv\",\"translation-font-size-5\":\"TranslationText_translation-font-size-5__5bjGX\",\"translation-font-size-6\":\"TranslationText_translation-font-size-6__6SMJi\",\"translation-font-size-7\":\"TranslationText_translation-font-size-7__03ez5\",\"translation-font-size-8\":\"TranslationText_translation-font-size-8__IA0Tr\",\"translation-font-size-9\":\"TranslationText_translation-font-size-9__tq3IG\",\"translation-font-size-10\":\"TranslationText_translation-font-size-10__A9YEa\",\"ltr\":\"TranslationText_ltr__146rZ\",\"rtl\":\"TranslationText_rtl__ytrpw\",\"urdu\":\"TranslationText_urdu__9N37Y\",\"kurdish\":\"TranslationText_kurdish__je0yf\",\"divehi\":\"TranslationText_divehi__e3rqQ\",\"translationName\":\"TranslationText_translationName__Vm9Sj\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"container\":\"_error_container__vJFnH\",\"withFullWidth\":\"_error_withFullWidth__VEzYc\",\"title\":\"_error_title__oLWAK\",\"goBack\":\"_error_goBack__U4WNd\",\"reportBug\":\"_error_reportBug__tsKmR\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"pageContainer\":\"index_pageContainer__Pxtn3\",\"loadingContainer\":\"index_loadingContainer__WEZFc\",\"flow\":\"index_flow__rCTR5\",\"flowItem\":\"index_flowItem__GnXWz\",\"additionalVerticalGap\":\"index_additionalVerticalGap__nzYz6\",\"fullWidth\":\"index_fullWidth__1n4ux\"};"],"names":["DataFetcher","queryKey","render","renderError","initialData","loading","Spinner","dataFetcher","fetcher","showSpinnerOnRevalidate","onFetchSuccess","useSWRImmutable","then","res","Promise","resolve","catch","err","reject","fallbackData","data","error","isValidating","mutate","errorComponent","Error","onRetryClicked","memo","_path","_extends","Object","assign","bind","n","e","arguments","length","t","r","hasOwnProperty","call","apply","props","width","height","viewBox","fill","xmlns","d","fillRule","clipRule","useTranslation","div","className","styles","p","message","OFFLINE_ERROR","Button","prefix","RetryIcon","size","ButtonSize","type","ButtonType","onClick","url","image","imageAlt","imageHeight","imageWidth","openGraph","description","rest","openGraphParams","images","alt","params","truncateString","NextSeo","footnoteName","footnote","onCloseClicked","onTextClicked","isLoading","lang","languageId","findLanguageIdByLocale","landData","getLanguageDataById","variant","ButtonVariant","shape","ButtonShape","CloseIcon","classNames","transStyles","direction","font","dangerouslySetInnerHTML","__html","text","translationFontScale","resourceName","useState","setIsLoading","showFootnote","setShowFootnote","setFootnote","activeFootnoteName","setActiveFootnoteName","activeSubFootnoteName","setActiveSubFootnoteName","subFootnote","setSubFootnote","PRE_DEFINED_FOOTNOTES","sg","pl","dl","resetFootnote","resetSubFootnote","event","isSubFootnote","target","tagName","footnoteText","innerText","trim","subFootnoteId","id","logButtonClick","footNoteId","getAttribute","Number","getFootnote","status","footNote","finally","langData","shouldShowFootnote","FootnoteText","undefined","verses","fontScale","useSelector","selectQuranReaderStyles","shallowEqual","quranFont","tafsirVerses","useMemo","values","map","verse","pageNumber","words","useQcfFont","getVerseWords","flat","PlainVerseText","currentlyFetchingFonts","useRef","dispatch","useDispatch","isFontQCF","isQCFFont","loadedFonts","selectLoadedFontFaces","onFontLoaded","useCallback","fontFace","addLoadedFontFace","useEffect","getPagesByVerses","forEach","isV1","QuranFont","fontFaceName","getFontFaceNameForPage","FontFace","getV1OrV2FontFaceSource","current","includes","display","document","fonts","add","load","removeItemFromArray","statusCode","hasFullWidth","router","useRouter","h1","referrer","back","push","Link","href","LinkVariant","rawString","suffix","characters","split","shortenedText","index","character","stripHTMLTags","replace","slugifiedCollectionIdToCollectionId","slugifiedCollectionId","splits","module","exports"],"sourceRoot":""}