diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 12ef4e5..9f54a62 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -13,13 +13,11 @@ uiKitConfigure({ const withContextProvider: Decorator = (Story, context) => { return ( - - - - - - - + + + + + ); }; diff --git a/src/components/AllPagesPanel/AllPagesListItem/AllPagesListItem.scss b/src/components/AllPagesPanel/AllPagesListItem/AllPagesListItem.scss index 85596f4..e5ea253 100644 --- a/src/components/AllPagesPanel/AllPagesListItem/AllPagesListItem.scss +++ b/src/components/AllPagesPanel/AllPagesListItem/AllPagesListItem.scss @@ -16,4 +16,8 @@ &__icon { color: var(--g-color-text-misc); } + + &_edit-mode { + padding: 0 0 0 var(--g-spacing-4); + } } diff --git a/src/components/AllPagesPanel/AllPagesListItem/AllPagesListItem.tsx b/src/components/AllPagesPanel/AllPagesListItem/AllPagesListItem.tsx index 74fbcac..71671c8 100644 --- a/src/components/AllPagesPanel/AllPagesListItem/AllPagesListItem.tsx +++ b/src/components/AllPagesPanel/AllPagesListItem/AllPagesListItem.tsx @@ -13,11 +13,14 @@ const b = block('all-pages-list-item'); interface AllPagesListItemProps { item: MenuItem; editMode?: boolean; + enableSorting?: boolean; onToggle: () => void; + onDragStart?: () => void; + onDragEnd?: () => void; } export const AllPagesListItem: React.FC = (props) => { - const {item, editMode, onToggle} = props; + const {item, editMode, onToggle, enableSorting, onDragStart, onDragEnd} = props; const onPinButtonClick = useCallback( (e: MouseEvent) => { e.stopPropagation(); @@ -33,8 +36,32 @@ export const AllPagesListItem: React.FC = (props) => { e.preventDefault(); } }; + + const onItemDrugStart = (e: MouseEvent) => { + if (editMode && onDragStart) { + e.stopPropagation(); + e.preventDefault(); + onDragStart(); + } + }; + + const onItemDrugEnd = (e: MouseEvent) => { + if (editMode && onDragEnd) { + e.stopPropagation(); + e.preventDefault(); + onDragEnd(); + } + }; + return ( -
+
{item.icon ? ( ) : null} diff --git a/src/components/AllPagesPanel/AllPagesPanel.scss b/src/components/AllPagesPanel/AllPagesPanel.scss index f9c9ceb..9f73ac9 100644 --- a/src/components/AllPagesPanel/AllPagesPanel.scss +++ b/src/components/AllPagesPanel/AllPagesPanel.scss @@ -20,4 +20,15 @@ &__discoverable-feature-wrapper { display: flex; } + + &__item_editMode { + padding: 0 var(--g-spacing-6); + } + + &__drag-placeholder { + padding-left: 88px; + padding-right: 68px; + text-wrap: nowrap; + visibility: hidden; + } } diff --git a/src/components/AllPagesPanel/AllPagesPanel.tsx b/src/components/AllPagesPanel/AllPagesPanel.tsx index f62f53b..ddfc949 100644 --- a/src/components/AllPagesPanel/AllPagesPanel.tsx +++ b/src/components/AllPagesPanel/AllPagesPanel.tsx @@ -1,4 +1,4 @@ -import React, {useCallback, useEffect, useRef, useState} from 'react'; +import React, {ReactNode, useCallback, useEffect, useMemo, useRef, useState} from 'react'; import {Gear} from '@gravity-ui/icons'; import {Button, Flex, Icon, List, ListItemData, Text} from '@gravity-ui/uikit'; @@ -30,6 +30,9 @@ export const AllPagesPanel: React.FC = (props) => { menuItemsRef.current = menuItems; const [isEditMode, setIsEditMode] = useState(false); + + const [dragingItemTitle, setDragingItemTitle] = useState(null); + const toggleEditMode = useCallback(() => { setIsEditMode((prev) => !prev); }, []); @@ -72,15 +75,28 @@ export const AllPagesPanel: React.FC = (props) => { [onMenuItemsChanged, editMenuProps], ); + const onDragEnd = useCallback(() => { + setDragingItemTitle(null); + }, [setDragingItemTitle]); + const itemRender = useCallback( - (item: ListItemData, _isActive: boolean, _itemIndex: number) => ( - togglePageVisibility(item)} - /> - ), - [isEditMode, togglePageVisibility], + (item: ListItemData, _isActive: boolean, _itemIndex: number) => { + const onDragStart = () => { + setDragingItemTitle(item.title); + }; + + return ( + togglePageVisibility(item)} + enableSorting={editMenuProps?.enableSorting} + /> + ); + }, + [isEditMode, togglePageVisibility, onDragEnd, setDragingItemTitle, editMenuProps], ); const onResetToDefaultClick = useCallback(() => { @@ -96,6 +112,28 @@ export const AllPagesPanel: React.FC = (props) => { })), ); }, [onMenuItemsChanged, editMenuProps]); + + const changeItemsOrder = useCallback( + ({oldIndex, newIndex}: {oldIndex: number; newIndex: number}) => { + const newItems = menuItemsRef.current.filter((item) => item.id !== ALL_PAGES_ID); + + const element = newItems.splice(oldIndex, 1)[0]; + newItems.splice(newIndex, 0, element); + + onMenuItemsChanged?.(newItems); + + setDragingItemTitle(null); + editMenuProps?.onChangeItemsOrder?.(element, oldIndex, newIndex); + }, + [onMenuItemsChanged, editMenuProps], + ); + + const sortableItems = useMemo(() => { + return menuItemsRef.current.filter( + (item) => item.id !== ALL_PAGES_ID && !item.afterMoreButton, + ); + }, []); + return ( @@ -107,22 +145,42 @@ export const AllPagesPanel: React.FC = (props) => { - {Object.keys(groupedItems).map((category) => { - return ( - - - {category} - - - - ); - })} + {isEditMode && editMenuProps?.enableSorting ? ( +
+ + + {dragingItemTitle && ( +
{dragingItemTitle}
+ )} +
+ ) : ( + Object.keys(groupedItems).map((category) => { + return ( + + + {category} + + + + ); + }) + )}
{isEditMode && ( diff --git a/src/components/AsideHeader/__stories__/AsideHeaderShowcase.tsx b/src/components/AsideHeader/__stories__/AsideHeaderShowcase.tsx index f8ae42a..7ea5513 100644 --- a/src/components/AsideHeader/__stories__/AsideHeaderShowcase.tsx +++ b/src/components/AsideHeader/__stories__/AsideHeaderShowcase.tsx @@ -297,6 +297,9 @@ export const AsideHeaderShowcase: React.FC = ({ }} onMenuMoreClick={() => console.log('onMenuMoreClick')} onAllPagesClick={() => console.log('onAllPagesClick')} + editMenuProps={{ + enableSorting: true, + }} />
); diff --git a/src/components/AsideHeader/types.tsx b/src/components/AsideHeader/types.tsx index 32a1b48..a38d84f 100644 --- a/src/components/AsideHeader/types.tsx +++ b/src/components/AsideHeader/types.tsx @@ -22,6 +22,8 @@ export interface EditMenuProps { onOpenEditMode?: () => void; onToggleMenuItem?: (changedItem: MenuItem) => void; onResetSettingsToDefault?: () => void; + enableSorting?: boolean; + onChangeItemsOrder?: (changedItem: MenuItem, oldIndex: number, newIndex: number) => void; } export interface AsideHeaderGeneralProps extends QAProps {