From 2b21e055244ae802f04180e9b32475caa3a16ca8 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Thu, 3 Aug 2023 10:36:11 -0700 Subject: [PATCH] Improve mouse tracking (#1061) * Improve mouse tracking * Fix lint * Fix regression on Filters * Fix according to review --- .../components/ActivityRelationPicker.tsx | 2 +- .../table/components/CompanyTableMockData.tsx | 4 +- .../BoardCardEditableFieldEditMode.tsx | 2 +- .../ui/board/components/BoardColumnMenu.tsx | 2 +- .../ui/board/components/BoardHeader.tsx | 26 ++-- .../hooks/useRegisterCloseFieldHandlers.ts | 2 +- .../components/DropdownMenuContainer.tsx | 2 +- .../components/MultipleEntitySelect.tsx | 2 +- .../components/SingleEntitySelect.tsx | 2 +- .../src/modules/ui/modal/components/Modal.tsx | 2 +- .../right-drawer/components/RightDrawer.tsx | 4 +- .../ui/table/components/EntityTable.tsx | 44 +------ .../ui/table/components/EntityTableCell.tsx | 9 +- .../ui/table/components/EntityTableHeader.tsx | 120 +++++++++++------- .../ui/table/components/EntityTableRow.tsx | 4 +- .../components/GenericEntityTableData.tsx | 1 - .../hooks/useRegisterCloseCellHandlers.ts | 2 +- .../type/components/DateCellEdit.tsx | 2 +- .../src/modules/ui/table/hooks/useLoadView.ts | 4 +- .../ui/table/states/resizeFieldOffsetState.ts | 6 + .../ui/table/states/viewFieldsState.ts | 6 +- .../table-header/components/TableHeader.tsx | 26 ++-- front/src/modules/ui/top-bar/TopBar.tsx | 6 +- .../useListenClickOutsideArrayOfRef.test.tsx | 0 .../hooks/useListenClickOutside.ts | 0 .../pointer-event/hooks/useTrackPointer.ts | 67 ++++++++++ front/src/pages/tasks/Tasks.tsx | 6 +- 27 files changed, 210 insertions(+), 143 deletions(-) create mode 100644 front/src/modules/ui/table/states/resizeFieldOffsetState.ts rename front/src/modules/ui/utilities/{click-outside => pointer-event}/hooks/__tests__/useListenClickOutsideArrayOfRef.test.tsx (100%) rename front/src/modules/ui/utilities/{click-outside => pointer-event}/hooks/useListenClickOutside.ts (100%) create mode 100644 front/src/modules/ui/utilities/pointer-event/hooks/useTrackPointer.ts diff --git a/front/src/modules/activities/components/ActivityRelationPicker.tsx b/front/src/modules/activities/components/ActivityRelationPicker.tsx index 49a5518e5006..2a9a6d4071bf 100644 --- a/front/src/modules/activities/components/ActivityRelationPicker.tsx +++ b/front/src/modules/activities/components/ActivityRelationPicker.tsx @@ -14,9 +14,9 @@ import { PersonChip } from '@/people/components/PersonChip'; import { useFilteredSearchPeopleQuery } from '@/people/queries'; import { MultipleEntitySelect } from '@/ui/input/relation-picker/components/MultipleEntitySelect'; import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope'; -import { useListenClickOutside } from '@/ui/utilities/click-outside/hooks/useListenClickOutside'; import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; +import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; import { Activity, ActivityTarget, CommentableType } from '~/generated/graphql'; import { assertNotNull } from '~/utils/assert'; diff --git a/front/src/modules/companies/table/components/CompanyTableMockData.tsx b/front/src/modules/companies/table/components/CompanyTableMockData.tsx index 420501eacd96..5cd168665e6a 100644 --- a/front/src/modules/companies/table/components/CompanyTableMockData.tsx +++ b/front/src/modules/companies/table/components/CompanyTableMockData.tsx @@ -3,7 +3,7 @@ import { useSetRecoilState } from 'recoil'; import { useSetEntityTableData } from '@/ui/table/hooks/useSetEntityTableData'; import { entityTableDimensionsState } from '@/ui/table/states/entityTableDimensionsState'; -import { viewFieldsFamilyState } from '@/ui/table/states/viewFieldsState'; +import { viewFieldsState } from '@/ui/table/states/viewFieldsState'; import { companyViewFields } from '../../constants/companyViewFields'; @@ -13,7 +13,7 @@ export function CompanyTableMockData() { const setEntityTableDimensions = useSetRecoilState( entityTableDimensionsState, ); - const setViewFields = useSetRecoilState(viewFieldsFamilyState); + const setViewFields = useSetRecoilState(viewFieldsState); const setEntityTableData = useSetEntityTableData(); setEntityTableData(mockedCompaniesData, []); diff --git a/front/src/modules/ui/board/card-field/components/BoardCardEditableFieldEditMode.tsx b/front/src/modules/ui/board/card-field/components/BoardCardEditableFieldEditMode.tsx index 1123af4de168..180091a13778 100644 --- a/front/src/modules/ui/board/card-field/components/BoardCardEditableFieldEditMode.tsx +++ b/front/src/modules/ui/board/card-field/components/BoardCardEditableFieldEditMode.tsx @@ -2,8 +2,8 @@ import { ReactElement, useRef } from 'react'; import styled from '@emotion/styled'; import { overlayBackground } from '@/ui/theme/constants/effects'; -import { useListenClickOutside } from '@/ui/utilities/click-outside/hooks/useListenClickOutside'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; +import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; import { BoardCardFieldHotkeyScope } from '../types/BoardCardFieldHotkeyScope'; diff --git a/front/src/modules/ui/board/components/BoardColumnMenu.tsx b/front/src/modules/ui/board/components/BoardColumnMenu.tsx index 345cc5271746..00fbc66607d5 100644 --- a/front/src/modules/ui/board/components/BoardColumnMenu.tsx +++ b/front/src/modules/ui/board/components/BoardColumnMenu.tsx @@ -7,7 +7,7 @@ import { DropdownMenuItemsContainer } from '@/ui/dropdown/components/DropdownMen import { DropdownMenuSelectableItem } from '@/ui/dropdown/components/DropdownMenuSelectableItem'; import DropdownButton from '@/ui/filter-n-sort/components/DropdownButton'; import { icon } from '@/ui/theme/constants/icon'; -import { useListenClickOutside } from '@/ui/utilities/click-outside/hooks/useListenClickOutside'; +import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; import { BoardColumnEditTitleMenu } from './BoardColumnEditTitleMenu'; diff --git a/front/src/modules/ui/board/components/BoardHeader.tsx b/front/src/modules/ui/board/components/BoardHeader.tsx index 553f663fbdda..9aae9d00afac 100644 --- a/front/src/modules/ui/board/components/BoardHeader.tsx +++ b/front/src/modules/ui/board/components/BoardHeader.tsx @@ -63,18 +63,20 @@ export function BoardHeader({ {viewName} } - rightComponents={[ - , - - isSortSelected={sorts.length > 0} - availableSorts={availableSorts || []} - onSortSelect={sortSelect} - HotkeyScope={FiltersHotkeyScope.FilterDropdownButton} - />, - ]} + rightComponent={ + <> + + + isSortSelected={sorts.length > 0} + availableSorts={availableSorts || []} + onSortSelect={sortSelect} + HotkeyScope={FiltersHotkeyScope.FilterDropdownButton} + /> + + } bottomComponent={ ({ onSortsUpdate, useUpdateEntityMutation, }: OwnProps) { - const viewFields = useRecoilValue(viewFieldsFamilyState); - const setViewFields = useSetRecoilState(viewFieldsFamilyState); - - const [updateViewFieldMutation] = useUpdateViewFieldMutation(); - const tableBodyRef = useRef(null); useMapKeyboardToSoftFocus(); @@ -120,25 +112,6 @@ export function EntityTable({ }, }); - const handleColumnResize = useCallback( - (resizedFieldId: string, width: number) => { - setViewFields((previousViewFields) => - previousViewFields.map((viewField) => - viewField.id === resizedFieldId - ? { ...viewField, columnSize: width } - : viewField, - ), - ); - updateViewFieldMutation({ - variables: { - data: { sizeInPx: width }, - where: { id: resizedFieldId }, - }, - }); - }, - [setViewFields, updateViewFieldMutation], - ); - return ( @@ -150,15 +123,10 @@ export function EntityTable({ onSortsUpdate={onSortsUpdate} /> - {viewFields.length > 0 && ( - - - - - )} + + + + diff --git a/front/src/modules/ui/table/components/EntityTableCell.tsx b/front/src/modules/ui/table/components/EntityTableCell.tsx index ba5882be5aba..a68a06e056b1 100644 --- a/front/src/modules/ui/table/components/EntityTableCell.tsx +++ b/front/src/modules/ui/table/components/EntityTableCell.tsx @@ -34,14 +34,7 @@ export function EntityTableCell({ cellIndex }: { cellIndex: number }) { return ( - handleContextMenu(event)} - style={{ - width: viewField.columnSize, - minWidth: viewField.columnSize, - maxWidth: viewField.columnSize, - }} - > + handleContextMenu(event)}> diff --git a/front/src/modules/ui/table/components/EntityTableHeader.tsx b/front/src/modules/ui/table/components/EntityTableHeader.tsx index 1f14827d5998..58d30d8f74a3 100644 --- a/front/src/modules/ui/table/components/EntityTableHeader.tsx +++ b/front/src/modules/ui/table/components/EntityTableHeader.tsx @@ -1,10 +1,17 @@ -import { PointerEvent, useCallback, useMemo, useState } from 'react'; +import { useCallback, useMemo, useState } from 'react'; import styled from '@emotion/styled'; +import { + useRecoilCallback, + useRecoilState, + useRecoilValue, + useSetRecoilState, +} from 'recoil'; -import type { - ViewFieldDefinition, - ViewFieldMetadata, -} from '../types/ViewField'; +import { useTrackPointer } from '@/ui/utilities/pointer-event/hooks/useTrackPointer'; +import { useUpdateViewFieldMutation } from '~/generated/graphql'; + +import { resizeFieldOffsetState } from '../states/resizeFieldOffsetState'; +import { viewFieldsState } from '../states/viewFieldsState'; import { ColumnHead } from './ColumnHead'; import { SelectAllCheckbox } from './SelectAllCheckbox'; @@ -42,12 +49,11 @@ const StyledResizeHandler = styled.div` z-index: 1; `; -type OwnProps = { - onColumnResize: (resizedFieldId: string, width: number) => void; - viewFields: ViewFieldDefinition[]; -}; +export function EntityTableHeader() { + const viewFields = useRecoilValue(viewFieldsState); + const setViewFields = useSetRecoilState(viewFieldsState); -export function EntityTableHeader({ onColumnResize, viewFields }: OwnProps) { + const [updateViewFieldMutation] = useUpdateViewFieldMutation(); const columnWidths = useMemo( () => viewFields.reduce>( @@ -59,46 +65,75 @@ export function EntityTableHeader({ onColumnResize, viewFields }: OwnProps) { ), [viewFields], ); - const [isResizing, setIsResizing] = useState(false); const [initialPointerPositionX, setInitialPointerPositionX] = useState< number | null >(null); const [resizedFieldId, setResizedFieldId] = useState(null); - const [offset, setOffset] = useState(0); - - const handleResizeHandlerDragStart = useCallback( - (event: PointerEvent, fieldId: string) => { - setIsResizing(true); - setResizedFieldId(fieldId); - setInitialPointerPositionX(event.clientX); + const [offset, setOffset] = useRecoilState(resizeFieldOffsetState); + + const handleColumnResize = useCallback( + (resizedFieldId: string, width: number) => { + setViewFields((previousViewFields) => + previousViewFields.map((viewField) => + viewField.id === resizedFieldId + ? { ...viewField, columnSize: width } + : viewField, + ), + ); + updateViewFieldMutation({ + variables: { + data: { sizeInPx: width }, + where: { id: resizedFieldId }, + }, + }); }, - [setIsResizing, setResizedFieldId, setInitialPointerPositionX], + [setViewFields, updateViewFieldMutation], ); - const handleResizeHandlerDrag = useCallback( - (event: PointerEvent) => { - if (!isResizing || initialPointerPositionX === null) return; - - setOffset(event.clientX - initialPointerPositionX); + const handleResizeHandlerStart = useCallback( + (positionX: number, _: number) => { + setInitialPointerPositionX(positionX); }, - [isResizing, initialPointerPositionX], + [], ); - const handleResizeHandlerDragEnd = useCallback(() => { - setIsResizing(false); - if (!resizedFieldId) return; - - const nextWidth = Math.round( - Math.max(columnWidths[resizedFieldId] + offset, COLUMN_MIN_WIDTH), - ); + const handleResizeHandlerMove = useCallback( + (positionX: number, _positionY: number) => { + if (!initialPointerPositionX) return; + setOffset(positionX - initialPointerPositionX); + }, + [setOffset, initialPointerPositionX], + ); - if (nextWidth !== columnWidths[resizedFieldId]) { - onColumnResize(resizedFieldId, nextWidth); - } + const handleResizeHandlerEnd = useRecoilCallback( + ({ snapshot, set }) => + (_positionX: number, _positionY: number) => { + if (!resizedFieldId) return; + const nextWidth = Math.round( + Math.max( + columnWidths[resizedFieldId] + + snapshot.getLoadable(resizeFieldOffsetState).valueOrThrow(), + COLUMN_MIN_WIDTH, + ), + ); + + if (nextWidth !== columnWidths[resizedFieldId]) { + handleColumnResize(resizedFieldId, nextWidth); + } + set(resizeFieldOffsetState, 0); + setInitialPointerPositionX(null); + setResizedFieldId(null); + }, + [resizedFieldId, columnWidths, setResizedFieldId, handleColumnResize], + ); - setOffset(0); - }, [resizedFieldId, columnWidths, offset, onColumnResize]); + useTrackPointer({ + shouldTrackPointer: resizedFieldId !== null, + onMouseDown: handleResizeHandlerStart, + onMouseMove: handleResizeHandlerMove, + onMouseUp: handleResizeHandlerEnd, + }); return ( @@ -116,7 +151,7 @@ export function EntityTableHeader({ onColumnResize, viewFields }: OwnProps) { {viewFields.map((viewField) => ( - handleResizeHandlerDragStart(event, viewField.id) - } - onPointerMove={handleResizeHandlerDrag} - onPointerOut={handleResizeHandlerDragEnd} - onPointerUp={handleResizeHandlerDragEnd} + onPointerDown={() => { + setResizedFieldId(viewField.id); + }} /> ))} diff --git a/front/src/modules/ui/table/components/EntityTableRow.tsx b/front/src/modules/ui/table/components/EntityTableRow.tsx index d01b14de22a7..8a566221cb17 100644 --- a/front/src/modules/ui/table/components/EntityTableRow.tsx +++ b/front/src/modules/ui/table/components/EntityTableRow.tsx @@ -2,7 +2,7 @@ import styled from '@emotion/styled'; import { useRecoilValue } from 'recoil'; import { ViewFieldContext } from '../states/ViewFieldContext'; -import { viewFieldsFamilyState } from '../states/viewFieldsState'; +import { viewFieldsState } from '../states/viewFieldsState'; import { CheckboxCell } from './CheckboxCell'; import { EntityTableCell } from './EntityTableCell'; @@ -13,7 +13,7 @@ const StyledRow = styled.tr<{ selected: boolean }>` `; export function EntityTableRow({ rowId }: { rowId: string }) { - const viewFields = useRecoilValue(viewFieldsFamilyState); + const viewFields = useRecoilValue(viewFieldsState); return ( diff --git a/front/src/modules/ui/table/components/GenericEntityTableData.tsx b/front/src/modules/ui/table/components/GenericEntityTableData.tsx index 2c4be00ab56e..c6fbebb2d1d2 100644 --- a/front/src/modules/ui/table/components/GenericEntityTableData.tsx +++ b/front/src/modules/ui/table/components/GenericEntityTableData.tsx @@ -33,7 +33,6 @@ export function GenericEntityTableData({ variables: { orderBy, where: whereFilters }, onCompleted: (data: any) => { const entities = data[getRequestResultKey] ?? []; - setEntityTableData(entities, filterDefinitionArray); }, }); diff --git a/front/src/modules/ui/table/editable-cell/hooks/useRegisterCloseCellHandlers.ts b/front/src/modules/ui/table/editable-cell/hooks/useRegisterCloseCellHandlers.ts index cfbc7d710dff..f27160263279 100644 --- a/front/src/modules/ui/table/editable-cell/hooks/useRegisterCloseCellHandlers.ts +++ b/front/src/modules/ui/table/editable-cell/hooks/useRegisterCloseCellHandlers.ts @@ -1,5 +1,5 @@ -import { useListenClickOutside } from '@/ui/utilities/click-outside/hooks/useListenClickOutside'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; +import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; import { useMoveSoftFocus } from '../../hooks/useMoveSoftFocus'; import { TableHotkeyScope } from '../../types/TableHotkeyScope'; diff --git a/front/src/modules/ui/table/editable-cell/type/components/DateCellEdit.tsx b/front/src/modules/ui/table/editable-cell/type/components/DateCellEdit.tsx index 01491b01926d..7510192b323b 100644 --- a/front/src/modules/ui/table/editable-cell/type/components/DateCellEdit.tsx +++ b/front/src/modules/ui/table/editable-cell/type/components/DateCellEdit.tsx @@ -4,8 +4,8 @@ import { Key } from 'ts-key-enum'; import { DateInputEdit } from '@/ui/input/date/components/DateInputEdit'; import { TableHotkeyScope } from '@/ui/table/types/TableHotkeyScope'; -import { useListenClickOutside } from '@/ui/utilities/click-outside/hooks/useListenClickOutside'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; +import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; import { useEditableCell } from '../../hooks/useEditableCell'; diff --git a/front/src/modules/ui/table/hooks/useLoadView.ts b/front/src/modules/ui/table/hooks/useLoadView.ts index 6d1b38e60505..df8381ef0c1b 100644 --- a/front/src/modules/ui/table/hooks/useLoadView.ts +++ b/front/src/modules/ui/table/hooks/useLoadView.ts @@ -9,7 +9,7 @@ import { } from '~/generated/graphql'; import { entityTableDimensionsState } from '../states/entityTableDimensionsState'; -import { viewFieldsFamilyState } from '../states/viewFieldsState'; +import { viewFieldsState } from '../states/viewFieldsState'; import { ViewFieldDefinition, ViewFieldMetadata, @@ -32,7 +32,7 @@ export const useLoadView = ({ const setEntityTableDimensions = useSetRecoilState( entityTableDimensionsState, ); - const setViewFields = useSetRecoilState(viewFieldsFamilyState); + const setViewFields = useSetRecoilState(viewFieldsState); const [createViewFieldsMutation] = useCreateViewFieldsMutation(); diff --git a/front/src/modules/ui/table/states/resizeFieldOffsetState.ts b/front/src/modules/ui/table/states/resizeFieldOffsetState.ts new file mode 100644 index 000000000000..847ebc1c774c --- /dev/null +++ b/front/src/modules/ui/table/states/resizeFieldOffsetState.ts @@ -0,0 +1,6 @@ +import { atom } from 'recoil'; + +export const resizeFieldOffsetState = atom({ + key: 'resizeFieldOffsetState', + default: 0, +}); diff --git a/front/src/modules/ui/table/states/viewFieldsState.ts b/front/src/modules/ui/table/states/viewFieldsState.ts index b1f7a73d0ce0..d78ddc5eee8d 100644 --- a/front/src/modules/ui/table/states/viewFieldsState.ts +++ b/front/src/modules/ui/table/states/viewFieldsState.ts @@ -2,9 +2,7 @@ import { atom } from 'recoil'; import { ViewFieldDefinition, ViewFieldMetadata } from '../types/ViewField'; -export const viewFieldsFamilyState = atom< - ViewFieldDefinition[] ->({ - key: 'viewFieldsFamilyState', +export const viewFieldsState = atom[]>({ + key: 'viewFieldsState', default: [], }); diff --git a/front/src/modules/ui/table/table-header/components/TableHeader.tsx b/front/src/modules/ui/table/table-header/components/TableHeader.tsx index f60d56d7524c..dc17b0773725 100644 --- a/front/src/modules/ui/table/table-header/components/TableHeader.tsx +++ b/front/src/modules/ui/table/table-header/components/TableHeader.tsx @@ -64,18 +64,20 @@ export function TableHeader({ } displayBottomBorder={false} - rightComponents={[ - , - - isSortSelected={sorts.length > 0} - availableSorts={availableSorts || []} - onSortSelect={sortSelect} - HotkeyScope={FiltersHotkeyScope.FilterDropdownButton} - />, - ]} + rightComponent={ + <> + + + isSortSelected={sorts.length > 0} + availableSorts={availableSorts || []} + onSortSelect={sortSelect} + HotkeyScope={FiltersHotkeyScope.FilterDropdownButton} + /> + + } bottomComponent={ {leftComponent} - {rightComponents} + {rightComponent} {bottomComponent} diff --git a/front/src/modules/ui/utilities/click-outside/hooks/__tests__/useListenClickOutsideArrayOfRef.test.tsx b/front/src/modules/ui/utilities/pointer-event/hooks/__tests__/useListenClickOutsideArrayOfRef.test.tsx similarity index 100% rename from front/src/modules/ui/utilities/click-outside/hooks/__tests__/useListenClickOutsideArrayOfRef.test.tsx rename to front/src/modules/ui/utilities/pointer-event/hooks/__tests__/useListenClickOutsideArrayOfRef.test.tsx diff --git a/front/src/modules/ui/utilities/click-outside/hooks/useListenClickOutside.ts b/front/src/modules/ui/utilities/pointer-event/hooks/useListenClickOutside.ts similarity index 100% rename from front/src/modules/ui/utilities/click-outside/hooks/useListenClickOutside.ts rename to front/src/modules/ui/utilities/pointer-event/hooks/useListenClickOutside.ts diff --git a/front/src/modules/ui/utilities/pointer-event/hooks/useTrackPointer.ts b/front/src/modules/ui/utilities/pointer-event/hooks/useTrackPointer.ts new file mode 100644 index 000000000000..c3e3f790b43e --- /dev/null +++ b/front/src/modules/ui/utilities/pointer-event/hooks/useTrackPointer.ts @@ -0,0 +1,67 @@ +import { useCallback, useEffect } from 'react'; + +type MouseListener = (positionX: number, positionY: number) => void; + +export function useTrackPointer({ + shouldTrackPointer = true, + onMouseMove, + onMouseDown, + onMouseUp, +}: { + shouldTrackPointer?: boolean; + onMouseMove?: MouseListener; + onMouseDown?: MouseListener; + onMouseUp?: MouseListener; +}) { + const extractPosition = useCallback((event: MouseEvent | TouchEvent) => { + const clientX = + 'clientX' in event ? event.clientX : event.changedTouches[0].clientX; + const clientY = + 'clientY' in event ? event.clientY : event.changedTouches[0].clientY; + + return { clientX, clientY }; + }, []); + + const onInternalMouseMove = useCallback( + (event: MouseEvent | TouchEvent) => { + const { clientX, clientY } = extractPosition(event); + onMouseMove?.(clientX, clientY); + }, + [onMouseMove, extractPosition], + ); + + const onInternalMouseDown = useCallback( + (event: MouseEvent | TouchEvent) => { + const { clientX, clientY } = extractPosition(event); + onMouseDown?.(clientX, clientY); + }, + [onMouseDown, extractPosition], + ); + + const onInternalMouseUp = useCallback( + (event: MouseEvent | TouchEvent) => { + const { clientX, clientY } = extractPosition(event); + onMouseUp?.(clientX, clientY); + }, + [onMouseUp, extractPosition], + ); + + useEffect(() => { + if (shouldTrackPointer) { + document.addEventListener('mousemove', onInternalMouseMove); + document.addEventListener('mousedown', onInternalMouseDown); + document.addEventListener('mouseup', onInternalMouseUp); + + return () => { + document.removeEventListener('mousemove', onInternalMouseMove); + document.removeEventListener('mousedown', onInternalMouseDown); + document.removeEventListener('mouseup', onInternalMouseUp); + }; + } + }, [ + shouldTrackPointer, + onInternalMouseMove, + onInternalMouseDown, + onInternalMouseUp, + ]); +} diff --git a/front/src/pages/tasks/Tasks.tsx b/front/src/pages/tasks/Tasks.tsx index 24b164c139b0..e9b678bcf64c 100644 --- a/front/src/pages/tasks/Tasks.tsx +++ b/front/src/pages/tasks/Tasks.tsx @@ -54,13 +54,13 @@ export function Tasks() { } - rightComponents={[ + rightComponent={ , - ]} + /> + } />