diff --git a/packages/client/src/Shell.jsx b/packages/client/src/Shell.jsx
index 521af8f316..e3f0a21e4c 100644
--- a/packages/client/src/Shell.jsx
+++ b/packages/client/src/Shell.jsx
@@ -429,13 +429,12 @@ const Shell = ({ items = [], page = "home", ...rest }) => {
{toast}
{/* */}
{withoutNavMenu ? <>> : }
- {currentDeviceType === DeviceType.mobile && !isFrame && }
- {currentDeviceType !== DeviceType.mobile && !isFrame && }
+ {!isFrame && }
diff --git a/packages/client/src/components/Layout/MobileLayout.js b/packages/client/src/components/Layout/MobileLayout.js
deleted file mode 100644
index 44adc9414a..0000000000
--- a/packages/client/src/components/Layout/MobileLayout.js
+++ /dev/null
@@ -1,183 +0,0 @@
-// (c) Copyright Ascensio System SIA 2009-2024
-//
-// This program is a free software product.
-// You can redistribute it and/or modify it under the terms
-// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
-// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
-// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
-// any third-party rights.
-//
-// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
-// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
-// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
-//
-// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
-//
-// The interactive user interfaces in modified source and object code versions of the Program must
-// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
-//
-// Pursuant to Section 7(b) of the License you must retain the original Product logo when
-// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
-// trademark law for use of our trademarks.
-//
-// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
-// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
-// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
-
-import React, { Component, createRef } from "react";
-import {
- isDesktop,
- isTouchDevice,
- getBannerAttribute,
-} from "@docspace/shared/utils";
-import { Scrollbar } from "@docspace/shared/components/scrollbar";
-import { LayoutContextProvider } from "./context";
-
-import PropTypes from "prop-types";
-import {
- isTablet,
- isMobile,
- isSafari,
- isIOS,
- isChrome,
-} from "react-device-detect";
-class MobileLayout extends Component {
- constructor(props) {
- super(props);
-
- this.state = {
- prevScrollPosition: window.pageYOffset,
- visibleContent: true,
- };
-
- this.scrollRefPage = createRef();
- }
-
- componentDidMount() {
- this.customScrollElm = document.querySelector(
- "#customScrollBar > .scroll-wrapper > .scroller",
- );
-
- if (!isChrome) this.customScrollElm.scrollTo(0, 0);
-
- this.customScrollElm.addEventListener(
- "scroll",
- this.scrolledTheVerticalAxis,
- );
-
- // this.setState({ visibleContent: true });
- }
-
- componentWillUnmount() {
- this.customScrollElm.removeEventListener(
- "scroll",
- this.scrolledTheVerticalAxis,
- );
- }
-
- scrolledTheVerticalAxis = () => {
- const { prevScrollPosition, visibleContent } = this.state;
- const { headerHeight } = getBannerAttribute();
-
- const currentScrollPosition =
- this.customScrollElm.scrollTop > 0 ? this.customScrollElm.scrollTop : 0;
-
- if (
- !isDesktop() &&
- document.getElementsByClassName("backdrop-active").length > 0 &&
- !this.props.isArticleVisibleOnUnpin
- ) {
- const elements = document.getElementsByClassName("backdrop-active");
- elements[0].click();
- return;
- }
-
- if (visibleContent && isMobile && !isTouchDevice) {
- return;
- }
- if (
- (isSafari || isIOS) &&
- this.customScrollElm.scrollHeight - this.customScrollElm.clientHeight <
- headerHeight
- ) {
- if (!this.state.visibleContent)
- this.setState({
- visibleContent: true,
- });
- return;
- }
-
- if (
- prevScrollPosition - currentScrollPosition > 0 &&
- currentScrollPosition < headerHeight
- ) {
- if (!this.state.visibleContent)
- this.setState({
- visibleContent: true,
- });
- return;
- }
-
- if (
- (isSafari || isIOS) &&
- Math.abs(currentScrollPosition - prevScrollPosition) <= headerHeight &&
- currentScrollPosition === 0
- ) {
- if (!this.state.visibleContent)
- this.setState({
- visibleContent: true,
- });
- return;
- }
-
- if (Math.abs(currentScrollPosition - prevScrollPosition) <= headerHeight) {
- return;
- }
-
- if (prevScrollPosition === 0 && currentScrollPosition > 100) {
- if (Math.abs(currentScrollPosition - prevScrollPosition) <= 104) {
- return;
- }
- }
-
- let isVisible = prevScrollPosition >= currentScrollPosition;
-
- if (
- (isSafari || isIOS) &&
- currentScrollPosition >=
- this.customScrollElm.scrollHeight - this.customScrollElm.clientHeight &&
- this.customScrollElm.scrollHeight !== this.customScrollElm.clientHeight
- ) {
- isVisible = false;
- }
-
- this.setState({
- prevScrollPosition: currentScrollPosition,
- visibleContent: isVisible,
- });
- };
-
- render() {
- const scrollProp = { ref: this.scrollRefPage };
- const { children } = this.props;
-
- return (
-
-
- {children}
-
-
- );
- }
-}
-
-MobileLayout.propTypes = {
- children: PropTypes.any,
-};
-
-export default MobileLayout;
diff --git a/packages/client/src/components/Layout/context.js b/packages/client/src/components/Layout/context.js
deleted file mode 100644
index efba9839f0..0000000000
--- a/packages/client/src/components/Layout/context.js
+++ /dev/null
@@ -1,32 +0,0 @@
-// (c) Copyright Ascensio System SIA 2009-2024
-//
-// This program is a free software product.
-// You can redistribute it and/or modify it under the terms
-// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
-// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
-// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
-// any third-party rights.
-//
-// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
-// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
-// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
-//
-// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
-//
-// The interactive user interfaces in modified source and object code versions of the Program must
-// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
-//
-// Pursuant to Section 7(b) of the License you must retain the original Product logo when
-// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
-// trademark law for use of our trademarks.
-//
-// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
-// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
-// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
-
-import { createContext } from "react";
-
-const LayoutContext = createContext({});
-
-export const LayoutContextProvider = LayoutContext.Provider;
-export const LayoutContextConsumer = LayoutContext.Consumer;
diff --git a/packages/client/src/components/Layout/index.js b/packages/client/src/components/Layout/index.js
index 9b56d7c825..2507c32729 100644
--- a/packages/client/src/components/Layout/index.js
+++ b/packages/client/src/components/Layout/index.js
@@ -24,18 +24,19 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
-import React, { useEffect, useState } from "react";
-import styled, { css } from "styled-components";
import PropTypes from "prop-types";
-import MobileLayout from "./MobileLayout";
+import { inject, observer } from "mobx-react";
+import styled, { css } from "styled-components";
+import React, { useEffect, useState } from "react";
import { useNavigate, useLocation } from "react-router-dom";
+import { isMobile, isMobileOnly } from "react-device-detect";
+
+import { Scrollbar } from "@docspace/shared/components/scrollbar";
import {
isTablet as isTabletUtils,
- isMobile as isMobileUtils,
+ mobileMore,
tablet,
} from "@docspace/shared/utils";
-import { isMobile, isMobileOnly } from "react-device-detect";
-import { inject, observer } from "mobx-react";
const StyledContainer = styled.div`
user-select: none;
@@ -58,6 +59,14 @@ const StyledContainer = styled.div`
padding: env(safe-area-inset-top) env(safe-area-inset-right)
env(safe-area-inset-bottom) env(safe-area-inset-left);
`}
+
+ @media ${mobileMore} {
+ #customScrollBar {
+ > .scroll-wrapper > .scroller > .scroll-body {
+ padding-inline: 0px !important;
+ }
+ }
+ }
`;
const Layout = (props) => {
@@ -157,7 +166,7 @@ const Layout = (props) => {
contentHeight={contentHeight}
isPortrait={isPortrait}
>
- {isMobileUtils() ? : children}
+ {children}
);
};
diff --git a/packages/client/src/components/Main/index.js b/packages/client/src/components/Main/index.js
index 94ec64b2b6..273f33a5af 100644
--- a/packages/client/src/components/Main/index.js
+++ b/packages/client/src/components/Main/index.js
@@ -33,7 +33,7 @@ import { isMobile as isMobileUtils } from "@docspace/shared/utils";
const StyledMain = styled.main`
height: ${(props) => props.mainHeight && `${props.mainHeight}px`};
- width: 100vw;
+ width: 100%;
z-index: 0;
display: flex;
flex-direction: column;
diff --git a/packages/client/src/components/NavMenu/index.js b/packages/client/src/components/NavMenu/index.js
index 8e967f496f..ab61002f23 100644
--- a/packages/client/src/components/NavMenu/index.js
+++ b/packages/client/src/components/NavMenu/index.js
@@ -39,7 +39,6 @@ import { withTranslation } from "react-i18next";
import { useNavigate, useLocation } from "react-router-dom";
import { NavMenuHeaderLoader } from "@docspace/shared/skeletons/nav-menu";
-import { LayoutContextConsumer } from "../Layout/context";
import { inject, observer } from "mobx-react";
import PreparationPortalDialog from "../dialogs/PreparationPortalDialog";
@@ -167,47 +166,43 @@ const NavMenu = (props) => {
const isPreparationPortal = location.pathname === "/preparation-portal";
return (
-
- {(value) => (
-
-
+
+
- {!hideHeader &&
- (isLoaded && isAuthenticated ? (
- <>
- {!isPreparationPortal && (
-
- )}
-
- >
- ) : !isLoaded && isAuthenticated ? (
-
- ) : (
-
- ))}
+ {!hideHeader &&
+ (isLoaded && isAuthenticated ? (
+ <>
+ {!isPreparationPortal && (
+
+ )}
+
+ >
+ ) : !isLoaded && isAuthenticated ? (
+
+ ) : (
+
+ ))}
- {isAsideAvailable && (
-
- )}
-
+ {isAsideAvailable && (
+
)}
-
+
);
};
diff --git a/packages/client/src/components/dialogs/CreateEditGroupDialog/sub-components/GroupMemberRow/index.styled.ts b/packages/client/src/components/dialogs/CreateEditGroupDialog/sub-components/GroupMemberRow/index.styled.ts
index 499cfff2ca..64fe27fef1 100644
--- a/packages/client/src/components/dialogs/CreateEditGroupDialog/sub-components/GroupMemberRow/index.styled.ts
+++ b/packages/client/src/components/dialogs/CreateEditGroupDialog/sub-components/GroupMemberRow/index.styled.ts
@@ -44,12 +44,18 @@ export const GroupMemberRow = styled.div<{}>`
align-items: flex-start;
justify-content: center;
padding: 9px 0;
+ width: 100%;
+ overflow: hidden;
.name {
color: ${({ theme }) => theme.sideBarRow.titleColor};
font-size: 14px;
font-weight: 600;
line-height: 16px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ width: 100%;
}
.email {
@@ -57,6 +63,10 @@ export const GroupMemberRow = styled.div<{}>`
font-size: 10px;
font-weight: 400;
line-height: normal;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ width: 100%;
}
}
diff --git a/packages/client/src/components/panels/InvitePanel/StyledInvitePanel.js b/packages/client/src/components/panels/InvitePanel/StyledInvitePanel.js
index a02a0309a7..4919d3486b 100644
--- a/packages/client/src/components/panels/InvitePanel/StyledInvitePanel.js
+++ b/packages/client/src/components/panels/InvitePanel/StyledInvitePanel.js
@@ -425,6 +425,7 @@ const StyledCrossIcon = styled(CrossIcon)`
StyledCrossIcon.defaultProps = { theme: Base };
const StyledDeleteIcon = styled(DeleteIcon)`
+cursor: pointer;
${(props) =>
props.theme.interfaceDirection === "rtl"
? css`
diff --git a/packages/client/src/components/panels/InvitePanel/sub-components/Item.js b/packages/client/src/components/panels/InvitePanel/sub-components/Item.js
index 3c0b8fdff1..be3bc7b83a 100644
--- a/packages/client/src/components/panels/InvitePanel/sub-components/Item.js
+++ b/packages/client/src/components/panels/InvitePanel/sub-components/Item.js
@@ -50,6 +50,7 @@ import AccessSelector from "./AccessSelector";
const Item = ({
t,
item,
+ theme,
setInviteItems,
inviteItems,
changeInviteItem,
@@ -216,7 +217,7 @@ const Item = ({
tooltipContent={t("EmailErrorMessage")}
openOnClick={false}
size={16}
- color="#F21C0E"
+ color={theme.infoPanel.errorColor}
/>
{
- {
const { setInviteItems, inviteItems, changeInviteItem } = dialogsStore;
const { isOwner } = userStore.user;
- const { standalone } = settingsStore;
+ const { theme, standalone } = settingsStore;
return {
setInviteItems,
@@ -204,5 +205,6 @@ export default inject(({ userStore, dialogsStore, settingsStore }) => {
changeInviteItem,
isOwner,
standalone,
+ theme,
};
})(observer(ItemsList));
diff --git a/packages/client/src/pages/Home/MediaViewer/index.js b/packages/client/src/pages/Home/MediaViewer/index.js
index 842cf2a726..514270d30f 100644
--- a/packages/client/src/pages/Home/MediaViewer/index.js
+++ b/packages/client/src/pages/Home/MediaViewer/index.js
@@ -34,6 +34,7 @@ import { PluginFileType } from "SRC_DIR/helpers/plugins/enums";
import { UrlActionType } from "@docspace/shared/enums";
import MediaViewer from "@docspace/shared/components/media-viewer/MediaViewer";
+import { Portal } from "@docspace/shared/components/portal";
const FilesMediaViewer = (props) => {
const {
@@ -275,41 +276,46 @@ const FilesMediaViewer = (props) => {
return (
visible && (
-
+ }
/>
)
);
diff --git a/packages/client/src/pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/Manager.js b/packages/client/src/pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/Manager.js
index d0b4bdedc4..c558d714c3 100644
--- a/packages/client/src/pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/Manager.js
+++ b/packages/client/src/pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/Manager.js
@@ -898,7 +898,7 @@ const Manager = (props) => {
scale={true}
onChange={onChangePage}
placeholder={t("EnterPage")}
- value={config.filter.page || 1}
+ value={config.filter.page}
isDisabled={!config.filter.count}
tabIndex={7}
/>
diff --git a/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/Certificates.js b/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/Certificates.js
index 15da75aac3..a7d3695844 100644
--- a/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/Certificates.js
+++ b/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/Certificates.js
@@ -65,7 +65,7 @@ const Certificates = (props) => {
spShowAdditionalParameters,
idpVerifyAlgorithm,
spEncryptAlgorithm,
- spDecryptAlgorithm,
+ spSigningAlgorithm,
isLoadingXml,
isDisabledSpSigning,
isDisabledSpEncrypt,
@@ -186,7 +186,7 @@ const Certificates = (props) => {
name="spSigningAlgorithm"
options={verifyAlgorithmsOptions}
tabIndex={14}
- value={spEncryptAlgorithm}
+ value={spSigningAlgorithm}
/>
{
name={"spEncryptAlgorithm"}
options={decryptAlgorithmsOptions}
tabIndex={15}
- value={spDecryptAlgorithm}
+ value={spEncryptAlgorithm}
/>
>
)}
@@ -220,7 +220,7 @@ export default inject(({ ssoStore }) => {
spShowAdditionalParameters,
idpVerifyAlgorithm,
spEncryptAlgorithm,
- spDecryptAlgorithm,
+ spSigningAlgorithm,
isLoadingXml,
isDisabledSpSigning,
isDisabledSpEncrypt,
@@ -237,7 +237,7 @@ export default inject(({ ssoStore }) => {
spShowAdditionalParameters,
idpVerifyAlgorithm,
spEncryptAlgorithm,
- spDecryptAlgorithm,
+ spSigningAlgorithm,
isLoadingXml,
isDisabledSpSigning,
isDisabledSpEncrypt,
diff --git a/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/index.js b/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/index.js
index 1b4697ab1b..90156a8721 100644
--- a/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/index.js
+++ b/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/index.js
@@ -58,7 +58,7 @@ const SingleSignOn = (props) => {
const isMobileView = currentDeviceType === DeviceType.mobile;
useEffect(() => {
- isSSOAvailable && !isMobileView && init();
+ isSSOAvailable && init();
setDocumentTitle(t("Settings:SingleSignOn"));
}, []);
diff --git a/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/sub-components/SsoComboBox.js b/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/sub-components/SsoComboBox.js
index 033933de32..5e25020805 100644
--- a/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/sub-components/SsoComboBox.js
+++ b/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/sub-components/SsoComboBox.js
@@ -53,7 +53,7 @@ const SsoComboBox = (props) => {
};
return (
-
+
import("../pages/PortalSettings"));
-
-const CustomizationSettings = loadable(
- () => import("../pages/PortalSettings/categories/common/index.js"),
-);
-const LanguageAndTimeZoneSettings = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/common/Customization/language-and-time-zone"
- ),
-);
-const WelcomePageSettings = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/common/Customization/welcome-page-settings"
- ),
-);
-const DNSSettings = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/common/Customization/dns-settings"
- ),
-);
-const PortalRenaming = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/common/Customization/portal-renaming"
- ),
-);
-const WhiteLabel = loadable(
- () => import("../pages/PortalSettings/categories/common/Branding/whitelabel"),
-);
-const CompanyInfoSettings = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/common/Branding/companyInfoSettings"
- ),
-);
-const AdditionalResources = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/common/Branding/additionalResources"
- ),
-);
-const SecuritySettings = loadable(
- () => import("../pages/PortalSettings/categories/security/index.js"),
-);
-const TfaPage = loadable(
- () => import("../pages/PortalSettings/categories/security/access-portal/tfa"),
-);
-const PasswordStrengthPage = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/security/access-portal/passwordStrength"
- ),
-);
-const TrustedMailPage = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/security/access-portal/trustedMail"
- ),
-);
-const IpSecurityPage = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/security/access-portal/ipSecurity"
- ),
-);
-const BruteForceProtectionPage = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/security/access-portal/bruteForceProtection"
- ),
-);
-const AdminMessagePage = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/security/access-portal/adminMessage"
- ),
-);
-const SessionLifetimePage = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/security/access-portal/sessionLifetime"
- ),
-);
-const Integration = loadable(
- () => import("../pages/PortalSettings/categories/integration"),
-);
-const Payments = loadable(
- () => import("../pages/PortalSettings/categories/payments"),
-);
-const Statistics = loadable(
- () => import("../pages/PortalSettings/categories/storage-management"),
-);
-const QuotaPerRoom = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/storage-management/sub-components/QuotaPerRoom.js"
- ),
-);
-const QuotaPerUser = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/storage-management/sub-components/QuotaPerUser.js"
- ),
-);
-const ThirdParty = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/integration/ThirdPartyServicesSettings"
- ),
+const PortalSettings = loadable(() =>
+ componentLoader(() => import("../pages/PortalSettings")),
);
-const DocumentService = loadable(
- () =>
- import("../pages/PortalSettings/categories/integration/DocumentService"),
+const CustomizationSettings = loadable(() =>
+ componentLoader(
+ () => import("../pages/PortalSettings/categories/common/index.js"),
+ ),
+);
+const LanguageAndTimeZoneSettings = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/common/Customization/language-and-time-zone"
+ ),
+ ),
+);
+const WelcomePageSettings = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/common/Customization/welcome-page-settings"
+ ),
+ ),
+);
+const DNSSettings = loadable(() =>
+ componentLoader(
+ () => () =>
+ import(
+ "../pages/PortalSettings/categories/common/Customization/dns-settings"
+ ),
+ ),
+);
+const PortalRenaming = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/common/Customization/portal-renaming"
+ ),
+ ),
+);
+const WhiteLabel = loadable(() =>
+ componentLoader(
+ () =>
+ import("../pages/PortalSettings/categories/common/Branding/whitelabel"),
+ ),
+);
+const CompanyInfoSettings = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/common/Branding/companyInfoSettings"
+ ),
+ ),
+);
+const AdditionalResources = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/common/Branding/additionalResources"
+ ),
+ ),
+);
+const SecuritySettings = loadable(() =>
+ componentLoader(
+ () => import("../pages/PortalSettings/categories/security/index.js"),
+ ),
+);
+const TfaPage = loadable(() =>
+ componentLoader(
+ () =>
+ import("../pages/PortalSettings/categories/security/access-portal/tfa"),
+ ),
+);
+const PasswordStrengthPage = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/security/access-portal/passwordStrength"
+ ),
+ ),
+);
+const TrustedMailPage = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/security/access-portal/trustedMail"
+ ),
+ ),
+);
+const IpSecurityPage = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/security/access-portal/ipSecurity"
+ ),
+ ),
+);
+const BruteForceProtectionPage = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/security/access-portal/bruteForceProtection"
+ ),
+ ),
+);
+const AdminMessagePage = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/security/access-portal/adminMessage"
+ ),
+ ),
+);
+const SessionLifetimePage = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/security/access-portal/sessionLifetime"
+ ),
+ ),
+);
+const Integration = loadable(() =>
+ componentLoader(
+ () => import("../pages/PortalSettings/categories/integration"),
+ ),
+);
+const Payments = loadable(() =>
+ componentLoader(() => import("../pages/PortalSettings/categories/payments")),
+);
+const Statistics = loadable(() =>
+ componentLoader(
+ () => import("../pages/PortalSettings/categories/storage-management"),
+ ),
+);
+const QuotaPerRoom = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/storage-management/sub-components/QuotaPerRoom.js"
+ ),
+ ),
+);
+const QuotaPerUser = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/storage-management/sub-components/QuotaPerUser.js"
+ ),
+ ),
+);
+const ThirdParty = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/integration/ThirdPartyServicesSettings"
+ ),
+ ),
);
-const SingleSignOn = loadable(
- () => import("../pages/PortalSettings/categories/integration/SingleSignOn"),
-);
-const SPSettings = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/integration/SingleSignOn/SPSettings"
- ),
-);
-const SPMetadata = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/integration/SingleSignOn/ProviderMetadata"
- ),
+const DocumentService = loadable(() =>
+ componentLoader(
+ () =>
+ import("../pages/PortalSettings/categories/integration/DocumentService"),
+ ),
);
-const DeveloperTools = loadable(
- () => import("../pages/PortalSettings/categories/developer-tools/index.js"),
+const SingleSignOn = loadable(() =>
+ componentLoader(
+ () => import("../pages/PortalSettings/categories/integration/SingleSignOn"),
+ ),
+);
+const SPSettings = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/integration/SingleSignOn/SPSettings"
+ ),
+ ),
+);
+const SPMetadata = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/integration/SingleSignOn/ProviderMetadata"
+ ),
+ ),
);
-const DataImport = loadable(
- () => import("../pages/PortalSettings/categories/data-import/index.js"),
-);
-const GoogleDataImport = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/data-import/GoogleWorkspace/index.js"
- ),
-);
-const NextcloudDataImport = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/data-import/NextCloudWorkspace/index.js"
- ),
-);
-const OnlyofficeDataImport = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/data-import/OnlyofficeWorkspace/index.js"
- ),
+const DeveloperTools = loadable(() =>
+ componentLoader(
+ () => import("../pages/PortalSettings/categories/developer-tools/index.js"),
+ ),
);
-const WebhookHistory = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/developer-tools/Webhooks/WebhookHistory"
- ),
+const DataImport = loadable(() =>
+ componentLoader(
+ () => import("../pages/PortalSettings/categories/data-import/index.js"),
+ ),
);
-const WebhookDetails = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/developer-tools/Webhooks/WebhookEventDetails"
- ),
+const GoogleDataImport = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/data-import/GoogleWorkspace/index.js"
+ ),
+ ),
);
-const Backup = loadable(
- () => import("../pages/PortalSettings/categories/data-management/index"),
+const NextcloudDataImport = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/data-import/NextCloudWorkspace/index.js"
+ ),
+ ),
);
-const DeleteDataPage = loadable(
- () => import("../pages/PortalSettings/categories/delete-data"),
+const OnlyofficeDataImport = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/data-import/OnlyofficeWorkspace/index.js"
+ ),
+ ),
);
-const RestoreBackup = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/data-management/backup/restore-backup/index"
- ),
-);
-const Bonus = loadable(() => import("../pages/Bonus"));
-const DocSpace = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/DocSpace"
- ),
+const WebhookHistory = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/developer-tools/Webhooks/WebhookHistory"
+ ),
+ ),
);
-const SimpleRoom = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/SimpleRoom"
- ),
+const WebhookDetails = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/developer-tools/Webhooks/WebhookEventDetails"
+ ),
+ ),
);
-const Manager = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/Manager"
- ),
+const Backup = loadable(() =>
+ componentLoader(
+ () => import("../pages/PortalSettings/categories/data-management/index"),
+ ),
);
-const RoomSelector = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/RoomSelector"
- ),
+const DeleteDataPage = loadable(() =>
+ componentLoader(
+ () => import("../pages/PortalSettings/categories/delete-data"),
+ ),
);
-const FileSelector = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/FileSelector"
- ),
+const RestoreBackup = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/data-management/backup/restore-backup/index"
+ ),
+ ),
);
-const Editor = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/Editor"
- ),
+const Bonus = loadable(() => componentLoader(() => import("../pages/Bonus")));
+
+const DocSpace = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/DocSpace"
+ ),
+ ),
);
-const Viewer = loadable(
- () =>
- import(
- "../pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/Viewer"
- ),
+const SimpleRoom = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/SimpleRoom"
+ ),
+ ),
+);
+const Manager = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/Manager"
+ ),
+ ),
+);
+const RoomSelector = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/RoomSelector"
+ ),
+ ),
+);
+const FileSelector = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/FileSelector"
+ ),
+ ),
+);
+const Editor = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/Editor"
+ ),
+ ),
+);
+const Viewer = loadable(() =>
+ componentLoader(
+ () =>
+ import(
+ "../pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/Viewer"
+ ),
+ ),
);
const PortalSettingsRoutes = {
diff --git a/packages/client/src/store/GroupsStore.ts b/packages/client/src/store/GroupsStore.ts
index 1eae05429f..cd3c8b07f0 100644
--- a/packages/client/src/store/GroupsStore.ts
+++ b/packages/client/src/store/GroupsStore.ts
@@ -651,6 +651,8 @@ class GroupsStore {
};
changeGroupContextSelection = (group: TGroup, isSingleMenu: boolean) => {
+ this.peopleStore.selectionStore.setBufferSelection(null);
+
if (isSingleMenu) {
this.singleContextMenuAction(group);
} else {
diff --git a/packages/client/webpack.config.js b/packages/client/webpack.config.js
index 8c6833c04d..5d5f20186e 100644
--- a/packages/client/webpack.config.js
+++ b/packages/client/webpack.config.js
@@ -338,7 +338,6 @@ module.exports = (env, argv) => {
"./shell": "./src/Shell",
"./store": "./src/store",
"./Layout": "./src/components/Layout",
- "./Layout/context": "./src/components/Layout/context.js",
"./Main": "./src/components/Main",
"./NavMenu": "./src/components/NavMenu",
"./PreparationPortalDialog":
diff --git a/packages/doceditor/src/app/(root)/create/page.tsx b/packages/doceditor/src/app/(root)/create/page.tsx
index c9c2b8a32a..10f3502c61 100644
--- a/packages/doceditor/src/app/(root)/create/page.tsx
+++ b/packages/doceditor/src/app/(root)/create/page.tsx
@@ -120,7 +120,7 @@ async function Page({ searchParams }: { searchParams: TSearchParams }) {
searchParams.append("action", action);
}
- const redirectURL = `${baseURL}/doceditor?${searchParams.toString()}`;
+ const redirectURL = `/doceditor?${searchParams.toString()}`;
return permanentRedirect(redirectURL);
}
diff --git a/packages/doceditor/src/utils/actions.ts b/packages/doceditor/src/utils/actions.ts
index 6ccb4e3e4a..8e5f361ea4 100644
--- a/packages/doceditor/src/utils/actions.ts
+++ b/packages/doceditor/src/utils/actions.ts
@@ -28,10 +28,7 @@
import { headers } from "next/headers";
-import {
- createRequest,
- getBaseUrl,
-} from "@docspace/shared/utils/next-ssr-helper";
+import { createRequest } from "@docspace/shared/utils/next-ssr-helper";
import { TenantStatus, EditorConfigErrorType } from "@docspace/shared/enums";
import type {
TDocServiceLocation,
@@ -80,6 +77,7 @@ export async function fileCopyAs(
enableExternalExt,
password,
}),
+ false,
);
const file = await (await fetch(createFile)).json();
@@ -141,6 +139,7 @@ export async function createFile(
[["Content-Type", "application/json;charset=utf-8"]],
"POST",
JSON.stringify({ title, templateId, formId }),
+ false,
);
const file = await (await fetch(createFile)).json();
@@ -311,6 +310,8 @@ export async function getUser(share?: string) {
[`/people/@self`],
[share ? ["Request-Token", share] : ["", ""]],
"GET",
+ undefined,
+ false,
);
if (!cookie?.includes("asc_auth_key")) return undefined;
@@ -335,6 +336,8 @@ export async function getSettings(share?: string) {
],
[share ? ["Request-Token", share] : ["", ""]],
"GET",
+ undefined,
+ false,
);
const settingsRes = await fetch(getSettings);
@@ -360,6 +363,7 @@ export async function checkFillFromDraft(
],
"POST",
JSON.stringify({ fileId: templateFileId }),
+ false,
);
const response = await fetch(checkFillFormDraft);
@@ -383,6 +387,8 @@ export async function openEdit(
[`/files/file/${fileId}/openedit?${searchParams}`],
[share ? ["Request-Token", share] : ["", ""]],
"GET",
+ undefined,
+ false,
);
const res = await fetch(getConfig);
@@ -442,6 +448,8 @@ export async function getEditorUrl(
[`/files/docservice?${editorSearchParams ? editorSearchParams : ""}`],
[share ? ["Request-Token", share] : ["", ""]],
"GET",
+ undefined,
+ false,
);
const res = await fetch(request);
diff --git a/packages/login/src/middleware.ts b/packages/login/src/middleware.ts
index 374d2129d5..357020289e 100644
--- a/packages/login/src/middleware.ts
+++ b/packages/login/src/middleware.ts
@@ -32,7 +32,7 @@ export function middleware(request: NextRequest) {
const host = request.headers.get("x-forwarded-host");
const proto = request.headers.get("x-forwarded-proto");
- const redirectUrl = `${proto}:${host}`;
+ const redirectUrl = `${proto}://${host}`;
if (request.nextUrl.pathname === "/health") {
console.log("Get login health check for portal: ", redirectUrl);
diff --git a/packages/login/src/utils/actions.ts b/packages/login/src/utils/actions.ts
index 93c714c2bb..4edc5c616b 100644
--- a/packages/login/src/utils/actions.ts
+++ b/packages/login/src/utils/actions.ts
@@ -54,7 +54,7 @@ export const checkIsAuthenticated = async () => {
export async function getSettings() {
const [getSettings] = createRequest(
- [`/settings?withPassword=false`],
+ [`/settings?withPassword=true`],
[["", ""]],
"GET",
);
diff --git a/packages/shared/components/context-menu-button/ContextMenuButton.tsx b/packages/shared/components/context-menu-button/ContextMenuButton.tsx
index 5e60625d28..a304537ab0 100644
--- a/packages/shared/components/context-menu-button/ContextMenuButton.tsx
+++ b/packages/shared/components/context-menu-button/ContextMenuButton.tsx
@@ -348,7 +348,7 @@ ContextMenuButtonPure.defaultProps = {
size: 16,
isDisabled: false,
directionX: "left",
- isFill: false,
+ isFill: true,
usePortal: true,
displayIconBorder: false,
diff --git a/packages/shared/components/link/Link.styled.tsx b/packages/shared/components/link/Link.styled.tsx
index a7641fcb25..b94bbfffd0 100644
--- a/packages/shared/components/link/Link.styled.tsx
+++ b/packages/shared/components/link/Link.styled.tsx
@@ -52,6 +52,7 @@ const PureText = ({
const StyledText = styled(PureText)`
text-decoration: ${(props) => props.theme.link.textDecoration};
+ text-underline-offset: 2px;
${(props) =>
props.enableUserSelect
diff --git a/packages/shared/components/media-viewer/MediaViewer.styled.ts b/packages/shared/components/media-viewer/MediaViewer.styled.ts
index 47ee110586..48a121d056 100644
--- a/packages/shared/components/media-viewer/MediaViewer.styled.ts
+++ b/packages/shared/components/media-viewer/MediaViewer.styled.ts
@@ -140,6 +140,7 @@ export const StyledSwitchToolbar = styled.div`
display: block;
opacity: 0;
transition: all 0.3s;
+ top: 0;
${(props) =>
props.left ? "left: 0" : props.isPDFFile ? "right: 20px" : "right: 0"};
@@ -154,7 +155,7 @@ export const StyledViewerContainer = styled.div`
color: ${(props) => props.theme.mediaViewer.color};
display: ${(props) => (props.visible ? "block" : "none")};
overflow: hidden;
- span {
+ > span {
position: fixed;
${(props) =>
props.theme.interfaceDirection === "rtl"
diff --git a/packages/shared/components/media-viewer/sub-components/ImageViewer/ImageViewer.props.ts b/packages/shared/components/media-viewer/sub-components/ImageViewer/ImageViewer.props.ts
index 0281112bb9..6dcf2a90c9 100644
--- a/packages/shared/components/media-viewer/sub-components/ImageViewer/ImageViewer.props.ts
+++ b/packages/shared/components/media-viewer/sub-components/ImageViewer/ImageViewer.props.ts
@@ -39,6 +39,7 @@ interface ImageViewerProps {
isFistImage: boolean;
isLastImage: boolean;
panelVisible: boolean;
+ isPublicFile?: boolean;
mobileDetails: JSX.Element;
toolbar: ReturnType;
devices: DevicesType;
diff --git a/packages/shared/components/media-viewer/sub-components/ImageViewer/index.tsx b/packages/shared/components/media-viewer/sub-components/ImageViewer/index.tsx
index 7947ed0a20..756bdf930c 100644
--- a/packages/shared/components/media-viewer/sub-components/ImageViewer/index.tsx
+++ b/packages/shared/components/media-viewer/sub-components/ImageViewer/index.tsx
@@ -93,6 +93,7 @@ export const ImageViewer = ({
contextModel,
errorTitle,
devices,
+ isPublicFile,
}: ImageViewerProps) => {
const imgRef = useRef(null);
const imgWrapperRef = useRef(null);
@@ -523,7 +524,7 @@ export const ImageViewer = ({
: dx,
y: dy,
opacity:
- style.scale.get() === 1 && !isDesktop && mdy > 0
+ style.scale.get() === 1 && !isDesktop && mdy > 0 && !isPublicFile
? imgRef.current.height / 10 / mdy
: style.opacity.get(),
immediate: true,
@@ -541,7 +542,7 @@ export const ImageViewer = ({
cancel();
}
- if (style.scale.get() === 1 && !isDesktop) {
+ if (style.scale.get() === 1 && !isDesktop && !isPublicFile) {
if (mdx < -imgRef.current.width / 4) {
return onNext?.();
}
diff --git a/packages/shared/components/media-viewer/sub-components/Viewer/index.tsx b/packages/shared/components/media-viewer/sub-components/Viewer/index.tsx
index 1247fa83aa..c982ece042 100644
--- a/packages/shared/components/media-viewer/sub-components/Viewer/index.tsx
+++ b/packages/shared/components/media-viewer/sub-components/Viewer/index.tsx
@@ -33,7 +33,6 @@ import React, {
} from "react";
import { DeviceType } from "@docspace/shared/enums";
-import { Portal } from "@docspace/shared/components/portal";
import { includesMethod } from "@docspace/shared/utils/typeGuards";
import type { TContextMenuRef } from "@docspace/shared/components/context-menu";
@@ -251,91 +250,78 @@ export const Viewer = (props: ViewerProps) => {
)}
{isImage ? (
-
- }
+
) : isVideo || isAudio ? (
-
- }
+
) : (
isPdf && (
-
- }
+
)
)}
diff --git a/packages/shared/components/media-viewer/sub-components/ViewerToolbar/index.tsx b/packages/shared/components/media-viewer/sub-components/ViewerToolbar/index.tsx
index bda72d8010..5593aff92b 100644
--- a/packages/shared/components/media-viewer/sub-components/ViewerToolbar/index.tsx
+++ b/packages/shared/components/media-viewer/sub-components/ViewerToolbar/index.tsx
@@ -24,9 +24,17 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
-import React, { forwardRef, useImperativeHandle, useState } from "react";
+import React, {
+ forwardRef,
+ useImperativeHandle,
+ useRef,
+ useState,
+} from "react";
import MediaContextMenu from "PUBLIC_DIR/images/vertical-dots.react.svg";
+
+import { useClickOutside } from "../../../../utils/useClickOutside";
+
import ImageViewerToolbarProps, {
ImperativeHandle,
ToolbarItemType,
@@ -50,11 +58,17 @@ const ViewerToolbar = forwardRef(
},
ref,
) => {
+ const contextMenuRef = useRef(null);
+
const [isOpen, setIsOpen] = useState(false);
const [percent, setPercent] = useState(() =>
Math.round(percentValue * 100),
);
+ useClickOutside(contextMenuRef, () => {
+ setIsOpen(false);
+ });
+
useImperativeHandle(
ref,
() => {
@@ -71,6 +85,7 @@ const ViewerToolbar = forwardRef(
const contextMenu = generateContextMenu(isOpen);
return (
{
diff --git a/packages/shared/themes/base.ts b/packages/shared/themes/base.ts
index 6948ef9350..e719eb6d1e 100644
--- a/packages/shared/themes/base.ts
+++ b/packages/shared/themes/base.ts
@@ -2094,6 +2094,7 @@ export const getBaseTheme = () => {
borderColor: grayLightMid,
thumbnailBorderColor: grayLightMid,
textColor: black,
+ errorColor: "#F21C0E",
closeButtonWrapperPadding: "0px",
closeButtonIcon: white,
diff --git a/packages/shared/themes/dark.ts b/packages/shared/themes/dark.ts
index 3d7daf1ebb..13536754d9 100644
--- a/packages/shared/themes/dark.ts
+++ b/packages/shared/themes/dark.ts
@@ -2067,6 +2067,7 @@ const Dark: TTheme = {
borderColor: "#474747",
thumbnailBorderColor: grayLightMid,
textColor: white,
+ errorColor: "#E06451",
closeButtonWrapperPadding: "6px",
closeButtonIcon: black,
diff --git a/packages/shared/utils/next-ssr-helper.ts b/packages/shared/utils/next-ssr-helper.ts
index 13466f1a56..1a2a1a2e47 100644
--- a/packages/shared/utils/next-ssr-helper.ts
+++ b/packages/shared/utils/next-ssr-helper.ts
@@ -34,13 +34,17 @@ export const getBaseUrl = () => {
const host = hdrs.get("x-forwarded-host");
const proto = hdrs.get("x-forwarded-proto");
- const baseURL = `${proto}:${host}`;
+ const baseURL = `${proto}://${host}`;
return baseURL;
};
-export const getAPIUrl = () => {
- const baseUrl = process.env.API_HOST?.trim() ?? getBaseUrl();
+export const getAPIUrl = (internalRequest: boolean) => {
+ const baseUrl = internalRequest
+ ? process.env.API_HOST?.trim() ?? getBaseUrl()
+ : getBaseUrl();
+
+ // const baseUrl = getBaseUrl();
const baseAPIUrl = `${baseUrl}/${API_PREFIX}`;
@@ -52,18 +56,19 @@ export const createRequest = (
newHeaders: [string, string][],
method: string,
body?: string,
+ internalRequest: boolean = true,
) => {
const hdrs = new Headers(headers());
- const apiURL = getAPIUrl();
+ const apiURL = getAPIUrl(internalRequest);
newHeaders.forEach((hdr) => {
if (hdr[0]) hdrs.set(hdr[0], hdr[1]);
});
- const host = hdrs.get("x-forwarded-host");
+ const baseURL = getBaseUrl();
- if (host && process.env.API_HOST?.trim()) hdrs.set("origin", host);
+ if (baseURL && process.env.API_HOST?.trim()) hdrs.set("origin", baseURL);
const urls = paths.map((path) => `${apiURL}${path}`);
diff --git a/packages/shared/utils/useClickOutside.ts b/packages/shared/utils/useClickOutside.ts
index 11aa3d1cf9..558d137bde 100644
--- a/packages/shared/utils/useClickOutside.ts
+++ b/packages/shared/utils/useClickOutside.ts
@@ -28,12 +28,12 @@
"use client";
-import { useEffect } from "react";
+import { DependencyList, RefObject, useEffect } from "react";
-export const useClickOutside = (
- ref: { current: HTMLElement },
- handler: () => void,
- ...deps: unknown[]
+export const useClickOutside = (
+ ref: RefObject,
+ handler: VoidFunction,
+ ...deps: DependencyList
) => {
useEffect(() => {
const handleClickOutside = (e: MouseEvent) => {