diff --git a/package-lock.json b/package-lock.json
index fab5ffa9..e8fd2255 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,7 +11,7 @@
"@babel/preset-env": "^7.24.5",
"@deriv-com/api-hooks": "^0.1.19",
"@deriv-com/translations": "^1.2.3",
- "@deriv-com/ui": "^1.21.1",
+ "@deriv-com/ui": "^1.26.0",
"@deriv-com/utils": "latest",
"@deriv/deriv-api": "^1.0.15",
"@deriv/quill-design": "^1.2.24",
@@ -2716,12 +2716,13 @@
}
},
"node_modules/@deriv-com/ui": {
- "version": "1.21.1",
- "resolved": "https://registry.npmjs.org/@deriv-com/ui/-/ui-1.21.1.tgz",
- "integrity": "sha512-8aokCnRAQJqnpr8Kzz4qpdRoqy2EJrusfVtUSS8nb1uUvIQiMRwPMzqPt1A/OojFmTDHpES7YJPPLlu2e90LpQ==",
+ "version": "1.26.0",
+ "resolved": "https://registry.npmjs.org/@deriv-com/ui/-/ui-1.26.0.tgz",
+ "integrity": "sha512-nk6NVpuqE/ibvuJ82+Eu5pqfaMVWTVOMj0lyMouD7oTcI1etkat2TdQ0qObDp9KGrLRhhNKrTlC6OT2gQpBgog==",
"dependencies": {
"@deriv/quill-icons": "^1.22.5",
- "@types/react-modal": "^3.16.3"
+ "@types/react-modal": "^3.16.3",
+ "react-tiny-popover": "^8.0.4"
},
"optionalDependencies": {
"@rollup/rollup-linux-x64-gnu": "^4.13.0"
@@ -16998,6 +16999,15 @@
"react-dom": ">=18.0.0"
}
},
+ "node_modules/react-tiny-popover": {
+ "version": "8.0.4",
+ "resolved": "https://registry.npmjs.org/react-tiny-popover/-/react-tiny-popover-8.0.4.tgz",
+ "integrity": "sha512-pn0Y/G0gyMdYTBEWSKCCnaZsXAa54PkfnRE4fnMM5633SSClYrXxwXKc6vPYgJ9shLatGginxMjnhXq6guZmng==",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
"node_modules/react-transition-group": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
@@ -22684,13 +22694,14 @@
}
},
"@deriv-com/ui": {
- "version": "1.21.1",
- "resolved": "https://registry.npmjs.org/@deriv-com/ui/-/ui-1.21.1.tgz",
- "integrity": "sha512-8aokCnRAQJqnpr8Kzz4qpdRoqy2EJrusfVtUSS8nb1uUvIQiMRwPMzqPt1A/OojFmTDHpES7YJPPLlu2e90LpQ==",
+ "version": "1.26.0",
+ "resolved": "https://registry.npmjs.org/@deriv-com/ui/-/ui-1.26.0.tgz",
+ "integrity": "sha512-nk6NVpuqE/ibvuJ82+Eu5pqfaMVWTVOMj0lyMouD7oTcI1etkat2TdQ0qObDp9KGrLRhhNKrTlC6OT2gQpBgog==",
"requires": {
"@deriv/quill-icons": "^1.22.5",
"@rollup/rollup-linux-x64-gnu": "^4.13.0",
- "@types/react-modal": "^3.16.3"
+ "@types/react-modal": "^3.16.3",
+ "react-tiny-popover": "^8.0.4"
}
},
"@deriv-com/utils": {
@@ -32933,6 +32944,12 @@
"integrity": "sha512-NTFkW8W3uwvI82Fv7JW5i7gmDjEZKxJmj+Z9vn+BjYIXT6ILdnU9qnSUP2cWrWN/WAUlue81f9SgM4CQcenltQ==",
"requires": {}
},
+ "react-tiny-popover": {
+ "version": "8.0.4",
+ "resolved": "https://registry.npmjs.org/react-tiny-popover/-/react-tiny-popover-8.0.4.tgz",
+ "integrity": "sha512-pn0Y/G0gyMdYTBEWSKCCnaZsXAa54PkfnRE4fnMM5633SSClYrXxwXKc6vPYgJ9shLatGginxMjnhXq6guZmng==",
+ "requires": {}
+ },
"react-transition-group": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
diff --git a/package.json b/package.json
index 1daa2d89..797d2c34 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,7 @@
"@babel/preset-env": "^7.24.5",
"@deriv-com/api-hooks": "^0.1.19",
"@deriv-com/translations": "^1.2.3",
- "@deriv-com/ui": "^1.21.1",
+ "@deriv-com/ui": "^1.26.0",
"@deriv-com/utils": "latest",
"@deriv/deriv-api": "^1.0.15",
"@deriv/quill-design": "^1.2.24",
diff --git a/src/components/AppFooter/AccountLimits.tsx b/src/components/AppFooter/AccountLimits.tsx
new file mode 100644
index 00000000..a039bfcb
--- /dev/null
+++ b/src/components/AppFooter/AccountLimits.tsx
@@ -0,0 +1,20 @@
+import { LegacyAccountLimitsIcon } from '@deriv/quill-icons';
+import { useTranslations } from '@deriv-com/translations';
+import { TooltipMenuIcon } from '@deriv-com/ui';
+
+const AccountLimits = () => {
+ const { localize } = useTranslations();
+
+ return (
+
+
+
+ );
+};
+
+export default AccountLimits;
diff --git a/src/components/AppFooter/AppFooter.scss b/src/components/AppFooter/AppFooter.scss
index 222db1ef..a4ab0a7e 100644
--- a/src/components/AppFooter/AppFooter.scss
+++ b/src/components/AppFooter/AppFooter.scss
@@ -1,13 +1,47 @@
.app-footer {
- padding: 2.4rem;
+ height: 3.2rem;
+ display: flex;
+ flex-direction: row-reverse;
+ align-items: center;
+ position: fixed;
+ bottom: 0;
+ right: 0;
+ left: 0;
+ border-top: 1px solid #f2f3f4;
+ box-shadow: 0px 1px 0px 0px #f2f3f4 inset;
+ background: #fff;
- &__language-btn {
- &:hover {
- background-color: transparent !important;
+ &__icon {
+ padding: 0.8rem;
+ }
+
+ &__vertical-line {
+ width: 0.1rem;
+ height: 1.6rem;
+ background-color: #f2f3f4;
+ margin: 0 0.8rem;
+ }
+
+ &__language {
+ display: flex;
+ align-items: center;
+ padding: 0.8rem;
- span {
- color: #000 !important;
- }
+ & span {
+ margin-left: 0.4rem;
}
}
+
+ &__network-status {
+ width: 0.8rem;
+ height: 0.8rem;
+ border-radius: 100%;
+ background-color: #4bb4b3;
+ margin-left: 2rem;
+ }
+
+ &__endpoint {
+ color: #377cfc;
+ text-decoration: underline;
+ }
}
diff --git a/src/components/AppFooter/AppFooter.tsx b/src/components/AppFooter/AppFooter.tsx
index 340e4947..147d7288 100644
--- a/src/components/AppFooter/AppFooter.tsx
+++ b/src/components/AppFooter/AppFooter.tsx
@@ -1,31 +1,56 @@
-import { LanguagesModal } from '@/components/Modals';
import { LANGUAGES } from '@/constants';
-import { useModalManager } from '@/hooks/custom-hooks';
-import { IconTypes } from '@deriv/quill-icons';
+import { useModalManager } from '@/hooks';
import { useTranslations } from '@deriv-com/translations';
-import { Button, Footer } from '@deriv-com/ui';
+import { DesktopLanguagesModal } from '@deriv-com/ui';
+import AccountLimits from './AccountLimits';
+import ChangeTheme from './ChangeTheme';
+import Deriv from './Deriv';
+import Endpoint from './Endpoint';
+import FullScreen from './FullScreen';
+import HelpCentre from './HelpCentre';
+import LanguageSettings from './LanguageSettings';
+import Livechat from './Livechat';
+import { NetworkStatus } from './NetworkStatus';
+import ResponsibleTrading from './ResponsibleTrading';
+import { ServerTime } from './ServerTime';
+import WhatsApp from './WhatsApp';
import './AppFooter.scss';
-// TODO: handle local storage values not updating after changing local storage values
const AppFooter = () => {
- const { currentLang } = useTranslations();
+ const { currentLang, localize, switchLanguage } = useTranslations();
const { hideModal, isModalOpenFor, showModal } = useModalManager();
- const CountryIcon = LANGUAGES.find(lang => lang.code === currentLang)?.icon as IconTypes;
+
+ const openLanguageSettingModal = () => showModal('DesktopLanguagesModal');
return (
-
+
);
};
diff --git a/src/components/AppFooter/ChangeTheme.tsx b/src/components/AppFooter/ChangeTheme.tsx
new file mode 100644
index 00000000..b5dcf083
--- /dev/null
+++ b/src/components/AppFooter/ChangeTheme.tsx
@@ -0,0 +1,15 @@
+import { LegacySettings1pxIcon } from '@deriv/quill-icons';
+import { useTranslations } from '@deriv-com/translations';
+import { TooltipMenuIcon } from '@deriv-com/ui';
+
+const ChangeTheme = () => {
+ const { localize } = useTranslations();
+
+ return (
+
+
+
+ );
+};
+
+export default ChangeTheme;
diff --git a/src/components/AppFooter/Deriv.tsx b/src/components/AppFooter/Deriv.tsx
new file mode 100644
index 00000000..1e7d9f76
--- /dev/null
+++ b/src/components/AppFooter/Deriv.tsx
@@ -0,0 +1,21 @@
+import { LegacyDerivIcon } from '@deriv/quill-icons';
+import { useTranslations } from '@deriv-com/translations';
+import { TooltipMenuIcon } from '@deriv-com/ui';
+
+const Deriv = () => {
+ const { localize } = useTranslations();
+
+ return (
+
+
+
+ );
+};
+
+export default Deriv;
diff --git a/src/components/AppFooter/Endpoint.tsx b/src/components/AppFooter/Endpoint.tsx
new file mode 100644
index 00000000..4ea8565e
--- /dev/null
+++ b/src/components/AppFooter/Endpoint.tsx
@@ -0,0 +1,21 @@
+import { Link } from 'react-router-dom';
+import { Text } from '@deriv-com/ui';
+
+const Endpoint = () => {
+ const serverURL = localStorage.getItem('config.server_url');
+
+ if (serverURL) {
+ return (
+
+ The server{' '}
+
+ endpoint
+ {' '}
+ {`is: ${serverURL}`}
+
+ );
+ }
+ return null;
+};
+
+export default Endpoint;
diff --git a/src/components/AppFooter/FullScreen.tsx b/src/components/AppFooter/FullScreen.tsx
new file mode 100644
index 00000000..69140426
--- /dev/null
+++ b/src/components/AppFooter/FullScreen.tsx
@@ -0,0 +1,22 @@
+import { useFullScreen } from '@/hooks';
+import { LegacyFullscreen1pxIcon } from '@deriv/quill-icons';
+import { useTranslations } from '@deriv-com/translations';
+import { TooltipMenuIcon } from '@deriv-com/ui';
+
+const FullScreen = () => {
+ const { toggleFullScreenMode } = useFullScreen();
+ const { localize } = useTranslations();
+
+ return (
+
+
+
+ );
+};
+
+export default FullScreen;
diff --git a/src/components/AppFooter/HelpCentre.tsx b/src/components/AppFooter/HelpCentre.tsx
new file mode 100644
index 00000000..7beae7d4
--- /dev/null
+++ b/src/components/AppFooter/HelpCentre.tsx
@@ -0,0 +1,21 @@
+import { LegacyHelpCentreIcon } from '@deriv/quill-icons';
+import { useTranslations } from '@deriv-com/translations';
+import { TooltipMenuIcon } from '@deriv-com/ui';
+
+const HelpCentre = () => {
+ const { localize } = useTranslations();
+
+ return (
+
+
+
+ );
+};
+
+export default HelpCentre;
diff --git a/src/components/AppFooter/LanguageSettings.tsx b/src/components/AppFooter/LanguageSettings.tsx
new file mode 100644
index 00000000..5add8a3a
--- /dev/null
+++ b/src/components/AppFooter/LanguageSettings.tsx
@@ -0,0 +1,30 @@
+import { LANGUAGES } from '@/constants';
+import { useTranslations } from '@deriv-com/translations';
+import { Text, TooltipMenuIcon } from '@deriv-com/ui';
+import './AppFooter.scss';
+
+type TLanguageSettings = {
+ openLanguageSettingModal: () => void;
+};
+
+const LanguageSettings = ({ openLanguageSettingModal }: TLanguageSettings) => {
+ const { currentLang, localize } = useTranslations();
+
+ const countryIcon = LANGUAGES.find(({ code }) => code == currentLang)?.icon;
+
+ return (
+
+ {countryIcon}
+
+ {currentLang}
+
+
+ );
+};
+
+export default LanguageSettings;
diff --git a/src/components/AppFooter/Livechat.tsx b/src/components/AppFooter/Livechat.tsx
new file mode 100644
index 00000000..dae77d22
--- /dev/null
+++ b/src/components/AppFooter/Livechat.tsx
@@ -0,0 +1,15 @@
+import { LegacyLiveChatOutlineIcon } from '@deriv/quill-icons';
+import { useTranslations } from '@deriv-com/translations';
+import { TooltipMenuIcon } from '@deriv-com/ui';
+
+const Livechat = () => {
+ const { localize } = useTranslations();
+
+ return (
+
+
+
+ );
+};
+
+export default Livechat;
diff --git a/src/components/AppFooter/NetworkStatus.tsx b/src/components/AppFooter/NetworkStatus.tsx
new file mode 100644
index 00000000..df87c97b
--- /dev/null
+++ b/src/components/AppFooter/NetworkStatus.tsx
@@ -0,0 +1,17 @@
+import { useTranslations } from '@deriv-com/translations';
+import { TooltipMenuIcon } from '@deriv-com/ui';
+
+export const NetworkStatus = () => {
+ const { localize } = useTranslations();
+
+ return (
+
+
+
+ );
+};
diff --git a/src/components/AppFooter/ResponsibleTrading.tsx b/src/components/AppFooter/ResponsibleTrading.tsx
new file mode 100644
index 00000000..007cf981
--- /dev/null
+++ b/src/components/AppFooter/ResponsibleTrading.tsx
@@ -0,0 +1,21 @@
+import { LegacyResponsibleTradingIcon } from '@deriv/quill-icons';
+import { useTranslations } from '@deriv-com/translations';
+import { TooltipMenuIcon } from '@deriv-com/ui';
+
+const ResponsibleTrading = () => {
+ const { localize } = useTranslations();
+
+ return (
+
+
+
+ );
+};
+
+export default ResponsibleTrading;
diff --git a/src/components/AppFooter/ServerTime.tsx b/src/components/AppFooter/ServerTime.tsx
new file mode 100644
index 00000000..1eb93591
--- /dev/null
+++ b/src/components/AppFooter/ServerTime.tsx
@@ -0,0 +1,17 @@
+import { useTranslations } from '@deriv-com/translations';
+import { Text, TooltipMenuIcon } from '@deriv-com/ui';
+
+export const ServerTime = () => {
+ const { localize } = useTranslations();
+
+ return (
+
+ 01 Jan 2021 00:00:00 GMT
+
+ );
+};
diff --git a/src/components/AppFooter/WhatsApp.tsx b/src/components/AppFooter/WhatsApp.tsx
new file mode 100644
index 00000000..a4dbb0df
--- /dev/null
+++ b/src/components/AppFooter/WhatsApp.tsx
@@ -0,0 +1,21 @@
+import { LegacyWhatsappIcon } from '@deriv/quill-icons';
+import { useTranslations } from '@deriv-com/translations';
+import { TooltipMenuIcon } from '@deriv-com/ui';
+
+const WhatsApp = () => {
+ const { localize } = useTranslations();
+
+ return (
+
+
+
+ );
+};
+
+export default WhatsApp;
diff --git a/src/components/AppFooter/__tests__/AppFooter.spec.tsx b/src/components/AppFooter/__tests__/AppFooter.spec.tsx
deleted file mode 100644
index dfdb0b98..00000000
--- a/src/components/AppFooter/__tests__/AppFooter.spec.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import { render, screen } from '@testing-library/react';
-import AppFooter from '../AppFooter';
-
-jest.mock('use-query-params', () => ({
- ...jest.requireActual('use-query-params'),
- useQueryParams: jest.fn().mockReturnValue([{}, jest.fn()]),
-}));
-
-jest.mock('@deriv-com/translations', () => ({
- useTranslations: jest.fn(() => ({ currentLang: 'EN' })),
-}));
-
-jest.mock('@deriv-com/ui', () => ({
- ...jest.requireActual('@deriv-com/ui'),
- useDevice: jest.fn(() => ({ isMobile: false })),
-}));
-
-describe('', () => {
- it('should render the footer', () => {
- render();
- expect(screen.getByRole('button', { name: 'EN' })).toBeInTheDocument();
- });
-});
diff --git a/src/components/Modals/LanguagesModal/LanguagesModal.scss b/src/components/Modals/LanguagesModal/LanguagesModal.scss
deleted file mode 100644
index 00e89425..00000000
--- a/src/components/Modals/LanguagesModal/LanguagesModal.scss
+++ /dev/null
@@ -1,23 +0,0 @@
-.languages-modal {
- &__body {
- display: grid;
- grid-template-columns: repeat(4, 1fr);
- grid-gap: 1rem;
- padding: 2rem;
-
- &-button {
- height: auto;
- display: flex;
- align-items: center;
- flex-direction: column;
-
- &:hover {
- background-color: transparent !important;
-
- span {
- color: #000 !important;
- }
- }
- }
- }
-}
diff --git a/src/components/Modals/LanguagesModal/LanguagesModal.tsx b/src/components/Modals/LanguagesModal/LanguagesModal.tsx
deleted file mode 100644
index b312e768..00000000
--- a/src/components/Modals/LanguagesModal/LanguagesModal.tsx
+++ /dev/null
@@ -1,45 +0,0 @@
-import { LANGUAGES } from '@/constants';
-import { useTranslations } from '@deriv-com/translations';
-import { Button, Modal, Text } from '@deriv-com/ui';
-import './LanguagesModal.scss';
-
-type TLanguagesModalProps = {
- isModalOpen: boolean;
- onClose: () => void;
-};
-
-const LanguagesModal = ({ isModalOpen, onClose }: TLanguagesModalProps) => {
- const { currentLang, switchLanguage } = useTranslations();
-
- return (
-
-
- {'Select Language'}
-
-
- {LANGUAGES.map(language => {
- const LanguageIcon = language.icon;
- return (
- }
- key={language.code}
- onClick={() => {
- switchLanguage(language.code);
- onClose();
- }}
- variant='ghost'
- >
-
- {language.display_name}
-
-
- );
- })}
-
-
- );
-};
-
-export default LanguagesModal;
diff --git a/src/components/Modals/LanguagesModal/index.ts b/src/components/Modals/LanguagesModal/index.ts
deleted file mode 100644
index 0cfe8480..00000000
--- a/src/components/Modals/LanguagesModal/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { default as LanguagesModal } from './LanguagesModal';
diff --git a/src/components/Modals/index.ts b/src/components/Modals/index.ts
index f98f6fdf..1d239b27 100644
--- a/src/components/Modals/index.ts
+++ b/src/components/Modals/index.ts
@@ -15,7 +15,6 @@ export * from './EmailVerificationModal';
export * from './ErrorModal';
export * from './FilterModal';
export * from './InvalidVerificationLinkModal';
-export * from './LanguagesModal';
export * from './LoadingModal';
export * from './MyAdsDeleteModal';
export * from './NicknameModal';
diff --git a/src/constants/languages.ts b/src/constants/languages.ts
deleted file mode 100644
index 9e5ac83b..00000000
--- a/src/constants/languages.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import {
- FlagFranceIcon,
- FlagGermanyIcon,
- FlagItalyIcon,
- FlagPolandIcon,
- FlagPortugalIcon,
- FlagRussiaIcon,
- FlagSpainIcon,
- FlagThailandIcon,
- FlagTurkeyIcon,
- FlagUnitedArabEmiratesIcon,
- FlagUnitedKingdomIcon,
- FlagVietnamIcon,
-} from '@deriv/quill-icons';
-
-export const LANGUAGES = [
- { code: 'AR', display_name: 'العربية', icon: FlagUnitedArabEmiratesIcon },
- { code: 'DE', display_name: 'Deutsch', icon: FlagGermanyIcon },
- { code: 'EN', display_name: 'English', icon: FlagUnitedKingdomIcon },
- { code: 'ES', display_name: 'Español', icon: FlagSpainIcon },
- { code: 'FR', display_name: 'Français', icon: FlagFranceIcon },
- { code: 'IT', display_name: 'Italiano', icon: FlagItalyIcon },
- { code: 'PL', display_name: 'Polish', icon: FlagPolandIcon },
- { code: 'PT', display_name: 'Português', icon: FlagPortugalIcon },
- { code: 'RU', display_name: 'Русский', icon: FlagRussiaIcon },
- { code: 'TH', display_name: 'ไทย', icon: FlagThailandIcon },
- { code: 'TR', display_name: 'Türkçe', icon: FlagTurkeyIcon },
- { code: 'VI', display_name: 'Tiếng Việt', icon: FlagVietnamIcon },
-];
diff --git a/src/constants/languages.tsx b/src/constants/languages.tsx
new file mode 100644
index 00000000..ba01c7ef
--- /dev/null
+++ b/src/constants/languages.tsx
@@ -0,0 +1,29 @@
+import {
+ FlagFranceIcon,
+ FlagGermanyIcon,
+ FlagItalyIcon,
+ FlagPolandIcon,
+ FlagPortugalIcon,
+ FlagRussiaIcon,
+ FlagSpainIcon,
+ FlagThailandIcon,
+ FlagTurkeyIcon,
+ FlagUnitedArabEmiratesIcon,
+ FlagUnitedKingdomIcon,
+ FlagVietnamIcon,
+} from '@deriv/quill-icons';
+
+export const LANGUAGES = [
+ { code: 'AR', displayName: 'العربية', icon: },
+ { code: 'DE', displayName: 'Deutsch', icon: },
+ { code: 'EN', displayName: 'English', icon: },
+ { code: 'ES', displayName: 'Español', icon: },
+ { code: 'FR', displayName: 'Français', icon: },
+ { code: 'IT', displayName: 'Italiano', icon: },
+ { code: 'PL', displayName: 'Polish', icon: },
+ { code: 'PT', displayName: 'Português', icon: },
+ { code: 'RU', displayName: 'Русский', icon: },
+ { code: 'TH', displayName: 'ไทย', icon: },
+ { code: 'TR', displayName: 'Türkçe', icon: },
+ { code: 'VI', displayName: 'Tiếng Việt', icon: },
+];
diff --git a/src/hooks/custom-hooks/index.ts b/src/hooks/custom-hooks/index.ts
index 3a18f3ba..dd9862cc 100644
--- a/src/hooks/custom-hooks/index.ts
+++ b/src/hooks/custom-hooks/index.ts
@@ -4,6 +4,7 @@ export { default as useDevice } from './useDevice';
export { default as useExtendedOrderDetails } from './useExtendedOrderDetails';
export { default as useFetchMore } from './useFetchMore';
export { default as useFloatingRate } from './useFloatingRate';
+export { default as useFullScreen } from './useFullScreen';
export { default as useIsAdvertiser } from './useIsAdvertiser';
export { default as useIsAdvertiserBarred } from './useIsAdvertiserBarred';
export { default as useModalManager } from './useModalManager';
diff --git a/src/hooks/custom-hooks/useFullScreen.ts b/src/hooks/custom-hooks/useFullScreen.ts
new file mode 100644
index 00000000..bf50da23
--- /dev/null
+++ b/src/hooks/custom-hooks/useFullScreen.ts
@@ -0,0 +1,43 @@
+import { MouseEvent, useCallback, useEffect, useState } from 'react';
+
+const fullScreenControls = {
+ exit: ['exitFullscreen', 'webkitExitFullscreen', 'mozCancelFullScreen', 'msExitFullscreen'],
+ request: ['requestFullscreen', 'webkitRequestFullscreen', 'mozRequestFullScreen', 'msRequestFullscreen'],
+ screenChange: ['fullscreenchange', 'webkitfullscreenchange', 'mozfullscreenchange', 'MSFullscreenChange'],
+ screenElement: ['fullscreenElement', 'webkitFullscreenElement', 'mozFullScreenElement', 'msFullscreenElement'],
+} as const;
+
+const useFullScreen = () => {
+ const [isInFullScreenMode, setFullScreenMode] = useState(false);
+ const { exit, request, screenChange, screenElement } = fullScreenControls;
+
+ const onFullScreen = useCallback(
+ () => setFullScreenMode(screenElement.some(element => document[element as keyof Document])),
+ [screenElement]
+ );
+
+ useEffect(() => {
+ screenChange.forEach(event => {
+ document.addEventListener(event, onFullScreen, false);
+ });
+ }, [onFullScreen, screenChange]);
+
+ const toggleFullScreenMode = (event: MouseEvent) => {
+ event.stopPropagation();
+
+ const exitFullScreen = exit.find(element => document[element as keyof Document]);
+ const requestFullScreen = request.find(element => document.documentElement[element as keyof HTMLElement]);
+
+ if (isInFullScreenMode && exitFullScreen) {
+ (document[exitFullScreen as keyof Document] as Document['exitFullscreen'])();
+ } else if (requestFullScreen) {
+ (document.documentElement[requestFullScreen as keyof HTMLElement] as HTMLElement['requestFullscreen'])();
+ } else {
+ setFullScreenMode(false); // fullscreen API is not enabled
+ }
+ };
+
+ return { toggleFullScreenMode };
+};
+
+export default useFullScreen;