@geneui/components
Version:
The Gene UI components library designed for BI tools
1,403 lines (1,367 loc) • 243 kB
JavaScript
import { _ as _extends } from './_rollupPluginBabelHelpers-e8fb2e5c.js';
import React__default, { createContext, memo, useEffect, useLayoutEffect, useState, useCallback, useMemo, isValidElement, cloneElement, useContext, useRef, forwardRef } from 'react';
import PropTypes from 'prop-types';
import { D as Dropdown, I as InfiniteLoader, W as WindowScroller, A as AutoSizer, L as List, C as CellMeasurer } from './index-9d8d0112.js';
import { C as CellMeasurerCache } from './CellMeasurerCache-661c24a8.js';
import { c as classnames } from './index-031ff73c.js';
import { s as stopEvent, o as oneIsRequired, n as noop } from './index-a0e4e333.js';
import useMount from './hooks/useMount.js';
import useUpdate from './hooks/useUpdate.js';
import './configs-00612ce0.js';
import useThrottle from './hooks/useThrottle.js';
import Empty from './Empty/index.js';
import CustomScrollbar from './Scrollbar/index.js';
import BusyLoader from './BusyLoader/index.js';
import useMutationObserver from './hooks/useMutationObserver.js';
import Icon from './Icon/index.js';
import { r as reactIsExports } from './index-6d7e99cd.js';
import Button from './Button/index.js';
import { s as styleInject } from './style-inject.es-746bb8ed.js';
import './dateValidation-67caec66.js';
import { g as guid } from './guid-8ddf77b3.js';
import ReactDOM__default from 'react-dom';
import SkeletonLoader from './SkeletonLoader/index.js';
import Copy from './Copy/index.js';
import { c as callAfterDelay } from './callAfterDelay-7272faca.js';
import Popover from './Popover/index.js';
import ExtendedInput from './ExtendedInput/index.js';
import Menu from './Menu/index.js';
import { d as debounce } from './debounce-4419bc2f.js';
import { j as jsxRuntimeExports } from './index-08898b29.js';
import { a as createStore } from './redux-b3e598ca.js';
/**
* Create the React Context
*/ const DndContext = createContext({
dragDropManager: undefined
});
/**
* Use invariant() to assert state which your program assumes to be true.
*
* Provide sprintf-style format (only %s is supported) and arguments
* to provide information about what broke and what you were
* expecting.
*
* The invariant message will be stripped in production, but the invariant
* will remain to ensure logic does not differ in production.
*/ function invariant(condition, format, ...args) {
if (isProduction()) {
if (format === undefined) {
throw new Error('invariant requires an error message argument');
}
}
if (!condition) {
let error;
if (format === undefined) {
error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.');
} else {
let argIndex = 0;
error = new Error(format.replace(/%s/g, function() {
return args[argIndex++];
}));
error.name = 'Invariant Violation';
}
error.framesToPop = 1 // we don't care about invariant's own frame
;
throw error;
}
}
function isProduction() {
return typeof process !== 'undefined' && process.env['NODE_ENV'] === 'production';
}
// cheap lodash replacements
/**
* drop-in replacement for _.get
* @param obj
* @param path
* @param defaultValue
*/ function get(obj, path, defaultValue) {
return path.split('.').reduce((a, c)=>a && a[c] ? a[c] : defaultValue || null
, obj);
}
/**
* drop-in replacement for _.without
*/ function without$1(items, item) {
return items.filter((i)=>i !== item
);
}
/**
* drop-in replacement for _.isString
* @param input
*/ function isObject(input) {
return typeof input === 'object';
}
/**
* replacement for _.xor
* @param itemsA
* @param itemsB
*/ function xor(itemsA, itemsB) {
const map = new Map();
const insertItem = (item)=>{
map.set(item, map.has(item) ? map.get(item) + 1 : 1);
};
itemsA.forEach(insertItem);
itemsB.forEach(insertItem);
const result = [];
map.forEach((count, key)=>{
if (count === 1) {
result.push(key);
}
});
return result;
}
/**
* replacement for _.intersection
* @param itemsA
* @param itemsB
*/ function intersection(itemsA, itemsB) {
return itemsA.filter((t)=>itemsB.indexOf(t) > -1
);
}
const INIT_COORDS = 'dnd-core/INIT_COORDS';
const BEGIN_DRAG = 'dnd-core/BEGIN_DRAG';
const PUBLISH_DRAG_SOURCE = 'dnd-core/PUBLISH_DRAG_SOURCE';
const HOVER = 'dnd-core/HOVER';
const DROP = 'dnd-core/DROP';
const END_DRAG = 'dnd-core/END_DRAG';
function setClientOffset(clientOffset, sourceClientOffset) {
return {
type: INIT_COORDS,
payload: {
sourceClientOffset: sourceClientOffset || null,
clientOffset: clientOffset || null
}
};
}
const ResetCoordinatesAction = {
type: INIT_COORDS,
payload: {
clientOffset: null,
sourceClientOffset: null
}
};
function createBeginDrag(manager) {
return function beginDrag(sourceIds = [], options = {
publishSource: true
}) {
const { publishSource =true , clientOffset , getSourceClientOffset , } = options;
const monitor = manager.getMonitor();
const registry = manager.getRegistry();
// Initialize the coordinates using the client offset
manager.dispatch(setClientOffset(clientOffset));
verifyInvariants$1(sourceIds, monitor, registry);
// Get the draggable source
const sourceId = getDraggableSource(sourceIds, monitor);
if (sourceId == null) {
manager.dispatch(ResetCoordinatesAction);
return;
}
// Get the source client offset
let sourceClientOffset = null;
if (clientOffset) {
if (!getSourceClientOffset) {
throw new Error('getSourceClientOffset must be defined');
}
verifyGetSourceClientOffsetIsFunction(getSourceClientOffset);
sourceClientOffset = getSourceClientOffset(sourceId);
}
// Initialize the full coordinates
manager.dispatch(setClientOffset(clientOffset, sourceClientOffset));
const source = registry.getSource(sourceId);
const item = source.beginDrag(monitor, sourceId);
// If source.beginDrag returns null, this is an indicator to cancel the drag
if (item == null) {
return undefined;
}
verifyItemIsObject(item);
registry.pinSource(sourceId);
const itemType = registry.getSourceType(sourceId);
return {
type: BEGIN_DRAG,
payload: {
itemType,
item,
sourceId,
clientOffset: clientOffset || null,
sourceClientOffset: sourceClientOffset || null,
isSourcePublic: !!publishSource
}
};
};
}
function verifyInvariants$1(sourceIds, monitor, registry) {
invariant(!monitor.isDragging(), 'Cannot call beginDrag while dragging.');
sourceIds.forEach(function(sourceId) {
invariant(registry.getSource(sourceId), 'Expected sourceIds to be registered.');
});
}
function verifyGetSourceClientOffsetIsFunction(getSourceClientOffset) {
invariant(typeof getSourceClientOffset === 'function', 'When clientOffset is provided, getSourceClientOffset must be a function.');
}
function verifyItemIsObject(item) {
invariant(isObject(item), 'Item must be an object.');
}
function getDraggableSource(sourceIds, monitor) {
let sourceId = null;
for(let i = sourceIds.length - 1; i >= 0; i--){
if (monitor.canDragSource(sourceIds[i])) {
sourceId = sourceIds[i];
break;
}
}
return sourceId;
}
function _defineProperty$4(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _objectSpread$4(target) {
for(var i = 1; i < arguments.length; i++){
var source = arguments[i] != null ? arguments[i] : {};
var ownKeys = Object.keys(source);
if (typeof Object.getOwnPropertySymbols === 'function') {
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
}));
}
ownKeys.forEach(function(key) {
_defineProperty$4(target, key, source[key]);
});
}
return target;
}
function createDrop(manager) {
return function drop(options = {}) {
const monitor = manager.getMonitor();
const registry = manager.getRegistry();
verifyInvariants(monitor);
const targetIds = getDroppableTargets(monitor);
// Multiple actions are dispatched here, which is why this doesn't return an action
targetIds.forEach((targetId, index)=>{
const dropResult = determineDropResult(targetId, index, registry, monitor);
const action = {
type: DROP,
payload: {
dropResult: _objectSpread$4({}, options, dropResult)
}
};
manager.dispatch(action);
});
};
}
function verifyInvariants(monitor) {
invariant(monitor.isDragging(), 'Cannot call drop while not dragging.');
invariant(!monitor.didDrop(), 'Cannot call drop twice during one drag operation.');
}
function determineDropResult(targetId, index, registry, monitor) {
const target = registry.getTarget(targetId);
let dropResult = target ? target.drop(monitor, targetId) : undefined;
verifyDropResultType(dropResult);
if (typeof dropResult === 'undefined') {
dropResult = index === 0 ? {} : monitor.getDropResult();
}
return dropResult;
}
function verifyDropResultType(dropResult) {
invariant(typeof dropResult === 'undefined' || isObject(dropResult), 'Drop result must either be an object or undefined.');
}
function getDroppableTargets(monitor) {
const targetIds = monitor.getTargetIds().filter(monitor.canDropOnTarget, monitor);
targetIds.reverse();
return targetIds;
}
function createEndDrag(manager) {
return function endDrag() {
const monitor = manager.getMonitor();
const registry = manager.getRegistry();
verifyIsDragging(monitor);
const sourceId = monitor.getSourceId();
if (sourceId != null) {
const source = registry.getSource(sourceId, true);
source.endDrag(monitor, sourceId);
registry.unpinSource();
}
return {
type: END_DRAG
};
};
}
function verifyIsDragging(monitor) {
invariant(monitor.isDragging(), 'Cannot call endDrag while not dragging.');
}
function matchesType(targetType, draggedItemType) {
if (draggedItemType === null) {
return targetType === null;
}
return Array.isArray(targetType) ? targetType.some((t)=>t === draggedItemType
) : targetType === draggedItemType;
}
function createHover(manager) {
return function hover(targetIdsArg, { clientOffset } = {}) {
verifyTargetIdsIsArray(targetIdsArg);
const targetIds = targetIdsArg.slice(0);
const monitor = manager.getMonitor();
const registry = manager.getRegistry();
const draggedItemType = monitor.getItemType();
removeNonMatchingTargetIds(targetIds, registry, draggedItemType);
checkInvariants(targetIds, monitor, registry);
hoverAllTargets(targetIds, monitor, registry);
return {
type: HOVER,
payload: {
targetIds,
clientOffset: clientOffset || null
}
};
};
}
function verifyTargetIdsIsArray(targetIdsArg) {
invariant(Array.isArray(targetIdsArg), 'Expected targetIds to be an array.');
}
function checkInvariants(targetIds, monitor, registry) {
invariant(monitor.isDragging(), 'Cannot call hover while not dragging.');
invariant(!monitor.didDrop(), 'Cannot call hover after drop.');
for(let i = 0; i < targetIds.length; i++){
const targetId = targetIds[i];
invariant(targetIds.lastIndexOf(targetId) === i, 'Expected targetIds to be unique in the passed array.');
const target = registry.getTarget(targetId);
invariant(target, 'Expected targetIds to be registered.');
}
}
function removeNonMatchingTargetIds(targetIds, registry, draggedItemType) {
// Remove those targetIds that don't match the targetType. This
// fixes shallow isOver which would only be non-shallow because of
// non-matching targets.
for(let i = targetIds.length - 1; i >= 0; i--){
const targetId = targetIds[i];
const targetType = registry.getTargetType(targetId);
if (!matchesType(targetType, draggedItemType)) {
targetIds.splice(i, 1);
}
}
}
function hoverAllTargets(targetIds, monitor, registry) {
// Finally call hover on all matching targets.
targetIds.forEach(function(targetId) {
const target = registry.getTarget(targetId);
target.hover(monitor, targetId);
});
}
function createPublishDragSource(manager) {
return function publishDragSource() {
const monitor = manager.getMonitor();
if (monitor.isDragging()) {
return {
type: PUBLISH_DRAG_SOURCE
};
}
return;
};
}
function createDragDropActions(manager) {
return {
beginDrag: createBeginDrag(manager),
publishDragSource: createPublishDragSource(manager),
hover: createHover(manager),
drop: createDrop(manager),
endDrag: createEndDrag(manager)
};
}
class DragDropManagerImpl {
receiveBackend(backend) {
this.backend = backend;
}
getMonitor() {
return this.monitor;
}
getBackend() {
return this.backend;
}
getRegistry() {
return this.monitor.registry;
}
getActions() {
/* eslint-disable-next-line @typescript-eslint/no-this-alias */ const manager = this;
const { dispatch } = this.store;
function bindActionCreator(actionCreator) {
return (...args)=>{
const action = actionCreator.apply(manager, args);
if (typeof action !== 'undefined') {
dispatch(action);
}
};
}
const actions = createDragDropActions(this);
return Object.keys(actions).reduce((boundActions, key)=>{
const action = actions[key];
boundActions[key] = bindActionCreator(action);
return boundActions;
}, {});
}
dispatch(action) {
this.store.dispatch(action);
}
constructor(store, monitor){
this.isSetUp = false;
this.handleRefCountChange = ()=>{
const shouldSetUp = this.store.getState().refCount > 0;
if (this.backend) {
if (shouldSetUp && !this.isSetUp) {
this.backend.setup();
this.isSetUp = true;
} else if (!shouldSetUp && this.isSetUp) {
this.backend.teardown();
this.isSetUp = false;
}
}
};
this.store = store;
this.monitor = monitor;
store.subscribe(this.handleRefCountChange);
}
}
/**
* Coordinate addition
* @param a The first coordinate
* @param b The second coordinate
*/ function add(a, b) {
return {
x: a.x + b.x,
y: a.y + b.y
};
}
/**
* Coordinate subtraction
* @param a The first coordinate
* @param b The second coordinate
*/ function subtract(a, b) {
return {
x: a.x - b.x,
y: a.y - b.y
};
}
/**
* Returns the cartesian distance of the drag source component's position, based on its position
* at the time when the current drag operation has started, and the movement difference.
*
* Returns null if no item is being dragged.
*
* @param state The offset state to compute from
*/ function getSourceClientOffset(state) {
const { clientOffset , initialClientOffset , initialSourceClientOffset } = state;
if (!clientOffset || !initialClientOffset || !initialSourceClientOffset) {
return null;
}
return subtract(add(clientOffset, initialSourceClientOffset), initialClientOffset);
}
/**
* Determines the x,y offset between the client offset and the initial client offset
*
* @param state The offset state to compute from
*/ function getDifferenceFromInitialOffset(state) {
const { clientOffset , initialClientOffset } = state;
if (!clientOffset || !initialClientOffset) {
return null;
}
return subtract(clientOffset, initialClientOffset);
}
const NONE = [];
const ALL = [];
NONE.__IS_NONE__ = true;
ALL.__IS_ALL__ = true;
/**
* Determines if the given handler IDs are dirty or not.
*
* @param dirtyIds The set of dirty handler ids
* @param handlerIds The set of handler ids to check
*/ function areDirty(dirtyIds, handlerIds) {
if (dirtyIds === NONE) {
return false;
}
if (dirtyIds === ALL || typeof handlerIds === 'undefined') {
return true;
}
const commonIds = intersection(handlerIds, dirtyIds);
return commonIds.length > 0;
}
class DragDropMonitorImpl {
subscribeToStateChange(listener, options = {}) {
const { handlerIds } = options;
invariant(typeof listener === 'function', 'listener must be a function.');
invariant(typeof handlerIds === 'undefined' || Array.isArray(handlerIds), 'handlerIds, when specified, must be an array of strings.');
let prevStateId = this.store.getState().stateId;
const handleChange = ()=>{
const state = this.store.getState();
const currentStateId = state.stateId;
try {
const canSkipListener = currentStateId === prevStateId || currentStateId === prevStateId + 1 && !areDirty(state.dirtyHandlerIds, handlerIds);
if (!canSkipListener) {
listener();
}
} finally{
prevStateId = currentStateId;
}
};
return this.store.subscribe(handleChange);
}
subscribeToOffsetChange(listener) {
invariant(typeof listener === 'function', 'listener must be a function.');
let previousState = this.store.getState().dragOffset;
const handleChange = ()=>{
const nextState = this.store.getState().dragOffset;
if (nextState === previousState) {
return;
}
previousState = nextState;
listener();
};
return this.store.subscribe(handleChange);
}
canDragSource(sourceId) {
if (!sourceId) {
return false;
}
const source = this.registry.getSource(sourceId);
invariant(source, `Expected to find a valid source. sourceId=${sourceId}`);
if (this.isDragging()) {
return false;
}
return source.canDrag(this, sourceId);
}
canDropOnTarget(targetId) {
// undefined on initial render
if (!targetId) {
return false;
}
const target = this.registry.getTarget(targetId);
invariant(target, `Expected to find a valid target. targetId=${targetId}`);
if (!this.isDragging() || this.didDrop()) {
return false;
}
const targetType = this.registry.getTargetType(targetId);
const draggedItemType = this.getItemType();
return matchesType(targetType, draggedItemType) && target.canDrop(this, targetId);
}
isDragging() {
return Boolean(this.getItemType());
}
isDraggingSource(sourceId) {
// undefined on initial render
if (!sourceId) {
return false;
}
const source = this.registry.getSource(sourceId, true);
invariant(source, `Expected to find a valid source. sourceId=${sourceId}`);
if (!this.isDragging() || !this.isSourcePublic()) {
return false;
}
const sourceType = this.registry.getSourceType(sourceId);
const draggedItemType = this.getItemType();
if (sourceType !== draggedItemType) {
return false;
}
return source.isDragging(this, sourceId);
}
isOverTarget(targetId, options = {
shallow: false
}) {
// undefined on initial render
if (!targetId) {
return false;
}
const { shallow } = options;
if (!this.isDragging()) {
return false;
}
const targetType = this.registry.getTargetType(targetId);
const draggedItemType = this.getItemType();
if (draggedItemType && !matchesType(targetType, draggedItemType)) {
return false;
}
const targetIds = this.getTargetIds();
if (!targetIds.length) {
return false;
}
const index = targetIds.indexOf(targetId);
if (shallow) {
return index === targetIds.length - 1;
} else {
return index > -1;
}
}
getItemType() {
return this.store.getState().dragOperation.itemType;
}
getItem() {
return this.store.getState().dragOperation.item;
}
getSourceId() {
return this.store.getState().dragOperation.sourceId;
}
getTargetIds() {
return this.store.getState().dragOperation.targetIds;
}
getDropResult() {
return this.store.getState().dragOperation.dropResult;
}
didDrop() {
return this.store.getState().dragOperation.didDrop;
}
isSourcePublic() {
return Boolean(this.store.getState().dragOperation.isSourcePublic);
}
getInitialClientOffset() {
return this.store.getState().dragOffset.initialClientOffset;
}
getInitialSourceClientOffset() {
return this.store.getState().dragOffset.initialSourceClientOffset;
}
getClientOffset() {
return this.store.getState().dragOffset.clientOffset;
}
getSourceClientOffset() {
return getSourceClientOffset(this.store.getState().dragOffset);
}
getDifferenceFromInitialOffset() {
return getDifferenceFromInitialOffset(this.store.getState().dragOffset);
}
constructor(store, registry){
this.store = store;
this.registry = registry;
}
}
// Safari 6 and 6.1 for desktop, iPad, and iPhone are the only browsers that
// have WebKitMutationObserver but not un-prefixed MutationObserver.
// Must use `global` or `self` instead of `window` to work in both frames and web
// workers. `global` is a provision of Browserify, Mr, Mrs, or Mop.
/* globals self */ const scope = typeof global !== 'undefined' ? global : self;
const BrowserMutationObserver = scope.MutationObserver || scope.WebKitMutationObserver;
function makeRequestCallFromTimer(callback) {
return function requestCall() {
// We dispatch a timeout with a specified delay of 0 for engines that
// can reliably accommodate that request. This will usually be snapped
// to a 4 milisecond delay, but once we're flushing, there's no delay
// between events.
const timeoutHandle = setTimeout(handleTimer, 0);
// However, since this timer gets frequently dropped in Firefox
// workers, we enlist an interval handle that will try to fire
// an event 20 times per second until it succeeds.
const intervalHandle = setInterval(handleTimer, 50);
function handleTimer() {
// Whichever timer succeeds will cancel both timers and
// execute the callback.
clearTimeout(timeoutHandle);
clearInterval(intervalHandle);
callback();
}
};
}
// To request a high priority event, we induce a mutation observer by toggling
// the text of a text node between "1" and "-1".
function makeRequestCallFromMutationObserver(callback) {
let toggle = 1;
const observer = new BrowserMutationObserver(callback);
const node = document.createTextNode('');
observer.observe(node, {
characterData: true
});
return function requestCall() {
toggle = -toggle;
node.data = toggle;
};
}
const makeRequestCall = typeof BrowserMutationObserver === 'function' ? // reliably everywhere they are implemented.
// They are implemented in all modern browsers.
//
// - Android 4-4.3
// - Chrome 26-34
// - Firefox 14-29
// - Internet Explorer 11
// - iPad Safari 6-7.1
// - iPhone Safari 7-7.1
// - Safari 6-7
makeRequestCallFromMutationObserver : // task queue, are implemented in Internet Explorer 10, Safari 5.0-1, and Opera
// 11-12, and in web workers in many engines.
// Although message channels yield to any queued rendering and IO tasks, they
// would be better than imposing the 4ms delay of timers.
// However, they do not work reliably in Internet Explorer or Safari.
// Internet Explorer 10 is the only browser that has setImmediate but does
// not have MutationObservers.
// Although setImmediate yields to the browser's renderer, it would be
// preferrable to falling back to setTimeout since it does not have
// the minimum 4ms penalty.
// Unfortunately there appears to be a bug in Internet Explorer 10 Mobile (and
// Desktop to a lesser extent) that renders both setImmediate and
// MessageChannel useless for the purposes of ASAP.
// https://github.com/kriskowal/q/issues/396
// Timers are implemented universally.
// We fall back to timers in workers in most engines, and in foreground
// contexts in the following browsers.
// However, note that even this simple case requires nuances to operate in a
// broad spectrum of browsers.
//
// - Firefox 3-13
// - Internet Explorer 6-9
// - iPad Safari 4.3
// - Lynx 2.8.7
makeRequestCallFromTimer;
class AsapQueue {
// Use the fastest means possible to execute a task in its own turn, with
// priority over other events including IO, animation, reflow, and redraw
// events in browsers.
//
// An exception thrown by a task will permanently interrupt the processing of
// subsequent tasks. The higher level `asap` function ensures that if an
// exception is thrown by a task, that the task queue will continue flushing as
// soon as possible, but if you use `rawAsap` directly, you are responsible to
// either ensure that no exceptions are thrown from your task, or to manually
// call `rawAsap.requestFlush` if an exception is thrown.
enqueueTask(task) {
const { queue: q , requestFlush } = this;
if (!q.length) {
requestFlush();
this.flushing = true;
}
// Equivalent to push, but avoids a function call.
q[q.length] = task;
}
constructor(){
this.queue = [];
// We queue errors to ensure they are thrown in right order (FIFO).
// Array-as-queue is good enough here, since we are just dealing with exceptions.
this.pendingErrors = [];
// Once a flush has been requested, no further calls to `requestFlush` are
// necessary until the next `flush` completes.
// @ts-ignore
this.flushing = false;
// The position of the next task to execute in the task queue. This is
// preserved between calls to `flush` so that it can be resumed if
// a task throws an exception.
this.index = 0;
// If a task schedules additional tasks recursively, the task queue can grow
// unbounded. To prevent memory exhaustion, the task queue will periodically
// truncate already-completed tasks.
this.capacity = 1024;
// The flush function processes all tasks that have been scheduled with
// `rawAsap` unless and until one of those tasks throws an exception.
// If a task throws an exception, `flush` ensures that its state will remain
// consistent and will resume where it left off when called again.
// However, `flush` does not make any arrangements to be called again if an
// exception is thrown.
this.flush = ()=>{
const { queue: q } = this;
while(this.index < q.length){
const currentIndex = this.index;
// Advance the index before calling the task. This ensures that we will
// begin flushing on the next task the task throws an error.
this.index++;
q[currentIndex].call();
// Prevent leaking memory for long chains of recursive calls to `asap`.
// If we call `asap` within tasks scheduled by `asap`, the queue will
// grow, but to avoid an O(n) walk for every task we execute, we don't
// shift tasks off the queue after they have been executed.
// Instead, we periodically shift 1024 tasks off the queue.
if (this.index > this.capacity) {
// Manually shift all values starting at the index back to the
// beginning of the queue.
for(let scan = 0, newLength = q.length - this.index; scan < newLength; scan++){
q[scan] = q[scan + this.index];
}
q.length -= this.index;
this.index = 0;
}
}
q.length = 0;
this.index = 0;
this.flushing = false;
};
// In a web browser, exceptions are not fatal. However, to avoid
// slowing down the queue of pending tasks, we rethrow the error in a
// lower priority turn.
this.registerPendingError = (err)=>{
this.pendingErrors.push(err);
this.requestErrorThrow();
};
// `requestFlush` requests that the high priority event queue be flushed as
// soon as possible.
// This is useful to prevent an error thrown in a task from stalling the event
// queue if the exception handled by Node.js’s
// `process.on("uncaughtException")` or by a domain.
// `requestFlush` is implemented using a strategy based on data collected from
// every available SauceLabs Selenium web driver worker at time of writing.
// https://docs.google.com/spreadsheets/d/1mG-5UYGup5qxGdEMWkhP6BWCz053NUb2E1QoUTU16uA/edit#gid=783724593
this.requestFlush = makeRequestCall(this.flush);
this.requestErrorThrow = makeRequestCallFromTimer(()=>{
// Throw first error
if (this.pendingErrors.length) {
throw this.pendingErrors.shift();
}
});
}
} // The message channel technique was discovered by Malte Ubl and was the
// original foundation for this library.
// http://www.nonblocking.io/2011/06/windownexttick.html
// Safari 6.0.5 (at least) intermittently fails to create message ports on a
// page's first load. Thankfully, this version of Safari supports
// MutationObservers, so we don't need to fall back in that case.
// function makeRequestCallFromMessageChannel(callback) {
// var channel = new MessageChannel();
// channel.port1.onmessage = callback;
// return function requestCall() {
// channel.port2.postMessage(0);
// };
// }
// For reasons explained above, we are also unable to use `setImmediate`
// under any circumstances.
// Even if we were, there is another bug in Internet Explorer 10.
// It is not sufficient to assign `setImmediate` to `requestFlush` because
// `setImmediate` must be called *by name* and therefore must be wrapped in a
// closure.
// Never forget.
// function makeRequestCallFromSetImmediate(callback) {
// return function requestCall() {
// setImmediate(callback);
// };
// }
// Safari 6.0 has a problem where timers will get lost while the user is
// scrolling. This problem does not impact ASAP because Safari 6.0 supports
// mutation observers, so that implementation is used instead.
// However, if we ever elect to use timers in Safari, the prevalent work-around
// is to add a scroll event listener that calls for a flush.
// `setTimeout` does not call the passed callback if the delay is less than
// approximately 7 in web workers in Firefox 8 through 18, and sometimes not
// even then.
// This is for `asap.js` only.
// Its name will be periodically randomized to break any code that depends on
// // its existence.
// rawAsap.makeRequestCallFromTimer = makeRequestCallFromTimer
// ASAP was originally a nextTick shim included in Q. This was factored out
// into this ASAP package. It was later adapted to RSVP which made further
// amendments. These decisions, particularly to marginalize MessageChannel and
// to capture the MutationObserver implementation in a closure, were integrated
// back into ASAP proper.
// https://github.com/tildeio/rsvp.js/blob/cddf7232546a9cf858524b75cde6f9edf72620a7/lib/rsvp/asap.js
// `call`, just like a function.
class RawTask {
call() {
try {
this.task && this.task();
} catch (error) {
this.onError(error);
} finally{
this.task = null;
this.release(this);
}
}
constructor(onError, release){
this.onError = onError;
this.release = release;
this.task = null;
}
}
class TaskFactory {
create(task) {
const tasks = this.freeTasks;
const t1 = tasks.length ? tasks.pop() : new RawTask(this.onError, (t)=>tasks[tasks.length] = t
);
t1.task = task;
return t1;
}
constructor(onError){
this.onError = onError;
this.freeTasks = [];
}
}
const asapQueue = new AsapQueue();
const taskFactory = new TaskFactory(asapQueue.registerPendingError);
/**
* Calls a task as soon as possible after returning, in its own event, with priority
* over other events like animation, reflow, and repaint. An error thrown from an
* event will not interrupt, nor even substantially slow down the processing of
* other events, but will be rather postponed to a lower priority event.
* @param {{call}} task A callable object, typically a function that takes no
* arguments.
*/ function asap(task) {
asapQueue.enqueueTask(taskFactory.create(task));
}
const ADD_SOURCE = 'dnd-core/ADD_SOURCE';
const ADD_TARGET = 'dnd-core/ADD_TARGET';
const REMOVE_SOURCE = 'dnd-core/REMOVE_SOURCE';
const REMOVE_TARGET = 'dnd-core/REMOVE_TARGET';
function addSource(sourceId) {
return {
type: ADD_SOURCE,
payload: {
sourceId
}
};
}
function addTarget(targetId) {
return {
type: ADD_TARGET,
payload: {
targetId
}
};
}
function removeSource(sourceId) {
return {
type: REMOVE_SOURCE,
payload: {
sourceId
}
};
}
function removeTarget(targetId) {
return {
type: REMOVE_TARGET,
payload: {
targetId
}
};
}
function validateSourceContract(source) {
invariant(typeof source.canDrag === 'function', 'Expected canDrag to be a function.');
invariant(typeof source.beginDrag === 'function', 'Expected beginDrag to be a function.');
invariant(typeof source.endDrag === 'function', 'Expected endDrag to be a function.');
}
function validateTargetContract(target) {
invariant(typeof target.canDrop === 'function', 'Expected canDrop to be a function.');
invariant(typeof target.hover === 'function', 'Expected hover to be a function.');
invariant(typeof target.drop === 'function', 'Expected beginDrag to be a function.');
}
function validateType(type, allowArray) {
if (allowArray && Array.isArray(type)) {
type.forEach((t)=>validateType(t, false)
);
return;
}
invariant(typeof type === 'string' || typeof type === 'symbol', allowArray ? 'Type can only be a string, a symbol, or an array of either.' : 'Type can only be a string or a symbol.');
}
var HandlerRole;
(function(HandlerRole) {
HandlerRole["SOURCE"] = "SOURCE";
HandlerRole["TARGET"] = "TARGET";
})(HandlerRole || (HandlerRole = {}));
let nextUniqueId = 0;
function getNextUniqueId() {
return nextUniqueId++;
}
function getNextHandlerId(role) {
const id = getNextUniqueId().toString();
switch(role){
case HandlerRole.SOURCE:
return `S${id}`;
case HandlerRole.TARGET:
return `T${id}`;
default:
throw new Error(`Unknown Handler Role: ${role}`);
}
}
function parseRoleFromHandlerId(handlerId) {
switch(handlerId[0]){
case 'S':
return HandlerRole.SOURCE;
case 'T':
return HandlerRole.TARGET;
default:
throw new Error(`Cannot parse handler ID: ${handlerId}`);
}
}
function mapContainsValue(map, searchValue) {
const entries = map.entries();
let isDone = false;
do {
const { done , value: [, value] , } = entries.next();
if (value === searchValue) {
return true;
}
isDone = !!done;
}while (!isDone)
return false;
}
class HandlerRegistryImpl {
addSource(type, source) {
validateType(type);
validateSourceContract(source);
const sourceId = this.addHandler(HandlerRole.SOURCE, type, source);
this.store.dispatch(addSource(sourceId));
return sourceId;
}
addTarget(type, target) {
validateType(type, true);
validateTargetContract(target);
const targetId = this.addHandler(HandlerRole.TARGET, type, target);
this.store.dispatch(addTarget(targetId));
return targetId;
}
containsHandler(handler) {
return mapContainsValue(this.dragSources, handler) || mapContainsValue(this.dropTargets, handler);
}
getSource(sourceId, includePinned = false) {
invariant(this.isSourceId(sourceId), 'Expected a valid source ID.');
const isPinned = includePinned && sourceId === this.pinnedSourceId;
const source = isPinned ? this.pinnedSource : this.dragSources.get(sourceId);
return source;
}
getTarget(targetId) {
invariant(this.isTargetId(targetId), 'Expected a valid target ID.');
return this.dropTargets.get(targetId);
}
getSourceType(sourceId) {
invariant(this.isSourceId(sourceId), 'Expected a valid source ID.');
return this.types.get(sourceId);
}
getTargetType(targetId) {
invariant(this.isTargetId(targetId), 'Expected a valid target ID.');
return this.types.get(targetId);
}
isSourceId(handlerId) {
const role = parseRoleFromHandlerId(handlerId);
return role === HandlerRole.SOURCE;
}
isTargetId(handlerId) {
const role = parseRoleFromHandlerId(handlerId);
return role === HandlerRole.TARGET;
}
removeSource(sourceId) {
invariant(this.getSource(sourceId), 'Expected an existing source.');
this.store.dispatch(removeSource(sourceId));
asap(()=>{
this.dragSources.delete(sourceId);
this.types.delete(sourceId);
});
}
removeTarget(targetId) {
invariant(this.getTarget(targetId), 'Expected an existing target.');
this.store.dispatch(removeTarget(targetId));
this.dropTargets.delete(targetId);
this.types.delete(targetId);
}
pinSource(sourceId) {
const source = this.getSource(sourceId);
invariant(source, 'Expected an existing source.');
this.pinnedSourceId = sourceId;
this.pinnedSource = source;
}
unpinSource() {
invariant(this.pinnedSource, 'No source is pinned at the time.');
this.pinnedSourceId = null;
this.pinnedSource = null;
}
addHandler(role, type, handler) {
const id = getNextHandlerId(role);
this.types.set(id, type);
if (role === HandlerRole.SOURCE) {
this.dragSources.set(id, handler);
} else if (role === HandlerRole.TARGET) {
this.dropTargets.set(id, handler);
}
return id;
}
constructor(store){
this.types = new Map();
this.dragSources = new Map();
this.dropTargets = new Map();
this.pinnedSourceId = null;
this.pinnedSource = null;
this.store = store;
}
}
const strictEquality = (a, b)=>a === b
;
/**
* Determine if two cartesian coordinate offsets are equal
* @param offsetA
* @param offsetB
*/ function areCoordsEqual(offsetA, offsetB) {
if (!offsetA && !offsetB) {
return true;
} else if (!offsetA || !offsetB) {
return false;
} else {
return offsetA.x === offsetB.x && offsetA.y === offsetB.y;
}
}
/**
* Determines if two arrays of items are equal
* @param a The first array of items
* @param b The second array of items
*/ function areArraysEqual(a, b, isEqual = strictEquality) {
if (a.length !== b.length) {
return false;
}
for(let i = 0; i < a.length; ++i){
if (!isEqual(a[i], b[i])) {
return false;
}
}
return true;
}
function reduce$5(// eslint-disable-next-line @typescript-eslint/no-unused-vars
_state = NONE, action) {
switch(action.type){
case HOVER:
break;
case ADD_SOURCE:
case ADD_TARGET:
case REMOVE_TARGET:
case REMOVE_SOURCE:
return NONE;
case BEGIN_DRAG:
case PUBLISH_DRAG_SOURCE:
case END_DRAG:
case DROP:
default:
return ALL;
}
const { targetIds =[] , prevTargetIds =[] } = action.payload;
const result = xor(targetIds, prevTargetIds);
const didChange = result.length > 0 || !areArraysEqual(targetIds, prevTargetIds);
if (!didChange) {
return NONE;
}
// Check the target ids at the innermost position. If they are valid, add them
// to the result
const prevInnermostTargetId = prevTargetIds[prevTargetIds.length - 1];
const innermostTargetId = targetIds[targetIds.length - 1];
if (prevInnermostTargetId !== innermostTargetId) {
if (prevInnermostTargetId) {
result.push(prevInnermostTargetId);
}
if (innermostTargetId) {
result.push(innermostTargetId);
}
}
return result;
}
function _defineProperty$3(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _objectSpread$3(target) {
for(var i = 1; i < arguments.length; i++){
var source = arguments[i] != null ? arguments[i] : {};
var ownKeys = Object.keys(source);
if (typeof Object.getOwnPropertySymbols === 'function') {
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
}));
}
ownKeys.forEach(function(key) {
_defineProperty$3(target, key, source[key]);
});
}
return target;
}
const initialState$1 = {
initialSourceClientOffset: null,
initialClientOffset: null,
clientOffset: null
};
function reduce$4(state = initialState$1, action) {
const { payload } = action;
switch(action.type){
case INIT_COORDS:
case BEGIN_DRAG:
return {
initialSourceClientOffset: payload.sourceClientOffset,
initialClientOffset: payload.clientOffset,
clientOffset: payload.clientOffset
};
case HOVER:
if (areCoordsEqual(state.clientOffset, payload.clientOffset)) {
return state;
}
return _objectSpread$3({}, state, {
clientOffset: payload.clientOffset
});
case END_DRAG:
case DROP:
return initialState$1;
default:
return state;
}
}
function _defineProperty$2(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _objectSpread$2(target) {
for(var i = 1; i < arguments.length; i++){
var source = arguments[i] != null ? arguments[i] : {};
var ownKeys = Object.keys(source);
if (typeof Object.getOwnPropertySymbols === 'function') {
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
}));
}
ownKeys.forEach(function(key) {
_defineProperty$2(target, key, source[key]);
});
}
return target;
}
const initialState = {
itemType: null,
item: null,
sourceId: null,
targetIds: [],
dropResult: null,
didDrop: false,
isSourcePublic: null
};
function reduce$3(state = initialState, action) {
const { payload } = action;
switch(action.type){
case BEGIN_DRAG:
return _objectSpread$2({}, state, {
itemType: payload.itemType,
item: payload.item,
sourceId: payload.sourceId,
isSourcePublic: payload.isSourcePublic,
dropResult: null,
didDrop: false
});
case PUBLISH_DRAG_SOURCE:
return _objectSpread$2({}, state, {
isSourcePublic: true
});
case HOVER:
return _objectSpread$2({}, state, {
targetIds: payload.targetIds
});
case REMOVE_TARGET:
if (state.targetIds.indexOf(payload.targetId) === -1) {
return state;
}
return _objectSpread$2({}, state, {
targetIds: without$1(state.targetIds, payload.targetId)
});
case DROP:
return _objectSpread$2({}, state, {
dropResult: payload.dropResult,
didDrop: true,
targetIds: []
});
case END_DRAG:
return _objectSpread$2({}, state, {
itemType: null,
item: null,
sourceId: null,
dropResult: null,
didDrop: false,
isSourcePublic: null,
targetIds: []
});
default:
return state;
}
}
function reduce$2(state = 0, action) {
switch(action.type){
case ADD_SOURCE:
case ADD_TARGET:
return state + 1;
case REMOVE_SOURCE:
case REMOVE_TARGET:
return state - 1;
default:
return state;
}
}
function reduce$1(state = 0) {
return state + 1;
}
function _defineProperty$1(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _objectSpread$1(target) {
for(var i = 1; i < arguments.length; i++){
var source = arguments[i] != null ? arguments[i] : {};
var ownKeys = Object.keys(source);
if (typeof Object.getOwnPropertySymbols === 'function') {
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
}));
}
ownKeys.forEach(function(key) {
_defineProperty$1(target, key, source[key]);
});
}
return target;
}
function reduce(state = {}, action) {
return {
dirtyHandlerIds: reduce$5(state.dirtyHandlerIds, {
type: action.type,
payload: _objectSpread$1({}, action.payload, {
prevTargetIds: get(state, 'dragOperation.targetIds', [])
})
}),
dragOffset: reduce$4(state.dragOffset, action),
refCount: reduce$2(state.refCount, action),
dragOperation: reduce$3(state.dragOperation, action),
stateId: reduce$1(state.stateId)
};
}
function createDragDropManager(backendFactory, globalContext = undefined, backendOptions = {}, debugMode = false) {
const store = makeStoreInstance(debugMode);
const monitor = new DragDropMonitorImpl(store, new HandlerRegistryImpl(store));
const manager = new DragDropManagerImpl(store, monitor);
const backend = backendFactory(manager, globalContext, backendOptions);
manager.receiveBackend(backend);
return manager;
}
function makeStoreInstance(debugMode) {
// TODO: if we ever make a react-native version of this,
// we'll need to consider how to pull off dev-tooling
const reduxDevTools = typeof window !== 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION__;
return createStore(reduce, debugMode && reduxDevTools && reduxDevTools({
name: 'dnd-core',
instanceId: 'dnd-core'
}));
}
function _objectWithoutProperties(source, excluded) {
if (source == null) return {};
var target = _objectWithoutPropertiesLoose(source, excluded);
var key, i;
if (Object.getOwnPropertySymbols) {
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
for(i = 0; i < sourceSymbolKeys.length; i++){