1
1
import { DragSource } from 'dnd-core' ;
2
2
import NativeTypes from '../NativeTypes' ;
3
3
import EnterLeaveCounter from '../utils/EnterLeaveCounter' ;
4
+ import createMonotonicInterpolant from '../utils/createMonotonicInterpolant' ;
4
5
import shallowEqual from '../utils/shallowEqual' ;
5
6
import defaults from 'lodash/object/defaults' ;
7
+ import memoize from 'lodash/function/memoize' ;
6
8
import invariant from 'react/lib/invariant' ;
7
9
import warning from 'react/lib/warning' ;
8
10
11
+ const isSafari = memoize ( ( ) => Boolean ( window . safari ) ) ;
12
+ const isFirefox = memoize ( ( ) => / f i r e f o x / i. test ( navigator . userAgent ) ) ;
13
+
9
14
function isUrlDataTransfer ( dataTransfer ) {
10
15
var types = Array . prototype . slice . call ( dataTransfer . types ) ;
11
16
return types . indexOf ( 'Url' ) > - 1 || types . indexOf ( 'text/uri-list' ) > - 1 ;
@@ -40,110 +45,6 @@ function getMouseEventOffsets(e, sourceNode, dragPreview) {
40
45
return { offsetFromClient, offsetFromSource, offsetFromDragPreview } ;
41
46
}
42
47
43
- function isDesktopSafari ( ) {
44
- return ! ! window . safari ;
45
- }
46
-
47
- function isFirefox ( ) {
48
- return / f i r e f o x / i. test ( navigator . userAgent ) ;
49
- }
50
-
51
- /**
52
- * I took this straight from Wikipedia, it must be good!
53
- */
54
- function createMonotonicInterpolant ( xs , ys ) {
55
- const length = xs . length ;
56
-
57
- // Rearrange xs and ys so that xs is sorted
58
- const indexes = [ ] ;
59
- for ( let i = 0 ; i < length ; i ++ ) {
60
- indexes . push ( i ) ;
61
- }
62
- indexes . sort ( ( a , b ) => xs [ a ] < xs [ b ] ? - 1 : 1 ) ;
63
-
64
- const oldXs = xs , oldYs = ys ;
65
- // Impl: Creating new arrays also prevents problems if the input arrays are mutated later
66
- xs = [ ] ;
67
- ys = [ ] ;
68
- // Impl: Unary plus properly converts values to numbers
69
- for ( let i = 0 ; i < length ; i ++ ) {
70
- xs . push ( + oldXs [ indexes [ i ] ] ) ;
71
- ys . push ( + oldYs [ indexes [ i ] ] ) ;
72
- }
73
-
74
- // Get consecutive differences and slopes
75
- const dys = [ ] ;
76
- const dxs = [ ] ;
77
- const ms = [ ] ;
78
- let dx , dy ;
79
- for ( let i = 0 ; i < length - 1 ; i ++ ) {
80
- dx = xs [ i + 1 ] - xs [ i ] ;
81
- dy = ys [ i + 1 ] - ys [ i ] ;
82
- dxs . push ( dx ) ;
83
- dys . push ( dy ) ;
84
- ms . push ( dy / dx ) ;
85
- }
86
-
87
- // Get degree-1 coefficients
88
- const c1s = [ ms [ 0 ] ] ;
89
- for ( let i = 0 ; i < dxs . length - 1 ; i ++ ) {
90
- const m = ms [ i ] ;
91
- const mNext = ms [ i + 1 ] ;
92
- if ( m * mNext <= 0 ) {
93
- c1s . push ( 0 ) ;
94
- } else {
95
- dx = dxs [ i ] ;
96
- const dxNext = dxs [ i + 1 ] ;
97
- const common = dx + dxNext ;
98
- c1s . push ( 3 * common / ( ( common + dxNext ) / m + ( common + dx ) / mNext ) ) ;
99
- }
100
- }
101
- c1s . push ( ms [ ms . length - 1 ] ) ;
102
-
103
- // Get degree-2 and degree-3 coefficients
104
- const c2s = [ ] ;
105
- const c3s = [ ] ;
106
- let m ;
107
- for ( let i = 0 ; i < c1s . length - 1 ; i ++ ) {
108
- m = ms [ i ] ;
109
- const c1 = c1s [ i ] ;
110
- const invDx = 1 / dxs [ i ] ;
111
- const common = c1 + c1s [ i + 1 ] - m - m ;
112
- c2s . push ( ( m - c1 - common ) * invDx ) ;
113
- c3s . push ( common * invDx * invDx ) ;
114
- }
115
-
116
- // Return interpolant function
117
- return function ( x ) {
118
- // The rightmost point in the dataset should give an exact result
119
- let i = xs . length - 1 ;
120
- if ( x === xs [ i ] ) {
121
- return ys [ i ] ;
122
- }
123
-
124
- // Search for the interval x is in, returning the corresponding y if x is one of the original xs
125
- let low = 0 ;
126
- let high = c3s . length - 1 ;
127
- let mid ;
128
- while ( low <= high ) {
129
- mid = Math . floor ( 0.5 * ( low + high ) ) ;
130
- const xHere = xs [ mid ] ;
131
- if ( xHere < x ) {
132
- low = mid + 1 ;
133
- } else if ( xHere > x ) {
134
- high = mid - 1 ;
135
- } else {
136
- return ys [ mid ] ;
137
- }
138
- }
139
- i = Math . max ( 0 , high ) ;
140
-
141
- // Interpolate
142
- const diff = x - xs [ i ] , diffSq = diff * diff ;
143
- return ys [ i ] + c1s [ i ] * diff + c2s [ i ] * diffSq + c3s [ i ] * diff * diffSq ;
144
- } ;
145
- }
146
-
147
48
function getDragPreviewOffset ( sourceNode , dragPreview , offsetFromDragPreview , anchorPoint ) {
148
49
const { offsetWidth : sourceWidth , offsetHeight : sourceHeight } = sourceNode ;
149
50
const { anchorX, anchorY } = anchorPoint ;
@@ -153,7 +54,7 @@ function getDragPreviewOffset(sourceNode, dragPreview, offsetFromDragPreview, an
153
54
let dragPreviewHeight = isImage ? dragPreview . height : sourceHeight ;
154
55
155
56
// Work around @2x coordinate discrepancies in browsers
156
- if ( isDesktopSafari ( ) && isImage ) {
57
+ if ( isSafari ( ) && isImage ) {
157
58
dragPreviewHeight /= window . devicePixelRatio ;
158
59
dragPreviewWidth /= window . devicePixelRatio ;
159
60
} else if ( isFirefox ( ) && ! isImage ) {
@@ -183,7 +84,7 @@ function getDragPreviewOffset(sourceNode, dragPreview, offsetFromDragPreview, an
183
84
let y = interpolateY ( anchorY ) ;
184
85
185
86
// Work around Safari 8 positioning bug
186
- if ( isDesktopSafari ( ) && isImage ) {
87
+ if ( isSafari ( ) && isImage ) {
187
88
// We'll have to wait for @3x to see if this is entirely correct
188
89
y += ( window . devicePixelRatio - 1 ) * dragPreviewHeight ;
189
90
}
0 commit comments