{"version":3,"file":"Timer-CI2MnCaN.js","sources":["../../node_modules/@tabler/icons-react/dist/esm/icons/IconClockFilled.mjs","../../src/components/Timer.tsx"],"sourcesContent":["/**\n * @license @tabler/icons-react v3.22.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nvar IconClockFilled = createReactComponent(\"filled\", \"clock-filled\", \"IconClockFilled\", [[\"path\", { \"d\": \"M17 3.34a10 10 0 1 1 -14.995 8.984l-.005 -.324l.005 -.324a10 10 0 0 1 14.995 -8.336zm-5 2.66a1 1 0 0 0 -.993 .883l-.007 .117v5l.009 .131a1 1 0 0 0 .197 .477l.087 .1l3 3l.094 .082a1 1 0 0 0 1.226 0l.094 -.083l.083 -.094a1 1 0 0 0 0 -1.226l-.083 -.094l-2.707 -2.708v-4.585l-.007 -.117a1 1 0 0 0 -.993 -.883z\", \"key\": \"svg-0\" }]]);\n\nexport { IconClockFilled as default };\n//# sourceMappingURL=IconClockFilled.mjs.map\n","import { Stack, Text, useMantineTheme } from '@mantine/core'\nimport { useMediaQuery } from '@mantine/hooks'\nimport { IconClockFilled } from '@tabler/icons-react'\nimport React, { memo, useCallback, useEffect, useState } from 'react'\n\nimport classes from './Timer.module.css'\n\ntype TimerProps = {\n /**\n * Callback for when this component ends. This function reference\n * doesn't need to be stable, although that'd be advisable.\n */\n text?: string\n secondary?: boolean\n onTimeout?: () => void\n} & (\n | {\n /**\n * Expiration timestamp in Epoch seconds\n */\n expiryTimestamp: number\n initialSeconds?: undefined\n }\n | {\n expiryTimestamp?: undefined\n /**\n * Number of seconds since the component is mounted.\n * If the Timer doesn't get unmounted as a side-effect\n * of onTimeout, it will reset and loop forever.\n */\n initialSeconds: number\n }\n)\n\nconst Timer: React.FC = ({\n text = 'remaining',\n expiryTimestamp,\n initialSeconds,\n secondary,\n onTimeout,\n}) => {\n const theme = useMantineTheme()\n // Calculates remaining seconds based on either an expiry timestamp or initial minutes.\n // This calculation is in a memoized function, so its value doesn't change on every\n // render if `expiryTimestamp` was used (seconds left would depend on the current time).\n const getSecondsLeft = useCallback(\n () =>\n initialSeconds\n ? Math.max(0, initialSeconds)\n : expiryTimestamp\n ? Math.floor(expiryTimestamp - Date.now() / 1000)\n : 0,\n [expiryTimestamp, initialSeconds]\n )\n const [time, setTime] = useState(getSecondsLeft)\n const isMobile = useMediaQuery(`(max-width: ${theme.breakpoints.xs})`)\n\n const [triggerTimeout, setTriggerTimeout] = useState(false)\n useEffect(() => {\n if (triggerTimeout) {\n onTimeout?.()\n setTriggerTimeout(false)\n }\n }, [onTimeout, triggerTimeout])\n\n // This effect, which controls a JS interval, should only be reset if\n // either `expiryTimestamp` or `initialSeconds` change, in which case,\n // `getSecondsLeft` will change its reference, making the effect start over.\n // This effect should not re-render every second or when the `onTimeout`\n // function changes. This is avoided by using a reference.\n useEffect(() => {\n const counterSeconds = getSecondsLeft()\n\n // Don't even try to start counting down if this timer is for 0 or\n // negative seconds, i.e. `expiryTimestamp` is in the past, or\n // `initialSeconds` is 0 or negative.\n if (counterSeconds <= 0) {\n setTime(0)\n return undefined\n }\n\n setTime(counterSeconds)\n\n const interval = setInterval(() => {\n setTime(prevTime => {\n let newTime = prevTime - 1\n\n if (newTime <= 0) {\n // If the timer is set with `initialSeconds`, then `getSecondsLeft`\n // will return the same number again\n const newCounterSeconds = getSecondsLeft()\n\n // If the timer was set with `expiryTimestamp`, `newCounterSeconds`\n // will be 0, in which case, the timer shouldn't reset.\n if (newCounterSeconds <= 0) {\n clearInterval(interval)\n }\n // Else, if the timer was set with `initialSeconds` (i.e.:\n // `newCounterSeconds > 0`), the timer should restart.\n else {\n newTime = newCounterSeconds\n }\n\n // Do this instead of calling the onTimeout function directly,\n // so it doesn't block the UI. setTime should return ASAP,\n // and the onTimeout function could also change the UI,\n // creating a bug in the component's lifecycle (think\n // the onTimeout function unmounts this component: it would\n // unmount the components and then setTime would return but\n // the component wouldn't exist anymore, aka a bug).\n setTriggerTimeout(true)\n }\n\n return newTime > 0 ? newTime : 0\n })\n }, 1000)\n\n return () => clearInterval(interval)\n }, [getSecondsLeft])\n\n const days = Math.floor(time / 86400)\n const hours = Math.floor((time % 86400) / 3600)\n const minutes = Math.floor((time % 3600) / 60)\n const seconds = time % 60\n\n const minsSeconds = `${secondary ? `${days.toString().padStart(2, '0')}d ` : ''}${secondary ? `${hours.toString().padStart(2, '0')}h ` : ''}${minutes\n .toString()\n .padStart(\n 2,\n '0'\n )}${secondary && 'm'}${secondary ? ' ' : ':'}${seconds.toString().padStart(2, '0')}${secondary && 's'}`\n\n return (\n \n \n \n {secondary && (\n \n {text}\n \n )}\n {isMobile ? (\n \n {minsSeconds}\n \n ) : (\n <>\n \n {minsSeconds}\n {' '}\n {!secondary && (\n \n {text}\n \n )}\n \n )}\n \n \n )\n}\n\nexport default memo(Timer)\n"],"names":["IconClockFilled","createReactComponent","Timer","text","expiryTimestamp","initialSeconds","secondary","onTimeout","theme","useMantineTheme","getSecondsLeft","useCallback","time","setTime","useState","isMobile","useMediaQuery","triggerTimeout","setTriggerTimeout","useEffect","counterSeconds","interval","prevTime","newTime","newCounterSeconds","days","hours","minutes","seconds","minsSeconds","jsxs","Stack","classes","jsx","Text","Fragment","memo"],"mappings":"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","x_google_ignoreList":[0]}