@cuemath/leap 3.1.20-link.0 → 3.1.21

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.
@@ -1,48 +1,51 @@
1
- import { jsxs as k, jsx as C } from "react/jsx-runtime";
2
- import { memo as E, useState as a, useCallback as M, useMemo as x, useEffect as u } from "react";
3
- import y from "./modal.js";
4
- import I from "./modal-context.js";
5
- import { lockScroll as S, unlockScroll as h } from "./modal-helpers.js";
6
- const D = 500, T = E(({ children: w, modals: d, isUserAuthenticated: t }) => {
7
- const [o, c] = a(null), [f, v] = a(void 0), [s, r] = a(!1), m = M(
8
- (n, l) => {
9
- const i = d.find((P) => P.name === n);
10
- if (!i)
11
- throw new Error(`Modal with name "${n}" not found`);
12
- if (i.isPrivate && !t)
1
+ import { jsxs as x, jsx as y } from "react/jsx-runtime";
2
+ import { memo as D, useState as d, useRef as I, useCallback as f, useMemo as S, useEffect as w } from "react";
3
+ import b from "./modal.js";
4
+ import h from "./modal-context.js";
5
+ import { lockScroll as R, unlockScroll as T } from "./modal-helpers.js";
6
+ const $ = 500, g = D(({ children: p, modals: u, isUserAuthenticated: t }) => {
7
+ const [o, M] = d(null), [m, C] = d(void 0), [r, i] = d(!1), l = I(void 0), v = f(
8
+ (e, s, P) => {
9
+ const c = u.find((E) => E.name === e);
10
+ if (!c)
11
+ throw new Error(`Modal with name "${e}" not found`);
12
+ if (c.isPrivate && !t)
13
13
  throw new Error(
14
- `Access violation: Modal "${n}" is private and user is not authenticated`
14
+ `Access violation: Modal "${e}" is private and user is not authenticated`
15
15
  );
16
- r(!1), c(i), v(l), S();
16
+ l.current = P, i(!1), M(c), C(s), R();
17
17
  },
18
- [t, d]
19
- ), e = M(() => {
20
- r(!0), h(), setTimeout(() => {
21
- c(null), r(!1);
22
- }, D);
23
- }, []), p = x(
18
+ [t, u]
19
+ ), n = f(() => {
20
+ i(!0), T(), setTimeout(() => {
21
+ M(null), i(!1);
22
+ }, $);
23
+ }, []), k = S(
24
24
  () => ({
25
25
  modal: o,
26
- modalParams: f,
27
- openModal: m,
28
- closeModal: e,
29
- isClosing: s
26
+ modalParams: m,
27
+ openModal: v,
28
+ closeModal: n,
29
+ isClosing: r
30
30
  }),
31
- [o, f, m, e, s]
32
- );
33
- return u(() => {
34
- !t && (o != null && o.isPrivate) && e();
35
- }, [t, o, e]), u(() => {
36
- const n = (l) => {
37
- l.key === "Escape" && (o == null ? void 0 : o.isDismissable) !== !1 && !s && e();
31
+ [o, m, v, n, r]
32
+ ), a = f(() => {
33
+ var e, s;
34
+ (o == null ? void 0 : o.isDismissable) !== !1 && !r && (n(), l.current && ((s = (e = l.current).onCloseModal) == null || s.call(e), l.current.onCloseModal = void 0));
35
+ }, [o, n, r]);
36
+ return w(() => {
37
+ !t && (o != null && o.isPrivate) && n();
38
+ }, [t, o, n]), w(() => {
39
+ const e = (s) => {
40
+ s.key === "Escape" && a();
38
41
  };
39
- return window.addEventListener("keydown", n), () => window.removeEventListener("keydown", n);
40
- }, [o, e, s]), /* @__PURE__ */ k(I.Provider, { value: p, children: [
41
- w,
42
- o && /* @__PURE__ */ C(y, { modal: o, isClosing: s, onClose: e })
42
+ return window.addEventListener("keydown", e), () => window.removeEventListener("keydown", e);
43
+ }, [a]), /* @__PURE__ */ x(h.Provider, { value: k, children: [
44
+ p,
45
+ o && /* @__PURE__ */ y(b, { modal: o, isClosing: r, onClose: a })
43
46
  ] });
44
- }), O = T;
47
+ }), K = g;
45
48
  export {
46
- O as default
49
+ K as default
47
50
  };
48
51
  //# sourceMappingURL=modal-provider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"modal-provider.js","sources":["../../../../src/features/ui/modals/modal-provider.tsx"],"sourcesContent":["import type { IModal, IModalContext, IModalProviderProps } from './modal-types';\nimport type { FC } from 'react';\n\nimport { memo, useCallback, useEffect, useMemo, useState } from 'react';\n\nimport Modal from './modal';\nimport ModalContext from './modal-context';\nimport { lockScroll, unlockScroll } from './modal-helpers';\n\nconst ANIMATION_DURATION_MS = 500; // Match the animation duration in modal.tsx\n\n/**\n * Provider component that manages modal state and provides modal context to child components\n */\nconst ModalProvider: FC<IModalProviderProps> = memo(({ children, modals, isUserAuthenticated }) => {\n const [modal, setModal] = useState<IModal | null>(null);\n const [modalParams, setModalParams] = useState<Record<string, unknown> | undefined>(undefined);\n const [isClosing, setIsClosing] = useState(false);\n\n /**\n * Opens a modal by name with optional parameters\n * Handles authentication check for private modals\n */\n const openModal = useCallback<IModalContext['openModal']>(\n (modalName, newModalParams) => {\n const newModal = modals.find(m => m.name === modalName);\n\n if (!newModal) {\n throw new Error(`Modal with name \"${modalName}\" not found`);\n }\n\n if (newModal.isPrivate && !isUserAuthenticated) {\n throw new Error(\n `Access violation: Modal \"${modalName}\" is private and user is not authenticated`,\n );\n }\n\n setIsClosing(false);\n setModal(newModal);\n setModalParams(newModalParams as unknown as Record<string, unknown> | undefined);\n lockScroll(); // Lock scroll while preserving scrollbar width\n },\n [isUserAuthenticated, modals],\n );\n\n const closeModal = useCallback(() => {\n setIsClosing(true);\n // Wait for the animation to complete before removing the modal\n unlockScroll();\n setTimeout(() => {\n setModal(null);\n setIsClosing(false);\n }, ANIMATION_DURATION_MS);\n }, []);\n\n const modalContent = useMemo<IModalContext>(\n () => ({\n modal,\n modalParams,\n openModal,\n closeModal,\n isClosing,\n }),\n [modal, modalParams, openModal, closeModal, isClosing],\n );\n\n useEffect(() => {\n if (!isUserAuthenticated && modal?.isPrivate) {\n // If the modal is private and user is not authenticated, close it\n closeModal();\n }\n }, [isUserAuthenticated, modal, closeModal]);\n\n // Handle ESC key\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && modal?.isDismissable !== false && !isClosing) {\n closeModal();\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [modal, closeModal, isClosing]);\n\n return (\n <ModalContext.Provider value={modalContent}>\n {children}\n {modal && <Modal modal={modal} isClosing={isClosing} onClose={closeModal} />}\n </ModalContext.Provider>\n );\n});\n\nexport default ModalProvider;\n"],"names":["ANIMATION_DURATION_MS","ModalProvider","memo","children","modals","isUserAuthenticated","modal","setModal","useState","modalParams","setModalParams","isClosing","setIsClosing","openModal","useCallback","modalName","newModalParams","newModal","m","lockScroll","closeModal","unlockScroll","modalContent","useMemo","useEffect","handleKeyDown","e","jsxs","ModalContext","jsx","Modal","ModalProvider$1"],"mappings":";;;;;AASA,MAAMA,IAAwB,KAKxBC,IAAyCC,EAAK,CAAC,EAAE,UAAAC,GAAU,QAAAC,GAAQ,qBAAAC,QAA0B;AACjG,QAAM,CAACC,GAAOC,CAAQ,IAAIC,EAAwB,IAAI,GAChD,CAACC,GAAaC,CAAc,IAAIF,EAA8C,MAAS,GACvF,CAACG,GAAWC,CAAY,IAAIJ,EAAS,EAAK,GAM1CK,IAAYC;AAAA,IAChB,CAACC,GAAWC,MAAmB;AAC7B,YAAMC,IAAWb,EAAO,KAAK,CAAKc,MAAAA,EAAE,SAASH,CAAS;AAEtD,UAAI,CAACE;AACH,cAAM,IAAI,MAAM,oBAAoBF,CAAS,aAAa;AAGxD,UAAAE,EAAS,aAAa,CAACZ;AACzB,cAAM,IAAI;AAAA,UACR,4BAA4BU,CAAS;AAAA,QAAA;AAIzC,MAAAH,EAAa,EAAK,GAClBL,EAASU,CAAQ,GACjBP,EAAeM,CAAgE,GACpEG;IACb;AAAA,IACA,CAACd,GAAqBD,CAAM;AAAA,EAAA,GAGxBgB,IAAaN,EAAY,MAAM;AACnC,IAAAF,EAAa,EAAI,GAEJS,KACb,WAAW,MAAM;AACf,MAAAd,EAAS,IAAI,GACbK,EAAa,EAAK;AAAA,OACjBZ,CAAqB;AAAA,EAC1B,GAAG,CAAE,CAAA,GAECsB,IAAeC;AAAA,IACnB,OAAO;AAAA,MACL,OAAAjB;AAAA,MACA,aAAAG;AAAA,MACA,WAAAI;AAAA,MACA,YAAAO;AAAA,MACA,WAAAT;AAAA,IAAA;AAAA,IAEF,CAACL,GAAOG,GAAaI,GAAWO,GAAYT,CAAS;AAAA,EAAA;AAGvD,SAAAa,EAAU,MAAM;AACV,IAAA,CAACnB,MAAuBC,KAAA,QAAAA,EAAO,cAEtBc;EAEZ,GAAA,CAACf,GAAqBC,GAAOc,CAAU,CAAC,GAG3CI,EAAU,MAAM;AACR,UAAAC,IAAgB,CAACC,MAAqB;AAC1C,MAAIA,EAAE,QAAQ,aAAYpB,KAAA,gBAAAA,EAAO,mBAAkB,MAAS,CAACK,KAChDS;IACb;AAGK,kBAAA,iBAAiB,WAAWK,CAAa,GAEzC,MAAM,OAAO,oBAAoB,WAAWA,CAAa;AAAA,EAC/D,GAAA,CAACnB,GAAOc,GAAYT,CAAS,CAAC,GAG9B,gBAAAgB,EAAAC,EAAa,UAAb,EAAsB,OAAON,GAC3B,UAAA;AAAA,IAAAnB;AAAA,IACAG,KAAU,gBAAAuB,EAAAC,GAAA,EAAM,OAAAxB,GAAc,WAAAK,GAAsB,SAASS,GAAY;AAAA,EAC5E,EAAA,CAAA;AAEJ,CAAC,GAEDW,IAAe9B;"}
1
+ {"version":3,"file":"modal-provider.js","sources":["../../../../src/features/ui/modals/modal-provider.tsx"],"sourcesContent":["import type { IModal, IModalCallbacks, IModalContext, IModalProviderProps } from './modal-types';\nimport type { FC } from 'react';\n\nimport { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport Modal from './modal';\nimport ModalContext from './modal-context';\nimport { lockScroll, unlockScroll } from './modal-helpers';\n\nconst ANIMATION_DURATION_MS = 500; // Match the animation duration in modal.tsx\n\n/**\n * Provider component that manages modal state and provides modal context to child components\n */\nconst ModalProvider: FC<IModalProviderProps> = memo(({ children, modals, isUserAuthenticated }) => {\n const [modal, setModal] = useState<IModal | null>(null);\n const [modalParams, setModalParams] = useState<Record<string, unknown> | undefined>(undefined);\n const [isClosing, setIsClosing] = useState(false);\n const callbacksRef = useRef<IModalCallbacks | undefined>(undefined);\n /**\n * Opens a modal by name with optional parameters\n * Handles authentication check for private modals\n */\n const openModal = useCallback<IModalContext['openModal']>(\n (modalName, newModalParams, callbacks) => {\n const newModal = modals.find(m => m.name === modalName);\n\n if (!newModal) {\n throw new Error(`Modal with name \"${modalName}\" not found`);\n }\n\n if (newModal.isPrivate && !isUserAuthenticated) {\n throw new Error(\n `Access violation: Modal \"${modalName}\" is private and user is not authenticated`,\n );\n }\n\n callbacksRef.current = callbacks;\n setIsClosing(false);\n setModal(newModal);\n setModalParams(newModalParams as unknown as Record<string, unknown> | undefined);\n lockScroll(); // Lock scroll while preserving scrollbar width\n },\n [isUserAuthenticated, modals],\n );\n\n const closeModal = useCallback(() => {\n setIsClosing(true);\n // Wait for the animation to complete before removing the modal\n unlockScroll();\n setTimeout(() => {\n setModal(null);\n setIsClosing(false);\n }, ANIMATION_DURATION_MS);\n }, []);\n\n const modalContent = useMemo<IModalContext>(\n () => ({\n modal,\n modalParams,\n openModal,\n closeModal,\n isClosing,\n }),\n [modal, modalParams, openModal, closeModal, isClosing],\n );\n\n const onModalDismiss = useCallback(() => {\n if (modal?.isDismissable !== false && !isClosing) {\n closeModal();\n if (callbacksRef.current) {\n callbacksRef.current.onCloseModal?.();\n callbacksRef.current.onCloseModal = undefined; // Clear callback reference\n }\n }\n }, [modal, closeModal, isClosing]);\n\n useEffect(() => {\n if (!isUserAuthenticated && modal?.isPrivate) {\n // If the modal is private and user is not authenticated, close it\n closeModal();\n }\n }, [isUserAuthenticated, modal, closeModal]);\n\n // Handle ESC key\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onModalDismiss();\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [onModalDismiss]);\n\n return (\n <ModalContext.Provider value={modalContent}>\n {children}\n {modal && <Modal modal={modal} isClosing={isClosing} onClose={onModalDismiss} />}\n </ModalContext.Provider>\n );\n});\n\nexport default ModalProvider;\n"],"names":["ANIMATION_DURATION_MS","ModalProvider","memo","children","modals","isUserAuthenticated","modal","setModal","useState","modalParams","setModalParams","isClosing","setIsClosing","callbacksRef","useRef","openModal","useCallback","modalName","newModalParams","callbacks","newModal","m","lockScroll","closeModal","unlockScroll","modalContent","useMemo","onModalDismiss","_b","_a","useEffect","handleKeyDown","e","jsxs","ModalContext","jsx","Modal","ModalProvider$1"],"mappings":";;;;;AASA,MAAMA,IAAwB,KAKxBC,IAAyCC,EAAK,CAAC,EAAE,UAAAC,GAAU,QAAAC,GAAQ,qBAAAC,QAA0B;AACjG,QAAM,CAACC,GAAOC,CAAQ,IAAIC,EAAwB,IAAI,GAChD,CAACC,GAAaC,CAAc,IAAIF,EAA8C,MAAS,GACvF,CAACG,GAAWC,CAAY,IAAIJ,EAAS,EAAK,GAC1CK,IAAeC,EAAoC,MAAS,GAK5DC,IAAYC;AAAA,IAChB,CAACC,GAAWC,GAAgBC,MAAc;AACxC,YAAMC,IAAWhB,EAAO,KAAK,CAAKiB,MAAAA,EAAE,SAASJ,CAAS;AAEtD,UAAI,CAACG;AACH,cAAM,IAAI,MAAM,oBAAoBH,CAAS,aAAa;AAGxD,UAAAG,EAAS,aAAa,CAACf;AACzB,cAAM,IAAI;AAAA,UACR,4BAA4BY,CAAS;AAAA,QAAA;AAIzC,MAAAJ,EAAa,UAAUM,GACvBP,EAAa,EAAK,GAClBL,EAASa,CAAQ,GACjBV,EAAeQ,CAAgE,GACpEI;IACb;AAAA,IACA,CAACjB,GAAqBD,CAAM;AAAA,EAAA,GAGxBmB,IAAaP,EAAY,MAAM;AACnC,IAAAJ,EAAa,EAAI,GAEJY,KACb,WAAW,MAAM;AACf,MAAAjB,EAAS,IAAI,GACbK,EAAa,EAAK;AAAA,OACjBZ,CAAqB;AAAA,EAC1B,GAAG,CAAE,CAAA,GAECyB,IAAeC;AAAA,IACnB,OAAO;AAAA,MACL,OAAApB;AAAA,MACA,aAAAG;AAAA,MACA,WAAAM;AAAA,MACA,YAAAQ;AAAA,MACA,WAAAZ;AAAA,IAAA;AAAA,IAEF,CAACL,GAAOG,GAAaM,GAAWQ,GAAYZ,CAAS;AAAA,EAAA,GAGjDgB,IAAiBX,EAAY,MAAM;;AACvC,KAAIV,KAAA,gBAAAA,EAAO,mBAAkB,MAAS,CAACK,MAC1BY,KACPV,EAAa,aACfe,KAAAC,IAAAhB,EAAa,SAAQ,iBAArB,QAAAe,EAAA,KAAAC,IACAhB,EAAa,QAAQ,eAAe;AAAA,EAGvC,GAAA,CAACP,GAAOiB,GAAYZ,CAAS,CAAC;AAEjC,SAAAmB,EAAU,MAAM;AACV,IAAA,CAACzB,MAAuBC,KAAA,QAAAA,EAAO,cAEtBiB;EAEZ,GAAA,CAAClB,GAAqBC,GAAOiB,CAAU,CAAC,GAG3CO,EAAU,MAAM;AACR,UAAAC,IAAgB,CAACC,MAAqB;AACtC,MAAAA,EAAE,QAAQ,YACGL;IACjB;AAGK,kBAAA,iBAAiB,WAAWI,CAAa,GAEzC,MAAM,OAAO,oBAAoB,WAAWA,CAAa;AAAA,EAAA,GAC/D,CAACJ,CAAc,CAAC,GAGhB,gBAAAM,EAAAC,EAAa,UAAb,EAAsB,OAAOT,GAC3B,UAAA;AAAA,IAAAtB;AAAA,IACAG,KAAU,gBAAA6B,EAAAC,GAAA,EAAM,OAAA9B,GAAc,WAAAK,GAAsB,SAASgB,GAAgB;AAAA,EAChF,EAAA,CAAA;AAEJ,CAAC,GAEDU,IAAepC;"}
@@ -1,6 +1,6 @@
1
1
  import o from "styled-components";
2
2
  const s = o.div(
3
- ({ theme: { colors: a }, $isClosing: t }) => `
3
+ ({ theme: { colors: a, zIndex: t }, $isClosing: i }) => `
4
4
  position: fixed;
5
5
  top: 0;
6
6
  left: 0;
@@ -9,8 +9,9 @@ const s = o.div(
9
9
  background-color: ${a.BLACK_T_60};
10
10
  backdrop-filter: blur(40px);
11
11
  display: flex;
12
- animation: ${t ? "backdropFadeOut" : "backdropFadeIn"} 0.2s ease-out forwards;
13
-
12
+ animation: ${i ? "backdropFadeOut" : "backdropFadeIn"} 0.2s ease-out forwards;
13
+ z-index: ${t.MODAL};
14
+
14
15
  @keyframes backdropFadeIn {
15
16
  from {
16
17
  opacity: 0;
@@ -1 +1 @@
1
- {"version":3,"file":"modal-styled.js","sources":["../../../../src/features/ui/modals/modal-styled.tsx"],"sourcesContent":["import styled from 'styled-components';\n\nconst ModalContainer = styled.div<{ $isClosing?: boolean }>(\n ({ theme: { colors }, $isClosing }) => `\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: ${colors.BLACK_T_60};\n backdrop-filter: blur(40px);\n display: flex;\n animation: ${$isClosing ? 'backdropFadeOut' : 'backdropFadeIn'} 0.2s ease-out forwards;\n \n @keyframes backdropFadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n \n @keyframes backdropFadeOut {\n from {\n opacity: 1;\n }\n to {\n opacity: 0;\n }\n }\n`,\n);\n\n/**\n * Base modal container with customizable width and animation state\n */\nconst BaseModal = styled.div<{\n $isClosing?: boolean;\n $width: string;\n}>(\n ({ theme: { colors }, $isClosing, $width }) => `\n position: relative;\n align-self: center;\n margin: 0 auto;\n width: ${$width};\n background-color: ${colors.WHITE_1};\n border: 1px solid ${colors.BLACK_1};\n transform-origin: center center;\n animation: ${\n $isClosing ? 'modalDisappear' : 'modalAppear'\n } 0.5s cubic-bezier(0.19, 1, 0.22, 1) forwards;\n box-shadow: 0px 10px 20px 0px rgba(0, 0, 0, 0.20);\n \n /* Responsive behavior for smaller screens */\n @media (max-width: calc(${$width} + 80px)) {\n width: 100%;\n max-width: 100%;\n height: 100%;\n max-height: 100%;\n border: none;\n }\n \n @keyframes modalAppear {\n 0% {\n opacity: 0;\n transform: perspective(1200px) translateZ(-50px) translateY(10px) scale(0.98);\n }\n 100% {\n opacity: 1;\n transform: perspective(1200px) translateZ(0) translateY(0) scale(1);\n }\n }\n \n @keyframes modalDisappear {\n 0% {\n opacity: 1;\n transform: perspective(1200px) translateZ(0) translateY(0) scale(1);\n }\n 100% {\n opacity: 0;\n transform: perspective(1200px) translateZ(-50px) translateY(10px) scale(0.98);\n }\n }\n`,\n);\n\n/**\n * Scrollable content container inside the modal\n */\nconst BaseModalContent = styled.div<{ $modalWidth: string }>(\n ({ $modalWidth }) => `\n max-height: calc(100vh - 142px);\n overflow-y: auto;\n\n @media (max-width: calc(${$modalWidth} + 80px)) {\n max-height: 100vh;\n }\n}`,\n);\n\n/**\n * Container for the close button with responsive positioning\n */\nconst CloseButtonContainer = styled.div<{ $modalWidth: string }>(\n ({ theme: { colors }, $modalWidth }) => `\n position: absolute;\n top: -56px;\n right: -40px;\n color: ${colors.WHITE_1};\n transition: all 0.2s ease;\n \n &:hover {\n transform: scale(1.05);\n }\n\n @media (max-width: calc(${$modalWidth} + 80px)) {\n top: 16px;\n right: 16px;\n color: ${colors.BLACK_1};\n }\n`,\n);\n\nconst spotlightWidth = 720;\nconst spotlightAnimationStartDuration = 800;\nconst spotlightAnimationEndDuration = 500;\n\nconst SpotlightModal = styled.div<{\n $isClosing?: boolean;\n}>(\n ({ $isClosing }) => `\n position: absolute;\n width: ${spotlightWidth}px;\n height: 100%;\n left: 50%;\n margin-left: ${-(spotlightWidth / 2)}px;\n clip-path: polygon(calc(50% - 100px) 0, calc(50% + 100px) 0, 100% 100%, 0 100%);\n background: linear-gradient(\n 180deg,\n rgba(0, 0, 0, 1) 0%,\n rgba(0, 0, 0, 0) 100%\n );\n animation: openSpotlight;\n animation-duration: ${spotlightAnimationStartDuration}ms;\n animation-timing-function: linear;\n animation-fill-mode: forwards;\n opacity: 0;\n ${\n $isClosing\n ? `\n animation: closeSpotlight;\n animation-duration: ${spotlightAnimationEndDuration}ms;\n animation-timing-function: linear;\n animation-fill-mode: forwards;\n opacity: 1;\n `\n : ''\n }\n\n @keyframes openSpotlight {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n\n @keyframes closeSpotlight {\n from {\n transform: rotateY(0);\n }\n to {\n transform: rotateY(90deg);\n }\n }\n`,\n);\n\nexport { ModalContainer, BaseModal, BaseModalContent, CloseButtonContainer, SpotlightModal };\n"],"names":["ModalContainer","styled","colors","$isClosing","BaseModal","$width","BaseModalContent","$modalWidth","CloseButtonContainer","spotlightWidth","spotlightAnimationStartDuration","spotlightAnimationEndDuration","SpotlightModal"],"mappings":";AAEA,MAAMA,IAAiBC,EAAO;AAAA,EAC5B,CAAC,EAAE,OAAO,EAAE,QAAAC,EAAO,GAAG,YAAAC,EAAiB,MAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAMnBD,EAAO,UAAU;AAAA;AAAA;AAAA,eAGxBC,IAAa,oBAAoB,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoBhE,GAKMC,IAAYH,EAAO;AAAA,EAIvB,CAAC,EAAE,OAAO,EAAE,QAAAC,EAAU,GAAA,YAAAC,GAAY,QAAAE,QAAa;AAAA;AAAA;AAAA;AAAA,WAItCA,CAAM;AAAA,sBACKH,EAAO,OAAO;AAAA,sBACdA,EAAO,OAAO;AAAA;AAAA,eAGhCC,IAAa,mBAAmB,aAClC;AAAA;AAAA;AAAA;AAAA,4BAI0BE,CAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA8BlC,GAKMC,IAAmBL,EAAO;AAAA,EAC9B,CAAC,EAAE,aAAAM,EAAA,MAAkB;AAAA;AAAA;AAAA;AAAA,4BAIKA,CAAW;AAAA;AAAA;AAAA;AAIvC,GAKMC,IAAuBP,EAAO;AAAA,EAClC,CAAC,EAAE,OAAO,EAAE,QAAAC,EAAO,GAAG,aAAAK,EAAkB,MAAA;AAAA;AAAA;AAAA;AAAA,WAI/BL,EAAO,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAOGK,CAAW;AAAA;AAAA;AAAA,aAG1BL,EAAO,OAAO;AAAA;AAAA;AAG3B,GAEMO,IAAiB,KACjBC,IAAkC,KAClCC,IAAgC,KAEhCC,IAAiBX,EAAO;AAAA,EAG5B,CAAC,EAAE,YAAAE,EAAA,MAAiB;AAAA;AAAA,WAEXM,CAAc;AAAA;AAAA;AAAA,iBAGR,EAAEA,IAAiB,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAQdC,CAA+B;AAAA;AAAA;AAAA;AAAA,IAKnDP,IACI;AAAA;AAAA,4BAEoBQ,CAA6B;AAAA;AAAA;AAAA;AAAA,QAKjD,EACN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoBF;"}
1
+ {"version":3,"file":"modal-styled.js","sources":["../../../../src/features/ui/modals/modal-styled.tsx"],"sourcesContent":["import styled from 'styled-components';\n\nconst ModalContainer = styled.div<{ $isClosing?: boolean }>(\n ({ theme: { colors, zIndex }, $isClosing }) => `\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: ${colors.BLACK_T_60};\n backdrop-filter: blur(40px);\n display: flex;\n animation: ${$isClosing ? 'backdropFadeOut' : 'backdropFadeIn'} 0.2s ease-out forwards;\n z-index: ${zIndex.MODAL};\n\n @keyframes backdropFadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n \n @keyframes backdropFadeOut {\n from {\n opacity: 1;\n }\n to {\n opacity: 0;\n }\n }\n`,\n);\n\n/**\n * Base modal container with customizable width and animation state\n */\nconst BaseModal = styled.div<{\n $isClosing?: boolean;\n $width: string;\n}>(\n ({ theme: { colors }, $isClosing, $width }) => `\n position: relative;\n align-self: center;\n margin: 0 auto;\n width: ${$width};\n background-color: ${colors.WHITE_1};\n border: 1px solid ${colors.BLACK_1};\n transform-origin: center center;\n animation: ${\n $isClosing ? 'modalDisappear' : 'modalAppear'\n } 0.5s cubic-bezier(0.19, 1, 0.22, 1) forwards;\n box-shadow: 0px 10px 20px 0px rgba(0, 0, 0, 0.20);\n \n /* Responsive behavior for smaller screens */\n @media (max-width: calc(${$width} + 80px)) {\n width: 100%;\n max-width: 100%;\n height: 100%;\n max-height: 100%;\n border: none;\n }\n \n @keyframes modalAppear {\n 0% {\n opacity: 0;\n transform: perspective(1200px) translateZ(-50px) translateY(10px) scale(0.98);\n }\n 100% {\n opacity: 1;\n transform: perspective(1200px) translateZ(0) translateY(0) scale(1);\n }\n }\n \n @keyframes modalDisappear {\n 0% {\n opacity: 1;\n transform: perspective(1200px) translateZ(0) translateY(0) scale(1);\n }\n 100% {\n opacity: 0;\n transform: perspective(1200px) translateZ(-50px) translateY(10px) scale(0.98);\n }\n }\n`,\n);\n\n/**\n * Scrollable content container inside the modal\n */\nconst BaseModalContent = styled.div<{ $modalWidth: string }>(\n ({ $modalWidth }) => `\n max-height: calc(100vh - 142px);\n overflow-y: auto;\n\n @media (max-width: calc(${$modalWidth} + 80px)) {\n max-height: 100vh;\n }\n}`,\n);\n\n/**\n * Container for the close button with responsive positioning\n */\nconst CloseButtonContainer = styled.div<{ $modalWidth: string }>(\n ({ theme: { colors }, $modalWidth }) => `\n position: absolute;\n top: -56px;\n right: -40px;\n color: ${colors.WHITE_1};\n transition: all 0.2s ease;\n \n &:hover {\n transform: scale(1.05);\n }\n\n @media (max-width: calc(${$modalWidth} + 80px)) {\n top: 16px;\n right: 16px;\n color: ${colors.BLACK_1};\n }\n`,\n);\n\nconst spotlightWidth = 720;\nconst spotlightAnimationStartDuration = 800;\nconst spotlightAnimationEndDuration = 500;\n\nconst SpotlightModal = styled.div<{\n $isClosing?: boolean;\n}>(\n ({ $isClosing }) => `\n position: absolute;\n width: ${spotlightWidth}px;\n height: 100%;\n left: 50%;\n margin-left: ${-(spotlightWidth / 2)}px;\n clip-path: polygon(calc(50% - 100px) 0, calc(50% + 100px) 0, 100% 100%, 0 100%);\n background: linear-gradient(\n 180deg,\n rgba(0, 0, 0, 1) 0%,\n rgba(0, 0, 0, 0) 100%\n );\n animation: openSpotlight;\n animation-duration: ${spotlightAnimationStartDuration}ms;\n animation-timing-function: linear;\n animation-fill-mode: forwards;\n opacity: 0;\n ${\n $isClosing\n ? `\n animation: closeSpotlight;\n animation-duration: ${spotlightAnimationEndDuration}ms;\n animation-timing-function: linear;\n animation-fill-mode: forwards;\n opacity: 1;\n `\n : ''\n }\n\n @keyframes openSpotlight {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n\n @keyframes closeSpotlight {\n from {\n transform: rotateY(0);\n }\n to {\n transform: rotateY(90deg);\n }\n }\n`,\n);\n\nexport { ModalContainer, BaseModal, BaseModalContent, CloseButtonContainer, SpotlightModal };\n"],"names":["ModalContainer","styled","colors","zIndex","$isClosing","BaseModal","$width","BaseModalContent","$modalWidth","CloseButtonContainer","spotlightWidth","spotlightAnimationStartDuration","spotlightAnimationEndDuration","SpotlightModal"],"mappings":";AAEA,MAAMA,IAAiBC,EAAO;AAAA,EAC5B,CAAC,EAAE,OAAO,EAAE,QAAAC,GAAQ,QAAAC,EAAO,GAAG,YAAAC,QAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAM3BF,EAAO,UAAU;AAAA;AAAA;AAAA,eAGxBE,IAAa,oBAAoB,gBAAgB;AAAA,aACnDD,EAAO,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoBzB,GAKME,IAAYJ,EAAO;AAAA,EAIvB,CAAC,EAAE,OAAO,EAAE,QAAAC,EAAU,GAAA,YAAAE,GAAY,QAAAE,QAAa;AAAA;AAAA;AAAA;AAAA,WAItCA,CAAM;AAAA,sBACKJ,EAAO,OAAO;AAAA,sBACdA,EAAO,OAAO;AAAA;AAAA,eAGhCE,IAAa,mBAAmB,aAClC;AAAA;AAAA;AAAA;AAAA,4BAI0BE,CAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA8BlC,GAKMC,IAAmBN,EAAO;AAAA,EAC9B,CAAC,EAAE,aAAAO,EAAA,MAAkB;AAAA;AAAA;AAAA;AAAA,4BAIKA,CAAW;AAAA;AAAA;AAAA;AAIvC,GAKMC,IAAuBR,EAAO;AAAA,EAClC,CAAC,EAAE,OAAO,EAAE,QAAAC,EAAO,GAAG,aAAAM,EAAkB,MAAA;AAAA;AAAA;AAAA;AAAA,WAI/BN,EAAO,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAOGM,CAAW;AAAA;AAAA;AAAA,aAG1BN,EAAO,OAAO;AAAA;AAAA;AAG3B,GAEMQ,IAAiB,KACjBC,IAAkC,KAClCC,IAAgC,KAEhCC,IAAiBZ,EAAO;AAAA,EAG5B,CAAC,EAAE,YAAAG,EAAA,MAAiB;AAAA;AAAA,WAEXM,CAAc;AAAA;AAAA;AAAA,iBAGR,EAAEA,IAAiB,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAQdC,CAA+B;AAAA;AAAA;AAAA;AAAA,IAKnDP,IACI;AAAA;AAAA,4BAEoBQ,CAA6B;AAAA;AAAA;AAAA;AAAA,QAKjD,EACN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoBF;"}
@@ -1,9 +1,9 @@
1
- import { useContext as e } from "react";
2
- import n from "./modal-context.js";
3
- const l = () => {
4
- const { openModal: o, closeModal: t, isClosing: s } = e(n);
5
- return { openModal: o, closeModal: t, isClosing: s };
6
- }, c = l;
1
+ import { useContext as n } from "react";
2
+ import l from "./modal-context.js";
3
+ const a = () => {
4
+ const { openModal: o, closeModal: t, isClosing: s, modal: e } = n(l);
5
+ return { openModal: o, closeModal: t, isClosing: s, modal: e };
6
+ }, c = a;
7
7
  export {
8
8
  c as default
9
9
  };
@@ -1 +1 @@
1
- {"version":3,"file":"use-modal-actions.js","sources":["../../../../src/features/ui/modals/use-modal-actions.ts"],"sourcesContent":["import type { IUseModalActions } from './modal-types';\n\nimport { useContext } from 'react';\n\nimport ModalContext from './modal-context';\n\nconst useModalActions: IUseModalActions = () => {\n const { openModal, closeModal, isClosing } = useContext(ModalContext);\n\n return { openModal, closeModal, isClosing };\n};\n\nexport default useModalActions;\n"],"names":["useModalActions","openModal","closeModal","isClosing","useContext","ModalContext","useModalActions$1"],"mappings":";;AAMA,MAAMA,IAAoC,MAAM;AAC9C,QAAM,EAAE,WAAAC,GAAW,YAAAC,GAAY,WAAAC,EAAU,IAAIC,EAAWC,CAAY;AAE7D,SAAA,EAAE,WAAAJ,GAAW,YAAAC,GAAY,WAAAC;AAClC,GAEAG,IAAeN;"}
1
+ {"version":3,"file":"use-modal-actions.js","sources":["../../../../src/features/ui/modals/use-modal-actions.ts"],"sourcesContent":["import type { IUseModalActions } from './modal-types';\n\nimport { useContext } from 'react';\n\nimport ModalContext from './modal-context';\n\nconst useModalActions: IUseModalActions = () => {\n const { openModal, closeModal, isClosing, modal } = useContext(ModalContext);\n\n return { openModal, closeModal, isClosing, modal };\n};\n\nexport default useModalActions;\n"],"names":["useModalActions","openModal","closeModal","isClosing","modal","useContext","ModalContext","useModalActions$1"],"mappings":";;AAMA,MAAMA,IAAoC,MAAM;AAC9C,QAAM,EAAE,WAAAC,GAAW,YAAAC,GAAY,WAAAC,GAAW,OAAAC,MAAUC,EAAWC,CAAY;AAE3E,SAAO,EAAE,WAAAL,GAAW,YAAAC,GAAY,WAAAC,GAAW,OAAAC,EAAM;AACnD,GAEAG,IAAeP;"}
package/dist/index.d.ts CHANGED
@@ -2389,6 +2389,11 @@ export declare interface IModal {
2389
2389
  modalWidth: string;
2390
2390
  }
2391
2391
 
2392
+ declare interface IModalCallbacks {
2393
+ /** Callback when the modal is closed */
2394
+ onCloseModal?: () => void;
2395
+ }
2396
+
2392
2397
  /**
2393
2398
  * Context for managing modals throughout the application
2394
2399
  */
@@ -2398,7 +2403,7 @@ declare interface IModalContext {
2398
2403
  /** Parameters passed to the modal when opened */
2399
2404
  modalParams?: Record<string, unknown>;
2400
2405
  /** Opens a modal by name with optional parameters */
2401
- openModal: <T = undefined>(name: string, params?: T) => void;
2406
+ openModal: <T = undefined>(name: string, params?: T, callbacks?: IModalCallbacks) => void;
2402
2407
  /** Closes the currently open modal */
2403
2408
  closeModal: () => void;
2404
2409
  /** Whether the modal is in the process of closing (for animation) */
@@ -3616,7 +3621,7 @@ declare interface IUseIsTabBlocked {
3616
3621
  }
3617
3622
 
3618
3623
  declare interface IUseModalActions {
3619
- (): Pick<IModalContext, 'openModal' | 'closeModal' | 'isClosing'>;
3624
+ (): Pick<IModalContext, 'openModal' | 'closeModal' | 'isClosing' | 'modal'>;
3620
3625
  }
3621
3626
 
3622
3627
  declare interface IUseModalParams {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cuemath/leap",
3
- "version": "3.1.20-link.0",
3
+ "version": "3.1.21",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"
@@ -95,5 +95,6 @@
95
95
  "vite-plugin-dts": "3.6.4",
96
96
  "vite-plugin-svgr": "3.2.0",
97
97
  "vite-tsconfig-paths": "^4.2.2"
98
- }
98
+ },
99
+ "packageManager": "yarn@4.4.1"
99
100
  }