react-chess-core 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -46
- package/dist/features/chessboard/ChessboardDnDProvider.d.ts +5 -0
- package/dist/features/chessboard/CorrectMoveCheckBadge.d.ts +3 -0
- package/dist/features/chessboard/HighlightChessboard.d.ts +5 -1
- package/dist/features/chessboard/boardSquareHighlightColors.d.ts +3 -0
- package/dist/features/chessboard/createFeedbackSquareRenderer.d.ts +3 -0
- package/dist/features/chessboard/index.d.ts +1 -0
- package/dist/features/chessboard/useClickToMove.d.ts +28 -0
- package/dist/features/training/correctMoveFeedbackMs.d.ts +2 -0
- package/dist/features/training/index.d.ts +2 -0
- package/dist/features/training/useCorrectMoveFeedback.d.ts +6 -0
- package/dist/index.esm.js +1848 -8
- package/dist/index.js +1849 -6
- package/dist/stories/Chessboard.stories.d.ts +2 -0
- package/package.json +69 -65
- package/dist/features/training/expectedMoveDrop.test.d.ts +0 -1
package/dist/index.js
CHANGED
|
@@ -98,9 +98,1598 @@ const ThemeProvider = ({ children, theme = 'dark', boardTheme, }) => {
|
|
|
98
98
|
return (jsxRuntime.jsx(ChessboardThemeContext.Provider, { value: { customDarkSquareStyle, customLightSquareStyle }, children: children }));
|
|
99
99
|
};
|
|
100
100
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
var E=r=>{throw TypeError(r)};var P=(r,n,e)=>n.has(r)||E("Cannot "+e);var t=(r,n,e)=>(P(r,n,"read from private field"),e?e.call(r):n.get(r)),s=(r,n,e)=>n.has(r)?E("Cannot add the same private member more than once"):n instanceof WeakSet?n.add(r):n.set(r,e),p=(r,n,e,i)=>(P(r,n,"write to private field"),n.set(r,e),e);var h,B=class{constructor(){s(this,h);this.register=n=>{t(this,h).push(n);};this.unregister=n=>{for(;t(this,h).indexOf(n)!==-1;)t(this,h).splice(t(this,h).indexOf(n),1);};this.backendChanged=n=>{for(let e of t(this,h))e.backendChanged(n);};p(this,h,[]);}};h=new WeakMap;var c$1,l,a,d,k,x,T,D,m,v,f,w=class w{constructor(n,e,i){s(this,c$1);s(this,l);s(this,a);s(this,d);s(this,k);s(this,x,(n,e,i)=>{if(!i.backend)throw new Error(`You must specify a 'backend' property in your Backend entry: ${JSON.stringify(i)}`);let u=i.backend(n,e,i.options),o=i.id,g=!i.id&&u&&u.constructor;if(g&&(o=u.constructor.name),!o)throw new Error(`You must specify an 'id' property in your Backend entry: ${JSON.stringify(i)}
|
|
102
|
+
see this guide: https://github.com/louisbrunner/dnd-multi-backend/tree/master/packages/react-dnd-multi-backend#migrating-from-5xx`);if(g&&console.warn(`Deprecation notice: You are using a pipeline which doesn't include backends' 'id'.
|
|
103
|
+
This might be unsupported in the future, please specify 'id' explicitely for every backend.`),t(this,a)[o])throw new Error(`You must specify a unique 'id' property in your Backend entry:
|
|
104
|
+
${JSON.stringify(i)} (conflicts with: ${JSON.stringify(t(this,a)[o])})`);return {id:o,instance:u,preview:i.preview??false,transition:i.transition,skipDispatchOnTransition:i.skipDispatchOnTransition??false}});this.setup=()=>{if(!(typeof window>"u")){if(w.isSetUp)throw new Error("Cannot have two MultiBackends at the same time.");w.isSetUp=true,t(this,T).call(this,window),t(this,a)[t(this,c$1)].instance.setup();}};this.teardown=()=>{typeof window>"u"||(w.isSetUp=false,t(this,D).call(this,window),t(this,a)[t(this,c$1)].instance.teardown());};this.connectDragSource=(n,e,i)=>t(this,f).call(this,"connectDragSource",n,e,i);this.connectDragPreview=(n,e,i)=>t(this,f).call(this,"connectDragPreview",n,e,i);this.connectDropTarget=(n,e,i)=>t(this,f).call(this,"connectDropTarget",n,e,i);this.profile=()=>t(this,a)[t(this,c$1)].instance.profile();this.previewEnabled=()=>t(this,a)[t(this,c$1)].preview;this.previewsList=()=>t(this,l);this.backendsList=()=>t(this,d);s(this,T,n=>{for(let e of t(this,d))e.transition&&n.addEventListener(e.transition.event,t(this,m));});s(this,D,n=>{for(let e of t(this,d))e.transition&&n.removeEventListener(e.transition.event,t(this,m));});s(this,m,n=>{let e=t(this,c$1);if(t(this,d).some(i=>i.id!==t(this,c$1)&&i.transition&&i.transition.check(n)?(p(this,c$1,i.id),true):false),t(this,c$1)!==e){t(this,a)[e].instance.teardown();for(let[g,b]of Object.entries(t(this,k)))b.unsubscribe(),b.unsubscribe=t(this,v).call(this,b.func,...b.args);t(this,l).backendChanged(this);let i=t(this,a)[t(this,c$1)];if(i.instance.setup(),i.skipDispatchOnTransition)return;let u=n.constructor,o=new u(n.type,n);n.target?.dispatchEvent(o);}});s(this,v,(n,e,i,u)=>t(this,a)[t(this,c$1)].instance[n](e,i,u));s(this,f,(n,e,i,u)=>{let o=`${n}_${e}`,g=t(this,v).call(this,n,e,i,u);return t(this,k)[o]={func:n,args:[e,i,u],unsubscribe:g},()=>{t(this,k)[o].unsubscribe(),delete t(this,k)[o];}});if(!i||!i.backends||i.backends.length<1)throw new Error(`You must specify at least one Backend, if you are coming from 2.x.x (or don't understand this error)
|
|
105
|
+
see this guide: https://github.com/louisbrunner/dnd-multi-backend/tree/master/packages/react-dnd-multi-backend#migrating-from-2xx`);p(this,l,new B),p(this,a,{}),p(this,d,[]);for(let u of i.backends){let o=t(this,x).call(this,n,e,u);t(this,a)[o.id]=o,t(this,d).push(o);}p(this,c$1,t(this,d)[0].id),p(this,k,{});}};c$1=new WeakMap,l=new WeakMap,a=new WeakMap,d=new WeakMap,k=new WeakMap,x=new WeakMap,T=new WeakMap,D=new WeakMap,m=new WeakMap,v=new WeakMap,f=new WeakMap,w.isSetUp=false;var M=w;var S=(r,n,e)=>new M(r,n,e);var y=(r,n)=>({event:r,check:n});var L=y("touchstart",r=>{let n=r;return n.touches!==null&&n.touches!==void 0}),U=y("pointerdown",r=>r.pointerType==="mouse");
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Use invariant() to assert state which your program assumes to be true.
|
|
109
|
+
*
|
|
110
|
+
* Provide sprintf-style format (only %s is supported) and arguments
|
|
111
|
+
* to provide information about what broke and what you were
|
|
112
|
+
* expecting.
|
|
113
|
+
*
|
|
114
|
+
* The invariant message will be stripped in production, but the invariant
|
|
115
|
+
* will remain to ensure logic does not differ in production.
|
|
116
|
+
*/ function invariant(condition, format, ...args) {
|
|
117
|
+
if (isProduction()) ;
|
|
118
|
+
if (!condition) {
|
|
119
|
+
let error;
|
|
120
|
+
{
|
|
121
|
+
let argIndex = 0;
|
|
122
|
+
error = new Error(format.replace(/%s/g, function() {
|
|
123
|
+
return args[argIndex++];
|
|
124
|
+
}));
|
|
125
|
+
error.name = 'Invariant Violation';
|
|
126
|
+
}
|
|
127
|
+
error.framesToPop = 1 // we don't care about invariant's own frame
|
|
128
|
+
;
|
|
129
|
+
throw error;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function isProduction() {
|
|
133
|
+
return typeof process !== 'undefined' && process.env['NODE_ENV'] === 'production';
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// cheap lodash replacements
|
|
137
|
+
function memoize(fn) {
|
|
138
|
+
let result = null;
|
|
139
|
+
const memoized = ()=>{
|
|
140
|
+
if (result == null) {
|
|
141
|
+
result = fn();
|
|
142
|
+
}
|
|
143
|
+
return result;
|
|
144
|
+
};
|
|
145
|
+
return memoized;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* drop-in replacement for _.without
|
|
149
|
+
*/ function without(items, item) {
|
|
150
|
+
return items.filter((i)=>i !== item
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
function union(itemsA, itemsB) {
|
|
154
|
+
const set = new Set();
|
|
155
|
+
const insertItem = (item)=>set.add(item)
|
|
156
|
+
;
|
|
157
|
+
itemsA.forEach(insertItem);
|
|
158
|
+
itemsB.forEach(insertItem);
|
|
159
|
+
const result = [];
|
|
160
|
+
set.forEach((key)=>result.push(key)
|
|
161
|
+
);
|
|
162
|
+
return result;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
class EnterLeaveCounter {
|
|
166
|
+
enter(enteringNode) {
|
|
167
|
+
const previousLength = this.entered.length;
|
|
168
|
+
const isNodeEntered = (node)=>this.isNodeInDocument(node) && (!node.contains || node.contains(enteringNode))
|
|
169
|
+
;
|
|
170
|
+
this.entered = union(this.entered.filter(isNodeEntered), [
|
|
171
|
+
enteringNode
|
|
172
|
+
]);
|
|
173
|
+
return previousLength === 0 && this.entered.length > 0;
|
|
174
|
+
}
|
|
175
|
+
leave(leavingNode) {
|
|
176
|
+
const previousLength = this.entered.length;
|
|
177
|
+
this.entered = without(this.entered.filter(this.isNodeInDocument), leavingNode);
|
|
178
|
+
return previousLength > 0 && this.entered.length === 0;
|
|
179
|
+
}
|
|
180
|
+
reset() {
|
|
181
|
+
this.entered = [];
|
|
182
|
+
}
|
|
183
|
+
constructor(isNodeInDocument){
|
|
184
|
+
this.entered = [];
|
|
185
|
+
this.isNodeInDocument = isNodeInDocument;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
class NativeDragSource {
|
|
190
|
+
initializeExposedProperties() {
|
|
191
|
+
Object.keys(this.config.exposeProperties).forEach((property)=>{
|
|
192
|
+
Object.defineProperty(this.item, property, {
|
|
193
|
+
configurable: true,
|
|
194
|
+
enumerable: true,
|
|
195
|
+
get () {
|
|
196
|
+
// eslint-disable-next-line no-console
|
|
197
|
+
console.warn(`Browser doesn't allow reading "${property}" until the drop event.`);
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
loadDataTransfer(dataTransfer) {
|
|
204
|
+
if (dataTransfer) {
|
|
205
|
+
const newProperties = {};
|
|
206
|
+
Object.keys(this.config.exposeProperties).forEach((property)=>{
|
|
207
|
+
const propertyFn = this.config.exposeProperties[property];
|
|
208
|
+
if (propertyFn != null) {
|
|
209
|
+
newProperties[property] = {
|
|
210
|
+
value: propertyFn(dataTransfer, this.config.matchesTypes),
|
|
211
|
+
configurable: true,
|
|
212
|
+
enumerable: true
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
Object.defineProperties(this.item, newProperties);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
canDrag() {
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
beginDrag() {
|
|
223
|
+
return this.item;
|
|
224
|
+
}
|
|
225
|
+
isDragging(monitor, handle) {
|
|
226
|
+
return handle === monitor.getSourceId();
|
|
227
|
+
}
|
|
228
|
+
endDrag() {
|
|
229
|
+
// empty
|
|
230
|
+
}
|
|
231
|
+
constructor(config){
|
|
232
|
+
this.config = config;
|
|
233
|
+
this.item = {};
|
|
234
|
+
this.initializeExposedProperties();
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const FILE = '__NATIVE_FILE__';
|
|
239
|
+
const URL$1 = '__NATIVE_URL__';
|
|
240
|
+
const TEXT = '__NATIVE_TEXT__';
|
|
241
|
+
const HTML = '__NATIVE_HTML__';
|
|
242
|
+
|
|
243
|
+
var NativeTypes = /*#__PURE__*/Object.freeze({
|
|
244
|
+
__proto__: null,
|
|
245
|
+
FILE: FILE,
|
|
246
|
+
HTML: HTML,
|
|
247
|
+
TEXT: TEXT,
|
|
248
|
+
URL: URL$1
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
function getDataFromDataTransfer(dataTransfer, typesToTry, defaultValue) {
|
|
252
|
+
const result = typesToTry.reduce((resultSoFar, typeToTry)=>resultSoFar || dataTransfer.getData(typeToTry)
|
|
253
|
+
, '');
|
|
254
|
+
return result != null ? result : defaultValue;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const nativeTypesConfig = {
|
|
258
|
+
[FILE]: {
|
|
259
|
+
exposeProperties: {
|
|
260
|
+
files: (dataTransfer)=>Array.prototype.slice.call(dataTransfer.files)
|
|
261
|
+
,
|
|
262
|
+
items: (dataTransfer)=>dataTransfer.items
|
|
263
|
+
,
|
|
264
|
+
dataTransfer: (dataTransfer)=>dataTransfer
|
|
265
|
+
},
|
|
266
|
+
matchesTypes: [
|
|
267
|
+
'Files'
|
|
268
|
+
]
|
|
269
|
+
},
|
|
270
|
+
[HTML]: {
|
|
271
|
+
exposeProperties: {
|
|
272
|
+
html: (dataTransfer, matchesTypes)=>getDataFromDataTransfer(dataTransfer, matchesTypes, '')
|
|
273
|
+
,
|
|
274
|
+
dataTransfer: (dataTransfer)=>dataTransfer
|
|
275
|
+
},
|
|
276
|
+
matchesTypes: [
|
|
277
|
+
'Html',
|
|
278
|
+
'text/html'
|
|
279
|
+
]
|
|
280
|
+
},
|
|
281
|
+
[URL$1]: {
|
|
282
|
+
exposeProperties: {
|
|
283
|
+
urls: (dataTransfer, matchesTypes)=>getDataFromDataTransfer(dataTransfer, matchesTypes, '').split('\n')
|
|
284
|
+
,
|
|
285
|
+
dataTransfer: (dataTransfer)=>dataTransfer
|
|
286
|
+
},
|
|
287
|
+
matchesTypes: [
|
|
288
|
+
'Url',
|
|
289
|
+
'text/uri-list'
|
|
290
|
+
]
|
|
291
|
+
},
|
|
292
|
+
[TEXT]: {
|
|
293
|
+
exposeProperties: {
|
|
294
|
+
text: (dataTransfer, matchesTypes)=>getDataFromDataTransfer(dataTransfer, matchesTypes, '')
|
|
295
|
+
,
|
|
296
|
+
dataTransfer: (dataTransfer)=>dataTransfer
|
|
297
|
+
},
|
|
298
|
+
matchesTypes: [
|
|
299
|
+
'Text',
|
|
300
|
+
'text/plain'
|
|
301
|
+
]
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
function createNativeDragSource(type, dataTransfer) {
|
|
306
|
+
const config = nativeTypesConfig[type];
|
|
307
|
+
if (!config) {
|
|
308
|
+
throw new Error(`native type ${type} has no configuration`);
|
|
309
|
+
}
|
|
310
|
+
const result = new NativeDragSource(config);
|
|
311
|
+
result.loadDataTransfer(dataTransfer);
|
|
312
|
+
return result;
|
|
313
|
+
}
|
|
314
|
+
function matchNativeItemType(dataTransfer) {
|
|
315
|
+
if (!dataTransfer) {
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
const dataTransferTypes = Array.prototype.slice.call(dataTransfer.types || []);
|
|
319
|
+
return Object.keys(nativeTypesConfig).filter((nativeItemType)=>{
|
|
320
|
+
const typeConfig = nativeTypesConfig[nativeItemType];
|
|
321
|
+
if (!(typeConfig === null || typeConfig === void 0 ? void 0 : typeConfig.matchesTypes)) {
|
|
322
|
+
return false;
|
|
323
|
+
}
|
|
324
|
+
return typeConfig.matchesTypes.some((t)=>dataTransferTypes.indexOf(t) > -1
|
|
325
|
+
);
|
|
326
|
+
})[0] || null;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const isFirefox = memoize(()=>/firefox/i.test(navigator.userAgent)
|
|
330
|
+
);
|
|
331
|
+
const isSafari = memoize(()=>Boolean(window.safari)
|
|
332
|
+
);
|
|
333
|
+
|
|
334
|
+
class MonotonicInterpolant {
|
|
335
|
+
interpolate(x) {
|
|
336
|
+
const { xs , ys , c1s , c2s , c3s } = this;
|
|
337
|
+
// The rightmost point in the dataset should give an exact result
|
|
338
|
+
let i = xs.length - 1;
|
|
339
|
+
if (x === xs[i]) {
|
|
340
|
+
return ys[i];
|
|
341
|
+
}
|
|
342
|
+
// Search for the interval x is in, returning the corresponding y if x is one of the original xs
|
|
343
|
+
let low = 0;
|
|
344
|
+
let high = c3s.length - 1;
|
|
345
|
+
let mid;
|
|
346
|
+
while(low <= high){
|
|
347
|
+
mid = Math.floor(0.5 * (low + high));
|
|
348
|
+
const xHere = xs[mid];
|
|
349
|
+
if (xHere < x) {
|
|
350
|
+
low = mid + 1;
|
|
351
|
+
} else if (xHere > x) {
|
|
352
|
+
high = mid - 1;
|
|
353
|
+
} else {
|
|
354
|
+
return ys[mid];
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
i = Math.max(0, high);
|
|
358
|
+
// Interpolate
|
|
359
|
+
const diff = x - xs[i];
|
|
360
|
+
const diffSq = diff * diff;
|
|
361
|
+
return ys[i] + c1s[i] * diff + c2s[i] * diffSq + c3s[i] * diff * diffSq;
|
|
362
|
+
}
|
|
363
|
+
constructor(xs, ys){
|
|
364
|
+
const { length } = xs;
|
|
365
|
+
// Rearrange xs and ys so that xs is sorted
|
|
366
|
+
const indexes = [];
|
|
367
|
+
for(let i = 0; i < length; i++){
|
|
368
|
+
indexes.push(i);
|
|
369
|
+
}
|
|
370
|
+
indexes.sort((a, b)=>xs[a] < xs[b] ? -1 : 1
|
|
371
|
+
);
|
|
372
|
+
const dxs = [];
|
|
373
|
+
const ms = [];
|
|
374
|
+
let dx;
|
|
375
|
+
let dy;
|
|
376
|
+
for(let i1 = 0; i1 < length - 1; i1++){
|
|
377
|
+
dx = xs[i1 + 1] - xs[i1];
|
|
378
|
+
dy = ys[i1 + 1] - ys[i1];
|
|
379
|
+
dxs.push(dx);
|
|
380
|
+
ms.push(dy / dx);
|
|
381
|
+
}
|
|
382
|
+
// Get degree-1 coefficients
|
|
383
|
+
const c1s = [
|
|
384
|
+
ms[0]
|
|
385
|
+
];
|
|
386
|
+
for(let i2 = 0; i2 < dxs.length - 1; i2++){
|
|
387
|
+
const m2 = ms[i2];
|
|
388
|
+
const mNext = ms[i2 + 1];
|
|
389
|
+
if (m2 * mNext <= 0) {
|
|
390
|
+
c1s.push(0);
|
|
391
|
+
} else {
|
|
392
|
+
dx = dxs[i2];
|
|
393
|
+
const dxNext = dxs[i2 + 1];
|
|
394
|
+
const common = dx + dxNext;
|
|
395
|
+
c1s.push(3 * common / ((common + dxNext) / m2 + (common + dx) / mNext));
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
c1s.push(ms[ms.length - 1]);
|
|
399
|
+
// Get degree-2 and degree-3 coefficients
|
|
400
|
+
const c2s = [];
|
|
401
|
+
const c3s = [];
|
|
402
|
+
let m;
|
|
403
|
+
for(let i3 = 0; i3 < c1s.length - 1; i3++){
|
|
404
|
+
m = ms[i3];
|
|
405
|
+
const c1 = c1s[i3];
|
|
406
|
+
const invDx = 1 / dxs[i3];
|
|
407
|
+
const common = c1 + c1s[i3 + 1] - m - m;
|
|
408
|
+
c2s.push((m - c1 - common) * invDx);
|
|
409
|
+
c3s.push(common * invDx * invDx);
|
|
410
|
+
}
|
|
411
|
+
this.xs = xs;
|
|
412
|
+
this.ys = ys;
|
|
413
|
+
this.c1s = c1s;
|
|
414
|
+
this.c2s = c2s;
|
|
415
|
+
this.c3s = c3s;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
const ELEMENT_NODE$1 = 1;
|
|
420
|
+
function getNodeClientOffset$1(node) {
|
|
421
|
+
const el = node.nodeType === ELEMENT_NODE$1 ? node : node.parentElement;
|
|
422
|
+
if (!el) {
|
|
423
|
+
return null;
|
|
424
|
+
}
|
|
425
|
+
const { top , left } = el.getBoundingClientRect();
|
|
426
|
+
return {
|
|
427
|
+
x: left,
|
|
428
|
+
y: top
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
function getEventClientOffset$1(e) {
|
|
432
|
+
return {
|
|
433
|
+
x: e.clientX,
|
|
434
|
+
y: e.clientY
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
function isImageNode(node) {
|
|
438
|
+
var ref;
|
|
439
|
+
return node.nodeName === 'IMG' && (isFirefox() || !((ref = document.documentElement) === null || ref === void 0 ? void 0 : ref.contains(node)));
|
|
440
|
+
}
|
|
441
|
+
function getDragPreviewSize(isImage, dragPreview, sourceWidth, sourceHeight) {
|
|
442
|
+
let dragPreviewWidth = isImage ? dragPreview.width : sourceWidth;
|
|
443
|
+
let dragPreviewHeight = isImage ? dragPreview.height : sourceHeight;
|
|
444
|
+
// Work around @2x coordinate discrepancies in browsers
|
|
445
|
+
if (isSafari() && isImage) {
|
|
446
|
+
dragPreviewHeight /= window.devicePixelRatio;
|
|
447
|
+
dragPreviewWidth /= window.devicePixelRatio;
|
|
448
|
+
}
|
|
449
|
+
return {
|
|
450
|
+
dragPreviewWidth,
|
|
451
|
+
dragPreviewHeight
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
function getDragPreviewOffset(sourceNode, dragPreview, clientOffset, anchorPoint, offsetPoint) {
|
|
455
|
+
// The browsers will use the image intrinsic size under different conditions.
|
|
456
|
+
// Firefox only cares if it's an image, but WebKit also wants it to be detached.
|
|
457
|
+
const isImage = isImageNode(dragPreview);
|
|
458
|
+
const dragPreviewNode = isImage ? sourceNode : dragPreview;
|
|
459
|
+
const dragPreviewNodeOffsetFromClient = getNodeClientOffset$1(dragPreviewNode);
|
|
460
|
+
const offsetFromDragPreview = {
|
|
461
|
+
x: clientOffset.x - dragPreviewNodeOffsetFromClient.x,
|
|
462
|
+
y: clientOffset.y - dragPreviewNodeOffsetFromClient.y
|
|
463
|
+
};
|
|
464
|
+
const { offsetWidth: sourceWidth , offsetHeight: sourceHeight } = sourceNode;
|
|
465
|
+
const { anchorX , anchorY } = anchorPoint;
|
|
466
|
+
const { dragPreviewWidth , dragPreviewHeight } = getDragPreviewSize(isImage, dragPreview, sourceWidth, sourceHeight);
|
|
467
|
+
const calculateYOffset = ()=>{
|
|
468
|
+
const interpolantY = new MonotonicInterpolant([
|
|
469
|
+
0,
|
|
470
|
+
0.5,
|
|
471
|
+
1
|
|
472
|
+
], [
|
|
473
|
+
// Dock to the top
|
|
474
|
+
offsetFromDragPreview.y,
|
|
475
|
+
// Align at the center
|
|
476
|
+
(offsetFromDragPreview.y / sourceHeight) * dragPreviewHeight,
|
|
477
|
+
// Dock to the bottom
|
|
478
|
+
offsetFromDragPreview.y + dragPreviewHeight - sourceHeight,
|
|
479
|
+
]);
|
|
480
|
+
let y = interpolantY.interpolate(anchorY);
|
|
481
|
+
// Work around Safari 8 positioning bug
|
|
482
|
+
if (isSafari() && isImage) {
|
|
483
|
+
// We'll have to wait for @3x to see if this is entirely correct
|
|
484
|
+
y += (window.devicePixelRatio - 1) * dragPreviewHeight;
|
|
485
|
+
}
|
|
486
|
+
return y;
|
|
487
|
+
};
|
|
488
|
+
const calculateXOffset = ()=>{
|
|
489
|
+
// Interpolate coordinates depending on anchor point
|
|
490
|
+
// If you know a simpler way to do this, let me know
|
|
491
|
+
const interpolantX = new MonotonicInterpolant([
|
|
492
|
+
0,
|
|
493
|
+
0.5,
|
|
494
|
+
1
|
|
495
|
+
], [
|
|
496
|
+
// Dock to the left
|
|
497
|
+
offsetFromDragPreview.x,
|
|
498
|
+
// Align at the center
|
|
499
|
+
(offsetFromDragPreview.x / sourceWidth) * dragPreviewWidth,
|
|
500
|
+
// Dock to the right
|
|
501
|
+
offsetFromDragPreview.x + dragPreviewWidth - sourceWidth,
|
|
502
|
+
]);
|
|
503
|
+
return interpolantX.interpolate(anchorX);
|
|
504
|
+
};
|
|
505
|
+
// Force offsets if specified in the options.
|
|
506
|
+
const { offsetX , offsetY } = offsetPoint;
|
|
507
|
+
const isManualOffsetX = offsetX === 0 || offsetX;
|
|
508
|
+
const isManualOffsetY = offsetY === 0 || offsetY;
|
|
509
|
+
return {
|
|
510
|
+
x: isManualOffsetX ? offsetX : calculateXOffset(),
|
|
511
|
+
y: isManualOffsetY ? offsetY : calculateYOffset()
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
let OptionsReader$1 = class OptionsReader {
|
|
516
|
+
get window() {
|
|
517
|
+
if (this.globalContext) {
|
|
518
|
+
return this.globalContext;
|
|
519
|
+
} else if (typeof window !== 'undefined') {
|
|
520
|
+
return window;
|
|
521
|
+
}
|
|
522
|
+
return undefined;
|
|
523
|
+
}
|
|
524
|
+
get document() {
|
|
525
|
+
var ref;
|
|
526
|
+
if ((ref = this.globalContext) === null || ref === void 0 ? void 0 : ref.document) {
|
|
527
|
+
return this.globalContext.document;
|
|
528
|
+
} else if (this.window) {
|
|
529
|
+
return this.window.document;
|
|
530
|
+
} else {
|
|
531
|
+
return undefined;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
get rootElement() {
|
|
535
|
+
var ref;
|
|
536
|
+
return ((ref = this.optionsArgs) === null || ref === void 0 ? void 0 : ref.rootElement) || this.window;
|
|
537
|
+
}
|
|
538
|
+
constructor(globalContext, options){
|
|
539
|
+
this.ownerDocument = null;
|
|
540
|
+
this.globalContext = globalContext;
|
|
541
|
+
this.optionsArgs = options;
|
|
542
|
+
}
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
function _defineProperty(obj, key, value) {
|
|
546
|
+
if (key in obj) {
|
|
547
|
+
Object.defineProperty(obj, key, {
|
|
548
|
+
value: value,
|
|
549
|
+
enumerable: true,
|
|
550
|
+
configurable: true,
|
|
551
|
+
writable: true
|
|
552
|
+
});
|
|
553
|
+
} else {
|
|
554
|
+
obj[key] = value;
|
|
555
|
+
}
|
|
556
|
+
return obj;
|
|
557
|
+
}
|
|
558
|
+
function _objectSpread(target) {
|
|
559
|
+
for(var i = 1; i < arguments.length; i++){
|
|
560
|
+
var source = arguments[i] != null ? arguments[i] : {};
|
|
561
|
+
var ownKeys = Object.keys(source);
|
|
562
|
+
if (typeof Object.getOwnPropertySymbols === 'function') {
|
|
563
|
+
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
|
|
564
|
+
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
|
|
565
|
+
}));
|
|
566
|
+
}
|
|
567
|
+
ownKeys.forEach(function(key) {
|
|
568
|
+
_defineProperty(target, key, source[key]);
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
return target;
|
|
572
|
+
}
|
|
573
|
+
class HTML5BackendImpl {
|
|
574
|
+
/**
|
|
575
|
+
* Generate profiling statistics for the HTML5Backend.
|
|
576
|
+
*/ profile() {
|
|
577
|
+
var ref, ref1;
|
|
578
|
+
return {
|
|
579
|
+
sourcePreviewNodes: this.sourcePreviewNodes.size,
|
|
580
|
+
sourcePreviewNodeOptions: this.sourcePreviewNodeOptions.size,
|
|
581
|
+
sourceNodeOptions: this.sourceNodeOptions.size,
|
|
582
|
+
sourceNodes: this.sourceNodes.size,
|
|
583
|
+
dragStartSourceIds: ((ref = this.dragStartSourceIds) === null || ref === void 0 ? void 0 : ref.length) || 0,
|
|
584
|
+
dropTargetIds: this.dropTargetIds.length,
|
|
585
|
+
dragEnterTargetIds: this.dragEnterTargetIds.length,
|
|
586
|
+
dragOverTargetIds: ((ref1 = this.dragOverTargetIds) === null || ref1 === void 0 ? void 0 : ref1.length) || 0
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
// public for test
|
|
590
|
+
get window() {
|
|
591
|
+
return this.options.window;
|
|
592
|
+
}
|
|
593
|
+
get document() {
|
|
594
|
+
return this.options.document;
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* Get the root element to use for event subscriptions
|
|
598
|
+
*/ get rootElement() {
|
|
599
|
+
return this.options.rootElement;
|
|
600
|
+
}
|
|
601
|
+
setup() {
|
|
602
|
+
const root = this.rootElement;
|
|
603
|
+
if (root === undefined) {
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
if (root.__isReactDndBackendSetUp) {
|
|
607
|
+
throw new Error('Cannot have two HTML5 backends at the same time.');
|
|
608
|
+
}
|
|
609
|
+
root.__isReactDndBackendSetUp = true;
|
|
610
|
+
this.addEventListeners(root);
|
|
611
|
+
}
|
|
612
|
+
teardown() {
|
|
613
|
+
const root = this.rootElement;
|
|
614
|
+
if (root === undefined) {
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
root.__isReactDndBackendSetUp = false;
|
|
618
|
+
this.removeEventListeners(this.rootElement);
|
|
619
|
+
this.clearCurrentDragSourceNode();
|
|
620
|
+
if (this.asyncEndDragFrameId) {
|
|
621
|
+
var ref;
|
|
622
|
+
(ref = this.window) === null || ref === void 0 ? void 0 : ref.cancelAnimationFrame(this.asyncEndDragFrameId);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
connectDragPreview(sourceId, node, options) {
|
|
626
|
+
this.sourcePreviewNodeOptions.set(sourceId, options);
|
|
627
|
+
this.sourcePreviewNodes.set(sourceId, node);
|
|
628
|
+
return ()=>{
|
|
629
|
+
this.sourcePreviewNodes.delete(sourceId);
|
|
630
|
+
this.sourcePreviewNodeOptions.delete(sourceId);
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
connectDragSource(sourceId, node, options) {
|
|
634
|
+
this.sourceNodes.set(sourceId, node);
|
|
635
|
+
this.sourceNodeOptions.set(sourceId, options);
|
|
636
|
+
const handleDragStart = (e)=>this.handleDragStart(e, sourceId)
|
|
637
|
+
;
|
|
638
|
+
const handleSelectStart = (e)=>this.handleSelectStart(e)
|
|
639
|
+
;
|
|
640
|
+
node.setAttribute('draggable', 'true');
|
|
641
|
+
node.addEventListener('dragstart', handleDragStart);
|
|
642
|
+
node.addEventListener('selectstart', handleSelectStart);
|
|
643
|
+
return ()=>{
|
|
644
|
+
this.sourceNodes.delete(sourceId);
|
|
645
|
+
this.sourceNodeOptions.delete(sourceId);
|
|
646
|
+
node.removeEventListener('dragstart', handleDragStart);
|
|
647
|
+
node.removeEventListener('selectstart', handleSelectStart);
|
|
648
|
+
node.setAttribute('draggable', 'false');
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
connectDropTarget(targetId, node) {
|
|
652
|
+
const handleDragEnter = (e)=>this.handleDragEnter(e, targetId)
|
|
653
|
+
;
|
|
654
|
+
const handleDragOver = (e)=>this.handleDragOver(e, targetId)
|
|
655
|
+
;
|
|
656
|
+
const handleDrop = (e)=>this.handleDrop(e, targetId)
|
|
657
|
+
;
|
|
658
|
+
node.addEventListener('dragenter', handleDragEnter);
|
|
659
|
+
node.addEventListener('dragover', handleDragOver);
|
|
660
|
+
node.addEventListener('drop', handleDrop);
|
|
661
|
+
return ()=>{
|
|
662
|
+
node.removeEventListener('dragenter', handleDragEnter);
|
|
663
|
+
node.removeEventListener('dragover', handleDragOver);
|
|
664
|
+
node.removeEventListener('drop', handleDrop);
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
addEventListeners(target) {
|
|
668
|
+
// SSR Fix (https://github.com/react-dnd/react-dnd/pull/813
|
|
669
|
+
if (!target.addEventListener) {
|
|
670
|
+
return;
|
|
671
|
+
}
|
|
672
|
+
target.addEventListener('dragstart', this.handleTopDragStart);
|
|
673
|
+
target.addEventListener('dragstart', this.handleTopDragStartCapture, true);
|
|
674
|
+
target.addEventListener('dragend', this.handleTopDragEndCapture, true);
|
|
675
|
+
target.addEventListener('dragenter', this.handleTopDragEnter);
|
|
676
|
+
target.addEventListener('dragenter', this.handleTopDragEnterCapture, true);
|
|
677
|
+
target.addEventListener('dragleave', this.handleTopDragLeaveCapture, true);
|
|
678
|
+
target.addEventListener('dragover', this.handleTopDragOver);
|
|
679
|
+
target.addEventListener('dragover', this.handleTopDragOverCapture, true);
|
|
680
|
+
target.addEventListener('drop', this.handleTopDrop);
|
|
681
|
+
target.addEventListener('drop', this.handleTopDropCapture, true);
|
|
682
|
+
}
|
|
683
|
+
removeEventListeners(target) {
|
|
684
|
+
// SSR Fix (https://github.com/react-dnd/react-dnd/pull/813
|
|
685
|
+
if (!target.removeEventListener) {
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
target.removeEventListener('dragstart', this.handleTopDragStart);
|
|
689
|
+
target.removeEventListener('dragstart', this.handleTopDragStartCapture, true);
|
|
690
|
+
target.removeEventListener('dragend', this.handleTopDragEndCapture, true);
|
|
691
|
+
target.removeEventListener('dragenter', this.handleTopDragEnter);
|
|
692
|
+
target.removeEventListener('dragenter', this.handleTopDragEnterCapture, true);
|
|
693
|
+
target.removeEventListener('dragleave', this.handleTopDragLeaveCapture, true);
|
|
694
|
+
target.removeEventListener('dragover', this.handleTopDragOver);
|
|
695
|
+
target.removeEventListener('dragover', this.handleTopDragOverCapture, true);
|
|
696
|
+
target.removeEventListener('drop', this.handleTopDrop);
|
|
697
|
+
target.removeEventListener('drop', this.handleTopDropCapture, true);
|
|
698
|
+
}
|
|
699
|
+
getCurrentSourceNodeOptions() {
|
|
700
|
+
const sourceId = this.monitor.getSourceId();
|
|
701
|
+
const sourceNodeOptions = this.sourceNodeOptions.get(sourceId);
|
|
702
|
+
return _objectSpread({
|
|
703
|
+
dropEffect: this.altKeyPressed ? 'copy' : 'move'
|
|
704
|
+
}, sourceNodeOptions || {});
|
|
705
|
+
}
|
|
706
|
+
getCurrentDropEffect() {
|
|
707
|
+
if (this.isDraggingNativeItem()) {
|
|
708
|
+
// It makes more sense to default to 'copy' for native resources
|
|
709
|
+
return 'copy';
|
|
710
|
+
}
|
|
711
|
+
return this.getCurrentSourceNodeOptions().dropEffect;
|
|
712
|
+
}
|
|
713
|
+
getCurrentSourcePreviewNodeOptions() {
|
|
714
|
+
const sourceId = this.monitor.getSourceId();
|
|
715
|
+
const sourcePreviewNodeOptions = this.sourcePreviewNodeOptions.get(sourceId);
|
|
716
|
+
return _objectSpread({
|
|
717
|
+
anchorX: 0.5,
|
|
718
|
+
anchorY: 0.5,
|
|
719
|
+
captureDraggingState: false
|
|
720
|
+
}, sourcePreviewNodeOptions || {});
|
|
721
|
+
}
|
|
722
|
+
isDraggingNativeItem() {
|
|
723
|
+
const itemType = this.monitor.getItemType();
|
|
724
|
+
return Object.keys(NativeTypes).some((key)=>NativeTypes[key] === itemType
|
|
725
|
+
);
|
|
726
|
+
}
|
|
727
|
+
beginDragNativeItem(type, dataTransfer) {
|
|
728
|
+
this.clearCurrentDragSourceNode();
|
|
729
|
+
this.currentNativeSource = createNativeDragSource(type, dataTransfer);
|
|
730
|
+
this.currentNativeHandle = this.registry.addSource(type, this.currentNativeSource);
|
|
731
|
+
this.actions.beginDrag([
|
|
732
|
+
this.currentNativeHandle
|
|
733
|
+
]);
|
|
734
|
+
}
|
|
735
|
+
setCurrentDragSourceNode(node) {
|
|
736
|
+
this.clearCurrentDragSourceNode();
|
|
737
|
+
this.currentDragSourceNode = node;
|
|
738
|
+
// A timeout of > 0 is necessary to resolve Firefox issue referenced
|
|
739
|
+
// See:
|
|
740
|
+
// * https://github.com/react-dnd/react-dnd/pull/928
|
|
741
|
+
// * https://github.com/react-dnd/react-dnd/issues/869
|
|
742
|
+
const MOUSE_MOVE_TIMEOUT = 1000;
|
|
743
|
+
// Receiving a mouse event in the middle of a dragging operation
|
|
744
|
+
// means it has ended and the drag source node disappeared from DOM,
|
|
745
|
+
// so the browser didn't dispatch the dragend event.
|
|
746
|
+
//
|
|
747
|
+
// We need to wait before we start listening for mousemove events.
|
|
748
|
+
// This is needed because the drag preview needs to be drawn or else it fires an 'mousemove' event
|
|
749
|
+
// immediately in some browsers.
|
|
750
|
+
//
|
|
751
|
+
// See:
|
|
752
|
+
// * https://github.com/react-dnd/react-dnd/pull/928
|
|
753
|
+
// * https://github.com/react-dnd/react-dnd/issues/869
|
|
754
|
+
//
|
|
755
|
+
this.mouseMoveTimeoutTimer = setTimeout(()=>{
|
|
756
|
+
var ref;
|
|
757
|
+
return (ref = this.rootElement) === null || ref === void 0 ? void 0 : ref.addEventListener('mousemove', this.endDragIfSourceWasRemovedFromDOM, true);
|
|
758
|
+
}, MOUSE_MOVE_TIMEOUT);
|
|
759
|
+
}
|
|
760
|
+
clearCurrentDragSourceNode() {
|
|
761
|
+
if (this.currentDragSourceNode) {
|
|
762
|
+
this.currentDragSourceNode = null;
|
|
763
|
+
if (this.rootElement) {
|
|
764
|
+
var ref;
|
|
765
|
+
(ref = this.window) === null || ref === void 0 ? void 0 : ref.clearTimeout(this.mouseMoveTimeoutTimer || undefined);
|
|
766
|
+
this.rootElement.removeEventListener('mousemove', this.endDragIfSourceWasRemovedFromDOM, true);
|
|
767
|
+
}
|
|
768
|
+
this.mouseMoveTimeoutTimer = null;
|
|
769
|
+
return true;
|
|
770
|
+
}
|
|
771
|
+
return false;
|
|
772
|
+
}
|
|
773
|
+
handleDragStart(e, sourceId) {
|
|
774
|
+
if (e.defaultPrevented) {
|
|
775
|
+
return;
|
|
776
|
+
}
|
|
777
|
+
if (!this.dragStartSourceIds) {
|
|
778
|
+
this.dragStartSourceIds = [];
|
|
779
|
+
}
|
|
780
|
+
this.dragStartSourceIds.unshift(sourceId);
|
|
781
|
+
}
|
|
782
|
+
handleDragEnter(_e, targetId) {
|
|
783
|
+
this.dragEnterTargetIds.unshift(targetId);
|
|
784
|
+
}
|
|
785
|
+
handleDragOver(_e, targetId) {
|
|
786
|
+
if (this.dragOverTargetIds === null) {
|
|
787
|
+
this.dragOverTargetIds = [];
|
|
788
|
+
}
|
|
789
|
+
this.dragOverTargetIds.unshift(targetId);
|
|
790
|
+
}
|
|
791
|
+
handleDrop(_e, targetId) {
|
|
792
|
+
this.dropTargetIds.unshift(targetId);
|
|
793
|
+
}
|
|
794
|
+
constructor(manager, globalContext, options){
|
|
795
|
+
this.sourcePreviewNodes = new Map();
|
|
796
|
+
this.sourcePreviewNodeOptions = new Map();
|
|
797
|
+
this.sourceNodes = new Map();
|
|
798
|
+
this.sourceNodeOptions = new Map();
|
|
799
|
+
this.dragStartSourceIds = null;
|
|
800
|
+
this.dropTargetIds = [];
|
|
801
|
+
this.dragEnterTargetIds = [];
|
|
802
|
+
this.currentNativeSource = null;
|
|
803
|
+
this.currentNativeHandle = null;
|
|
804
|
+
this.currentDragSourceNode = null;
|
|
805
|
+
this.altKeyPressed = false;
|
|
806
|
+
this.mouseMoveTimeoutTimer = null;
|
|
807
|
+
this.asyncEndDragFrameId = null;
|
|
808
|
+
this.dragOverTargetIds = null;
|
|
809
|
+
this.lastClientOffset = null;
|
|
810
|
+
this.hoverRafId = null;
|
|
811
|
+
this.getSourceClientOffset = (sourceId)=>{
|
|
812
|
+
const source = this.sourceNodes.get(sourceId);
|
|
813
|
+
return source && getNodeClientOffset$1(source) || null;
|
|
814
|
+
};
|
|
815
|
+
this.endDragNativeItem = ()=>{
|
|
816
|
+
if (!this.isDraggingNativeItem()) {
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
819
|
+
this.actions.endDrag();
|
|
820
|
+
if (this.currentNativeHandle) {
|
|
821
|
+
this.registry.removeSource(this.currentNativeHandle);
|
|
822
|
+
}
|
|
823
|
+
this.currentNativeHandle = null;
|
|
824
|
+
this.currentNativeSource = null;
|
|
825
|
+
};
|
|
826
|
+
this.isNodeInDocument = (node)=>{
|
|
827
|
+
// Check the node either in the main document or in the current context
|
|
828
|
+
return Boolean(node && this.document && this.document.body && this.document.body.contains(node));
|
|
829
|
+
};
|
|
830
|
+
this.endDragIfSourceWasRemovedFromDOM = ()=>{
|
|
831
|
+
const node = this.currentDragSourceNode;
|
|
832
|
+
if (node == null || this.isNodeInDocument(node)) {
|
|
833
|
+
return;
|
|
834
|
+
}
|
|
835
|
+
if (this.clearCurrentDragSourceNode() && this.monitor.isDragging()) {
|
|
836
|
+
this.actions.endDrag();
|
|
837
|
+
}
|
|
838
|
+
this.cancelHover();
|
|
839
|
+
};
|
|
840
|
+
this.scheduleHover = (dragOverTargetIds)=>{
|
|
841
|
+
if (this.hoverRafId === null && typeof requestAnimationFrame !== 'undefined') {
|
|
842
|
+
this.hoverRafId = requestAnimationFrame(()=>{
|
|
843
|
+
if (this.monitor.isDragging()) {
|
|
844
|
+
this.actions.hover(dragOverTargetIds || [], {
|
|
845
|
+
clientOffset: this.lastClientOffset
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
this.hoverRafId = null;
|
|
849
|
+
});
|
|
850
|
+
}
|
|
851
|
+
};
|
|
852
|
+
this.cancelHover = ()=>{
|
|
853
|
+
if (this.hoverRafId !== null && typeof cancelAnimationFrame !== 'undefined') {
|
|
854
|
+
cancelAnimationFrame(this.hoverRafId);
|
|
855
|
+
this.hoverRafId = null;
|
|
856
|
+
}
|
|
857
|
+
};
|
|
858
|
+
this.handleTopDragStartCapture = ()=>{
|
|
859
|
+
this.clearCurrentDragSourceNode();
|
|
860
|
+
this.dragStartSourceIds = [];
|
|
861
|
+
};
|
|
862
|
+
this.handleTopDragStart = (e)=>{
|
|
863
|
+
if (e.defaultPrevented) {
|
|
864
|
+
return;
|
|
865
|
+
}
|
|
866
|
+
const { dragStartSourceIds } = this;
|
|
867
|
+
this.dragStartSourceIds = null;
|
|
868
|
+
const clientOffset = getEventClientOffset$1(e);
|
|
869
|
+
// Avoid crashing if we missed a drop event or our previous drag died
|
|
870
|
+
if (this.monitor.isDragging()) {
|
|
871
|
+
this.actions.endDrag();
|
|
872
|
+
this.cancelHover();
|
|
873
|
+
}
|
|
874
|
+
// Don't publish the source just yet (see why below)
|
|
875
|
+
this.actions.beginDrag(dragStartSourceIds || [], {
|
|
876
|
+
publishSource: false,
|
|
877
|
+
getSourceClientOffset: this.getSourceClientOffset,
|
|
878
|
+
clientOffset
|
|
879
|
+
});
|
|
880
|
+
const { dataTransfer } = e;
|
|
881
|
+
const nativeType = matchNativeItemType(dataTransfer);
|
|
882
|
+
if (this.monitor.isDragging()) {
|
|
883
|
+
if (dataTransfer && typeof dataTransfer.setDragImage === 'function') {
|
|
884
|
+
// Use custom drag image if user specifies it.
|
|
885
|
+
// If child drag source refuses drag but parent agrees,
|
|
886
|
+
// use parent's node as drag image. Neither works in IE though.
|
|
887
|
+
const sourceId = this.monitor.getSourceId();
|
|
888
|
+
const sourceNode = this.sourceNodes.get(sourceId);
|
|
889
|
+
const dragPreview = this.sourcePreviewNodes.get(sourceId) || sourceNode;
|
|
890
|
+
if (dragPreview) {
|
|
891
|
+
const { anchorX , anchorY , offsetX , offsetY } = this.getCurrentSourcePreviewNodeOptions();
|
|
892
|
+
const anchorPoint = {
|
|
893
|
+
anchorX,
|
|
894
|
+
anchorY
|
|
895
|
+
};
|
|
896
|
+
const offsetPoint = {
|
|
897
|
+
offsetX,
|
|
898
|
+
offsetY
|
|
899
|
+
};
|
|
900
|
+
const dragPreviewOffset = getDragPreviewOffset(sourceNode, dragPreview, clientOffset, anchorPoint, offsetPoint);
|
|
901
|
+
dataTransfer.setDragImage(dragPreview, dragPreviewOffset.x, dragPreviewOffset.y);
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
try {
|
|
905
|
+
// Firefox won't drag without setting data
|
|
906
|
+
dataTransfer === null || dataTransfer === void 0 ? void 0 : dataTransfer.setData('application/json', {});
|
|
907
|
+
} catch (err) {
|
|
908
|
+
// IE doesn't support MIME types in setData
|
|
909
|
+
}
|
|
910
|
+
// Store drag source node so we can check whether
|
|
911
|
+
// it is removed from DOM and trigger endDrag manually.
|
|
912
|
+
this.setCurrentDragSourceNode(e.target);
|
|
913
|
+
// Now we are ready to publish the drag source.. or are we not?
|
|
914
|
+
const { captureDraggingState } = this.getCurrentSourcePreviewNodeOptions();
|
|
915
|
+
if (!captureDraggingState) {
|
|
916
|
+
// Usually we want to publish it in the next tick so that browser
|
|
917
|
+
// is able to screenshot the current (not yet dragging) state.
|
|
918
|
+
//
|
|
919
|
+
// It also neatly avoids a situation where render() returns null
|
|
920
|
+
// in the same tick for the source element, and browser freaks out.
|
|
921
|
+
setTimeout(()=>this.actions.publishDragSource()
|
|
922
|
+
, 0);
|
|
923
|
+
} else {
|
|
924
|
+
// In some cases the user may want to override this behavior, e.g.
|
|
925
|
+
// to work around IE not supporting custom drag previews.
|
|
926
|
+
//
|
|
927
|
+
// When using a custom drag layer, the only way to prevent
|
|
928
|
+
// the default drag preview from drawing in IE is to screenshot
|
|
929
|
+
// the dragging state in which the node itself has zero opacity
|
|
930
|
+
// and height. In this case, though, returning null from render()
|
|
931
|
+
// will abruptly end the dragging, which is not obvious.
|
|
932
|
+
//
|
|
933
|
+
// This is the reason such behavior is strictly opt-in.
|
|
934
|
+
this.actions.publishDragSource();
|
|
935
|
+
}
|
|
936
|
+
} else if (nativeType) {
|
|
937
|
+
// A native item (such as URL) dragged from inside the document
|
|
938
|
+
this.beginDragNativeItem(nativeType);
|
|
939
|
+
} else if (dataTransfer && !dataTransfer.types && (e.target && !e.target.hasAttribute || !e.target.hasAttribute('draggable'))) {
|
|
940
|
+
// Looks like a Safari bug: dataTransfer.types is null, but there was no draggable.
|
|
941
|
+
// Just let it drag. It's a native type (URL or text) and will be picked up in
|
|
942
|
+
// dragenter handler.
|
|
943
|
+
return;
|
|
944
|
+
} else {
|
|
945
|
+
// If by this time no drag source reacted, tell browser not to drag.
|
|
946
|
+
e.preventDefault();
|
|
947
|
+
}
|
|
948
|
+
};
|
|
949
|
+
this.handleTopDragEndCapture = ()=>{
|
|
950
|
+
if (this.clearCurrentDragSourceNode() && this.monitor.isDragging()) {
|
|
951
|
+
// Firefox can dispatch this event in an infinite loop
|
|
952
|
+
// if dragend handler does something like showing an alert.
|
|
953
|
+
// Only proceed if we have not handled it already.
|
|
954
|
+
this.actions.endDrag();
|
|
955
|
+
}
|
|
956
|
+
this.cancelHover();
|
|
957
|
+
};
|
|
958
|
+
this.handleTopDragEnterCapture = (e)=>{
|
|
959
|
+
this.dragEnterTargetIds = [];
|
|
960
|
+
if (this.isDraggingNativeItem()) {
|
|
961
|
+
var ref;
|
|
962
|
+
(ref = this.currentNativeSource) === null || ref === void 0 ? void 0 : ref.loadDataTransfer(e.dataTransfer);
|
|
963
|
+
}
|
|
964
|
+
const isFirstEnter = this.enterLeaveCounter.enter(e.target);
|
|
965
|
+
if (!isFirstEnter || this.monitor.isDragging()) {
|
|
966
|
+
return;
|
|
967
|
+
}
|
|
968
|
+
const { dataTransfer } = e;
|
|
969
|
+
const nativeType = matchNativeItemType(dataTransfer);
|
|
970
|
+
if (nativeType) {
|
|
971
|
+
// A native item (such as file or URL) dragged from outside the document
|
|
972
|
+
this.beginDragNativeItem(nativeType, dataTransfer);
|
|
973
|
+
}
|
|
974
|
+
};
|
|
975
|
+
this.handleTopDragEnter = (e)=>{
|
|
976
|
+
const { dragEnterTargetIds } = this;
|
|
977
|
+
this.dragEnterTargetIds = [];
|
|
978
|
+
if (!this.monitor.isDragging()) {
|
|
979
|
+
// This is probably a native item type we don't understand.
|
|
980
|
+
return;
|
|
981
|
+
}
|
|
982
|
+
this.altKeyPressed = e.altKey;
|
|
983
|
+
// If the target changes position as the result of `dragenter`, `dragover` might still
|
|
984
|
+
// get dispatched despite target being no longer there. The easy solution is to check
|
|
985
|
+
// whether there actually is a target before firing `hover`.
|
|
986
|
+
if (dragEnterTargetIds.length > 0) {
|
|
987
|
+
this.actions.hover(dragEnterTargetIds, {
|
|
988
|
+
clientOffset: getEventClientOffset$1(e)
|
|
989
|
+
});
|
|
990
|
+
}
|
|
991
|
+
const canDrop = dragEnterTargetIds.some((targetId)=>this.monitor.canDropOnTarget(targetId)
|
|
992
|
+
);
|
|
993
|
+
if (canDrop) {
|
|
994
|
+
// IE requires this to fire dragover events
|
|
995
|
+
e.preventDefault();
|
|
996
|
+
if (e.dataTransfer) {
|
|
997
|
+
e.dataTransfer.dropEffect = this.getCurrentDropEffect();
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
};
|
|
1001
|
+
this.handleTopDragOverCapture = (e)=>{
|
|
1002
|
+
this.dragOverTargetIds = [];
|
|
1003
|
+
if (this.isDraggingNativeItem()) {
|
|
1004
|
+
var ref;
|
|
1005
|
+
(ref = this.currentNativeSource) === null || ref === void 0 ? void 0 : ref.loadDataTransfer(e.dataTransfer);
|
|
1006
|
+
}
|
|
1007
|
+
};
|
|
1008
|
+
this.handleTopDragOver = (e)=>{
|
|
1009
|
+
const { dragOverTargetIds } = this;
|
|
1010
|
+
this.dragOverTargetIds = [];
|
|
1011
|
+
if (!this.monitor.isDragging()) {
|
|
1012
|
+
// This is probably a native item type we don't understand.
|
|
1013
|
+
// Prevent default "drop and blow away the whole document" action.
|
|
1014
|
+
e.preventDefault();
|
|
1015
|
+
if (e.dataTransfer) {
|
|
1016
|
+
e.dataTransfer.dropEffect = 'none';
|
|
1017
|
+
}
|
|
1018
|
+
return;
|
|
1019
|
+
}
|
|
1020
|
+
this.altKeyPressed = e.altKey;
|
|
1021
|
+
this.lastClientOffset = getEventClientOffset$1(e);
|
|
1022
|
+
this.scheduleHover(dragOverTargetIds);
|
|
1023
|
+
const canDrop = (dragOverTargetIds || []).some((targetId)=>this.monitor.canDropOnTarget(targetId)
|
|
1024
|
+
);
|
|
1025
|
+
if (canDrop) {
|
|
1026
|
+
// Show user-specified drop effect.
|
|
1027
|
+
e.preventDefault();
|
|
1028
|
+
if (e.dataTransfer) {
|
|
1029
|
+
e.dataTransfer.dropEffect = this.getCurrentDropEffect();
|
|
1030
|
+
}
|
|
1031
|
+
} else if (this.isDraggingNativeItem()) {
|
|
1032
|
+
// Don't show a nice cursor but still prevent default
|
|
1033
|
+
// "drop and blow away the whole document" action.
|
|
1034
|
+
e.preventDefault();
|
|
1035
|
+
} else {
|
|
1036
|
+
e.preventDefault();
|
|
1037
|
+
if (e.dataTransfer) {
|
|
1038
|
+
e.dataTransfer.dropEffect = 'none';
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
};
|
|
1042
|
+
this.handleTopDragLeaveCapture = (e)=>{
|
|
1043
|
+
if (this.isDraggingNativeItem()) {
|
|
1044
|
+
e.preventDefault();
|
|
1045
|
+
}
|
|
1046
|
+
const isLastLeave = this.enterLeaveCounter.leave(e.target);
|
|
1047
|
+
if (!isLastLeave) {
|
|
1048
|
+
return;
|
|
1049
|
+
}
|
|
1050
|
+
if (this.isDraggingNativeItem()) {
|
|
1051
|
+
setTimeout(()=>this.endDragNativeItem()
|
|
1052
|
+
, 0);
|
|
1053
|
+
}
|
|
1054
|
+
this.cancelHover();
|
|
1055
|
+
};
|
|
1056
|
+
this.handleTopDropCapture = (e)=>{
|
|
1057
|
+
this.dropTargetIds = [];
|
|
1058
|
+
if (this.isDraggingNativeItem()) {
|
|
1059
|
+
var ref;
|
|
1060
|
+
e.preventDefault();
|
|
1061
|
+
(ref = this.currentNativeSource) === null || ref === void 0 ? void 0 : ref.loadDataTransfer(e.dataTransfer);
|
|
1062
|
+
} else if (matchNativeItemType(e.dataTransfer)) {
|
|
1063
|
+
// Dragging some elements, like <a> and <img> may still behave like a native drag event,
|
|
1064
|
+
// even if the current drag event matches a user-defined type.
|
|
1065
|
+
// Stop the default behavior when we're not expecting a native item to be dropped.
|
|
1066
|
+
e.preventDefault();
|
|
1067
|
+
}
|
|
1068
|
+
this.enterLeaveCounter.reset();
|
|
1069
|
+
};
|
|
1070
|
+
this.handleTopDrop = (e)=>{
|
|
1071
|
+
const { dropTargetIds } = this;
|
|
1072
|
+
this.dropTargetIds = [];
|
|
1073
|
+
this.actions.hover(dropTargetIds, {
|
|
1074
|
+
clientOffset: getEventClientOffset$1(e)
|
|
1075
|
+
});
|
|
1076
|
+
this.actions.drop({
|
|
1077
|
+
dropEffect: this.getCurrentDropEffect()
|
|
1078
|
+
});
|
|
1079
|
+
if (this.isDraggingNativeItem()) {
|
|
1080
|
+
this.endDragNativeItem();
|
|
1081
|
+
} else if (this.monitor.isDragging()) {
|
|
1082
|
+
this.actions.endDrag();
|
|
1083
|
+
}
|
|
1084
|
+
this.cancelHover();
|
|
1085
|
+
};
|
|
1086
|
+
this.handleSelectStart = (e)=>{
|
|
1087
|
+
const target = e.target;
|
|
1088
|
+
// Only IE requires us to explicitly say
|
|
1089
|
+
// we want drag drop operation to start
|
|
1090
|
+
if (typeof target.dragDrop !== 'function') {
|
|
1091
|
+
return;
|
|
1092
|
+
}
|
|
1093
|
+
// Inputs and textareas should be selectable
|
|
1094
|
+
if (target.tagName === 'INPUT' || target.tagName === 'SELECT' || target.tagName === 'TEXTAREA' || target.isContentEditable) {
|
|
1095
|
+
return;
|
|
1096
|
+
}
|
|
1097
|
+
// For other targets, ask IE
|
|
1098
|
+
// to enable drag and drop
|
|
1099
|
+
e.preventDefault();
|
|
1100
|
+
target.dragDrop();
|
|
1101
|
+
};
|
|
1102
|
+
this.options = new OptionsReader$1(globalContext, options);
|
|
1103
|
+
this.actions = manager.getActions();
|
|
1104
|
+
this.monitor = manager.getMonitor();
|
|
1105
|
+
this.registry = manager.getRegistry();
|
|
1106
|
+
this.enterLeaveCounter = new EnterLeaveCounter(this.isNodeInDocument);
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
const HTML5Backend = function createBackend(manager, context, options) {
|
|
1111
|
+
return new HTML5BackendImpl(manager, context, options);
|
|
1112
|
+
};
|
|
1113
|
+
|
|
1114
|
+
var ListenerType;
|
|
1115
|
+
(function(ListenerType) {
|
|
1116
|
+
ListenerType["mouse"] = "mouse";
|
|
1117
|
+
ListenerType["touch"] = "touch";
|
|
1118
|
+
ListenerType["keyboard"] = "keyboard";
|
|
1119
|
+
})(ListenerType || (ListenerType = {}));
|
|
1120
|
+
|
|
1121
|
+
class OptionsReader {
|
|
1122
|
+
get delay() {
|
|
1123
|
+
var _delay;
|
|
1124
|
+
return (_delay = this.args.delay) !== null && _delay !== void 0 ? _delay : 0;
|
|
1125
|
+
}
|
|
1126
|
+
get scrollAngleRanges() {
|
|
1127
|
+
return this.args.scrollAngleRanges;
|
|
1128
|
+
}
|
|
1129
|
+
get getDropTargetElementsAtPoint() {
|
|
1130
|
+
return this.args.getDropTargetElementsAtPoint;
|
|
1131
|
+
}
|
|
1132
|
+
get ignoreContextMenu() {
|
|
1133
|
+
var _ignoreContextMenu;
|
|
1134
|
+
return (_ignoreContextMenu = this.args.ignoreContextMenu) !== null && _ignoreContextMenu !== void 0 ? _ignoreContextMenu : false;
|
|
1135
|
+
}
|
|
1136
|
+
get enableHoverOutsideTarget() {
|
|
1137
|
+
var _enableHoverOutsideTarget;
|
|
1138
|
+
return (_enableHoverOutsideTarget = this.args.enableHoverOutsideTarget) !== null && _enableHoverOutsideTarget !== void 0 ? _enableHoverOutsideTarget : false;
|
|
1139
|
+
}
|
|
1140
|
+
get enableKeyboardEvents() {
|
|
1141
|
+
var _enableKeyboardEvents;
|
|
1142
|
+
return (_enableKeyboardEvents = this.args.enableKeyboardEvents) !== null && _enableKeyboardEvents !== void 0 ? _enableKeyboardEvents : false;
|
|
1143
|
+
}
|
|
1144
|
+
get enableMouseEvents() {
|
|
1145
|
+
var _enableMouseEvents;
|
|
1146
|
+
return (_enableMouseEvents = this.args.enableMouseEvents) !== null && _enableMouseEvents !== void 0 ? _enableMouseEvents : false;
|
|
1147
|
+
}
|
|
1148
|
+
get enableTouchEvents() {
|
|
1149
|
+
var _enableTouchEvents;
|
|
1150
|
+
return (_enableTouchEvents = this.args.enableTouchEvents) !== null && _enableTouchEvents !== void 0 ? _enableTouchEvents : true;
|
|
1151
|
+
}
|
|
1152
|
+
get touchSlop() {
|
|
1153
|
+
return this.args.touchSlop || 0;
|
|
1154
|
+
}
|
|
1155
|
+
get delayTouchStart() {
|
|
1156
|
+
var ref, ref1;
|
|
1157
|
+
var ref2, ref3;
|
|
1158
|
+
return (ref3 = (ref2 = (ref = this.args) === null || ref === void 0 ? void 0 : ref.delayTouchStart) !== null && ref2 !== void 0 ? ref2 : (ref1 = this.args) === null || ref1 === void 0 ? void 0 : ref1.delay) !== null && ref3 !== void 0 ? ref3 : 0;
|
|
1159
|
+
}
|
|
1160
|
+
get delayMouseStart() {
|
|
1161
|
+
var ref, ref4;
|
|
1162
|
+
var ref5, ref6;
|
|
1163
|
+
return (ref6 = (ref5 = (ref = this.args) === null || ref === void 0 ? void 0 : ref.delayMouseStart) !== null && ref5 !== void 0 ? ref5 : (ref4 = this.args) === null || ref4 === void 0 ? void 0 : ref4.delay) !== null && ref6 !== void 0 ? ref6 : 0;
|
|
1164
|
+
}
|
|
1165
|
+
get window() {
|
|
1166
|
+
if (this.context && this.context.window) {
|
|
1167
|
+
return this.context.window;
|
|
1168
|
+
} else if (typeof window !== 'undefined') {
|
|
1169
|
+
return window;
|
|
1170
|
+
}
|
|
1171
|
+
return undefined;
|
|
1172
|
+
}
|
|
1173
|
+
get document() {
|
|
1174
|
+
var ref;
|
|
1175
|
+
if ((ref = this.context) === null || ref === void 0 ? void 0 : ref.document) {
|
|
1176
|
+
return this.context.document;
|
|
1177
|
+
}
|
|
1178
|
+
if (this.window) {
|
|
1179
|
+
return this.window.document;
|
|
1180
|
+
}
|
|
1181
|
+
return undefined;
|
|
1182
|
+
}
|
|
1183
|
+
get rootElement() {
|
|
1184
|
+
var ref;
|
|
1185
|
+
return ((ref = this.args) === null || ref === void 0 ? void 0 : ref.rootElement) || this.document;
|
|
1186
|
+
}
|
|
1187
|
+
constructor(args, context){
|
|
1188
|
+
this.args = args;
|
|
1189
|
+
this.context = context;
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
function distance(x1, y1, x2, y2) {
|
|
1194
|
+
return Math.sqrt(Math.pow(Math.abs(x2 - x1), 2) + Math.pow(Math.abs(y2 - y1), 2));
|
|
1195
|
+
}
|
|
1196
|
+
function inAngleRanges(x1, y1, x2, y2, angleRanges) {
|
|
1197
|
+
if (!angleRanges) {
|
|
1198
|
+
return false;
|
|
1199
|
+
}
|
|
1200
|
+
const angle = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI + 180;
|
|
1201
|
+
for(let i = 0; i < angleRanges.length; ++i){
|
|
1202
|
+
const ar = angleRanges[i];
|
|
1203
|
+
if (ar && (ar.start == null || angle >= ar.start) && (ar.end == null || angle <= ar.end)) {
|
|
1204
|
+
return true;
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
return false;
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
// Used for MouseEvent.buttons (note the s on the end).
|
|
1211
|
+
const MouseButtons = {
|
|
1212
|
+
Left: 1};
|
|
1213
|
+
// Used for e.button (note the lack of an s on the end).
|
|
1214
|
+
const MouseButton = {
|
|
1215
|
+
Left: 0};
|
|
1216
|
+
/**
|
|
1217
|
+
* Only touch events and mouse events where the left button is pressed should initiate a drag.
|
|
1218
|
+
* @param {MouseEvent | TouchEvent} e The event
|
|
1219
|
+
*/ function eventShouldStartDrag(e) {
|
|
1220
|
+
// For touch events, button will be undefined. If e.button is defined,
|
|
1221
|
+
// then it should be MouseButton.Left.
|
|
1222
|
+
return e.button === undefined || e.button === MouseButton.Left;
|
|
1223
|
+
}
|
|
1224
|
+
/**
|
|
1225
|
+
* Only touch events and mouse events where the left mouse button is no longer held should end a drag.
|
|
1226
|
+
* It's possible the user mouse downs with the left mouse button, then mouse down and ups with the right mouse button.
|
|
1227
|
+
* We don't want releasing the right mouse button to end the drag.
|
|
1228
|
+
* @param {MouseEvent | TouchEvent} e The event
|
|
1229
|
+
*/ function eventShouldEndDrag(e) {
|
|
1230
|
+
// Touch events will have buttons be undefined, while mouse events will have e.buttons's left button
|
|
1231
|
+
// bit field unset if the left mouse button has been released
|
|
1232
|
+
return e.buttons === undefined || (e.buttons & MouseButtons.Left) === 0;
|
|
1233
|
+
}
|
|
1234
|
+
function isTouchEvent(e) {
|
|
1235
|
+
return !!e.targetTouches;
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
const ELEMENT_NODE = 1;
|
|
1239
|
+
function getNodeClientOffset(node) {
|
|
1240
|
+
const el = node.nodeType === ELEMENT_NODE ? node : node.parentElement;
|
|
1241
|
+
if (!el) {
|
|
1242
|
+
return undefined;
|
|
1243
|
+
}
|
|
1244
|
+
const { top , left } = el.getBoundingClientRect();
|
|
1245
|
+
return {
|
|
1246
|
+
x: left,
|
|
1247
|
+
y: top
|
|
1248
|
+
};
|
|
1249
|
+
}
|
|
1250
|
+
function getEventClientTouchOffset(e, lastTargetTouchFallback) {
|
|
1251
|
+
if (e.targetTouches.length === 1) {
|
|
1252
|
+
return getEventClientOffset(e.targetTouches[0]);
|
|
1253
|
+
} else if (lastTargetTouchFallback && e.touches.length === 1) {
|
|
1254
|
+
if (e.touches[0].target === lastTargetTouchFallback.target) {
|
|
1255
|
+
return getEventClientOffset(e.touches[0]);
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
return;
|
|
1259
|
+
}
|
|
1260
|
+
function getEventClientOffset(e, lastTargetTouchFallback) {
|
|
1261
|
+
if (isTouchEvent(e)) {
|
|
1262
|
+
return getEventClientTouchOffset(e, lastTargetTouchFallback);
|
|
1263
|
+
} else {
|
|
1264
|
+
return {
|
|
1265
|
+
x: e.clientX,
|
|
1266
|
+
y: e.clientY
|
|
1267
|
+
};
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
const supportsPassive = (()=>{
|
|
1272
|
+
// simular to jQuery's test
|
|
1273
|
+
let supported = false;
|
|
1274
|
+
try {
|
|
1275
|
+
addEventListener('test', ()=>{
|
|
1276
|
+
// do nothing
|
|
1277
|
+
}, Object.defineProperty({}, 'passive', {
|
|
1278
|
+
get () {
|
|
1279
|
+
supported = true;
|
|
1280
|
+
return true;
|
|
1281
|
+
}
|
|
1282
|
+
}));
|
|
1283
|
+
} catch (e) {
|
|
1284
|
+
// do nothing
|
|
1285
|
+
}
|
|
1286
|
+
return supported;
|
|
1287
|
+
})();
|
|
1288
|
+
|
|
1289
|
+
const eventNames = {
|
|
1290
|
+
[ListenerType.mouse]: {
|
|
1291
|
+
start: 'mousedown',
|
|
1292
|
+
move: 'mousemove',
|
|
1293
|
+
end: 'mouseup',
|
|
1294
|
+
contextmenu: 'contextmenu'
|
|
1295
|
+
},
|
|
1296
|
+
[ListenerType.touch]: {
|
|
1297
|
+
start: 'touchstart',
|
|
1298
|
+
move: 'touchmove',
|
|
1299
|
+
end: 'touchend'
|
|
1300
|
+
},
|
|
1301
|
+
[ListenerType.keyboard]: {
|
|
1302
|
+
keydown: 'keydown'
|
|
1303
|
+
}
|
|
1304
|
+
};
|
|
1305
|
+
class TouchBackendImpl {
|
|
1306
|
+
/**
|
|
1307
|
+
* Generate profiling statistics for the HTML5Backend.
|
|
1308
|
+
*/ profile() {
|
|
1309
|
+
var ref;
|
|
1310
|
+
return {
|
|
1311
|
+
sourceNodes: this.sourceNodes.size,
|
|
1312
|
+
sourcePreviewNodes: this.sourcePreviewNodes.size,
|
|
1313
|
+
sourcePreviewNodeOptions: this.sourcePreviewNodeOptions.size,
|
|
1314
|
+
targetNodes: this.targetNodes.size,
|
|
1315
|
+
dragOverTargetIds: ((ref = this.dragOverTargetIds) === null || ref === void 0 ? void 0 : ref.length) || 0
|
|
1316
|
+
};
|
|
1317
|
+
}
|
|
1318
|
+
// public for test
|
|
1319
|
+
get document() {
|
|
1320
|
+
return this.options.document;
|
|
1321
|
+
}
|
|
1322
|
+
setup() {
|
|
1323
|
+
const root = this.options.rootElement;
|
|
1324
|
+
if (!root) {
|
|
1325
|
+
return;
|
|
1326
|
+
}
|
|
1327
|
+
invariant(!TouchBackendImpl.isSetUp, 'Cannot have two Touch backends at the same time.');
|
|
1328
|
+
TouchBackendImpl.isSetUp = true;
|
|
1329
|
+
this.addEventListener(root, 'start', this.getTopMoveStartHandler());
|
|
1330
|
+
this.addEventListener(root, 'start', this.handleTopMoveStartCapture, true);
|
|
1331
|
+
this.addEventListener(root, 'move', this.handleTopMove);
|
|
1332
|
+
this.addEventListener(root, 'move', this.handleTopMoveCapture, true);
|
|
1333
|
+
this.addEventListener(root, 'end', this.handleTopMoveEndCapture, true);
|
|
1334
|
+
if (this.options.enableMouseEvents && !this.options.ignoreContextMenu) {
|
|
1335
|
+
this.addEventListener(root, 'contextmenu', this.handleTopMoveEndCapture);
|
|
1336
|
+
}
|
|
1337
|
+
if (this.options.enableKeyboardEvents) {
|
|
1338
|
+
this.addEventListener(root, 'keydown', this.handleCancelOnEscape, true);
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
teardown() {
|
|
1342
|
+
const root = this.options.rootElement;
|
|
1343
|
+
if (!root) {
|
|
1344
|
+
return;
|
|
1345
|
+
}
|
|
1346
|
+
TouchBackendImpl.isSetUp = false;
|
|
1347
|
+
this._mouseClientOffset = {};
|
|
1348
|
+
this.removeEventListener(root, 'start', this.handleTopMoveStartCapture, true);
|
|
1349
|
+
this.removeEventListener(root, 'start', this.handleTopMoveStart);
|
|
1350
|
+
this.removeEventListener(root, 'move', this.handleTopMoveCapture, true);
|
|
1351
|
+
this.removeEventListener(root, 'move', this.handleTopMove);
|
|
1352
|
+
this.removeEventListener(root, 'end', this.handleTopMoveEndCapture, true);
|
|
1353
|
+
if (this.options.enableMouseEvents && !this.options.ignoreContextMenu) {
|
|
1354
|
+
this.removeEventListener(root, 'contextmenu', this.handleTopMoveEndCapture);
|
|
1355
|
+
}
|
|
1356
|
+
if (this.options.enableKeyboardEvents) {
|
|
1357
|
+
this.removeEventListener(root, 'keydown', this.handleCancelOnEscape, true);
|
|
1358
|
+
}
|
|
1359
|
+
this.uninstallSourceNodeRemovalObserver();
|
|
1360
|
+
}
|
|
1361
|
+
addEventListener(subject, event, handler, capture = false) {
|
|
1362
|
+
const options = supportsPassive ? {
|
|
1363
|
+
capture,
|
|
1364
|
+
passive: false
|
|
1365
|
+
} : capture;
|
|
1366
|
+
this.listenerTypes.forEach(function(listenerType) {
|
|
1367
|
+
const evt = eventNames[listenerType][event];
|
|
1368
|
+
if (evt) {
|
|
1369
|
+
subject.addEventListener(evt, handler, options);
|
|
1370
|
+
}
|
|
1371
|
+
});
|
|
1372
|
+
}
|
|
1373
|
+
removeEventListener(subject, event, handler, capture = false) {
|
|
1374
|
+
const options = supportsPassive ? {
|
|
1375
|
+
capture,
|
|
1376
|
+
passive: false
|
|
1377
|
+
} : capture;
|
|
1378
|
+
this.listenerTypes.forEach(function(listenerType) {
|
|
1379
|
+
const evt = eventNames[listenerType][event];
|
|
1380
|
+
if (evt) {
|
|
1381
|
+
subject.removeEventListener(evt, handler, options);
|
|
1382
|
+
}
|
|
1383
|
+
});
|
|
1384
|
+
}
|
|
1385
|
+
connectDragSource(sourceId, node) {
|
|
1386
|
+
const handleMoveStart = this.handleMoveStart.bind(this, sourceId);
|
|
1387
|
+
this.sourceNodes.set(sourceId, node);
|
|
1388
|
+
this.addEventListener(node, 'start', handleMoveStart);
|
|
1389
|
+
return ()=>{
|
|
1390
|
+
this.sourceNodes.delete(sourceId);
|
|
1391
|
+
this.removeEventListener(node, 'start', handleMoveStart);
|
|
1392
|
+
};
|
|
1393
|
+
}
|
|
1394
|
+
connectDragPreview(sourceId, node, options) {
|
|
1395
|
+
this.sourcePreviewNodeOptions.set(sourceId, options);
|
|
1396
|
+
this.sourcePreviewNodes.set(sourceId, node);
|
|
1397
|
+
return ()=>{
|
|
1398
|
+
this.sourcePreviewNodes.delete(sourceId);
|
|
1399
|
+
this.sourcePreviewNodeOptions.delete(sourceId);
|
|
1400
|
+
};
|
|
1401
|
+
}
|
|
1402
|
+
connectDropTarget(targetId, node) {
|
|
1403
|
+
const root = this.options.rootElement;
|
|
1404
|
+
if (!this.document || !root) {
|
|
1405
|
+
return ()=>{
|
|
1406
|
+
/* noop */ };
|
|
1407
|
+
}
|
|
1408
|
+
const handleMove = (e)=>{
|
|
1409
|
+
if (!this.document || !root || !this.monitor.isDragging()) {
|
|
1410
|
+
return;
|
|
1411
|
+
}
|
|
1412
|
+
let coords;
|
|
1413
|
+
/**
|
|
1414
|
+
* Grab the coordinates for the current mouse/touch position
|
|
1415
|
+
*/ switch(e.type){
|
|
1416
|
+
case eventNames.mouse.move:
|
|
1417
|
+
coords = {
|
|
1418
|
+
x: e.clientX,
|
|
1419
|
+
y: e.clientY
|
|
1420
|
+
};
|
|
1421
|
+
break;
|
|
1422
|
+
case eventNames.touch.move:
|
|
1423
|
+
var ref, ref1;
|
|
1424
|
+
coords = {
|
|
1425
|
+
x: ((ref = e.touches[0]) === null || ref === void 0 ? void 0 : ref.clientX) || 0,
|
|
1426
|
+
y: ((ref1 = e.touches[0]) === null || ref1 === void 0 ? void 0 : ref1.clientY) || 0
|
|
1427
|
+
};
|
|
1428
|
+
break;
|
|
1429
|
+
}
|
|
1430
|
+
/**
|
|
1431
|
+
* Use the coordinates to grab the element the drag ended on.
|
|
1432
|
+
* If the element is the same as the target node (or any of it's children) then we have hit a drop target and can handle the move.
|
|
1433
|
+
*/ const droppedOn = coords != null ? this.document.elementFromPoint(coords.x, coords.y) : undefined;
|
|
1434
|
+
const childMatch = droppedOn && node.contains(droppedOn);
|
|
1435
|
+
if (droppedOn === node || childMatch) {
|
|
1436
|
+
return this.handleMove(e, targetId);
|
|
1437
|
+
}
|
|
1438
|
+
};
|
|
1439
|
+
/**
|
|
1440
|
+
* Attaching the event listener to the body so that touchmove will work while dragging over multiple target elements.
|
|
1441
|
+
*/ this.addEventListener(this.document.body, 'move', handleMove);
|
|
1442
|
+
this.targetNodes.set(targetId, node);
|
|
1443
|
+
return ()=>{
|
|
1444
|
+
if (this.document) {
|
|
1445
|
+
this.targetNodes.delete(targetId);
|
|
1446
|
+
this.removeEventListener(this.document.body, 'move', handleMove);
|
|
1447
|
+
}
|
|
1448
|
+
};
|
|
1449
|
+
}
|
|
1450
|
+
getTopMoveStartHandler() {
|
|
1451
|
+
if (!this.options.delayTouchStart && !this.options.delayMouseStart) {
|
|
1452
|
+
return this.handleTopMoveStart;
|
|
1453
|
+
}
|
|
1454
|
+
return this.handleTopMoveStartDelay;
|
|
1455
|
+
}
|
|
1456
|
+
installSourceNodeRemovalObserver(node) {
|
|
1457
|
+
this.uninstallSourceNodeRemovalObserver();
|
|
1458
|
+
this.draggedSourceNode = node;
|
|
1459
|
+
this.draggedSourceNodeRemovalObserver = new MutationObserver(()=>{
|
|
1460
|
+
if (node && !node.parentElement) {
|
|
1461
|
+
this.resurrectSourceNode();
|
|
1462
|
+
this.uninstallSourceNodeRemovalObserver();
|
|
1463
|
+
}
|
|
1464
|
+
});
|
|
1465
|
+
if (!node || !node.parentElement) {
|
|
1466
|
+
return;
|
|
1467
|
+
}
|
|
1468
|
+
this.draggedSourceNodeRemovalObserver.observe(node.parentElement, {
|
|
1469
|
+
childList: true
|
|
1470
|
+
});
|
|
1471
|
+
}
|
|
1472
|
+
resurrectSourceNode() {
|
|
1473
|
+
if (this.document && this.draggedSourceNode) {
|
|
1474
|
+
this.draggedSourceNode.style.display = 'none';
|
|
1475
|
+
this.draggedSourceNode.removeAttribute('data-reactid');
|
|
1476
|
+
this.document.body.appendChild(this.draggedSourceNode);
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
uninstallSourceNodeRemovalObserver() {
|
|
1480
|
+
if (this.draggedSourceNodeRemovalObserver) {
|
|
1481
|
+
this.draggedSourceNodeRemovalObserver.disconnect();
|
|
1482
|
+
}
|
|
1483
|
+
this.draggedSourceNodeRemovalObserver = undefined;
|
|
1484
|
+
this.draggedSourceNode = undefined;
|
|
1485
|
+
}
|
|
1486
|
+
constructor(manager, context, options){
|
|
1487
|
+
this.getSourceClientOffset = (sourceId)=>{
|
|
1488
|
+
const element = this.sourceNodes.get(sourceId);
|
|
1489
|
+
return element && getNodeClientOffset(element);
|
|
1490
|
+
};
|
|
1491
|
+
this.handleTopMoveStartCapture = (e)=>{
|
|
1492
|
+
if (!eventShouldStartDrag(e)) {
|
|
1493
|
+
return;
|
|
1494
|
+
}
|
|
1495
|
+
this.moveStartSourceIds = [];
|
|
1496
|
+
};
|
|
1497
|
+
this.handleMoveStart = (sourceId)=>{
|
|
1498
|
+
// Just because we received an event doesn't necessarily mean we need to collect drag sources.
|
|
1499
|
+
// We only collect start collecting drag sources on touch and left mouse events.
|
|
1500
|
+
if (Array.isArray(this.moveStartSourceIds)) {
|
|
1501
|
+
this.moveStartSourceIds.unshift(sourceId);
|
|
1502
|
+
}
|
|
1503
|
+
};
|
|
1504
|
+
this.handleTopMoveStart = (e)=>{
|
|
1505
|
+
if (!eventShouldStartDrag(e)) {
|
|
1506
|
+
return;
|
|
1507
|
+
}
|
|
1508
|
+
// Don't prematurely preventDefault() here since it might:
|
|
1509
|
+
// 1. Mess up scrolling
|
|
1510
|
+
// 2. Mess up long tap (which brings up context menu)
|
|
1511
|
+
// 3. If there's an anchor link as a child, tap won't be triggered on link
|
|
1512
|
+
const clientOffset = getEventClientOffset(e);
|
|
1513
|
+
if (clientOffset) {
|
|
1514
|
+
if (isTouchEvent(e)) {
|
|
1515
|
+
this.lastTargetTouchFallback = e.targetTouches[0];
|
|
1516
|
+
}
|
|
1517
|
+
this._mouseClientOffset = clientOffset;
|
|
1518
|
+
}
|
|
1519
|
+
this.waitingForDelay = false;
|
|
1520
|
+
};
|
|
1521
|
+
this.handleTopMoveStartDelay = (e)=>{
|
|
1522
|
+
if (!eventShouldStartDrag(e)) {
|
|
1523
|
+
return;
|
|
1524
|
+
}
|
|
1525
|
+
const delay = e.type === eventNames.touch.start ? this.options.delayTouchStart : this.options.delayMouseStart;
|
|
1526
|
+
this.timeout = setTimeout(this.handleTopMoveStart.bind(this, e), delay);
|
|
1527
|
+
this.waitingForDelay = true;
|
|
1528
|
+
};
|
|
1529
|
+
this.handleTopMoveCapture = ()=>{
|
|
1530
|
+
this.dragOverTargetIds = [];
|
|
1531
|
+
};
|
|
1532
|
+
this.handleMove = (_evt, targetId)=>{
|
|
1533
|
+
if (this.dragOverTargetIds) {
|
|
1534
|
+
this.dragOverTargetIds.unshift(targetId);
|
|
1535
|
+
}
|
|
1536
|
+
};
|
|
1537
|
+
this.handleTopMove = (e1)=>{
|
|
1538
|
+
if (this.timeout) {
|
|
1539
|
+
clearTimeout(this.timeout);
|
|
1540
|
+
}
|
|
1541
|
+
if (!this.document || this.waitingForDelay) {
|
|
1542
|
+
return;
|
|
1543
|
+
}
|
|
1544
|
+
const { moveStartSourceIds , dragOverTargetIds } = this;
|
|
1545
|
+
const enableHoverOutsideTarget = this.options.enableHoverOutsideTarget;
|
|
1546
|
+
const clientOffset = getEventClientOffset(e1, this.lastTargetTouchFallback);
|
|
1547
|
+
if (!clientOffset) {
|
|
1548
|
+
return;
|
|
1549
|
+
}
|
|
1550
|
+
// If the touch move started as a scroll, or is is between the scroll angles
|
|
1551
|
+
if (this._isScrolling || !this.monitor.isDragging() && inAngleRanges(this._mouseClientOffset.x || 0, this._mouseClientOffset.y || 0, clientOffset.x, clientOffset.y, this.options.scrollAngleRanges)) {
|
|
1552
|
+
this._isScrolling = true;
|
|
1553
|
+
return;
|
|
1554
|
+
}
|
|
1555
|
+
// If we're not dragging and we've moved a little, that counts as a drag start
|
|
1556
|
+
if (!this.monitor.isDragging() && // eslint-disable-next-line no-prototype-builtins
|
|
1557
|
+
this._mouseClientOffset.hasOwnProperty('x') && moveStartSourceIds && distance(this._mouseClientOffset.x || 0, this._mouseClientOffset.y || 0, clientOffset.x, clientOffset.y) > (this.options.touchSlop ? this.options.touchSlop : 0)) {
|
|
1558
|
+
this.moveStartSourceIds = undefined;
|
|
1559
|
+
this.actions.beginDrag(moveStartSourceIds, {
|
|
1560
|
+
clientOffset: this._mouseClientOffset,
|
|
1561
|
+
getSourceClientOffset: this.getSourceClientOffset,
|
|
1562
|
+
publishSource: false
|
|
1563
|
+
});
|
|
1564
|
+
}
|
|
1565
|
+
if (!this.monitor.isDragging()) {
|
|
1566
|
+
return;
|
|
1567
|
+
}
|
|
1568
|
+
const sourceNode = this.sourceNodes.get(this.monitor.getSourceId());
|
|
1569
|
+
this.installSourceNodeRemovalObserver(sourceNode);
|
|
1570
|
+
this.actions.publishDragSource();
|
|
1571
|
+
if (e1.cancelable) e1.preventDefault();
|
|
1572
|
+
// Get the node elements of the hovered DropTargets
|
|
1573
|
+
const dragOverTargetNodes = (dragOverTargetIds || []).map((key)=>this.targetNodes.get(key)
|
|
1574
|
+
).filter((e)=>!!e
|
|
1575
|
+
);
|
|
1576
|
+
// Get the a ordered list of nodes that are touched by
|
|
1577
|
+
const elementsAtPoint = this.options.getDropTargetElementsAtPoint ? this.options.getDropTargetElementsAtPoint(clientOffset.x, clientOffset.y, dragOverTargetNodes) : this.document.elementsFromPoint(clientOffset.x, clientOffset.y);
|
|
1578
|
+
// Extend list with parents that are not receiving elementsFromPoint events (size 0 elements and svg groups)
|
|
1579
|
+
const elementsAtPointExtended = [];
|
|
1580
|
+
for(const nodeId in elementsAtPoint){
|
|
1581
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
1582
|
+
if (!elementsAtPoint.hasOwnProperty(nodeId)) {
|
|
1583
|
+
continue;
|
|
1584
|
+
}
|
|
1585
|
+
let currentNode = elementsAtPoint[nodeId];
|
|
1586
|
+
if (currentNode != null) {
|
|
1587
|
+
elementsAtPointExtended.push(currentNode);
|
|
1588
|
+
}
|
|
1589
|
+
while(currentNode){
|
|
1590
|
+
currentNode = currentNode.parentElement;
|
|
1591
|
+
if (currentNode && elementsAtPointExtended.indexOf(currentNode) === -1) {
|
|
1592
|
+
elementsAtPointExtended.push(currentNode);
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
const orderedDragOverTargetIds = elementsAtPointExtended// Filter off nodes that arent a hovered DropTargets nodes
|
|
1597
|
+
.filter((node)=>dragOverTargetNodes.indexOf(node) > -1
|
|
1598
|
+
)// Map back the nodes elements to targetIds
|
|
1599
|
+
.map((node)=>this._getDropTargetId(node)
|
|
1600
|
+
)// Filter off possible null rows
|
|
1601
|
+
.filter((node)=>!!node
|
|
1602
|
+
).filter((id, index, ids)=>ids.indexOf(id) === index
|
|
1603
|
+
);
|
|
1604
|
+
// Invoke hover for drop targets when source node is still over and pointer is outside
|
|
1605
|
+
if (enableHoverOutsideTarget) {
|
|
1606
|
+
for(const targetId in this.targetNodes){
|
|
1607
|
+
const targetNode = this.targetNodes.get(targetId);
|
|
1608
|
+
if (sourceNode && targetNode && targetNode.contains(sourceNode) && orderedDragOverTargetIds.indexOf(targetId) === -1) {
|
|
1609
|
+
orderedDragOverTargetIds.unshift(targetId);
|
|
1610
|
+
break;
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
// Reverse order because dnd-core reverse it before calling the DropTarget drop methods
|
|
1615
|
+
orderedDragOverTargetIds.reverse();
|
|
1616
|
+
this.actions.hover(orderedDragOverTargetIds, {
|
|
1617
|
+
clientOffset: clientOffset
|
|
1618
|
+
});
|
|
1619
|
+
};
|
|
1620
|
+
/**
|
|
1621
|
+
*
|
|
1622
|
+
* visible for testing
|
|
1623
|
+
*/ this._getDropTargetId = (node)=>{
|
|
1624
|
+
const keys = this.targetNodes.keys();
|
|
1625
|
+
let next = keys.next();
|
|
1626
|
+
while(next.done === false){
|
|
1627
|
+
const targetId = next.value;
|
|
1628
|
+
if (node === this.targetNodes.get(targetId)) {
|
|
1629
|
+
return targetId;
|
|
1630
|
+
} else {
|
|
1631
|
+
next = keys.next();
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
return undefined;
|
|
1635
|
+
};
|
|
1636
|
+
this.handleTopMoveEndCapture = (e)=>{
|
|
1637
|
+
this._isScrolling = false;
|
|
1638
|
+
this.lastTargetTouchFallback = undefined;
|
|
1639
|
+
if (!eventShouldEndDrag(e)) {
|
|
1640
|
+
return;
|
|
1641
|
+
}
|
|
1642
|
+
if (!this.monitor.isDragging() || this.monitor.didDrop()) {
|
|
1643
|
+
this.moveStartSourceIds = undefined;
|
|
1644
|
+
return;
|
|
1645
|
+
}
|
|
1646
|
+
if (e.cancelable) e.preventDefault();
|
|
1647
|
+
this._mouseClientOffset = {};
|
|
1648
|
+
this.uninstallSourceNodeRemovalObserver();
|
|
1649
|
+
this.actions.drop();
|
|
1650
|
+
this.actions.endDrag();
|
|
1651
|
+
};
|
|
1652
|
+
this.handleCancelOnEscape = (e)=>{
|
|
1653
|
+
if (e.key === 'Escape' && this.monitor.isDragging()) {
|
|
1654
|
+
this._mouseClientOffset = {};
|
|
1655
|
+
this.uninstallSourceNodeRemovalObserver();
|
|
1656
|
+
this.actions.endDrag();
|
|
1657
|
+
}
|
|
1658
|
+
};
|
|
1659
|
+
this.options = new OptionsReader(options, context);
|
|
1660
|
+
this.actions = manager.getActions();
|
|
1661
|
+
this.monitor = manager.getMonitor();
|
|
1662
|
+
this.sourceNodes = new Map();
|
|
1663
|
+
this.sourcePreviewNodes = new Map();
|
|
1664
|
+
this.sourcePreviewNodeOptions = new Map();
|
|
1665
|
+
this.targetNodes = new Map();
|
|
1666
|
+
this.listenerTypes = [];
|
|
1667
|
+
this._mouseClientOffset = {};
|
|
1668
|
+
this._isScrolling = false;
|
|
1669
|
+
if (this.options.enableMouseEvents) {
|
|
1670
|
+
this.listenerTypes.push(ListenerType.mouse);
|
|
1671
|
+
}
|
|
1672
|
+
if (this.options.enableTouchEvents) {
|
|
1673
|
+
this.listenerTypes.push(ListenerType.touch);
|
|
1674
|
+
}
|
|
1675
|
+
if (this.options.enableKeyboardEvents) {
|
|
1676
|
+
this.listenerTypes.push(ListenerType.keyboard);
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
|
|
1681
|
+
const TouchBackend = function createBackend(manager, context = {}, options = {}) {
|
|
1682
|
+
return new TouchBackendImpl(manager, context, options);
|
|
1683
|
+
};
|
|
1684
|
+
|
|
1685
|
+
var c={backends:[{id:"html5",backend:HTML5Backend,transition:U},{id:"touch",backend:TouchBackend,options:{enableMouseEvents:true},preview:true,transition:L}]};
|
|
1686
|
+
|
|
1687
|
+
/**
|
|
1688
|
+
* HTML5 for mouse (desktop + Chrome device emulation), touch backend for real
|
|
1689
|
+
* mobile devices. react-chessboard alone picks TouchBackend whenever
|
|
1690
|
+
* `ontouchstart` is in window, which breaks mouse drags in DevTools emulation.
|
|
1691
|
+
*/
|
|
1692
|
+
const ChessboardDnDProvider = ({ children, }) => (jsxRuntime.jsx(reactChessboard.ChessboardDnDProvider, { backend: S, options: c, children: children }));
|
|
104
1693
|
|
|
105
1694
|
/******************************************************************************
|
|
106
1695
|
Copyright (c) Microsoft Corporation.
|
|
@@ -154,8 +1743,200 @@ const boardSquareHighlightColors = {
|
|
|
154
1743
|
hint: 'rgba(119, 177, 212, 0.75)',
|
|
155
1744
|
/** Muted red — softer than the in-check highlight. */
|
|
156
1745
|
incorrect: 'rgba(140, 38, 38, 0.82)',
|
|
1746
|
+
selected: 'rgba(255, 255, 0, 0.45)',
|
|
1747
|
+
moveTarget: 'radial-gradient(circle, rgba(0, 0, 0, 0.18) 22%, transparent 22%)',
|
|
1748
|
+
captureTarget: 'radial-gradient(circle, rgba(0, 0, 0, 0.18) 72%, transparent 72%)',
|
|
1749
|
+
};
|
|
1750
|
+
|
|
1751
|
+
const badgeStyle = {
|
|
1752
|
+
position: 'absolute',
|
|
1753
|
+
right: '6%',
|
|
1754
|
+
bottom: '6%',
|
|
1755
|
+
width: '26%',
|
|
1756
|
+
height: '26%',
|
|
1757
|
+
minWidth: 14,
|
|
1758
|
+
minHeight: 14,
|
|
1759
|
+
maxWidth: 26,
|
|
1760
|
+
maxHeight: 26,
|
|
1761
|
+
borderRadius: '50%',
|
|
1762
|
+
backgroundColor: '#2e7d32',
|
|
1763
|
+
display: 'flex',
|
|
1764
|
+
alignItems: 'center',
|
|
1765
|
+
justifyContent: 'center',
|
|
1766
|
+
boxShadow: '0 1px 3px rgba(0, 0, 0, 0.35)',
|
|
1767
|
+
pointerEvents: 'none',
|
|
1768
|
+
};
|
|
1769
|
+
/** Green circle with a white check, anchored to the bottom-right of a square
|
|
1770
|
+
* square (over the piece). */
|
|
1771
|
+
const CorrectMoveCheckBadge = () => (jsxRuntime.jsx("span", { "aria-hidden": true, style: badgeStyle, children: jsxRuntime.jsx("svg", { viewBox: "0 0 12 12", width: "62%", height: "62%", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: jsxRuntime.jsx("path", { d: "M2.5 6.2 5 8.7 9.5 3.8", stroke: "#fff", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) }) }));
|
|
1772
|
+
|
|
1773
|
+
const overlayStyle$1 = {
|
|
1774
|
+
position: 'absolute',
|
|
1775
|
+
inset: 0,
|
|
1776
|
+
pointerEvents: 'none',
|
|
1777
|
+
zIndex: 20,
|
|
1778
|
+
overflow: 'visible',
|
|
157
1779
|
};
|
|
1780
|
+
function createFeedbackSquareRenderer(correctMoveSquare) {
|
|
1781
|
+
return function FeedbackSquare({ children, style, square, ref }) {
|
|
1782
|
+
return (jsxRuntime.jsxs("div", { ref: ref, style: Object.assign(Object.assign({}, style), { position: 'relative', overflow: 'visible' }), children: [children, square === correctMoveSquare ? (jsxRuntime.jsx("div", { style: overlayStyle$1, children: jsxRuntime.jsx(CorrectMoveCheckBadge, {}) })) : null] }));
|
|
1783
|
+
};
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1786
|
+
function defaultPromotionCheck(sourceSquare, targetSquare, piece) {
|
|
1787
|
+
return (((piece === 'wP' && sourceSquare[1] === '7' && targetSquare[1] === '8') ||
|
|
1788
|
+
(piece === 'bP' && sourceSquare[1] === '2' && targetSquare[1] === '1')) &&
|
|
1789
|
+
Math.abs(sourceSquare.charCodeAt(0) - targetSquare.charCodeAt(0)) <= 1);
|
|
1790
|
+
}
|
|
1791
|
+
function pieceAtSquare(fen, square) {
|
|
1792
|
+
const boardPiece = new chess_js.Chess(fen).get(square);
|
|
1793
|
+
if (!boardPiece) {
|
|
1794
|
+
return null;
|
|
1795
|
+
}
|
|
1796
|
+
const color = boardPiece.color === 'w' ? 'w' : 'b';
|
|
1797
|
+
const type = boardPiece.type.toUpperCase();
|
|
1798
|
+
return `${color}${type}`;
|
|
1799
|
+
}
|
|
1800
|
+
function getMoveOptionStyles(fen, fromSquare) {
|
|
1801
|
+
const chess = new chess_js.Chess(fen);
|
|
1802
|
+
const moves = chess.moves({ square: fromSquare, verbose: true });
|
|
1803
|
+
if (!moves.length) {
|
|
1804
|
+
return {
|
|
1805
|
+
[fromSquare]: { backgroundColor: boardSquareHighlightColors.selected },
|
|
1806
|
+
};
|
|
1807
|
+
}
|
|
1808
|
+
const styles = {
|
|
1809
|
+
[fromSquare]: { backgroundColor: boardSquareHighlightColors.selected },
|
|
1810
|
+
};
|
|
1811
|
+
for (const move of moves) {
|
|
1812
|
+
styles[move.to] = {
|
|
1813
|
+
background: chess.get(move.to)
|
|
1814
|
+
? boardSquareHighlightColors.captureTarget
|
|
1815
|
+
: boardSquareHighlightColors.moveTarget,
|
|
1816
|
+
borderRadius: '50%',
|
|
1817
|
+
};
|
|
1818
|
+
}
|
|
1819
|
+
return styles;
|
|
1820
|
+
}
|
|
1821
|
+
function useClickToMove({ enabled, position, arePiecesDraggable = true, autoPromoteToQueen = false, isDraggablePiece, onPromotionCheck = defaultPromotionCheck, onPieceDrop, onSquareClick, onPromotionPieceSelect, onPieceDragBegin, }) {
|
|
1822
|
+
var _a;
|
|
1823
|
+
const [moveFrom, setMoveFrom] = react.useState(null);
|
|
1824
|
+
const [pendingPromotion, setPendingPromotion] = react.useState(null);
|
|
1825
|
+
const fen = typeof position === 'string' ? position : undefined;
|
|
1826
|
+
const clearSelection = react.useCallback(() => {
|
|
1827
|
+
setMoveFrom(null);
|
|
1828
|
+
setPendingPromotion(null);
|
|
1829
|
+
}, []);
|
|
1830
|
+
react.useEffect(() => {
|
|
1831
|
+
clearSelection();
|
|
1832
|
+
}, [fen, clearSelection]);
|
|
1833
|
+
const clickSquareStyles = react.useMemo(() => {
|
|
1834
|
+
if (!enabled || !moveFrom || !fen) {
|
|
1835
|
+
return {};
|
|
1836
|
+
}
|
|
1837
|
+
return getMoveOptionStyles(fen, moveFrom);
|
|
1838
|
+
}, [enabled, fen, moveFrom]);
|
|
1839
|
+
const canSelectPiece = react.useCallback((square, piece) => {
|
|
1840
|
+
if (!piece || !arePiecesDraggable || !onPieceDrop) {
|
|
1841
|
+
return false;
|
|
1842
|
+
}
|
|
1843
|
+
if (isDraggablePiece) {
|
|
1844
|
+
return isDraggablePiece({ piece, sourceSquare: square });
|
|
1845
|
+
}
|
|
1846
|
+
return true;
|
|
1847
|
+
}, [arePiecesDraggable, isDraggablePiece, onPieceDrop]);
|
|
1848
|
+
const tryCompleteMove = react.useCallback((from, to, piece) => {
|
|
1849
|
+
if (!onPieceDrop) {
|
|
1850
|
+
return false;
|
|
1851
|
+
}
|
|
1852
|
+
if (onPromotionCheck(from, to, piece)) {
|
|
1853
|
+
if (autoPromoteToQueen) {
|
|
1854
|
+
const promotedPiece = piece[0] === 'w' ? 'wQ' : 'bQ';
|
|
1855
|
+
const accepted = onPieceDrop(from, to, promotedPiece);
|
|
1856
|
+
clearSelection();
|
|
1857
|
+
return accepted;
|
|
1858
|
+
}
|
|
1859
|
+
setPendingPromotion({ from, to, piece });
|
|
1860
|
+
setMoveFrom(null);
|
|
1861
|
+
return true;
|
|
1862
|
+
}
|
|
1863
|
+
const accepted = onPieceDrop(from, to, piece);
|
|
1864
|
+
clearSelection();
|
|
1865
|
+
return accepted;
|
|
1866
|
+
}, [autoPromoteToQueen, clearSelection, onPieceDrop, onPromotionCheck]);
|
|
1867
|
+
const handleSquareClick = react.useCallback((square, piece) => {
|
|
1868
|
+
onSquareClick === null || onSquareClick === void 0 ? void 0 : onSquareClick(square, piece);
|
|
1869
|
+
if (!enabled || !onPieceDrop || !arePiecesDraggable || !fen) {
|
|
1870
|
+
return;
|
|
1871
|
+
}
|
|
1872
|
+
if (!moveFrom) {
|
|
1873
|
+
if (canSelectPiece(square, piece)) {
|
|
1874
|
+
setMoveFrom(square);
|
|
1875
|
+
}
|
|
1876
|
+
return;
|
|
1877
|
+
}
|
|
1878
|
+
if (square === moveFrom) {
|
|
1879
|
+
clearSelection();
|
|
1880
|
+
return;
|
|
1881
|
+
}
|
|
1882
|
+
const sourcePiece = pieceAtSquare(fen, moveFrom);
|
|
1883
|
+
if (!sourcePiece) {
|
|
1884
|
+
clearSelection();
|
|
1885
|
+
return;
|
|
1886
|
+
}
|
|
1887
|
+
const accepted = tryCompleteMove(moveFrom, square, sourcePiece);
|
|
1888
|
+
if (accepted) {
|
|
1889
|
+
return;
|
|
1890
|
+
}
|
|
1891
|
+
if (canSelectPiece(square, piece)) {
|
|
1892
|
+
setMoveFrom(square);
|
|
1893
|
+
return;
|
|
1894
|
+
}
|
|
1895
|
+
clearSelection();
|
|
1896
|
+
}, [
|
|
1897
|
+
arePiecesDraggable,
|
|
1898
|
+
canSelectPiece,
|
|
1899
|
+
clearSelection,
|
|
1900
|
+
enabled,
|
|
1901
|
+
fen,
|
|
1902
|
+
moveFrom,
|
|
1903
|
+
onPieceDrop,
|
|
1904
|
+
onSquareClick,
|
|
1905
|
+
tryCompleteMove,
|
|
1906
|
+
]);
|
|
1907
|
+
const handlePromotionPieceSelect = react.useCallback((piece, promoteFromSquare, promoteToSquare) => {
|
|
1908
|
+
if (pendingPromotion && piece) {
|
|
1909
|
+
const { from, to } = pendingPromotion;
|
|
1910
|
+
onPieceDrop === null || onPieceDrop === void 0 ? void 0 : onPieceDrop(from, to, piece);
|
|
1911
|
+
onPromotionPieceSelect === null || onPromotionPieceSelect === void 0 ? void 0 : onPromotionPieceSelect(piece, from, to);
|
|
1912
|
+
clearSelection();
|
|
1913
|
+
return false;
|
|
1914
|
+
}
|
|
1915
|
+
if (onPromotionPieceSelect) {
|
|
1916
|
+
return onPromotionPieceSelect(piece, promoteFromSquare, promoteToSquare);
|
|
1917
|
+
}
|
|
1918
|
+
return true;
|
|
1919
|
+
}, [clearSelection, onPieceDrop, onPromotionPieceSelect, pendingPromotion]);
|
|
1920
|
+
const handlePieceDragBegin = react.useCallback((piece, sourceSquare) => {
|
|
1921
|
+
clearSelection();
|
|
1922
|
+
onPieceDragBegin === null || onPieceDragBegin === void 0 ? void 0 : onPieceDragBegin(piece, sourceSquare);
|
|
1923
|
+
}, [clearSelection, onPieceDragBegin]);
|
|
1924
|
+
return {
|
|
1925
|
+
clickSquareStyles,
|
|
1926
|
+
handleSquareClick,
|
|
1927
|
+
handlePromotionPieceSelect,
|
|
1928
|
+
handlePieceDragBegin,
|
|
1929
|
+
showPromotionDialog: pendingPromotion !== null,
|
|
1930
|
+
promotionToSquare: (_a = pendingPromotion === null || pendingPromotion === void 0 ? void 0 : pendingPromotion.to) !== null && _a !== void 0 ? _a : null,
|
|
1931
|
+
};
|
|
1932
|
+
}
|
|
158
1933
|
|
|
1934
|
+
/** Prevent mobile long-press text selection and iOS callout menus on the board. */
|
|
1935
|
+
const nonSelectableBoardStyle = {
|
|
1936
|
+
userSelect: 'none',
|
|
1937
|
+
WebkitUserSelect: 'none',
|
|
1938
|
+
WebkitTouchCallout: 'none',
|
|
1939
|
+
};
|
|
159
1940
|
const getCheckHighlighting = (checkSquare) => {
|
|
160
1941
|
const styles = {};
|
|
161
1942
|
styles[checkSquare] = { backgroundColor: boardSquareHighlightColors.check };
|
|
@@ -174,12 +1955,40 @@ const getFeedbackHighlighting = (hintSquare, incorrectMoveSquare) => {
|
|
|
174
1955
|
return styles;
|
|
175
1956
|
};
|
|
176
1957
|
const HighlightChessboard = (_a) => {
|
|
177
|
-
var { checkSquare, hintSquare, incorrectMoveSquare, customSquareStyles: extraSquareStyles } = _a, props = __rest(_a, ["checkSquare", "hintSquare", "incorrectMoveSquare", "customSquareStyles"]);
|
|
1958
|
+
var { checkSquare, hintSquare, incorrectMoveSquare, correctMoveSquare = null, clickToMove, customSquareStyles: extraSquareStyles, customBoardStyle, onPieceDrop, position, arePiecesDraggable, autoPromoteToQueen, isDraggablePiece, onPromotionCheck, onSquareClick, onPromotionPieceSelect, onPieceDragBegin, showPromotionDialog: showPromotionDialogProp, promotionToSquare: promotionToSquareProp } = _a, props = __rest(_a, ["checkSquare", "hintSquare", "incorrectMoveSquare", "correctMoveSquare", "clickToMove", "customSquareStyles", "customBoardStyle", "onPieceDrop", "position", "arePiecesDraggable", "autoPromoteToQueen", "isDraggablePiece", "onPromotionCheck", "onSquareClick", "onPromotionPieceSelect", "onPieceDragBegin", "showPromotionDialog", "promotionToSquare"]);
|
|
178
1959
|
const { customDarkSquareStyle, customLightSquareStyle } = useChessboardTheme();
|
|
1960
|
+
const clickToMoveEnabled = clickToMove !== false && typeof onPieceDrop === 'function';
|
|
1961
|
+
const { clickSquareStyles, handleSquareClick, handlePromotionPieceSelect, handlePieceDragBegin, showPromotionDialog: clickPromotionDialog, promotionToSquare: clickPromotionToSquare, } = useClickToMove({
|
|
1962
|
+
enabled: clickToMoveEnabled,
|
|
1963
|
+
position,
|
|
1964
|
+
arePiecesDraggable,
|
|
1965
|
+
autoPromoteToQueen,
|
|
1966
|
+
isDraggablePiece,
|
|
1967
|
+
onPromotionCheck,
|
|
1968
|
+
onPieceDrop,
|
|
1969
|
+
onSquareClick,
|
|
1970
|
+
onPromotionPieceSelect,
|
|
1971
|
+
onPieceDragBegin,
|
|
1972
|
+
});
|
|
179
1973
|
const checkStyles = getCheckHighlighting(checkSquare);
|
|
180
1974
|
const feedbackStyles = getFeedbackHighlighting(hintSquare, incorrectMoveSquare);
|
|
181
|
-
const customSquareStyles = Object.assign(Object.assign(Object.assign({}, checkStyles), feedbackStyles), extraSquareStyles);
|
|
182
|
-
|
|
1975
|
+
const customSquareStyles = Object.assign(Object.assign(Object.assign(Object.assign({}, clickSquareStyles), checkStyles), feedbackStyles), extraSquareStyles);
|
|
1976
|
+
const customSquare = react.useMemo(() => correctMoveSquare
|
|
1977
|
+
? createFeedbackSquareRenderer(correctMoveSquare)
|
|
1978
|
+
: undefined, [correctMoveSquare]);
|
|
1979
|
+
const promotionControlProps = clickPromotionDialog
|
|
1980
|
+
? {
|
|
1981
|
+
showPromotionDialog: true,
|
|
1982
|
+
promotionToSquare: clickPromotionToSquare,
|
|
1983
|
+
}
|
|
1984
|
+
: showPromotionDialogProp !== undefined ||
|
|
1985
|
+
promotionToSquareProp !== undefined
|
|
1986
|
+
? {
|
|
1987
|
+
showPromotionDialog: showPromotionDialogProp,
|
|
1988
|
+
promotionToSquare: promotionToSquareProp,
|
|
1989
|
+
}
|
|
1990
|
+
: {};
|
|
1991
|
+
return (jsxRuntime.jsx(reactChessboard.Chessboard, Object.assign({ customDarkSquareStyle: customDarkSquareStyle, customLightSquareStyle: customLightSquareStyle, customSquareStyles: customSquareStyles, customSquare: customSquare, customBoardStyle: Object.assign(Object.assign({}, nonSelectableBoardStyle), customBoardStyle), position: position, arePiecesDraggable: arePiecesDraggable, autoPromoteToQueen: autoPromoteToQueen, isDraggablePiece: isDraggablePiece, onPromotionCheck: onPromotionCheck, onPieceDrop: onPieceDrop, onSquareClick: clickToMoveEnabled ? handleSquareClick : onSquareClick, onPromotionPieceSelect: clickToMoveEnabled ? handlePromotionPieceSelect : onPromotionPieceSelect, onPieceDragBegin: clickToMoveEnabled ? handlePieceDragBegin : onPieceDragBegin }, promotionControlProps, props)));
|
|
183
1992
|
};
|
|
184
1993
|
|
|
185
1994
|
const emptyEngineEvaluation = () => ({
|
|
@@ -1915,6 +3724,37 @@ function useBoardRevision() {
|
|
|
1915
3724
|
return { revision, bumpRevision };
|
|
1916
3725
|
}
|
|
1917
3726
|
|
|
3727
|
+
/** Pause (ms) to show the correct-move check before advancing the line. */
|
|
3728
|
+
const CORRECT_MOVE_FEEDBACK_MS = 450;
|
|
3729
|
+
|
|
3730
|
+
function useCorrectMoveFeedback(delayMs = CORRECT_MOVE_FEEDBACK_MS) {
|
|
3731
|
+
const [correctMoveSquare, setCorrectMoveSquare] = react.useState(null);
|
|
3732
|
+
const timeoutRef = react.useRef(null);
|
|
3733
|
+
const clearCorrectMoveFeedback = react.useCallback(() => {
|
|
3734
|
+
if (timeoutRef.current !== null) {
|
|
3735
|
+
window.clearTimeout(timeoutRef.current);
|
|
3736
|
+
timeoutRef.current = null;
|
|
3737
|
+
}
|
|
3738
|
+
setCorrectMoveSquare(null);
|
|
3739
|
+
}, []);
|
|
3740
|
+
const showCorrectMove = react.useCallback((targetSquare, onComplete) => {
|
|
3741
|
+
clearCorrectMoveFeedback();
|
|
3742
|
+
setCorrectMoveSquare(targetSquare);
|
|
3743
|
+
timeoutRef.current = window.setTimeout(() => {
|
|
3744
|
+
timeoutRef.current = null;
|
|
3745
|
+
setCorrectMoveSquare(null);
|
|
3746
|
+
onComplete === null || onComplete === void 0 ? void 0 : onComplete();
|
|
3747
|
+
}, delayMs);
|
|
3748
|
+
}, [clearCorrectMoveFeedback, delayMs]);
|
|
3749
|
+
react.useEffect(() => clearCorrectMoveFeedback, [clearCorrectMoveFeedback]);
|
|
3750
|
+
return {
|
|
3751
|
+
correctMoveSquare,
|
|
3752
|
+
showCorrectMove,
|
|
3753
|
+
clearCorrectMoveFeedback,
|
|
3754
|
+
isShowingCorrectMove: correctMoveSquare !== null,
|
|
3755
|
+
};
|
|
3756
|
+
}
|
|
3757
|
+
|
|
1918
3758
|
/** Minimum eval loss (pawns) from the wrong move before showing a refutation. */
|
|
1919
3759
|
const REFUTATION_EVAL_GAP_PAWNS = 0.5;
|
|
1920
3760
|
const REFUTATION_EVAL_GAP_CP = REFUTATION_EVAL_GAP_PAWNS * 100;
|
|
@@ -2232,8 +4072,10 @@ exports.AnalysisErrorBoundary = AnalysisErrorBoundary;
|
|
|
2232
4072
|
exports.AnalysisPosition = AnalysisPosition;
|
|
2233
4073
|
exports.BOARD_THEMES = BOARD_THEMES;
|
|
2234
4074
|
exports.BOARD_THEME_IDS = BOARD_THEME_IDS;
|
|
4075
|
+
exports.CORRECT_MOVE_FEEDBACK_MS = CORRECT_MOVE_FEEDBACK_MS;
|
|
2235
4076
|
exports.ChessboardDnDProvider = ChessboardDnDProvider;
|
|
2236
4077
|
exports.ChessboardThemeContext = ChessboardThemeContext;
|
|
4078
|
+
exports.CorrectMoveCheckBadge = CorrectMoveCheckBadge;
|
|
2237
4079
|
exports.DEFAULT_ANALYSIS_LAYOUT = DEFAULT_ANALYSIS_LAYOUT;
|
|
2238
4080
|
exports.DEFAULT_BOARD_THEME = DEFAULT_BOARD_THEME;
|
|
2239
4081
|
exports.DEFAULT_STOCKFISH_SCRIPT_URL = DEFAULT_STOCKFISH_SCRIPT_URL;
|
|
@@ -2300,6 +4142,7 @@ exports.useAnalysisEngine = useAnalysisEngine;
|
|
|
2300
4142
|
exports.useAnalysisEngineContext = useAnalysisEngineContext;
|
|
2301
4143
|
exports.useBoardRevision = useBoardRevision;
|
|
2302
4144
|
exports.useChessboardTheme = useChessboardTheme;
|
|
4145
|
+
exports.useCorrectMoveFeedback = useCorrectMoveFeedback;
|
|
2303
4146
|
exports.useMissBoard = useMissBoard;
|
|
2304
4147
|
exports.useMissRefutation = useMissRefutation;
|
|
2305
4148
|
exports.useMissSequence = useMissSequence;
|