-
Notifications
You must be signed in to change notification settings - Fork 381
/
draggablePage.js
87 lines (77 loc) · 2.53 KB
/
draggablePage.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/**
* External dependencies
*/
import styled from 'styled-components';
/**
* WordPress dependencies
*/
import { forwardRef, useCallback } from '@wordpress/element';
/**
* Internal dependencies
*/
import DropZone from '../dropzone';
import { useStory } from '../../app/story';
const Page = styled.button`
padding: 0;
margin: 0;
border: none;
outline: 2px solid ${ ( { isActive, theme } ) => isActive ? theme.colors.selection : theme.colors.bg.v1 };
&:focus, &:hover {
outline: 2px solid ${ ( { theme } ) => theme.colors.selection };
}
height: ${ ( { height } ) => height }px;
width: ${ ( { width } ) => width }px;
background-color: ${ ( { theme } ) => theme.colors.mg.v1 };
flex: none;
transition: width .2s ease, height .2s ease;
`;
// Disable reason: forwardRef render functions do not support propTypes
//eslint-disable-next-line react/prop-types
function DraggablePageWithRef( { pageIndex, onClick, isActive, ariaLabel, width, height, dragIndicatorOffset }, ref ) {
const { state: { pages }, actions: { setCurrentPage, arrangePage } } = useStory();
const getArrangeIndex = ( sourceIndex, dstIndex, position ) => {
// If the dropped element is before the dropzone index then we have to deduct
// that from the index to make up for the "lost" element in the row.
const indexAdjustment = sourceIndex < dstIndex ? -1 : 0;
if ( 'left' === position.x ) {
return dstIndex + indexAdjustment;
}
return dstIndex + 1 + indexAdjustment;
};
const onDragStart = useCallback( ( evt ) => {
const pageData = {
type: 'page',
index: pageIndex,
};
evt.dataTransfer.setData( 'text', JSON.stringify( pageData ) );
}, [ pageIndex ] );
const onDrop = ( evt, { position } ) => {
const droppedEl = JSON.parse( evt.dataTransfer.getData( 'text' ) );
if ( ! droppedEl || 'page' !== droppedEl.type ) {
return;
}
const arrangedIndex = getArrangeIndex( droppedEl.index, pageIndex, position );
// Do nothing if the index didn't change.
if ( droppedEl.index !== arrangedIndex ) {
const pageId = pages[ droppedEl.index ].id;
arrangePage( { pageId, position: arrangedIndex } );
setCurrentPage( { pageId } );
}
};
return (
<DropZone onDrop={ onDrop } pageIndex={ pageIndex } dragIndicatorOffset={ dragIndicatorOffset }>
<Page
draggable="true"
onClick={ onClick }
onDragStart={ onDragStart }
isActive={ isActive }
aria-label={ ariaLabel }
width={ width }
height={ height }
ref={ ref }
/>
</DropZone>
);
}
const DraggablePage = forwardRef( DraggablePageWithRef );
export default DraggablePage;