@cuemath/leap 3.3.8 → 3.3.9-as2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,102 @@
1
+ import { jsxs as f, Fragment as g, jsx as e } from "react/jsx-runtime";
2
+ import { memo as N, useState as k, useRef as w, useEffect as u, useCallback as c } from "react";
3
+ import i from "styled-components";
4
+ import O from "../../assets/line-icons/icons/plus.js";
5
+ import D from "../hooks/use-audio-player.js";
6
+ import R from "../hooks/use-previous.js";
7
+ import X from "../ui/buttons/clickable/clickable.js";
8
+ import a from "../ui/layout/flex-view.js";
9
+ import m from "../ui/text/text.js";
10
+ import { ALERT_AUDIO_LIST as F } from "../worksheet/worksheet/constants.js";
11
+ import I from "./animations/open-close.js";
12
+ import { ANIMATION_TIME as r, TIME_LEFT_IDLE as M, LAST_FIVE as y, START_TIMER as z, EXTEND_IDLE as V } from "./constants.js";
13
+ const W = i(a)`
14
+ position: absolute;
15
+ top: -8px;
16
+ right: 8px;
17
+ z-index: ${({ theme: o }) => o.zIndex.EXTEND_CLASS_ANIMATION_3};
18
+ `, v = i(m)`
19
+ padding-left: 4px;
20
+ padding-right: 8px;
21
+ `, j = i(a)`
22
+ flex-flow: nowrap;
23
+ z-index: ${({ theme: o }) => o.zIndex.EXTEND_CLASS_ANIMATION_2};
24
+ `, P = i(a)`
25
+ position: fixed;
26
+ top: 0;
27
+ bottom: 0;
28
+ left: 0;
29
+ right: 0;
30
+ background: rgba(0, 0, 0, 0.4);
31
+ z-index: ${({ theme: o }) => o.zIndex.EXTEND_CLASS_ANIMATION_1};
32
+ `, B = (o) => {
33
+ const {
34
+ animateClock: t,
35
+ classStartedTime: E,
36
+ duration: x,
37
+ onExtendClass: _ = () => {
38
+ },
39
+ setAnimateClock: d,
40
+ setStartTimer: p,
41
+ showExtendIcon: C = !1
42
+ } = o, [$, l] = k(!1), n = Math.floor(x - (+/* @__PURE__ */ new Date() - E) / 1e3), h = C && n <= r.LAST_FIVE, A = R(t), s = w(null);
43
+ u(() => {
44
+ t && !A && (s.current = setTimeout(() => {
45
+ l(!0);
46
+ }, 1e3));
47
+ }, [t, A]), u(() => () => {
48
+ s.current && clearTimeout(s.current);
49
+ }, []);
50
+ const L = c(() => {
51
+ d(!1);
52
+ }, [d]), T = D(F), b = c(() => {
53
+ p(!0), T("ALERT");
54
+ }, [T, p]), S = c(() => {
55
+ l(!1);
56
+ }, [l]);
57
+ return /* @__PURE__ */ f(g, { children: [
58
+ n <= r.LAST_FIVE && t && /* @__PURE__ */ e(P, {}),
59
+ /* @__PURE__ */ e(
60
+ I,
61
+ {
62
+ background: n <= r.LAST_FIVE ? "ORANGE_4" : "YELLOW_3",
63
+ onAnimationComplete: L,
64
+ onOpenAnimationComplete: b,
65
+ visible: t,
66
+ idleTime: M,
67
+ children: /* @__PURE__ */ f(
68
+ j,
69
+ {
70
+ $flexDirection: "row",
71
+ $alignItems: "center",
72
+ $width: "100%",
73
+ $justifyContent: "space-around",
74
+ $borderRadiusX: 1.25,
75
+ $gutterX: 0.35,
76
+ $gapX: 0.35,
77
+ $flexGapX: 0.25,
78
+ children: [
79
+ /* @__PURE__ */ e(m, { $renderAs: "ac3-black", children: n <= r.LAST_FIVE ? `0${y / 60}:00` : `${z / 60}:00` }),
80
+ /* @__PURE__ */ e(m, { $renderAs: "ac3-black", children: "Left" })
81
+ ]
82
+ }
83
+ )
84
+ }
85
+ ),
86
+ h && /* @__PURE__ */ e(W, { children: /* @__PURE__ */ e(
87
+ I,
88
+ {
89
+ onAnimationComplete: S,
90
+ background: "BLACK",
91
+ Icon: /* @__PURE__ */ e(X, { label: "Extend Class", onClick: _, children: /* @__PURE__ */ e(a, { $background: "WHITE", $borderRadiusX: 1.25, $borderColor: "BLACK_3", children: /* @__PURE__ */ e(O, { width: 16, height: 16 }) }) }),
92
+ visible: $,
93
+ idleTime: V,
94
+ children: /* @__PURE__ */ e(v, { $color: "WHITE", $renderAs: "body3", children: "Extend Class" })
95
+ }
96
+ ) })
97
+ ] });
98
+ }, ne = N(B);
99
+ export {
100
+ ne as default
101
+ };
102
+ //# sourceMappingURL=animate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"animate.js","sources":["../../../src/features/class-timer/animate.tsx"],"sourcesContent":["import { useState, useCallback, useEffect, useRef, memo } from 'react';\nimport styled from 'styled-components';\n\nimport PlusIcon from '../../assets/line-icons/icons/plus';\nimport useAudioPlayer from '../hooks/use-audio-player';\nimport usePrevious from '../hooks/use-previous';\nimport Clickable from '../ui/buttons/clickable/clickable';\nimport FlexView from '../ui/layout/flex-view';\nimport Text from '../ui/text/text';\nimport { ALERT_AUDIO_LIST } from '../worksheet/worksheet/constants';\nimport OpenCloseAnimation from './animations/open-close';\nimport { ANIMATION_TIME, EXTEND_IDLE, LAST_FIVE, START_TIMER, TIME_LEFT_IDLE } from './constants';\n\nconst IconWrapper = styled(FlexView)`\n position: absolute;\n top: -8px;\n right: 8px;\n z-index: ${({ theme }) => theme.zIndex.EXTEND_CLASS_ANIMATION_3};\n`;\n\nconst StyledText = styled(Text)`\n padding-left: 4px;\n padding-right: 8px;\n`;\n\nconst NoWrapRow = styled(FlexView)`\n flex-flow: nowrap;\n z-index: ${({ theme }) => theme.zIndex.EXTEND_CLASS_ANIMATION_2};\n`;\n\nconst OpacityWrapper = styled(FlexView)`\n position: fixed;\n top: 0;\n bottom: 0;\n left: 0;\n right: 0;\n background: rgba(0, 0, 0, 0.4);\n z-index: ${({ theme }) => theme.zIndex.EXTEND_CLASS_ANIMATION_1};\n`;\n\ninterface AnimateProps {\n animateClock: boolean;\n classStartedTime: number;\n duration: number;\n onExtendClass?: () => void;\n setAnimateClock: (value: boolean) => void;\n setStartTimer: (value: boolean) => void;\n showExtendIcon?: boolean;\n}\n\nconst Animate = (props: AnimateProps) => {\n const {\n animateClock,\n classStartedTime,\n duration,\n onExtendClass = () => {},\n setAnimateClock,\n setStartTimer,\n showExtendIcon = false,\n } = props;\n const [animateTip, setAnimateTip] = useState(false);\n const remainingTime = Math.floor(duration - (+new Date() - classStartedTime) / 1000); // in seconds\n const showIcon = showExtendIcon && remainingTime <= ANIMATION_TIME.LAST_FIVE;\n const previousAnimateClock = usePrevious(animateClock);\n const timer = useRef<NodeJS.Timeout | null>(null);\n\n useEffect(() => {\n if (animateClock && !previousAnimateClock) {\n timer.current = setTimeout(() => {\n setAnimateTip(true);\n }, 1000);\n }\n }, [animateClock, previousAnimateClock]);\n\n useEffect(() => {\n return () => {\n if (timer.current) {\n clearTimeout(timer.current);\n }\n };\n }, []);\n\n const onClockAnimationComplete = useCallback(() => {\n setAnimateClock(false);\n }, [setAnimateClock]);\n const playNotifSound = useAudioPlayer(ALERT_AUDIO_LIST);\n\n const onOpenAnimationComplete = useCallback(() => {\n setStartTimer(true);\n playNotifSound('ALERT');\n }, [playNotifSound, setStartTimer]);\n\n const onAnimateComplete = useCallback(() => {\n setAnimateTip(false);\n }, [setAnimateTip]);\n\n return (\n <>\n {remainingTime <= ANIMATION_TIME.LAST_FIVE && animateClock && <OpacityWrapper />}\n <OpenCloseAnimation\n background={remainingTime <= ANIMATION_TIME.LAST_FIVE ? 'ORANGE_4' : 'YELLOW_3'}\n onAnimationComplete={onClockAnimationComplete}\n onOpenAnimationComplete={onOpenAnimationComplete}\n visible={animateClock}\n idleTime={TIME_LEFT_IDLE}\n >\n <NoWrapRow\n $flexDirection=\"row\"\n $alignItems=\"center\"\n $width=\"100%\"\n $justifyContent=\"space-around\"\n $borderRadiusX={1.25}\n $gutterX={0.35}\n $gapX={0.35}\n $flexGapX={0.25}\n >\n <Text $renderAs=\"ac3-black\">\n {remainingTime <= ANIMATION_TIME.LAST_FIVE\n ? `0${LAST_FIVE / 60}:00`\n : `${START_TIMER / 60}:00`}\n </Text>\n <Text $renderAs=\"ac3-black\">Left</Text>\n </NoWrapRow>\n </OpenCloseAnimation>\n {showIcon && (\n <IconWrapper>\n <OpenCloseAnimation\n onAnimationComplete={onAnimateComplete}\n background=\"BLACK\"\n Icon={\n <Clickable label=\"Extend Class\" onClick={onExtendClass}>\n <FlexView $background=\"WHITE\" $borderRadiusX={1.25} $borderColor=\"BLACK_3\">\n <PlusIcon width={16} height={16} />\n </FlexView>\n </Clickable>\n }\n visible={animateTip}\n idleTime={EXTEND_IDLE}\n >\n <StyledText $color=\"WHITE\" $renderAs=\"body3\">\n Extend Class\n </StyledText>\n </OpenCloseAnimation>\n </IconWrapper>\n )}\n </>\n );\n};\n\nexport default memo(Animate);\n"],"names":["IconWrapper","styled","FlexView","theme","StyledText","Text","NoWrapRow","OpacityWrapper","Animate","props","animateClock","classStartedTime","duration","onExtendClass","setAnimateClock","setStartTimer","showExtendIcon","animateTip","setAnimateTip","useState","remainingTime","showIcon","ANIMATION_TIME","previousAnimateClock","usePrevious","timer","useRef","useEffect","onClockAnimationComplete","useCallback","playNotifSound","useAudioPlayer","ALERT_AUDIO_LIST","onOpenAnimationComplete","onAnimateComplete","jsxs","Fragment","jsx","OpenCloseAnimation","TIME_LEFT_IDLE","LAST_FIVE","START_TIMER","Clickable","PlusIcon","EXTEND_IDLE","Animate$1","memo"],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ import { jsxs as I, jsx as $ } from "react/jsx-runtime";
2
+ import { memo as g, useState as p, useRef as y, useEffect as f } from "react";
3
+ import u, { keyframes as w, css as h } from "styled-components";
4
+ import x from "../../ui/layout/flex-view.js";
5
+ const E = w`
6
+ 0% {
7
+ transform: translateX(-100%);
8
+ }
9
+ 100% {
10
+ transform: translateX(0%);
11
+ }
12
+ `, R = w`
13
+ 0% {
14
+ transform: translateX(0%);
15
+ }
16
+ 100% {
17
+ transform: translateX(-100%);
18
+ }
19
+ `, d = 1 * 1e3, X = 1.5 * 1e3, z = u(x)`
20
+ position: absolute;
21
+ z-index: 10;
22
+ overflow: hidden;
23
+ `, M = u.div`
24
+ position: absolute;
25
+ cursor: pointer;
26
+ z-index: 1;
27
+ `, b = u(x)`
28
+ animation-name: ${({ $animate: t }) => t ? E : R};
29
+ max-width: fit-content;
30
+ animation-duration: ${d / 1e3}s;
31
+ animation-timing-function: ease-in-out;
32
+ animation-fill-mode: forwards;
33
+ overflow: hidden;
34
+ white-space: nowrap;
35
+ height: 100%;
36
+ ${({ $isIcon: t, $size: i }) => t && h`
37
+ padding-left: ${i}px;
38
+ `};
39
+ ${({ $isVisible: t }) => !t && h`
40
+ visibility: hidden;
41
+ `};
42
+ `, j = ({
43
+ background: t,
44
+ children: i,
45
+ Icon: n = null,
46
+ onAnimationComplete: s,
47
+ onOpenAnimationComplete: a,
48
+ size: T = null,
49
+ visible: r,
50
+ idleTime: l = X
51
+ }) => {
52
+ const [e, m] = p(!1), o = y(!1);
53
+ return f(() => {
54
+ r && (o.current = !1, m(!0));
55
+ }, [r]), f(() => {
56
+ if (e) {
57
+ const c = setTimeout(() => {
58
+ o.current = !0, m(!1), a == null || a();
59
+ }, d + l);
60
+ return () => {
61
+ clearTimeout(c);
62
+ };
63
+ }
64
+ }, [e, a, l]), f(() => {
65
+ if (r && !e && o.current) {
66
+ const c = setTimeout(() => {
67
+ s == null || s();
68
+ }, d);
69
+ return () => {
70
+ clearTimeout(c);
71
+ };
72
+ }
73
+ }, [r, e, s]), /* @__PURE__ */ I(z, { $flexDirection: "row", $alignItems: "center", $borderRadius: 16, children: [
74
+ n && /* @__PURE__ */ $(M, { children: n }),
75
+ /* @__PURE__ */ $(
76
+ b,
77
+ {
78
+ $alignItems: "center",
79
+ $animate: e,
80
+ $background: t,
81
+ $borderRadius: 16,
82
+ $isIcon: !!n,
83
+ $isVisible: r,
84
+ $size: T,
85
+ $hidden: !r,
86
+ children: i
87
+ }
88
+ )
89
+ ] });
90
+ }, S = g(j);
91
+ export {
92
+ S as default
93
+ };
94
+ //# sourceMappingURL=open-close.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-close.js","sources":["../../../../src/features/class-timer/animations/open-close.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef, memo } from 'react';\nimport styled, { css, keyframes } from 'styled-components';\n\nimport FlexView from '../../ui/layout/flex-view';\n\nconst FillAnimation = keyframes`\n 0% {\n transform: translateX(-100%);\n }\n 100% {\n transform: translateX(0%);\n }\n`;\n\nconst EmptyAnimation = keyframes`\n 0% {\n transform: translateX(0%);\n }\n 100% {\n transform: translateX(-100%);\n }\n`;\n\nconst ANIMATION_TIME = 1 * 1000; // 1 seconds\nconst IDLE_TIME = 1.5 * 1000;\n\nconst StyledRow = styled(FlexView)`\n position: absolute;\n z-index: 10;\n overflow: hidden;\n`;\n\nconst IconWrapper = styled.div`\n position: absolute;\n cursor: pointer;\n z-index: 1;\n`;\n\nconst Wrapper = styled(FlexView)<{\n $animate: boolean;\n $isIcon: boolean;\n $isVisible: boolean;\n $size: number | null;\n}>`\n animation-name: ${({ $animate }) => ($animate ? FillAnimation : EmptyAnimation)};\n max-width: fit-content;\n animation-duration: ${ANIMATION_TIME / 1000}s;\n animation-timing-function: ease-in-out;\n animation-fill-mode: forwards;\n overflow: hidden;\n white-space: nowrap;\n height: 100%;\n ${({ $isIcon, $size }) =>\n $isIcon &&\n css`\n padding-left: ${$size}px;\n `};\n ${({ $isVisible }) =>\n !$isVisible &&\n css`\n visibility: hidden;\n `};\n`;\n\ninterface OpenCloseAnimationProps {\n background: 'ORANGE_4' | 'YELLOW_3' | 'BLACK';\n children: React.ReactNode;\n idleTime?: number;\n Icon?: React.ReactNode;\n onAnimationComplete?: () => void;\n onOpenAnimationComplete?: () => void;\n size?: number | null;\n visible: boolean;\n}\n\nconst OpenCloseAnimation: React.FC<OpenCloseAnimationProps> = ({\n background,\n children,\n Icon = null,\n onAnimationComplete,\n onOpenAnimationComplete,\n size = null,\n visible,\n idleTime = IDLE_TIME,\n}) => {\n const [animate, setAnimate] = useState(false);\n const prevAnimate = useRef(false);\n\n useEffect(() => {\n if (visible) {\n prevAnimate.current = false;\n setAnimate(true);\n }\n }, [visible]);\n\n useEffect(() => {\n if (animate) {\n const animateTimer = setTimeout(() => {\n prevAnimate.current = true;\n setAnimate(false);\n onOpenAnimationComplete?.();\n }, ANIMATION_TIME + idleTime);\n\n return () => {\n clearTimeout(animateTimer);\n };\n }\n }, [animate, onOpenAnimationComplete, idleTime]);\n\n useEffect(() => {\n if (visible && !animate && prevAnimate.current) {\n const hideTimer = setTimeout(() => {\n onAnimationComplete?.();\n }, ANIMATION_TIME);\n\n return () => {\n clearTimeout(hideTimer);\n };\n }\n }, [visible, animate, onAnimationComplete]);\n\n return (\n <StyledRow $flexDirection=\"row\" $alignItems=\"center\" $borderRadius={16}>\n {Icon && <IconWrapper>{Icon}</IconWrapper>}\n <Wrapper\n $alignItems=\"center\"\n $animate={animate}\n $background={background}\n $borderRadius={16}\n $isIcon={!!Icon}\n $isVisible={visible}\n $size={size}\n $hidden={!visible}\n >\n {children}\n </Wrapper>\n </StyledRow>\n );\n};\n\nexport default memo(OpenCloseAnimation);\n"],"names":["FillAnimation","keyframes","EmptyAnimation","ANIMATION_TIME","IDLE_TIME","StyledRow","styled","FlexView","IconWrapper","Wrapper","$animate","$isIcon","$size","css","$isVisible","OpenCloseAnimation","background","children","Icon","onAnimationComplete","onOpenAnimationComplete","size","visible","idleTime","animate","setAnimate","useState","prevAnimate","useRef","useEffect","animateTimer","hideTimer","jsx","OpenCloseAnimation$1","memo"],"mappings":";;;;AAKA,MAAMA,IAAgBC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAShBC,IAAiBD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASjBE,IAAiB,IAAI,KACrBC,IAAY,MAAM,KAElBC,IAAYC,EAAOC,CAAQ;AAAA;AAAA;AAAA;AAAA,GAM3BC,IAAcF,EAAO;AAAA;AAAA;AAAA;AAAA,GAMrBG,IAAUH,EAAOC,CAAQ;AAAA,oBAMX,CAAC,EAAE,UAAAG,EAAA,MAAgBA,IAAWV,IAAgBE,CAAe;AAAA;AAAA,wBAEzDC,IAAiB,GAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMzC,CAAC,EAAE,SAAAQ,GAAS,OAAAC,EAAA,MACZD,KACAE;AAAA,sBACkBD,CAAK;AAAA,KACtB;AAAA,IACD,CAAC,EAAE,YAAAE,EAAW,MACd,CAACA,KACDD;AAAA;AAAA,KAEC;AAAA,GAcCE,IAAwD,CAAC;AAAA,EAC7D,YAAAC;AAAA,EACA,UAAAC;AAAA,EACA,MAAAC,IAAO;AAAA,EACP,qBAAAC;AAAA,EACA,yBAAAC;AAAA,EACA,MAAAC,IAAO;AAAA,EACP,SAAAC;AAAA,EACA,UAAAC,IAAWnB;AACb,MAAM;AACJ,QAAM,CAACoB,GAASC,CAAU,IAAIC,EAAS,EAAK,GACtCC,IAAcC,EAAO,EAAK;AAEhC,SAAAC,EAAU,MAAM;AACd,IAAIP,MACFK,EAAY,UAAU,IACtBF,EAAW,EAAI;AAAA,EACjB,GACC,CAACH,CAAO,CAAC,GAEZO,EAAU,MAAM;AACd,QAAIL,GAAS;AACL,YAAAM,IAAe,WAAW,MAAM;AACpC,QAAAH,EAAY,UAAU,IACtBF,EAAW,EAAK,GACUL,KAAA,QAAAA;AAAA,MAAA,GACzBjB,IAAiBoB,CAAQ;AAE5B,aAAO,MAAM;AACX,qBAAaO,CAAY;AAAA,MAAA;AAAA,IAE7B;AAAA,EACC,GAAA,CAACN,GAASJ,GAAyBG,CAAQ,CAAC,GAE/CM,EAAU,MAAM;AACd,QAAIP,KAAW,CAACE,KAAWG,EAAY,SAAS;AACxC,YAAAI,IAAY,WAAW,MAAM;AACX,QAAAZ,KAAA,QAAAA;AAAA,SACrBhB,CAAc;AAEjB,aAAO,MAAM;AACX,qBAAa4B,CAAS;AAAA,MAAA;AAAA,IAE1B;AAAA,EACC,GAAA,CAACT,GAASE,GAASL,CAAmB,CAAC,qBAGvCd,GAAU,EAAA,gBAAe,OAAM,aAAY,UAAS,eAAe,IACjE,UAAA;AAAA,IAAQa,KAAA,gBAAAc,EAACxB,KAAa,UAAKU,EAAA,CAAA;AAAA,IAC5B,gBAAAc;AAAA,MAACvB;AAAA,MAAA;AAAA,QACC,aAAY;AAAA,QACZ,UAAUe;AAAA,QACV,aAAaR;AAAA,QACb,eAAe;AAAA,QACf,SAAS,CAAC,CAACE;AAAA,QACX,YAAYI;AAAA,QACZ,OAAOD;AAAA,QACP,SAAS,CAACC;AAAA,QAET,UAAAL;AAAA,MAAA;AAAA,IACH;AAAA,EACF,EAAA,CAAA;AAEJ,GAEegB,IAAAC,EAAKnB,CAAkB;"}
@@ -0,0 +1,44 @@
1
+ import { jsx as r } from "react/jsx-runtime";
2
+ import { memo as a } from "react";
3
+ import p, { css as $, keyframes as m } from "styled-components";
4
+ import x from "../../ui/layout/flex-view.js";
5
+ import { getTheme as d } from "../../ui/theme/get-theme.js";
6
+ const f = d(), { colors: l } = f, u = (e) => {
7
+ const t = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);
8
+ return t && t[1] && t[2] && t[3] ? [parseInt(t[1], 16), parseInt(t[2], 16), parseInt(t[3], 16)] : null;
9
+ }, s = (e, t) => {
10
+ const n = u(e);
11
+ return n ? `rgba(${n.join(", ")}, ${t})` : null;
12
+ }, c = (e) => m`
13
+ 0% {
14
+ box-shadow:
15
+ 0 2px 5px ${e},
16
+ 0 0 0 0 ${e},
17
+ 0 0 0 2px ${s(e, 0.5)},
18
+ 0 0 0 5px ${s(e, 0.5)};
19
+ }
20
+ 100% {
21
+ box-shadow:
22
+ 0 2px 5px ${s(e, 0.5)},
23
+ 0 0 0 2px ${s(e, 0.5)},
24
+ 0 0 0 5px ${s(e, 0.5)},
25
+ 0 0 0 10px ${s(e, 0)};
26
+ }
27
+ `, b = p.div`
28
+ ${({ $visible: e, $borderRadius: t, $color: n }) => e && $`
29
+ animation: ${c(n)} 1s linear infinite;
30
+ background: transparent;
31
+ border-radius: ${t}px;
32
+ z-index: 1;
33
+ `};
34
+ `, g = ({
35
+ children: e,
36
+ visible: t = !1,
37
+ color: n = "YELLOW_1",
38
+ borderRadius: i = 24,
39
+ ...o
40
+ }) => /* @__PURE__ */ r(x, { $position: "relative", $alignItems: "center", $justifyContent: "center", children: /* @__PURE__ */ r(b, { $visible: t, $color: l[n], $borderRadius: i, ...o, children: e }) }), w = a(g);
41
+ export {
42
+ w as default
43
+ };
44
+ //# sourceMappingURL=ripple.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ripple.js","sources":["../../../../src/features/class-timer/animations/ripple.tsx"],"sourcesContent":["import type { TColorNames } from '../../ui/types';\n\nimport { memo, type ReactNode } from 'react';\nimport styled, { keyframes, css } from 'styled-components';\n\nimport FlexView from '../../ui/layout/flex-view';\nimport { getTheme } from '../../ui/theme/get-theme';\n\nconst theme = getTheme();\nconst { colors: COLORS } = theme;\n\nconst toRGB = (hex: string): number[] | null => {\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n\n return result && result[1] && result[2] && result[3]\n ? [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)]\n : null;\n};\n\nconst toRGBA = (hex: string, alpha: number): string | null => {\n const rgb = toRGB(hex);\n\n return rgb ? `rgba(${rgb.join(', ')}, ${alpha})` : null;\n};\n\nconst pulse = (color: string) => keyframes`\n 0% {\n box-shadow: \n 0 2px 5px ${color},\n 0 0 0 0 ${color},\n 0 0 0 2px ${toRGBA(color, 0.5)},\n 0 0 0 5px ${toRGBA(color, 0.5)};\n }\n 100% {\n box-shadow:\n 0 2px 5px ${toRGBA(color, 0.5)},\n 0 0 0 2px ${toRGBA(color, 0.5)},\n 0 0 0 5px ${toRGBA(color, 0.5)},\n 0 0 0 10px ${toRGBA(color, 0)};\n }\n`;\n\ninterface PulseProps {\n $visible: boolean;\n $borderRadius: number;\n $color: string;\n}\n\nconst Pulse = styled.div<PulseProps>`\n ${({ $visible, $borderRadius, $color }) =>\n $visible &&\n css`\n animation: ${pulse($color)} 1s linear infinite;\n background: transparent;\n border-radius: ${$borderRadius}px;\n z-index: 1;\n `};\n`;\n\ninterface PulsatingProps {\n children: ReactNode;\n visible?: boolean;\n color?: TColorNames;\n borderRadius?: number;\n}\n\nconst Pulsating = ({\n children,\n visible = false,\n color = 'YELLOW_1',\n borderRadius = 24,\n ...other\n}: PulsatingProps) => (\n <FlexView $position=\"relative\" $alignItems=\"center\" $justifyContent=\"center\">\n <Pulse $visible={visible} $color={COLORS[color]} $borderRadius={borderRadius} {...other}>\n {children}\n </Pulse>\n </FlexView>\n);\n\nexport default memo(Pulsating);\n"],"names":["theme","getTheme","COLORS","toRGB","hex","result","toRGBA","alpha","rgb","pulse","color","keyframes","Pulse","styled","$visible","$borderRadius","$color","css","Pulsating","children","visible","borderRadius","other","jsx","FlexView","Ripple","memo"],"mappings":";;;;;AAQA,MAAMA,IAAQC,EAAS,GACjB,EAAE,QAAQC,EAAW,IAAAF,GAErBG,IAAQ,CAACC,MAAiC;AACxC,QAAAC,IAAS,4CAA4C,KAAKD,CAAG;AAEnE,SAAOC,KAAUA,EAAO,CAAC,KAAKA,EAAO,CAAC,KAAKA,EAAO,CAAC,IAC/C,CAAC,SAASA,EAAO,CAAC,GAAG,EAAE,GAAG,SAASA,EAAO,CAAC,GAAG,EAAE,GAAG,SAASA,EAAO,CAAC,GAAG,EAAE,CAAC,IAC1E;AACN,GAEMC,IAAS,CAACF,GAAaG,MAAiC;AACtD,QAAAC,IAAML,EAAMC,CAAG;AAEd,SAAAI,IAAM,QAAQA,EAAI,KAAK,IAAI,CAAC,KAAKD,CAAK,MAAM;AACrD,GAEME,IAAQ,CAACC,MAAkBC;AAAA;AAAA;AAAA,kBAGfD,CAAK;AAAA,gBACPA,CAAK;AAAA,kBACHJ,EAAOI,GAAO,GAAG,CAAC;AAAA,kBAClBJ,EAAOI,GAAO,GAAG,CAAC;AAAA;AAAA;AAAA;AAAA,kBAIlBJ,EAAOI,GAAO,GAAG,CAAC;AAAA,kBAClBJ,EAAOI,GAAO,GAAG,CAAC;AAAA,kBAClBJ,EAAOI,GAAO,GAAG,CAAC;AAAA,mBACjBJ,EAAOI,GAAO,CAAC,CAAC;AAAA;AAAA,GAU7BE,IAAQC,EAAO;AAAA,IACjB,CAAC,EAAE,UAAAC,GAAU,eAAAC,GAAe,QAAAC,QAC5BF,KACAG;AAAA,mBACeR,EAAMO,CAAM,CAAC;AAAA;AAAA,uBAETD,CAAa;AAAA;AAAA,KAE/B;AAAA,GAUCG,IAAY,CAAC;AAAA,EACjB,UAAAC;AAAA,EACA,SAAAC,IAAU;AAAA,EACV,OAAAV,IAAQ;AAAA,EACR,cAAAW,IAAe;AAAA,EACf,GAAGC;AACL,MACE,gBAAAC,EAACC,KAAS,WAAU,YAAW,aAAY,UAAS,iBAAgB,UAClE,UAAC,gBAAAD,EAAAX,GAAA,EAAM,UAAUQ,GAAS,QAAQlB,EAAOQ,CAAK,GAAG,eAAeW,GAAe,GAAGC,GAC/E,UAAAH,EACH,CAAA,EACF,CAAA,GAGaM,IAAAC,EAAKR,CAAS;"}
@@ -0,0 +1,140 @@
1
+ import { jsx as l, jsxs as F } from "react/jsx-runtime";
2
+ import { memo as Y, useMemo as f, useState as $, useCallback as x, useEffect as S, useRef as q } from "react";
3
+ import z from "../../assets/line-icons/icons/clock2.js";
4
+ import B from "../hooks/use-visibility-change.js";
5
+ import I from "../ui/layout/flex-view.js";
6
+ import H from "./animate.js";
7
+ import J from "./animations/ripple.js";
8
+ import K from "./clock.js";
9
+ import { START_TIMER as P, getClockColor as Q, ANIMATION_TIME as A, LAST_FIVE as U, IconWrapper as Z } from "./constants.js";
10
+ import ee from "./timer.js";
11
+ const te = (N) => {
12
+ const {
13
+ classDuration: e,
14
+ classStartedTime: r = 0,
15
+ extendedTime: t = 0,
16
+ ongoing: v,
17
+ onComplete: o,
18
+ onExtendClass: O,
19
+ onExtendedTimeStart: h,
20
+ showExtendIcon: V = !1,
21
+ updateWithExtendedTime: c = !1
22
+ } = N, d = (+/* @__PURE__ */ new Date() - +r) / 1e3, m = B(), k = f(() => t ? Math.floor(e - d) <= t * 60 : !1, [e, t, d]), [a, X] = $(k), u = f(() => {
23
+ const n = (+/* @__PURE__ */ new Date() - +r) / 1e3, p = Math.floor(e - n);
24
+ return c || !t || p <= t * 60 ? e : e - t * 60;
25
+ }, [e, t, r, c]), [s, R] = $(u), w = f(() => s + +r / 1e3, [s, r]), C = f(() => !!(d >= s - P || a || c && t), [d, s, a, c, t]), [b, D] = $(!1), T = Math.floor(s - d), [_, M] = $(C), G = Q({
26
+ remainingTime: T,
27
+ updateWithExtendedTime: c,
28
+ extendedTime: t,
29
+ extendedTimeStarted: a
30
+ }), g = x(() => {
31
+ X(!0), R(u), h == null || h();
32
+ }, [u, h]), E = x(() => {
33
+ D(!0);
34
+ }, []), y = f(
35
+ () => [
36
+ {
37
+ at: A.LAST_TEN,
38
+ callback: E,
39
+ id: "rem-10min"
40
+ },
41
+ {
42
+ at: A.LAST_FIVE,
43
+ callback: E,
44
+ id: "rem-5min"
45
+ }
46
+ ],
47
+ [E]
48
+ ), W = x(() => {
49
+ if (t && !a && !c) {
50
+ g();
51
+ return;
52
+ }
53
+ o == null || o();
54
+ }, [
55
+ t,
56
+ a,
57
+ o,
58
+ g,
59
+ c
60
+ ]);
61
+ S(() => {
62
+ const n = +/* @__PURE__ */ new Date() / 1e3 >= +r / 1e3 + e && e;
63
+ m && n && (o == null || o());
64
+ }, [e, r, m, o]), S(() => {
65
+ e && R(u);
66
+ }, [e, u]), S(() => {
67
+ m && k && !a && g();
68
+ }, [m, g, a, k]), S(() => {
69
+ s && r && m && M(C);
70
+ }, [r, s, C, m]);
71
+ const L = q(/* @__PURE__ */ new Set()), i = f(
72
+ () => y.filter((n) => {
73
+ const p = n.id || `multi-reminder-${n.at}`;
74
+ return !L.current.has(p) && T >= n.at;
75
+ }).sort((n, p) => p.at - n.at)[0],
76
+ [y, T]
77
+ ), j = x(() => {
78
+ if (!i) return;
79
+ const n = i.id || `multi-reminder-${i.at}`;
80
+ L.current.add(n), typeof i.callback == "function" && i.callback();
81
+ }, [i]);
82
+ return !v || d >= 0 && T <= 0 ? null : /* @__PURE__ */ l(I, { $flexDirection: "row", $alignItems: "center", children: /* @__PURE__ */ F(I, { $position: "relative", $flexDirection: "row", $alignItems: "center", children: [
83
+ /* @__PURE__ */ l(
84
+ H,
85
+ {
86
+ animateClock: b,
87
+ classStartedTime: +r,
88
+ duration: s,
89
+ onExtendClass: O,
90
+ setAnimateClock: D,
91
+ setStartTimer: M,
92
+ showExtendIcon: !a && V
93
+ }
94
+ ),
95
+ /* @__PURE__ */ l(
96
+ J,
97
+ {
98
+ color: T <= U ? "ORANGE_3" : "YELLOW_3",
99
+ visible: !b && _,
100
+ children: /* @__PURE__ */ F(
101
+ I,
102
+ {
103
+ $flexDirection: "row",
104
+ $alignItems: "center",
105
+ $background: "GREY_1",
106
+ $borderRadiusX: 1.25,
107
+ $gutterX: 0.5,
108
+ $gapX: 0.25,
109
+ $flexGapX: 0.25,
110
+ $position: "relative",
111
+ children: [
112
+ /* @__PURE__ */ l(Z, { $iconColor: G, children: /* @__PURE__ */ l(z, {}) }),
113
+ m && (_ ? /* @__PURE__ */ l(
114
+ ee,
115
+ {
116
+ endTime: w,
117
+ onComplete: W,
118
+ reminder: i == null ? void 0 : i.at,
119
+ onReminder: j
120
+ },
121
+ w
122
+ ) : /* @__PURE__ */ l(
123
+ K,
124
+ {
125
+ completionTime: e - A.LAST_TEN,
126
+ onComplete: E,
127
+ startedOn: new Date(r)
128
+ }
129
+ ))
130
+ ]
131
+ }
132
+ )
133
+ }
134
+ )
135
+ ] }) });
136
+ }, ue = Y(te);
137
+ export {
138
+ ue as default
139
+ };
140
+ //# sourceMappingURL=class-timer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"class-timer.js","sources":["../../../src/features/class-timer/class-timer.tsx"],"sourcesContent":["import type { IClassTimeProps, MultiReminder } from './class-time-types';\n\nimport { useState, useCallback, useEffect, useMemo, useRef, memo } from 'react';\n\nimport Clock2Icon from '../../assets/line-icons/icons/clock2';\nimport useVisibilityChange from '../hooks/use-visibility-change';\nimport FlexView from '../ui/layout/flex-view';\nimport Animate from './animate';\nimport Ripple from './animations/ripple';\nimport Clock from './clock';\nimport { ANIMATION_TIME, getClockColor, IconWrapper, LAST_FIVE, START_TIMER } from './constants';\nimport Timer from './timer';\n\nconst ClassTime = (props: IClassTimeProps) => {\n const {\n classDuration,\n classStartedTime = 0,\n extendedTime = 0,\n ongoing,\n onComplete,\n onExtendClass,\n onExtendedTimeStart,\n showExtendIcon = false,\n updateWithExtendedTime = false,\n } = props;\n\n const elapsedTime = (+new Date() - +classStartedTime) / 1000;\n const isTabActive = useVisibilityChange();\n\n const hasExtendedTimeStarted = useMemo(() => {\n if (!extendedTime) return false;\n\n const orgRemainingTime = Math.floor(classDuration - elapsedTime);\n\n return orgRemainingTime <= extendedTime * 60;\n }, [classDuration, extendedTime, elapsedTime]);\n\n const [extendedTimeStarted, setExtendedTimeStarted] = useState(hasExtendedTimeStarted);\n\n const computedDuration = useMemo(() => {\n const elapsedT = (+new Date() - +classStartedTime) / 1000;\n const remainingT = Math.floor(classDuration - elapsedT);\n\n if (updateWithExtendedTime || !extendedTime || remainingT <= extendedTime * 60)\n return classDuration;\n\n return classDuration - extendedTime * 60;\n }, [classDuration, extendedTime, classStartedTime, updateWithExtendedTime]);\n\n const [duration, setDuration] = useState(computedDuration);\n const endTime = useMemo(() => duration + +classStartedTime / 1000, [duration, classStartedTime]);\n\n const canStartTimer = useMemo(() => {\n return !!(\n elapsedTime >= duration - START_TIMER ||\n extendedTimeStarted ||\n (updateWithExtendedTime && extendedTime)\n );\n }, [elapsedTime, duration, extendedTimeStarted, updateWithExtendedTime, extendedTime]);\n\n const [animateClock, setAnimateClock] = useState(false);\n const remainingTime = Math.floor(duration - elapsedTime); // in seconds\n const [startTimer, setStartTimer] = useState(canStartTimer);\n const clockColor = getClockColor({\n remainingTime,\n updateWithExtendedTime,\n extendedTime,\n extendedTimeStarted,\n });\n\n const handleStartExtendedTime = useCallback(() => {\n setExtendedTimeStarted(true);\n setDuration(computedDuration);\n onExtendedTimeStart?.();\n }, [computedDuration, onExtendedTimeStart]);\n\n const handleStartAnimation = useCallback(() => {\n setAnimateClock(true);\n }, []);\n\n const animationReminders = useMemo(\n () => [\n {\n at: ANIMATION_TIME.LAST_TEN,\n callback: handleStartAnimation,\n id: 'rem-10min',\n },\n\n {\n at: ANIMATION_TIME.LAST_FIVE,\n callback: handleStartAnimation,\n id: 'rem-5min',\n },\n ],\n [handleStartAnimation],\n );\n\n const handleTimerComplete = useCallback(() => {\n if (extendedTime && !extendedTimeStarted && !updateWithExtendedTime) {\n handleStartExtendedTime();\n\n return;\n }\n onComplete?.();\n }, [\n extendedTime,\n extendedTimeStarted,\n onComplete,\n handleStartExtendedTime,\n updateWithExtendedTime,\n ]);\n\n useEffect(() => {\n const isClassCompleted =\n +new Date() / 1000 >= +classStartedTime / 1000 + classDuration && classDuration;\n\n if (isTabActive && isClassCompleted) {\n onComplete?.();\n }\n }, [classDuration, classStartedTime, isTabActive, onComplete]);\n\n useEffect(() => {\n if (classDuration) {\n setDuration(computedDuration);\n }\n }, [classDuration, computedDuration]);\n\n useEffect(() => {\n if (isTabActive && hasExtendedTimeStarted && !extendedTimeStarted) {\n handleStartExtendedTime();\n }\n }, [isTabActive, handleStartExtendedTime, extendedTimeStarted, hasExtendedTimeStarted]);\n\n useEffect(() => {\n if (duration && classStartedTime && isTabActive) {\n setStartTimer(canStartTimer);\n }\n }, [classStartedTime, duration, canStartTimer, isTabActive]);\n\n const firedReminders = useRef<Set<string>>(new Set());\n const nextReminder = useMemo(\n () =>\n animationReminders\n .filter((r: MultiReminder) => {\n const key = r.id || `multi-reminder-${r.at}`;\n const alreadyFired = firedReminders.current.has(key);\n\n return !alreadyFired && remainingTime >= r.at;\n })\n .sort((a: { at: number }, b: { at: number }) => b.at - a.at)[0],\n [animationReminders, remainingTime],\n );\n\n const handleMultiReminder = useCallback(() => {\n if (!nextReminder) return;\n\n const key = nextReminder.id || `multi-reminder-${nextReminder.at}`;\n\n firedReminders.current.add(key);\n\n if (typeof nextReminder.callback === 'function') {\n nextReminder.callback();\n }\n }, [nextReminder]);\n\n if (!ongoing || (elapsedTime >= 0 && remainingTime <= 0)) {\n return null;\n }\n\n return (\n <FlexView $flexDirection=\"row\" $alignItems=\"center\">\n <FlexView $position=\"relative\" $flexDirection=\"row\" $alignItems=\"center\">\n <Animate\n animateClock={animateClock}\n classStartedTime={+classStartedTime}\n duration={duration}\n onExtendClass={onExtendClass}\n setAnimateClock={setAnimateClock}\n setStartTimer={setStartTimer}\n showExtendIcon={!extendedTimeStarted && showExtendIcon}\n />\n <Ripple\n color={remainingTime <= LAST_FIVE ? 'ORANGE_3' : 'YELLOW_3'}\n visible={!animateClock && startTimer}\n >\n <FlexView\n $flexDirection=\"row\"\n $alignItems=\"center\"\n $background=\"GREY_1\"\n $borderRadiusX={1.25}\n $gutterX={0.5}\n $gapX={0.25}\n $flexGapX={0.25}\n $position=\"relative\"\n >\n <IconWrapper $iconColor={clockColor}>\n <Clock2Icon />\n </IconWrapper>\n {isTabActive &&\n (startTimer ? (\n <Timer\n endTime={endTime}\n key={endTime}\n onComplete={handleTimerComplete}\n reminder={nextReminder?.at}\n onReminder={handleMultiReminder}\n />\n ) : (\n <Clock\n completionTime={classDuration - ANIMATION_TIME.LAST_TEN}\n onComplete={handleStartAnimation}\n startedOn={new Date(classStartedTime)}\n />\n ))}\n </FlexView>\n </Ripple>\n </FlexView>\n </FlexView>\n );\n};\n\nexport default memo(ClassTime);\n"],"names":["ClassTime","props","classDuration","classStartedTime","extendedTime","ongoing","onComplete","onExtendClass","onExtendedTimeStart","showExtendIcon","updateWithExtendedTime","elapsedTime","isTabActive","useVisibilityChange","hasExtendedTimeStarted","useMemo","extendedTimeStarted","setExtendedTimeStarted","useState","computedDuration","elapsedT","remainingT","duration","setDuration","endTime","canStartTimer","START_TIMER","animateClock","setAnimateClock","remainingTime","startTimer","setStartTimer","clockColor","getClockColor","handleStartExtendedTime","useCallback","handleStartAnimation","animationReminders","ANIMATION_TIME","handleTimerComplete","useEffect","isClassCompleted","firedReminders","useRef","nextReminder","r","key","a","b","handleMultiReminder","jsx","FlexView","jsxs","Animate","Ripple","LAST_FIVE","IconWrapper","Clock2Icon","Timer","Clock","classTimer","memo"],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { jsx as d } from "react/jsx-runtime";
2
+ import { memo as w, useState as E, useRef as m, useCallback as $, useEffect as s } from "react";
3
+ import b from "../ui/text/text.js";
4
+ import { formatTimeInHHMMSS as h } from "../utils/utils.js";
5
+ import { getTime as f, TIMEOUT_INTERVAL as i } from "./constants.js";
6
+ const k = ({
7
+ completionTime: t = null,
8
+ onComplete: o = () => {
9
+ },
10
+ startedOn: u,
11
+ textVariant: a = "ab2-bold",
12
+ textColor: p
13
+ }) => {
14
+ const [e, T] = E(f(u)), r = m(null), l = h(e), n = m(null), c = $(() => {
15
+ performance.now() - (n.current || 0) >= 1e3 && (T(f(u)), n.current = performance.now()), r.current = setTimeout(c, i);
16
+ }, [u]);
17
+ return s(() => {
18
+ t && e >= t && e <= t + 5 && (r.current && (clearTimeout(r.current), r.current = null), o());
19
+ }, [t, e, o]), s(() => (r.current && (clearTimeout(r.current), r.current = null), n.current === null && (n.current = performance.now()), r.current = setTimeout(c, i), () => {
20
+ r.current && clearTimeout(r.current);
21
+ }), [c]), e < 0 ? null : /* @__PURE__ */ d(b, { $width: l.length > 5 ? 71 : 57, $renderAs: a, $color: p, children: l });
22
+ }, C = w(k);
23
+ export {
24
+ C as default
25
+ };
26
+ //# sourceMappingURL=clock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clock.js","sources":["../../../src/features/class-timer/clock.tsx"],"sourcesContent":["import type { TColorNames, TTextVariants } from '../ui/types';\n\nimport { useState, useEffect, useCallback, useRef, memo } from 'react';\n\nimport Text from '../ui/text/text';\nimport { formatTimeInHHMMSS } from '../utils/utils';\nimport { getTime, TIMEOUT_INTERVAL } from './constants';\n\ninterface IClockProps {\n completionTime?: number | null;\n onComplete?: () => void;\n startedOn: Date;\n textVariant?: TTextVariants;\n textColor?: TColorNames;\n}\n\nconst Clock = ({\n completionTime = null,\n onComplete = () => {},\n startedOn,\n textVariant = 'ab2-bold',\n textColor,\n}: IClockProps) => {\n const [elapsedTime, setElapsedTime] = useState(getTime(startedOn));\n const timerRef = useRef<NodeJS.Timeout | null>(null);\n const formattedTime = formatTimeInHHMMSS(elapsedTime);\n const start = useRef<number | null>(null);\n const timer = useCallback(() => {\n const timestamp = performance.now();\n\n const elapsed = timestamp - (start.current || 0);\n\n if (elapsed >= 1000) {\n setElapsedTime(getTime(startedOn));\n\n start.current = performance.now();\n }\n\n timerRef.current = setTimeout(timer, TIMEOUT_INTERVAL);\n }, [startedOn]);\n\n useEffect(() => {\n if (completionTime && elapsedTime >= completionTime && elapsedTime <= completionTime + 5) {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n\n onComplete();\n }\n }, [completionTime, elapsedTime, onComplete]);\n\n useEffect(() => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n\n if (start.current === null) {\n start.current = performance.now();\n }\n\n timerRef.current = setTimeout(timer, TIMEOUT_INTERVAL);\n\n return () => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n }\n };\n }, [timer]);\n\n if (elapsedTime < 0) return null;\n\n return (\n <Text $width={formattedTime.length > 5 ? 71 : 57} $renderAs={textVariant} $color={textColor}>\n {formattedTime}\n </Text>\n );\n};\n\nexport default memo(Clock);\n"],"names":["Clock","completionTime","onComplete","startedOn","textVariant","textColor","elapsedTime","setElapsedTime","useState","getTime","timerRef","useRef","formattedTime","formatTimeInHHMMSS","start","timer","useCallback","TIMEOUT_INTERVAL","useEffect","jsx","Text","Clock$1","memo"],"mappings":";;;;;AAgBA,MAAMA,IAAQ,CAAC;AAAA,EACb,gBAAAC,IAAiB;AAAA,EACjB,YAAAC,IAAa,MAAM;AAAA,EAAC;AAAA,EACpB,WAAAC;AAAA,EACA,aAAAC,IAAc;AAAA,EACd,WAAAC;AACF,MAAmB;AACjB,QAAM,CAACC,GAAaC,CAAc,IAAIC,EAASC,EAAQN,CAAS,CAAC,GAC3DO,IAAWC,EAA8B,IAAI,GAC7CC,IAAgBC,EAAmBP,CAAW,GAC9CQ,IAAQH,EAAsB,IAAI,GAClCI,IAAQC,EAAY,MAAM;AAK9B,IAJkB,YAAY,SAEDF,EAAM,WAAW,MAE/B,QACEP,EAAAE,EAAQN,CAAS,CAAC,GAE3BW,EAAA,UAAU,YAAY,QAGrBJ,EAAA,UAAU,WAAWK,GAAOE,CAAgB;AAAA,EAAA,GACpD,CAACd,CAAS,CAAC;AAgCV,SA9BJe,EAAU,MAAM;AACd,IAAIjB,KAAkBK,KAAeL,KAAkBK,KAAeL,IAAiB,MACjFS,EAAS,YACX,aAAaA,EAAS,OAAO,GAC7BA,EAAS,UAAU,OAGVR;EAEZ,GAAA,CAACD,GAAgBK,GAAaJ,CAAU,CAAC,GAE5CgB,EAAU,OACJR,EAAS,YACX,aAAaA,EAAS,OAAO,GAC7BA,EAAS,UAAU,OAGjBI,EAAM,YAAY,SACdA,EAAA,UAAU,YAAY,QAGrBJ,EAAA,UAAU,WAAWK,GAAOE,CAAgB,GAE9C,MAAM;AACX,IAAIP,EAAS,WACX,aAAaA,EAAS,OAAO;AAAA,EAC/B,IAED,CAACK,CAAK,CAAC,GAENT,IAAc,IAAU,OAGzB,gBAAAa,EAAAC,GAAA,EAAK,QAAQR,EAAc,SAAS,IAAI,KAAK,IAAI,WAAWR,GAAa,QAAQC,GAC/E,UACHO,EAAA,CAAA;AAEJ,GAEeS,IAAAC,EAAKtB,CAAK;"}
@@ -0,0 +1,27 @@
1
+ import c from "styled-components";
2
+ import n from "../ui/layout/flex-view.js";
3
+ const s = c(n)`
4
+ svg {
5
+ color: ${(o) => o.theme.colors[o.$iconColor]};
6
+ }
7
+ `, t = 60 * 10, e = 60 * 5, L = {
8
+ LAST_TEN: t + 2,
9
+ LAST_FIVE: e + 2
10
+ }, A = 2e3, l = 1500, i = 250, m = ({
11
+ remainingTime: o,
12
+ updateWithExtendedTime: r,
13
+ extendedTime: T,
14
+ extendedTimeStarted: E
15
+ }) => o <= e ? "ORANGE_3" : o <= t || r && T || E ? "YELLOW_3" : "BLACK_3", M = (o) => Math.floor(((/* @__PURE__ */ new Date()).getTime() - o.getTime()) / 1e3);
16
+ export {
17
+ L as ANIMATION_TIME,
18
+ l as EXTEND_IDLE,
19
+ s as IconWrapper,
20
+ e as LAST_FIVE,
21
+ t as START_TIMER,
22
+ i as TIMEOUT_INTERVAL,
23
+ A as TIME_LEFT_IDLE,
24
+ m as getClockColor,
25
+ M as getTime
26
+ };
27
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sources":["../../../src/features/class-timer/constants.ts"],"sourcesContent":["import type { TColorNames } from '../ui/types';\n\nimport styled from 'styled-components';\n\nimport FlexView from '../ui/layout/flex-view';\n\nconst IconWrapper = styled(FlexView)<{ $iconColor: TColorNames }>`\n svg {\n color: ${props => props.theme.colors[props.$iconColor]};\n }\n`;\n\nconst START_TIMER = 60 * 10; // 10 minutes\nconst LAST_FIVE = 60 * 5; // 5 minutes\nconst ANIMATION_TIME = {\n LAST_TEN: START_TIMER + 2,\n LAST_FIVE: LAST_FIVE + 2,\n};\n\nconst TIME_LEFT_IDLE = 2000;\nconst EXTEND_IDLE = 1500;\nconst TIMEOUT_INTERVAL = 250;\n\ninterface IClockColorParams {\n remainingTime: number;\n updateWithExtendedTime: boolean;\n extendedTime: number;\n extendedTimeStarted: boolean;\n}\n\nconst getClockColor = ({\n remainingTime,\n updateWithExtendedTime,\n extendedTime,\n extendedTimeStarted,\n}: IClockColorParams): TColorNames => {\n if (remainingTime <= LAST_FIVE) return 'ORANGE_3';\n\n if (\n remainingTime <= START_TIMER ||\n (updateWithExtendedTime && extendedTime) ||\n extendedTimeStarted\n )\n return 'YELLOW_3';\n\n return 'BLACK_3';\n};\n\nconst getTime = (startedOn: Date): number => {\n return Math.floor((new Date().getTime() - startedOn.getTime()) / 1000);\n};\n\nexport {\n getClockColor,\n getTime,\n IconWrapper,\n ANIMATION_TIME,\n START_TIMER,\n LAST_FIVE,\n TIME_LEFT_IDLE,\n EXTEND_IDLE,\n TIMEOUT_INTERVAL,\n};\n"],"names":["IconWrapper","styled","FlexView","props","START_TIMER","LAST_FIVE","ANIMATION_TIME","TIME_LEFT_IDLE","EXTEND_IDLE","TIMEOUT_INTERVAL","getClockColor","remainingTime","updateWithExtendedTime","extendedTime","extendedTimeStarted","getTime","startedOn"],"mappings":";;AAMM,MAAAA,IAAcC,EAAOC,CAAQ;AAAA;AAAA,aAEtB,OAASC,EAAM,MAAM,OAAOA,EAAM,UAAU,CAAC;AAAA;AAAA,GAIpDC,IAAc,KAAK,IACnBC,IAAY,KAAK,GACjBC,IAAiB;AAAA,EACrB,UAAUF,IAAc;AAAA,EACxB,WAAWC,IAAY;AACzB,GAEME,IAAiB,KACjBC,IAAc,MACdC,IAAmB,KASnBC,IAAgB,CAAC;AAAA,EACrB,eAAAC;AAAA,EACA,wBAAAC;AAAA,EACA,cAAAC;AAAA,EACA,qBAAAC;AACF,MACMH,KAAiBN,IAAkB,aAGrCM,KAAiBP,KAChBQ,KAA0BC,KAC3BC,IAEO,aAEF,WAGHC,IAAU,CAACC,MACR,KAAK,QAAO,oBAAI,KAAK,GAAE,YAAYA,EAAU,QAAQ,KAAK,GAAI;"}
@@ -0,0 +1,65 @@
1
+ import { jsxs as x, jsx as i } from "react/jsx-runtime";
2
+ import { memo as I, useState as b, useRef as f, useCallback as A, useEffect as p } from "react";
3
+ import M from "styled-components";
4
+ import k from "../../assets/line-icons/icons/clock2.js";
5
+ import E from "../ui/layout/flex-view.js";
6
+ import $ from "../ui/text/text.js";
7
+ import { formatTimeInHHMMSS as R } from "../utils/utils.js";
8
+ import { TIMEOUT_INTERVAL as T, IconWrapper as X } from "./constants.js";
9
+ const D = M(E)`
10
+ border-radius: 20px;
11
+ position: relative;
12
+ z-index: 7;
13
+ gap: 8px;
14
+ `, L = ({
15
+ styledTimer: d = !1,
16
+ endTime: o,
17
+ onComplete: e,
18
+ onReminder: u,
19
+ reminder: a,
20
+ iconColor: h = "BLACK",
21
+ textColor: m = "BLACK",
22
+ textVariant: l = "ac3-black"
23
+ }) => {
24
+ const [t, g] = b(Math.ceil(o - Date.now() / 1e3)), r = f(null), c = f(null), s = A(() => {
25
+ if (performance.now() - (c.current || 0) >= 1e3) {
26
+ const w = Math.ceil(o - Date.now() / 1e3);
27
+ g(w), c.current = performance.now();
28
+ }
29
+ r.current = setTimeout(s, T);
30
+ }, [o]);
31
+ p(() => (r.current && (clearTimeout(r.current), r.current = null), c.current === null && (c.current = performance.now()), r.current = setTimeout(s, T), () => {
32
+ r.current && clearTimeout(r.current);
33
+ }), [s]), p(() => {
34
+ a && u && t === a && u(), t <= 0 && (r.current && (clearTimeout(r.current), r.current = null), e == null || e());
35
+ }, [a, u, e, t]);
36
+ const n = R(t);
37
+ return d ? /* @__PURE__ */ x(
38
+ D,
39
+ {
40
+ $flexDirection: "row",
41
+ $alignItems: "center",
42
+ $background: "GREY_1",
43
+ $borderRadiusX: 1.25,
44
+ $gutterX: 0.75,
45
+ $gapX: 0.15,
46
+ $flexGapX: 0.25,
47
+ children: [
48
+ /* @__PURE__ */ i(X, { $iconColor: h, children: /* @__PURE__ */ i(k, {}) }),
49
+ /* @__PURE__ */ i(
50
+ $,
51
+ {
52
+ $width: n.length > 5 ? 71 : 57,
53
+ $renderAs: l,
54
+ $color: m,
55
+ children: n
56
+ }
57
+ )
58
+ ]
59
+ }
60
+ ) : /* @__PURE__ */ i($, { $width: n.length > 5 ? 71 : 57, $renderAs: l, $color: m, children: n });
61
+ }, z = I(L);
62
+ export {
63
+ z as default
64
+ };
65
+ //# sourceMappingURL=timer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timer.js","sources":["../../../src/features/class-timer/timer.tsx"],"sourcesContent":["import type { TColorNames, TTextVariants } from '../ui/types';\n\nimport { memo, useCallback, useEffect, useRef, useState } from 'react';\nimport styled from 'styled-components';\n\nimport Clock2Icon from '../../assets/line-icons/icons/clock2';\nimport FlexView from '../ui/layout/flex-view';\nimport Text from '../ui/text/text';\nimport { formatTimeInHHMMSS } from '../utils/utils';\nimport { IconWrapper, TIMEOUT_INTERVAL } from './constants';\n\nconst TimeWrapper = styled(FlexView)`\n border-radius: 20px;\n position: relative;\n z-index: 7;\n gap: 8px;\n`;\n\ninterface ITimerProps {\n styledTimer?: boolean;\n endTime: number;\n onComplete?: () => void;\n onReminder?: () => void;\n reminder?: number;\n iconColor?: TColorNames;\n textColor?: TColorNames;\n textVariant?: TTextVariants;\n}\n\nconst Timer = ({\n styledTimer = false,\n endTime,\n onComplete,\n onReminder,\n reminder,\n iconColor = 'BLACK',\n textColor = 'BLACK',\n textVariant = 'ac3-black',\n}: ITimerProps) => {\n const [remainingTime, setRemainingTime] = useState(Math.ceil(endTime - Date.now() / 1000));\n const timerRef = useRef<NodeJS.Timeout | null>(null);\n const start = useRef<number | null>(null);\n const timer = useCallback(() => {\n const timestamp = performance.now();\n const elapsed = timestamp - (start.current || 0);\n\n if (elapsed >= 1000) {\n // only if 1s has elapsed\n const rt = Math.ceil(endTime - Date.now() / 1000);\n\n setRemainingTime(rt);\n start.current = performance.now();\n }\n\n timerRef.current = setTimeout(timer, TIMEOUT_INTERVAL);\n }, [endTime]);\n\n useEffect(() => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n\n if (start.current === null) {\n start.current = performance.now();\n }\n\n timerRef.current = setTimeout(timer, TIMEOUT_INTERVAL);\n\n return () => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n }\n };\n }, [timer]);\n\n useEffect(() => {\n if (reminder && onReminder && remainingTime === reminder) {\n onReminder();\n }\n\n if (remainingTime <= 0) {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n onComplete?.();\n }\n }, [reminder, onReminder, onComplete, remainingTime]);\n const formattedTime = formatTimeInHHMMSS(remainingTime);\n\n if (styledTimer) {\n return (\n <TimeWrapper\n $flexDirection=\"row\"\n $alignItems=\"center\"\n $background=\"GREY_1\"\n $borderRadiusX={1.25}\n $gutterX={0.75}\n $gapX={0.15}\n $flexGapX={0.25}\n >\n <IconWrapper $iconColor={iconColor}>\n <Clock2Icon />\n </IconWrapper>\n <Text\n $width={formattedTime.length > 5 ? 71 : 57}\n $renderAs={textVariant}\n $color={textColor}\n >\n {formattedTime}\n </Text>\n </TimeWrapper>\n );\n }\n\n return (\n <Text $width={formattedTime.length > 5 ? 71 : 57} $renderAs={textVariant} $color={textColor}>\n {formattedTime}\n </Text>\n );\n};\n\nexport default memo(Timer);\n"],"names":["TimeWrapper","styled","FlexView","Timer","styledTimer","endTime","onComplete","onReminder","reminder","iconColor","textColor","textVariant","remainingTime","setRemainingTime","useState","timerRef","useRef","start","timer","useCallback","rt","TIMEOUT_INTERVAL","useEffect","formattedTime","formatTimeInHHMMSS","jsxs","jsx","IconWrapper","Clock2Icon","Text","Timer$1","memo"],"mappings":";;;;;;;;AAWA,MAAMA,IAAcC,EAAOC,CAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,GAkB7BC,IAAQ,CAAC;AAAA,EACb,aAAAC,IAAc;AAAA,EACd,SAAAC;AAAA,EACA,YAAAC;AAAA,EACA,YAAAC;AAAA,EACA,UAAAC;AAAA,EACA,WAAAC,IAAY;AAAA,EACZ,WAAAC,IAAY;AAAA,EACZ,aAAAC,IAAc;AAChB,MAAmB;AACjB,QAAM,CAACC,GAAeC,CAAgB,IAAIC,EAAS,KAAK,KAAKT,IAAU,KAAK,QAAQ,GAAI,CAAC,GACnFU,IAAWC,EAA8B,IAAI,GAC7CC,IAAQD,EAAsB,IAAI,GAClCE,IAAQC,EAAY,MAAM;AAI9B,QAHkB,YAAY,SACDF,EAAM,WAAW,MAE/B,KAAM;AAEnB,YAAMG,IAAK,KAAK,KAAKf,IAAU,KAAK,IAAA,IAAQ,GAAI;AAEhD,MAAAQ,EAAiBO,CAAE,GACbH,EAAA,UAAU,YAAY;IAC9B;AAES,IAAAF,EAAA,UAAU,WAAWG,GAAOG,CAAgB;AAAA,EAAA,GACpD,CAAChB,CAAO,CAAC;AAEZ,EAAAiB,EAAU,OACJP,EAAS,YACX,aAAaA,EAAS,OAAO,GAC7BA,EAAS,UAAU,OAGjBE,EAAM,YAAY,SACdA,EAAA,UAAU,YAAY,QAGrBF,EAAA,UAAU,WAAWG,GAAOG,CAAgB,GAE9C,MAAM;AACX,IAAIN,EAAS,WACX,aAAaA,EAAS,OAAO;AAAA,EAC/B,IAED,CAACG,CAAK,CAAC,GAEVI,EAAU,MAAM;AACV,IAAAd,KAAYD,KAAcK,MAAkBJ,KACnCD,KAGTK,KAAiB,MACfG,EAAS,YACX,aAAaA,EAAS,OAAO,GAC7BA,EAAS,UAAU,OAERT,KAAA,QAAAA;AAAA,KAEd,CAACE,GAAUD,GAAYD,GAAYM,CAAa,CAAC;AAC9C,QAAAW,IAAgBC,EAAmBZ,CAAa;AAEtD,SAAIR,IAEA,gBAAAqB;AAAA,IAACzB;AAAA,IAAA;AAAA,MACC,gBAAe;AAAA,MACf,aAAY;AAAA,MACZ,aAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,UAAU;AAAA,MACV,OAAO;AAAA,MACP,WAAW;AAAA,MAEX,UAAA;AAAA,QAAA,gBAAA0B,EAACC,GAAY,EAAA,YAAYlB,GACvB,UAAA,gBAAAiB,EAACE,IAAW,CAAA,GACd;AAAA,QACA,gBAAAF;AAAA,UAACG;AAAA,UAAA;AAAA,YACC,QAAQN,EAAc,SAAS,IAAI,KAAK;AAAA,YACxC,WAAWZ;AAAA,YACX,QAAQD;AAAA,YAEP,UAAAa;AAAA,UAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,IAMH,gBAAAG,EAAAG,GAAA,EAAK,QAAQN,EAAc,SAAS,IAAI,KAAK,IAAI,WAAWZ,GAAa,QAAQD,GAC/E,UACHa,EAAA,CAAA;AAEJ,GAEeO,IAAAC,EAAK5B,CAAK;"}
@@ -0,0 +1,12 @@
1
+ import { useState as n, useCallback as l, useEffect as a } from "react";
2
+ const o = () => {
3
+ const [t, e] = n(document.visibilityState === "visible"), i = l(() => {
4
+ const s = document.visibilityState === "visible";
5
+ e(s);
6
+ }, [e]);
7
+ return a(() => (document.addEventListener("visibilitychange", i), () => document.removeEventListener("visibilitychange", i)), [i]), t;
8
+ }, c = o;
9
+ export {
10
+ c as default
11
+ };
12
+ //# sourceMappingURL=use-visibility-change.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-visibility-change.js","sources":["../../../src/features/hooks/use-visibility-change.tsx"],"sourcesContent":["import { useEffect, useState, useCallback } from 'react';\n\n/**\n * Custom hook to detect visibility change of the document.\n * Returns true if the document is visible, false otherwise.\n */\nconst useVisibilityChange = () => {\n const [isVisible, setIsVisible] = useState(document.visibilityState === 'visible');\n\n const onVisibilityChange = useCallback(() => {\n const isVisibleState = document.visibilityState === 'visible';\n\n setIsVisible(isVisibleState);\n }, [setIsVisible]);\n\n useEffect(() => {\n document.addEventListener('visibilitychange', onVisibilityChange);\n\n return () => document.removeEventListener('visibilitychange', onVisibilityChange);\n }, [onVisibilityChange]);\n\n return isVisible;\n};\n\nexport default useVisibilityChange;\n"],"names":["useVisibilityChange","isVisible","setIsVisible","useState","onVisibilityChange","useCallback","isVisibleState","useEffect","useVisibilityChange$1"],"mappings":";AAMA,MAAMA,IAAsB,MAAM;AAChC,QAAM,CAACC,GAAWC,CAAY,IAAIC,EAAS,SAAS,oBAAoB,SAAS,GAE3EC,IAAqBC,EAAY,MAAM;AACrC,UAAAC,IAAiB,SAAS,oBAAoB;AAEpD,IAAAJ,EAAaI,CAAc;AAAA,EAAA,GAC1B,CAACJ,CAAY,CAAC;AAEjB,SAAAK,EAAU,OACC,SAAA,iBAAiB,oBAAoBH,CAAkB,GAEzD,MAAM,SAAS,oBAAoB,oBAAoBA,CAAkB,IAC/E,CAACA,CAAkB,CAAC,GAEhBH;AACT,GAEAO,IAAeR;"}
@@ -15,7 +15,10 @@ const _ = {
15
15
  DESMOS_CALCULATOR: 2,
16
16
  GOAL_CHAPTER_SHEETS_MENU: 4,
17
17
  JOURNEY_OVERLAY: 1e3,
18
- CHAPTER_COMPLETED_LOTTIE: 5
18
+ CHAPTER_COMPLETED_LOTTIE: 5,
19
+ EXTEND_CLASS_ANIMATION_1: 24,
20
+ EXTEND_CLASS_ANIMATION_2: 25,
21
+ EXTEND_CLASS_ANIMATION_3: 26
19
22
  };
20
23
  export {
21
24
  _ as ZINDEX