From b780f3ad2e186505c43d9b86b782e90572da0571 Mon Sep 17 00:00:00 2001 From: Deeksha Deepak Date: Wed, 15 Jul 2026 11:50:21 +0530 Subject: [PATCH] Remove React QuML player (migrated to Sunbird-inQuiry/player-v2) --- .../workflows/publish_web_component_react.yml | 43 - projects/sunbird-quml-player-react/.gitignore | 27 - .../sunbird-quml-player-react/.oxlintrc.json | 8 - projects/sunbird-quml-player-react/README.md | 32 - projects/sunbird-quml-player-react/index.html | 19 - .../package-lock.json | 5641 ----------------- .../sunbird-quml-player-react/package.json | 53 - .../public/favicon.svg | 1 - .../public/icons.svg | 24 - .../scripts/build-wc.js | 126 - .../sunbird-quml-player-react/src/App.css | 184 - .../sunbird-quml-player-react/src/App.tsx | 50 - .../src/assets/hero.png | Bin 13057 -> 0 bytes .../src/assets/react.svg | 1 - .../src/assets/vite.svg | 1 - .../src/components/Alert/Alert.module.scss | 94 - .../src/components/Alert/Alert.test.tsx | 59 - .../src/components/Alert/Alert.tsx | 76 - .../src/components/Header/Header.module.scss | 116 - .../src/components/Header/Header.test.tsx | 53 - .../src/components/Header/Header.tsx | 106 - .../src/components/Hint/Hint.module.scss | 56 - .../src/components/Hint/Hint.test.tsx | 52 - .../src/components/Hint/Hint.tsx | 129 - .../components/ImageViewer/ImageViewer.tsx | 41 - .../components/ImageViewer/image-viewer.css | 141 - .../components/ImageViewer/useImageZoom.ts | 103 - .../MainPlayer.embedded-render.test.tsx | 117 - .../MainPlayer.max-attempts.test.tsx | 147 - .../MainPlayer.metadata-config.test.tsx | 79 - .../MainPlayer/MainPlayer.module.scss | 108 - .../MainPlayer.portal-fetch.test.tsx | 104 - .../MainPlayer.preview-config.test.tsx | 119 - .../MainPlayer.reorder-telemetry.test.tsx | 83 - .../components/MainPlayer/MainPlayer.test.tsx | 176 - ...MainPlayer.timer-showtimer-parity.test.tsx | 87 - .../src/components/MainPlayer/MainPlayer.tsx | 668 -- .../MobileSectionsDrawer.module.scss | 93 - .../MobileSectionsDrawer.test.tsx | 62 - .../MobileSectionsDrawer.tsx | 117 - .../PlayerHeader/PlayerHeader.module.scss | 320 - .../PlayerHeader/PlayerHeader.test.tsx | 53 - .../components/PlayerHeader/PlayerHeader.tsx | 166 - .../ProgressIndicators.module.scss | 90 - .../ProgressIndicators.test.tsx | 39 - .../ProgressIndicators/ProgressIndicators.tsx | 79 - .../QuestionBody/QuestionBody.module.scss | 67 - .../QuestionBody/QuestionBody.test.tsx | 54 - .../components/QuestionBody/QuestionBody.tsx | 95 - .../QuestionCard/QuestionCard.module.scss | 85 - .../QuestionCard/QuestionCard.test.tsx | 32 - .../components/QuestionCard/QuestionCard.tsx | 45 - .../QuestionPalette.module.scss | 76 - .../QuestionPalette/QuestionPalette.test.tsx | 43 - .../QuestionPalette/QuestionPalette.tsx | 80 - .../QuestionRenderer.module.scss | 15 - .../QuestionRenderer.test.tsx | 39 - .../QuestionRenderer/QuestionRenderer.tsx | 89 - .../ResultsScreen/ResultsScreen.module.scss | 101 - .../ResultsScreen/ResultsScreen.test.tsx | 97 - .../ResultsScreen/ResultsScreen.tsx | 93 - .../ReviewScreen/ReviewScreen.module.scss | 230 - .../ReviewScreen/ReviewScreen.test.tsx | 76 - .../components/ReviewScreen/ReviewScreen.tsx | 204 - .../Scoreboard/Scoreboard.module.scss | 111 - .../components/Scoreboard/Scoreboard.test.tsx | 37 - .../src/components/Scoreboard/Scoreboard.tsx | 69 - .../SectionIntro/SectionIntro.module.scss | 218 - .../SectionIntro/SectionIntro.test.tsx | 68 - .../components/SectionIntro/SectionIntro.tsx | 81 - .../SectionPlayer.feedback.test.tsx | 112 - .../SectionPlayer/SectionPlayer.module.scss | 187 - .../SectionPlayer/SectionPlayer.test.tsx | 113 - .../SectionPlayer/SectionPlayer.tsx | 296 - .../components/Sidebar/Sidebar.module.scss | 134 - .../src/components/Sidebar/Sidebar.test.tsx | 66 - .../src/components/Sidebar/Sidebar.tsx | 76 - .../StartPage/StartPage.module.scss | 500 -- .../components/StartPage/StartPage.test.tsx | 72 - .../src/components/StartPage/StartPage.tsx | 206 - .../StartPage/useIsCompactViewport.ts | 48 - .../SubmitModal/SubmitModal.module.scss | 147 - .../SubmitModal/SubmitModal.test.tsx | 37 - .../components/SubmitModal/SubmitModal.tsx | 118 - .../src/components/Toast/Toast.module.scss | 104 - .../src/components/Toast/Toast.test.tsx | 38 - .../src/components/Toast/Toast.tsx | 59 - .../src/components/icons/AttemptsIcon.tsx | 25 - .../src/components/icons/CheckIcon.tsx | 24 - .../src/components/icons/ChevronRightIcon.tsx | 23 - .../src/components/icons/ClipboardIcon.tsx | 24 - .../src/components/icons/CloseIcon.tsx | 24 - .../src/components/icons/GridIcon.tsx | 26 - .../src/components/icons/HintIcon.tsx | 25 - .../src/components/icons/MenuIcon.tsx | 25 - .../src/components/icons/NextIcon.tsx | 23 - .../src/components/icons/PreviousIcon.tsx | 23 - .../src/components/icons/ShieldIcon.tsx | 23 - .../src/components/icons/TimerIcon.tsx | 25 - .../src/components/icons/ZoomInIcon.tsx | 26 - .../src/components/icons/ZoomOutIcon.tsx | 25 - .../src/components/icons/icons.test.tsx | 64 - .../src/components/icons/index.tsx | 16 - .../src/components/icons/types.ts | 9 - .../BooleanQuestion.module.scss | 89 - .../BooleanQuestion/BooleanQuestion.test.tsx | 112 - .../BooleanQuestion/BooleanQuestion.tsx | 105 - .../FtbQuestion/FtbQuestion.module.scss | 81 - .../FtbQuestion/FtbQuestion.test.tsx | 57 - .../questions/FtbQuestion/FtbQuestion.tsx | 105 - .../McqQuestion/McqQuestion.module.scss | 102 - .../McqQuestion/McqQuestion.test.tsx | 75 - .../questions/McqQuestion/McqQuestion.tsx | 87 - .../MtfQuestion/MtfQuestion.module.scss | 97 - .../MtfQuestion/MtfQuestion.test.tsx | 54 - .../questions/MtfQuestion/MtfQuestion.tsx | 180 - .../ReoQuestion/ReoQuestion.module.scss | 119 - .../ReoQuestion/ReoQuestion.test.tsx | 127 - .../questions/ReoQuestion/ReoQuestion.tsx | 200 - .../SaQuestion/SaQuestion.module.scss | 60 - .../questions/SaQuestion/SaQuestion.test.tsx | 54 - .../questions/SaQuestion/SaQuestion.tsx | 80 - .../SeqQuestion/SeqQuestion.module.scss | 62 - .../SeqQuestion/SeqQuestion.test.tsx | 47 - .../questions/SeqQuestion/SeqQuestion.tsx | 159 - .../components/questions/question-utils.ts | 61 - .../src/components/questions/types.ts | 23 - .../src/context/QumlContext.test.tsx | 240 - .../src/context/QumlContext.tsx | 330 - .../src/context/useQuml.test.tsx | 56 - .../src/context/useQuml.ts | 47 - .../src/context/useTelemetry.test.tsx | 48 - .../src/context/useTelemetry.ts | 52 - .../src/dev/sample-data.ts | 330 - .../src/i18n/translations-ar.ts | 130 - .../src/i18n/translations-en.ts | 126 - .../src/i18n/translations-fr.ts | 132 - .../src/i18n/translations-pt.ts | 132 - .../src/i18n/translations.test.ts | 81 - .../src/i18n/translations.ts | 105 - .../sunbird-quml-player-react/src/index.css | 111 - .../sunbird-quml-player-react/src/main.tsx | 10 - .../registry/question-type-registry.test.ts | 74 - .../src/registry/question-type-registry.ts | 87 - .../src/registry/scoring-registry.test.ts | 50 - .../src/registry/scoring-registry.ts | 53 - .../services/data-service.embedded.test.ts | 138 - .../services/data-service.realpayload.test.ts | 80 - .../src/services/data-service.test.ts | 216 - .../src/services/data-service.ts | 220 - .../src/services/http-client.test.ts | 54 - .../src/services/http-client.ts | 103 - .../src/services/navigation-service.test.ts | 63 - .../src/services/navigation-service.ts | 91 - .../src/services/quml-library-service.ts | 31 - .../src/services/storage-service.test.ts | 45 - .../src/services/storage-service.ts | 58 - .../src/services/telemetry-service.test.ts | 82 - .../src/services/telemetry-service.ts | 118 - .../services/transformation-service.test.ts | 182 - .../src/services/transformation-service.ts | 333 - .../src/styles/global.scss | 41 - .../src/styles/mixins.scss | 105 - .../src/styles/variables.scss | 115 - .../src/test-setup.ts | 15 - .../src/types/api.ts | 86 - .../src/types/index.ts | 212 - .../src/utils/answered.test.ts | 39 - .../src/utils/answered.ts | 46 - .../src/utils/api-endpoints.ts | 35 - .../src/utils/constants.ts | 112 - .../src/utils/id.test.ts | 11 - .../sunbird-quml-player-react/src/utils/id.ts | 6 - .../src/utils/media.test.ts | 118 - .../src/utils/media.ts | 172 - .../src/utils/object.test.ts | 18 - .../src/utils/object.ts | 9 - .../src/utils/score.test.ts | 233 - .../src/utils/score.ts | Bin 10648 -> 0 bytes .../src/utils/shuffle.ts | 14 - .../src/utils/time.test.ts | 10 - .../src/utils/time.ts | 9 - .../src/utils/validation.test.ts | 14 - .../src/utils/validation.ts | 5 - .../web-component/element-registration.tsx | 178 - .../tsconfig.app.json | 25 - .../sunbird-quml-player-react/tsconfig.json | 7 - .../tsconfig.node.json | 25 - .../sunbird-quml-player-react/vite.config.ts | 95 - .../vitest.config.ts | 16 - 190 files changed, 22706 deletions(-) delete mode 100644 .github/workflows/publish_web_component_react.yml delete mode 100644 projects/sunbird-quml-player-react/.gitignore delete mode 100644 projects/sunbird-quml-player-react/.oxlintrc.json delete mode 100644 projects/sunbird-quml-player-react/README.md delete mode 100644 projects/sunbird-quml-player-react/index.html delete mode 100644 projects/sunbird-quml-player-react/package-lock.json delete mode 100644 projects/sunbird-quml-player-react/package.json delete mode 100644 projects/sunbird-quml-player-react/public/favicon.svg delete mode 100644 projects/sunbird-quml-player-react/public/icons.svg delete mode 100644 projects/sunbird-quml-player-react/scripts/build-wc.js delete mode 100644 projects/sunbird-quml-player-react/src/App.css delete mode 100644 projects/sunbird-quml-player-react/src/App.tsx delete mode 100644 projects/sunbird-quml-player-react/src/assets/hero.png delete mode 100644 projects/sunbird-quml-player-react/src/assets/react.svg delete mode 100644 projects/sunbird-quml-player-react/src/assets/vite.svg delete mode 100644 projects/sunbird-quml-player-react/src/components/Alert/Alert.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/Alert/Alert.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/Alert/Alert.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/Header/Header.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/Header/Header.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/Header/Header.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/Hint/Hint.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/Hint/Hint.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/Hint/Hint.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/ImageViewer/ImageViewer.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/ImageViewer/image-viewer.css delete mode 100644 projects/sunbird-quml-player-react/src/components/ImageViewer/useImageZoom.ts delete mode 100644 projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.embedded-render.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.max-attempts.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.metadata-config.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.portal-fetch.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.preview-config.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.reorder-telemetry.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.timer-showtimer-parity.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/MobileSectionsDrawer/MobileSectionsDrawer.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/MobileSectionsDrawer/MobileSectionsDrawer.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/MobileSectionsDrawer/MobileSectionsDrawer.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/PlayerHeader/PlayerHeader.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/PlayerHeader/PlayerHeader.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/PlayerHeader/PlayerHeader.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/ProgressIndicators/ProgressIndicators.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/ProgressIndicators/ProgressIndicators.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/ProgressIndicators/ProgressIndicators.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/QuestionBody/QuestionBody.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/QuestionBody/QuestionBody.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/QuestionBody/QuestionBody.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/QuestionCard/QuestionCard.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/QuestionCard/QuestionCard.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/QuestionCard/QuestionCard.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/QuestionPalette/QuestionPalette.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/QuestionPalette/QuestionPalette.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/QuestionPalette/QuestionPalette.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/QuestionRenderer/QuestionRenderer.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/QuestionRenderer/QuestionRenderer.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/QuestionRenderer/QuestionRenderer.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/ResultsScreen/ResultsScreen.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/ResultsScreen/ResultsScreen.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/ResultsScreen/ResultsScreen.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/ReviewScreen/ReviewScreen.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/ReviewScreen/ReviewScreen.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/ReviewScreen/ReviewScreen.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/Scoreboard/Scoreboard.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/Scoreboard/Scoreboard.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/Scoreboard/Scoreboard.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/SectionIntro/SectionIntro.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/SectionIntro/SectionIntro.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/SectionIntro/SectionIntro.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/SectionPlayer/SectionPlayer.feedback.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/SectionPlayer/SectionPlayer.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/SectionPlayer/SectionPlayer.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/SectionPlayer/SectionPlayer.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/Sidebar/Sidebar.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/Sidebar/Sidebar.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/Sidebar/Sidebar.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/StartPage/StartPage.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/StartPage/StartPage.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/StartPage/StartPage.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/StartPage/useIsCompactViewport.ts delete mode 100644 projects/sunbird-quml-player-react/src/components/SubmitModal/SubmitModal.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/SubmitModal/SubmitModal.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/SubmitModal/SubmitModal.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/Toast/Toast.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/Toast/Toast.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/Toast/Toast.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/icons/AttemptsIcon.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/icons/CheckIcon.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/icons/ChevronRightIcon.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/icons/ClipboardIcon.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/icons/CloseIcon.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/icons/GridIcon.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/icons/HintIcon.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/icons/MenuIcon.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/icons/NextIcon.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/icons/PreviousIcon.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/icons/ShieldIcon.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/icons/TimerIcon.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/icons/ZoomInIcon.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/icons/ZoomOutIcon.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/icons/icons.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/icons/index.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/icons/types.ts delete mode 100644 projects/sunbird-quml-player-react/src/components/questions/BooleanQuestion/BooleanQuestion.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/questions/BooleanQuestion/BooleanQuestion.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/questions/BooleanQuestion/BooleanQuestion.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/questions/FtbQuestion/FtbQuestion.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/questions/FtbQuestion/FtbQuestion.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/questions/FtbQuestion/FtbQuestion.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/questions/McqQuestion/McqQuestion.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/questions/McqQuestion/McqQuestion.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/questions/McqQuestion/McqQuestion.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/questions/MtfQuestion/MtfQuestion.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/questions/MtfQuestion/MtfQuestion.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/questions/MtfQuestion/MtfQuestion.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/questions/ReoQuestion/ReoQuestion.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/questions/ReoQuestion/ReoQuestion.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/questions/ReoQuestion/ReoQuestion.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/questions/SaQuestion/SaQuestion.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/questions/SaQuestion/SaQuestion.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/questions/SaQuestion/SaQuestion.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/questions/SeqQuestion/SeqQuestion.module.scss delete mode 100644 projects/sunbird-quml-player-react/src/components/questions/SeqQuestion/SeqQuestion.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/questions/SeqQuestion/SeqQuestion.tsx delete mode 100644 projects/sunbird-quml-player-react/src/components/questions/question-utils.ts delete mode 100644 projects/sunbird-quml-player-react/src/components/questions/types.ts delete mode 100644 projects/sunbird-quml-player-react/src/context/QumlContext.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/context/QumlContext.tsx delete mode 100644 projects/sunbird-quml-player-react/src/context/useQuml.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/context/useQuml.ts delete mode 100644 projects/sunbird-quml-player-react/src/context/useTelemetry.test.tsx delete mode 100644 projects/sunbird-quml-player-react/src/context/useTelemetry.ts delete mode 100644 projects/sunbird-quml-player-react/src/dev/sample-data.ts delete mode 100644 projects/sunbird-quml-player-react/src/i18n/translations-ar.ts delete mode 100644 projects/sunbird-quml-player-react/src/i18n/translations-en.ts delete mode 100644 projects/sunbird-quml-player-react/src/i18n/translations-fr.ts delete mode 100644 projects/sunbird-quml-player-react/src/i18n/translations-pt.ts delete mode 100644 projects/sunbird-quml-player-react/src/i18n/translations.test.ts delete mode 100644 projects/sunbird-quml-player-react/src/i18n/translations.ts delete mode 100644 projects/sunbird-quml-player-react/src/index.css delete mode 100644 projects/sunbird-quml-player-react/src/main.tsx delete mode 100644 projects/sunbird-quml-player-react/src/registry/question-type-registry.test.ts delete mode 100644 projects/sunbird-quml-player-react/src/registry/question-type-registry.ts delete mode 100644 projects/sunbird-quml-player-react/src/registry/scoring-registry.test.ts delete mode 100644 projects/sunbird-quml-player-react/src/registry/scoring-registry.ts delete mode 100644 projects/sunbird-quml-player-react/src/services/data-service.embedded.test.ts delete mode 100644 projects/sunbird-quml-player-react/src/services/data-service.realpayload.test.ts delete mode 100644 projects/sunbird-quml-player-react/src/services/data-service.test.ts delete mode 100644 projects/sunbird-quml-player-react/src/services/data-service.ts delete mode 100644 projects/sunbird-quml-player-react/src/services/http-client.test.ts delete mode 100644 projects/sunbird-quml-player-react/src/services/http-client.ts delete mode 100644 projects/sunbird-quml-player-react/src/services/navigation-service.test.ts delete mode 100644 projects/sunbird-quml-player-react/src/services/navigation-service.ts delete mode 100644 projects/sunbird-quml-player-react/src/services/quml-library-service.ts delete mode 100644 projects/sunbird-quml-player-react/src/services/storage-service.test.ts delete mode 100644 projects/sunbird-quml-player-react/src/services/storage-service.ts delete mode 100644 projects/sunbird-quml-player-react/src/services/telemetry-service.test.ts delete mode 100644 projects/sunbird-quml-player-react/src/services/telemetry-service.ts delete mode 100644 projects/sunbird-quml-player-react/src/services/transformation-service.test.ts delete mode 100644 projects/sunbird-quml-player-react/src/services/transformation-service.ts delete mode 100644 projects/sunbird-quml-player-react/src/styles/global.scss delete mode 100644 projects/sunbird-quml-player-react/src/styles/mixins.scss delete mode 100644 projects/sunbird-quml-player-react/src/styles/variables.scss delete mode 100644 projects/sunbird-quml-player-react/src/test-setup.ts delete mode 100644 projects/sunbird-quml-player-react/src/types/api.ts delete mode 100644 projects/sunbird-quml-player-react/src/types/index.ts delete mode 100644 projects/sunbird-quml-player-react/src/utils/answered.test.ts delete mode 100644 projects/sunbird-quml-player-react/src/utils/answered.ts delete mode 100644 projects/sunbird-quml-player-react/src/utils/api-endpoints.ts delete mode 100644 projects/sunbird-quml-player-react/src/utils/constants.ts delete mode 100644 projects/sunbird-quml-player-react/src/utils/id.test.ts delete mode 100644 projects/sunbird-quml-player-react/src/utils/id.ts delete mode 100644 projects/sunbird-quml-player-react/src/utils/media.test.ts delete mode 100644 projects/sunbird-quml-player-react/src/utils/media.ts delete mode 100644 projects/sunbird-quml-player-react/src/utils/object.test.ts delete mode 100644 projects/sunbird-quml-player-react/src/utils/object.ts delete mode 100644 projects/sunbird-quml-player-react/src/utils/score.test.ts delete mode 100644 projects/sunbird-quml-player-react/src/utils/score.ts delete mode 100644 projects/sunbird-quml-player-react/src/utils/shuffle.ts delete mode 100644 projects/sunbird-quml-player-react/src/utils/time.test.ts delete mode 100644 projects/sunbird-quml-player-react/src/utils/time.ts delete mode 100644 projects/sunbird-quml-player-react/src/utils/validation.test.ts delete mode 100644 projects/sunbird-quml-player-react/src/utils/validation.ts delete mode 100644 projects/sunbird-quml-player-react/src/web-component/element-registration.tsx delete mode 100644 projects/sunbird-quml-player-react/tsconfig.app.json delete mode 100644 projects/sunbird-quml-player-react/tsconfig.json delete mode 100644 projects/sunbird-quml-player-react/tsconfig.node.json delete mode 100644 projects/sunbird-quml-player-react/vite.config.ts delete mode 100644 projects/sunbird-quml-player-react/vitest.config.ts diff --git a/.github/workflows/publish_web_component_react.yml b/.github/workflows/publish_web_component_react.yml deleted file mode 100644 index f30f4aa4..00000000 --- a/.github/workflows/publish_web_component_react.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Publish sunbird-quml-player-web-component-react - -# Publish on a React-specific tag (e.g. react-v0.1.0). A tag push runs the -# workflow file from the tagged commit's branch, so this works without the file -# being on the default branch. Note: the Angular publish_web_component.yml -# triggers on any tag ('*') and will also fire on these tags — its run fails -# harmlessly on the duplicate version and does not affect this publish. -on: - push: - tags: - - '*' - -defaults: - run: - working-directory: projects/sunbird-quml-player-react - -jobs: - publish-npm: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: '22.21.1' - registry-url: 'https://registry.npmjs.org' - - - name: Install dependencies - run: npm ci --legacy-peer-deps - - - name: Build web component - # tsc -b && vite build && build:wc — emits web-component/ (assets + manifest) - run: npm run build - - - name: Publish to NPM - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - run: | - echo "//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}" > ~/.npmrc - npm publish ./web-component --access public diff --git a/projects/sunbird-quml-player-react/.gitignore b/projects/sunbird-quml-player-react/.gitignore deleted file mode 100644 index 93769bcd..00000000 --- a/projects/sunbird-quml-player-react/.gitignore +++ /dev/null @@ -1,27 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Web component build output (root only — NOT src/web-component/) -/web-component/ - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/projects/sunbird-quml-player-react/.oxlintrc.json b/projects/sunbird-quml-player-react/.oxlintrc.json deleted file mode 100644 index 6fa991da..00000000 --- a/projects/sunbird-quml-player-react/.oxlintrc.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "$schema": "./node_modules/oxlint/configuration_schema.json", - "plugins": ["react", "typescript", "oxc"], - "rules": { - "react/rules-of-hooks": "error", - "react/only-export-components": ["warn", { "allowConstantExport": true }] - } -} diff --git a/projects/sunbird-quml-player-react/README.md b/projects/sunbird-quml-player-react/README.md deleted file mode 100644 index d6af7e39..00000000 --- a/projects/sunbird-quml-player-react/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# React + TypeScript + Vite - -This template provides a minimal setup to get React working in Vite with HMR and some Oxlint rules. - -Currently, two official plugins are available: - -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs) -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) - -## React Compiler - -The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). - -## Expanding the Oxlint configuration - -If you are developing a production application, we recommend enabling type-aware lint rules by installing `oxlint-tsgolint` and editing `.oxlintrc.json`: - -```json -{ - "$schema": "./node_modules/oxlint/configuration_schema.json", - "plugins": ["react", "typescript", "oxc"], - "options": { - "typeAware": true - }, - "rules": { - "react/rules-of-hooks": "error", - "react/only-export-components": ["warn", { "allowConstantExport": true }] - } -} -``` - -See the [Oxlint rules documentation](https://oxc.rs/docs/guide/usage/linter/rules) for the full list of rules and categories. diff --git a/projects/sunbird-quml-player-react/index.html b/projects/sunbird-quml-player-react/index.html deleted file mode 100644 index be341868..00000000 --- a/projects/sunbird-quml-player-react/index.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - QUML Player - - -
- - - diff --git a/projects/sunbird-quml-player-react/package-lock.json b/projects/sunbird-quml-player-react/package-lock.json deleted file mode 100644 index 6d9d9195..00000000 --- a/projects/sunbird-quml-player-react/package-lock.json +++ /dev/null @@ -1,5641 +0,0 @@ -{ - "name": "@project-sunbird/sunbird-quml-player-web-component-react", - "version": "0.1.8", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "@project-sunbird/sunbird-quml-player-web-component-react", - "version": "0.1.8", - "dependencies": { - "@dnd-kit/core": "^6.3.1", - "@dnd-kit/sortable": "^8.0.0", - "@dnd-kit/utilities": "^3.2.2", - "@project-sunbird/client-services": "^8.1.4", - "@project-sunbird/sb-styles": "0.0.16", - "@project-sunbird/sunbird-player-sdk-v9": "6.0.5", - "@project-sunbird/telemetry-sdk": "1.3.0", - "axios": "^1.7.2", - "bootstrap": "5.3.3", - "classnames": "2.3.2", - "jquery": "3.7.1", - "katex": "0.16.10", - "lodash-es": "4.17.21", - "react": "18.2.0", - "react-dnd": "16.0.1", - "react-dnd-html5-backend": "16.0.1", - "react-dom": "18.2.0", - "uuid": "9.0.1" - }, - "devDependencies": { - "@rollup/plugin-terser": "0.4.4", - "@testing-library/jest-dom": "6.1.0", - "@testing-library/react": "14.0.0", - "@types/node": "^20.11.0", - "@types/react": "^18.2.0", - "@types/react-dom": "^18.2.0", - "@vitejs/plugin-react": "4.0.0", - "fs-extra": "11.1.1", - "jsdom": "^22.1.0", - "rollup": "3.29.0", - "sass": "1.69.0", - "typescript": "^5.3.0", - "vite": "^4.4.0", - "vitest": "0.34.0" - } - }, - "node_modules/@adobe/css-tools": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.5.0.tgz", - "integrity": "sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==", - "dev": true - }, - "node_modules/@angular/common": { - "version": "16.2.12", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-16.2.12.tgz", - "integrity": "sha512-B+WY/cT2VgEaz9HfJitBmgdk4I333XG/ybC98CMC4Wz8E49T8yzivmmxXB3OD6qvjcOB6ftuicl6WBqLbZNg2w==", - "peer": true, - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^16.14.0 || >=18.10.0" - }, - "peerDependencies": { - "@angular/core": "16.2.12", - "rxjs": "^6.5.3 || ^7.4.0" - } - }, - "node_modules/@angular/core": { - "version": "16.2.12", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-16.2.12.tgz", - "integrity": "sha512-GLLlDeke/NjroaLYOks0uyzFVo6HyLl7VOm0K1QpLXnYvW63W9Ql/T3yguRZa7tRkOAeFZ3jw+1wnBD4O8MoUA==", - "peer": true, - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^16.14.0 || >=18.10.0" - }, - "peerDependencies": { - "rxjs": "^6.5.3 || ^7.4.0", - "zone.js": "~0.13.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", - "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.29.7", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", - "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", - "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.29.7", - "@babel/generator": "^7.29.7", - "@babel/helper-compilation-targets": "^7.29.7", - "@babel/helper-module-transforms": "^7.29.7", - "@babel/helpers": "^7.29.7", - "@babel/parser": "^7.29.7", - "@babel/template": "^7.29.7", - "@babel/traverse": "^7.29.7", - "@babel/types": "^7.29.7", - "@jridgewell/remapping": "^2.3.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", - "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.29.7", - "@babel/types": "^7.29.7", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", - "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.29.7", - "@babel/helper-validator-option": "^7.29.7", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-globals": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", - "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", - "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.29.7", - "@babel/types": "^7.29.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", - "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.29.7", - "@babel/helper-validator-identifier": "^7.29.7", - "@babel/traverse": "^7.29.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", - "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", - "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", - "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", - "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", - "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", - "dev": true, - "dependencies": { - "@babel/template": "^7.29.7", - "@babel/types": "^7.29.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", - "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.29.7" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz", - "integrity": "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.29.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz", - "integrity": "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.29.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", - "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", - "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.29.7", - "@babel/parser": "^7.29.7", - "@babel/types": "^7.29.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", - "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.29.7", - "@babel/generator": "^7.29.7", - "@babel/helper-globals": "^7.29.7", - "@babel/parser": "^7.29.7", - "@babel/template": "^7.29.7", - "@babel/types": "^7.29.7", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", - "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.29.7", - "@babel/helper-validator-identifier": "^7.29.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@digitalbazaar/http-client": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@digitalbazaar/http-client/-/http-client-1.2.0.tgz", - "integrity": "sha512-W9KQQ5pUJcaR0I4c2HPJC0a7kRbZApIorZgPnEDwMBgj16iQzutGLrCXYaZOmxqVLVNqqlQ4aUJh+HBQZy4W6Q==", - "dependencies": { - "esm": "^3.2.22", - "ky": "^0.25.1", - "ky-universal": "^0.8.2" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@dnd-kit/accessibility": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.1.1.tgz", - "integrity": "sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==", - "dependencies": { - "tslib": "^2.0.0" - }, - "peerDependencies": { - "react": ">=16.8.0" - } - }, - "node_modules/@dnd-kit/core": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz", - "integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==", - "dependencies": { - "@dnd-kit/accessibility": "^3.1.1", - "@dnd-kit/utilities": "^3.2.2", - "tslib": "^2.0.0" - }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } - }, - "node_modules/@dnd-kit/sortable": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-8.0.0.tgz", - "integrity": "sha512-U3jk5ebVXe1Lr7c2wU7SBZjcWdQP+j7peHJfCspnA81enlu88Mgd7CC8Q+pub9ubP7eKVETzJW+IBAhsqbSu/g==", - "dependencies": { - "@dnd-kit/utilities": "^3.2.2", - "tslib": "^2.0.0" - }, - "peerDependencies": { - "@dnd-kit/core": "^6.1.0", - "react": ">=16.8.0" - } - }, - "node_modules/@dnd-kit/utilities": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.2.2.tgz", - "integrity": "sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==", - "dependencies": { - "tslib": "^2.0.0" - }, - "peerDependencies": { - "react": ">=16.8.0" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", - "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", - "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@popperjs/core": { - "version": "2.11.8", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", - "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", - "peer": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } - }, - "node_modules/@project-sunbird/client-services": { - "version": "8.1.4", - "resolved": "https://registry.npmjs.org/@project-sunbird/client-services/-/client-services-8.1.4.tgz", - "integrity": "sha512-0/VFo1x+v/wdCltMjmdhXA90Nq0N0CQARjJliYWSxo+krDiWUYO0dIUT5P847yL4v8LedvJjjwUiKrjlh1FC0w==", - "dependencies": { - "@project-sunbird/telemetry-sdk": "1.3.0", - "crypto-ld": "3.9.0", - "dayjs": "1.9.8", - "global": "^4.4.0", - "inversify": "5.1.1", - "jsonld": "5.2.0", - "jsonld-signatures": "7.0.0", - "jszip": "3.10.1", - "node-fetch": "2.7.0", - "path-browserify": "^1.0.1", - "qs": "6.9.7", - "reflect-metadata": "0.1.13", - "security-context": "4.0.0", - "whatwg-fetch": "3.6.19" - }, - "peerDependencies": { - "rxjs": ">=6" - } - }, - "node_modules/@project-sunbird/sb-styles": { - "version": "0.0.16", - "resolved": "https://registry.npmjs.org/@project-sunbird/sb-styles/-/sb-styles-0.0.16.tgz", - "integrity": "sha512-bQB1ZGEdxk7/mcDMjcY9d7C2tpJpinmBzbxOPV0YDoOiZVHv1haS+yFlUbxxgDz9hhrr3u6A+vBoBUaX2We5gA==" - }, - "node_modules/@project-sunbird/sunbird-player-sdk-v9": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/@project-sunbird/sunbird-player-sdk-v9/-/sunbird-player-sdk-v9-6.0.5.tgz", - "integrity": "sha512-TN6Dn/BFhZ5ETxdLulZvYO4N+LTRp1ZznkHxAcfDGLl0c1L2wCEH4dEVAzcFvjgXMXwVjac400gDWL0ElCXTYw==", - "dependencies": { - "tslib": "^2.0.0" - }, - "peerDependencies": { - "@angular/common": "^16.2.12", - "@angular/core": "^16.2.12", - "@project-sunbird/sb-styles": ">= 0.0.7", - "ally.js": "1.4.1" - } - }, - "node_modules/@project-sunbird/telemetry-sdk": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@project-sunbird/telemetry-sdk/-/telemetry-sdk-1.3.0.tgz", - "integrity": "sha512-9vocPJpB08/8pAXDUKQmhCiBxJ9qHxORF1+ot3kJczSnRh/K+POpAWDCR4iJ2+gWXPDE03WIWezshKpyf0RdYQ==" - }, - "node_modules/@react-dnd/asap": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-5.0.2.tgz", - "integrity": "sha512-WLyfoHvxhs0V9U+GTsGilGgf2QsPl6ZZ44fnv0/b8T3nQyvzxidxsg/ZltbWssbsRDlYW8UKSQMTGotuTotZ6A==" - }, - "node_modules/@react-dnd/invariant": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@react-dnd/invariant/-/invariant-4.0.2.tgz", - "integrity": "sha512-xKCTqAK/FFauOM9Ta2pswIyT3D8AQlfrYdOi/toTPEhqCuAs1v5tcJ3Y08Izh1cJ5Jchwy9SeAXmMg6zrKs2iw==" - }, - "node_modules/@react-dnd/shallowequal": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz", - "integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==" - }, - "node_modules/@rollup/plugin-terser": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", - "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==", - "dev": true, - "dependencies": { - "serialize-javascript": "^6.0.1", - "smob": "^1.0.0", - "terser": "^5.17.4" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.10", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", - "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==", - "dev": true - }, - "node_modules/@testing-library/dom": { - "version": "9.3.4", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.4.tgz", - "integrity": "sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "5.1.3", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@testing-library/dom/node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", - "dev": true, - "dependencies": { - "deep-equal": "^2.0.5" - } - }, - "node_modules/@testing-library/dom/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@testing-library/jest-dom": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.1.0.tgz", - "integrity": "sha512-EUAg9pvOkzmGXUSyAPt0h6yAXHxsn+FMNS1o7OX8TErmldZML2ywt10lotZXx/a1PDiSnq0fGGyEV/ybKSLPWQ==", - "dev": true, - "dependencies": { - "@adobe/css-tools": "^4.0.1", - "@babel/runtime": "^7.9.2", - "aria-query": "^5.0.0", - "chalk": "^3.0.0", - "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.5.6", - "lodash": "^4.17.15", - "redent": "^3.0.0" - }, - "engines": { - "node": ">=14", - "npm": ">=6", - "yarn": ">=1" - }, - "peerDependencies": { - "@jest/globals": ">= 28", - "@types/jest": ">= 28", - "jest": ">= 28", - "vitest": ">= 0.32" - }, - "peerDependenciesMeta": { - "@jest/globals": { - "optional": true - }, - "@types/jest": { - "optional": true - }, - "jest": { - "optional": true - }, - "vitest": { - "optional": true - } - } - }, - "node_modules/@testing-library/react": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-14.0.0.tgz", - "integrity": "sha512-S04gSNJbYE30TlIMLTzv6QCTzt9AqIF5y6s6SzVFILNcNvbV/jU96GeiTPillGQo+Ny64M/5PV7klNYYgv5Dfg==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^9.0.0", - "@types/react-dom": "^18.0.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@tootallnate/once": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.1.tgz", - "integrity": "sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@types/aria-query": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", - "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", - "dev": true - }, - "node_modules/@types/chai": { - "version": "4.3.20", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.20.tgz", - "integrity": "sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ==", - "dev": true - }, - "node_modules/@types/chai-subset": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.6.tgz", - "integrity": "sha512-m8lERkkQj+uek18hXOZuec3W/fCRTrU4hrnXjH3qhHy96ytuPaPiWGgu7sJb7tZxZonO75vYAjCvpe/e4VUwRw==", - "dev": true, - "peerDependencies": { - "@types/chai": "<5.2.0" - } - }, - "node_modules/@types/node": { - "version": "20.19.43", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", - "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", - "devOptional": true, - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@types/prop-types": { - "version": "15.7.15", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", - "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", - "devOptional": true - }, - "node_modules/@types/react": { - "version": "18.3.31", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.31.tgz", - "integrity": "sha512-vfEqpXTvwT91yhmwdfouStN2hSKwTvyRs8qpLfADyrq/kxDw0hZM7Wk9Ug1FELj8hIby+S/+kQCSRFF32nv2Qw==", - "devOptional": true, - "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.2.2" - } - }, - "node_modules/@types/react-dom": { - "version": "18.3.7", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", - "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", - "dev": true, - "peerDependencies": { - "@types/react": "^18.0.0" - } - }, - "node_modules/@vitejs/plugin-react": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.0.0.tgz", - "integrity": "sha512-HX0XzMjL3hhOYm+0s95pb0Z7F8O81G7joUHgfDd/9J/ZZf5k4xX6QAMFkKsHFxaHlf6X7GD7+XuaZ66ULiJuhQ==", - "dev": true, - "dependencies": { - "@babel/core": "^7.21.4", - "@babel/plugin-transform-react-jsx-self": "^7.21.0", - "@babel/plugin-transform-react-jsx-source": "^7.19.6", - "react-refresh": "^0.14.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "vite": "^4.2.0" - } - }, - "node_modules/@vitest/expect": { - "version": "0.34.0", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.0.tgz", - "integrity": "sha512-d1ZU0XomWFAFyYIc6uNuY0N8NJIWESyO/6ZmwLvlHZw0GevH4AEEpq178KjXIvSCrbHN0GnzYzitd0yjfy7+Ow==", - "dev": true, - "dependencies": { - "@vitest/spy": "0.34.0", - "@vitest/utils": "0.34.0", - "chai": "^4.3.7" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "0.34.0", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.0.tgz", - "integrity": "sha512-xaqM+oArJothtYXzy/dwu/iHe93Khq5QkvnYbzTxiLA0enD2peft1cask3yE6cJpwMkr7C2D1uMJwnTt4mquDw==", - "dev": true, - "dependencies": { - "@vitest/utils": "0.34.0", - "p-limit": "^4.0.0", - "pathe": "^1.1.1" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot": { - "version": "0.34.0", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.0.tgz", - "integrity": "sha512-eGN5XBZHYOghxCOQbf8dcn6/3g7IW77GOOOC/mNFYwRXsPeoQgcgWnhj+6wgJ04pVv25wpxWL9jUkzaQ7LoFtg==", - "dev": true, - "dependencies": { - "magic-string": "^0.30.1", - "pathe": "^1.1.1", - "pretty-format": "^29.5.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@vitest/snapshot/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@vitest/snapshot/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true - }, - "node_modules/@vitest/spy": { - "version": "0.34.0", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.0.tgz", - "integrity": "sha512-0SZaWrQvL9ZiF/uJvyWSvsKjfuMvD1M6dE5BbE4Dmt8Vh3k4htwCV8g3ce8YOYmJSxkbh6TNOpippD6NVsxW6w==", - "dev": true, - "dependencies": { - "tinyspy": "^2.1.1" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "0.34.0", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.0.tgz", - "integrity": "sha512-IktrDLhBKf3dEUUxH+lcHiPnaw952+GdGvoxg99liMscgP6IePf6LuMY7B9dEIHkFunB1R8VMR/wmI/4UGg1aw==", - "dev": true, - "dependencies": { - "diff-sequences": "^29.4.3", - "loupe": "^2.3.6", - "pretty-format": "^29.5.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@vitest/utils/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@vitest/utils/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true - }, - "node_modules/abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "deprecated": "Use your platform's native atob() and btoa() methods instead", - "dev": true - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/acorn": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", - "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.5", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", - "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", - "dev": true, - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/ajv": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", - "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ally.js": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/ally.js/-/ally.js-1.4.1.tgz", - "integrity": "sha512-ZewdfuwP6VewtMN36QY0gmiyvBfMnmEaNwbVu2nTS6zRt069viTgkYgaDiqu6vRJ1VJCriNqV0jGMu44R8zNbA==", - "peer": true, - "dependencies": { - "css.escape": "^1.5.0", - "platform": "1.3.3" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/aria-query": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", - "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", - "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", - "dependencies": { - "call-bound": "^1.0.3", - "is-array-buffer": "^3.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", - "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/async-function": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", - "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", - "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==" - }, - "node_modules/axios": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", - "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/base-x": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz", - "integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/base64url": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", - "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/base64url-universal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/base64url-universal/-/base64url-universal-1.1.0.tgz", - "integrity": "sha512-WyftvZqye29YQ10ZnuiBeEj0lk8SN8xHU9hOznkLc85wS1cLTp6RpzlMrHxMPD9nH7S55gsBqMqgGyz93rqmkA==", - "dependencies": { - "base64url": "^3.0.0" - }, - "engines": { - "node": ">=8.3.0" - } - }, - "node_modules/baseline-browser-mapping": { - "version": "2.10.40", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.40.tgz", - "integrity": "sha512-BSSLZ9/Cjjv7Gtj5B68ZzXcXUg8iOf3fme+FCuh8rC/Go+Kmh8cox7M3A8dolou16s64QjLPOSdngh7GxXvkSw==", - "dev": true, - "bin": { - "baseline-browser-mapping": "dist/cli.cjs" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bootstrap": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz", - "integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/twbs" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/bootstrap" - } - ], - "peerDependencies": { - "@popperjs/core": "^2.11.8" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.28.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.4.tgz", - "integrity": "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "baseline-browser-mapping": "^2.10.38", - "caniuse-lite": "^1.0.30001799", - "electron-to-chromium": "^1.5.376", - "node-releases": "^2.0.48", - "update-browserslist-db": "^1.2.3" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", - "dependencies": { - "base-x": "^3.0.2" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/call-bind": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", - "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "get-intrinsic": "^1.3.0", - "set-function-length": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001799", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz", - "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/canonicalize": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/canonicalize/-/canonicalize-1.0.8.tgz", - "integrity": "sha512-0CNTVCLZggSh7bc5VkX5WWPWO+cyZbNd07IHIsSXLia/eAq+r836hgk+8BKoEh7949Mda87VUOitx5OddVj64A==" - }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" - }, - "node_modules/chai": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", - "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", - "dev": true, - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.3", - "deep-eql": "^4.1.3", - "get-func-name": "^2.0.2", - "loupe": "^2.3.6", - "pathval": "^1.1.1", - "type-detect": "^4.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/check-error": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/classnames": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", - "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "engines": { - "node": ">= 12" - } - }, - "node_modules/confbox": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", - "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", - "dev": true - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "node_modules/crypto-ld": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/crypto-ld/-/crypto-ld-3.9.0.tgz", - "integrity": "sha512-PFE7V6A2QNnUp6iiPVEZI4p8wsztkEWLbY1BAXVnclm/aw4KGwpJ+1Ds4vQUCJ5BsWxj15fwE5rHQ8AWaWB2nw==", - "dependencies": { - "base64url-universal": "^1.0.1", - "bs58": "^4.0.1", - "node-forge": "~0.10.0", - "semver": "^6.2.0" - }, - "engines": { - "node": ">=8.3.0" - }, - "optionalDependencies": { - "sodium-native": "^3.2.0" - } - }, - "node_modules/css.escape": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", - "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==" - }, - "node_modules/cssstyle": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-3.0.0.tgz", - "integrity": "sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==", - "dev": true, - "dependencies": { - "rrweb-cssom": "^0.6.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "devOptional": true - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/data-uri-to-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz", - "integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/data-urls": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-4.0.0.tgz", - "integrity": "sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==", - "dev": true, - "dependencies": { - "abab": "^2.0.6", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^12.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/data-view-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", - "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", - "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/inspect-js" - } - }, - "node_modules/data-view-byte-offset": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", - "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/dayjs": { - "version": "1.9.8", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.9.8.tgz", - "integrity": "sha512-F42qBtJRa30FKF7XDnOQyNUTsaxDkuaZRj/i7BejSHC34LlLfPoIU4aeopvWfM+m1dJ6/DHKAWLg2ur+pLgq1w==" - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decimal.js": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", - "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", - "dev": true - }, - "node_modules/deep-eql": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", - "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", - "dev": true, - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/deep-equal": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", - "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.5", - "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.2", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.2", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/deep-equal/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/dnd-core": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-16.0.1.tgz", - "integrity": "sha512-HK294sl7tbw6F6IeuK16YSBUoorvHpY8RHO+9yFfaJyCDVb6n7PRcezrOEOa2SBCqiYpemh5Jx20ZcjKdFAVng==", - "dependencies": { - "@react-dnd/asap": "^5.0.1", - "@react-dnd/invariant": "^4.0.1", - "redux": "^4.2.0" - } - }, - "node_modules/dom-accessibility-api": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", - "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", - "dev": true - }, - "node_modules/dom-walk": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", - "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" - }, - "node_modules/domexception": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", - "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", - "deprecated": "Use your platform's native DOMException instead", - "dev": true, - "dependencies": { - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.5.381", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.381.tgz", - "integrity": "sha512-n9Wa6yB+vDsGuA8AKbl/0z7HbvWqt5jxIdvr1IUicd0ryPrk7/xzwqLv8D9AbbvZ6avVNtXYLTfmgFHkwkyelg==", - "dev": true - }, - "node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/es-abstract": { - "version": "1.24.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", - "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", - "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.3.0", - "get-proto": "^1.0.1", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-set": "^2.0.3", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.1", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.4", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "stop-iteration-iterator": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.19" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-abstract-get": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-abstract-get/-/es-abstract-get-1.0.0.tgz", - "integrity": "sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==", - "dependencies": { - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.2", - "is-callable": "^1.2.7", - "object-inspect": "^1.13.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-get-iterator/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/es-object-atoms": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", - "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-to-primitive": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.4.tgz", - "integrity": "sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==", - "dependencies": { - "es-abstract-get": "^1.0.0", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "is-callable": "^1.2.7", - "is-date-object": "^1.1.0", - "is-symbol": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/esm": { - "version": "3.2.25", - "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", - "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fetch-blob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-2.1.2.tgz", - "integrity": "sha512-YKqtUDwqLyfyMnmbw8XD6Q8j9i/HggKtPEI+pZ1+8bvheBu78biSmNaXWusx1TauGqtUUGx/cBb1mKdq2rLYow==", - "engines": { - "node": "^10.17.0 || >=12.3.0" - }, - "peerDependenciesMeta": { - "domexception": { - "optional": true - } - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/follow-redirects": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", - "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-each": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", - "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", - "dependencies": { - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", - "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.4", - "mime-types": "^2.1.35" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fs-extra": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", - "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function.prototype.name": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.2.0.tgz", - "integrity": "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==", - "dependencies": { - "call-bind": "^1.0.9", - "call-bound": "^1.0.4", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2", - "hasown": "^2.0.4", - "is-callable": "^1.2.7", - "is-document.all": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/generator-function": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", - "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/get-symbol-description": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", - "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "dependencies": { - "assert-plus": "^1.0.0" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/global": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", - "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", - "dependencies": { - "min-document": "^2.19.0", - "process": "^0.11.10" - } - }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/has-bigints": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", - "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", - "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", - "dependencies": { - "dunder-proto": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", - "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "dependencies": { - "react-is": "^16.7.0" - } - }, - "node_modules/hoist-non-react-statics/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/html-encoding-sniffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", - "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", - "dev": true, - "dependencies": { - "whatwg-encoding": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" - }, - "node_modules/immutable": { - "version": "4.3.9", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.9.tgz", - "integrity": "sha512-ObHy4YN7ycwZOUCLI1/6svfyAFu7vL8RhAvVu/bh/RZW9EPlOyDaQ9jDQWCtdqzaXUjgXZCW1migtHE7YI7UGQ==", - "dev": true - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/internal-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", - "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.2", - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/inversify": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/inversify/-/inversify-5.1.1.tgz", - "integrity": "sha512-j8grHGDzv1v+8T1sAQ+3boTCntFPfvxLCkNcxB1J8qA0lUN+fAlSyYd+RXKvaPRL4AGyPxViutBEJHNXOyUdFQ==" - }, - "node_modules/is-arguments": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", - "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", - "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-async-function": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", - "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", - "dependencies": { - "async-function": "^1.0.0", - "call-bound": "^1.0.3", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", - "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", - "dependencies": { - "has-bigints": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", - "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-view": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", - "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", - "dependencies": { - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", - "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", - "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-document.all": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-document.all/-/is-document.all-1.0.0.tgz", - "integrity": "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==", - "dependencies": { - "call-bound": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finalizationregistry": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", - "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-generator-function": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", - "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", - "dependencies": { - "call-bound": "^1.0.4", - "generator-function": "^2.0.0", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", - "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, - "node_modules/is-regex": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", - "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", - "dependencies": { - "call-bound": "^1.0.2", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-set": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", - "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-string": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", - "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", - "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", - "dependencies": { - "call-bound": "^1.0.2", - "has-symbols": "^1.1.0", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", - "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", - "dependencies": { - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" - }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", - "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", - "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", - "dependencies": { - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" - }, - "node_modules/jquery": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", - "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==" - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" - }, - "node_modules/jsdom": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-22.1.0.tgz", - "integrity": "sha512-/9AVW7xNbsBv6GfWho4TTNjEo9fe6Zhf9O7s0Fhhr3u+awPwAJMKwAMXnkk5vBxflqLW9hTHX/0cs+P3gW+cQw==", - "dev": true, - "dependencies": { - "abab": "^2.0.6", - "cssstyle": "^3.0.0", - "data-urls": "^4.0.0", - "decimal.js": "^10.4.3", - "domexception": "^4.0.0", - "form-data": "^4.0.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.1", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.4", - "parse5": "^7.1.2", - "rrweb-cssom": "^0.6.0", - "saxes": "^6.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.2", - "w3c-xmlserializer": "^4.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^2.0.0", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^12.0.1", - "ws": "^8.13.0", - "xml-name-validator": "^4.0.0" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonfile": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", - "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonld": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/jsonld/-/jsonld-5.2.0.tgz", - "integrity": "sha512-JymgT6Xzk5CHEmHuEyvoTNviEPxv6ihLWSPu1gFdtjSAyM6cFqNrv02yS/SIur3BBIkCf0HjizRc24d8/FfQKw==", - "dependencies": { - "@digitalbazaar/http-client": "^1.1.0", - "canonicalize": "^1.0.1", - "lru-cache": "^6.0.0", - "rdf-canonize": "^3.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/jsonld-signatures": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/jsonld-signatures/-/jsonld-signatures-7.0.0.tgz", - "integrity": "sha512-J/nA+llcYYjErPHG9WFpXvR82TOg5fbHk/7rXbx4Ts854DPReaKAAd0hAZ+s5/P2WIIAZPIHCqA+iz1QrOqeiQ==", - "dependencies": { - "base64url": "^3.0.1", - "crypto-ld": "^3.7.0", - "jsonld": "^4.0.1", - "node-forge": "^0.10.0", - "security-context": "^4.0.0", - "serialize-error": "^5.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jsonld-signatures/node_modules/jsonld": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsonld/-/jsonld-4.0.1.tgz", - "integrity": "sha512-ltEqMQB37ZxZnsgmI+9rqHYkz1M6PqUykuS1t2aQNuH1oiLrUDYz5nyVkHQDgjFd7CFKTIWeLiNhwdwFrH5o5A==", - "dependencies": { - "canonicalize": "^1.0.1", - "lru-cache": "^5.1.1", - "object.fromentries": "^2.0.2", - "rdf-canonize": "^2.0.1", - "request": "^2.88.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonld-signatures/node_modules/rdf-canonize": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/rdf-canonize/-/rdf-canonize-2.0.1.tgz", - "integrity": "sha512-/GVELjrfW8G/wS4QfDZ5Kq68cS1belVNJqZlcwiErerexeBUsgOINCROnP7UumWIBNdeCwTVLE9NVXMnRYK0lA==", - "dependencies": { - "semver": "^6.3.0", - "setimmediate": "^1.0.5" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonld/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jsonld/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/jszip": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", - "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", - "dependencies": { - "lie": "~3.3.0", - "pako": "~1.0.2", - "readable-stream": "~2.3.6", - "setimmediate": "^1.0.5" - } - }, - "node_modules/katex": { - "version": "0.16.10", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.10.tgz", - "integrity": "sha512-ZiqaC04tp2O5utMsl2TEZTXxa6WSC4yo0fv5ML++D3QZv/vx2Mct0mTlRx3O+uUkjfuAgOkzsCmq5MiUEsDDdA==", - "funding": [ - "https://opencollective.com/katex", - "https://github.com/sponsors/katex" - ], - "dependencies": { - "commander": "^8.3.0" - }, - "bin": { - "katex": "cli.js" - } - }, - "node_modules/ky": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/ky/-/ky-0.25.1.tgz", - "integrity": "sha512-PjpCEWlIU7VpiMVrTwssahkYXX1by6NCT0fhTUX34F3DTinARlgMpriuroolugFPcMgpPWrOW4mTb984Qm1RXA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/ky?sponsor=1" - } - }, - "node_modules/ky-universal": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/ky-universal/-/ky-universal-0.8.2.tgz", - "integrity": "sha512-xe0JaOH9QeYxdyGLnzUOVGK4Z6FGvDVzcXFTdrYA1f33MZdEa45sUDaMBy98xQMcsd2XIBrTXRrRYnegcSdgVQ==", - "dependencies": { - "abort-controller": "^3.0.0", - "node-fetch": "3.0.0-beta.9" - }, - "engines": { - "node": ">=10.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/ky-universal?sponsor=1" - }, - "peerDependencies": { - "ky": ">=0.17.0", - "web-streams-polyfill": ">=2.0.0" - }, - "peerDependenciesMeta": { - "web-streams-polyfill": { - "optional": true - } - } - }, - "node_modules/ky-universal/node_modules/node-fetch": { - "version": "3.0.0-beta.9", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.0.0-beta.9.tgz", - "integrity": "sha512-RdbZCEynH2tH46+tj0ua9caUHVWrd/RHnRfvly2EVdqGmI3ndS1Vn/xjm5KuGejDt2RNDQsVRLPNd2QPwcewVg==", - "dependencies": { - "data-uri-to-buffer": "^3.0.1", - "fetch-blob": "^2.1.1" - }, - "engines": { - "node": "^10.17 || >=12.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, - "node_modules/lie": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", - "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", - "dependencies": { - "immediate": "~3.0.5" - } - }, - "node_modules/local-pkg": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz", - "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/lodash": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", - "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", - "dev": true - }, - "node_modules/lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/loupe": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", - "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.1" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/lz-string": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", - "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", - "dev": true, - "bin": { - "lz-string": "bin/bin.js" - } - }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dev": true, - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/min-document": { - "version": "2.19.2", - "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.2.tgz", - "integrity": "sha512-8S5I8db/uZN8r9HSLFVWPdJCvYOejMcEC82VIzNUc6Zkklf/d1gg2psfE79/vyhWOj4+J8MtwmoOz3TmvaGu5A==", - "dependencies": { - "dom-walk": "^0.1.0" - } - }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/mlly": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.2.tgz", - "integrity": "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==", - "dev": true, - "dependencies": { - "acorn": "^8.16.0", - "pathe": "^2.0.3", - "pkg-types": "^1.3.1", - "ufo": "^1.6.3" - } - }, - "node_modules/mlly/node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.3.15", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz", - "integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/node-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/node-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/node-forge": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", - "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/node-gyp-build": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", - "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", - "optional": true, - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/node-releases": { - "version": "2.0.50", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.50.tgz", - "integrity": "sha512-J6l92tKHX6w8Jy5nO1Vuc01NoIiRGi/d6qBKVxh+IQ8Cr3b6HbVNfKiF8ZpFKufTwpwxMmce2W3iQZ861ZRyTg==", - "dev": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nwsapi": { - "version": "2.2.24", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.24.tgz", - "integrity": "sha512-7YRhZ3jS45LwmSCT4b2sVFHt/WuovaktDU07QrtOBY2PXskss5a9jfmR9jptyumwXST+rFjrmppMY1KT/yn35A==", - "dev": true - }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "engines": { - "node": "*" - } - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-is": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", - "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", - "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0", - "has-symbols": "^1.1.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/own-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", - "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", - "dependencies": { - "get-intrinsic": "^1.2.6", - "object-keys": "^1.1.1", - "safe-push-apply": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^1.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" - }, - "node_modules/parse5": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", - "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", - "dev": true, - "dependencies": { - "entities": "^6.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" - }, - "node_modules/pathe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", - "dev": true - }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", - "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pkg-types": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", - "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", - "dev": true, - "dependencies": { - "confbox": "^0.1.8", - "mlly": "^1.7.4", - "pathe": "^2.0.1" - } - }, - "node_modules/pkg-types/node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true - }, - "node_modules/platform": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.3.tgz", - "integrity": "sha512-VJK1SRmXBpjwsB4YOHYSturx48rLKMzHgCqDH2ZDa6ZbMS/N5huoNqyQdK5Fj/xayu3fqbXckn5SeCS1EbMDZg==", - "peer": true - }, - "node_modules/possible-typed-array-names": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", - "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/postcss": { - "version": "8.5.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.16.tgz", - "integrity": "sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.12", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "node_modules/psl": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", - "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", - "dependencies": { - "punycode": "^2.3.1" - }, - "funding": { - "url": "https://github.com/sponsors/lupomontero" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/rdf-canonize": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/rdf-canonize/-/rdf-canonize-3.4.0.tgz", - "integrity": "sha512-fUeWjrkOO0t1rg7B2fdyDTvngj+9RlUyL92vOdiB7c0FPguWVsniIMjEtHH+meLBO9rzkUlUzBVXgWrjI8P9LA==", - "dependencies": { - "setimmediate": "^1.0.5" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dnd": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/react-dnd/-/react-dnd-16.0.1.tgz", - "integrity": "sha512-QeoM/i73HHu2XF9aKksIUuamHPDvRglEwdHL4jsp784BgUuWcg6mzfxT0QDdQz8Wj0qyRKx2eMg8iZtWvU4E2Q==", - "dependencies": { - "@react-dnd/invariant": "^4.0.1", - "@react-dnd/shallowequal": "^4.0.1", - "dnd-core": "^16.0.1", - "fast-deep-equal": "^3.1.3", - "hoist-non-react-statics": "^3.3.2" - }, - "peerDependencies": { - "@types/hoist-non-react-statics": ">= 3.3.1", - "@types/node": ">= 12", - "@types/react": ">= 16", - "react": ">= 16.14" - }, - "peerDependenciesMeta": { - "@types/hoist-non-react-statics": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@types/react": { - "optional": true - } - } - }, - "node_modules/react-dnd-html5-backend": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/react-dnd-html5-backend/-/react-dnd-html5-backend-16.0.1.tgz", - "integrity": "sha512-Wu3dw5aDJmOGw8WjH1I1/yTH+vlXEL4vmjk5p+MHxP8HuHJS1lAGeIdG/hze1AvNeXWo/JgULV87LyQOr+r5jw==", - "dependencies": { - "dnd-core": "^16.0.1" - } - }, - "node_modules/react-dom": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", - "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" - }, - "peerDependencies": { - "react": "^18.2.0" - } - }, - "node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, - "node_modules/react-refresh": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", - "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, - "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/redux": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", - "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", - "dependencies": { - "@babel/runtime": "^7.9.2" - } - }, - "node_modules/reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" - }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", - "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.1", - "which-builtin-type": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", - "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "set-function-name": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/request/node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/request/node_modules/qs": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.5.tgz", - "integrity": "sha512-mzR4sElr1bfCaPJe7m8ilJ6ZXdDaGoObcYR0ZHSsktM/Lt21MVHj5De30GQH2eiZ1qGRTO7LCAzQsUeXTNexWQ==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/request/node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/request/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, - "node_modules/rollup": { - "version": "3.29.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.0.tgz", - "integrity": "sha512-nszM8DINnx1vSS+TpbWKMkxem0CDWk3cSit/WWCBVs9/JZ1I/XLwOsiUglYuYReaeWWSsW9kge5zE5NZtf/a4w==", - "dev": true, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=14.18.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/rrweb-cssom": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", - "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==", - "dev": true - }, - "node_modules/rxjs": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", - "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", - "peer": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/safe-array-concat": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz", - "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==", - "dependencies": { - "call-bind": "^1.0.9", - "call-bound": "^1.0.4", - "get-intrinsic": "^1.3.0", - "has-symbols": "^1.1.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-array-concat/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-push-apply": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", - "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", - "dependencies": { - "es-errors": "^1.3.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-push-apply/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" - }, - "node_modules/safe-regex-test": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", - "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-regex": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/sass": { - "version": "1.69.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.69.0.tgz", - "integrity": "sha512-l3bbFpfTOGgQZCLU/gvm1lbsQ5mC/WnLz3djL2v4WCJBDrWm58PO+jgngcGRNnKUh6wSsdm50YaovTqskZ0xDQ==", - "dev": true, - "dependencies": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/saxes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", - "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "dev": true, - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=v12.22.7" - } - }, - "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "node_modules/security-context": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/security-context/-/security-context-4.0.0.tgz", - "integrity": "sha512-yiDCS7tpKQl6p4NG57BdKLTSNLFfj5HosBIzXBl4jZf/qorJzSzbEUIdLhN+vVYgyLlvjixY8DPPTgqI8zvNCA==" - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/serialize-error": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-5.0.0.tgz", - "integrity": "sha512-/VtpuyzYf82mHYTtI4QKtwHa79vAdU5OQpNPAmE/0UDdlGT0ZxHwC+J6gXkw29wwoVI8fMPsfcVHOwXtUQYYQA==", - "dependencies": { - "type-fest": "^0.8.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-proto": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", - "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" - }, - "node_modules/side-channel": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", - "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.4", - "side-channel-list": "^1.0.1", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", - "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true - }, - "node_modules/smob": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/smob/-/smob-1.6.2.tgz", - "integrity": "sha512-RQsvleCbF8cVHEv+xuDGaA4pOizFqJ0GgjtMSRo6oP8pnN7WsigHgVGey6aILRBKv4W2YOMHLqbKdnB6hpB9fw==", - "dev": true, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/sodium-native": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-3.4.1.tgz", - "integrity": "sha512-PaNN/roiFWzVVTL6OqjzYct38NSXewdl2wz8SRB51Br/MLIJPrbM3XexhVWkq7D3UWMysfrhKVf1v1phZq6MeQ==", - "hasInstallScript": true, - "optional": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/sshpk": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", - "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true - }, - "node_modules/std-env": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", - "dev": true - }, - "node_modules/stop-iteration-iterator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", - "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", - "dependencies": { - "es-errors": "^1.3.0", - "internal-slot": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/string.prototype.trim": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.11.tgz", - "integrity": "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==", - "dependencies": { - "call-bind": "^1.0.9", - "call-bound": "^1.0.4", - "define-data-property": "^1.1.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.24.2", - "es-object-atoms": "^1.1.2", - "has-property-descriptors": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.10.tgz", - "integrity": "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==", - "dependencies": { - "call-bind": "^1.0.9", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-literal": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.3.0.tgz", - "integrity": "sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==", - "dev": true, - "dependencies": { - "acorn": "^8.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, - "node_modules/terser": { - "version": "5.48.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.48.0.tgz", - "integrity": "sha512-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q==", - "dev": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.15.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/tinybench": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", - "dev": true - }, - "node_modules/tinypool": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.7.0.tgz", - "integrity": "sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==", - "dev": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tinyspy": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", - "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", - "dev": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/tough-cookie": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", - "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", - "dev": true, - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tough-cookie/node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/tr46": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", - "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", - "dev": true, - "dependencies": { - "punycode": "^2.3.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" - }, - "node_modules/type-detect": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", - "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/typed-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", - "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", - "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", - "dependencies": { - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", - "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.15", - "reflect.getprototypeof": "^1.0.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.8.tgz", - "integrity": "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==", - "dependencies": { - "call-bind": "^1.0.9", - "for-each": "^0.3.5", - "gopd": "^1.2.0", - "is-typed-array": "^1.1.15", - "possible-typed-array-names": "^1.1.0", - "reflect.getprototypeof": "^1.0.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/ufo": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.4.tgz", - "integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==", - "dev": true - }, - "node_modules/unbox-primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", - "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", - "dependencies": { - "call-bound": "^1.0.3", - "has-bigints": "^1.0.2", - "has-symbols": "^1.1.0", - "which-boxed-primitive": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "devOptional": true - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/verror/node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" - }, - "node_modules/vite": { - "version": "4.5.14", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.14.tgz", - "integrity": "sha512-+v57oAaoYNnO3hIu5Z/tJRZjq5aHM2zDve9YZ8HngVHbhk66RStobhb1sqPMIPEleV6cNKYK4eGrAbE9Ulbl2g==", - "dev": true, - "dependencies": { - "esbuild": "^0.18.10", - "postcss": "^8.4.27", - "rollup": "^3.27.1" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - }, - "peerDependencies": { - "@types/node": ">= 14", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/vite-node": { - "version": "0.34.0", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.34.0.tgz", - "integrity": "sha512-rGZMvpb052rjUwJA/a17xMfOibzNF7byMdRSTcN2Lw8uxX08s5EfjWW5mBkm3MSFTPctMSVtT2yC+8ShrZbT5g==", - "dev": true, - "dependencies": { - "cac": "^6.7.14", - "debug": "^4.3.4", - "mlly": "^1.4.0", - "pathe": "^1.1.1", - "picocolors": "^1.0.0", - "vite": "^3.0.0 || ^4.0.0" - }, - "bin": { - "vite-node": "vite-node.mjs" - }, - "engines": { - "node": ">=v14.18.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/vitest": { - "version": "0.34.0", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.34.0.tgz", - "integrity": "sha512-8Pnc1fVt1P6uBncdUZ++hgiJGgxIRKuz4bmS/PQziaEcUj0D1g9cGiR1MbLrcsvFTC6fgrqDhYoTAdBG356WMA==", - "dev": true, - "dependencies": { - "@types/chai": "^4.3.5", - "@types/chai-subset": "^1.3.3", - "@types/node": "*", - "@vitest/expect": "0.34.0", - "@vitest/runner": "0.34.0", - "@vitest/snapshot": "0.34.0", - "@vitest/spy": "0.34.0", - "@vitest/utils": "0.34.0", - "acorn": "^8.9.0", - "acorn-walk": "^8.2.0", - "cac": "^6.7.14", - "chai": "^4.3.7", - "debug": "^4.3.4", - "local-pkg": "^0.4.3", - "magic-string": "^0.30.1", - "pathe": "^1.1.1", - "picocolors": "^1.0.0", - "std-env": "^3.3.3", - "strip-literal": "^1.0.1", - "tinybench": "^2.5.0", - "tinypool": "^0.7.0", - "vite": "^3.0.0 || ^4.0.0", - "vite-node": "0.34.0", - "why-is-node-running": "^2.2.2" - }, - "bin": { - "vitest": "vitest.mjs" - }, - "engines": { - "node": ">=v14.18.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@vitest/browser": "*", - "@vitest/ui": "*", - "happy-dom": "*", - "jsdom": "*", - "playwright": "*", - "safaridriver": "*", - "webdriverio": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@vitest/browser": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - }, - "playwright": { - "optional": true - }, - "safaridriver": { - "optional": true - }, - "webdriverio": { - "optional": true - } - } - }, - "node_modules/w3c-xmlserializer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", - "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", - "dev": true, - "dependencies": { - "xml-name-validator": "^4.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", - "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", - "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", - "dev": true, - "dependencies": { - "iconv-lite": "0.6.3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-fetch": { - "version": "3.6.19", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.19.tgz", - "integrity": "sha512-d67JP4dHSbm2TrpFj8AbO8DnL1JXL5J9u0Kq2xW6d0TFDbCA3Muhdt8orXC22utleTVj7Prqt82baN6RBvnEgw==" - }, - "node_modules/whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-url": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-12.0.1.tgz", - "integrity": "sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ==", - "dev": true, - "dependencies": { - "tr46": "^4.1.1", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", - "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", - "dependencies": { - "is-bigint": "^1.1.0", - "is-boolean-object": "^1.2.1", - "is-number-object": "^1.1.1", - "is-string": "^1.1.1", - "is-symbol": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", - "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", - "dependencies": { - "call-bound": "^1.0.2", - "function.prototype.name": "^1.1.6", - "has-tostringtag": "^1.0.2", - "is-async-function": "^2.0.0", - "is-date-object": "^1.1.0", - "is-finalizationregistry": "^1.1.0", - "is-generator-function": "^1.0.10", - "is-regex": "^1.2.1", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.1.0", - "which-collection": "^1.0.2", - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" - }, - "node_modules/which-collection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", - "dependencies": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.22", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.22.tgz", - "integrity": "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.9", - "call-bound": "^1.0.4", - "for-each": "^0.3.5", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/why-is-node-running": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", - "dev": true, - "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, - "bin": { - "why-is-node-running": "cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ws": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", - "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xml-name-validator": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "node_modules/yocto-queue": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", - "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zone.js": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.13.3.tgz", - "integrity": "sha512-MKPbmZie6fASC/ps4dkmIhaT5eonHkEt6eAy80K42tAm0G2W+AahLJjbfi6X9NPdciOE9GRFTTM8u2IiF6O3ww==", - "peer": true, - "dependencies": { - "tslib": "^2.3.0" - } - } - } -} diff --git a/projects/sunbird-quml-player-react/package.json b/projects/sunbird-quml-player-react/package.json deleted file mode 100644 index c741e5e7..00000000 --- a/projects/sunbird-quml-player-react/package.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "name": "@project-sunbird/sunbird-quml-player-web-component-react", - "private": true, - "version": "0.1.11", - "type": "module", - "scripts": { - "dev": "vite", - "build": "tsc -b && vite build && npm run build:wc", - "build:wc": "node scripts/build-wc.js", - "preview": "vite preview", - "test": "vitest", - "test:ui": "vitest --ui", - "test:coverage": "vitest --coverage", - "lint": "npm run type-check", - "type-check": "tsc --noEmit" - }, - "dependencies": { - "@dnd-kit/core": "^6.3.1", - "@dnd-kit/sortable": "^8.0.0", - "@dnd-kit/utilities": "^3.2.2", - "@project-sunbird/client-services": "^8.1.4", - "@project-sunbird/sb-styles": "0.0.16", - "@project-sunbird/sunbird-player-sdk-v9": "6.0.5", - "@project-sunbird/telemetry-sdk": "1.3.0", - "axios": "^1.7.2", - "bootstrap": "5.3.3", - "classnames": "2.3.2", - "jquery": "3.7.1", - "katex": "0.16.10", - "lodash-es": "4.17.21", - "react": "18.2.0", - "react-dnd": "16.0.1", - "react-dnd-html5-backend": "16.0.1", - "react-dom": "18.2.0", - "uuid": "9.0.1" - }, - "devDependencies": { - "@rollup/plugin-terser": "0.4.4", - "@testing-library/jest-dom": "6.1.0", - "@testing-library/react": "14.0.0", - "@types/node": "^20.11.0", - "@types/react": "^18.2.0", - "@types/react-dom": "^18.2.0", - "@vitejs/plugin-react": "4.0.0", - "fs-extra": "11.1.1", - "jsdom": "^22.1.0", - "rollup": "3.29.0", - "sass": "1.69.0", - "typescript": "^5.3.0", - "vite": "^4.4.0", - "vitest": "0.34.0" - } -} diff --git a/projects/sunbird-quml-player-react/public/favicon.svg b/projects/sunbird-quml-player-react/public/favicon.svg deleted file mode 100644 index 6893eb13..00000000 --- a/projects/sunbird-quml-player-react/public/favicon.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/projects/sunbird-quml-player-react/public/icons.svg b/projects/sunbird-quml-player-react/public/icons.svg deleted file mode 100644 index e9522193..00000000 --- a/projects/sunbird-quml-player-react/public/icons.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/projects/sunbird-quml-player-react/scripts/build-wc.js b/projects/sunbird-quml-player-react/scripts/build-wc.js deleted file mode 100644 index 6f7eee62..00000000 --- a/projects/sunbird-quml-player-react/scripts/build-wc.js +++ /dev/null @@ -1,126 +0,0 @@ -// Post-build packaging for the web component (Phase 8, spec §6.3.5 / §6.4). -// -// Written as ESM (package.json has "type": "module"); the spec's CommonJS -// `require(...)` form would fail under ESM. After `vite build` emits the IIFE -// bundle + single CSS file, this script: -// 1. Embeds the compiled player CSS into the bundle as a top-level -// `BUNDLED_CSS` constant (so the web component injects it into shadow DOM -// with no runtime fetch). -// 2. Copies the self-contained bundle + stylesheet into the package output. -// 3. Writes an example index.html. -// -// Output path: 'web-component/assets/quml-player' relative to this project (the -// literal spec path). This does NOT touch the repo-root Angular web-component -// package — see the deviation note in the Phase 8 report. - -import fs from 'fs-extra'; -import path from 'path'; - -const DIST = 'dist'; -const PKG_ROOT = 'web-component'; -const DEST = 'web-component/assets/quml-player'; -const BUNDLE = 'sunbird-quml-player.js'; - -// npm package name for the React web component. Deliberately DISTINCT from the -// Angular package (@project-sunbird/sunbird-quml-player-web-component) so the two -// coexist rather than one superseding the other. The version is taken from this -// project's package.json (single source of truth) — do not hardcode it here. -const WC_PACKAGE_NAME = '@project-sunbird/sunbird-quml-player-web-component-react'; - -const build = async () => { - try { - const bundlePath = path.join(DIST, BUNDLE); - if (!fs.existsSync(bundlePath)) { - throw new Error(`Missing ${bundlePath} — did 'vite build' run first?`); - } - - // 1. Locate the single compiled stylesheet (cssCodeSplit:false → one .css). - const cssFile = fs.readdirSync(DIST).find((f) => f.endsWith('.css')); - let bundleJs = fs.readFileSync(bundlePath, 'utf-8'); - const css = cssFile ? fs.readFileSync(path.join(DIST, cssFile), 'utf-8') : ''; - - if (cssFile) { - console.log(`[Build] Embedding ${cssFile} into the bundle...`); - // Escape backticks and ${ so the CSS is a safe template-literal value. - // BUNDLED_CSS is the FULL stylesheet — reset + component classes + fonts — - // injected into the shadow root, where it styles the player in isolation. - // This must stay complete; the player's own CSS depends on it. - const safeCss = css.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$\{/g, '\\${'); - const embedded = `var BUNDLED_CSS = \`${safeCss}\`;\n`; - bundleJs = embedded + bundleJs; - fs.writeFileSync(bundlePath, bundleJs); - } else { - console.warn('[Build] No CSS emitted; the bundle will ship without embedded styles.'); - } - - // 2. Copy the self-contained bundle. - console.log('[Build] Copying built files...'); - await fs.ensureDir(DEST); - await fs.copy(bundlePath, path.join(DEST, BUNDLE)); - if (cssFile) { - // The `./styles` export (styles.css) is loaded into the HOST document by - // some consumers. The player is fully styled via BUNDLED_CSS inside its - // shadow root (above), so this file must NOT carry the global reset (`*{}`) - // or the hashed component classes — those would leak into / mutate any host - // page that links it (a web component must never restyle its host). Ship - // ONLY document-level @font-face (KaTeX), which is safe to load anywhere. - const fontFaces = (css.match(/@font-face\s*\{[^}]*\}/g) || []).join('\n'); - await fs.writeFile(path.join(DEST, 'styles.css'), fontFaces); - console.log( - `[Build] Wrote host-safe styles.css (@font-face only): ${(fontFaces.length / 1024).toFixed(0)}KB`, - ); - } - - // 3. Example HTML. - console.log('[Build] Creating example HTML...'); - const exampleHtml = ` - - - - - QuML Player Example - - - - - - -`; - await fs.writeFile(path.join(DEST, 'index.html'), exampleHtml); - - // 4. Generate the package manifest so CI can `npm pack ./web-component` - // without a committed (and drift-prone) copy. Version is derived from the - // project package.json so it never diverges from the source of truth. - console.log('[Build] Writing package manifest...'); - const projectPkg = await fs.readJson('package.json'); - const manifest = { - name: WC_PACKAGE_NAME, - version: projectPkg.version, - description: 'React-based QUML player web component', - main: 'assets/quml-player/sunbird-quml-player.js', - exports: { - '.': './assets/quml-player/sunbird-quml-player.js', - './styles': './assets/quml-player/styles.css', - }, - files: ['assets/quml-player/'], - homepage: 'https://github.com/Sunbird-inQuiry/player#readme', - repository: { - type: 'git', - url: 'https://github.com/Sunbird-inQuiry/player.git', - }, - keywords: ['sunbird', 'quml', 'question', 'player', 'web-component', 'react'], - author: 'Sunbird', - license: 'MIT', - }; - await fs.writeJson(path.join(PKG_ROOT, 'package.json'), manifest, { spaces: 2 }); - - console.log('[Build] ✅ Web component built successfully!'); - console.log(`[Build] Output: ${DEST}/`); - console.log(`[Build] Package: ${WC_PACKAGE_NAME}@${projectPkg.version}`); - } catch (error) { - console.error('[Build] ❌ Error:', error); - process.exit(1); - } -}; - -build(); diff --git a/projects/sunbird-quml-player-react/src/App.css b/projects/sunbird-quml-player-react/src/App.css deleted file mode 100644 index f90339d8..00000000 --- a/projects/sunbird-quml-player-react/src/App.css +++ /dev/null @@ -1,184 +0,0 @@ -.counter { - font-size: 16px; - padding: 5px 10px; - border-radius: 5px; - color: var(--accent); - background: var(--accent-bg); - border: 2px solid transparent; - transition: border-color 0.3s; - margin-bottom: 24px; - - &:hover { - border-color: var(--accent-border); - } - &:focus-visible { - outline: 2px solid var(--accent); - outline-offset: 2px; - } -} - -.hero { - position: relative; - - .base, - .framework, - .vite { - inset-inline: 0; - margin: 0 auto; - } - - .base { - width: 170px; - position: relative; - z-index: 0; - } - - .framework, - .vite { - position: absolute; - } - - .framework { - z-index: 1; - top: 34px; - height: 28px; - transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg) - scale(1.4); - } - - .vite { - z-index: 0; - top: 107px; - height: 26px; - width: auto; - transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg) - scale(0.8); - } -} - -#center { - display: flex; - flex-direction: column; - gap: 25px; - place-content: center; - place-items: center; - flex-grow: 1; - - @media (max-width: 1024px) { - padding: 32px 20px 24px; - gap: 18px; - } -} - -#next-steps { - display: flex; - border-top: 1px solid var(--border); - text-align: left; - - & > div { - flex: 1 1 0; - padding: 32px; - @media (max-width: 1024px) { - padding: 24px 20px; - } - } - - .icon { - margin-bottom: 16px; - width: 22px; - height: 22px; - } - - @media (max-width: 1024px) { - flex-direction: column; - text-align: center; - } -} - -#docs { - border-right: 1px solid var(--border); - - @media (max-width: 1024px) { - border-right: none; - border-bottom: 1px solid var(--border); - } -} - -#next-steps ul { - list-style: none; - padding: 0; - display: flex; - gap: 8px; - margin: 32px 0 0; - - .logo { - height: 18px; - } - - a { - color: var(--text-h); - font-size: 16px; - border-radius: 6px; - background: var(--social-bg); - display: flex; - padding: 6px 12px; - align-items: center; - gap: 8px; - text-decoration: none; - transition: box-shadow 0.3s; - - &:hover { - box-shadow: var(--shadow); - } - .button-icon { - height: 18px; - width: 18px; - } - } - - @media (max-width: 1024px) { - margin-top: 20px; - flex-wrap: wrap; - justify-content: center; - - li { - flex: 1 1 calc(50% - 8px); - } - - a { - width: 100%; - justify-content: center; - box-sizing: border-box; - } - } -} - -#spacer { - height: 88px; - border-top: 1px solid var(--border); - @media (max-width: 1024px) { - height: 48px; - } -} - -.ticks { - position: relative; - width: 100%; - - &::before, - &::after { - content: ''; - position: absolute; - top: -4.5px; - border: 5px solid transparent; - } - - &::before { - left: 0; - border-left-color: var(--border); - } - &::after { - right: 0; - border-right-color: var(--border); - } -} diff --git a/projects/sunbird-quml-player-react/src/App.tsx b/projects/sunbird-quml-player-react/src/App.tsx deleted file mode 100644 index 522bfeed..00000000 --- a/projects/sunbird-quml-player-react/src/App.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { QumlProvider } from './context/QumlContext'; -import { MainPlayer } from './components/MainPlayer/MainPlayer'; -import { sampleConfig } from './dev/sample-data'; -import type { PlayerConfig } from './types'; - -/** - * DEV harness — mounts the real player so `npm run dev` shows a runnable UI. - * - * Two modes, chosen by the URL: - * - API mode: ?identifier=[&lang=en] - * Builds a config with NO embedded data → MainPlayer fetches the hierarchy - * + questions via the data service. `host` is left empty so requests are - * same-origin relative and go through the Vite proxy → localhost:9000. - * - Embedded mode (default): the bundled sample data (no network). - */ -function resolveConfig(): PlayerConfig { - const params = new URLSearchParams(window.location.search); - const identifier = params.get('identifier'); - - if (identifier) { - return { - // host is empty → API requests are same-origin relative and go through the - // Vite proxy → localhost:9000. - context: { uid: 'dev-user', sid: 'dev-session', channel: 'dev', host: '' }, - // Only set language when ?lang is present; otherwise let the language - // precedence (localStorage['app-language'] → 'en') apply. - config: { language: params.get('lang') ?? undefined }, - // API mode: only an identifier, no embedded sections. Online asset hosts - // come from each media[].baseUrl in the backend response (Angular parity). - data: { identifier }, - // maxAttempts is host/backend data (Angular parity: playerConfig.metadata), - // not a player UI setting. - metadata: { maxAttempts: 3 }, - }; - } - - return sampleConfig; -} - -function App() { - const playerConfig = resolveConfig(); - - return ( - - - - ); -} - -export default App; diff --git a/projects/sunbird-quml-player-react/src/assets/hero.png b/projects/sunbird-quml-player-react/src/assets/hero.png deleted file mode 100644 index 02251f4b956c55af2d76fd0788124d7eee2b45eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13057 zcmV+cGycqpP)V|)f$;Qooc7=_G zlYe)HToTQIc!$)^+J1M1y0*T%w!p~7%ux`!eRhO?c80XDxKQ*R^lUUMnA>6NT^?feoZ8xxvP32D&s-9ow zqjcM}eesrC)NeDmsf)*P7wJ|K!&xP%Zy4iI8lF)Tv2!reW)tCzg_1=PmOwd1SQfxa z8;58t!=z~Ba7CYlNWVG>he8aRPY|+-JmozNhn!#9i#77Aa_Edt$ijyCWL#=~I>~2X zZNrQ8I0=D+NWD4pq=7~(i zhfThMNw|G>g^y9pGzxX7ZSApl@tIxFcs{p#MX{Ax&XZT+cR#U+OWc@S)pkIuI}dzu zH?^Q=<(y&Vq-oxSLfc0Zmq81bjZWf}RnssBaD6}2g-XJHLcN_|*IOu>m|x$nbm(?E zyNy!Zp=RroS;?Vg*kmoJYBi!n5{_^@rA!)=t#a^;N$8GL!*DsQb}`yvEuX!G@||An znOfUZAevPrkV_qjl|<~3QRZzG&h@C9Y5z zqpNH4xqbF_InIPh)kX}Vn^5kyed|mOuq+2>M;v~KO37a#yrEn3XDqtOl=rc6_KZ!; zreo)DFVB4|>1Zd(bvMI%8uM;3!)YMYu&cG?(PE!B~y@3yKBMt|R zAf=I16tFwPsl)!jDqvYkLHaAQ+f@W1m6F5aZvwhm4JL z{_l)@b;)mDSzle2gyFP5-r1x-5X{G}ot%VyWP@vEW80!Q=f%RTfpg>B*TA^pyWYUQ z<=xPtz}WcZ!;rFl4m1D&FFHv?K~#9!?A%+fn=lXt;9!Fc#kQ;zk~gZFsH z8e5iu@c_pzX&qb8&Dum*oXwB+fm6l6gFfC|o*wgEiy6tw~&co z9Vd_4)P%wP-KwQW7|lN-znGK#?N+j24U=$982myIBM+vsiKsc*@4-rwJxuAaHKna6 zT3wi!C~a4ZKH03qU}_1bKyx0&$CaK7_%Z+Kl$)fF5^op zZApQF2TvDav!s|krTjw-8US6ep z%!VmX4luub+fseQz_D9ATJQ?iQQwD}TZz{-yo#l12a%+7bT@E(X-hyaVS-5vuXc#^ zx^w;L21;NphGVoj*{s3f4dme0y2LC=G1-7THd`#z?;tuC{^9k(dM{Rf2GOxg7Jzho z7nSZHl7?M9kdalX`)YgoKEfiae5+;$(OGeN1eqxrv!ZCVKyH>xiyNqfe8xzY8*7)H zQls8KMp)F4D>ED;idMOU^^WhVF@q>ZSmeB0y~qC~|DB648hr%Sh|*T(4q|w2l?m2+ zvBVw3@7+Mz?^Yc#+se6KM;a<=(W-I>k)$-qL2V*t}VaW`;?P4)WqI%maIDq8!oUcSYAD`}wWjkSyAVsnF65#2zQ zZ>(K*TlS(E#4y$4Zq+e^_&}d)q20hCe3!LfLYP%nQpLJ~gM6a1hJlz3)aS<9C9me| zAcmJ#>tOwBy{HoP0Sm1&_(E+S@6 zgBIFUoei8zJmdpiq8q5=OY7t@`)JWxn_&GvKVr=Zdb_pEL_j|=?f;WK^U9Q0efd#K z9q7SfJTl4pmA$jsZ5oK8@O9#!I3Cv-kL)<8SalSsp#dcpvJ}Nz#G6FC0%9|7Fi#8; zGDJXtj!&GljT3*HE@0EE>G8Se&d)*nkqe}-?`3vPl&UqK?xG z!3XJ4M-x`EuQjhBbu?ik-)rmIt=DF_N?TVMP)8Gjn)TZ2V%H|zENbeix}kOxd@0}Q z>)HuH6Ean!uS#~4g2Ne2WsMGel|h%j9*W_quQheG^JqmKhc*RYzp0wKlGjBq2VzY_ zgOv8WC1+%W=W)k)Yp_`8kfE=uiiwOZTXi8Uj9YGr$f@yJcJ;#&-Nq~sJ7anE(@;QN z=~br%7%7`isKStX|7!1?L(apl^QvPKlrHV4S+6tNVQ*R1iGdC~WMNE1$a+=rpQmcB z>wxiLIBvOnm;u*;9Y!kJdy(T4lk|8>JAm(&wEsFIF1$_*{>2ZNd$V6DS=SfrGxAv0 zzKe377JI`&o9Ljr+VnS*EwehA{f&{cKZF(6*MG5!p5MvrFA3ll{fmRG*L@6^cb;o^ z3Wm8c?Sc6$`>~VEWw(c$Y?nRO;2Q$=ulpqPtM^=1IZx;@xK0PgO7rKQ^WHVLwtgUT z%|JF{^f(VH)wLKQ%dYiu2RmchBdxL0-M?wxxul_z*{h6ZZ`>-k(vizs((vW8Lt6Z6 zY;Dt?@JWyN`O`f;&d1Mb?e%9oyRK1ql?EE5XB2(W)|D1~Rx35$H6@6)$F?)7V|zEO zI}fu0-0}8W5=6sg$fPnZ~7=tTudl?Ecb@pxbo)vni%gP-?hL|%*?62C;x6?@E`VRnJv z?fTb;k4x;TS7Cu-z%J}uy}e-pwpLQ17Q@4DC+FCdAmNKklG$`I_pyw7E{fYmw~{Fj zi?6KcVy=Wrel)EB_DWO|0CKmI|13!gBV?X`Ozp7x>?6jr`>Qz=^4ea35!$*f}) zS$i+x_k+@P2q1RFUH^ZTTk7=n?cjfR>hTq3l3SY~#w+I8SSutXGyhw;Ws~=zMQ%Vc z>$On~47Ut?P*_!TOQ&PFmLAyJieB2X4_Fd_!WxI-AY`q1Lc-oK?+qcOTzlQ?@~x@OT}*9jTVNfl@3rGvZpWI=eKg>T zZb@6YWz)J=IhP7CF|c?G62vMEG%#U}?#86$0jR4sG~i(jRd#jmn`7b(O#?N;3a;1t zhXLssmUwGhp79luw#(*V8WL0|8+E z6=YZ_O@er~$LrD_PYGc(kJgB=;yw#+Z3X6LDUZ(NcwN=B-hjdiHm!JFar%m{(5bEW z@@_VEtG$5;`EJZ|OkJ@l&G9n((w@uNFwmU%bG|s#TbcJJos!{e+bjCjrCq_}LcN!UFgKtgg7siV*7# z!}1whTRRi*-avJPu->C}Z8EiuK$#886+H_#_!btv+rsiBbv2jAJvJ+O0{#}y(%L3H zfjU-kq_-L@2XrL*ae{{qYJkD{@dw%*bkh2P&YS-0!Xt!PRz7KHV0+~j(t9W8lAVWR zt@B*DgURgEz4>WuN>o?_iKcw$?k{||Pg7{Q2o4|VmJ)mg?{VQJA<}zEr^YAAS zgGm5RT4T3p)U;yz-tfBO^kw8?IoG!IVmc+Z3m#}AOQ?5MRa>)OcU!$N^_+yK6ayn? zK>~WK0!#ysuj^oNLakm)Zvu+J)OSubX^kv!c*xgdIvs;kln!rgG4*uZ;w0mQQO4XD zO9P{GNdv!=cQ(CAL{S(%KtuV^zC&Q{%g)PoXnp^gn^>c*`E>$hLYg2HjnbVGtWLa{7zHdG1jT@B{|Dm16 z7K2(jsfG+m*Zxof)iXxu+!H5Mo-0$pkyV3VV4B@Qms46M zuBxGRV@HxU7Wwx-6CB zaU*HO<_qn$5GH>&@?nRy1{z zkik!sLfWQ)r#75)vVwCBU*r_)Q6mp?!j85{#Xqse)ApRdE$V0%I0*~e(_{)5H)`Mk z#rExC>yjhZxuL@|+#v4#<Axw$+VpV zuT;!2Vww$je$DpAW`$FX_Ab|Ip%$;&T$-lW8jS~B$>G}rd>eQG+$h9lQx4Mx0w={m zx9?T6VU`>sR}XClkAhHEShOUe8awiq zmizhL+}5UKs3}6~It7vBTig9dfQ2Q8coo+Miiaw7n~>4ybv2Ptt0^^=VqX(t*Yya9 zr`FxxFX8(v*H=+uJ#JJWIB2A(==HDYx~^zZ2nu?2`}|Wsa*f3h3ixc+U|FDtAG$Y! z*lc_7se5Oso-Cgqe0){{!8H4g$3<8!R<6JOurD;((({c$1(pwb>(#TT!sge@4>r2@ zVL7>U`0`nsWAYErezk4(Z!gMI2?UTo{J3Ajo(u4)KYIRd>BRcG4BoS3G0EXyEp@tw z%P7__?A^a>Q&AKL@ayDO9D*Qkc!NHnO9l}kpp_6hXbMppYL(X1L?njdFT|-h2<_$; zAtDZ!1Rf%|yb!qbWKd}%0b`LzBeyNy43|QO(&h2mxQLUL)|0%agVOW)6TV!&Ip^Ls z`PG2cygM8)IecQx=Fc+nqYRo4hS^^-nM_&-y8?EJXUczP=DIw(GkTJdpEdh<_STs{ z|A)4n1GKdE=Wu!!nYoZHcUQ4S&R;oDOKX2lrkdF(mK>hz<$Pp>igjOcvoRIjlN=W8 zu8Gx5(roqn8$>gEE5vy{GiGeW8Tq{vnf3hS-V=$tZkQuftUVuU8o6k&dn=Yg3)6MOIH>nlK^-2+C6BZITr~1@So?NvG#TwL)|~=1YXGMTLpS<)ziK_CSOabe z=cB#5)yz|@0i9dSo?*CX)}UP=s6)B+F@~Em(u@Q(I9J9i_V{LmMu8BfXYMh~*oPP+ z!3~xTv|(>|=n6ZOtT~C@V!z!w%18*8T2t6}U2S##rC)mekBql&VsBX;$~ByGE$oA9 z`0Wzq8p?R{4)$l*on;!cLa}Dh^Xe?owiQZt9nH1fxxh$pN9K%CtOw?u3>85L7rr!d zXs)l{TZ{xXP&U8exz?9cv~dNNibOmt*K4I$?RxqIBZ0(?Mg-9FS{*9Bc49Qc1`=sIF-rye`aNT1G@4NwXcnyc@+bw_mTsR>5< zF<2;X0QesG_pw|TonqVBhRtfqI>ty(SIu&VOXd0CrLlfp+;WH7HYjhqnu^oAY!9cB z=B6#R?Rfz9BP`dJ=@v_?70s3HxQPk+{6Y+lM85f2NF^00*^OcM0~?JOZfR9ZPYF+# zYSs}(_BUYV8{n@2a1hD^SV41bwmi2uztR;PeBgF1F-`9>`zoNss-@3LaF2sjl~>OaaVmp7PNp+UT`6@}gR%uzqHDVeEZ14{Yt?n%JeQm+t(1_u zSc}oj^{b;+rlS|ME%+LjzSI&xu0Bblxo$MJ-J$kJ?Qu_XUXh}*@*-x@ny|}wVM%Lg z3tNB`yvr*}N?ClGL;H2cglcvErIccU3(eP7>@~4nOIcI~-`P8tSQnx=jI&{9)!1}l z;gQ%_h>ZlPSV@o@Azq1R$C6ja5!^ZGh;YRhhxs58qJWo9@Bceac&yy(pET1hnn`~7@}2L0&dfPKYs$ih7m2}R!25!(hxqA(!UIw; zK4+~Jowy3=RNC6nE=ncU{LH5?*9@W24lacJlvCZXB$CYtE@>c+~H zkV=(5I&gb{xn2!~f&fs2NQgAL6`p|kyt6kpWk}iVlqIp(H;ig`{_U9yxs1jzu^ETM z7~)Rg8C-NueqTYP&U8l{DY=Y47cR zOR@U%$KQV{mkRF|4)z9Y^t3K`@p>duY&QLUFeh6VoV`a`$U@)(z!-N*5Cj<11$EZW&hJLX83TO{lJYP74rlDZQPkm@t<=U^I)x@|UnHHkdQlh?!ltZwl92rE;;^ zZuIappj4dhld1}kttYYV-j|KF1Kus zWBnzttD^00%LFK(wrwNragFub6xiV8QE2rm<`&fcR4SLFcdtLxVuN!Aal-g6dE4%k zARZ}|xeo;K{0yf7@9aua%2j5o)CPcIOc6uLHFJOcgtB5owlcNAwyAHc0QB0Dts?c@ zUemG~j_E&W7R%+x-IO4FJl8e&*2Blmp1S#RA|)geVrxvP)NHdYuxi~g&Etn?QdNK8ZDKZ?QFLU?zh30G|t9G>a_X4zk}Ygw<^$7K!GIn(Io$>(d4ODJQ2XSd%jpK zm7>ptl$a3GyB}5-%p4>Q*p#VL^B{yQMuFCM^#l#+N!Ne z5_PrJWB=@Iy+t)H`g1lX`{bm($KE5I?0c(JEYm#t{F}j!xtsbob0{xu@0TB_*>G7w0ICn zr#VoBktqHZ~XxhiKD*lcG|b;H*|Ny3P^8ceV`sfBRfrhwZ!T+MFZ!F1Bt{q$8d9i6o?~ zODj^POr}&ivSa^R^YFIq7o0giLBKCycH_aU`F6)O6JX%nPTwh~Q`eq6*0iE#Srj2^ z*_hN3%*b83zfafy60@Cp3{J({RlSaEn&E?mrxRNC9GQ7#+f=s! z0KBf-9Ny_v2VbE%aB|Di)5kNJ^t&C`4D(>t7zYUWUFtbxt+Oq=!@O7BU)}>d*R72o zFF)3jQD_lLe4is&xzyJYC1-c{8TX$RU>&>P$%)ufpez0XSAukmh!xcekg`s$c<>-q zI#zn^JU0zzF}V60)o$_gY}PQH>b2M9&8fRZa#OauglPb zeQ@pMm&=!vNgos4CluQjLMV!pfkmxK+35bi^k&=k>9h02?l+u+m0agG;(h2|Jslc-llvtEwn~*w3bx7qnvZACG<8}AGeaDVvcHbKd2>3G^ zSFPULUn-?Pmo^-_`mLZr??uNH`2=I&yajlrF{DtUxMy#Nu}z=3y7qbUA;5`)hibMR zhXL@@uKyV0-2&A@t@!xyrBnMJl&^o@Gx$&5_q6?D=ji5grd-~=?dlg;ur(_V0wjh! zA=JV^C1m+DDkOsgr<%O9ZQFg!0}pD(#PSz4Dr_EyS5$`)VIAv);4n-SFP~YtC7sH= z7&*MfpH;gd*FHbkmD#)hVxb6xjc9~`t?_{=JS+@ip_cTicXxG<=7m9& zPX+Z8IC*GSAXuGCrZDHgR$r%jyk-fctis2Kx4HvZ|B~8uC@o)m^>Hy-O!&TKA?$&n zkP2Xc54w~!=z2?^NafyL*L0V9cbYrugHBBUj`xVyZmGFR&kvk#>1J*Z~i zNTz}?IAdJ$gkqd2!Gw(%LzE!O5s4C7q4%T~e_P{+z=DNDKrG**p=U`d5yg^vp`;Zn zsU=8gd0a9s4s0FPJePWR9eH5=+O^Kks&kC-iblNqTh2&Pw*^(4384f+D8N|fewZu_ zg2ejQ)ov;ztz;NQl7yj;A`(!H!XQu_$sqY9h_IrH*}_%1{L&_YLDvO?%R5Z-t+ClW z_qERbL?HKUZ!nt+!E9S`uoh^5A|DaIHe*_gf1`E_Vq+}{&T@t$EGhMnRjJ4z2w_W8 zp+qjs7as22^&S3wY1?+}^j-I=RcCE>#|39)g(lU7v_8;?=qK(9D8-*pPdiy)P3lIblG`+?%ea| zYoD3dopYt!tKgFicfNmNi(EWE=E4hC6(r|PYtanqJlmt57YOVrr2^tfrG(eG9C##X zu&1t@%L$RIvpj!wUA z8i>Pqot#_+Cnp6L2XPcZy1ar|9MnY+7eNvK1E)@Tr#2KsXq1*>)uUCozT7L##ok?o zhA6ofP4E|b*9tAfG?uf$#}>TIR&1A!yslP8}i7w-EzW(x#9VEvx18k%Tn=-$VV zkOtUr0b2!w3t>h?#8AZl^Az*(6KCGlD;4j~yx};`#2gN1_gv=%7KVzecIRakN{f*4 zeaI>yH;-o4OGhvGTU)(quWI)-q?V*(sVesSMv|wMUQ3hLEt=lBB$KZ9TyHr>)f7o%) zPYeU<3P)*P10*7vE)nA5#{c=6-E-_>r_u4e3i!I2+UksELwDqwMeBZ9FSP$;^Ajro z_@M#_Ss$?ejoB@!wN|kbGKs(0zLo%0QpQXW#t;oC$B0MZYZ&Ej?8~fNhcCVvPo3vo zFn0WWZaPliF^8_}yzb`*f@yg0uWv6HgNI)xa=pO%Ck(C<=-60l#uD3(wXP~c7!NoX z0&^6=N`zcc90F#qt@=Rn@r!3(*1v(Tl{B!m?Mc7yIA+nEHpY{YWr$=)F7rhR1P}(v zt{YhY#;jsW6G>#xhP*B`OCk|Pf+NN;ju1rxa*HAgoGq*rvqw&xe~;t1JA31$s?GBb z*g7&@cbKo4n<`>)!UlIAgR6q&))B0KYU8r66GbFj?8Guw4E%&}Qi_lT003LtoIZei zwD~=XZmeo+yZ2Pq3KYCF-R&11^p= z@H%s+=G`}wrbJ{()Mh71#2SP3Zy3m>l1n?0N-N1Q;z6?oSxr-G(H5m4EO>~&;}VKi zfY}3w+9z>vp#d)hVuu`)vG_aaH%3b=WKMnSu&c31;<3O;bz2iD=w+o4#oBb36 z5ZCF*Gu?zjZIR0S>_%pHY2$k8D^n7Sz_K8tCDeXM+dO<#LSg%h6`~dnVG1N@T7v&e z%wEd1!k{^zfz_1BTW{!$!B%g)J^2b87!9Y>>100X1SgT7s0z$o>^lAA=Gp_cC1(h=*5Tmf8z&LGJJ>$|K^~s`z9*OWz5MFUr?>Bi?_PGBB)#psD5?>n+q{o_ zz7~ez&;t#h8l$jwGPCC&xq2YetXYQT+0F3j(`xmNGf8dj#an|p#I*pvI*kwW4iuB> z+q3_7xB8y;pLzHG-S%+UHQA zvqp;$kmGJY>lLsN4C~&TcvAS1SErTcwcw0r@wngk zShAUA1M9b#g}^pL-zH7Q#z^&j#r9F8BTVfkR&qF<=e35goTu7c|GN)0mokj4m0%~0 zXJ8j4Hc_l;HJ&uU*Iw`8d_EscJ``s0tk9mkKo^&#TYXm-EoAzTQObxa@^u~g2t#T) zJz|rE!I_?i4dCJC=B8(_pZ{YR>|V?0iCcnU;E@$239^x?SYCfNaMHN;CtHIS_zHN9 zTkQc1v@O35okiFtq5_u+5FkY55ap@pi)O?}x0D1c*qB0KpYR}>Ul+B0Vmr}Z@+%mJ|As}sis_=ROPbov@*2thpE&?!V#Qgu$snYvCZ zrkhmkMU+fSf-s8(L37fPr&M*jRs{{THb!aXQu|P9l_-vJhHvLzMGH zE?1U0H_+PmNABp9`|KzkGfrrZ%XvdGo6*<{d5m9~L7 z_^`M;X6xDo=m6LY6RfvJEvsTK1!u8d2HPx|$S}p;sRy!I zWL55Yxu~_B`OP@~(q6&W3#)~I&+MGL%GWR$#udC151^wsswhqlii;rP9jJpiI7o&Z zAb})=HY7?4HA|re3ns`%$)FuvKCFWjhb~?IE)F6dF2K5}poj-NK6Gf;hw$t3=1txY zoxQxZWrQU6K!%|~!m?~Bnw-6Rr!F3BZ{u5!LqnZTDON}Coj9^@&le)V!NYrVwS~B% zEL+>Sr@}qGwGvu|HrOo|gSt__ezN^&%~{*)a=rf7y1HujUcr`zZB<4#l@T#eN)si} z)lZA<{=tKx8E%c9>A(##6}_p+~EZpKsl5a4pj`E*;_-6`ysiv zffA!7=MT1vCz}-m4~tjVey1b2KSR4OEtLd-(_DdUqYZ74LaDkhH?KFh?%WAOP2WbX zp@zT+Dx|5_f%JQiAGvVw!oh+g3e50u!aPfMxdC=E)XB{F5IcEZhePIM- zph6Y`$Oy?JBL<8Ex(SqEhLeQ@XcrdA>a?rx+_~HLA;l14)WmmpH}_w?Pg#HBZs0eS zwypwAW?M-x+3AU-(GGWSJ=ngxUEcEZ5OsX(Qlt!MQ zn^(`S{GHkAv(8@D`EAfSYig%Cxv?z!{=w^F#y)5_d7FuKZH7qlR-#5B0bt806%D0I zT7VdVP_?q*%Rq8UR;JkD4i^RXowt+E%#V2U>TfDqzZSDZ+dR!a#T3I>-z_$q9@k|m zy5~A*m~&JWP@E7a=pc}4kVHTc4h&R;Li7d@f`|hKMLkbb^uhOakNr3&FLjlm~i5NBM< zFaYI{;cpiHCNRdE0dg*>qIm(_t?#$h=(SCw?h3rJV2*ER8{O4^3#=dO)KwklZkoqU zS8i5c%YL*y*4;FY#D=XmkQnYj%LH)?02~gSJH`Qp1XY64g>%c_K$xseI&|e)7vRoL zAqRba$G@%fSGA7X7hQk%_3NVOYVS+$leU_!&6*5uN)8#5ZBz_6ASCA;azYS-Rt@ki zg2NWz(=;t}SC(~Ibl63$5C8FPmhXqb^)5#jaJ~I{Ex3xZ!+2h8$}}h_g@Be>HZ;72 z6#y#>AY3^skuVKF#0WxFBQ()5d5_nWb?c6c>EeMM|Mh+*&wEpPyxHCq{R-Gdr-`hN zF=1sxl&mBoK+#qRLl9#CEN|Fg8>nbmsTg3a1;#M9enQ$RgWk}kp#-5wh=EF&1tl%mJln2V^8o%Qv(*=zEuO7y z=m*8?xpUn-*@h5Cl_3BK3joiGkyaScK+>|MWdMRWm@RT!Q1piAlv5hL@B6>3&GI8) zP!xBc6}ZNIpJLL%2a8Y!+(<=f%WX>_uWVxlga9!D*oYt$l0cxRDMvqfU;Kq_mLK5k z)dvqYcgLa_Lz?3HyeF)@$%$&6lI?r4I>6W#M*<)vq{?&Oqrx``d`mhpVPr> z#q078F6gw_X<=?KR>8%^t%@wbITvNMu!hKiTSkCTJkw>1!e*Y{%31#_yMf=LW7{RJ zYoC^w$6%3cBtVG5)x#{Hg6IVTh9XEcM{gQwXk!R^y95^f-hZ`d{aVa+xW1EO4wDV4 zB?JgD7*?qkvc|$nIykTvNl2x0j3Q!MXoLL^)~}d7jcYf(H8D~c+?$pKL(px>Z3`eb z04RzS6_AgFT6Pn#iZAg$Sl_j8#;6ShF%&(Fag#E2asU@@LaN;=b=Wf7sgPKhfzhBM zC@eFL8^MrnA*9&Khe*Ab@CC9*uyJGXyi(;y2>lQLJZt;ShtJi?3Yf_t`F+$hY!+Q2Ndsx=U+bjTiAy7djLji>7k%k`$9&--f<*BNA3Hy&ZrHH|4 zG5H&9cB?O#zI1_OOf0Ce%mDfQxdtp3vU%(iY6yji3iISS61XLv#z|!zI_sZqza@B+ zyu9st5-h+`H7QUKx9}3w@oU@EO}&cEzG?fu!!bLO->%zkcg;i9^j`S~=WKMnDi1f= P00000NkvXXu0mjft=yBf diff --git a/projects/sunbird-quml-player-react/src/assets/react.svg b/projects/sunbird-quml-player-react/src/assets/react.svg deleted file mode 100644 index 6c87de9b..00000000 --- a/projects/sunbird-quml-player-react/src/assets/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/projects/sunbird-quml-player-react/src/assets/vite.svg b/projects/sunbird-quml-player-react/src/assets/vite.svg deleted file mode 100644 index 5101b674..00000000 --- a/projects/sunbird-quml-player-react/src/assets/vite.svg +++ /dev/null @@ -1 +0,0 @@ -Vite diff --git a/projects/sunbird-quml-player-react/src/components/Alert/Alert.module.scss b/projects/sunbird-quml-player-react/src/components/Alert/Alert.module.scss deleted file mode 100644 index e9d33659..00000000 --- a/projects/sunbird-quml-player-react/src/components/Alert/Alert.module.scss +++ /dev/null @@ -1,94 +0,0 @@ -@use '../../styles/variables' as v; -@use '../../styles/mixins' as m; - -.alert { - padding: v.$space-4; - margin-bottom: v.$space-4; - border-left: 4px solid v.$gray-300; - background: v.$g100; - border-radius: v.$r-sm; - font-family: v.$ff-base; -} - -.correct { - border-color: v.$success; - background: v.$success-bg; -} - -.incorrect { - border-color: v.$danger; - background: v.$danger-bg; -} - -.partial { - border-color: v.$warning; - background: v.$warning-bg; -} - -.info { - border-color: v.$info; - background: v.$info-bg; -} - -.header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: v.$space-3; -} - -.title { - font-weight: v.$fw-semibold; - color: v.$g700; -} - -.closeBtn { - @include m.focus-ring; - - display: inline-flex; - align-items: center; - justify-content: center; - padding: v.$space-1; - background: none; - border: none; - border-radius: v.$r-sm; - color: v.$g400; - cursor: pointer; - transition: color v.$dur-fast v.$ease-out; - - &:hover { - color: v.$g700; - } -} - -.message { - margin: 0 0 v.$space-3; - color: v.$g700; - line-height: v.$lh-snug; -} - -.details { - padding: v.$space-3; - background: rgba(0, 0, 0, 0.03); - border-radius: v.$r-sm; - margin-bottom: v.$space-3; - font-size: v.$text-sm; - color: v.$g600; -} - -.actions { - display: flex; - gap: v.$space-3; -} - -.actionBtn { - @include m.button-base; - @include m.focus-ring; - - background: v.$dark; - color: v.$white; - - &:hover:not(:disabled) { - background: v.$g800; - } -} diff --git a/projects/sunbird-quml-player-react/src/components/Alert/Alert.test.tsx b/projects/sunbird-quml-player-react/src/components/Alert/Alert.test.tsx deleted file mode 100644 index a5196306..00000000 --- a/projects/sunbird-quml-player-react/src/components/Alert/Alert.test.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { describe, it, expect, vi } from 'vitest'; -import { render, screen, fireEvent } from '@testing-library/react'; -import type { ReactNode } from 'react'; -import { QumlProvider } from '../../context/QumlContext'; -import { Alert } from './Alert'; -import type { PlayerConfig } from '../../types'; - -const mockConfig: PlayerConfig = { context: {}, config: { language: 'en' } }; -const wrap = (ui: ReactNode) => - render({ui}); - -describe('Alert', () => { - it('renders the message with role="alert"', () => { - wrap(); - const alert = screen.getByRole('alert'); - expect(alert).toBeInTheDocument(); - expect(alert).toHaveTextContent('Well done'); - }); - - it('shows the correct title per type', () => { - wrap(); - expect(screen.getByText(/correct answer/i)).toBeInTheDocument(); - }); - - it.each(['correct', 'incorrect', 'partial', 'info'] as const)( - 'renders the %s variant', - (type) => { - wrap(); - expect(screen.getByRole('alert')).toBeInTheDocument(); - }, - ); - - it('fires onClose when the close button is clicked', () => { - const onClose = vi.fn(); - wrap(); - fireEvent.click(screen.getByRole('button', { name: /close/i })); - expect(onClose).toHaveBeenCalledTimes(1); - }); - - it('shows expected-answer details when provided', () => { - wrap(); - expect(screen.getByText(/expected answer/i)).toBeInTheDocument(); - expect(screen.getByText(/Paris/)).toBeInTheDocument(); - }); - - it('shows "View Solution" only when showSolution is true and fires its callback', () => { - const onShowSolution = vi.fn(); - const { rerender } = wrap(); - expect(screen.queryByRole('button', { name: /view solution/i })).not.toBeInTheDocument(); - - rerender( - - - , - ); - fireEvent.click(screen.getByRole('button', { name: /view solution/i })); - expect(onShowSolution).toHaveBeenCalledTimes(1); - }); -}); diff --git a/projects/sunbird-quml-player-react/src/components/Alert/Alert.tsx b/projects/sunbird-quml-player-react/src/components/Alert/Alert.tsx deleted file mode 100644 index 8941674d..00000000 --- a/projects/sunbird-quml-player-react/src/components/Alert/Alert.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { useQuml } from '../../context/useQuml'; -import { t } from '../../i18n/translations'; -import { CloseIcon } from '../icons'; -import styles from './Alert.module.scss'; - -/** - * Alert — inline dismissible feedback banner (per spec §3.3). - * - * Presentational: reads ONLY `state.language` from Context for translations; - * everything else is props + callbacks. No toast behavior (per design decision), - * no business logic, no scoring. - */ -type AlertType = 'correct' | 'incorrect' | 'partial' | 'info'; - -interface AlertProps { - type?: AlertType; - message?: string; - /** Extra detail line (e.g. the expected answer). */ - details?: string | null; - onClose?: () => void; - showSolution?: boolean; - onShowSolution?: () => void; -} - -export function Alert({ - type = 'info', - message = '', - details = null, - onClose, - showSolution = false, - onShowSolution, -}: AlertProps) { - const { state } = useQuml(); - const language = state.language; - - const typeLabel: Record = { - correct: t(language, 'CORRECT_ANSWER'), - incorrect: t(language, 'INCORRECT_ANSWER'), - partial: t(language, 'PARTIAL_SCORE'), - info: 'Info', - }; - - return ( -
-
- {typeLabel[type]} - -
- - {message &&

{message}

} - - {details && ( -
-

- {t(language, 'EXPECTED_ANSWER')}: {details} -

-
- )} - - {showSolution && ( -
- -
- )} -
- ); -} diff --git a/projects/sunbird-quml-player-react/src/components/Header/Header.module.scss b/projects/sunbird-quml-player-react/src/components/Header/Header.module.scss deleted file mode 100644 index 2f931fc1..00000000 --- a/projects/sunbird-quml-player-react/src/components/Header/Header.module.scss +++ /dev/null @@ -1,116 +0,0 @@ -@use '../../styles/variables' as v; -@use '../../styles/mixins' as m; - -.header { - position: sticky; - top: 0; - z-index: 100; - display: flex; - justify-content: space-between; - align-items: center; - gap: v.$space-4; - min-height: 54px; - padding: v.$space-2 v.$space-4; - background: v.$ivory; - border-bottom: 1px solid v.$gray-200; -} - -.left, -.center, -.right { - display: flex; - align-items: center; - gap: v.$space-3; -} - -// Mobile-only navigation menu toggle (spec §6.6); hidden ≥ 768px where the -// persistent sidebar is visible. -.menuBtn { - @include m.focus-ring; - - display: none; - align-items: center; - justify-content: center; - padding: v.$space-1; - border: none; - border-radius: v.$r-sm; - background: transparent; - color: v.$g600; - cursor: pointer; - - &:hover { - background: v.$g100; - color: v.$g900; - } - - @include m.mobile { - display: inline-flex; - } -} - -.counter { - font-family: v.$ff-base; - font-size: v.$text-sm; - font-weight: v.$fw-medium; - color: v.$g600; - font-variant-numeric: tabular-nums; - white-space: nowrap; -} - -.timer { - display: inline-flex; - align-items: center; - gap: v.$space-2; - padding: v.$space-1 v.$space-3; - border-radius: v.$r-sm; - background: v.$g100; - color: v.$g600; - font-family: v.$ff-base; - font-size: v.$text-xs; - font-weight: v.$fw-semibold; - font-variant-numeric: tabular-nums; - white-space: nowrap; - transition: background v.$dur-fast v.$ease-out, color v.$dur-fast v.$ease-out; -} - -.timerIcon { - display: block; -} - -// Low-time warning (≤ 60s): red + gentle pulse — visual fidelity to the design. -.timerLow { - background: v.$danger-bg; - color: v.$danger; - animation: header-timer-pulse 1s ease-in-out infinite; -} - -@keyframes header-timer-pulse { - 0%, - 100% { - opacity: 1; - } - 50% { - opacity: 0.7; - } -} - -.navBtn { - @include m.button-base; - @include m.focus-ring; - - background: transparent; - color: v.$g600; - border: 1.5px solid v.$gray-200; - - &:hover:not(:disabled) { - border-color: v.$g400; - color: v.$g900; - background: v.$cream-bg; - } -} - -.navLabel { - @include m.mobile { - display: none; - } -} diff --git a/projects/sunbird-quml-player-react/src/components/Header/Header.test.tsx b/projects/sunbird-quml-player-react/src/components/Header/Header.test.tsx deleted file mode 100644 index c9ad1d4e..00000000 --- a/projects/sunbird-quml-player-react/src/components/Header/Header.test.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { describe, it, expect, vi } from 'vitest'; -import { render, screen, fireEvent } from '@testing-library/react'; -import type { ReactNode } from 'react'; -import { QumlProvider } from '../../context/QumlContext'; -import { Header } from './Header'; -import type { PlayerConfig } from '../../types'; - -const mockConfig: PlayerConfig = { context: {}, config: { language: 'en' } }; - -const wrap = (ui: ReactNode) => - render({ui}); - -describe('Header', () => { - it('renders the question counter', () => { - wrap(
); - expect(screen.getByText(/Question 3 of 10/i)).toBeInTheDocument(); - }); - - it('shows the timer (mm:ss) when timeRemaining is provided', () => { - wrap(
); - expect(screen.getByText('1:05')).toBeInTheDocument(); - }); - - it('hides the timer when timeRemaining is null', () => { - wrap(
); - expect(screen.queryByRole('timer')).not.toBeInTheDocument(); - }); - - it('disables Previous on the first question', () => { - wrap(
); - expect(screen.getByRole('button', { name: /previous/i })).toBeDisabled(); - }); - - it('disables Next on the last question', () => { - wrap(
); - expect(screen.getByRole('button', { name: /next/i })).toBeDisabled(); - }); - - it('emits onPrevious / onNext via callbacks', () => { - const onPrevious = vi.fn(); - const onNext = vi.fn(); - wrap(
); - fireEvent.click(screen.getByRole('button', { name: /previous/i })); - fireEvent.click(screen.getByRole('button', { name: /next/i })); - expect(onPrevious).toHaveBeenCalledTimes(1); - expect(onNext).toHaveBeenCalledTimes(1); - }); - - it('does not render a bookmark control', () => { - wrap(
); - expect(screen.queryByRole('button', { name: /bookmark/i })).not.toBeInTheDocument(); - }); -}); diff --git a/projects/sunbird-quml-player-react/src/components/Header/Header.tsx b/projects/sunbird-quml-player-react/src/components/Header/Header.tsx deleted file mode 100644 index ca077aa9..00000000 --- a/projects/sunbird-quml-player-react/src/components/Header/Header.tsx +++ /dev/null @@ -1,106 +0,0 @@ -import { useQuml } from '../../context/useQuml'; -import { t } from '../../i18n/translations'; -import { PreviousIcon, NextIcon, TimerIcon, MenuIcon } from '../icons'; -import styles from './Header.module.scss'; - -/** - * Header — presentational top bar: question counter, optional timer, and - * previous/next navigation. - * - * Per spec §3.2 it reads ONLY `state.language` from Context (for translations); - * everything else arrives as typed props and intent is emitted via callbacks. - * No bookmark (sidebar is the navigation pattern), no NavBar, no business logic. - */ -interface HeaderProps { - questionNumber?: number; - totalQuestions?: number; - /** Seconds remaining; `null`/omitted hides the timer. */ - timeRemaining?: number | null; - onPrevious?: () => void; - onNext?: () => void; - isFirstQuestion?: boolean; - isLastQuestion?: boolean; - /** When provided, renders a mobile-only menu button (toggles the sections drawer, spec §6.6). */ - onMenuClick?: () => void; -} - -/** Local mm:ss formatter (per spec §3.2 — distinct from utils/time HH:MM:SS). */ -function formatTime(seconds: number): string { - const mins = Math.floor(seconds / 60); - const secs = seconds % 60; - return `${mins}:${String(secs).padStart(2, '0')}`; -} - -export function Header({ - questionNumber = 1, - totalQuestions = 10, - timeRemaining = null, - onPrevious, - onNext, - isFirstQuestion = false, - isLastQuestion = false, - onMenuClick, -}: HeaderProps) { - const { state } = useQuml(); - const language = state.language; - - const showTimer = timeRemaining != null; - const isTimeLow = showTimer && timeRemaining <= 60; - - return ( -
-
- {onMenuClick && ( - - )} - - {t(language, 'QUESTION')} {questionNumber} {t(language, 'OF')} {totalQuestions} - -
- -
- {showTimer && ( -
- - {formatTime(timeRemaining)} -
- )} -
- -
- - - -
-
- ); -} diff --git a/projects/sunbird-quml-player-react/src/components/Hint/Hint.module.scss b/projects/sunbird-quml-player-react/src/components/Hint/Hint.module.scss deleted file mode 100644 index d2a5b168..00000000 --- a/projects/sunbird-quml-player-react/src/components/Hint/Hint.module.scss +++ /dev/null @@ -1,56 +0,0 @@ -@use '../../styles/variables' as v; -@use '../../styles/mixins' as m; - -.hint { - display: flex; - flex-direction: column; - gap: v.$space-4; - margin-top: v.$space-8; - - @include m.short { - margin-top: v.$space-3; - } -} - -.actions { - display: flex; - flex-wrap: wrap; - gap: v.$space-3; -} - -.toggleBtn { - @include m.button-base; - @include m.focus-ring; - - background: transparent; - color: v.$brick-shade; - border: 1.5px solid v.$brick; - - &:hover:not(:disabled) { - background: v.$brick-lt; - } -} - -.panel { - padding: v.$space-5; - border-radius: v.$r-sm; - font-family: v.$ff-base; -} - -.hintPanel { - background: v.$sunflower; - color: v.$g800; -} - -.solutionPanel { - background: v.$success-bg; - color: v.$g800; -} - -.panelHeading { - margin: 0 0 v.$space-3; - font-size: v.$text-sm; - font-weight: v.$fw-semibold; - text-transform: uppercase; - letter-spacing: 0.04em; -} diff --git a/projects/sunbird-quml-player-react/src/components/Hint/Hint.test.tsx b/projects/sunbird-quml-player-react/src/components/Hint/Hint.test.tsx deleted file mode 100644 index 91e5436d..00000000 --- a/projects/sunbird-quml-player-react/src/components/Hint/Hint.test.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import { render, screen, fireEvent } from '@testing-library/react'; -import { Hint } from './Hint'; - -describe('Hint', () => { - it('renders nothing when there is no content', () => { - const { container } = render(); - expect(container).toBeEmptyDOMElement(); - }); - - it('shows the hint button when showHints is set and hints are supplied', () => { - render(Think about Mars.

' }]} showHints />); - const toggle = screen.getByRole('button', { name: /show hint/i }); - expect(toggle).toHaveAttribute('aria-expanded', 'false'); - fireEvent.click(toggle); - expect(screen.getByRole('button', { name: /hide hint/i })).toHaveAttribute( - 'aria-expanded', - 'true', - ); - }); - - it('hides the hint button when showHints is false, even with hint content', () => { - render(Think about Mars.

' }]} />); - expect(screen.queryByRole('button', { name: /show hint/i })).not.toBeInTheDocument(); - }); - - it('hides the View Solution button until the learner has interacted', () => { - render(Because iron oxide.

' }]} showSolutions />); - // canViewSolution defaults to false → no solution button yet. - expect(screen.queryByRole('button', { name: /view solution/i })).not.toBeInTheDocument(); - }); - - it('hides the View Solution button when showSolutions is false, even after interaction', () => { - render(Because iron oxide.

' }]} canViewSolution />); - // showSolutions defaults to false → button stays hidden despite interaction + content. - expect(screen.queryByRole('button', { name: /view solution/i })).not.toBeInTheDocument(); - }); - - it('shows the View Solution button once opted in and unlocked, and reveals the solution', () => { - render( - Because iron oxide.

' }]} canViewSolution showSolutions />, - ); - fireEvent.click(screen.getByRole('button', { name: /view solution/i })); - expect(screen.getByText(/^solution$/i)).toBeInTheDocument(); - }); - - it('falls back to the SA answer as the solution body when opted in and unlocked', () => { - render(); - fireEvent.click(screen.getByRole('button', { name: /view solution/i })); - expect(screen.getByText(/^solution$/i)).toBeInTheDocument(); - }); -}); diff --git a/projects/sunbird-quml-player-react/src/components/Hint/Hint.tsx b/projects/sunbird-quml-player-react/src/components/Hint/Hint.tsx deleted file mode 100644 index c6c70a3e..00000000 --- a/projects/sunbird-quml-player-react/src/components/Hint/Hint.tsx +++ /dev/null @@ -1,129 +0,0 @@ -import { useState } from 'react'; -import { t, readI18n } from '../../i18n/translations'; -import { QuestionBody } from '../QuestionBody/QuestionBody'; -import { HintIcon } from '../icons'; -import type { I18nValue } from '../../types'; -import type { MediaResolveContext } from '../../utils/media'; -import styles from './Hint.module.scss'; - -/** - * Hint + Solution reveal UI (spec §6.8). - * - * Pure UI over already-normalized question content. Visibility is gated by the - * section's showHints/showSolutions flags AND content presence (Angular parity — - * section-player.component.ts:241,244; alert...html:126-127): - * - "Show Hint" appears when `showHints` is true AND the backend supplied hints. - * - "View Solution" appears when `showSolutions` is true AND solution/answer - * content exists AND `canViewSolution` is true (learner has interacted). - * Absent flags are falsy, so the buttons stay hidden unless the creator opts in. - * No scoring, no Context mutation. HTML/KaTeX is rendered via QuestionBody. - */ -export interface HintProps { - hints?: unknown[]; - solutions?: unknown[]; - /** SA model answer (used as the solution body when no `solutions` are sent). */ - answer?: string | I18nValue; - /** Unlock the View Solution button — set once the learner has interacted. */ - canViewSolution?: boolean; - /** Section flag: creator opted in to showing hints. Absent → hidden. */ - showHints?: boolean; - /** Section flag: creator opted in to showing solutions. Absent → hidden. */ - showSolutions?: boolean; - language?: string; - /** Media + offline resolution inputs so solution/hint assets resolve like the stem. */ - mediaCtx?: MediaResolveContext; -} - -/** - * Extract renderable HTML from a QuML hint/solution array entry. - * The candidate may be a plain string or an I18nValue map (API form) — localize - * via readI18n so both offline and fetched content render. - */ -function extractHtml(entry: unknown, language: string): string { - if (typeof entry === 'string') return entry; - if (entry && typeof entry === 'object') { - const obj = entry as Record; - const candidate = obj.value ?? obj.body ?? obj.solution ?? obj.hint; - if (typeof candidate === 'string') return candidate; - if (candidate && typeof candidate === 'object') { - return readI18n(candidate as I18nValue, language); - } - } - return ''; -} - -export function Hint({ - hints = [], - solutions = [], - answer, - canViewSolution = false, - showHints: showHintsFlag = false, - showSolutions: showSolutionsFlag = false, - language = 'en', - mediaCtx, -}: HintProps) { - const [showHint, setShowHint] = useState(false); - const [showSolution, setShowSolution] = useState(false); - - const hintHtml = hints.map((h) => extractHtml(h, language)).filter(Boolean); - const solutionHtml = solutions.map((s) => extractHtml(s, language)).filter(Boolean); - const answerText = readI18n(answer, language); - - // Hint button: section opted in (showHints) AND the backend sent hint content. - const hasHints = showHintsFlag && hintHtml.length > 0; - // Solution button: section opted in (showSolutions) AND the learner has - // interacted (canViewSolution) AND there is solution/answer content to reveal. - const hasSolution = - showSolutionsFlag && canViewSolution && (solutionHtml.length > 0 || Boolean(answerText)); - - if (!hasHints && !hasSolution) return null; - - return ( -
-
- {hasHints && ( - - )} - {hasSolution && ( - - )} -
- - {showHint && hasHints && ( -
-

{t(language, 'HINT')}

- {hintHtml.map((html, i) => ( - - ))} -
- )} - - {showSolution && hasSolution && ( -
-

{t(language, 'SOLUTION')}

- {solutionHtml.map((html, i) => ( - - ))} - {solutionHtml.length === 0 && answerText && ( - - )} -
- )} -
- ); -} diff --git a/projects/sunbird-quml-player-react/src/components/ImageViewer/ImageViewer.tsx b/projects/sunbird-quml-player-react/src/components/ImageViewer/ImageViewer.tsx deleted file mode 100644 index 1b386922..00000000 --- a/projects/sunbird-quml-player-react/src/components/ImageViewer/ImageViewer.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import './image-viewer.css'; -import type { ImageZoomState } from './useImageZoom'; - -/** - * Full-screen image viewer overlay. - * Mirrors Angular section-player.component.html:143-153 (image-viewer overlay, - * close button, zoom-in/out) and applies the portrait/landscape/neutral class to - * the enlarged image, matching setImageZoom()'s #imageModal handling. - */ -interface ImageViewerProps { - state: ImageZoomState; - onClose: () => void; - onZoomIn: () => void; - onZoomOut: () => void; -} - -export function ImageViewer({ state, onClose, onZoomIn, onZoomOut }: ImageViewerProps) { - if (!state.open) return null; - - return ( -
- - -
- - ); -} diff --git a/projects/sunbird-quml-player-react/src/components/ImageViewer/image-viewer.css b/projects/sunbird-quml-player-react/src/components/ImageViewer/image-viewer.css deleted file mode 100644 index 197fb929..00000000 --- a/projects/sunbird-quml-player-react/src/components/ImageViewer/image-viewer.css +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Image viewer + magnify styles. - * Mirrors Angular section-player.component.scss (.image-viewer__*, .magnify-icon, - * .portrait/.landscape/.neutral). Global (not CSS-modules) because the magnify - * icon and its orientation classes are attached to DOM injected via - * dangerouslySetInnerHTML, which module-scoped class names cannot reach. - */ - -.image-viewer__overlay, -.image-viewer__container, -.image-viewer__close, -.image-viewer__zoom { - position: absolute; -} - -.image-viewer__overlay { - top: 0; - left: 0; - width: 100%; - height: 100%; - background: #fff; - z-index: 11111; -} - -.image-viewer__container { - background-color: #fff; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - z-index: 11111; - width: 80%; - height: 80%; - display: flex; - align-items: center; - justify-content: center; -} - -.image-viewer__img { - width: 100%; - height: 100%; - object-fit: contain; -} - -.image-viewer__container .portrait { - width: auto; - height: 100%; -} - -.image-viewer__container .neutral { - width: auto; - height: auto; -} - -.image-viewer__container .landscape { - width: 100%; - height: auto; -} - -.image-viewer__close { - top: 1rem; - right: 1rem; - text-align: center; - cursor: pointer; - z-index: 999999; - background: rgba(0, 0, 0, 0.5); - border-radius: 100%; - width: 3rem; - height: 3rem; - border: none; -} - -.image-viewer__close::after { - content: "\2715"; - color: #fff; - font-size: 2rem; -} - -.image-viewer__close:hover { - background: rgba(0, 0, 0, 1); -} - -.image-viewer__zoom { - bottom: 1rem; - right: 1rem; - width: 2.5rem; - border-radius: 0.5rem; - background: #fff; - display: flex; - flex-direction: column; - align-items: center; - overflow: hidden; - z-index: 99999; - border: 0.0625rem solid #ccc; -} - -.image-viewer__zoomin, -.image-viewer__zoomout { - text-align: center; - height: 2.5rem; - width: 2.5rem; - cursor: pointer; - font-size: 1.5rem; - line-height: 2.5rem; - background: none; - border: none; -} - -.image-viewer__zoomin:hover, -.image-viewer__zoomout:hover { - background-color: #f0f0f0; -} - -.image-viewer__zoomin { - border-bottom: 0.0625rem solid #e0e0e0; -} - -/* Magnify icon injected next to each data-asset-variable image. */ -.magnify-icon { - position: absolute; - right: 0; - bottom: 0; - width: 1.5rem; - height: 1.5rem; - border-top-left-radius: 0.5rem; - cursor: pointer; - background-color: #fff; -} - -.magnify-icon::after { - content: ""; - position: absolute; - bottom: 0.125rem; - right: 0.125rem; - z-index: 1; - width: 1rem; - height: 1rem; - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 37.166 37.166'%3E%3Cpath d='M35.829,32.045l-6.833-6.833c-0.513-0.513-1.167-0.788-1.836-0.853c2.06-2.567,3.298-5.819,3.298-9.359 c0-8.271-6.729-15-15-15c-8.271,0-15,6.729-15,15c0,8.271,6.729,15,15,15c3.121,0,6.021-0.96,8.424-2.598 c0.018,0.744,0.305,1.482,0.872,2.052l6.833,6.833c0.585,0.586,1.354,0.879,2.121,0.879s1.536-0.293,2.121-0.879 C37.001,35.116,37.001,33.217,35.829,32.045z M15.458,25c-5.514,0-10-4.484-10-10c0-5.514,4.486-10,10-10c5.514,0,10,4.486,10,10 C25.458,20.516,20.972,25,15.458,25z M22.334,15c0,1.104-0.896,2-2,2h-2.75v2.75c0,1.104-0.896,2-2,2s-2-0.896-2-2V17h-2.75 c-1.104,0-2-0.896-2-2s0.896-2,2-2h2.75v-2.75c0-1.104,0.896-2,2-2s2,0.896,2,2V13h2.75C21.438,13,22.334,13.895,22.334,15z' fill='%23333'/%3E%3C/svg%3E"); - background-size: cover; - background-repeat: no-repeat; - background-position: center; -} diff --git a/projects/sunbird-quml-player-react/src/components/ImageViewer/useImageZoom.ts b/projects/sunbird-quml-player-react/src/components/ImageViewer/useImageZoom.ts deleted file mode 100644 index 9cc4d46e..00000000 --- a/projects/sunbird-quml-player-react/src/components/ImageViewer/useImageZoom.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { useEffect, useState, useCallback } from 'react'; -import type { RefObject } from 'react'; -import './image-viewer.css'; - -/** - * Image zoom / click-to-enlarge, ported from the Angular web-component. - * - * Mirrors: - * - section-player.component.ts:setImageZoom() (magnify icon + open) - * - section-player.component.ts:setImageHeightWidthClass() (portrait/landscape) - * - section-player.component.ts:zoomIn/zoomOut/closeZoom() - * - * Angular queries the whole document after each slide change; here we scope the - * pass to a container ref and re-run on DOM mutations (covering late-rendered - * solution content), which reproduces the same runtime result. - */ - -export type Orientation = 'portrait' | 'landscape' | 'neutral'; - -export interface ImageZoomState { - open: boolean; - src: string; - orientation: Orientation; - /** Zoom percentage; starts at 100, +/-10 per step, min 100 (Angular parity). */ - zoom: number; -} - -const INITIAL: ImageZoomState = { open: false, src: '', orientation: 'neutral', zoom: 100 }; - -/** Portrait if taller than wide, landscape if wider, else neutral (Angular rule). */ -function orientationOf(img: HTMLImageElement): Orientation { - const h = img.naturalHeight || img.clientHeight; - const w = img.naturalWidth || img.clientWidth; - if (h > w) return 'portrait'; - if (h < w) return 'landscape'; - return 'neutral'; -} - -export function useImageZoom( - containerRef: RefObject, - deps: unknown[] = [], -) { - const [state, setState] = useState(INITIAL); - - const openViewer = useCallback((img: HTMLImageElement) => { - setState({ open: true, src: img.src, orientation: orientationOf(img), zoom: 100 }); - }, []); - - const close = useCallback(() => setState((s) => ({ ...s, open: false, zoom: 100 })), []); - const zoomIn = useCallback(() => setState((s) => ({ ...s, zoom: s.zoom + 10 })), []); - // Mirrors Angular zoomOut(): only steps down while above 100%. - const zoomOut = useCallback( - () => setState((s) => (s.zoom > 100 ? { ...s, zoom: s.zoom - 10 } : s)), - [], - ); - - useEffect(() => { - const root = containerRef.current; - if (!root) return; - - // Mirrors setImageZoom() + setImageHeightWidthClass(): decorate every - // data-asset-variable with an orientation class + a magnify icon. - const decorate = () => { - const images = root.querySelectorAll('img[data-asset-variable]'); - images.forEach((image) => { - if (image.dataset.zoomBound === 'true') return; - image.dataset.zoomBound = 'true'; - image.classList.add('option-image'); - - const applyOrientation = () => { - image.classList.remove('portrait', 'landscape', 'neutral'); - image.classList.add(orientationOf(image)); - }; - if (image.complete) applyOrientation(); - else image.addEventListener('load', applyOrientation, { once: true }); - - const icon = document.createElement('div'); - icon.className = 'magnify-icon'; - icon.onclick = (event) => { - event.stopPropagation(); - openViewer(image); - }; - if (image.parentNode) { - // Ensure the icon anchors to a positioned parent. - const parent = image.parentElement; - if (parent && getComputedStyle(parent).position === 'static') { - parent.style.position = 'relative'; - } - image.parentNode.insertBefore(icon, image.nextSibling); - } - }); - }; - - decorate(); - // Re-decorate when solution/hint content mounts later. - const observer = new MutationObserver(() => decorate()); - observer.observe(root, { childList: true, subtree: true }); - return () => observer.disconnect(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, deps); - - return { state, close, zoomIn, zoomOut }; -} diff --git a/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.embedded-render.test.tsx b/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.embedded-render.test.tsx deleted file mode 100644 index fd9c1082..00000000 --- a/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.embedded-render.test.tsx +++ /dev/null @@ -1,117 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import { render, screen, fireEvent } from '@testing-library/react'; -import { QumlProvider } from '../../context/QumlContext'; -import { MainPlayer } from './MainPlayer'; -import type { PlayerConfig } from '../../types'; - -// The real editor/portal contract: the WHOLE questionset with question content -// embedded in metadata.children (Section A: MCQ + SA; Section B: FTB + REO). -// This drives the full render path (no network) to prove questions actually paint. -const metadata = { - identifier: 'do_214609811633471488164', - name: 'Sample question set', - objectType: 'QuestionSetImage', - timeLimits: { questionSet: { max: 0, min: 0 } }, - children: [ - { - identifier: 'do_secA', - name: 'Section A', - objectType: 'QuestionSet', - index: 1, - children: [ - { - identifier: 'do_q1', - name: 'Q1', - objectType: 'Question', - primaryCategory: 'Multiple Choice Question', - qType: 'MCQ', - index: 1, - maxScore: 5, - body: '
Which is the capital of France?
', - interactions: { - response1: { - type: 'choice', - options: [ - { label: { en: 'New York' }, value: 0 }, - { label: { en: 'Paris' }, value: 1 }, - ], - }, - }, - responseDeclaration: { - response1: { cardinality: 'single', type: 'integer', correctResponse: { value: 1 } }, - }, - }, - { - identifier: 'do_q2', - name: 'Q2', - objectType: 'Question', - primaryCategory: 'Subjective Question', - qType: 'SA', - index: 2, - maxScore: 5, - body: 'When is Independence Day observed in India', - interactions: {}, - answer: '
15th August
', - }, - ], - }, - { - identifier: 'do_secB', - name: 'Section B', - objectType: 'QuestionSet', - index: 2, - children: [ - { - identifier: 'do_q3', - name: 'Q3', - objectType: 'Question', - primaryCategory: 'FTB Question', - qType: 'FTB', - index: 1, - maxScore: 1, - body: 'The tree is [[response1]]', - interactions: { response1: { type: 'text' } }, - responseProcessing: { template: 'MAP_RESPONSE' }, - responseDeclaration: { - response1: { - cardinality: 'single', - type: 'string', - correctResponse: { value: 'tall' }, - mapping: [{ value: 'tall', score: 1, caseSensitive: false }], - }, - }, - }, - ], - }, - ], -}; - -const cfg: PlayerConfig = { context: {}, config: { language: 'en' }, metadata, data: {} }; - -const renderPlayer = () => - render( - - - , - ); - -describe('MainPlayer — renders from embedded metadata (portal/editor contract)', () => { - it('shows the real assessment name on the overview (not the fallback)', () => { - renderPlayer(); - expect(screen.queryByText(/loading/i)).not.toBeInTheDocument(); - // Real name proves metadata was consumed (fallback would be "Assessment Overview"). - expect(screen.getByText('Sample question set')).toBeInTheDocument(); - expect(screen.getByRole('button', { name: /start assessment/i })).toBeInTheDocument(); - }); - - it('paints the first question stem + options after entering the assessment', () => { - renderPlayer(); - fireEvent.click(screen.getByRole('button', { name: /start assessment/i })); - fireEvent.click(screen.getByRole('button', { name: /start section/i })); - // The MCQ stem and both option labels actually reach the DOM. - expect(screen.getByText(/capital of France/i)).toBeInTheDocument(); - expect(screen.getByText('Paris')).toBeInTheDocument(); - expect(screen.getByText('New York')).toBeInTheDocument(); - expect(screen.getAllByRole('radio')).toHaveLength(2); - }); -}); diff --git a/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.max-attempts.test.tsx b/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.max-attempts.test.tsx deleted file mode 100644 index 5f292fe8..00000000 --- a/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.max-attempts.test.tsx +++ /dev/null @@ -1,147 +0,0 @@ -import { describe, it, expect, vi } from 'vitest'; -import { render, screen, fireEvent, within } from '@testing-library/react'; -import { QumlProvider } from '../../context/QumlContext'; -import { MainPlayer } from './MainPlayer'; -import type { PlayerConfig } from '../../types'; - -// Angular parity (main-player.component.ts:249,253,483-485) — maxAttempts is -// host/backend data under `playerConfig.metadata`, not `config`. -const baseData = { - showTimer: false, - sections: [ - { - identifier: 's1', - name: 'Section 1', - timeLimits: { questionSet: { max: 0, min: 0 } }, - children: [ - { - identifier: 'q1', - body: '

Q1

', - primaryCategory: 'Multiple Choice Question', - interactions: { response1: { options: [{ value: 0, label: 'Apple' }, { value: 1, label: 'Banana' }] } }, - responseDeclaration: { - response1: { cardinality: 'single', type: 'integer', correctResponse: { value: 0 } }, - }, - }, - ], - }, - ], -}; - -const enterAssessment = () => { - fireEvent.click(screen.getByRole('button', { name: /start assessment/i })); - fireEvent.click(screen.getByRole('button', { name: /start section/i })); -}; - -const submitAssessment = () => { - fireEvent.click(screen.getAllByRole('radio')[0]); // answer correctly - fireEvent.click(screen.getAllByRole('button', { name: /^submit$/i })[0]); - const dialog = screen.getByRole('dialog'); - fireEvent.click(within(dialog).getByRole('button', { name: /^submit$/i })); -}; - -describe('MainPlayer — max attempts (Angular parity)', () => { - it('hides Retake on Results once this attempt is the last one allowed', () => { - const cfg: PlayerConfig = { - context: {}, - config: { language: 'en' }, - metadata: { maxAttempts: 1 }, - data: baseData, - }; - render( - - - , - ); - enterAssessment(); - submitAssessment(); - expect(screen.getByRole('heading', { name: /your results/i })).toBeInTheDocument(); - expect(screen.queryByRole('button', { name: /retake/i })).not.toBeInTheDocument(); - }); - - it('keeps Retake when attempts remain', () => { - const cfg: PlayerConfig = { - context: {}, - config: { language: 'en' }, - metadata: { maxAttempts: 3 }, - data: baseData, - }; - render( - - - , - ); - enterAssessment(); - submitAssessment(); - expect(screen.getByRole('button', { name: /retake/i })).toBeInTheDocument(); - }); - - it('emits an exdata isLastAttempt event when the final attempt starts', () => { - const onPlayerEvent = vi.fn(); - const cfg: PlayerConfig = { - context: {}, - config: { language: 'en' }, - metadata: { maxAttempts: 1 }, - data: baseData, - }; - render( - - - , - ); - expect(onPlayerEvent).toHaveBeenCalledWith( - expect.objectContaining({ - eid: 'exdata', - edata: expect.objectContaining({ - currentattempt: 1, - isLastAttempt: true, - maxLimitExceeded: false, - }), - }), - ); - }); - - it('emits an exdata maxLimitExceeded event when the last attempt is submitted', () => { - const onPlayerEvent = vi.fn(); - const cfg: PlayerConfig = { - context: {}, - config: { language: 'en' }, - metadata: { maxAttempts: 1 }, - data: baseData, - }; - render( - - - , - ); - onPlayerEvent.mockClear(); - enterAssessment(); - submitAssessment(); - expect(onPlayerEvent).toHaveBeenCalledWith( - expect.objectContaining({ - eid: 'exdata', - edata: expect.objectContaining({ - currentattempt: 1, - isLastAttempt: false, - maxLimitExceeded: true, - }), - }), - ); - }); - - it('does not restrict Retake when maxAttempts is not sent (unlimited)', () => { - const cfg: PlayerConfig = { - context: {}, - config: { language: 'en' }, - data: baseData, - }; - render( - - - , - ); - enterAssessment(); - submitAssessment(); - expect(screen.getByRole('button', { name: /retake/i })).toBeInTheDocument(); - }); -}); diff --git a/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.metadata-config.test.tsx b/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.metadata-config.test.tsx deleted file mode 100644 index fc9375d8..00000000 --- a/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.metadata-config.test.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { describe, it, expect, vi } from 'vitest'; -import { render, screen, waitFor, act } from '@testing-library/react'; -import { QumlProvider } from '../../context/QumlContext'; -import { MainPlayer } from './MainPlayer'; -import type { PlayerConfig } from '../../types'; - -// The Sunbird editor/portal pass the questionset under `playerConfig.metadata` -// (Angular contract) with `data` empty. Mock the data service to assert the -// player fetches using the identifier taken from metadata. -const { loadQuestionSet } = vi.hoisted(() => ({ loadQuestionSet: vi.fn() })); -// These configs carry no embedded question content, so force the fetch path. -vi.mock('../../services/data-service', () => ({ - loadQuestionSet, - hasEmbeddedQuestions: () => false, - transformEmbeddedQuestionSet: () => [], -})); - -describe('MainPlayer — metadata config contract (editor/portal)', () => { - it('fetches by identifier from playerConfig.metadata when data is empty', async () => { - loadQuestionSet.mockResolvedValue({ - metadata: { name: 'questionset-t1' }, - sections: [], - }); - const cfg: PlayerConfig = { - context: {}, - config: { language: 'en' }, - metadata: { identifier: 'do_qs1', name: 'questionset-t1' }, - data: {}, - }; - - render( - - - , - ); - - await waitFor(() => - expect(loadQuestionSet).toHaveBeenCalledWith('do_qs1', expect.anything()), - ); - // The overview title reflects the fetched metadata name, not the fallback. - await waitFor(() => expect(screen.getByText('questionset-t1')).toBeInTheDocument()); - }); - - it('does not fetch when neither data nor metadata carries an identifier', async () => { - loadQuestionSet.mockClear(); - const cfg: PlayerConfig = { - context: {}, - config: { language: 'en' }, - metadata: {}, - data: {}, - }; - render( - - - , - ); - // Flush effects with a single microtask tick; the no-identifier path returns - // synchronously, so loadQuestionSet must not be called. - await act(async () => {}); - expect(loadQuestionSet).not.toHaveBeenCalled(); - }); - - it('does not fetch when the identifier is a non-string (guards against .../[object Object])', async () => { - loadQuestionSet.mockClear(); - const cfg: PlayerConfig = { - context: {}, - config: { language: 'en' }, - metadata: { identifier: { bad: true } as unknown as string }, - data: {}, - }; - render( - - - , - ); - await act(async () => {}); - expect(loadQuestionSet).not.toHaveBeenCalled(); - }); -}); diff --git a/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.module.scss b/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.module.scss deleted file mode 100644 index 69915483..00000000 --- a/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.module.scss +++ /dev/null @@ -1,108 +0,0 @@ -@use '../../styles/variables' as v; -@use '../../styles/mixins' as m; - -// app-shell (column) → app-body (row: sidebar + main), collapsing to a single -// column with a drawer < 768px (spec §6.6 / §6.11). -.appShell { - display: flex; - flex-direction: column; - height: 100%; - width: 100%; - max-width: 100%; - // Query container for the player's responsive rules (m.mobile / m.tablet). - // `inline-size` contains ONLY the inline (width) axis, so the height:100% - // chain — and the :host height:100% freeze fix — is untouched. Every - // responsive component is a descendant of this element, so they respond to - // the player's own available width instead of the browser viewport (needed - // for the editor's narrow mobile preview). - container-type: inline-size; - container-name: quml; - // Positioning context for the player's overlays. The overlays (submit modal, - // mobile sections drawer, feedback toast) are `position: absolute` and anchor - // to THIS box, so they stay within the player instead of covering the whole - // browser window when the player is embedded in a small frame (editor mobile - // preview). When the player fills the viewport (portal, real mobile, - // standalone) this box == the viewport, so it is visually identical to the - // previous `position: fixed` behavior. (container-type does not reliably - // establish a fixed-positioning containing block across browsers, so we rely - // on absolute positioning + this explicit relative anchor instead.) - position: relative; - overflow-x: hidden; // hard guard: nothing scrolls the shell sideways - // Overview / results / review render their screen directly in the shell (the - // assessment stage scrolls via its inner .main). When the host constrains the - // player height, those screens overflow and their bottom CTA (e.g. "Start - // Assessment") gets clipped — so allow the shell itself to scroll vertically. - // Harmless for the assessment stage: its content fills exactly 100% and scrolls - // internally, so the shell never overflows. - overflow-y: auto; - background: v.$cream-bg; - font-family: v.$ff-base; -} - -.appBody { - display: flex; - flex: 1; - min-height: 0; - overflow: hidden; // sidebar + main scroll independently (design .app-body) -} - -.sidebarSlot { - flex-shrink: 0; - - @include m.mobile { - display: none; - } -} - -.main { - display: flex; - flex-direction: column; - flex: 1; - min-width: 0; - min-height: 0; - overflow-x: hidden; - overflow-y: auto; -} - -.sectionStepsBar { - display: flex; - justify-content: center; - padding: v.$space-4 v.$space-6; - background: v.$ivory; - border-bottom: 1px solid v.$gray-200; - - @include m.mobile { - padding: v.$space-3 v.$space-4; - } -} - -.endPage { - max-width: 640px; - margin: 0 auto; - padding: v.$space-12 v.$space-6; - text-align: center; -} - -.title { - margin: 0 0 v.$space-2; - font-size: v.$text-2xl; - font-weight: v.$fw-bold; - color: v.$dark; -} - -.subtitle { - margin: 0 0 v.$space-8; - color: v.$g500; -} - -.status, -.error { - padding: v.$space-12; - text-align: center; - font-family: v.$ff-base; - color: v.$g600; -} - -.error { - color: v.$danger; -} diff --git a/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.portal-fetch.test.tsx b/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.portal-fetch.test.tsx deleted file mode 100644 index 6b87b25b..00000000 --- a/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.portal-fetch.test.tsx +++ /dev/null @@ -1,104 +0,0 @@ -import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; -import { render, screen, fireEvent, waitFor } from '@testing-library/react'; -import { QumlProvider } from '../../context/QumlContext'; -import { MainPlayer } from './MainPlayer'; -import type { PlayerConfig } from '../../types'; - -// Simulate the PORTAL end-to-end: it passes SHALLOW metadata (identifier only, -// from /content/v1/read) and sets the /portal gateway URLs. The player must -// fetch hierarchy (stubs) + list (bodies) from those URLs, merge, and render. -vi.mock('../../services/http-client', () => ({ httpGet: vi.fn(), httpPost: vi.fn() })); -import { httpGet, httpPost } from '../../services/http-client'; -const mockGet = httpGet as unknown as ReturnType; -const mockPost = httpPost as unknown as ReturnType; - -// /portal/questionset/v2/hierarchy → sections with STUB questions (no body). -const hierarchy = { - questionset: { - identifier: 'do_qs', - name: 'Sample question set', - objectType: 'QuestionSetImage', - children: [ - { - identifier: 'do_secA', - name: 'Section A', - objectType: 'QuestionSet', - index: 1, - children: [ - { identifier: 'do_q1', objectType: 'Question', qType: 'MCQ', primaryCategory: 'Multiple Choice Question', index: 1 }, - ], - }, - ], - }, -}; - -// /portal/question/v2/list → full question content (bodies + interactions). -const questions = [ - { - identifier: 'do_q1', - qType: 'MCQ', - primaryCategory: 'Multiple Choice Question', - maxScore: 5, - body: '
Which is the capital of France?
', - interactions: { - response1: { - type: 'choice', - options: [ - { label: { en: 'New York' }, value: 0 }, - { label: { en: 'Paris' }, value: 1 }, - ], - }, - }, - responseDeclaration: { - response1: { cardinality: 'single', type: 'integer', correctResponse: { value: 1 } }, - }, - }, -]; - -// Shallow metadata, exactly like the portal's content-read result. -const cfg: PlayerConfig = { - context: {}, - config: { language: 'en' }, - metadata: { identifier: 'do_qs', name: 'Sample question set' }, - data: {}, -}; - -describe('MainPlayer — full portal path (shallow metadata → /portal fetch → render)', () => { - beforeEach(() => { - mockGet.mockReset(); - mockPost.mockReset(); - (window as any).questionSetHierarchyUrl = '/portal/questionset/v2/hierarchy/'; - (window as any).questionListUrl = '/portal/question/v2/list'; - }); - afterEach(() => { - delete (window as any).questionSetHierarchyUrl; - delete (window as any).questionListUrl; - }); - - it('fetches from the /portal gateway URLs, merges, and renders the question', async () => { - mockGet.mockResolvedValue(hierarchy); - mockPost.mockResolvedValue({ questions }); - - render( - - - , - ); - - // Hierarchy fetched from the portal gateway route (not /learner). - await waitFor(() => - expect(mockGet).toHaveBeenCalledWith('/portal/questionset/v2/hierarchy/do_qs?mode=edit', expect.anything()), - ); - // Question list fetched from the portal gateway route (not /api or /action); - // a ?lang= suffix is appended from config.language. - expect(mockPost.mock.calls[0][0]).toContain('/portal/question/v2/list'); - - // Overview shows, then enter the assessment and confirm the question paints. - await waitFor(() => expect(screen.getByText('Sample question set')).toBeInTheDocument()); - fireEvent.click(screen.getByRole('button', { name: /start assessment/i })); - fireEvent.click(screen.getByRole('button', { name: /start section/i })); - expect(screen.getByText(/capital of France/i)).toBeInTheDocument(); - expect(screen.getByText('Paris')).toBeInTheDocument(); - expect(screen.getAllByRole('radio')).toHaveLength(2); - }); -}); diff --git a/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.preview-config.test.tsx b/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.preview-config.test.tsx deleted file mode 100644 index 37a27248..00000000 --- a/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.preview-config.test.tsx +++ /dev/null @@ -1,119 +0,0 @@ -import { describe, it, expect, vi } from 'vitest'; -import { render, screen, fireEvent, act } from '@testing-library/react'; -import { QumlProvider } from '../../context/QumlContext'; -import { MainPlayer } from './MainPlayer'; -import type { PlayerConfig } from '../../types'; - -// Embedded single-question config, mirroring what the editor's single-question -// preview sends. `showStartPage` / `requiresSubmit` live on the questionset -// metadata (here, alongside the embedded sections → metadata === data). -const buildConfig = (overrides: { - showStartPage?: string; - requiresSubmit?: string; - showSectionIntro?: boolean; -}): PlayerConfig => ({ - context: {}, - config: { - language: 'en', - showFeedback: true, - ...(overrides.showSectionIntro !== undefined - ? { showSectionIntro: overrides.showSectionIntro } - : {}), - }, - data: { - ...(overrides.showStartPage !== undefined ? { showStartPage: overrides.showStartPage } : {}), - ...(overrides.requiresSubmit !== undefined ? { requiresSubmit: overrides.requiresSubmit } : {}), - sections: [ - { - identifier: 's1', - name: 'Section 1', - timeLimits: { questionSet: { max: 0, min: 0 } }, - children: [ - { - identifier: 'q1', - body: '

Q1

', - primaryCategory: 'Multiple Choice Question', - interactions: { - response1: { options: [{ value: 0, label: 'Apple' }, { value: 1, label: 'Banana' }] }, - }, - responseDeclaration: { - response1: { cardinality: 'single', type: 'integer', correctResponse: { value: 0 } }, - }, - }, - ], - }, - ], - }, -}); - -const renderPlayer = (cfg: PlayerConfig) => - render( - - - , - ); - -describe('MainPlayer — preview parity (showStartPage / requiresSubmit)', () => { - it('showStartPage:"No" lands directly on the question (skips overview AND section intro — Angular parity)', () => { - // Section intros are enabled by default (no showSectionIntro), yet the entry - // still bypasses both the overview and the intro screen. - renderPlayer(buildConfig({ showStartPage: 'No' })); - expect(screen.queryByRole('button', { name: /start assessment/i })).not.toBeInTheDocument(); - expect(screen.queryByRole('button', { name: /start section/i })).not.toBeInTheDocument(); - // Straight into the first question. - expect(screen.getByText('Apple')).toBeInTheDocument(); - expect(screen.getByText(/Question 1 of 1/i)).toBeInTheDocument(); - }); - - it('normal content still shows the overview then the section intro (feature intact)', () => { - renderPlayer(buildConfig({})); // no showStartPage → default flow - // 1. Overview first. - const start = screen.getByRole('button', { name: /start assessment/i }); - expect(screen.queryByText('Apple')).not.toBeInTheDocument(); - // 2. Start → section intro (intros default on, NOT skipped for normal content). - fireEvent.click(start); - const begin = screen.getByRole('button', { name: /start section/i }); - // 3. Begin → the question. - fireEvent.click(begin); - expect(screen.getByText('Apple')).toBeInTheDocument(); - }); - - it('with showStartPage:"No", an explicit return to overview (Retake) shows it, not a stuck loader', () => { - vi.useFakeTimers(); - try { - renderPlayer(buildConfig({ showStartPage: 'No', requiresSubmit: 'No' })); - // Initial: skipped overview, landed on the question. - expect(screen.getByText('Apple')).toBeInTheDocument(); - // Submit (no confirmation) → results. - const submits = screen.getAllByRole('button', { name: /^submit$/i }); - fireEvent.click(submits[submits.length - 1]); - act(() => vi.advanceTimersByTime(1000)); - // Retake → returns to overview. The one-shot auto-start does NOT re-fire, - // so the overview must actually render (regression: was a stuck loader). - fireEvent.click(screen.getByRole('button', { name: /retake/i })); - expect(screen.getByRole('button', { name: /start assessment/i })).toBeInTheDocument(); - } finally { - vi.useRealTimers(); - } - }); - - it('requiresSubmit:"No" submits straight to results with no confirmation dialog', () => { - vi.useFakeTimers(); - try { - // Land directly on the question (showStartPage/showSectionIntro skipped) - // so we can exercise the submit path in isolation. - renderPlayer( - buildConfig({ requiresSubmit: 'No', showStartPage: 'No', showSectionIntro: false }), - ); - // On the only question; the bottom action is the final Submit. - const submits = screen.getAllByRole('button', { name: /^submit$/i }); - fireEvent.click(submits[submits.length - 1]); - act(() => vi.advanceTimersByTime(1000)); // feedback dwell then proceed - // No confirmation dialog — straight to the results screen. - expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); - expect(screen.getByRole('button', { name: /review all answers/i })).toBeInTheDocument(); - } finally { - vi.useRealTimers(); - } - }); -}); diff --git a/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.reorder-telemetry.test.tsx b/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.reorder-telemetry.test.tsx deleted file mode 100644 index e6b5ec1b..00000000 --- a/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.reorder-telemetry.test.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; -import { render, screen, fireEvent } from '@testing-library/react'; -import { QumlProvider } from '../../context/QumlContext'; -import { MainPlayer } from './MainPlayer'; -import { initializeTelemetry } from '../../services/telemetry-service'; -import type { PlayerConfig, TelemetryContext } from '../../types'; - -// Reproduces the real crash condition: a host telemetry SDK that has NO logEvent -// (portal/editor) — set BEFORE interacting. Then answer a reorder question (whose -// drag/tap/nudge fire onOptionSelected → telemetry) and assert nothing throws. -const metadata = { - identifier: 'do_qs', - name: 'QS', - objectType: 'QuestionSetImage', - children: [ - { - identifier: 'do_sec', - name: 'Section', - objectType: 'QuestionSet', - index: 1, - children: [ - { - identifier: 'do_reo', - name: 'Q', - objectType: 'Question', - primaryCategory: 'Reorder Question', - qType: 'REO', - index: 1, - maxScore: 1, - body: '
Reorder the sentence
', - interactions: { - response1: { - type: 'order', - options: [ - { value: 'A', label: 'Book' }, - { value: 'B', label: 'is' }, - { value: 'C', label: 'on' }, - ], - }, - }, - responseDeclaration: { - response1: { - cardinality: 'ordered', - type: 'string', - correctResponse: { value: ['A', 'B', 'C'] }, - }, - }, - }, - ], - }, - ], -}; - -const cfg: PlayerConfig = { context: {}, config: { language: 'en' }, metadata, data: {} }; - -describe('MainPlayer — reorder interaction with a logEvent-less telemetry SDK', () => { - beforeEach(() => { - // Host SDK exposes initialize but NOT logEvent — exactly the failing case. - (window as any).EkTelemetry = { initialize: vi.fn() }; - initializeTelemetry({} as TelemetryContext); - }); - afterEach(() => { - delete (window as any).EkTelemetry; - vi.restoreAllMocks(); - }); - - it('answering a reorder question does NOT throw (regression: Mp.logEvent is not a function)', () => { - render( - - - , - ); - fireEvent.click(screen.getByRole('button', { name: /start assessment/i })); - fireEvent.click(screen.getByRole('button', { name: /start section/i })); - - // The reorder question renders; tapping a bank word changes the answer, which - // fires onOptionSelected → handleQuestionAnswer → logOptionSelected/ - // logAnswerSubmitted → raiseInteractEvent/raiseAssessEvent → the SDK path. - // Before the fix this threw synchronously inside the click; now it must not. - expect(() => fireEvent.click(screen.getByText('Book'))).not.toThrow(); - expect(() => fireEvent.click(screen.getByText('is'))).not.toThrow(); - }); -}); diff --git a/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.test.tsx b/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.test.tsx deleted file mode 100644 index b0bfd09c..00000000 --- a/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.test.tsx +++ /dev/null @@ -1,176 +0,0 @@ -import { describe, it, expect, vi } from 'vitest'; -import { render, screen, fireEvent, within, act } from '@testing-library/react'; -import { QumlProvider } from '../../context/QumlContext'; -import { MainPlayer } from './MainPlayer'; -import type { PlayerConfig } from '../../types'; - -// Raw-ish embedded config (MainPlayer normalizes via the transformation service). -const cfg: PlayerConfig = { - context: {}, - config: { language: 'en', showFeedback: true }, - data: { - // Timer is opt-in (Angular parity): content must set showTimer for it to show. - showTimer: true, - sections: [ - { - identifier: 's1', - name: 'Section 1', - timeLimits: { questionSet: { max: 0, min: 0 } }, - children: [ - { - identifier: 'q1', - body: '

Q1

', - primaryCategory: 'Multiple Choice Question', - interactions: { response1: { options: [{ value: 0, label: 'Apple' }, { value: 1, label: 'Banana' }] } }, - responseDeclaration: { - response1: { cardinality: 'single', type: 'integer', correctResponse: { value: 0 } }, - }, - }, - ], - }, - ], - }, -}; - -const renderPlayer = () => - render( - - - , - ); - -/** Advance the Phase 6 flow: overview → sectionIntro → assessment. */ -const enterAssessment = () => { - fireEvent.click(screen.getByRole('button', { name: /start assessment/i })); - fireEvent.click(screen.getByRole('button', { name: /start section/i })); -}; - -describe('MainPlayer', () => { - it('shows the Assessment Overview first with a Start CTA', () => { - renderPlayer(); - expect(screen.queryByText(/loading/i)).not.toBeInTheDocument(); - expect(screen.getByRole('button', { name: /start assessment/i })).toBeInTheDocument(); - // Question chrome is not rendered until the assessment stage. - expect(screen.queryByText('Apple')).not.toBeInTheDocument(); - }); - - it('renders the section intro then the first question after Start/Begin', () => { - renderPlayer(); - enterAssessment(); - expect(screen.getByText('Apple')).toBeInTheDocument(); - expect(screen.getByText(/Question 1 of 1/i)).toBeInTheDocument(); - }); - - it('does not flash feedback on selection; proceeds (non-blocking) on Submit', () => { - vi.useFakeTimers(); - try { - renderPlayer(); - enterAssessment(); - // Selecting an option must NOT flash feedback mid-answer. - fireEvent.click(screen.getAllByRole('radio')[1]); // wrong option (value 1) - expect(screen.queryByRole('status')).not.toBeInTheDocument(); - // Section Submit shows feedback briefly, then proceeds even on a wrong - // answer (non-blocking) → the end-of-assessment confirm dialog opens. - const submits = screen.getAllByRole('button', { name: /^submit$/i }); - fireEvent.click(submits[submits.length - 1]); // section-level submit - act(() => vi.advanceTimersByTime(1000)); - expect(screen.getByRole('dialog')).toBeInTheDocument(); - } finally { - vi.useRealTimers(); - } - }); - - it('opens the submit dialog, then shows results on confirm', () => { - renderPlayer(); - enterAssessment(); - fireEvent.click(screen.getAllByRole('radio')[0]); // answer correctly - // Header "Submit" opens the confirmation dialog (Phase 7). - fireEvent.click(screen.getAllByRole('button', { name: /^submit$/i })[0]); - const dialog = screen.getByRole('dialog'); - expect(dialog).toBeInTheDocument(); - // Confirm inside the dialog → Results screen with the reused Scoreboard. - fireEvent.click(within(dialog).getByRole('button', { name: /^submit$/i })); - expect(screen.getByRole('region', { name: /quiz summary/i })).toBeInTheDocument(); - expect(screen.getByRole('heading', { name: /your results/i })).toBeInTheDocument(); - }); - - it('returns to overview on retake', () => { - renderPlayer(); - enterAssessment(); - fireEvent.click(screen.getAllByRole('button', { name: /^submit$/i })[0]); - const dialog = screen.getByRole('dialog'); - fireEvent.click(within(dialog).getByRole('button', { name: /^submit$/i })); - fireEvent.click(screen.getByRole('button', { name: /retake/i })); - expect(screen.getByRole('button', { name: /start assessment/i })).toBeInTheDocument(); - }); - - it('count-up timer runs from Start (including section intros) when there is no limit', () => { - vi.useFakeTimers(); - try { - renderPlayer(); // cfg has timeLimits max 0 → count-up mode - fireEvent.click(screen.getByRole('button', { name: /start assessment/i })); - // The clock runs through the section intro (switching sections doesn't pause it). - act(() => vi.advanceTimersByTime(3000)); - expect(screen.getByRole('timer')).toHaveTextContent('0:03'); - // …and keeps ticking inside the assessment. - fireEvent.click(screen.getByRole('button', { name: /start section/i })); - act(() => vi.advanceTimersByTime(2000)); - expect(screen.getByRole('timer')).toHaveTextContent('0:05'); - } finally { - vi.useRealTimers(); - } - }); - - it('countdown runs from Start (including section intros)', () => { - vi.useFakeTimers(); - try { - // 5:00 assessment limit (read from data.timeLimits.questionSet.max). - const timedCfg = { - ...cfg, - data: { ...(cfg.data as object), timeLimits: { questionSet: { max: 300, min: 0 } } }, - } as PlayerConfig; - render( - - - , - ); - fireEvent.click(screen.getByRole('button', { name: /start assessment/i })); - // The countdown ticks during the section intro too. - act(() => vi.advanceTimersByTime(3000)); - expect(screen.getByText('4:57')).toBeInTheDocument(); - fireEvent.click(screen.getByRole('button', { name: /start section/i })); - act(() => vi.advanceTimersByTime(2000)); - expect(screen.getByText('4:55')).toBeInTheDocument(); - } finally { - vi.useRealTimers(); - } - }); - - // Both the omitted case and an explicit `showTimer: false` must suppress the - // timer (Angular parity: header *ngIf="showTimer"), even with a time limit. - it.each([ - ['omitted', (() => { const { showTimer: _o, ...rest } = cfg.data as Record; return rest; })()], - ['explicit false', { ...(cfg.data as Record), showTimer: false }], - ])('shows NO timer when showTimer is %s, even with a time limit', (_label, data) => { - vi.useFakeTimers(); - try { - const noTimerCfg = { - ...cfg, - data: { ...data, timeLimits: { questionSet: { max: 300, min: 0 } } }, - } as PlayerConfig; - render( - - - , - ); - fireEvent.click(screen.getByRole('button', { name: /start assessment/i })); - act(() => vi.advanceTimersByTime(3000)); - expect(screen.queryByRole('timer')).not.toBeInTheDocument(); - fireEvent.click(screen.getByRole('button', { name: /start section/i })); - act(() => vi.advanceTimersByTime(2000)); - expect(screen.queryByRole('timer')).not.toBeInTheDocument(); - } finally { - vi.useRealTimers(); - } - }); -}); diff --git a/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.timer-showtimer-parity.test.tsx b/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.timer-showtimer-parity.test.tsx deleted file mode 100644 index 982b7877..00000000 --- a/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.timer-showtimer-parity.test.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import { describe, it, expect, vi } from 'vitest'; -import { render, screen, fireEvent, act, within } from '@testing-library/react'; -import { QumlProvider } from '../../context/QumlContext'; -import { MainPlayer } from './MainPlayer'; -import type { PlayerConfig } from '../../types'; - -// Angular parity (section-player.component.ts:232-235, main-player.component.ts -// :172,257,488-493) — `showTimer` only gates the LIVE widget's visibility; it -// has no bearing on whether the clock is tracked, whether a time limit is -// enforced, or whether the results screen can report duration. These configs -// all set `showTimer: false` (or omit it) while still exercising the clock. - -const mcq = (id: string) => ({ - identifier: id, - body: `

${id}

`, - primaryCategory: 'Multiple Choice Question', - interactions: { response1: { options: [{ value: 0, label: 'Apple' }, { value: 1, label: 'Banana' }] } }, - responseDeclaration: { - response1: { cardinality: 'single', type: 'integer', correctResponse: { value: 0 } }, - }, -}); - -const enterAssessment = () => { - fireEvent.click(screen.getByRole('button', { name: /start assessment/i })); - fireEvent.click(screen.getByRole('button', { name: /start section/i })); -}; - -describe('MainPlayer — showTimer/summaryType parity (Angular)', () => { - it('auto-submits at time-limit expiry even when showTimer is false (hidden limit is still enforced)', () => { - const cfg: PlayerConfig = { - context: {}, - config: { language: 'en' }, - data: { - showTimer: false, - timeLimits: { questionSet: { max: 2, min: 0 } }, - sections: [{ identifier: 's1', name: 'Section 1', children: [mcq('q1')] }], - }, - }; - vi.useFakeTimers(); - try { - render( - - - , - ); - enterAssessment(); - expect(screen.getByText('Apple')).toBeInTheDocument(); - // No visible countdown — showTimer is false. - expect(screen.queryByRole('timer')).not.toBeInTheDocument(); - // Past the 2s limit → auto-submit, no confirmation needed. - act(() => vi.advanceTimersByTime(2100)); - expect(screen.getByRole('heading', { name: /your results/i })).toBeInTheDocument(); - } finally { - vi.useRealTimers(); - } - }); - - it('reports duration on Results when showTimer is false and summaryType allows it', () => { - const cfg: PlayerConfig = { - context: {}, - config: { language: 'en' }, - data: { - showTimer: false, - summaryType: 'Score and Duration', - sections: [{ identifier: 's1', name: 'Section 1', children: [mcq('q1')] }], - }, - }; - vi.useFakeTimers(); - try { - render( - - - , - ); - enterAssessment(); - act(() => vi.advanceTimersByTime(3000)); // 3s elapsed, count-up mode (no time limit) - fireEvent.click(screen.getAllByRole('radio')[0]); - fireEvent.click(screen.getAllByRole('button', { name: /^submit$/i })[0]); - const dialog = screen.getByRole('dialog'); - fireEvent.click(within(dialog).getByRole('button', { name: /^submit$/i })); - expect(screen.getByRole('heading', { name: /your results/i })).toBeInTheDocument(); - expect(screen.getByText(/time taken/i)).toBeInTheDocument(); - } finally { - vi.useRealTimers(); - } - }); -}); diff --git a/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.tsx b/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.tsx deleted file mode 100644 index cfa695ec..00000000 --- a/projects/sunbird-quml-player-react/src/components/MainPlayer/MainPlayer.tsx +++ /dev/null @@ -1,668 +0,0 @@ -import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; -import type { ReactNode } from 'react'; -import { DndProvider } from 'react-dnd'; -import { HTML5Backend } from 'react-dnd-html5-backend'; -import { useQuml } from '../../context/useQuml'; -import { SectionPlayer } from '../SectionPlayer/SectionPlayer'; -import { StartPage } from '../StartPage/StartPage'; -import { SectionIntro } from '../SectionIntro/SectionIntro'; -import { Sidebar } from '../Sidebar/Sidebar'; -import { MobileSectionsDrawer } from '../MobileSectionsDrawer/MobileSectionsDrawer'; -import { PlayerHeader } from '../PlayerHeader/PlayerHeader'; -import { SubmitModal } from '../SubmitModal/SubmitModal'; -import { ResultsScreen } from '../ResultsScreen/ResultsScreen'; -import { ReviewScreen } from '../ReviewScreen/ReviewScreen'; -import { t, readI18n } from '../../i18n/translations'; -import { transformSection, transformQuestion } from '../../services/transformation-service'; -import { - loadQuestionSet, - hasEmbeddedQuestions, - transformEmbeddedQuestionSet, -} from '../../services/data-service'; -import { QumlApiError } from '../../types/api'; -import { calculateScore } from '../../registry/scoring-registry'; -import { isAnswered } from '../../utils/answered'; -import type { Question, Section, PlayerConfig, I18nValue } from '../../types'; -import styles from './MainPlayer.module.scss'; - -/** - * MainPlayer — top-level orchestrator + assessment shell (Phase 5 engine + - * Phase 6 experience). - * - * Owns the player FLOW state machine (local React state — NOT Context, per spec - * §6.0): overview → sectionIntro → assessment → submit. Context stays the single - * source of truth for runtime data (sections, indices, answers). Shell components - * are children here; they receive Context-derived data as props and emit jump - * intent that maps to setCurrentSection / setCurrentQuestion. Hosts the single - * application-level DndProvider. - * - * Phase 7 extends the flow with `results`/`review` stages and a transient - * `submitDialog`; Results/Review READ Context + the scoring-registry and never - * own runtime answers. - */ -interface MainPlayerProps { - playerConfig: PlayerConfig; - onPlayerEvent?: (event: unknown) => void; - /** Reserved — telemetry flows through useTelemetry; wired to the SDK in a later phase. */ - onTelemetryEvent?: (event: unknown) => void; -} - -type Stage = 'overview' | 'sectionIntro' | 'assessment' | 'results' | 'review'; - -export function MainPlayer({ playerConfig, onPlayerEvent }: MainPlayerProps) { - const { - state, - setPlayerConfig, - setSections, - setCurrentSection, - setCurrentQuestion, - setLoading, - setError, - clearError, - resetState, - setAttempt, - } = useQuml(); - const language = state.language; - - // Assessment-level metadata source for the overview. Embedded: playerConfig.data. - // Fetched: the raw questionset root returned by the data service. - const [metadata, setMetadata] = useState>({}); - - const [stage, setStage] = useState('overview'); - const [drawerOpen, setDrawerOpen] = useState(false); - // Transient submit-confirmation dialog (spec §7.0); overlays the assessment shell. - const [submitDialog, setSubmitDialog] = useState(false); - // Where Review opens to (set when entering review from results). - const [reviewStartIndex, setReviewStartIndex] = useState(0); - // Assessment-level countdown (owned by the shell, not Context). Null = no limit. - const [timeRemaining, setTimeRemaining] = useState(null); - // One-shot guard for the showStartPage:'No' auto-advance past the overview. - const autoStartedRef = useRef(false); - // True once the assessment has been entered at least once this attempt — the - // brand-click (onBrandClick) returns to Overview WITHOUT resetting progress - // or the clock, so the CTA there must read "Resume", not "Start" (Retake is - // the only path that clears this, since it's the only path that actually - // restarts from zero). - const [hasStarted, setHasStarted] = useState(false); - - // Section intros can be disabled via config (spec §6.0). - const sectionIntrosEnabled = - (playerConfig?.config as { showSectionIntro?: boolean } | undefined)?.showSectionIntro !== false; - - // Preview parity (Angular): the host can ask the player to skip the overview / - // start page and the submit-confirmation step. These arrive on the questionset - // metadata as 'Yes'/'No' strings. Absent → the full behaviour (show overview, - // confirm on submit), so existing content is unaffected. - // showStartPage:'No' → land straight in the assessment (see auto-start effect) - // requiresSubmit:'No' → Submit goes straight to results, no confirmation modal - const skipStartPage = metadata.showStartPage === 'No' || metadata.showStartPage === false; - const requiresSubmitConfirmation = - metadata.requiresSubmit !== 'No' && metadata.requiresSubmit !== false; - - // Angular parity (main-player.component.ts:249) — host/backend data under - // `playerConfig.metadata`, not the player's own `config` (UI-only settings). - // Read once here since it's needed beyond the overview (Retake gating below - // + the exdata event effect further down). - const maxAttempts = - (playerConfig?.metadata as { maxAttempts?: number } | undefined)?.maxAttempts ?? null; - // Angular parity (main-player.component.ts:253 `showReplay`) — once this - // attempt IS the last allowed one, Retake must not offer another. - const canRetake = maxAttempts == null || state.attemptNumber < maxAttempts; - - // Initialize config + normalized sections. - // - // Two data sources, decided by shape (never both): - // - EMBEDDED: playerConfig.data.sections is present → normalize inline (sync). - // - FETCHED: no embedded sections but an identifier → the data service - // fetches the hierarchy + questions and returns normalized sections. - // - // Extracted so Retake (spec §7.5) can re-initialize after resetState() — which - // returns initialState and therefore clears playerConfig/sections. - const initializeFromConfig = useCallback(async () => { - if (!playerConfig) return; - setPlayerConfig(playerConfig); - - // Angular parity (main-player.component.ts:250) — the host tracks attempts - // used across PAST sessions and passes the count back; this session's - // attempt number is one past that. Retake's own `setAttempt(nextAttempt)` - // (called right after this function) overrides this for the in-session - // case, so this only matters on a fresh mount. - const seedAttempt = (playerConfig.metadata as { currentAttempt?: number } | undefined) - ?.currentAttempt; - if (typeof seedAttempt === 'number') { - setAttempt(seedAttempt + 1); - } - - const data = (playerConfig.data as Record | undefined) ?? {}; - // Host-contract compatibility: the Sunbird editor/portal follow the Angular - // contract — they pass the questionset under `playerConfig.metadata` and leave - // `data` empty. Fall back to metadata so both config shapes load. - const meta = (playerConfig.metadata as Record | undefined) ?? {}; - // Guard with Array.isArray: a non-array `sections` (e.g. a string) would have - // a truthy `.length` and crash on `.map` in the embedded path below. - const sectionsCandidate = data.sections ?? meta.sections; - const rawSections = Array.isArray(sectionsCandidate) ? (sectionsCandidate as unknown[]) : []; - - // EMBEDDED path (unchanged behavior). - if (rawSections.length > 0) { - const sections = rawSections - .map((raw) => { - const normalized = transformSection(raw); - if (!normalized) return null; - const children = (((raw as { children?: unknown[] }).children ?? []) as unknown[]) - .map((q) => transformQuestion(q)) - .filter((q): q is Question => Boolean(q)); - return { ...normalized, children }; - }) - .filter((s): s is Section => Boolean(s)); - // Overview metadata comes from whichever source carried the sections. - setMetadata(data.sections ? data : meta); - setSections(sections); - return; - } - - // EMBEDDED-METADATA path: hosts (Sunbird editor/portal) pass the WHOLE - // questionset — with question content embedded in its hierarchy — as - // `metadata`. Render it directly, no network calls. This also avoids relying - // on the player's own API endpoints matching the host's proxy routing. - if (hasEmbeddedQuestions(meta)) { - const sections = transformEmbeddedQuestionSet(meta); - if (sections.length > 0) { - setMetadata(meta); - setSections(sections); - return; - } - } - - // FETCHED path — delegate ALL network + normalization to the data service. - // Require a real string id: a non-string (e.g. an object) would otherwise - // build a bad request URL like `.../[object Object]`. - const identifierCandidate = data.identifier ?? meta.identifier; - const identifier = typeof identifierCandidate === 'string' ? identifierCandidate : undefined; - if (!identifier) return; - // API base URL only — the content/asset base (config.baseUrl) is separate and - // used for image resolution, so it must NOT leak into API requests. - const baseUrl = (playerConfig.context?.host as string | undefined) ?? ''; - // API path prefix (host slug, e.g. the portal's `/portal`). This is the React - // stand-in for Angular's host-provided QuestionCursor choosing the URL. The - // portal passes it as `config.apiSlug` (its existing convention — see - // QumlEditorService `apiSlug: '/portal'`); `slug` is accepted as an alias. - // data-service falls back to `/api` when neither is supplied. - const cfg = playerConfig.config ?? {}; - const pathPrefix = - (typeof cfg.apiSlug === 'string' ? cfg.apiSlug : undefined) ?? - (typeof cfg.slug === 'string' ? cfg.slug : undefined); - - setLoading(true); - try { - const { metadata: qsMetadata, sections } = await loadQuestionSet(identifier, { - baseUrl, - language: playerConfig.config?.language, - pathPrefix, - }); - setMetadata(qsMetadata as Record); - setSections(sections); - setLoading(false); - } catch (err) { - const message = - err instanceof QumlApiError ? err.message : 'Failed to load the assessment.'; - setError(message); - } - }, [playerConfig, setPlayerConfig, setSections, setLoading, setError, setAttempt]); - - useEffect(() => { - initializeFromConfig(); - }, [initializeFromConfig]); - - const summary = useMemo(() => { - let correct = 0; - let incorrect = 0; - let partial = 0; - let skipped = 0; - let totalScore = 0; - let maxScore = 0; - for (const section of state.sections) { - for (const q of section.children) { - const max = q.maxScore ?? 1; - maxScore += max; - const answer = state.answers[q.identifier]; - if (!isAnswered(answer)) { - skipped += 1; - continue; - } - const score = calculateScore(q, answer, language); - totalScore += score * max; - if (score >= 1) correct += 1; - else if (score > 0) partial += 1; - else incorrect += 1; - } - } - return { correct, incorrect, partial, skipped, totalScore: Math.round(totalScore), maxScore }; - }, [state.sections, state.answers, language]); - - // Overview / details data, derived from Context + raw config (spec §6.1–§6.2). - const overview = useMemo(() => { - const data = metadata; - const totalQuestions = state.sections.reduce((n, s) => n + s.children.length, 0); - const maxScore = state.sections.reduce( - (n, s) => n + s.children.reduce((m, q) => m + (q.maxScore ?? 1), 0), - 0, - ); - const timeLimits = (data.timeLimits as { questionSet?: { max?: number } } | undefined) - ?.questionSet; - return { - title: readI18n(data.name as I18nValue | undefined, language) || t(language, 'ASSESSMENT_OVERVIEW'), - description: readI18n(data.description as I18nValue | undefined, language) || undefined, - instructions: data.instructions as string | undefined, - totalQuestions, - totalSections: state.sections.length, - timeLimit: Number(timeLimits?.max) || 0, - // Angular parity (main-player.component.ts:172 → header *ngIf="showTimer"): - // the timer is shown ONLY when the content opts in via `showTimer`. Absent / - // false → no timer at all; the count-up fallback also requires it. - showTimer: data.showTimer === true || data.showTimer === 'true', - // Angular parity (main-player.component.ts:488-524) — gates score/duration - // visibility on the results screen. 'Complete'→score as a fraction, - // 'Duration'→score hidden, 'Score'→duration hidden, 'Score and Duration'/ - // absent→both shown as plain values. - summaryType: data.summaryType as string | undefined, - maxScore, - // Absent (not sent by the backend) → unlimited attempts: null, distinct - // from an explicit 0/low maxAttempts, so StartPage can show "No Limit" - // instead of a fabricated default. - attemptsLeft: - maxAttempts == null ? null : Math.max(0, maxAttempts - (state.attemptNumber - 1)), - }; - }, [metadata, maxAttempts, state.sections, state.attemptNumber, language]); - - // Angular parity (main-player.component.ts:258,276-282,415-417 emitMaxAttemptEvents - // + replayContent) — tell the host when the CURRENT attempt is the last one - // allowed, or already past the limit (the host decides how to react, e.g. its - // own "no attempts left" messaging). Keyed on attemptNumber, so this covers - // BOTH Angular call sites (component init AND Retake) in one place — Retake - // changes attemptNumber, which re-fires this effect with the new value. - useEffect(() => { - if (maxAttempts == null) return; - const current = state.attemptNumber; - if (current < maxAttempts) return; - onPlayerEvent?.({ - eid: 'exdata', - edata: { - type: 'exdata', - currentattempt: current, - isLastAttempt: current === maxAttempts, - maxLimitExceeded: current > maxAttempts, - }, - }); - // onPlayerEvent identity isn't guaranteed stable across host re-renders; - // only the attempt boundary itself should re-trigger this. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [state.attemptNumber, maxAttempts]); - - // Stages where the exam clock runs: once started, it keeps ticking through - // section intros (switching sections doesn't stop the clock). It PAUSES on - // Start/Overview, Results and Review. - const isClockRunning = stage === 'assessment' || stage === 'sectionIntro'; - - // Shell countdown. Remaining time is derived from a fixed deadline timestamp - // rather than by decrementing per tick, so re-creating the interval at a - // stage boundary can't accumulate drift. - const deadlineRef = useRef(null); - useEffect(() => { - if (!isClockRunning || timeRemaining == null) { - deadlineRef.current = null; - return; - } - // Anchor the deadline from whatever time was left when the assessment - // (re)started; a paused-then-resumed clock continues from the frozen value. - deadlineRef.current = Date.now() + timeRemaining * 1000; - const id = setInterval(() => { - const remaining = Math.max(0, Math.ceil((deadlineRef.current! - Date.now()) / 1000)); - setTimeRemaining(remaining); - if (remaining <= 0) clearInterval(id); - }, 250); - return () => clearInterval(id); - // Re-anchor only when the clock starts/stops, NOT every tick. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isClockRunning]); - - // Count-up elapsed timer (Angular header showCountUp parity): when the - // assessment has NO time limit, this tracks time spent instead of a - // countdown. Same run/pause semantics as the countdown, anchored to a - // timestamp so it never drifts. - // - // Angular parity — NOT gated on `showTimer`: showTimer only controls whether - // the live widget is *visible* (main-player.component.ts:172, section-player - // .component.ts:58,235 — fed straight into the timer display component, - // nothing else). Duration tracking itself (main-player.component.ts:257 - // initialTime, :488-493 setDurationSpent) and time-limit enforcement - // (section-player.component.ts:232-233) both run unconditionally in - // Angular. Previously this effect also required `overview.showTimer`, so a - // hidden timer (showTimer:false/unset) meant elapsed time was never tracked - // at all — the results screen had nothing to show regardless of - // `summaryType`. The header's OWN display of this value is still gated on - // `showTimer` separately, further down — only the tracking moved. - const [timeElapsed, setTimeElapsed] = useState(0); - const elapsedAnchorRef = useRef(null); - useEffect(() => { - if (!isClockRunning || overview.timeLimit > 0) return; - elapsedAnchorRef.current = Date.now() - timeElapsed * 1000; - const id = setInterval(() => { - setTimeElapsed(Math.floor((Date.now() - elapsedAnchorRef.current!) / 1000)); - }, 250); - return () => clearInterval(id); - // Re-anchor only when the clock starts/stops; timeElapsed is read once as - // the resume point. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isClockRunning, overview.timeLimit]); - - // Time up → auto-submit straight to results (no confirmation dialog). - useEffect(() => { - if (timeRemaining === 0) { - setSubmitDialog(false); - setStage('results'); - } - }, [timeRemaining]); - - // Flattened question list across all sections, for review + counts. - const allQuestions = useMemo( - () => state.sections.flatMap((s) => s.children), - [state.sections], - ); - - // Per-section completion (every child answered) — drives the section step dots. - const completed = useMemo( - () => - state.sections.map((s) => - s.children.length > 0 && s.children.every((q) => isAnswered(state.answers[q.identifier])), - ), - [state.sections, state.answers], - ); - - // ── Flow transitions ─────────────────────────────────────────────────────── - const beginAssessmentTimer = () => { - // Angular parity — NOT gated on `showTimer` (see the count-up effect's - // comment above for the citations): a real `timeLimit` always counts down - // and enforces auto-submit-at-zero, whether or not the content shows the - // live widget. `showTimer` only gates the header's own display, below. - if (timeRemaining == null && overview.timeLimit > 0) { - setTimeRemaining(overview.timeLimit); - } - }; - - const handleStart = () => { - setCurrentSection(0); - setCurrentQuestion(0); - beginAssessmentTimer(); - setHasStarted(true); - setStage(sectionIntrosEnabled ? 'sectionIntro' : 'assessment'); - }; - - const handleBegin = () => { - setCurrentQuestion(0); - setStage('assessment'); - }; - - // Overview section card → jump straight into that section's intro. - const handleSectionSelectFromOverview = (index: number) => { - setCurrentSection(index); - setCurrentQuestion(0); - beginAssessmentTimer(); - setHasStarted(true); - setStage(sectionIntrosEnabled ? 'sectionIntro' : 'assessment'); - }; - - // Submit (header) → open the confirmation dialog (spec §7.1), unless the host - // opted out via requiresSubmit:'No' (then submit straight to results). - const handleSubmitAssessment = () => { - if (requiresSubmitConfirmation) setSubmitDialog(true); - else handleConfirmSubmit(); - }; - - const handleConfirmSubmit = () => { - setSubmitDialog(false); - setStage('results'); - onPlayerEvent?.({ type: 'quizEnd', summary }); - // Angular parity (main-player.component.ts:483-485 raiseEndEvent) — flag - // to the host that this attempt, now finished, was the last one allowed. - if (maxAttempts != null && state.attemptNumber >= maxAttempts) { - onPlayerEvent?.({ - eid: 'exdata', - edata: { - type: 'exdata', - currentattempt: state.attemptNumber, - isLastAttempt: false, - maxLimitExceeded: true, - }, - }); - } - }; - - const handleCancelSubmit = () => setSubmitDialog(false); - - const handleReviewAll = () => { - setReviewStartIndex(0); - setStage('review'); - }; - - // Retake (spec §7.5): clear answers via resetState(), re-initialize from the - // config prop (resetState wipes config/sections), bump the attempt, return to - // Overview, and reset the shell timer. - const handleRetake = () => { - const nextAttempt = state.attemptNumber + 1; - resetState(); - initializeFromConfig(); - setAttempt(nextAttempt); - setTimeRemaining(null); - setTimeElapsed(0); - setSubmitDialog(false); - setHasStarted(false); - setStage('overview'); - }; - - const handleSectionEnd = () => { - const nextIndex = state.currentSectionIndex + 1; - if (nextIndex < state.sections.length) { - setCurrentSection(nextIndex); - setCurrentQuestion(0); - setStage(sectionIntrosEnabled ? 'sectionIntro' : 'assessment'); - onPlayerEvent?.({ type: 'sectionEnd', sectionIndex: state.currentSectionIndex }); - } else if (requiresSubmitConfirmation) { - // End of the last section → confirm before submitting. - setSubmitDialog(true); - } else { - handleConfirmSubmit(); - } - }; - - const handleSectionJump = (index: number) => { - setCurrentSection(index); - setCurrentQuestion(0); - setStage('assessment'); - }; - - // showStartPage:'No' → auto-advance past the overview once sections are ready. - // Angular parity (section-player.component.ts:195,248): with showStartPage:'No' - // the player renders the FIRST QUESTION directly — no overview AND no section - // intro (the intro screen is a React-only addition). So land on 'assessment', - // not 'sectionIntro'. Later section-to-section intros are unaffected. - // One-shot (ref-guarded) so an explicit later return to overview (retake / - // brand click) is still respected. - useEffect(() => { - if (autoStartedRef.current || !skipStartPage) return; - if (stage !== 'overview' || state.sections.length === 0) return; - autoStartedRef.current = true; - setCurrentSection(0); - setCurrentQuestion(0); - beginAssessmentTimer(); - setHasStarted(true); - setStage('assessment'); - // Guarded by the ref; the setters/timer are stable enough here. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [skipStartPage, stage, state.sections.length]); - - if (!state.playerConfig || state.loading) { - return
{t(language, 'LOADING')}
; - } - if (state.error) { - // Retry: clear the error and re-run the fetch/normalize pipeline. - const handleRetry = () => { - clearError(); - initializeFromConfig(); - }; - return ( -
-

{state.error}

- -
- ); - } - - const currentSection = state.sections[state.currentSectionIndex]; - - // Global question counter (across all sections) for the shell header. - const priorQuestions = state.sections - .slice(0, state.currentSectionIndex) - .reduce((n, s) => n + s.children.length, 0); - const globalQuestionNumber = priorQuestions + state.currentQuestionIndex + 1; - - let content: ReactNode; - if (stage === 'overview' && skipStartPage && !autoStartedRef.current) { - // Initial auto-start still pending (effect above) — don't flash the overview - // we're skipping. Gated on the ref so that an EXPLICIT later return to - // overview (Retake / brand click) shows the real overview instead of a - // permanent loading screen (the one-shot effect won't re-fire). - content =
{t(language, 'LOADING')}
; - } else if (stage === 'overview') { - content = ( - - ); - } else if (stage === 'results') { - // Total time spent: countdown mode → limit minus what was left; count-up - // mode → the elapsed counter (both tick unconditionally once the - // assessment stage starts — Angular parity, see the count-up effect's - // comment above: NOT gated on `showTimer`, which only controls the live - // widget's visibility, not whether time is tracked). `summaryType:'Score'` - // hides duration on-screen — that gating lives in ResultsScreen, not here. - const timeTaken = - overview.timeLimit > 0 ? overview.timeLimit - (timeRemaining ?? overview.timeLimit) : timeElapsed; - content = ( - - ); - } else if (stage === 'review') { - content = ( - setStage('results')} - language={language} - /> - ); - } else { - // Persistent shell (spec §6.6/§6.12): header + sidebar wrap BOTH the section - // intro and the in-section player; only the main area swaps between them. - const mainArea = - stage === 'sectionIntro' && currentSection ? ( - setStage('overview')} - language={language} - /> - ) : ( - - ); - - // The header timer is gated by the content's `showTimer` flag (Angular parity). - // When enabled: countdown if a time limit exists, count-up elapsed otherwise. - // When disabled: both props are null, so PlayerHeader renders no timer at all. - content = ( - <> - setDrawerOpen(true)} - onBrandClick={() => setStage('overview')} - language={language} - /> - -
- - -
{mainArea}
- - setDrawerOpen(false)} - sections={state.sections} - currentSectionIndex={state.currentSectionIndex} - answers={state.answers} - onSectionJump={handleSectionJump} - language={language} - /> -
- - {submitDialog && ( - - )} - - ); - } - - return ( - -
{content}
-
- ); -} diff --git a/projects/sunbird-quml-player-react/src/components/MobileSectionsDrawer/MobileSectionsDrawer.module.scss b/projects/sunbird-quml-player-react/src/components/MobileSectionsDrawer/MobileSectionsDrawer.module.scss deleted file mode 100644 index e2b08f70..00000000 --- a/projects/sunbird-quml-player-react/src/components/MobileSectionsDrawer/MobileSectionsDrawer.module.scss +++ /dev/null @@ -1,93 +0,0 @@ -@use '../../styles/variables' as v; -@use '../../styles/mixins' as m; - -// Mobile sections navigator — bottom sheet (matches the design's `sheetUp`). -// `absolute` (anchored to MainPlayer's .appShell), not `fixed`, so the sheet -// stays within the player box when embedded in a small frame (editor preview). -// When the player fills the viewport (.appShell == viewport) it is identical to -// fixed. -.overlay { - position: absolute; - inset: 0; - z-index: 1000; - display: flex; - align-items: flex-end; // dock the sheet to the bottom edge - background: rgba(0, 0, 0, 0.4); -} - -.panel { - display: flex; - flex-direction: column; - width: 100%; - // `%` (not `vh`) so the sheet height tracks the player box, not the browser - // viewport: in a short embedded frame it can't grow taller than .appShell. - // The overlay is absolute inset:0 (== .appShell height), so 80% == 80% of the - // player; identical to `80vh` when the player fills the viewport. - max-height: 80%; - overflow-y: auto; - -webkit-overflow-scrolling: touch; - background: v.$ivory; - border-top-left-radius: v.$r-lg; - border-top-right-radius: v.$r-lg; - box-shadow: v.$shadow-lg; - animation: sheet-up v.$dur-base v.$ease-out; -} - -// Grab handle affordance (typical of bottom sheets). -.panel::before { - content: ''; - align-self: center; - width: 2.25rem; - height: 0.25rem; - margin: v.$space-3 0 0; - border-radius: v.$r-pill; - background: v.$gray-300; - flex-shrink: 0; -} - -@keyframes sheet-up { - from { - transform: translateY(100%); - } - to { - transform: translateY(0); - } -} - -.panelHeader { - position: sticky; - top: 0; - z-index: 1; - display: flex; - align-items: center; - justify-content: space-between; - padding: v.$space-4 v.$space-5; - background: v.$ivory; - border-bottom: 1px solid v.$gray-200; -} - -.panelTitle { - font-family: v.$ff-base; - font-size: v.$text-md; - font-weight: v.$fw-semibold; - color: v.$dark; -} - -.closeBtn { - @include m.focus-ring; - - display: inline-flex; - align-items: center; - justify-content: center; - padding: v.$space-1; - border: none; - border-radius: v.$r-sm; - background: transparent; - color: v.$g600; - cursor: pointer; - - &:hover { - background: v.$g100; - color: v.$g900; - } -} diff --git a/projects/sunbird-quml-player-react/src/components/MobileSectionsDrawer/MobileSectionsDrawer.test.tsx b/projects/sunbird-quml-player-react/src/components/MobileSectionsDrawer/MobileSectionsDrawer.test.tsx deleted file mode 100644 index 7d7525e8..00000000 --- a/projects/sunbird-quml-player-react/src/components/MobileSectionsDrawer/MobileSectionsDrawer.test.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { describe, it, expect, vi } from 'vitest'; -import { render, screen, fireEvent } from '@testing-library/react'; -import { MobileSectionsDrawer } from './MobileSectionsDrawer'; -import type { Section } from '../../types'; - -const sections: Section[] = [ - { - identifier: 's1', - name: 'Section One', - children: [ - { identifier: 'q1', body: '', primaryCategory: 'multiple choice question', maxScore: 1 }, - ], - timeLimits: { max: 0, min: 0 }, - allowSkip: true, - shuffle: false, - }, -]; - -const baseProps = { - sections, - currentSectionIndex: 0, - answers: {}, - onSectionJump: vi.fn(), -}; - -describe('MobileSectionsDrawer', () => { - it('renders nothing when closed', () => { - const { container } = render( - , - ); - expect(container).toBeEmptyDOMElement(); - }); - - it('renders a modal dialog when open', () => { - render(); - const dialog = screen.getByRole('dialog'); - expect(dialog).toHaveAttribute('aria-modal', 'true'); - }); - - it('closes on Escape', () => { - const onClose = vi.fn(); - render(); - fireEvent.keyDown(document, { key: 'Escape' }); - expect(onClose).toHaveBeenCalled(); - }); - - it('closes after a section jump', () => { - const onClose = vi.fn(); - const onSectionJump = vi.fn(); - render( - , - ); - fireEvent.click(screen.getByRole('button', { name: /Section One/i })); - expect(onSectionJump).toHaveBeenCalledWith(0); - expect(onClose).toHaveBeenCalled(); - }); -}); diff --git a/projects/sunbird-quml-player-react/src/components/MobileSectionsDrawer/MobileSectionsDrawer.tsx b/projects/sunbird-quml-player-react/src/components/MobileSectionsDrawer/MobileSectionsDrawer.tsx deleted file mode 100644 index 93da481e..00000000 --- a/projects/sunbird-quml-player-react/src/components/MobileSectionsDrawer/MobileSectionsDrawer.tsx +++ /dev/null @@ -1,117 +0,0 @@ -import { useEffect, useRef } from 'react'; -import { t } from '../../i18n/translations'; -import { Sidebar } from '../Sidebar/Sidebar'; -import { CloseIcon } from '../icons'; -import type { Section, AnswersMap } from '../../types'; -import styles from './MobileSectionsDrawer.module.scss'; - -/** - * MobileSectionsDrawer — slide-in navigator for < 768px (spec §6.6). - * - * Reuses Sidebar/QuestionPalette content. Accessibility (spec §6.10): - * focus trap while open, `Esc` closes, `aria-modal`, focus returns to the toggle. - * Pure presentational beyond the focus-management effect; no Context mutation. - */ -export interface MobileSectionsDrawerProps { - isOpen: boolean; - onClose: () => void; - sections: Section[]; - currentSectionIndex: number; - answers: AnswersMap; - onSectionJump: (sectionIndex: number) => void; - language?: string; -} - -export function MobileSectionsDrawer({ - isOpen, - onClose, - sections, - currentSectionIndex, - answers, - onSectionJump, - language = 'en', -}: MobileSectionsDrawerProps) { - const panelRef = useRef(null); - const previouslyFocused = useRef(null); - - // Focus management: trap focus inside the panel, restore on close. - useEffect(() => { - if (!isOpen) return; - - previouslyFocused.current = document.activeElement as HTMLElement | null; - const panel = panelRef.current; - const focusables = () => - Array.from( - panel?.querySelectorAll( - 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])', - ) ?? [], - ).filter((el) => !el.hasAttribute('disabled')); - - focusables()[0]?.focus(); - - const onKeyDown = (e: KeyboardEvent) => { - if (e.key === 'Escape') { - e.preventDefault(); - onClose(); - return; - } - if (e.key !== 'Tab') return; - const items = focusables(); - if (items.length === 0) return; - const first = items[0]; - const last = items[items.length - 1]; - if (e.shiftKey && document.activeElement === first) { - e.preventDefault(); - last.focus(); - } else if (!e.shiftKey && document.activeElement === last) { - e.preventDefault(); - first.focus(); - } - }; - - document.addEventListener('keydown', onKeyDown); - return () => { - document.removeEventListener('keydown', onKeyDown); - previouslyFocused.current?.focus?.(); - }; - }, [isOpen, onClose]); - - if (!isOpen) return null; - - return ( -
- {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */} -
e.stopPropagation()} - > -
- {t(language, 'NAVIGATION')} - -
- - { - onSectionJump(i); - onClose(); - }} - language={language} - /> -
-
- ); -} diff --git a/projects/sunbird-quml-player-react/src/components/PlayerHeader/PlayerHeader.module.scss b/projects/sunbird-quml-player-react/src/components/PlayerHeader/PlayerHeader.module.scss deleted file mode 100644 index a66f0c99..00000000 --- a/projects/sunbird-quml-player-react/src/components/PlayerHeader/PlayerHeader.module.scss +++ /dev/null @@ -1,320 +0,0 @@ -@use '../../styles/variables' as v; -@use '../../styles/mixins' as m; - -.header { - position: sticky; - top: 0; - z-index: 100; - display: flex; - align-items: center; - justify-content: space-between; - gap: v.$space-4; - height: v.$header-h; - padding: 0 v.$space-6; - background: v.$white; - border-bottom: 1px solid v.$gray-200; - - @include m.mobile { - padding: 0 v.$space-4; - } -} - -.left, -.right { - display: flex; - align-items: center; - gap: v.$space-4; - min-width: 0; - - @include m.mobile { - gap: v.$space-2; - } -} - -.left { - flex: 1 1 auto; - // No overflow:hidden here — it was clipping the brand badge. The brand NAME - // truncates itself (its own ellipsis) and is hidden on mobile anyway. -} - -.right { - flex-shrink: 0; -} - -.menuBtn { - @include m.focus-ring; - - display: none; - flex-shrink: 0; - align-items: center; - justify-content: center; - width: 2.5rem; - height: 2.5rem; - padding: v.$space-1; - border: 1.5px solid v.$gray-200; - border-radius: v.$r-sm; - background: v.$white; - color: v.$g700; - cursor: pointer; - - &:hover { - border-color: v.$g400; - color: v.$g900; - } - - // Visible on mobile (≤768px) where the sidebar is hidden — this is the entry - // point to the sections/palette bottom sheet. - @include m.mobile { - display: inline-flex; - } -} - -// ── Brand ──────────────────────────────────────────────────────────────────── -.brand { - @include m.focus-ring; - - display: inline-flex; - align-items: center; - gap: v.$space-3; - min-width: 0; - padding: v.$space-1; - border: none; - border-radius: v.$r-sm; - background: transparent; - cursor: pointer; - - &:hover .brandName { - color: v.$brick; - } -} - -.brandBadge { - flex-shrink: 0; -} - -.brandBadge { - display: flex; - align-items: center; - justify-content: center; - width: 2rem; - height: 2rem; - border-radius: v.$r-pill; - background: v.$brick; - color: v.$white; - font-size: v.$text-sm; - font-weight: v.$fw-bold; -} - -.brandName { - min-width: 0; - font-size: v.$text-md; - font-weight: v.$fw-bold; - color: v.$g900; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - - // On mobile the header is tight (timer + counter + Submit); drop the brand - // NAME but keep the badge as the home affordance, leaving room for the - // sections menu button. - @include m.mobile { - display: none; - } -} - -// ── Section steps ──────────────────────────────────────────────────────────── -.steps { - display: flex; - align-items: center; - gap: v.$space-2; - margin: 0 0 0 v.$space-3; - padding: 0 0 0 v.$space-4; - border-inline-start: 1px solid v.$gray-200; - list-style: none; - - // Hide the section-step rail on tablet and below — it competes for width - // with the brand + timer/counter/submit cluster. The sidebar/drawer still - // shows section progress. - @include m.tablet { - display: none; - } -} - -.step { - display: flex; - align-items: center; - - // Connector line between steps. - &:not(:first-child)::before { - content: ''; - width: v.$space-4; - height: 1.5px; - margin-inline-end: v.$space-2; - background: v.$gray-300; - } -} - -.stepDot { - display: flex; - align-items: center; - justify-content: center; - width: 1.75rem; - height: 1.75rem; - border-radius: v.$r-pill; - background: v.$g100; - color: v.$gray-400; - font-size: v.$text-xs; - font-weight: v.$fw-bold; -} - -.active .stepDot { - background: v.$brick; - color: v.$white; -} - -.completed .stepDot { - background: v.$success-bg; - color: v.$success; -} - -// ── Right cluster ──────────────────────────────────────────────────────────── -.timer { - display: inline-flex; - align-items: center; - gap: v.$space-2; - padding: v.$space-2 v.$space-3; - border-radius: v.$r-pill; - background: v.$g100; - color: v.$g700; - font-size: v.$text-sm; - font-weight: v.$fw-semibold; - font-variant-numeric: tabular-nums; - flex-shrink: 0; - - @include m.mobile { - padding: v.$space-1 v.$space-2; - } -} - -.timerLow { - background: v.$danger-bg; - color: v.$danger; -} - -.helpWrap { - position: relative; - display: flex; - - @include m.mobile { - display: none; - } -} - -.help { - display: flex; - align-items: center; - justify-content: center; - width: 1.75rem; - height: 1.75rem; - border-radius: v.$r-pill; - border: 1.5px solid v.$gray-300; - background: transparent; - color: v.$gray-500; - font-size: v.$text-sm; - font-weight: v.$fw-bold; - cursor: pointer; - - &:hover, - &[aria-expanded='true'] { - border-color: v.$brick; - color: v.$brick; - } -} - -.legendBackdrop { - position: fixed; - inset: 0; - z-index: 40; -} - -.legend { - position: absolute; - top: calc(100% + 0.5rem); - right: 0; - z-index: 41; - min-width: 13.5rem; - padding: v.$space-4; - background: v.$white; - border: 1px solid v.$gray-200; - border-radius: v.$r-md; - box-shadow: v.$shadow-lg; - display: flex; - flex-direction: column; - gap: v.$space-3; -} - -.legendTitle { - margin: 0; - font-size: v.$text-xs; - font-weight: v.$fw-bold; - text-transform: uppercase; - letter-spacing: 0.04em; - color: v.$g500; -} - -.legendItem { - display: flex; - align-items: center; - gap: v.$space-3; - font-size: v.$text-sm; - color: v.$g700; -} - -.legendDot { - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - width: 1.5rem; - height: 1.5rem; - border-radius: v.$r-pill; - background: v.$g100; - color: v.$gray-400; - font-size: v.$text-xs; - font-weight: v.$fw-bold; - - &.active { - background: v.$brick; - color: v.$white; - } - - &.completed { - background: v.$success-bg; - color: v.$success; - } -} - -.counter { - font-size: v.$text-sm; - font-weight: v.$fw-semibold; - color: v.$g700; - font-variant-numeric: tabular-nums; - white-space: nowrap; -} - -.submitBtn { - @include m.button-base; - @include m.focus-ring($color: v.$g700); - - flex-shrink: 0; - background: v.$dark; - color: v.$white; - - &:hover:not(:disabled) { - background: v.$g800; - } - - @include m.mobile { - padding: v.$space-2 v.$space-3; - } -} diff --git a/projects/sunbird-quml-player-react/src/components/PlayerHeader/PlayerHeader.test.tsx b/projects/sunbird-quml-player-react/src/components/PlayerHeader/PlayerHeader.test.tsx deleted file mode 100644 index 9909c9c3..00000000 --- a/projects/sunbird-quml-player-react/src/components/PlayerHeader/PlayerHeader.test.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { describe, it, expect, vi } from 'vitest'; -import { render, screen, fireEvent } from '@testing-library/react'; -import { PlayerHeader } from './PlayerHeader'; -import type { Section } from '../../types'; - -const mkSection = (id: string): Section => ({ - identifier: id, - name: id, - children: [], - timeLimits: { max: 0, min: 0 }, - allowSkip: true, - shuffle: false, -}); - -const baseProps = { - brand: 'Sunbird', - sections: [mkSection('a'), mkSection('b'), mkSection('c')], - currentSectionIndex: 0, - completed: [false, false, false], - questionNumber: 1, - totalQuestions: 9, - onSubmit: vi.fn(), -}; - -describe('PlayerHeader', () => { - it('renders brand, step indicators, counter and timer', () => { - render(); - expect(screen.getByText('Sunbird')).toBeInTheDocument(); - expect(screen.getByText('1/9')).toBeInTheDocument(); - expect(screen.getByText('14:49')).toBeInTheDocument(); // mm:ss of 889 - const steps = screen.getAllByRole('listitem'); - expect(steps[0]).toHaveAttribute('aria-current', 'step'); - }); - - it('hides the timer when no time remaining is given', () => { - render(); - expect(screen.queryByRole('timer')).not.toBeInTheDocument(); - }); - - it('emits onSubmit', () => { - const onSubmit = vi.fn(); - render(); - fireEvent.click(screen.getByRole('button', { name: /submit/i })); - expect(onSubmit).toHaveBeenCalledTimes(1); - }); - - it('emits onBrandClick when the brand is clicked', () => { - const onBrandClick = vi.fn(); - render(); - fireEvent.click(screen.getByRole('button', { name: /sunbird/i })); - expect(onBrandClick).toHaveBeenCalledTimes(1); - }); -}); diff --git a/projects/sunbird-quml-player-react/src/components/PlayerHeader/PlayerHeader.tsx b/projects/sunbird-quml-player-react/src/components/PlayerHeader/PlayerHeader.tsx deleted file mode 100644 index 0fbe40a6..00000000 --- a/projects/sunbird-quml-player-react/src/components/PlayerHeader/PlayerHeader.tsx +++ /dev/null @@ -1,166 +0,0 @@ -import { useState } from 'react'; -import { t, readI18n } from '../../i18n/translations'; -import { TimerIcon, MenuIcon } from '../icons'; -import type { Section } from '../../types'; -import styles from './PlayerHeader.module.scss'; - -/** - * PlayerHeader — persistent assessment shell header (Phase 6 design). - * - * Pure presentational: brand + section step indicators (left) and timer, help, - * global question counter, and Submit (right). All data is supplied by MainPlayer - * from Context; intent is emitted via callbacks. No Context mutation. - */ -export interface PlayerHeaderProps { - brand: string; - sections: Section[]; - currentSectionIndex: number; - completed: boolean[]; - /** Seconds remaining (countdown mode); null/omitted hides the countdown. */ - timeRemaining?: number | null; - /** - * Seconds elapsed (count-up mode — Angular header showCountUp parity, shown - * when there is no time limit). Ignored while a countdown is active. - */ - timeElapsed?: number | null; - questionNumber: number; - totalQuestions: number; - onSubmit: () => void; - onMenuClick?: () => void; - /** Click the brand to return to the overview / start page. */ - onBrandClick?: () => void; - language?: string; -} - -function formatMmSs(seconds: number): string { - const mins = Math.floor(seconds / 60); - const secs = seconds % 60; - return `${mins}:${String(secs).padStart(2, '0')}`; -} - -export function PlayerHeader({ - brand, - sections, - currentSectionIndex, - completed, - timeRemaining = null, - timeElapsed = null, - questionNumber, - totalQuestions, - onSubmit, - onMenuClick, - onBrandClick, - language = 'en', -}: PlayerHeaderProps) { - // Countdown takes precedence; count-up shows when there is no time limit. - const showCountdown = timeRemaining != null; - const showTimer = showCountdown || timeElapsed != null; - const isTimeLow = showCountdown && timeRemaining <= 60; - const [showLegend, setShowLegend] = useState(false); - - return ( -
-
- {onMenuClick && ( - - )} - - - -
    - {sections.map((section, index) => { - const status = - index === currentSectionIndex - ? 'active' - : completed[index] - ? 'completed' - : 'upcoming'; - return ( -
  1. - {String.fromCharCode(65 + index)} -
  2. - ); - })} -
-
- -
- {showTimer && ( -
- - - {formatMmSs(showCountdown ? timeRemaining! : timeElapsed!)} - -
- )} - -
- - - {showLegend && ( - <> -
setShowLegend(false)} /> -
-

{t(language, 'HELP_LEGEND_TITLE')}

-
- - {t(language, 'SECTION_CURRENT')} -
-
- - {t(language, 'SECTION_DONE')} -
-
- - {t(language, 'SECTION_UPCOMING')} -
-
- - )} -
- - - {questionNumber}/{totalQuestions} - - - -
-
- ); -} diff --git a/projects/sunbird-quml-player-react/src/components/ProgressIndicators/ProgressIndicators.module.scss b/projects/sunbird-quml-player-react/src/components/ProgressIndicators/ProgressIndicators.module.scss deleted file mode 100644 index d8714142..00000000 --- a/projects/sunbird-quml-player-react/src/components/ProgressIndicators/ProgressIndicators.module.scss +++ /dev/null @@ -1,90 +0,0 @@ -@use '../../styles/variables' as v; - -.progressBar { - display: flex; - flex-direction: column; - gap: v.$space-2; - font-family: v.$ff-base; -} - -.progressMeta { - display: flex; - justify-content: space-between; - align-items: baseline; -} - -.progressLabel { - font-size: v.$text-xs; - font-weight: v.$fw-semibold; - color: v.$g600; - text-transform: uppercase; - letter-spacing: 0.04em; -} - -.progressCount { - font-size: v.$text-xs; - font-weight: v.$fw-medium; - color: v.$g500; - font-variant-numeric: tabular-nums; -} - -.track { - width: 100%; - height: 0.5rem; - background: v.$gray-200; - border-radius: v.$r-pill; - overflow: hidden; -} - -.fill { - height: 100%; - background: v.$brick; - border-radius: v.$r-pill; - transition: width v.$dur-base v.$ease-out; -} - -.steps { - display: flex; - align-items: center; - gap: v.$space-2; - margin: 0; - padding: 0; - list-style: none; -} - -.step { - display: flex; -} - -.dot { - display: flex; - align-items: center; - justify-content: center; - width: 1.75rem; - height: 1.75rem; - border-radius: v.$r-pill; - border: 1.5px solid v.$gray-300; - background: v.$white; - color: v.$g500; - font-family: v.$ff-base; - font-size: v.$text-xs; - font-weight: v.$fw-semibold; - font-variant-numeric: tabular-nums; - transition: all v.$dur-fast v.$ease-out; -} - -.active .dot { - border-color: v.$brick; - background: v.$brick; - color: v.$white; -} - -.completed .dot { - border-color: v.$success; - background: v.$success-bg; - color: v.$success; -} - -.upcoming .dot { - opacity: 0.85; -} diff --git a/projects/sunbird-quml-player-react/src/components/ProgressIndicators/ProgressIndicators.test.tsx b/projects/sunbird-quml-player-react/src/components/ProgressIndicators/ProgressIndicators.test.tsx deleted file mode 100644 index 8a3aa5da..00000000 --- a/projects/sunbird-quml-player-react/src/components/ProgressIndicators/ProgressIndicators.test.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import { render, screen } from '@testing-library/react'; -import { ProgressBar, SectionSteps } from './ProgressIndicators'; -import type { Section } from '../../types'; - -const mkSection = (id: string): Section => ({ - identifier: id, - name: id, - children: [], - timeLimits: { max: 0, min: 0 }, - allowSkip: true, - shuffle: false, -}); - -describe('ProgressBar', () => { - it('exposes progressbar ARIA values', () => { - render(); - const bar = screen.getByRole('progressbar'); - expect(bar).toHaveAttribute('aria-valuenow', '3'); - expect(bar).toHaveAttribute('aria-valuemax', '10'); - expect(bar).toHaveAttribute('aria-valuemin', '0'); - }); -}); - -describe('SectionSteps', () => { - it('marks the active section with aria-current', () => { - const sections = [mkSection('a'), mkSection('b'), mkSection('c')]; - render( - , - ); - const items = screen.getAllByRole('listitem'); - expect(items[1]).toHaveAttribute('aria-current', 'step'); - expect(items[0]).not.toHaveAttribute('aria-current'); - }); -}); diff --git a/projects/sunbird-quml-player-react/src/components/ProgressIndicators/ProgressIndicators.tsx b/projects/sunbird-quml-player-react/src/components/ProgressIndicators/ProgressIndicators.tsx deleted file mode 100644 index 2a988db5..00000000 --- a/projects/sunbird-quml-player-react/src/components/ProgressIndicators/ProgressIndicators.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { t, readI18n } from '../../i18n/translations'; -import type { Section } from '../../types'; -import styles from './ProgressIndicators.module.scss'; - -/** - * Progress indicators (spec §6.5) — pure, derived entirely from Context props. - * Two exports: - * - ProgressBar: answered/total bar (role="progressbar"). - * - SectionSteps: active/completed/upcoming section dots. - */ - -export interface ProgressBarProps { - answered: number; - total: number; - language?: string; -} - -export function ProgressBar({ answered, total, language = 'en' }: ProgressBarProps) { - const pct = total > 0 ? Math.round((answered / total) * 100) : 0; - return ( -
-
- {t(language, 'PROGRESS')} - - {answered} {t(language, 'OF')} {total} - -
-
-
-
-
- ); -} - -export interface SectionStepsProps { - sections: Section[]; - currentSectionIndex: number; - completed: boolean[]; - language?: string; -} - -export function SectionSteps({ - sections, - currentSectionIndex, - completed, - language = 'en', -}: SectionStepsProps) { - return ( -
    - {sections.map((section, index) => { - const state = - index === currentSectionIndex - ? 'active' - : completed[index] - ? 'completed' - : 'upcoming'; - return ( -
  1. - -
  2. - ); - })} -
- ); -} diff --git a/projects/sunbird-quml-player-react/src/components/QuestionBody/QuestionBody.module.scss b/projects/sunbird-quml-player-react/src/components/QuestionBody/QuestionBody.module.scss deleted file mode 100644 index ac82b310..00000000 --- a/projects/sunbird-quml-player-react/src/components/QuestionBody/QuestionBody.module.scss +++ /dev/null @@ -1,67 +0,0 @@ -@use '../../styles/variables' as v; - -.body { - font-family: v.$ff-question; // Noto Serif — editorial question stem (design) - font-size: v.$text-base; - line-height: v.$lh-normal; - color: v.$g700; - word-wrap: break-word; - overflow-wrap: anywhere; // long URLs / unbroken strings never overflow - max-width: 100%; - - // Images in body - img { - max-width: 100%; - height: auto; - margin: v.$space-3 0; - border-radius: v.$r-sm; - } - - // Tables — scroll horizontally inside their own box rather than the page. - table { - display: block; - width: 100%; - max-width: 100%; - overflow-x: auto; - -webkit-overflow-scrolling: touch; - border-collapse: collapse; - margin: v.$space-3 0; - - td, - th { - border: 1px solid v.$gray-200; - padding: v.$space-2; - text-align: left; - } - } - - // KaTeX — wide display math scrolls inside its own box (no page overflow). - :global(.katex-display) { - max-width: 100%; - overflow-x: auto; - overflow-y: hidden; - padding-bottom: v.$space-1; - } - - :global(.math-block) { - max-width: 100%; - overflow-x: auto; - } - - // RTL support comes from dir="auto" on the container (direction resolved - // from the content itself); `start` alignment follows whichever direction - // the browser resolves, so tables align correctly in both scripts. - table { - td, - th { - text-align: start; - } - } - - // In an RTL UI (renderer wrapper sets dir="rtl") the body BLOCK aligns right - // like the rest of the mirrored layout — while dir="auto" above still keeps - // the CHARACTER order of English/math fallback content intact (1+1=?). - [dir='rtl'] & { - text-align: right; - } -} diff --git a/projects/sunbird-quml-player-react/src/components/QuestionBody/QuestionBody.test.tsx b/projects/sunbird-quml-player-react/src/components/QuestionBody/QuestionBody.test.tsx deleted file mode 100644 index c1a946a9..00000000 --- a/projects/sunbird-quml-player-react/src/components/QuestionBody/QuestionBody.test.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import { render } from '@testing-library/react'; -import { QuestionBody } from './QuestionBody'; - -describe('QuestionBody', () => { - it('renders plain HTML body', () => { - const { container } = render(What is 2+2?

' }} />); - expect(container.textContent).toContain('What is 2+2?'); - }); - - it('renders images from the body', () => { - const { container } = render(' }} />); - expect(container.querySelector('img')).toBeInTheDocument(); - }); - - it('renders tables from the body', () => { - const { container } = render( - cell' }} />, - ); - expect(container.querySelector('table')).toBeInTheDocument(); - expect(container.textContent).toContain('cell'); - }); - - it('uses dir="auto" so content direction follows the text (Arabic)', () => { - const { container } = render( - السلام عليكم

' }} language="ar" />, - ); - const root = container.firstElementChild; - // dir="auto" (not a forced rtl): Arabic content resolves RTL, while - // English/math fallback keeps its LTR character order (e.g. "1+1=?"). - expect(root).toHaveAttribute('dir', 'auto'); - expect(root).toHaveAttribute('lang', 'ar'); - }); - - it('uses dir="auto" and the given lang for non-Arabic', () => { - const { container } = render(Hello

' }} />); - const root = container.firstElementChild; - expect(root).toHaveAttribute('dir', 'auto'); - expect(root).toHaveAttribute('lang', 'en'); - }); - - it('renders KaTeX math from .math elements', () => { - const { container } = render( - x^2' }} />, - ); - // KaTeX replaces the element content with .katex markup - expect(container.querySelector('.katex')).toBeInTheDocument(); - }); - - it('does not crash on empty body', () => { - const { container } = render(); - expect(container.firstElementChild).toBeInTheDocument(); - }); -}); diff --git a/projects/sunbird-quml-player-react/src/components/QuestionBody/QuestionBody.tsx b/projects/sunbird-quml-player-react/src/components/QuestionBody/QuestionBody.tsx deleted file mode 100644 index 5ddc4394..00000000 --- a/projects/sunbird-quml-player-react/src/components/QuestionBody/QuestionBody.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import { useEffect, useRef } from 'react'; -import katex from 'katex'; -import 'katex/dist/katex.min.css'; -import { resolveMediaHtml } from '../../utils/media'; -import type { MediaItem, MediaResolveContext } from '../../utils/media'; -import { readI18n } from '../../i18n/translations'; -import type { Question } from '../../types'; -import styles from './QuestionBody.module.scss'; - -/** - * QuestionBody — generic, shared renderer for question text. - * - * Responsibilities ONLY: - * - Render raw HTML body (may contain images, tables, etc.) - * - Render KaTeX math found in `.math` / `.math-block` elements - * - RTL support (Arabic) - * - * It is question-type AGNOSTIC: no MCQ/SA/MTF/SEQ/REO/FTB logic, no answer - * handling, no scoring/telemetry/navigation. Every Phase 4 question type reuses - * this component to render its stem. - */ -interface QuestionBodyProps { - question: Pick; - language?: string; - /** - * Media + offline resolution inputs. When supplied (e.g. by Hint for solution - * content), its `media` takes precedence over `question.media`. - */ - mediaCtx?: MediaResolveContext; -} - -export function QuestionBody({ question, language = 'en', mediaCtx }: QuestionBodyProps) { - const containerRef = useRef(null); - // The HTML most recently written to the container. Parents rebuild the - // `question`/`mediaCtx` props as fresh object literals on every render (and - // the shell timer re-renders the tree every second), so the effect must NOT - // rewrite innerHTML unless the RESOLVED content actually changed — rewriting - // destroys and recreates embedded