From 06c39e7c1ca6b4ed8574dd34d01d6a92db10a96b Mon Sep 17 00:00:00 2001 From: Prateek Shourya Date: Thu, 12 Sep 2024 17:32:33 +0530 Subject: [PATCH 1/2] [WEB-2444] improvement: performace improvement for `useOutsideClickDetector` and `usePeekOverviewOutsideClickDetector`. * Move outside click detector to plane helpers package. --- admin/core/components/admin-sidebar/root.tsx | 7 ++- .../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/helpers/yarn.lock | 57 +++++++++++++++++++ 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 + 54 files changed, 204 insertions(+), 197 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 create mode 100644 packages/helpers/yarn.lock 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 c2a90daa377..a57132b7085 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 +// plane helpers +import { useOutsideClickDetector } from "@plane/helpers"; +// components import { HelpSection, SidebarMenu, SidebarDropdown } from "@/components/admin-sidebar"; +// hooks import { useTheme } from "@/hooks/store"; -import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; -// components 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 b7b48c8579a..00000000000 --- 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 4f11a03dc6c..40c3d68096c 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 44e5a3a6d92..0117ec86c0b 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 337a3c84e4f..43966637b10 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 00000000000..c7a8f4c06b8 --- /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 00000000000..0649cecfe01 --- /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 00000000000..007f69d09c5 --- /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 00000000000..736459f9824 --- /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/helpers/yarn.lock b/packages/helpers/yarn.lock new file mode 100644 index 00000000000..d4465e64598 --- /dev/null +++ b/packages/helpers/yarn.lock @@ -0,0 +1,57 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@types/node@^22.5.4": + version "22.5.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.5.4.tgz#83f7d1f65bc2ed223bdbf57c7884f1d5a4fa84e8" + integrity sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg== + dependencies: + undici-types "~6.19.2" + +"@types/prop-types@*": + version "15.7.12" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6" + integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q== + +"@types/react@^18.3.5": + version "18.3.5" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.5.tgz#5f524c2ad2089c0ff372bbdabc77ca2c4dbadf8f" + integrity sha512-WeqMfGJLGuLCqHGYRGHxnKrXcTitc6L/nBUWfWPcTarG3t9PsquqUMuVeXZeca+mglY4Vo5GZjCi0A3Or2lnxA== + dependencies: + "@types/prop-types" "*" + csstype "^3.0.2" + +csstype@^3.0.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" + integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== + +"js-tokens@^3.0.0 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +loose-envify@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +react@^18.3.1: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" + integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== + dependencies: + loose-envify "^1.1.0" + +typescript@^5.6.2: + version "5.6.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.2.tgz#d1de67b6bef77c41823f822df8f0b3bcff60a5a0" + integrity sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw== + +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== diff --git a/packages/ui/package.json b/packages/ui/package.json index 7130590989f..c5a1d279c1a 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 3b51351173b..b05630ee5c2 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 06987e10ff5..8ad8ecf1907 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 bea6189de12..03fe0cf7bc5 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 a0be60a68e1..274601822ea 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 255ab898baf..81d33df6eaa 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 671991c8467..7d73cdc0475 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 41ad6968208..4a4c64eda1c 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 ea3fcf00288..fa476cb5e33 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 608b88df0aa..00000000000 --- 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 f2bed415f77..00000000000 --- 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 c6ea85f310d..c5234b19934 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 c638d52fff2..adb06863d52 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 8ca22c3862c..51880a6ba1b 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 5edcecdcfa4..db946199135 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 b3848a4379e..42485fcef4e 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 5fe815a7912..f1398cd3bf9 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 4e9ee719385..79506ef4ecf 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 6826f81961c..6c3a69bfc94 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 fd3e7a46fbb..db4d8caacfa 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 438797db63b..5ffd2b3815a 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 71bcc6f15c9..6401fcb5e37 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 4b241bfe2d1..29cd54926d4 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 ee59ab861fd..ef6a34d1acc 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 ec2905770a9..9fefe7c84dd 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 564481dc8ba..02109563362 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 36f2179d140..5a15687a27a 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 3038f0bc7aa..38c5a1b04ac 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 8f677405bfe..412bae7c614 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 4df6ac5ef41..319bb03bf0a 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 302d3d40537..332e58af927 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 a055b457359..78d235ba97c 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 4921506be86..70dd006cb76 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 cb9449f94ea..84f66c0a718 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 f326804a329..1b95ba3a041 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 42c6d10d4de..a512b9f33c7 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 8766fd09ddc..62cf672cfef 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 fa851a49256..5877f7c7522 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 7bee1bd0cef..1a694225da9 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 c1a47780377..00000000000 --- 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 d8c198ca2e9..65742f816c8 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 dee239c38d7..fa78c4ccc61 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 abb529781cb..bb3c946638c 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", From 2f53a28290bdcdc3ae787b0feaa78c53aba85d3c Mon Sep 17 00:00:00 2001 From: Prateek Shourya Date: Thu, 12 Sep 2024 17:43:08 +0530 Subject: [PATCH 2/2] chore: remove plane helpers yarn.lock --- packages/helpers/yarn.lock | 57 -------------------------------------- 1 file changed, 57 deletions(-) delete mode 100644 packages/helpers/yarn.lock diff --git a/packages/helpers/yarn.lock b/packages/helpers/yarn.lock deleted file mode 100644 index d4465e64598..00000000000 --- a/packages/helpers/yarn.lock +++ /dev/null @@ -1,57 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@types/node@^22.5.4": - version "22.5.4" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.5.4.tgz#83f7d1f65bc2ed223bdbf57c7884f1d5a4fa84e8" - integrity sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg== - dependencies: - undici-types "~6.19.2" - -"@types/prop-types@*": - version "15.7.12" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6" - integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q== - -"@types/react@^18.3.5": - version "18.3.5" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.5.tgz#5f524c2ad2089c0ff372bbdabc77ca2c4dbadf8f" - integrity sha512-WeqMfGJLGuLCqHGYRGHxnKrXcTitc6L/nBUWfWPcTarG3t9PsquqUMuVeXZeca+mglY4Vo5GZjCi0A3Or2lnxA== - dependencies: - "@types/prop-types" "*" - csstype "^3.0.2" - -csstype@^3.0.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" - integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== - -"js-tokens@^3.0.0 || ^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -loose-envify@^1.1.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -react@^18.3.1: - version "18.3.1" - resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" - integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== - dependencies: - loose-envify "^1.1.0" - -typescript@^5.6.2: - version "5.6.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.2.tgz#d1de67b6bef77c41823f822df8f0b3bcff60a5a0" - integrity sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw== - -undici-types@~6.19.2: - version "6.19.8" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" - integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==