1- import { useEffect , useRef } from 'react'
2- import SortableList , { SortableItem } from 'react-easy-sort'
1+ import { useMemo , useRef } from 'react'
2+ //import SortableList, { SortableItem } from 'react-easy-sort'
3+ import {
4+ DndContext ,
5+ DragEndEvent ,
6+ KeyboardSensor ,
7+ PointerSensor ,
8+ useSensor ,
9+ useSensors ,
10+ } from '@dnd-kit/core'
11+ import {
12+ horizontalListSortingStrategy ,
13+ SortableContext ,
14+ sortableKeyboardCoordinates ,
15+ useSortable ,
16+ } from '@dnd-kit/sortable'
17+ import { CSS } from '@dnd-kit/utilities'
18+ import { clsx } from 'clsx'
19+ import { MdOutlineDragIndicator } from 'react-icons/md'
320import { SUPPORTED_CARDS } from 'src/config/supportedCards'
421import { CustomRssCard } from 'src/features/cards'
522import { useRemoteConfigStore } from 'src/features/remoteConfig'
623import { trackPageDrag } from 'src/lib/analytics'
24+ import { DesktopBreakpoint } from 'src/providers/DesktopBreakpoint'
725import { useUserPreferences } from 'src/stores/preferences'
826import { SelectedCard , SupportedCardType } from 'src/types'
927
28+ type SortableItemProps = {
29+ id : string
30+ card : SupportedCardType
31+ withAds : boolean
32+ }
33+
34+ const SortableItem = ( { id, card, withAds } : SortableItemProps ) => {
35+ const { attributes, listeners, setNodeRef, isDragging, transform, transition } = useSortable ( {
36+ id,
37+ } )
38+
39+ const style = {
40+ transform : CSS . Transform . toString ( transform ) ,
41+ transition,
42+ }
43+
44+ const Component = card . component || CustomRssCard
45+
46+ return (
47+ < div ref = { setNodeRef } style = { style } >
48+ < Component
49+ meta = { card }
50+ className = { clsx ( isDragging && 'draggedBlock' ) }
51+ withAds = { withAds }
52+ knob = {
53+ < DesktopBreakpoint >
54+ < button className = "blockHeaderDragButton" { ...attributes } { ...listeners } >
55+ < MdOutlineDragIndicator />
56+ </ button >
57+ </ DesktopBreakpoint >
58+ }
59+ />
60+ </ div >
61+ )
62+ }
63+
1064export const DesktopCards = ( {
1165 cards,
1266 userCustomCards,
@@ -16,46 +70,78 @@ export const DesktopCards = ({
1670} ) => {
1771 const AVAILABLE_CARDS = [ ...SUPPORTED_CARDS , ...userCustomCards ]
1872 const { updateCardOrder } = useUserPreferences ( )
19- const scrollHolderRef = useRef < HTMLElement | null > ( null )
73+ const cardsWrapperRef = useRef < HTMLDivElement > ( null )
2074 const { adsConfig } = useRemoteConfigStore ( )
2175
22- const onSortEnd = ( oldIndex : number , newIndex : number ) => {
23- updateCardOrder ( oldIndex , newIndex )
24- trackPageDrag ( )
25- if ( newIndex === 0 || ( oldIndex > 3 && newIndex < 3 ) ) {
26- scrollHolderRef . current ?. scrollTo ( 0 , 0 )
76+ const sensors = useSensors (
77+ useSensor ( PointerSensor ) ,
78+ useSensor ( KeyboardSensor , {
79+ coordinateGetter : sortableKeyboardCoordinates ,
80+ } )
81+ )
82+
83+ const handleDragStart = ( ) => {
84+ cardsWrapperRef . current ?. classList . add ( 'snapDisabled' )
85+ }
86+
87+ const handleDragEnd = ( event : DragEndEvent ) => {
88+ const { active, over } = event
89+
90+ if ( active . id !== over ?. id ) {
91+ const previousCard = cards . find ( ( card ) => card . name === active . id )
92+ const newCard = cards . find ( ( card ) => card . name === over ?. id )
93+ if ( ! previousCard || ! newCard ) {
94+ return
95+ }
96+
97+ const oldIndex = previousCard . id
98+ const newIndex = newCard . id
99+
100+ updateCardOrder ( oldIndex , newIndex )
101+ trackPageDrag ( )
27102 }
103+
104+ cardsWrapperRef . current ?. classList . remove ( 'snapDisabled' )
28105 }
29106
30- useEffect ( ( ) => {
31- scrollHolderRef . current = document . querySelector ( '.Cards' )
32- } , [ ] )
107+ const memoCards = useMemo ( ( ) => {
108+ return cards
109+ . map ( ( card ) => {
110+ const constantCard = AVAILABLE_CARDS . find ( ( c ) => c . value === card . name )
111+ if ( ! constantCard ) {
112+ return null
113+ }
114+
115+ return {
116+ card : constantCard ,
117+ id : card . name ,
118+ }
119+ } )
120+ . filter ( Boolean ) as { id : string ; card : SupportedCardType } [ ]
121+ } , [ cards ] )
33122
34123 return (
35- < SortableList
36- as = "div"
37- onSortEnd = { onSortEnd }
38- lockAxis = "x"
39- className = "Cards HorizontalScroll"
40- draggedItemClassName = "draggedBlock" >
41- { [ ...cards ]
42- . sort ( ( a , b ) => a . id - b . id )
43- . map ( ( card , index ) => {
44- const constantCard = AVAILABLE_CARDS . find ( ( c ) => c . value === card . name )
45- if ( ! constantCard ) {
46- return null
47- }
48-
49- const Component = constantCard ?. component || CustomRssCard
50-
51- return (
52- < SortableItem key = { card . name } >
53- < div >
54- < Component meta = { constantCard } withAds = { index === adsConfig . columnPosition } />
55- </ div >
56- </ SortableItem >
57- )
58- } ) }
59- </ SortableList >
124+ < div ref = { cardsWrapperRef } className = "Cards HorizontalScroll" >
125+ < DndContext
126+ sensors = { sensors }
127+ autoScroll = { false }
128+ onDragEnd = { handleDragEnd }
129+ onDragStart = { handleDragStart } >
130+ < SortableContext
131+ items = { memoCards . map ( ( { id } ) => id ) }
132+ strategy = { horizontalListSortingStrategy } >
133+ { memoCards . map ( ( { id, card } , index ) => {
134+ return (
135+ < SortableItem
136+ key = { id }
137+ id = { id }
138+ card = { card }
139+ withAds = { index === adsConfig . columnPosition }
140+ />
141+ )
142+ } ) }
143+ </ SortableContext >
144+ </ DndContext >
145+ </ div >
60146 )
61147}
0 commit comments