From b2533b94ce37b85ed6e32a6c508637d3bd7a5090 Mon Sep 17 00:00:00 2001 From: Prateek Shourya Date: Thu, 12 Sep 2024 20:10:04 +0530 Subject: [PATCH] [WEB-2444] improvement: performance improvement for `useOutsideClickDetector` and `usePeekOverviewOutsideClickDetector`. (#5595) * [WEB-2444] improvement: performace improvement for `useOutsideClickDetector` and `usePeekOverviewOutsideClickDetector`. * Move outside click detector to plane helpers package. * chore: remove plane helpers yarn.lock --- admin/core/components/admin-sidebar/root.tsx | 9 ++-- .../core/hooks/use-outside-click-detector.tsx | 21 ---------- admin/next-env.d.ts | 2 +- admin/package.json | 1 + package.json | 3 +- packages/helpers/hooks/index.ts | 1 + .../hooks/use-outside-click-detector.tsx | 29 +++++++++++++ packages/helpers/index.ts | 1 + packages/helpers/package.json | 15 +++++++ packages/ui/package.json | 1 + packages/ui/src/dropdown/multi-select.tsx | 3 +- packages/ui/src/dropdown/single-select.tsx | 3 +- .../ui/src/dropdowns/context-menu/root.tsx | 3 +- packages/ui/src/dropdowns/custom-menu.tsx | 3 +- .../ui/src/dropdowns/custom-search-select.tsx | 3 +- packages/ui/src/dropdowns/custom-select.tsx | 3 +- .../ui/src/emoji/emoji-icon-picker-new.tsx | 3 +- packages/ui/src/emoji/emoji-icon-picker.tsx | 3 +- .../src/hooks/use-outside-click-detector.tsx | 42 ------------------- space/core/hooks/use-outside-click.tsx | 21 ---------- .../[workspaceSlug]/(projects)/sidebar.tsx | 3 +- web/app/profile/sidebar.tsx | 3 +- web/ce/components/issues/quick-add/root.tsx | 3 +- .../components/core/image-picker-popover.tsx | 3 +- .../cycles/archived-cycles/header.tsx | 3 +- .../components/cycles/cycles-view-header.tsx | 3 +- .../gantt-chart/sidebar/gantt-dnd-HOC.tsx | 2 +- .../calendar/issue-block-root.tsx | 3 +- .../issue-layouts/calendar/issue-block.tsx | 3 +- .../issues/issue-layouts/gantt/blocks.tsx | 1 + .../issues/issue-layouts/kanban/block.tsx | 4 +- .../issues/issue-layouts/list/block-root.tsx | 3 +- .../issue-layouts/properties/labels.tsx | 3 +- .../issue-layouts/spreadsheet/issue-row.tsx | 3 +- web/core/components/issues/select/label.tsx | 3 +- .../labels/label-block/label-item-block.tsx | 4 +- .../modules/archived-modules/header.tsx | 3 +- .../components/modules/module-view-header.tsx | 5 ++- .../components/pages/list/search-input.tsx | 4 +- web/core/components/profile/sidebar.tsx | 7 +--- web/core/components/project/header.tsx | 3 +- .../components/views/view-list-header.tsx | 3 +- .../sidebar/favorites/favorite-folder.tsx | 4 +- .../sidebar/favorites/favorite-items/root.tsx | 3 +- .../sidebar/favorites/new-fav-folder.tsx | 5 ++- .../workspace/sidebar/projects-list-item.tsx | 3 +- .../workspace/sidebar/workspace-menu.tsx | 3 +- web/core/hooks/use-dropdown.ts | 3 +- web/core/hooks/use-dynamic-dropdown.tsx | 5 +-- web/core/hooks/use-outside-click-detector.tsx | 42 ------------------- .../hooks/use-peek-overview-outside-click.tsx | 33 +++++++-------- web/core/store/user/index.ts | 2 +- web/package.json | 1 + 53 files changed, 148 insertions(+), 198 deletions(-) delete mode 100644 admin/core/hooks/use-outside-click-detector.tsx create mode 100644 packages/helpers/hooks/index.ts create mode 100644 packages/helpers/hooks/use-outside-click-detector.tsx create mode 100644 packages/helpers/index.ts create mode 100644 packages/helpers/package.json delete mode 100644 packages/ui/src/hooks/use-outside-click-detector.tsx delete mode 100644 space/core/hooks/use-outside-click.tsx delete mode 100644 web/core/hooks/use-outside-click-detector.tsx diff --git a/admin/core/components/admin-sidebar/root.tsx b/admin/core/components/admin-sidebar/root.tsx index c2a90daa37..a57132b708 100644 --- a/admin/core/components/admin-sidebar/root.tsx +++ b/admin/core/components/admin-sidebar/root.tsx @@ -2,11 +2,12 @@ import { FC, useEffect, useRef } from "react"; import { observer } from "mobx-react"; -// hooks -import { HelpSection, SidebarMenu, SidebarDropdown } from "@/components/admin-sidebar"; -import { useTheme } from "@/hooks/store"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // components +import { HelpSection, SidebarMenu, SidebarDropdown } from "@/components/admin-sidebar"; +// hooks +import { useTheme } from "@/hooks/store"; export interface IInstanceSidebar {} diff --git a/admin/core/hooks/use-outside-click-detector.tsx b/admin/core/hooks/use-outside-click-detector.tsx deleted file mode 100644 index b7b48c8579..0000000000 --- a/admin/core/hooks/use-outside-click-detector.tsx +++ /dev/null @@ -1,21 +0,0 @@ -"use client"; - -import React, { useEffect } from "react"; - -const useOutsideClickDetector = (ref: React.RefObject, callback: () => void) => { - const handleClick = (event: MouseEvent) => { - if (ref.current && !ref.current.contains(event.target as Node)) { - callback(); - } - }; - - useEffect(() => { - document.addEventListener("mousedown", handleClick); - - return () => { - document.removeEventListener("mousedown", handleClick); - }; - }); -}; - -export default useOutsideClickDetector; diff --git a/admin/next-env.d.ts b/admin/next-env.d.ts index 4f11a03dc6..40c3d68096 100644 --- a/admin/next-env.d.ts +++ b/admin/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. +// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information. diff --git a/admin/package.json b/admin/package.json index 44e5a3a6d9..0117ec86c0 100644 --- a/admin/package.json +++ b/admin/package.json @@ -15,6 +15,7 @@ "@plane/types": "*", "@plane/ui": "*", "@plane/constants": "*", + "@plane/helpers": "*", "@tailwindcss/typography": "^0.5.9", "@types/lodash": "^4.17.0", "autoprefixer": "10.4.14", diff --git a/package.json b/package.json index 337a3c84e4..43966637b1 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "packages/tsconfig", "packages/ui", "packages/types", - "packages/constants" + "packages/constants", + "packages/helpers" ], "scripts": { "build": "turbo run build", diff --git a/packages/helpers/hooks/index.ts b/packages/helpers/hooks/index.ts new file mode 100644 index 0000000000..c7a8f4c06b --- /dev/null +++ b/packages/helpers/hooks/index.ts @@ -0,0 +1 @@ +export * from "./use-outside-click-detector"; diff --git a/packages/helpers/hooks/use-outside-click-detector.tsx b/packages/helpers/hooks/use-outside-click-detector.tsx new file mode 100644 index 0000000000..0649cecfe0 --- /dev/null +++ b/packages/helpers/hooks/use-outside-click-detector.tsx @@ -0,0 +1,29 @@ +import React, { useEffect } from "react"; + +export const useOutsideClickDetector = ( + ref: React.RefObject, + callback: () => void, + useCapture = false +) => { + const handleClick = (event: MouseEvent) => { + if (ref.current && !ref.current.contains(event.target as Node)) { + // check for the closest element with attribute name data-prevent-outside-click + const preventOutsideClickElement = ( + event.target as HTMLElement | undefined + )?.closest("[data-prevent-outside-click]"); + // if the closest element with attribute name data-prevent-outside-click is found, return + if (preventOutsideClickElement) { + return; + } + // else call the callback + callback(); + } + }; + + useEffect(() => { + document.addEventListener("mousedown", handleClick, useCapture); + return () => { + document.removeEventListener("mousedown", handleClick, useCapture); + }; + }); +}; diff --git a/packages/helpers/index.ts b/packages/helpers/index.ts new file mode 100644 index 0000000000..007f69d09c --- /dev/null +++ b/packages/helpers/index.ts @@ -0,0 +1 @@ +export * from "./hooks"; diff --git a/packages/helpers/package.json b/packages/helpers/package.json new file mode 100644 index 0000000000..736459f982 --- /dev/null +++ b/packages/helpers/package.json @@ -0,0 +1,15 @@ +{ + "name": "@plane/helpers", + "version": "0.22.0", + "description": "Helper functions shared across multiple apps internally", + "main": "index.ts", + "private": true, + "devDependencies": { + "@types/node": "^22.5.4", + "@types/react": "^18.3.5", + "typescript": "^5.6.2" + }, + "dependencies": { + "react": "^18.3.1" + } +} diff --git a/packages/ui/package.json b/packages/ui/package.json index 7130590989..c5a1d279c1 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -26,6 +26,7 @@ "@blueprintjs/popover2": "^1.13.3", "@headlessui/react": "^1.7.3", "@popperjs/core": "^2.11.8", + "@plane/helpers": "*", "clsx": "^2.0.0", "emoji-picker-react": "^4.5.16", "lodash": "^4.17.21", diff --git a/packages/ui/src/dropdown/multi-select.tsx b/packages/ui/src/dropdown/multi-select.tsx index 3b51351173..b05630ee5c 100644 --- a/packages/ui/src/dropdown/multi-select.tsx +++ b/packages/ui/src/dropdown/multi-select.tsx @@ -4,12 +4,13 @@ import sortBy from "lodash/sortBy"; import { Combobox } from "@headlessui/react"; // popper-js import { usePopper } from "react-popper"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // components import { DropdownButton } from "./common"; import { DropdownOptions } from "./common/options"; // hooks import { useDropdownKeyPressed } from "../hooks/use-dropdown-key-pressed"; -import useOutsideClickDetector from "../hooks/use-outside-click-detector"; // helper import { cn } from "../../helpers"; // types diff --git a/packages/ui/src/dropdown/single-select.tsx b/packages/ui/src/dropdown/single-select.tsx index 06987e10ff..8ad8ecf190 100644 --- a/packages/ui/src/dropdown/single-select.tsx +++ b/packages/ui/src/dropdown/single-select.tsx @@ -4,12 +4,13 @@ import sortBy from "lodash/sortBy"; import { Combobox } from "@headlessui/react"; // popper-js import { usePopper } from "react-popper"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // components import { DropdownButton } from "./common"; import { DropdownOptions } from "./common/options"; // hooks import { useDropdownKeyPressed } from "../hooks/use-dropdown-key-pressed"; -import useOutsideClickDetector from "../hooks/use-outside-click-detector"; // helper import { cn } from "../../helpers"; // types diff --git a/packages/ui/src/dropdowns/context-menu/root.tsx b/packages/ui/src/dropdowns/context-menu/root.tsx index bea6189de1..03fe0cf7bc 100644 --- a/packages/ui/src/dropdowns/context-menu/root.tsx +++ b/packages/ui/src/dropdowns/context-menu/root.tsx @@ -1,11 +1,12 @@ import React, { useEffect, useRef, useState } from "react"; import ReactDOM from "react-dom"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // components import { ContextMenuItem } from "./item"; // helpers import { cn } from "../../../helpers"; // hooks -import useOutsideClickDetector from "../../hooks/use-outside-click-detector"; import { usePlatformOS } from "../../hooks/use-platform-os"; export type TContextMenuItem = { diff --git a/packages/ui/src/dropdowns/custom-menu.tsx b/packages/ui/src/dropdowns/custom-menu.tsx index a0be60a68e..274601822e 100644 --- a/packages/ui/src/dropdowns/custom-menu.tsx +++ b/packages/ui/src/dropdowns/custom-menu.tsx @@ -3,9 +3,10 @@ import ReactDOM from "react-dom"; import { Menu } from "@headlessui/react"; import { usePopper } from "react-popper"; import { ChevronDown, MoreHorizontal } from "lucide-react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // hooks import { useDropdownKeyDown } from "../hooks/use-dropdown-key-down"; -import useOutsideClickDetector from "../hooks/use-outside-click-detector"; // helpers import { cn } from "../../helpers"; // types diff --git a/packages/ui/src/dropdowns/custom-search-select.tsx b/packages/ui/src/dropdowns/custom-search-select.tsx index 255ab898ba..81d33df6ea 100644 --- a/packages/ui/src/dropdowns/custom-search-select.tsx +++ b/packages/ui/src/dropdowns/custom-search-select.tsx @@ -3,9 +3,10 @@ import { usePopper } from "react-popper"; import { Combobox } from "@headlessui/react"; import { Check, ChevronDown, Search } from "lucide-react"; import { createPortal } from "react-dom"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // hooks import { useDropdownKeyDown } from "../hooks/use-dropdown-key-down"; -import useOutsideClickDetector from "../hooks/use-outside-click-detector"; // helpers import { cn } from "../../helpers"; // types diff --git a/packages/ui/src/dropdowns/custom-select.tsx b/packages/ui/src/dropdowns/custom-select.tsx index 671991c846..7d73cdc047 100644 --- a/packages/ui/src/dropdowns/custom-select.tsx +++ b/packages/ui/src/dropdowns/custom-select.tsx @@ -2,9 +2,10 @@ import React, { useRef, useState } from "react"; import { usePopper } from "react-popper"; import { Listbox } from "@headlessui/react"; import { Check, ChevronDown } from "lucide-react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // hooks import { useDropdownKeyDown } from "../hooks/use-dropdown-key-down"; -import useOutsideClickDetector from "../hooks/use-outside-click-detector"; // helpers import { cn } from "../../helpers"; // types diff --git a/packages/ui/src/emoji/emoji-icon-picker-new.tsx b/packages/ui/src/emoji/emoji-icon-picker-new.tsx index 41ad696820..4a4c64eda1 100644 --- a/packages/ui/src/emoji/emoji-icon-picker-new.tsx +++ b/packages/ui/src/emoji/emoji-icon-picker-new.tsx @@ -2,10 +2,11 @@ import React, { useRef, useState } from "react"; import { usePopper } from "react-popper"; import { Popover, Tab } from "@headlessui/react"; import EmojiPicker from "emoji-picker-react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // helpers import { cn } from "../../helpers"; // hooks -import useOutsideClickDetector from "../hooks/use-outside-click-detector"; import { LucideIconsList } from "./lucide-icons-list"; // helpers import { EmojiIconPickerTypes, TABS_LIST, TCustomEmojiPicker } from "./emoji-icon-helper"; diff --git a/packages/ui/src/emoji/emoji-icon-picker.tsx b/packages/ui/src/emoji/emoji-icon-picker.tsx index ea3fcf0028..fa476cb5e3 100644 --- a/packages/ui/src/emoji/emoji-icon-picker.tsx +++ b/packages/ui/src/emoji/emoji-icon-picker.tsx @@ -2,12 +2,13 @@ import React, { useRef, useState } from "react"; import { usePopper } from "react-popper"; import EmojiPicker from "emoji-picker-react"; import { Popover, Tab } from "@headlessui/react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // components import { IconsList } from "./icons-list"; // helpers import { cn } from "../../helpers"; // hooks -import useOutsideClickDetector from "../hooks/use-outside-click-detector"; import { EmojiIconPickerTypes, TABS_LIST, TCustomEmojiPicker } from "./emoji-icon-helper"; export const CustomEmojiIconPicker: React.FC = (props) => { diff --git a/packages/ui/src/hooks/use-outside-click-detector.tsx b/packages/ui/src/hooks/use-outside-click-detector.tsx deleted file mode 100644 index 608b88df0a..0000000000 --- a/packages/ui/src/hooks/use-outside-click-detector.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React, { useEffect } from "react"; - -// TODO: move it to helpers package -const useOutsideClickDetector = (ref: React.RefObject, callback: () => void, useCapture = false) => { - const handleClick = (event: MouseEvent) => { - if (ref.current && !ref.current.contains(event.target as Node)) { - // get all the element with attribute name data-prevent-outside-click - const preventOutsideClickElements = document.querySelectorAll("[data-prevent-outside-click]"); - // check if the click target is any of the elements with attribute name data-prevent-outside-click - for (let i = 0; i < preventOutsideClickElements.length; i++) { - if (preventOutsideClickElements[i].contains(event.target as Node)) { - // if the click target is any of the elements with attribute name data-prevent-outside-click, return - return; - } - } - // get all the element with attribute name data-delay-outside-click - const delayOutsideClickElements = document.querySelectorAll("[data-delay-outside-click]"); - // check if the click target is any of the elements with attribute name data-delay-outside-click - for (let i = 0; i < delayOutsideClickElements.length; i++) { - if (delayOutsideClickElements[i].contains(event.target as Node)) { - // if the click target is any of the elements with attribute name data-delay-outside-click, delay the callback - setTimeout(() => { - callback(); - }, 1); - return; - } - } - // else, call the callback immediately - callback(); - } - }; - - useEffect(() => { - document.addEventListener("mousedown", handleClick, useCapture); - - return () => { - document.removeEventListener("mousedown", handleClick, useCapture); - }; - }); -}; - -export default useOutsideClickDetector; diff --git a/space/core/hooks/use-outside-click.tsx b/space/core/hooks/use-outside-click.tsx deleted file mode 100644 index f2bed415f7..0000000000 --- a/space/core/hooks/use-outside-click.tsx +++ /dev/null @@ -1,21 +0,0 @@ -"use client"; - -import { useEffect } from "react"; - -const useOutSideClick = (ref: any, callback: any) => { - const handleClick = (e: any) => { - if (ref.current && !ref.current.contains(e.target)) { - callback(); - } - }; - - useEffect(() => { - document.addEventListener("click", handleClick); - - return () => { - document.removeEventListener("click", handleClick); - }; - }); -}; - -export default useOutSideClick; diff --git a/web/app/[workspaceSlug]/(projects)/sidebar.tsx b/web/app/[workspaceSlug]/(projects)/sidebar.tsx index c6ea85f310..c5234b1993 100644 --- a/web/app/[workspaceSlug]/(projects)/sidebar.tsx +++ b/web/app/[workspaceSlug]/(projects)/sidebar.tsx @@ -1,5 +1,7 @@ import { FC, useEffect, useRef } from "react"; import { observer } from "mobx-react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // components import { SidebarDropdown, @@ -14,7 +16,6 @@ import { SidebarFavoritesMenu } from "@/components/workspace/sidebar/favorites/f import { cn } from "@/helpers/common.helper"; // hooks import { useAppTheme, useUserPermissions } from "@/hooks/store"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; // plane web components import useSize from "@/hooks/use-window-size"; import { SidebarAppSwitcher } from "@/plane-web/components/sidebar"; diff --git a/web/app/profile/sidebar.tsx b/web/app/profile/sidebar.tsx index c638d52fff..adb06863d5 100644 --- a/web/app/profile/sidebar.tsx +++ b/web/app/profile/sidebar.tsx @@ -6,6 +6,8 @@ import Link from "next/link"; import { usePathname } from "next/navigation"; // icons import { ChevronLeft, LogOut, MoveLeft, Plus, UserPlus } from "lucide-react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // ui import { TOAST_TYPE, Tooltip, setToast } from "@plane/ui"; // components @@ -16,7 +18,6 @@ import { PROFILE_ACTION_LINKS } from "@/constants/profile"; import { cn } from "@/helpers/common.helper"; // hooks import { useAppTheme, useUser, useUserSettings, useWorkspace } from "@/hooks/store"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; import { usePlatformOS } from "@/hooks/use-platform-os"; const WORKSPACE_ACTION_LINKS = [ diff --git a/web/ce/components/issues/quick-add/root.tsx b/web/ce/components/issues/quick-add/root.tsx index 8ca22c3862..51880a6ba1 100644 --- a/web/ce/components/issues/quick-add/root.tsx +++ b/web/ce/components/issues/quick-add/root.tsx @@ -1,6 +1,8 @@ import { FC, useEffect, useRef } from "react"; import { observer } from "mobx-react"; import { UseFormRegister, UseFormSetFocus } from "react-hook-form"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // types import { TIssue } from "@plane/types"; // components @@ -17,7 +19,6 @@ import { EIssueLayoutTypes } from "@/constants/issue"; // hooks import { useProject } from "@/hooks/store"; import useKeypress from "@/hooks/use-keypress"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; export type TQuickAddIssueFormRoot = { isOpen: boolean; diff --git a/web/core/components/core/image-picker-popover.tsx b/web/core/components/core/image-picker-popover.tsx index 5edcecdcfa..db94619913 100644 --- a/web/core/components/core/image-picker-popover.tsx +++ b/web/core/components/core/image-picker-popover.tsx @@ -9,6 +9,8 @@ import { Control, Controller } from "react-hook-form"; import useSWR from "swr"; // headless ui import { Tab, Popover } from "@headlessui/react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // ui import { Button, Input, Loader } from "@plane/ui"; // constants @@ -16,7 +18,6 @@ import { MAX_FILE_SIZE } from "@/constants/common"; // hooks import { useWorkspace, useInstance } from "@/hooks/store"; import { useDropdownKeyDown } from "@/hooks/use-dropdown-key-down"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; // services import { FileService } from "@/services/file.service"; diff --git a/web/core/components/cycles/archived-cycles/header.tsx b/web/core/components/cycles/archived-cycles/header.tsx index b3848a4379..42485fcef4 100644 --- a/web/core/components/cycles/archived-cycles/header.tsx +++ b/web/core/components/cycles/archived-cycles/header.tsx @@ -3,6 +3,8 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // icons import { ListFilter, Search, X } from "lucide-react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // types import type { TCycleFilters } from "@plane/types"; // components @@ -14,7 +16,6 @@ import { cn } from "@/helpers/common.helper"; import { calculateTotalFilters } from "@/helpers/filter.helper"; // hooks import { useCycleFilter } from "@/hooks/store"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; export const ArchivedCyclesHeader: FC = observer(() => { // router diff --git a/web/core/components/cycles/cycles-view-header.tsx b/web/core/components/cycles/cycles-view-header.tsx index 5fe815a791..f1398cd3bf 100644 --- a/web/core/components/cycles/cycles-view-header.tsx +++ b/web/core/components/cycles/cycles-view-header.tsx @@ -2,6 +2,8 @@ import { useCallback, useEffect, useRef, useState } from "react"; import { observer } from "mobx-react"; // icons import { ListFilter, Search, X } from "lucide-react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // types import { TCycleFilters } from "@plane/types"; // components @@ -12,7 +14,6 @@ import { cn } from "@/helpers/common.helper"; import { calculateTotalFilters } from "@/helpers/filter.helper"; // hooks import { useCycleFilter } from "@/hooks/store"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; type Props = { projectId: string; diff --git a/web/core/components/gantt-chart/sidebar/gantt-dnd-HOC.tsx b/web/core/components/gantt-chart/sidebar/gantt-dnd-HOC.tsx index 4e9ee71938..79506ef4ec 100644 --- a/web/core/components/gantt-chart/sidebar/gantt-dnd-HOC.tsx +++ b/web/core/components/gantt-chart/sidebar/gantt-dnd-HOC.tsx @@ -5,9 +5,9 @@ import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine"; import { draggable, dropTargetForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter"; import { attachInstruction, extractInstruction } from "@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item"; import { observer } from "mobx-react"; +import { useOutsideClickDetector } from "@plane/helpers"; import { DropIndicator, TOAST_TYPE, setToast } from "@plane/ui"; import { HIGHLIGHT_WITH_LINE, highlightIssueOnDrop } from "@/components/issues/issue-layouts/utils"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; type Props = { id: string; diff --git a/web/core/components/issues/issue-layouts/calendar/issue-block-root.tsx b/web/core/components/issues/issue-layouts/calendar/issue-block-root.tsx index 6826f81961..6c3a69bfc9 100644 --- a/web/core/components/issues/issue-layouts/calendar/issue-block-root.tsx +++ b/web/core/components/issues/issue-layouts/calendar/issue-block-root.tsx @@ -2,10 +2,11 @@ import React, { useEffect, useRef, useState } from "react"; import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine"; import { draggable } from "@atlaskit/pragmatic-drag-and-drop/element/adapter"; import { observer } from "mobx-react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // components import { CalendarIssueBlock } from "@/components/issues"; import { useIssueDetail } from "@/hooks/store"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; import { TRenderQuickActions } from "../list/list-view-types"; import { HIGHLIGHT_CLASS } from "../utils"; // types diff --git a/web/core/components/issues/issue-layouts/calendar/issue-block.tsx b/web/core/components/issues/issue-layouts/calendar/issue-block.tsx index fd3e7a46fb..db4d8caacf 100644 --- a/web/core/components/issues/issue-layouts/calendar/issue-block.tsx +++ b/web/core/components/issues/issue-layouts/calendar/issue-block.tsx @@ -5,6 +5,8 @@ import { useState, useRef, forwardRef } from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { MoreHorizontal } from "lucide-react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // types import { TIssue } from "@plane/types"; // ui @@ -15,7 +17,6 @@ import { cn } from "@/helpers/common.helper"; import { useIssueDetail, useIssues, useProjectState } from "@/hooks/store"; import { useIssueStoreType } from "@/hooks/use-issue-layout-store"; import useIssuePeekOverviewRedirection from "@/hooks/use-issue-peek-overview-redirection"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; import { usePlatformOS } from "@/hooks/use-platform-os"; // plane web components import { IssueIdentifier } from "@/plane-web/components/issues/issue-details"; diff --git a/web/core/components/issues/issue-layouts/gantt/blocks.tsx b/web/core/components/issues/issue-layouts/gantt/blocks.tsx index 438797db63..5ffd2b3815 100644 --- a/web/core/components/issues/issue-layouts/gantt/blocks.tsx +++ b/web/core/components/issues/issue-layouts/gantt/blocks.tsx @@ -96,6 +96,7 @@ export const IssueGanttSidebarBlock: React.FC = observer((props) => { return ( = observer((props) => { <>
{ diff --git a/web/core/components/issues/issue-layouts/list/block-root.tsx b/web/core/components/issues/issue-layouts/list/block-root.tsx index 71bcc6f15c..6401fcb5e3 100644 --- a/web/core/components/issues/issue-layouts/list/block-root.tsx +++ b/web/core/components/issues/issue-layouts/list/block-root.tsx @@ -5,6 +5,8 @@ import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine"; import { dropTargetForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter"; import { attachInstruction, extractInstruction } from "@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item"; import { observer } from "mobx-react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // types import { IIssueDisplayProperties, TIssue, TIssueMap } from "@plane/types"; // components @@ -14,7 +16,6 @@ import { IssueBlock } from "@/components/issues/issue-layouts/list"; // hooks import { useIssueDetail } from "@/hooks/store"; import { TSelectionHelper } from "@/hooks/use-multiple-select"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; // types import { HIGHLIGHT_CLASS, getIssueBlockId, isIssueNew } from "../utils"; import { TRenderQuickActions } from "./list-view-types"; diff --git a/web/core/components/issues/issue-layouts/properties/labels.tsx b/web/core/components/issues/issue-layouts/properties/labels.tsx index 4b241bfe2d..29cd54926d 100644 --- a/web/core/components/issues/issue-layouts/properties/labels.tsx +++ b/web/core/components/issues/issue-layouts/properties/labels.tsx @@ -7,6 +7,8 @@ import { useParams } from "next/navigation"; import { usePopper } from "react-popper"; import { Check, ChevronDown, Search, Tags } from "lucide-react"; import { Combobox } from "@headlessui/react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // types import { IIssueLabel } from "@plane/types"; // ui @@ -14,7 +16,6 @@ import { ComboDropDown, Tooltip } from "@plane/ui"; // hooks import { useLabel } from "@/hooks/store"; import { useDropdownKeyDown } from "@/hooks/use-dropdown-key-down"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; import { usePlatformOS } from "@/hooks/use-platform-os"; export interface IIssuePropertyLabels { diff --git a/web/core/components/issues/issue-layouts/spreadsheet/issue-row.tsx b/web/core/components/issues/issue-layouts/spreadsheet/issue-row.tsx index ee59ab861f..ef6a34d1ac 100644 --- a/web/core/components/issues/issue-layouts/spreadsheet/issue-row.tsx +++ b/web/core/components/issues/issue-layouts/spreadsheet/issue-row.tsx @@ -4,6 +4,8 @@ import { Dispatch, MouseEvent, MutableRefObject, SetStateAction, useRef, useStat import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { ChevronRight, MoreHorizontal } from "lucide-react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // types import { IIssueDisplayProperties, TIssue } from "@plane/types"; // ui @@ -19,7 +21,6 @@ import { cn } from "@/helpers/common.helper"; import { useIssueDetail, useProject } from "@/hooks/store"; import useIssuePeekOverviewRedirection from "@/hooks/use-issue-peek-overview-redirection"; import { TSelectionHelper } from "@/hooks/use-multiple-select"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; import { usePlatformOS } from "@/hooks/use-platform-os"; // plane web components import { IssueIdentifier } from "@/plane-web/components/issues"; diff --git a/web/core/components/issues/select/label.tsx b/web/core/components/issues/select/label.tsx index 44525b9d62..b5e5643825 100644 --- a/web/core/components/issues/select/label.tsx +++ b/web/core/components/issues/select/label.tsx @@ -4,6 +4,8 @@ import { useParams } from "next/navigation"; import { usePopper } from "react-popper"; import { Check, Component, Plus, Search, Tag } from "lucide-react"; import { Combobox } from "@headlessui/react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // components import { IssueLabelsList } from "@/components/ui"; // helpers @@ -11,7 +13,6 @@ import { cn } from "@/helpers/common.helper"; // hooks import { useLabel } from "@/hooks/store"; import { useDropdownKeyDown } from "@/hooks/use-dropdown-key-down"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; import { usePlatformOS } from "@/hooks/use-platform-os"; type Props = { diff --git a/web/core/components/labels/label-block/label-item-block.tsx b/web/core/components/labels/label-block/label-item-block.tsx index 12a263a743..7771c82cc0 100644 --- a/web/core/components/labels/label-block/label-item-block.tsx +++ b/web/core/components/labels/label-block/label-item-block.tsx @@ -2,14 +2,14 @@ import { MutableRefObject, useRef, useState } from "react"; import { LucideIcon, X } from "lucide-react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // types import { IIssueLabel } from "@plane/types"; // ui import { CustomMenu, DragHandle } from "@plane/ui"; // helpers import { cn } from "@/helpers/common.helper"; -// hooks -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; // components import { LabelName } from "./label-name"; diff --git a/web/core/components/modules/archived-modules/header.tsx b/web/core/components/modules/archived-modules/header.tsx index 36f2179d14..5a15687a27 100644 --- a/web/core/components/modules/archived-modules/header.tsx +++ b/web/core/components/modules/archived-modules/header.tsx @@ -3,6 +3,8 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // icons import { ListFilter, Search, X } from "lucide-react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // types import type { TModuleFilters } from "@plane/types"; // components @@ -14,7 +16,6 @@ import { cn } from "@/helpers/common.helper"; import { calculateTotalFilters } from "@/helpers/filter.helper"; // hooks import { useMember, useModuleFilter } from "@/hooks/store"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; export const ArchivedModulesHeader: FC = observer(() => { // router diff --git a/web/core/components/modules/module-view-header.tsx b/web/core/components/modules/module-view-header.tsx index 3038f0bc7a..38c5a1b04a 100644 --- a/web/core/components/modules/module-view-header.tsx +++ b/web/core/components/modules/module-view-header.tsx @@ -5,8 +5,10 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // icons import { ListFilter, Search, X } from "lucide-react"; -// helpers +// editor import { cn } from "@plane/editor"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // types import { TModuleFilters } from "@plane/types"; // ui @@ -20,7 +22,6 @@ import { MODULE_VIEW_LAYOUTS } from "@/constants/module"; import { calculateTotalFilters } from "@/helpers/filter.helper"; // hooks import { useMember, useModuleFilter } from "@/hooks/store"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; import { usePlatformOS } from "@/hooks/use-platform-os"; export const ModuleViewHeader: FC = observer(() => { diff --git a/web/core/components/pages/list/search-input.tsx b/web/core/components/pages/list/search-input.tsx index 8f677405bf..412bae7c61 100644 --- a/web/core/components/pages/list/search-input.tsx +++ b/web/core/components/pages/list/search-input.tsx @@ -1,9 +1,9 @@ import { FC, useState, useRef, useEffect } from "react"; import { Search, X } from "lucide-react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // helpers import { cn } from "@/helpers/common.helper"; -// hooks -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; type Props = { searchQuery: string; diff --git a/web/core/components/profile/sidebar.tsx b/web/core/components/profile/sidebar.tsx index 4df6ac5ef4..319bb03bf0 100644 --- a/web/core/components/profile/sidebar.tsx +++ b/web/core/components/profile/sidebar.tsx @@ -8,26 +8,23 @@ import { useParams } from "next/navigation"; import { ChevronDown, Pencil } from "lucide-react"; // headless ui import { Disclosure, Transition } from "@headlessui/react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // types import { IUserProfileProjectSegregation } from "@plane/types"; // plane ui import { Loader, Tooltip } from "@plane/ui"; // components import { Logo } from "@/components/common"; -// fetch-keys // helpers import { cn } from "@/helpers/common.helper"; import { renderFormattedDate } from "@/helpers/date-time.helper"; // hooks import { useAppTheme, useProject, useUser } from "@/hooks/store"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; import { usePlatformOS } from "@/hooks/use-platform-os"; -// services // components import { ProfileSidebarTime } from "./time"; -// services - type TProfileSidebar = { userProjectsData: IUserProfileProjectSegregation | undefined; className?: string; diff --git a/web/core/components/project/header.tsx b/web/core/components/project/header.tsx index 302d3d4053..332e58af92 100644 --- a/web/core/components/project/header.tsx +++ b/web/core/components/project/header.tsx @@ -4,6 +4,8 @@ import { useEffect, useRef, useState } from "react"; import { observer } from "mobx-react"; import { usePathname } from "next/navigation"; import { Search, Briefcase, X } from "lucide-react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // ui import { Breadcrumbs, Button, Header } from "@plane/ui"; // components @@ -12,7 +14,6 @@ import { BreadcrumbLink } from "@/components/common"; import { cn } from "@/helpers/common.helper"; // hooks import { useCommandPalette, useEventTracker, useProjectFilter, useUserPermissions } from "@/hooks/store"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/user-permissions"; import HeaderFilters from "./filters"; diff --git a/web/core/components/views/view-list-header.tsx b/web/core/components/views/view-list-header.tsx index a055b45735..78d235ba97 100644 --- a/web/core/components/views/view-list-header.tsx +++ b/web/core/components/views/view-list-header.tsx @@ -2,11 +2,12 @@ import React, { useEffect, useRef, useState } from "react"; import { observer } from "mobx-react"; // icons import { ListFilter, Search, X } from "lucide-react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // helpers import { cn } from "@/helpers/common.helper"; // hooks import { useMember, useProjectView } from "@/hooks/store"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; import { FiltersDropdown } from "../issues"; import { ViewFiltersSelection } from "./filters/filter-selection"; import { ViewOrderByDropdown } from "./filters/order-by"; diff --git a/web/core/components/workspace/sidebar/favorites/favorite-folder.tsx b/web/core/components/workspace/sidebar/favorites/favorite-folder.tsx index 4921506be8..70dd006cb7 100644 --- a/web/core/components/workspace/sidebar/favorites/favorite-folder.tsx +++ b/web/core/components/workspace/sidebar/favorites/favorite-folder.tsx @@ -9,16 +9,16 @@ import uniqBy from "lodash/uniqBy"; import { useParams } from "next/navigation"; import { PenSquare, Star, MoreHorizontal, ChevronRight, GripVertical } from "lucide-react"; import { Disclosure, Transition } from "@headlessui/react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // ui import { IFavorite } from "@plane/types"; import { CustomMenu, Tooltip, DropIndicator, setToast, TOAST_TYPE, FavoriteFolderIcon, DragHandle } from "@plane/ui"; - // helpers import { cn } from "@/helpers/common.helper"; // hooks import { useAppTheme } from "@/hooks/store"; import { useFavorite } from "@/hooks/store/use-favorite"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; import { usePlatformOS } from "@/hooks/use-platform-os"; // constants import { FavoriteRoot } from "./favorite-items"; diff --git a/web/core/components/workspace/sidebar/favorites/favorite-items/root.tsx b/web/core/components/workspace/sidebar/favorites/favorite-items/root.tsx index cb9449f94e..84f66c0a71 100644 --- a/web/core/components/workspace/sidebar/favorites/favorite-items/root.tsx +++ b/web/core/components/workspace/sidebar/favorites/favorite-items/root.tsx @@ -4,6 +4,8 @@ import React, { FC, useEffect, useRef, useState } from "react"; import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine"; import { draggable, dropTargetForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter"; import { observer } from "mobx-react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // ui import { IFavorite } from "@plane/types"; // components @@ -16,7 +18,6 @@ import { // hooks import { useAppTheme } from "@/hooks/store"; import { useFavoriteItemDetails } from "@/hooks/use-favorite-item-details"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; type Props = { workspaceSlug: string; diff --git a/web/core/components/workspace/sidebar/favorites/new-fav-folder.tsx b/web/core/components/workspace/sidebar/favorites/new-fav-folder.tsx index f326804a32..1b95ba3a04 100644 --- a/web/core/components/workspace/sidebar/favorites/new-fav-folder.tsx +++ b/web/core/components/workspace/sidebar/favorites/new-fav-folder.tsx @@ -2,9 +2,12 @@ import { useEffect, useRef } from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { Controller, SubmitHandler, useForm } from "react-hook-form"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; +// plane ui import { FavoriteFolderIcon, Input, setToast, TOAST_TYPE } from "@plane/ui"; +// hooks import { useFavorite } from "@/hooks/store/use-favorite"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; type TForm = { name: string; diff --git a/web/core/components/workspace/sidebar/projects-list-item.tsx b/web/core/components/workspace/sidebar/projects-list-item.tsx index 42c6d10d4d..a512b9f33c 100644 --- a/web/core/components/workspace/sidebar/projects-list-item.tsx +++ b/web/core/components/workspace/sidebar/projects-list-item.tsx @@ -23,6 +23,8 @@ import { Layers, } from "lucide-react"; import { Disclosure, Transition } from "@headlessui/react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // ui import { CustomMenu, @@ -45,7 +47,6 @@ import { SidebarNavItem } from "@/components/sidebar"; import { cn } from "@/helpers/common.helper"; // hooks import { useAppTheme, useEventTracker, useProject, useUserPermissions } from "@/hooks/store"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; import { usePlatformOS } from "@/hooks/use-platform-os"; // constants import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/user-permissions"; diff --git a/web/core/components/workspace/sidebar/workspace-menu.tsx b/web/core/components/workspace/sidebar/workspace-menu.tsx index 8766fd09dd..62cf672cfe 100644 --- a/web/core/components/workspace/sidebar/workspace-menu.tsx +++ b/web/core/components/workspace/sidebar/workspace-menu.tsx @@ -6,6 +6,8 @@ import Link from "next/link"; import { useParams, usePathname } from "next/navigation"; import { ArchiveIcon, ChevronRight, MoreHorizontal, Settings } from "lucide-react"; import { Disclosure, Transition } from "@headlessui/react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // ui import { CustomMenu, Tooltip } from "@plane/ui"; // components @@ -18,7 +20,6 @@ import { cn } from "@/helpers/common.helper"; // hooks import { useAppTheme, useEventTracker, useUserPermissions } from "@/hooks/store"; import useLocalStorage from "@/hooks/use-local-storage"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; import { usePlatformOS } from "@/hooks/use-platform-os"; // plane web components import { UpgradeBadge } from "@/plane-web/components/workspace"; diff --git a/web/core/hooks/use-dropdown.ts b/web/core/hooks/use-dropdown.ts index fa851a4925..5877f7c752 100644 --- a/web/core/hooks/use-dropdown.ts +++ b/web/core/hooks/use-dropdown.ts @@ -1,7 +1,8 @@ import { useEffect } from "react"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; // hooks import { useDropdownKeyDown } from "@/hooks/use-dropdown-key-down"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; import { usePlatformOS } from "./use-platform-os"; type TArguments = { diff --git a/web/core/hooks/use-dynamic-dropdown.tsx b/web/core/hooks/use-dynamic-dropdown.tsx index 7bee1bd0ce..1a694225da 100644 --- a/web/core/hooks/use-dynamic-dropdown.tsx +++ b/web/core/hooks/use-dynamic-dropdown.tsx @@ -1,7 +1,6 @@ import React, { useCallback, useEffect } from "react"; - -// hook -import useOutsideClickDetector from "./use-outside-click-detector"; +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; /** * Custom hook for dynamic dropdown position calculation. diff --git a/web/core/hooks/use-outside-click-detector.tsx b/web/core/hooks/use-outside-click-detector.tsx deleted file mode 100644 index c1a4778037..0000000000 --- a/web/core/hooks/use-outside-click-detector.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React, { useEffect } from "react"; - -// TODO: move it to helpers package -const useOutsideClickDetector = (ref: React.RefObject, callback: () => void) => { - const handleClick = (event: MouseEvent) => { - if (ref.current && !ref.current.contains(event.target as Node)) { - // get all the element with attribute name data-prevent-outside-click - const preventOutsideClickElements = document.querySelectorAll("[data-prevent-outside-click]"); - // check if the click target is any of the elements with attribute name data-prevent-outside-click - for (let i = 0; i < preventOutsideClickElements.length; i++) { - if (preventOutsideClickElements[i].contains(event.target as Node)) { - // if the click target is any of the elements with attribute name data-prevent-outside-click, return - return; - } - } - // get all the element with attribute name data-delay-outside-click - const delayOutsideClickElements = document.querySelectorAll("[data-delay-outside-click]"); - // check if the click target is any of the elements with attribute name data-delay-outside-click - for (let i = 0; i < delayOutsideClickElements.length; i++) { - if (delayOutsideClickElements[i].contains(event.target as Node)) { - // if the click target is any of the elements with attribute name data-delay-outside-click, delay the callback - setTimeout(() => { - callback(); - }, 1); - return; - } - } - // else, call the callback immediately - callback(); - } - }; - - useEffect(() => { - document.addEventListener("mousedown", handleClick); - - return () => { - document.removeEventListener("mousedown", handleClick); - }; - }); -}; - -export default useOutsideClickDetector; diff --git a/web/core/hooks/use-peek-overview-outside-click.tsx b/web/core/hooks/use-peek-overview-outside-click.tsx index d8c198ca2e..65742f816c 100644 --- a/web/core/hooks/use-peek-overview-outside-click.tsx +++ b/web/core/hooks/use-peek-overview-outside-click.tsx @@ -7,14 +7,13 @@ const usePeekOverviewOutsideClickDetector = ( ) => { const handleClick = (event: MouseEvent) => { if (ref.current && !ref.current.contains(event.target as Node)) { - // get all the element with attribute name data-prevent-outside-click - const preventOutsideClickElements = document.querySelectorAll("[data-prevent-outside-click]"); - // check if the click target is any of the elements with attribute name data-prevent-outside-click - for (let i = 0; i < preventOutsideClickElements.length; i++) { - if (preventOutsideClickElements[i].contains(event.target as Node)) { - // if the click target is any of the elements with attribute name data-prevent-outside-click, return - return; - } + // check for the closest element with attribute name data-prevent-outside-click + const preventOutsideClickElement = (event.target as HTMLElement | undefined)?.closest( + "[data-prevent-outside-click]" + ); + // if the closest element with attribute name data-prevent-outside-click is found, return + if (preventOutsideClickElement) { + return; } // check if the click target is the current issue element or its children let targetElement = event.target as HTMLElement | null; @@ -25,17 +24,13 @@ const usePeekOverviewOutsideClickDetector = ( } targetElement = targetElement.parentElement; } - // get all the element with attribute name data-prevent-outside-click - const delayOutsideClickElements = document.querySelectorAll("[data-delay-outside-click]"); - // check if the click target is any of the elements with attribute name data-delay-outside-click - for (let i = 0; i < delayOutsideClickElements.length; i++) { - if (delayOutsideClickElements[i].contains(event.target as Node)) { - // if the click target is any of the elements with attribute name data-delay-outside-click, delay the callback - setTimeout(() => { - callback(); - }, 1); - return; - } + const delayOutsideClickElement = (event.target as HTMLElement | undefined)?.closest("[data-delay-outside-click]"); + if (delayOutsideClickElement) { + // if the click target is the closest element with attribute name data-delay-outside-click, delay the callback + setTimeout(() => { + callback(); + }, 0); + return; } // else, call the callback immediately callback(); diff --git a/web/core/store/user/index.ts b/web/core/store/user/index.ts index dee239c38d..fa78c4ccc6 100644 --- a/web/core/store/user/index.ts +++ b/web/core/store/user/index.ts @@ -3,6 +3,7 @@ import set from "lodash/set"; import { action, makeObservable, observable, runInAction, computed } from "mobx"; // types import { IUser } from "@plane/types"; +import { TUserPermissions } from "@plane/types/src/enums"; // constants // helpers import { API_BASE_URL } from "@/helpers/common.helper"; @@ -16,7 +17,6 @@ import { IAccountStore } from "@/store/user/account.store"; import { ProfileStore, IUserProfileStore } from "@/store/user/profile.store"; import { IUserPermissionStore, UserPermissionStore } from "./permissions.store"; import { IUserSettingsStore, UserSettingsStore } from "./settings.store"; -import { TUserPermissions } from "@plane/types/src/enums"; type TUserErrorStatus = { status: string; diff --git a/web/package.json b/web/package.json index abb529781c..bb3c946638 100644 --- a/web/package.json +++ b/web/package.json @@ -27,6 +27,7 @@ "@nivo/scatterplot": "0.80.0", "@plane/constants": "*", "@plane/editor": "*", + "@plane/helpers": "*", "@plane/types": "*", "@plane/ui": "*", "@popperjs/core": "^2.11.8",