From 0d8fdcba6ba3adaa344eb111ecbc7461b4fc3aa7 Mon Sep 17 00:00:00 2001 From: YOKE Date: Tue, 11 Jun 2024 19:30:51 +0800 Subject: [PATCH] feat: `tableMode` support --- README.md | 1 + dist/virtual-drag-list.js | 475 +++++++++++++++++----------------- dist/virtual-drag-list.min.js | 6 +- package.json | 2 +- src/hooks/useSortable.ts | 76 ------ src/hooks/useVirtual.ts | 94 ------- src/index.tsx | 260 +++++++++++++++---- src/interface.ts | 1 + types/index.d.ts | 1 + 9 files changed, 446 insertions(+), 470 deletions(-) delete mode 100644 src/hooks/useSortable.ts delete mode 100644 src/hooks/useVirtual.ts diff --git a/README.md b/README.md index 5a606d1..79f7044 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,7 @@ function Virtual() { | `direction` | `vertical \| horizontal` | `vertical` | Scroll direction | | `debounceTime` | `Number` | `0` | debounce time on scroll | | `throttleTime` | `Number` | `0` | debounce time on scroll | +| `tableMode` | `Boolean` | `false` | display with table and tbody | **Uncommonly used** diff --git a/dist/virtual-drag-list.js b/dist/virtual-drag-list.js index 862238e..664b1be 100644 --- a/dist/virtual-drag-list.js +++ b/dist/virtual-drag-list.js @@ -1,5 +1,5 @@ /*! - * react-virtual-drag-list v2.7.0 + * react-virtual-drag-list v2.7.1 * open source under the MIT license * https://github.com/mfuu/react-virtual-drag-list#readme */ @@ -10,8 +10,6 @@ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.VirtualList = factory(global.React)); })(this, (function (React) { 'use strict'; - function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } - function _interopNamespace(e) { if (e && e.__esModule) return e; var n = Object.create(null); @@ -31,7 +29,6 @@ } var React__namespace = /*#__PURE__*/_interopNamespace(React); - var React__default = /*#__PURE__*/_interopDefaultLegacy(React); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); @@ -159,6 +156,10 @@ throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } + function useCombine(states, effect) { + React__namespace.useEffect(effect, Object.values(states)); + } + function Item(props) { var itemClass = props.itemClass, dataKey = props.dataKey, @@ -1699,12 +1700,47 @@ }); } - function useCombine(states, effect) { - React__namespace.useEffect(effect, Object.values(states)); - } + var Emits = { + drag: 'onDrag', + drop: 'onDrop', + top: 'onTop', + bottom: 'onBottom' + }; - function useSortable(list, props, wrapRef, uniqueKeys, onDrag, onDrop) { - var _props$delay = props.delay, + function VirtualList(props, ref) { + var _props$dataKey = props.dataKey, + dataKey = _props$dataKey === void 0 ? '' : _props$dataKey, + _props$dataSource = props.dataSource, + dataSource = _props$dataSource === void 0 ? [] : _props$dataSource, + _props$tableMode = props.tableMode, + tableMode = _props$tableMode === void 0 ? false : _props$tableMode, + _props$wrapTag = props.wrapTag, + wrapTag = _props$wrapTag === void 0 ? 'div' : _props$wrapTag, + _props$rootTag = props.rootTag, + rootTag = _props$rootTag === void 0 ? 'div' : _props$rootTag, + _props$style = props.style, + style = _props$style === void 0 ? {} : _props$style, + _props$className = props.className, + className = _props$className === void 0 ? '' : _props$className, + _props$wrapStyle = props.wrapStyle, + wrapStyle = _props$wrapStyle === void 0 ? {} : _props$wrapStyle, + _props$wrapClass = props.wrapClass, + wrapClass = _props$wrapClass === void 0 ? '' : _props$wrapClass, + _props$itemClass = props.itemClass, + itemClass = _props$itemClass === void 0 ? 'virutal-dnd-list-item' : _props$itemClass, + _props$size = props.size, + size = _props$size === void 0 ? undefined : _props$size, + _props$keeps = props.keeps, + keeps = _props$keeps === void 0 ? 30 : _props$keeps, + _props$scroller = props.scroller, + scroller = _props$scroller === void 0 ? undefined : _props$scroller, + _props$direction = props.direction, + direction = _props$direction === void 0 ? 'vertical' : _props$direction, + _props$debounceTime = props.debounceTime, + debounceTime = _props$debounceTime === void 0 ? 0 : _props$debounceTime, + _props$throttleTime = props.throttleTime, + throttleTime = _props$throttleTime === void 0 ? 0 : _props$throttleTime, + _props$delay = props.delay, delay = _props$delay === void 0 ? 0 : _props$delay, _props$group = props.group, group = _props$group === void 0 ? '' : _props$group, @@ -1735,171 +1771,7 @@ _props$delayOnTouchOn = props.delayOnTouchOnly, delayOnTouchOnly = _props$delayOnTouchOn === void 0 ? false : _props$delayOnTouchOn; - var _React$useState = React__namespace.useState(undefined), - _React$useState2 = _slicedToArray(_React$useState, 2), - dnd = _React$useState2[0], - setDnd = _React$useState2[1]; - - var combinedStates = { - delay: delay, - group: group, - handle: handle, - lockAxis: lockAxis, - disabled: disabled, - sortable: sortable, - draggable: draggable, - animation: animation, - autoScroll: autoScroll, - ghostClass: ghostClass, - ghostStyle: ghostStyle, - chosenClass: chosenClass, - fallbackOnBody: fallbackOnBody, - scrollThreshold: scrollThreshold, - delayOnTouchOnly: delayOnTouchOnly - }; - React__namespace.useEffect(function () { - setDnd(function () { - return new Sortable(wrapRef.current, Object.assign(Object.assign({}, combinedStates), { - list: list, - uniqueKeys: uniqueKeys, - onDrag: onDrag, - onDrop: onDrop - })); - }); - return function () { - dnd === null || dnd === void 0 ? void 0 : dnd.destroy(); - }; - }, []); - useCombine(combinedStates, function () { - SortableAttrs.forEach(function (key) { - dnd === null || dnd === void 0 ? void 0 : dnd.option(key, props[key]); - }); - }); - return [dnd]; - } - - var Emits$1 = { - top: 'onTop', - bottom: 'onBottom' - }; - - function useVirtual(props, rootRef, wrapRef, uniqueKeys, onUpdate) { - var _props$size = props.size, - size = _props$size === void 0 ? undefined : _props$size, - _props$keeps = props.keeps, - keeps = _props$keeps === void 0 ? 30 : _props$keeps, - _props$scroller = props.scroller, - scroller = _props$scroller === void 0 ? undefined : _props$scroller, - _props$direction = props.direction, - direction = _props$direction === void 0 ? 'vertical' : _props$direction, - _props$dataSource = props.dataSource, - dataSource = _props$dataSource === void 0 ? [] : _props$dataSource, - _props$debounceTime = props.debounceTime, - debounceTime = _props$debounceTime === void 0 ? 0 : _props$debounceTime, - _props$throttleTime = props.throttleTime, - throttleTime = _props$throttleTime === void 0 ? 0 : _props$throttleTime; - - var _React$useState = React__namespace.useState(undefined), - _React$useState2 = _slicedToArray(_React$useState, 2), - virutal = _React$useState2[0], - setVirtual = _React$useState2[1]; - - var topLoading = React__namespace.useRef(false); - var combinedStates = { - size: size, - keeps: keeps, - scroller: scroller, - direction: direction, - debounceTime: debounceTime, - throttleTime: throttleTime - }; - var handleToTop = debounce(function () { - var _a; - - topLoading.current = true; - (_a = props[Emits$1.top]) === null || _a === void 0 ? void 0 : _a.call(props); - }, 50); - var handleToBottom = debounce(function () { - var _a; - - (_a = props[Emits$1.bottom]) === null || _a === void 0 ? void 0 : _a.call(props); - }, 50); - React__namespace.useEffect(function () { - setVirtual(function () { - return new Virtual(Object.assign(Object.assign({}, combinedStates), { - buffer: Math.round(keeps / 3), - wrapper: wrapRef.current, - scroller: scroller || rootRef.current, - uniqueKeys: uniqueKeys, - onScroll: function onScroll(event) { - topLoading.current = false; - - if (event.top) { - handleToTop(); - } else if (event.bottom) { - handleToBottom(); - } - }, - onUpdate: onUpdate - })); - }); - return function () { - virutal === null || virutal === void 0 ? void 0 : virutal.removeScrollEventListener(); - }; - }, []); - var lastLength = React__namespace.useRef(null); - React__namespace.useEffect(function () { - // if auto scroll to the last offset - if (topLoading.current && props.keepOffset) { - var index = Math.abs(dataSource.length - lastLength.current); - virutal === null || virutal === void 0 ? void 0 : virutal.scrollToIndex(index); - topLoading.current = false; - } - - lastLength.current = dataSource.length; - }, [dataSource]); - useCombine(combinedStates, function () { - VirtualAttrs.forEach(function (key) { - virutal === null || virutal === void 0 ? void 0 : virutal.option(key, props[key]); - }); - }); - return [virutal]; - } - - var Emits = { - drag: 'onDrag', - drop: 'onDrop' - }; - - function VirtualList(props, ref) { - var _props$keeps = props.keeps, - keeps = _props$keeps === void 0 ? 30 : _props$keeps, - _props$dataKey = props.dataKey, - dataKey = _props$dataKey === void 0 ? '' : _props$dataKey, - _props$sortable = props.sortable, - sortable = _props$sortable === void 0 ? true : _props$sortable, - _props$scroller = props.scroller, - scroller = _props$scroller === void 0 ? undefined : _props$scroller, - _props$direction = props.direction, - direction = _props$direction === void 0 ? 'vertical' : _props$direction, - _props$dataSource = props.dataSource, - dataSource = _props$dataSource === void 0 ? [] : _props$dataSource, - _props$style = props.style, - style = _props$style === void 0 ? {} : _props$style, - _props$className = props.className, - className = _props$className === void 0 ? '' : _props$className, - _props$wrapStyle = props.wrapStyle, - wrapStyle = _props$wrapStyle === void 0 ? {} : _props$wrapStyle, - _props$wrapClass = props.wrapClass, - wrapClass = _props$wrapClass === void 0 ? '' : _props$wrapClass, - _props$itemClass = props.itemClass, - itemClass = _props$itemClass === void 0 ? 'virutal-dnd-list-item' : _props$itemClass, - _props$wrapTag = props.wrapTag, - Wrapper = _props$wrapTag === void 0 ? 'div' : _props$wrapTag, - _props$rootTag = props.rootTag, - Rooter = _props$rootTag === void 0 ? 'div' : _props$rootTag; - - var _React$useState = React__default["default"].useState({ + var _React$useState = React__namespace.useState({ start: 0, end: keeps - 1, front: 0, @@ -1909,26 +1781,14 @@ range = _React$useState2[0], setRange = _React$useState2[1]; - var dragging = React__default["default"].useRef(''); - var uniqueKeys = React__default["default"].useRef([]); - var rootRef = React__default["default"].useRef(null); - var wrapRef = React__default["default"].useRef(null); - - var _React$useMemo = React__default["default"].useMemo(function () { - var isHorizontal = direction !== 'vertical'; - var itemSizeKey = isHorizontal ? 'offsetWidth' : 'offsetHeight'; - return { - isHorizontal: isHorizontal, - itemSizeKey: itemSizeKey - }; - }, [direction]), - isHorizontal = _React$useMemo.isHorizontal, - itemSizeKey = _React$useMemo.itemSizeKey; + var dragging = React__namespace.useRef(''); + var uniqueKeys = React__namespace.useRef([]); + var rootRef = React__namespace.useRef(null); + var wrapRef = React__namespace.useRef(null); /** * git item size by data-key */ - var getSize = function getSize(key) { return virtualRef.current.getSize(key); }; @@ -2001,7 +1861,7 @@ virtualRef.current.scrollToBottom(); }; - React__default["default"].useImperativeHandle(ref, function () { + React__namespace.useImperativeHandle(ref, function () { return { getSize: getSize, getOffset: getOffset, @@ -2014,24 +1874,47 @@ scrollToBottom: scrollToBottom }; }); - var list = React__default["default"].useRef([]); - React__default["default"].useEffect(function () { + React__namespace.useEffect(function () { + installVirtual(); + installSortable(); + return function () { + var _a, _b; + + (_a = virtualRef.current) === null || _a === void 0 ? void 0 : _a.removeScrollEventListener(); + (_b = sortableRef.current) === null || _b === void 0 ? void 0 : _b.destroy(); + }; + }, []); // ========================================== use virtual ========================================== + + var topLoading = React__namespace.useRef(false); + var virtualRef = React__namespace.useRef(undefined); + var virtualCombinedStates = { + size: size, + keeps: keeps, + scroller: scroller, + direction: direction, + debounceTime: debounceTime, + throttleTime: throttleTime + }; + var handleToTop = debounce(function () { var _a; - updateUniqueKeys(); - updateRange(list.current, dataSource); - list.current = dataSource; - (_a = sortableRef.current) === null || _a === void 0 ? void 0 : _a.option('list', dataSource); - }, [dataSource]); + topLoading.current = true; + (_a = props[Emits.top]) === null || _a === void 0 ? void 0 : _a.call(props); + }, 50); + var handleToBottom = debounce(function () { + var _a; - var updateUniqueKeys = function updateUniqueKeys() { - var _a, _b; + (_a = props[Emits.bottom]) === null || _a === void 0 ? void 0 : _a.call(props); + }, 50); - uniqueKeys.current = dataSource.map(function (item) { - return getDataKey(item, dataKey); - }); - (_a = virtualRef.current) === null || _a === void 0 ? void 0 : _a.option('uniqueKeys', uniqueKeys.current); - (_b = sortableRef.current) === null || _b === void 0 ? void 0 : _b.option('uniqueKeys', uniqueKeys.current); + var onScroll = function onScroll(event) { + topLoading.current = false; + + if (event.top) { + handleToTop(); + } else if (event.bottom) { + handleToBottom(); + } }; var onUpdate = function onUpdate(range) { @@ -2044,13 +1927,62 @@ }); }; - var virtualRef = React__default["default"].useRef(undefined); + var installVirtual = function installVirtual() { + virtualRef.current = new Virtual(Object.assign(Object.assign({}, virtualCombinedStates), { + buffer: Math.round(keeps / 3), + wrapper: wrapRef.current, + scroller: scroller || rootRef.current, + uniqueKeys: uniqueKeys.current, + onScroll: onScroll, + onUpdate: onUpdate + })); + }; + + useCombine(virtualCombinedStates, function () { + VirtualAttrs.forEach(function (key) { + var _a; + + if (props[key] !== undefined) { + (_a = virtualRef.current) === null || _a === void 0 ? void 0 : _a.option(key, props[key]); + } + }); + }); + var lastLength = React__namespace.useRef(null); + React__namespace.useEffect(function () { + var _a; // if auto scroll to the last offset + + + if (lastLength.current && topLoading.current && props.keepOffset) { + var index = Math.abs(dataSource.length - lastLength.current); + + if (index > 0) { + (_a = virtualRef.current) === null || _a === void 0 ? void 0 : _a.scrollToIndex(index); + } + + topLoading.current = false; + } - var _useVirtual = useVirtual(props, rootRef, wrapRef, uniqueKeys.current, onUpdate), - _useVirtual2 = _slicedToArray(_useVirtual, 1), - virtual = _useVirtual2[0]; + lastLength.current = dataSource.length; + }, [dataSource]); // ========================================== use dnd ========================================== - virtualRef.current = virtual; + var sortableRef = React__namespace.useRef(undefined); + var sortableCombinedStates = { + delay: delay, + group: group, + handle: handle, + lockAxis: lockAxis, + disabled: disabled, + sortable: sortable, + draggable: draggable, + animation: animation, + autoScroll: autoScroll, + ghostClass: ghostClass, + ghostStyle: ghostStyle, + chosenClass: chosenClass, + fallbackOnBody: fallbackOnBody, + scrollThreshold: scrollThreshold, + delayOnTouchOnly: delayOnTouchOnly + }; var onDrag = function onDrag(event) { var _a; @@ -2071,18 +2003,50 @@ dragging.current = ''; virtualRef.current.enableScroll(true); sortableRef.current.option('autoScroll', props.autoScroll); - (_a = props[Emits.drop]) === null || _a === void 0 ? void 0 : _a.call(props, Object.assign(Object.assign({}, event), { + var params = Object.assign(Object.assign({}, event), { list: _toConsumableArray(event.list) + }); + (_a = props[Emits.drop]) === null || _a === void 0 ? void 0 : _a.call(props, params); + }; + + var installSortable = function installSortable() { + sortableRef.current = new Sortable(rootRef.current, Object.assign(Object.assign({}, sortableCombinedStates), { + list: dataSource, + uniqueKeys: uniqueKeys.current, + onDrag: onDrag, + onDrop: onDrop })); }; - var sortableRef = React__default["default"].useRef(undefined); + useCombine(sortableCombinedStates, function () { + SortableAttrs.forEach(function (key) { + var _a; - var _useSortable = useSortable(dataSource, props, wrapRef, uniqueKeys.current, onDrag, onDrop), - _useSortable2 = _slicedToArray(_useSortable, 1), - dnd = _useSortable2[0]; + if (props[key] !== undefined) { + (_a = sortableRef.current) === null || _a === void 0 ? void 0 : _a.option(key, props[key]); + } + }); + }); // ========================================== layout ========================================== + + var list = React__namespace.useRef([]); + React__namespace.useEffect(function () { + var _a; - sortableRef.current = dnd; + updateUniqueKeys(); + updateRange(list.current, dataSource); + list.current = dataSource; + (_a = sortableRef.current) === null || _a === void 0 ? void 0 : _a.option('list', dataSource); + }, [dataSource]); + + var updateUniqueKeys = function updateUniqueKeys() { + var _a, _b; + + uniqueKeys.current = dataSource.map(function (item) { + return getDataKey(item, dataKey); + }); + (_a = virtualRef.current) === null || _a === void 0 ? void 0 : _a.option('uniqueKeys', uniqueKeys.current); + (_b = sortableRef.current) === null || _b === void 0 ? void 0 : _b.option('uniqueKeys', uniqueKeys.current); + }; var updateRange = function updateRange(oldlist, newlist) { var _a; @@ -2104,16 +2068,50 @@ return offset + clientSize + 1 >= scrollSize; }; - var onItemSizeChange = function onItemSizeChange(key, size) { - var sizes = virtualRef.current.sizes.size; + var onSizeChange = function onSizeChange(key, size) { + var _a, _b; + + var sizes = (_a = virtualRef.current) === null || _a === void 0 ? void 0 : _a.sizes.size; var renders = Math.min(keeps, dataSource.length); - virtualRef.current.onItemResized(key, size); + (_b = virtualRef.current) === null || _b === void 0 ? void 0 : _b.onItemResized(key, size); if (sizes === renders - 1) { updateRange(dataSource, dataSource); } }; + var _React$useMemo = React__namespace.useMemo(function () { + var front = range.front, + behind = range.behind; + var isHorizontal = direction !== 'vertical'; + var overflowStyle = isHorizontal ? 'auto hidden' : 'hidden auto'; + var padding = isHorizontal ? "0px ".concat(behind, "px 0px ").concat(front, "px") : "".concat(front, "px 0px ").concat(behind, "px"); + var containerStyle = Object.assign(Object.assign({}, style), { + overflow: tableMode || scroller ? '' : overflowStyle + }); + var wrapperStyle = Object.assign(Object.assign({}, wrapStyle), { + padding: tableMode ? null : padding + }); + var itemSizeKey = isHorizontal ? 'offsetWidth' : 'offsetHeight'; + return { + containerStyle: containerStyle, + wrapperStyle: wrapperStyle, + itemSizeKey: itemSizeKey + }; + }, [range, style, wrapStyle, scroller, tableMode, direction]), + containerStyle = _React$useMemo.containerStyle, + wrapperStyle = _React$useMemo.wrapperStyle, + itemSizeKey = _React$useMemo.itemSizeKey; + + var _React$useMemo2 = React__namespace.useMemo(function () { + var container = tableMode ? 'table' : wrapTag; + var wrapper = tableMode ? 'tbody' : wrapTag; + return [container, wrapper]; + }, [rootTag, wrapTag, tableMode]), + _React$useMemo3 = _slicedToArray(_React$useMemo2, 2), + Container = _React$useMemo3[0], + Wrapper = _React$useMemo3[1]; + var listChildren = useChildren({ list: dataSource, start: range.start, @@ -2123,34 +2121,33 @@ children: props.children, dragging: dragging.current, itemClass: itemClass, - onSizeChange: onItemSizeChange + onSizeChange: onSizeChange }); - var rooterStyle = React__default["default"].useMemo(function () { - var overflowStyle = isHorizontal ? 'auto hidden' : 'hidden auto'; - return Object.assign(Object.assign({}, style), { - overflow: scroller ? '' : overflowStyle - }); - }, [style, isHorizontal, scroller]); - var wrapperStyle = React__default["default"].useMemo(function () { - var front = range.front, - behind = range.behind; - var padding = isHorizontal ? "0px ".concat(behind, "px 0px ").concat(front, "px") : "".concat(front, "px 0px ").concat(behind, "px"); - return Object.assign(Object.assign({}, wrapStyle), { - padding: padding - }); - }, [wrapStyle, isHorizontal, range]); - return /*#__PURE__*/React__default["default"].createElement(Rooter, { + + var TableSpacer = function TableSpacer(offset) { + var style = { + padding: 0, + border: 0, + margin: 0, + height: "".concat(offset, "px") + }; + return /*#__PURE__*/React__namespace.createElement("tr", null, /*#__PURE__*/React__namespace.createElement("td", { + style: style + })); + }; + + return /*#__PURE__*/React__namespace.createElement(Container, { ref: rootRef, - style: rooterStyle, + style: containerStyle, className: className - }, props.header, /*#__PURE__*/React__default["default"].createElement(Wrapper, { + }, props.header, /*#__PURE__*/React__namespace.createElement(Wrapper, { ref: wrapRef, style: wrapperStyle, className: wrapClass - }, listChildren), props.footer); + }, tableMode && TableSpacer(range.front), listChildren, tableMode && TableSpacer(range.behind)), props.footer); } - var index = /*#__PURE__*/React__default["default"].forwardRef(VirtualList); + var index = /*#__PURE__*/React__namespace.forwardRef(VirtualList); return index; diff --git a/dist/virtual-drag-list.min.js b/dist/virtual-drag-list.min.js index 6172853..66f5b35 100644 --- a/dist/virtual-drag-list.min.js +++ b/dist/virtual-drag-list.min.js @@ -1,11 +1,11 @@ /*! - * react-virtual-drag-list v2.7.0 + * react-virtual-drag-list v2.7.1 * open source under the MIT license * https://github.com/mfuu/react-virtual-drag-list#readme */ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("react")):"function"==typeof define&&define.amd?define(["react"],e):(t="undefined"!=typeof globalThis?globalThis:t||self).VirtualList=e(t.React)}(this,(function(t){"use strict";function e(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}function n(t){if(t&&t.__esModule)return t;var e=Object.create(null);return t&&Object.keys(t).forEach((function(n){if("default"!==n){var o=Object.getOwnPropertyDescriptor(t,n);Object.defineProperty(e,n,o.get?o:{enumerable:!0,get:function(){return t[n]}})}})),e.default=t,Object.freeze(e)}var o=n(t),i=e(t);function r(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(t);e&&(o=o.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,o)}return n}function s(t){for(var e=1;et.length)&&(e=t.length);for(var n=0,o=new Array(e);nt.length)&&(e=t.length);for(var n=0,o=new Array(e);n"===e[0]?t.parentNode===n&&S(t,e):S(t,e))||o&&t===n)return t;if(t===n)break}while(t=t.parentNode);return null}}function p(t,e){if(!t||!e)return!1;if(e.compareDocumentPosition)return!!(16&e.compareDocumentPosition(t));if(e.contains&&1===t.nodeType)return e.contains(t)&&e!==t;for(;t=t.parentNode;)if(t===e)return!0;return!1}function m(t,e){for(var n=t.lastElementChild;n&&(n===ot.ghost||"none"===w(n,"display")||e&&!S(n,e));)n=n.previousElementSibling;return n||null}function g(t,e){if(!t||!t.parentNode)return-1;for(var n=0;t=t.previousElementSibling;)"TEMPLATE"===t.nodeName.toUpperCase()||e&&!S(t,e)||"none"===w(t,"display")||n++;return n}function v(t,e,n,o){for(var i=0,r=0,s=t.children;i=o&&"none"===n[f]||l&&"none"===n[f]&&u+h>o)?"vertical":"horizontal"}function b(t,e,n){if(t&&e)if(t.classList)t.classList[n?"add":"remove"](e);else{var i=(" "+t.className+" ").replace(o," ").replace(" "+e+" "," ");t.className=(i+(n?" "+e:"")).replace(o," ")}}function S(t,e){if(e){if(">"===e[0]&&(e=e.substring(1)),t)try{if(t.matches)return t.matches(e);if(t.msMatchesSelector)return t.msMatchesSelector(e);if(t.webkitMatchesSelector)return t.webkitMatchesSelector(e)}catch(t){return!1}return!1}}function w(t,e,n){var o=t&&t.style;if(o){if(void 0===n)return document.defaultView&&document.defaultView.getComputedStyle?n=document.defaultView.getComputedStyle(t,""):t.currentStyle&&(n=t.currentStyle),void 0===e?n:n[e];e in o||-1!==e.indexOf("webkit")||(e="-webkit-"+e),o[e]=n+("string"==typeof n?"":"px")}}function x(t,e){var n,o,i=(o=e,(n=t).compareDocumentPosition?n.compareDocumentPosition(o):n.contains?(n!=o&&n.contains(o)&&16)+(n!=o&&o.contains(n)&&8)+(n.sourceIndex>=0&&o.sourceIndex>=0?(n.sourceIndexo.sourceIndex&&2):1):0);return 2===i?1:4===i?-1:0}function E(t){void 0!==t.preventDefault&&t.cancelable&&t.preventDefault()}function O(t){var n=t.sortable,o=t.name,i=t.params,r=n.options[o];"function"==typeof r&&r(e({},i))}!function(){if("undefined"==typeof window||"undefined"==typeof document)return"";var t=window.getComputedStyle(document.documentElement,"")||["-moz-hidden-iframe"];(Array.prototype.slice.call(t).join("").match(/-(moz|webkit|ms)-/)||""===t.OLink&&["","o"])[1]}();var I,D,T="Sortable"+Date.now();function _(t){this.options=t,this.autoScrollAnimationFrame=null}function z(t){this.options=t,this.stack=[]}function C(t){this.options=t||{},this.selectedElements=[]}window.requestAnimationFrame||(window.requestAnimationFrame=function(t){return setTimeout(t,17)}),window.cancelAnimationFrame||(window.cancelAnimationFrame=function(t){clearTimeout(t)}),_.prototype={destroy:function(){this.autoScrollAnimationFrame&&(cancelAnimationFrame(this.autoScrollAnimationFrame),this.autoScrollAnimationFrame=null)},update:function(t,e,n){var o=this;cancelAnimationFrame(this.autoScrollAnimationFrame),this.autoScrollAnimationFrame=requestAnimationFrame((function(){e&&n&&o.autoScroll(t,n),o.update(t,e,n)}))},autoScroll:function(t,e){if(t&&void 0!==e.clientX&&void 0!==e.clientY){var n=d(t);if(n){var o=e.clientX,i=e.clientY,r=n.top,s=n.right,l=n.bottom,a=n.left,c=n.height,u=n.width;if(!(is||i>l||o0&&i>=r&&i<=r+f,b=g+u=s-f,S=m+c=l-f;g>0&&o>=a&&o<=a+f&&(t.scrollLeft+=Math.floor(Math.max(-1,(o-a)/f-1)*p.x)),b&&(t.scrollLeft+=Math.ceil(Math.min(1,(o-s)/f+1)*p.x)),y&&(t.scrollTop+=Math.floor(Math.max(-1,(i-r)/f-1)*p.y)),S&&(t.scrollTop+=Math.ceil(Math.min(1,(i-l)/f+1)*p.y))}}}}},z.prototype={collect:function(t){if(t){for(var e=d(t),n=window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth,o=window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight,i=Math.min(e.right,n),r=Math.min(e.bottom,o),s=Array.prototype.slice.call(t.children),l=[],a=0,c=s.length;a<=c;a++){var u=s[a];if(u&&u!==ot.ghost&&"none"!==w(u,"display")){var h=d(u);if(!(h.bottom<0||h.right<0)){if(h.top-h.height>r||h.left-h.width>i)break;l.push({el:u,rect:h})}}}this.stack.push(l)}},animate:function(){for(var t=this.stack.pop(),e=0,n=t.length;e-1&&(b(t,this.options.selectedClass,!1),this.selectedElements.splice(e,1))},getGhostElement:function(){if(!I)return null;var t=document.createElement("div");return this.selectedElements.forEach((function(e,n){var o=e.cloneNode(!0),i=0===n?1:.5;o.style="position: absolute;left: 0;top: 0;bottom: 0;right: 0;opacity: ".concat(i,";z-index: ").concat(n,";"),t.appendChild(o)})),t},toggleSelected:function(t,e){var n=this;e?t.forEach((function(t){return n.selectedElements.push(t)})):this.selectedElements=this.selectedElements.filter((function(e){return t.indexOf(e)<0}))},toggleClass:function(t){if(I)for(var e=0;e0?t[o-1]:n;n.parentNode.insertBefore(t[o],i.nextSibling)}},_hideElements:function(t){for(var e=0;e-1&&tt.splice(t,1),this.el[T]=this.animator=this.multiplayer=this.autoScroller=null},option:function(t,e){if(void 0===e)return this.options[t];this.options[t]=e,this.animator.options[t]=e,this.multiplayer.options[t]=e,this.autoScroller.options[t]=e,"group"===t&&et(this.options)},select:function(t){this.multiplayer.select(t)},deselect:function(t){this.multiplayer.deselect(t)},getSelectedElements:function(){return this.multiplayer.selectedElements},_onDrag:function(t){var e=this;if(!N&&!this.options.disabled&&this.options.group.pull&&(!/mousedown|pointerdown/.test(t.type)||0===t.button)){var n=t.touches&&t.touches[0],o=(n||t).target;if(!l||!o||"SELECT"!==o.tagName.toUpperCase()){var i=f(o,this.options.draggable,this.el);if(i&&!i.animated){W={origin:t,clientX:(n||t).clientX,clientY:(n||t).clientY},N=i,c($=n?N:document,"mouseup",this._onDrop),c($,"touchend",this._onDrop),c($,"touchcancel",this._onDrop);var a=this.options,u=a.handle,h=a.selectHandle;if("function"==typeof h&&h(t)||"string"==typeof h&&S(o,h))Z=!0;else if(("function"!=typeof u||u(t))&&("string"!=typeof u||S(o,u))){var d=this.options,p=d.delay,m=d.delayOnTouchOnly;!p||m&&!n||s||r?this._onStart(n,t):(c(this.el.ownerDocument,"touchmove",this._delayMoveHandler),c(this.el.ownerDocument,"mousemove",this._delayMoveHandler),c(this.el.ownerDocument,"mouseup",this._cancelStart),c(this.el.ownerDocument,"touchend",this._cancelStart),c(this.el.ownerDocument,"touchcancel",this._cancelStart),Q=setTimeout((function(){return e._onStart(n,t)}),p)),c(document,"selectstart",E),l&&w(document.body,"user-select","none")}}}}},_delayMoveHandler:function(t){var e=t.touches?t.touches[0]:t;Math.max(Math.abs(e.clientX-W.clientX),Math.abs(e.clientY-W.clientY))>=Math.floor(this.options.touchStartThreshold/(window.devicePixelRatio||1))&&this._cancelStart()},_cancelStart:function(){clearTimeout(Q),u(this.el.ownerDocument,"touchmove",this._delayMoveHandler),u(this.el.ownerDocument,"mousemove",this._delayMoveHandler),u(this.el.ownerDocument,"mouseup",this._cancelStart),u(this.el.ownerDocument,"touchend",this._cancelStart),u(this.el.ownerDocument,"touchcancel",this._cancelStart),u(document,"selectstart",E),l&&w(document.body,"user-select","")},_onStart:function(t,e){var n=g(N);k=this.el,M=this.el,F=N,K=n,X=n,Y=n,G={to:this.el,target:N,newIndex:n,relative:0},V=N,A=this.el,B=N.cloneNode(!0),L=N.parentNode,H=this.options.group.pull,ot.clone=B,ot.active=this,ot.dragged=N,b(N,this.options.chosenClass,!0),this.multiplayer.onChoose(),O({sortable:this,name:"onChoose",params:this._getParams(e)}),c($,t?"touchmove":"mousemove",this._nearestSortable);try{document.selection?setTimeout((function(){return document.selection.empty()}),0):window.getSelection().removeAllRanges()}catch(t){}},_onStarted:function(){b(B,this.options.chosenClass,!0),this._appendGhost(),this.multiplayer.onDrag(this),O({sortable:this,name:"onDrag",params:this._getParams(W.origin)}),w(N,"display","none"),b(N,this.options.chosenClass,!1),N.parentNode.insertBefore(B,N)},_getGhostElement:function(){var t=this.options.customGhost;if("function"==typeof t){var e=this.multiplayer.selectedElements;return t(e.length?e:[N])}return this.multiplayer.getGhostElement()||N},_appendGhost:function(){if(!P){var t=this.options.fallbackOnBody?document.body:this.el,n=this._getGhostElement();b(P=n.cloneNode(!0),this.options.ghostClass,!0);var o=d(N),i=e({position:"fixed",top:o.top,left:o.left,width:o.width,height:o.height,zIndex:"100000",opacity:"0.8",overflow:"hidden",boxSizing:"border-box",transform:"translate3d(0px, 0px, 0px)",transition:"none",pointerEvents:"none"},this.options.ghostStyle);for(var r in i)w(P,r,i[r]);ot.ghost=P,t.appendChild(P);var s=(W.clientX-o.left)/parseInt(P.style.width)*100,l=(W.clientY-o.top)/parseInt(P.style.height)*100;w(P,"transform-origin",s+"% "+l+"%"),w(P,"will-change","transform")}},_nearestSortable:function(t){E(t);var e=t.touches&&t.touches[0]||t;if(N&&nt(e)){!q&&this._onStarted();var n=this.options.lockAxis,o="x"===n?W.clientX:e.clientX,i="y"===n?W.clientY:e.clientY,r=document.elementFromPoint(o,i),s=o-W.clientX,l=i-W.clientY;q={origin:t,clientX:o,clientY:i},w(P,"transform","translate3d("+s+"px, "+l+"px, 0)");var a,c,u,f=(a=o,c=i,tt.reduce((function(t,e){var n=e[T].options.emptyInsertThreshold;if(null!=n){var o=d(e),i=a>=o.left-n&&a<=o.right+n,r=c>=o.top-n&&c<=o.bottom+n;return i&&r&&(!u||u&&o.left>=u.left&&o.right<=u.right&&o.top>=u.top&&o.bottom<=u.bottom)&&(t=e,u=o),t}}),null));if(f&&f[T]._onMove(t,r),!f||f[T].options.autoScroll){var p=function(t,e){if(!t||!t.getBoundingClientRect)return h();var n=t,o=!1;do{if(n.clientWidth-1||o.name&&e&&o.name===e}return!1},_getDirection:function(){var t=this.options,e=t.draggable,n=t.direction;return n?"function"==typeof n?n.call(q.origin,N,this):n:y(L,e)},_allowSwap:function(){var t=d(R),e="vertical"===this._getDirection(),n=e?"top":"left",o=e?"bottom":"right",i=R[e?"offsetHeight":"offsetWidth"],r=e?q.clientY:q.clientX,s=r>=t[n]&&ru[o]&&(j=R.nextSibling,!0);var h=x(B,R);return j=h<0?R.nextSibling:R,U!==R?(J=s,!0):J!==s&&(J=s,s<0?h>0:h<0)},_onMove:function(t,e){if(!this.options.disabled&&this._allowPut()){if(R=f(e,this.options.draggable,this.el),O({sortable:this,name:"onMove",params:this._getParams(t,{target:R})}),this.options.sortable||this.el!==A)return this.el===M||e!==this.el&&m(this.el)?void(R&&!R.animated&&!p(R,B)&&this._allowSwap()&&(R!==B&&j!==B?(this.el!==M?this._onInsert(t):R!==N&&this._onChange(t),U=R):U=R)):(R=U=null,void this._onInsert(t));M!==A&&(R=U=N,J=0,this._onInsert(t))}},_onInsert:function(t){var e=R||B,n="clone"===H&&this.el!==A&&M===A,o="clone"===H&&this.el===A&&M!==A,i=p(R,document),r=R===N&&!i;k=this.el,K=g(B),F=e,L=i?R.parentNode:this.el,M[T].animator.collect(B.parentNode),this.animator.collect(L),n&&(G.target=V,G.newIndex=K,G.relative=V===N?0:x(B,V),w(N,"display",""),A[T].multiplayer.toggleVisible(!0),A[T].options.group.revertDrag||B.parentNode.insertBefore(N,B)),o&&(K=g(N),w(N,"display","none"),this.multiplayer.toggleVisible(!1)),w(B,"display",r?"none":""),R&&i?L.insertBefore(B,J<0?R:R.nextSibling):L.appendChild(B),X=r?Y:g(B),n&&A[T].options.group.revertDrag&&(G.target=N,G.newIndex=Y,G.relative=0,O({sortable:A[T],name:"onChange",params:this._getParams(t,{to:A,target:N,newIndex:Y,revertDrag:!0})})),n||O({sortable:M[T],name:"onRemove",params:this._getParams(t,{newIndex:-1})}),o&&e!==N&&(V=e,O({sortable:this,name:"onChange",params:this._getParams(t,{from:A,backToOrigin:!0})})),o||O({sortable:this,name:"onAdd",params:this._getParams(t,{oldIndex:-1})}),M[T].animator.animate(),this.animator.animate(),M=this.el},_onChange:function(t){K=g(B),L=R.parentNode,F=R,this.el===A&&(V=R),this.animator.collect(L),L.insertBefore(B,j),X=g(B),O({sortable:this,name:"onChange",params:this._getParams(t)}),this.animator.animate(),M=this.el},_onDrop:function(t){this._cancelStart(),u($,"touchmove",this._nearestSortable),u($,"mousemove",this._nearestSortable),u($,"mouseup",this._onDrop),u($,"touchend",this._onDrop),u($,"touchcancel",this._onDrop),b(N,this.options.chosenClass,!1),A&&(M=A,K=Y,F===B&&(F=N),this.multiplayer.toggleClass(!1),O({sortable:this,name:"onUnchoose",params:this._getParams(t)}),q&&this._onEnd(t));var e=this.options,n=e.multiple,o=e.selectHandle;n&&(o&&Z||!o&&!A)&&!nt(t.changedTouches?t.changedTouches[0]:t)&&this.multiplayer.onSelect(t,N,this),P&&P.parentNode&&P.parentNode.removeChild(P),this.autoScroller.destroy(),this.multiplayer.destroy(),this._nulling()},_onEnd:function(t){var n=this._getParams(t);this.multiplayer.onDrop(M,k,H);var o=this.options.swapOnDrop;"clone"===H&&M!==k||!("function"==typeof o?o(n):o)||L.insertBefore(N,B),"clone"!==H||M===k||this.multiplayer.active()?B&&B.parentNode&&B.parentNode.removeChild(B):b(B,this.options.chosenClass,!1),w(N,"display",""),M!==k&&O({sortable:M[T],name:"onDrop",params:e({},n,"clone"===H?G:{newIndex:-1})}),O({sortable:k[T],name:"onDrop",params:e({},n,M===k?{}:{oldIndex:-1})})},_getParams:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},o={};return o.event=t,o.to=k,o.from=M,o.node=N,o.clone=B,o.target=F,o.oldIndex=K,o.newIndex=X,o.pullMode=H,this.multiplayer.setParams(o),e(o,n),o.relative=F===N?0:x(B,F),o},_nulling:function(){k=M=A=N=R=j=B=P=F=L=H=K=X=Y=W=q=U=G=V=$=J=Q=Z=ot.clone=ot.ghost=ot.active=ot.dragged=null}},ot.utils={on:c,off:u,css:w,index:g,closest:f,getRect:d,toggleClass:b,detectDirection:y},ot.get=function(t){return t[T]},ot.create=function(t,e){return new ot(t,e)},ot}()}(g);var v=m(g.exports),y=["delay","group","handle","lockAxis","disabled","sortable","draggable","animation","autoScroll","ghostClass","ghostStyle","chosenClass","fallbackOnBody","scrollThreshold","delayOnTouchOnly"];function b(t,e){this.el=t,this.options=e,this.reRendered=!1,this.installSortable()}function S(t,e){var n=null,o=function(){for(var o=this,i=arguments.length,r=new Array(i),s=0;sl&&1===e.relative)&&(l+=e.relative),l!==a&&(r.splice(a,1),r.splice(l,0,n))):(e.from===this.el&&(a=this.getIndex(o),r.splice(a,1)),e.to===this.el&&(a=-1,l=this.getIndex(s),0===e.relative?l=r.length:1===e.relative&&(l+=e.relative),r.splice(l,0,n))),t.changed=e.from!==e.to||l!==a,t.list=r,t.oldIndex=a,t.newIndex=l},getIndex:function(t){return this.options.uniqueKeys.indexOf(t)},dispatchEvent:function(t,e){var n=this.options[t];n&&n(e)}};var E=["size","keeps","scroller","direction","debounceTime","throttleTime"],O={INIT:"INIT",FIXED:"FIXED",DYNAMIC:"DYNAMIC"},I="FRONT",D="BEHIND",T="STATIONARY",_={vertical:"top",horizontal:"left"},z={vertical:"scrollTop",horizontal:"scrollLeft"},C={vertical:"scrollHeight",horizontal:"scrollWidth"},k={vertical:"offsetHeight",horizontal:"offsetWidth"};function M(t){this.options=t;var e={size:0,keeps:0,buffer:0,wrapper:null,scroller:null,direction:"vertical",uniqueKeys:[],debounceTime:null,throttleTime:null};for(var n in e)!(n in this.options)&&(this.options[n]=e[n]);this.sizes=new Map,this.range={start:0,end:0,front:0,behind:0},this.offset=0,this.calcType=O.INIT,this.calcSize={average:0,total:0,fixed:0},this.scrollDirection="",this.updateScrollElement(),this.updateOnScrollFunction(),this.addScrollEventListener(),this.checkIfUpdate(0,t.keeps-1)}function A(t,e){o.useEffect(e,Object.values(t))}M.prototype={constructor:M,isFront:function(){return this.scrollDirection===I},isBehind:function(){return this.scrollDirection===D},isFixed:function(){return this.calcType===O.FIXED},getSize:function(t){return this.sizes.get(t)||this.getItemSize()},getOffset:function(){return this.scrollEl[z[this.options.direction]]},getScrollSize:function(){return this.scrollEl[C[this.options.direction]]},getClientSize:function(){return this.scrollEl[k[this.options.direction]]},scrollToOffset:function(t){this.scrollEl[z[this.options.direction]]=t},scrollToIndex:function(t){if(t>=this.options.uniqueKeys.length-1)this.scrollToBottom();else{var e=this.getOffsetByIndex(t),n=this.getScrollStartOffset();this.scrollToOffset(e+n)}},scrollToBottom:function(){var t=this,e=this.getScrollSize();this.scrollToOffset(e),setTimeout((function(){var e=t.getClientSize(),n=t.getScrollSize();t.getOffset()+e+1=n;this.options.onScroll({top:o,bottom:i,offset:t,direction:this.scrollDirection}),this.isFront()?this.handleScrollFront():this.isBehind()&&this.handleScrollBehind()},handleScrollFront:function(){var t=this.getScrollItems();if(!(t>this.range.start)){var e=Math.max(t-this.options.buffer,0);this.checkIfUpdate(e,this.getEndByStart(e))}},handleScrollBehind:function(){var t=this.getScrollItems();tt&&(n=o-1)}return e>0?--e:0},checkIfUpdate:function(t,e){var n=this.options.keeps;this.options.uniqueKeys.length<=n?(t=0,e=this.getLastIndex()):e-t0?e.length-1:n-1},getItemSize:function(){return this.isFixed()?this.calcSize.fixed:this.options.size||this.calcSize.average},getScrollStartOffset:function(){var t=0,e=this.options,n=e.wrapper,o=e.scroller,i=e.direction;if(o&&n){var r=o instanceof Window?v.utils.getRect(n):v.utils.getRect(n,!0,o);t=this.offset+r[_[i]]}return t}};var N={top:"onTop",bottom:"onBottom"};var R="onDrag",j="onDrop";function B(t,e){var n=t.keeps,r=void 0===n?30:n,s=t.dataKey,l=void 0===s?"":s,a=t.sortable,h=void 0===a||a,d=t.scroller,f=void 0===d?void 0:d,m=t.direction,g=void 0===m?"vertical":m,v=t.dataSource,S=void 0===v?[]:v,O=t.style,I=void 0===O?{}:O,D=t.className,T=void 0===D?"":D,_=t.wrapStyle,z=void 0===_?{}:_,C=t.wrapClass,k=void 0===C?"":C,B=t.itemClass,P=void 0===B?"virutal-dnd-list-item":B,F=t.wrapTag,L=void 0===F?"div":F,H=t.rootTag,K=void 0===H?"div":H,X=c(i.default.useState({start:0,end:r-1,front:0,behind:0}),2),Y=X[0],W=X[1],q=i.default.useRef(""),U=i.default.useRef([]),G=i.default.useRef(null),V=i.default.useRef(null),$=i.default.useMemo((function(){var t="vertical"!==g;return{isHorizontal:t,itemSizeKey:t?"offsetWidth":"offsetHeight"}}),[g]),J=$.isHorizontal,Q=$.itemSizeKey,Z=function(t){return ut.current.getSize(t)},tt=function(){return ut.current.getOffset()},et=function(){return ut.current.getClientSize()},nt=function(){return ut.current.getScrollSize()},ot=function(t){ut.current.scrollToOffset(t)},it=function(t){ut.current.scrollToIndex(t)},rt=function(t){var e=U.current.indexOf(t);e>-1&&ut.current.scrollToIndex(e)},st=function(){ot(0)},lt=function(){ut.current.scrollToBottom()};i.default.useImperativeHandle(e,(function(){return{getSize:Z,getOffset:tt,getClientSize:et,getScrollSize:nt,scrollToTop:st,scrollToKey:rt,scrollToIndex:it,scrollToOffset:ot,scrollToBottom:lt}}));var at=i.default.useRef([]);i.default.useEffect((function(){var t;ct(),gt(at.current,S),at.current=S,null===(t=ft.current)||void 0===t||t.option("list",S)}),[S]);var ct=function(){var t,e;U.current=S.map((function(t){return x(t,l)})),null===(t=ut.current)||void 0===t||t.option("uniqueKeys",U.current),null===(e=ft.current)||void 0===e||e.option("uniqueKeys",U.current)},ut=i.default.useRef(void 0),ht=function(t,e,n,i,r){var s=t.size,l=void 0===s?void 0:s,a=t.keeps,u=void 0===a?30:a,h=t.scroller,d=void 0===h?void 0:h,f=t.direction,p=void 0===f?"vertical":f,m=t.dataSource,g=void 0===m?[]:m,v=t.debounceTime,y=void 0===v?0:v,b=t.throttleTime,S=void 0===b?0:b,x=c(o.useState(void 0),2),O=x[0],I=x[1],D=o.useRef(!1),T={size:l,keeps:u,scroller:d,direction:p,debounceTime:y,throttleTime:S},_=w((function(){var e;D.current=!0,null===(e=t[N.top])||void 0===e||e.call(t)}),50),z=w((function(){var e;null===(e=t[N.bottom])||void 0===e||e.call(t)}),50);o.useEffect((function(){return I((function(){return new M(Object.assign(Object.assign({},T),{buffer:Math.round(u/3),wrapper:n.current,scroller:d||e.current,uniqueKeys:i,onScroll:function(t){D.current=!1,t.top?_():t.bottom&&z()},onUpdate:r}))})),function(){null==O||O.removeScrollEventListener()}}),[]);var C=o.useRef(null);return o.useEffect((function(){if(D.current&&t.keepOffset){var e=Math.abs(g.length-C.current);null==O||O.scrollToIndex(e),D.current=!1}C.current=g.length}),[g]),A(T,(function(){E.forEach((function(e){null==O||O.option(e,t[e])}))})),[O]}(t,G,V,U.current,(function(t){W((function(e){return q.current&&t.start!==e.start&&(ft.current.reRendered=!0),t}))})),dt=c(ht,1)[0];ut.current=dt;var ft=i.default.useRef(void 0),pt=function(t,e,n,i,r,s){var l=e.delay,a=void 0===l?0:l,u=e.group,h=void 0===u?"":u,d=e.handle,f=void 0===d?"":d,p=e.lockAxis,m=void 0===p?void 0:p,g=e.disabled,v=void 0!==g&&g,S=e.sortable,w=void 0===S||S,x=e.draggable,E=void 0===x?".virutal-dnd-list-item":x,O=e.animation,I=void 0===O?150:O,D=e.autoScroll,T=void 0===D||D,_=e.ghostClass,z=void 0===_?"":_,C=e.ghostStyle,k=void 0===C?void 0:C,M=e.chosenClass,N=void 0===M?"":M,R=e.fallbackOnBody,j=void 0!==R&&R,B=e.scrollThreshold,P=void 0===B?55:B,F=e.delayOnTouchOnly,L=void 0!==F&&F,H=c(o.useState(void 0),2),K=H[0],X=H[1],Y={delay:a,group:h,handle:f,lockAxis:m,disabled:v,sortable:w,draggable:E,animation:I,autoScroll:T,ghostClass:z,ghostStyle:k,chosenClass:N,fallbackOnBody:j,scrollThreshold:P,delayOnTouchOnly:L};return o.useEffect((function(){return X((function(){return new b(n.current,Object.assign(Object.assign({},Y),{list:t,uniqueKeys:i,onDrag:r,onDrop:s}))})),function(){null==K||K.destroy()}}),[]),A(Y,(function(){y.forEach((function(t){null==K||K.option(t,e[t])}))})),[K]}(S,t,V,U.current,(function(e){var n;q.current=e.key,h||(ut.current.enableScroll(!1),ft.current.option("autoScroll",!1)),null===(n=t[R])||void 0===n||n.call(t,e)}),(function(e){var n;q.current="",ut.current.enableScroll(!0),ft.current.option("autoScroll",t.autoScroll),null===(n=t[j])||void 0===n||n.call(t,Object.assign(Object.assign({},e),{list:u(e.list)}))})),mt=c(pt,1)[0];ft.current=mt;var gt=function(t,e){var n,o=Object.assign({},Y);t.length&&e.length>t.length&&Y.end===t.length-1&&vt()&&(o.end++,o.start=Math.max(0,o.end-r)),null===(n=ut.current)||void 0===n||n.updateRange(o)},vt=function(){return tt()+et()+1>=nt()},yt=function(t){var e=t.list,n=t.start,i=t.end,r=t.dataKey,s=t.sizeKey,l=t.dragging,a=t.children,c=t.itemClass,u=t.onSizeChange;return e.slice(n,i+1).map((function(t,e){var i=n+e,h=x(t,r);return o.createElement(p,{key:h,dataKey:h,sizeKey:s,dragging:l,children:a,itemClass:c,onSizeChange:u},"function"==typeof a?a(t,i,h):a)}))}({list:S,start:Y.start,end:Y.end,dataKey:l,sizeKey:Q,children:t.children,dragging:q.current,itemClass:P,onSizeChange:function(t,e){var n=ut.current.sizes.size,o=Math.min(r,S.length);ut.current.onItemResized(t,e),n===o-1&>(S,S)}}),bt=i.default.useMemo((function(){var t=J?"auto hidden":"hidden auto";return Object.assign(Object.assign({},I),{overflow:f?"":t})}),[I,J,f]),St=i.default.useMemo((function(){var t=Y.front,e=Y.behind,n=J?"0px ".concat(e,"px 0px ").concat(t,"px"):"".concat(t,"px 0px ").concat(e,"px");return Object.assign(Object.assign({},z),{padding:n})}),[z,J,Y]);return i.default.createElement(K,{ref:G,style:bt,className:T},t.header,i.default.createElement(L,{ref:V,style:St,className:k},yt),t.footer)}return i.default.forwardRef(B)})); + */!function(t,e){t.exports=function(){function t(e){return(t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(e)}function e(){return e=Object.assign?Object.assign.bind():function(t){for(var e=1;e"===e[0]?t.parentNode===n&&S(t,e):S(t,e))||o&&t===n)return t;if(t===n)break}while(t=t.parentNode);return null}}function p(t,e){if(!t||!e)return!1;if(e.compareDocumentPosition)return!!(16&e.compareDocumentPosition(t));if(e.contains&&1===t.nodeType)return e.contains(t)&&e!==t;for(;t=t.parentNode;)if(t===e)return!0;return!1}function m(t,e){for(var n=t.lastElementChild;n&&(n===ot.ghost||"none"===w(n,"display")||e&&!S(n,e));)n=n.previousElementSibling;return n||null}function g(t,e){if(!t||!t.parentNode)return-1;for(var n=0;t=t.previousElementSibling;)"TEMPLATE"===t.nodeName.toUpperCase()||e&&!S(t,e)||"none"===w(t,"display")||n++;return n}function v(t,e,n,o){for(var i=0,r=0,s=t.children;i=o&&"none"===n[f]||l&&"none"===n[f]&&u+h>o)?"vertical":"horizontal"}function b(t,e,n){if(t&&e)if(t.classList)t.classList[n?"add":"remove"](e);else{var i=(" "+t.className+" ").replace(o," ").replace(" "+e+" "," ");t.className=(i+(n?" "+e:"")).replace(o," ")}}function S(t,e){if(e){if(">"===e[0]&&(e=e.substring(1)),t)try{if(t.matches)return t.matches(e);if(t.msMatchesSelector)return t.msMatchesSelector(e);if(t.webkitMatchesSelector)return t.webkitMatchesSelector(e)}catch(t){return!1}return!1}}function w(t,e,n){var o=t&&t.style;if(o){if(void 0===n)return document.defaultView&&document.defaultView.getComputedStyle?n=document.defaultView.getComputedStyle(t,""):t.currentStyle&&(n=t.currentStyle),void 0===e?n:n[e];e in o||-1!==e.indexOf("webkit")||(e="-webkit-"+e),o[e]=n+("string"==typeof n?"":"px")}}function x(t,e){var n,o,i=(o=e,(n=t).compareDocumentPosition?n.compareDocumentPosition(o):n.contains?(n!=o&&n.contains(o)&&16)+(n!=o&&o.contains(n)&&8)+(n.sourceIndex>=0&&o.sourceIndex>=0?(n.sourceIndexo.sourceIndex&&2):1):0);return 2===i?1:4===i?-1:0}function E(t){void 0!==t.preventDefault&&t.cancelable&&t.preventDefault()}function O(t){var n=t.sortable,o=t.name,i=t.params,r=n.options[o];"function"==typeof r&&r(e({},i))}!function(){if("undefined"==typeof window||"undefined"==typeof document)return"";var t=window.getComputedStyle(document.documentElement,"")||["-moz-hidden-iframe"];(Array.prototype.slice.call(t).join("").match(/-(moz|webkit|ms)-/)||""===t.OLink&&["","o"])[1]}();var I,D,T="Sortable"+Date.now();function _(t){this.options=t,this.autoScrollAnimationFrame=null}function z(t){this.options=t,this.stack=[]}function C(t){this.options=t||{},this.selectedElements=[]}window.requestAnimationFrame||(window.requestAnimationFrame=function(t){return setTimeout(t,17)}),window.cancelAnimationFrame||(window.cancelAnimationFrame=function(t){clearTimeout(t)}),_.prototype={destroy:function(){this.autoScrollAnimationFrame&&(cancelAnimationFrame(this.autoScrollAnimationFrame),this.autoScrollAnimationFrame=null)},update:function(t,e,n){var o=this;cancelAnimationFrame(this.autoScrollAnimationFrame),this.autoScrollAnimationFrame=requestAnimationFrame((function(){e&&n&&o.autoScroll(t,n),o.update(t,e,n)}))},autoScroll:function(t,e){if(t&&void 0!==e.clientX&&void 0!==e.clientY){var n=d(t);if(n){var o=e.clientX,i=e.clientY,r=n.top,s=n.right,l=n.bottom,a=n.left,c=n.height,u=n.width;if(!(is||i>l||o0&&i>=r&&i<=r+f,b=g+u=s-f,S=m+c=l-f;g>0&&o>=a&&o<=a+f&&(t.scrollLeft+=Math.floor(Math.max(-1,(o-a)/f-1)*p.x)),b&&(t.scrollLeft+=Math.ceil(Math.min(1,(o-s)/f+1)*p.x)),y&&(t.scrollTop+=Math.floor(Math.max(-1,(i-r)/f-1)*p.y)),S&&(t.scrollTop+=Math.ceil(Math.min(1,(i-l)/f+1)*p.y))}}}}},z.prototype={collect:function(t){if(t){for(var e=d(t),n=window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth,o=window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight,i=Math.min(e.right,n),r=Math.min(e.bottom,o),s=Array.prototype.slice.call(t.children),l=[],a=0,c=s.length;a<=c;a++){var u=s[a];if(u&&u!==ot.ghost&&"none"!==w(u,"display")){var h=d(u);if(!(h.bottom<0||h.right<0)){if(h.top-h.height>r||h.left-h.width>i)break;l.push({el:u,rect:h})}}}this.stack.push(l)}},animate:function(){for(var t=this.stack.pop(),e=0,n=t.length;e-1&&(b(t,this.options.selectedClass,!1),this.selectedElements.splice(e,1))},getGhostElement:function(){if(!I)return null;var t=document.createElement("div");return this.selectedElements.forEach((function(e,n){var o=e.cloneNode(!0),i=0===n?1:.5;o.style="position: absolute;left: 0;top: 0;bottom: 0;right: 0;opacity: ".concat(i,";z-index: ").concat(n,";"),t.appendChild(o)})),t},toggleSelected:function(t,e){var n=this;e?t.forEach((function(t){return n.selectedElements.push(t)})):this.selectedElements=this.selectedElements.filter((function(e){return t.indexOf(e)<0}))},toggleClass:function(t){if(I)for(var e=0;e0?t[o-1]:n;n.parentNode.insertBefore(t[o],i.nextSibling)}},_hideElements:function(t){for(var e=0;e-1&&tt.splice(t,1),this.el[T]=this.animator=this.multiplayer=this.autoScroller=null},option:function(t,e){if(void 0===e)return this.options[t];this.options[t]=e,this.animator.options[t]=e,this.multiplayer.options[t]=e,this.autoScroller.options[t]=e,"group"===t&&et(this.options)},select:function(t){this.multiplayer.select(t)},deselect:function(t){this.multiplayer.deselect(t)},getSelectedElements:function(){return this.multiplayer.selectedElements},_onDrag:function(t){var e=this;if(!N&&!this.options.disabled&&this.options.group.pull&&(!/mousedown|pointerdown/.test(t.type)||0===t.button)){var n=t.touches&&t.touches[0],o=(n||t).target;if(!l||!o||"SELECT"!==o.tagName.toUpperCase()){var i=f(o,this.options.draggable,this.el);if(i&&!i.animated){W={origin:t,clientX:(n||t).clientX,clientY:(n||t).clientY},N=i,c($=n?N:document,"mouseup",this._onDrop),c($,"touchend",this._onDrop),c($,"touchcancel",this._onDrop);var a=this.options,u=a.handle,h=a.selectHandle;if("function"==typeof h&&h(t)||"string"==typeof h&&S(o,h))Z=!0;else if(("function"!=typeof u||u(t))&&("string"!=typeof u||S(o,u))){var d=this.options,p=d.delay,m=d.delayOnTouchOnly;!p||m&&!n||s||r?this._onStart(n,t):(c(this.el.ownerDocument,"touchmove",this._delayMoveHandler),c(this.el.ownerDocument,"mousemove",this._delayMoveHandler),c(this.el.ownerDocument,"mouseup",this._cancelStart),c(this.el.ownerDocument,"touchend",this._cancelStart),c(this.el.ownerDocument,"touchcancel",this._cancelStart),Q=setTimeout((function(){return e._onStart(n,t)}),p)),c(document,"selectstart",E),l&&w(document.body,"user-select","none")}}}}},_delayMoveHandler:function(t){var e=t.touches?t.touches[0]:t;Math.max(Math.abs(e.clientX-W.clientX),Math.abs(e.clientY-W.clientY))>=Math.floor(this.options.touchStartThreshold/(window.devicePixelRatio||1))&&this._cancelStart()},_cancelStart:function(){clearTimeout(Q),u(this.el.ownerDocument,"touchmove",this._delayMoveHandler),u(this.el.ownerDocument,"mousemove",this._delayMoveHandler),u(this.el.ownerDocument,"mouseup",this._cancelStart),u(this.el.ownerDocument,"touchend",this._cancelStart),u(this.el.ownerDocument,"touchcancel",this._cancelStart),u(document,"selectstart",E),l&&w(document.body,"user-select","")},_onStart:function(t,e){var n=g(N);k=this.el,M=this.el,F=N,H=n,X=n,Y=n,G={to:this.el,target:N,newIndex:n,relative:0},V=N,A=this.el,B=N.cloneNode(!0),L=N.parentNode,K=this.options.group.pull,ot.clone=B,ot.active=this,ot.dragged=N,b(N,this.options.chosenClass,!0),this.multiplayer.onChoose(),O({sortable:this,name:"onChoose",params:this._getParams(e)}),c($,t?"touchmove":"mousemove",this._nearestSortable);try{document.selection?setTimeout((function(){return document.selection.empty()}),0):window.getSelection().removeAllRanges()}catch(t){}},_onStarted:function(){b(B,this.options.chosenClass,!0),this._appendGhost(),this.multiplayer.onDrag(this),O({sortable:this,name:"onDrag",params:this._getParams(W.origin)}),w(N,"display","none"),b(N,this.options.chosenClass,!1),N.parentNode.insertBefore(B,N)},_getGhostElement:function(){var t=this.options.customGhost;if("function"==typeof t){var e=this.multiplayer.selectedElements;return t(e.length?e:[N])}return this.multiplayer.getGhostElement()||N},_appendGhost:function(){if(!P){var t=this.options.fallbackOnBody?document.body:this.el,n=this._getGhostElement();b(P=n.cloneNode(!0),this.options.ghostClass,!0);var o=d(N),i=e({position:"fixed",top:o.top,left:o.left,width:o.width,height:o.height,zIndex:"100000",opacity:"0.8",overflow:"hidden",boxSizing:"border-box",transform:"translate3d(0px, 0px, 0px)",transition:"none",pointerEvents:"none"},this.options.ghostStyle);for(var r in i)w(P,r,i[r]);ot.ghost=P,t.appendChild(P);var s=(W.clientX-o.left)/parseInt(P.style.width)*100,l=(W.clientY-o.top)/parseInt(P.style.height)*100;w(P,"transform-origin",s+"% "+l+"%"),w(P,"will-change","transform")}},_nearestSortable:function(t){E(t);var e=t.touches&&t.touches[0]||t;if(N&&nt(e)){!q&&this._onStarted();var n=this.options.lockAxis,o="x"===n?W.clientX:e.clientX,i="y"===n?W.clientY:e.clientY,r=document.elementFromPoint(o,i),s=o-W.clientX,l=i-W.clientY;q={origin:t,clientX:o,clientY:i},w(P,"transform","translate3d("+s+"px, "+l+"px, 0)");var a,c,u,f=(a=o,c=i,tt.reduce((function(t,e){var n=e[T].options.emptyInsertThreshold;if(null!=n){var o=d(e),i=a>=o.left-n&&a<=o.right+n,r=c>=o.top-n&&c<=o.bottom+n;return i&&r&&(!u||u&&o.left>=u.left&&o.right<=u.right&&o.top>=u.top&&o.bottom<=u.bottom)&&(t=e,u=o),t}}),null));if(f&&f[T]._onMove(t,r),!f||f[T].options.autoScroll){var p=function(t,e){if(!t||!t.getBoundingClientRect)return h();var n=t,o=!1;do{if(n.clientWidth-1||o.name&&e&&o.name===e}return!1},_getDirection:function(){var t=this.options,e=t.draggable,n=t.direction;return n?"function"==typeof n?n.call(q.origin,N,this):n:y(L,e)},_allowSwap:function(){var t=d(R),e="vertical"===this._getDirection(),n=e?"top":"left",o=e?"bottom":"right",i=R[e?"offsetHeight":"offsetWidth"],r=e?q.clientY:q.clientX,s=r>=t[n]&&ru[o]&&(j=R.nextSibling,!0);var h=x(B,R);return j=h<0?R.nextSibling:R,U!==R?(J=s,!0):J!==s&&(J=s,s<0?h>0:h<0)},_onMove:function(t,e){if(!this.options.disabled&&this._allowPut()){if(R=f(e,this.options.draggable,this.el),O({sortable:this,name:"onMove",params:this._getParams(t,{target:R})}),this.options.sortable||this.el!==A)return this.el===M||e!==this.el&&m(this.el)?void(R&&!R.animated&&!p(R,B)&&this._allowSwap()&&(R!==B&&j!==B?(this.el!==M?this._onInsert(t):R!==N&&this._onChange(t),U=R):U=R)):(R=U=null,void this._onInsert(t));M!==A&&(R=U=N,J=0,this._onInsert(t))}},_onInsert:function(t){var e=R||B,n="clone"===K&&this.el!==A&&M===A,o="clone"===K&&this.el===A&&M!==A,i=p(R,document),r=R===N&&!i;k=this.el,H=g(B),F=e,L=i?R.parentNode:this.el,M[T].animator.collect(B.parentNode),this.animator.collect(L),n&&(G.target=V,G.newIndex=H,G.relative=V===N?0:x(B,V),w(N,"display",""),A[T].multiplayer.toggleVisible(!0),A[T].options.group.revertDrag||B.parentNode.insertBefore(N,B)),o&&(H=g(N),w(N,"display","none"),this.multiplayer.toggleVisible(!1)),w(B,"display",r?"none":""),R&&i?L.insertBefore(B,J<0?R:R.nextSibling):L.appendChild(B),X=r?Y:g(B),n&&A[T].options.group.revertDrag&&(G.target=N,G.newIndex=Y,G.relative=0,O({sortable:A[T],name:"onChange",params:this._getParams(t,{to:A,target:N,newIndex:Y,revertDrag:!0})})),n||O({sortable:M[T],name:"onRemove",params:this._getParams(t,{newIndex:-1})}),o&&e!==N&&(V=e,O({sortable:this,name:"onChange",params:this._getParams(t,{from:A,backToOrigin:!0})})),o||O({sortable:this,name:"onAdd",params:this._getParams(t,{oldIndex:-1})}),M[T].animator.animate(),this.animator.animate(),M=this.el},_onChange:function(t){H=g(B),L=R.parentNode,F=R,this.el===A&&(V=R),this.animator.collect(L),L.insertBefore(B,j),X=g(B),O({sortable:this,name:"onChange",params:this._getParams(t)}),this.animator.animate(),M=this.el},_onDrop:function(t){this._cancelStart(),u($,"touchmove",this._nearestSortable),u($,"mousemove",this._nearestSortable),u($,"mouseup",this._onDrop),u($,"touchend",this._onDrop),u($,"touchcancel",this._onDrop),b(N,this.options.chosenClass,!1),A&&(M=A,H=Y,F===B&&(F=N),this.multiplayer.toggleClass(!1),O({sortable:this,name:"onUnchoose",params:this._getParams(t)}),q&&this._onEnd(t));var e=this.options,n=e.multiple,o=e.selectHandle;n&&(o&&Z||!o&&!A)&&!nt(t.changedTouches?t.changedTouches[0]:t)&&this.multiplayer.onSelect(t,N,this),P&&P.parentNode&&P.parentNode.removeChild(P),this.autoScroller.destroy(),this.multiplayer.destroy(),this._nulling()},_onEnd:function(t){var n=this._getParams(t);this.multiplayer.onDrop(M,k,K);var o=this.options.swapOnDrop;"clone"===K&&M!==k||!("function"==typeof o?o(n):o)||L.insertBefore(N,B),"clone"!==K||M===k||this.multiplayer.active()?B&&B.parentNode&&B.parentNode.removeChild(B):b(B,this.options.chosenClass,!1),w(N,"display",""),M!==k&&O({sortable:M[T],name:"onDrop",params:e({},n,"clone"===K?G:{newIndex:-1})}),O({sortable:k[T],name:"onDrop",params:e({},n,M===k?{}:{oldIndex:-1})})},_getParams:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},o={};return o.event=t,o.to=k,o.from=M,o.node=N,o.clone=B,o.target=F,o.oldIndex=H,o.newIndex=X,o.pullMode=K,this.multiplayer.setParams(o),e(o,n),o.relative=F===N?0:x(B,F),o},_nulling:function(){k=M=A=N=R=j=B=P=F=L=K=H=X=Y=W=q=U=G=V=$=J=Q=Z=ot.clone=ot.ghost=ot.active=ot.dragged=null}},ot.utils={on:c,off:u,css:w,index:g,closest:f,getRect:d,toggleClass:b,detectDirection:y},ot.get=function(t){return t[T]},ot.create=function(t,e){return new ot(t,e)},ot}()}(m);var g=p(m.exports),v=["delay","group","handle","lockAxis","disabled","sortable","draggable","animation","autoScroll","ghostClass","ghostStyle","chosenClass","fallbackOnBody","scrollThreshold","delayOnTouchOnly"];function y(t,e){this.el=t,this.options=e,this.reRendered=!1,this.installSortable()}function b(t,e){var n=null,o=function(){for(var o=this,i=arguments.length,r=new Array(i),s=0;sl&&1===e.relative)&&(l+=e.relative),l!==a&&(r.splice(a,1),r.splice(l,0,n))):(e.from===this.el&&(a=this.getIndex(o),r.splice(a,1)),e.to===this.el&&(a=-1,l=this.getIndex(s),0===e.relative?l=r.length:1===e.relative&&(l+=e.relative),r.splice(l,0,n))),t.changed=e.from!==e.to||l!==a,t.list=r,t.oldIndex=a,t.newIndex=l},getIndex:function(t){return this.options.uniqueKeys.indexOf(t)},dispatchEvent:function(t,e){var n=this.options[t];n&&n(e)}};var x=["size","keeps","scroller","direction","debounceTime","throttleTime"],E={INIT:"INIT",FIXED:"FIXED",DYNAMIC:"DYNAMIC"},O="FRONT",I="BEHIND",D="STATIONARY",T={vertical:"top",horizontal:"left"},_={vertical:"scrollTop",horizontal:"scrollLeft"},z={vertical:"scrollHeight",horizontal:"scrollWidth"},C={vertical:"offsetHeight",horizontal:"offsetWidth"};function k(t){this.options=t;var e={size:0,keeps:0,buffer:0,wrapper:null,scroller:null,direction:"vertical",uniqueKeys:[],debounceTime:null,throttleTime:null};for(var n in e)!(n in this.options)&&(this.options[n]=e[n]);this.sizes=new Map,this.range={start:0,end:0,front:0,behind:0},this.offset=0,this.calcType=E.INIT,this.calcSize={average:0,total:0,fixed:0},this.scrollDirection="",this.updateScrollElement(),this.updateOnScrollFunction(),this.addScrollEventListener(),this.checkIfUpdate(0,t.keeps-1)}k.prototype={constructor:k,isFront:function(){return this.scrollDirection===O},isBehind:function(){return this.scrollDirection===I},isFixed:function(){return this.calcType===E.FIXED},getSize:function(t){return this.sizes.get(t)||this.getItemSize()},getOffset:function(){return this.scrollEl[_[this.options.direction]]},getScrollSize:function(){return this.scrollEl[z[this.options.direction]]},getClientSize:function(){return this.scrollEl[C[this.options.direction]]},scrollToOffset:function(t){this.scrollEl[_[this.options.direction]]=t},scrollToIndex:function(t){if(t>=this.options.uniqueKeys.length-1)this.scrollToBottom();else{var e=this.getOffsetByIndex(t),n=this.getScrollStartOffset();this.scrollToOffset(e+n)}},scrollToBottom:function(){var t=this,e=this.getScrollSize();this.scrollToOffset(e),setTimeout((function(){var e=t.getClientSize(),n=t.getScrollSize();t.getOffset()+e+1=n;this.options.onScroll({top:o,bottom:i,offset:t,direction:this.scrollDirection}),this.isFront()?this.handleScrollFront():this.isBehind()&&this.handleScrollBehind()},handleScrollFront:function(){var t=this.getScrollItems();if(!(t>this.range.start)){var e=Math.max(t-this.options.buffer,0);this.checkIfUpdate(e,this.getEndByStart(e))}},handleScrollBehind:function(){var t=this.getScrollItems();tt&&(n=o-1)}return e>0?--e:0},checkIfUpdate:function(t,e){var n=this.options.keeps;this.options.uniqueKeys.length<=n?(t=0,e=this.getLastIndex()):e-t0?e.length-1:n-1},getItemSize:function(){return this.isFixed()?this.calcSize.fixed:this.options.size||this.calcSize.average},getScrollStartOffset:function(){var t=0,e=this.options,n=e.wrapper,o=e.scroller,i=e.direction;if(o&&n){var r=o instanceof Window?g.utils.getRect(n):g.utils.getRect(n,!0,o);t=this.offset+r[T[i]]}return t}};var M="onDrag",A="onDrop",N="onTop",R="onBottom";function j(t,e){var o=t.dataKey,i=void 0===o?"":o,r=t.dataSource,s=void 0===r?[]:r,c=t.tableMode,u=void 0!==c&&c,d=t.wrapTag,p=void 0===d?"div":d,m=t.rootTag,g=void 0===m?"div":m,b=t.style,E=void 0===b?{}:b,O=t.className,I=void 0===O?"":O,D=t.wrapStyle,T=void 0===D?{}:D,_=t.wrapClass,z=void 0===_?"":_,C=t.itemClass,j=void 0===C?"virutal-dnd-list-item":C,B=t.size,P=void 0===B?void 0:B,F=t.keeps,L=void 0===F?30:F,K=t.scroller,H=void 0===K?void 0:K,X=t.direction,Y=void 0===X?"vertical":X,W=t.debounceTime,q=void 0===W?0:W,U=t.throttleTime,G=void 0===U?0:U,V=t.delay,$=void 0===V?0:V,J=t.group,Q=void 0===J?"":J,Z=t.handle,tt=void 0===Z?"":Z,et=t.lockAxis,nt=void 0===et?void 0:et,ot=t.disabled,it=void 0!==ot&&ot,rt=t.sortable,st=void 0===rt||rt,lt=t.draggable,at=void 0===lt?".virutal-dnd-list-item":lt,ct=t.animation,ut=void 0===ct?150:ct,ht=t.autoScroll,dt=void 0===ht||ht,ft=t.ghostClass,pt=void 0===ft?"":ft,mt=t.ghostStyle,gt=void 0===mt?void 0:mt,vt=t.chosenClass,yt=void 0===vt?"":vt,bt=t.fallbackOnBody,St=void 0!==bt&&bt,wt=t.scrollThreshold,xt=void 0===wt?55:wt,Et=t.delayOnTouchOnly,Ot=void 0!==Et&&Et,It=l(n.useState({start:0,end:L-1,front:0,behind:0}),2),Dt=It[0],Tt=It[1],_t=n.useRef(""),zt=n.useRef([]),Ct=n.useRef(null),kt=n.useRef(null),Mt=function(t){return Ht.current.getSize(t)},At=function(){return Ht.current.getOffset()},Nt=function(){return Ht.current.getClientSize()},Rt=function(){return Ht.current.getScrollSize()},jt=function(t){Ht.current.scrollToOffset(t)},Bt=function(t){Ht.current.scrollToIndex(t)},Pt=function(t){var e=zt.current.indexOf(t);e>-1&&Ht.current.scrollToIndex(e)},Ft=function(){jt(0)},Lt=function(){Ht.current.scrollToBottom()};n.useImperativeHandle(e,(function(){return{getSize:Mt,getOffset:At,getClientSize:Nt,getScrollSize:Rt,scrollToTop:Ft,scrollToKey:Pt,scrollToIndex:Bt,scrollToOffset:jt,scrollToBottom:Lt}})),n.useEffect((function(){return Gt(),te(),function(){var t,e;null===(t=Ht.current)||void 0===t||t.removeScrollEventListener(),null===(e=$t.current)||void 0===e||e.destroy()}}),[]);var Kt=n.useRef(!1),Ht=n.useRef(void 0),Xt={size:P,keeps:L,scroller:H,direction:Y,debounceTime:q,throttleTime:G},Yt=S((function(){var e;Kt.current=!0,null===(e=t[N])||void 0===e||e.call(t)}),50),Wt=S((function(){var e;null===(e=t[R])||void 0===e||e.call(t)}),50),qt=function(t){Kt.current=!1,t.top?Yt():t.bottom&&Wt()},Ut=function(t){Tt((function(e){return _t.current&&t.start!==e.start&&($t.current.reRendered=!0),t}))},Gt=function(){Ht.current=new k(Object.assign(Object.assign({},Xt),{buffer:Math.round(L/3),wrapper:kt.current,scroller:H||Ct.current,uniqueKeys:zt.current,onScroll:qt,onUpdate:Ut}))};h(Xt,(function(){x.forEach((function(e){var n;void 0!==t[e]&&(null===(n=Ht.current)||void 0===n||n.option(e,t[e]))}))}));var Vt=n.useRef(null);n.useEffect((function(){var e;if(Vt.current&&Kt.current&&t.keepOffset){var n=Math.abs(s.length-Vt.current);n>0&&(null===(e=Ht.current)||void 0===e||e.scrollToIndex(n)),Kt.current=!1}Vt.current=s.length}),[s]);var $t=n.useRef(void 0),Jt={delay:$,group:Q,handle:tt,lockAxis:nt,disabled:it,sortable:st,draggable:at,animation:ut,autoScroll:dt,ghostClass:pt,ghostStyle:gt,chosenClass:yt,fallbackOnBody:St,scrollThreshold:xt,delayOnTouchOnly:Ot},Qt=function(e){var n;_t.current=e.key,st||(Ht.current.enableScroll(!1),$t.current.option("autoScroll",!1)),null===(n=t[M])||void 0===n||n.call(t,e)},Zt=function(e){var n;_t.current="",Ht.current.enableScroll(!0),$t.current.option("autoScroll",t.autoScroll);var o=Object.assign(Object.assign({},e),{list:a(e.list)});null===(n=t[A])||void 0===n||n.call(t,o)},te=function(){$t.current=new y(Ct.current,Object.assign(Object.assign({},Jt),{list:s,uniqueKeys:zt.current,onDrag:Qt,onDrop:Zt}))};h(Jt,(function(){v.forEach((function(e){var n;void 0!==t[e]&&(null===(n=$t.current)||void 0===n||n.option(e,t[e]))}))}));var ee=n.useRef([]);n.useEffect((function(){var t;ne(),oe(ee.current,s),ee.current=s,null===(t=$t.current)||void 0===t||t.option("list",s)}),[s]);var ne=function(){var t,e;zt.current=s.map((function(t){return w(t,i)})),null===(t=Ht.current)||void 0===t||t.option("uniqueKeys",zt.current),null===(e=$t.current)||void 0===e||e.option("uniqueKeys",zt.current)},oe=function(t,e){var n,o=Object.assign({},Dt);t.length&&e.length>t.length&&Dt.end===t.length-1&&ie()&&(o.end++,o.start=Math.max(0,o.end-L)),null===(n=Ht.current)||void 0===n||n.updateRange(o)},ie=function(){return At()+Nt()+1>=Rt()},re=n.useMemo((function(){var t=Dt.front,e=Dt.behind,n="vertical"!==Y,o=n?"auto hidden":"hidden auto",i=n?"0px ".concat(e,"px 0px ").concat(t,"px"):"".concat(t,"px 0px ").concat(e,"px");return{containerStyle:Object.assign(Object.assign({},E),{overflow:u||H?"":o}),wrapperStyle:Object.assign(Object.assign({},T),{padding:u?null:i}),itemSizeKey:n?"offsetWidth":"offsetHeight"}}),[Dt,E,T,H,u,Y]),se=re.containerStyle,le=re.wrapperStyle,ae=re.itemSizeKey,ce=l(n.useMemo((function(){return[u?"table":p,u?"tbody":p]}),[g,p,u]),2),ue=ce[0],he=ce[1],de=function(t){var e=t.list,o=t.start,i=t.end,r=t.dataKey,s=t.sizeKey,l=t.dragging,a=t.children,c=t.itemClass,u=t.onSizeChange;return e.slice(o,i+1).map((function(t,e){var i=o+e,h=w(t,r);return n.createElement(f,{key:h,dataKey:h,sizeKey:s,dragging:l,children:a,itemClass:c,onSizeChange:u},"function"==typeof a?a(t,i,h):a)}))}({list:s,start:Dt.start,end:Dt.end,dataKey:i,sizeKey:ae,children:t.children,dragging:_t.current,itemClass:j,onSizeChange:function(t,e){var n,o,i=null===(n=Ht.current)||void 0===n?void 0:n.sizes.size,r=Math.min(L,s.length);null===(o=Ht.current)||void 0===o||o.onItemResized(t,e),i===r-1&&oe(s,s)}}),fe=function(t){var e={padding:0,border:0,margin:0,height:"".concat(t,"px")};return n.createElement("tr",null,n.createElement("td",{style:e}))};return n.createElement(ue,{ref:Ct,style:se,className:I},t.header,n.createElement(he,{ref:kt,style:le,className:z},u&&fe(Dt.front),de,u&&fe(Dt.behind)),t.footer)}return n.forwardRef(j)})); diff --git a/package.json b/package.json index eacae31..5f9c0f4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-virtual-drag-list", - "version": "2.7.0", + "version": "2.7.1", "description": "A virtual scrolling list component that can be sorted by dragging", "main": "dist/virtual-drag-list.js", "types": "types/index.d.ts", diff --git a/src/hooks/useSortable.ts b/src/hooks/useSortable.ts deleted file mode 100644 index 0b6a055..0000000 --- a/src/hooks/useSortable.ts +++ /dev/null @@ -1,76 +0,0 @@ -import * as React from 'react'; -import useCombine from './useCombine'; -import { Sortable, SortableAttrs } from '../core'; -import { DragEvent, DropEvent, VirtualProps } from '../interface'; - -function useSortable( - list: T[], - props: VirtualProps, - wrapRef: any, - uniqueKeys: string[], - onDrag: (event: DragEvent) => void, - onDrop: (event: DropEvent) => void -) { - const { - delay = 0, - group = '', - handle = '', - lockAxis = undefined, - disabled = false, - sortable = true, - draggable = '.virutal-dnd-list-item', - animation = 150, - autoScroll = true, - ghostClass = '', - ghostStyle = undefined, - chosenClass = '', - fallbackOnBody = false, - scrollThreshold = 55, - delayOnTouchOnly = false, - } = props; - - const [dnd, setDnd] = React.useState(undefined); - const combinedStates = { - delay, - group, - handle, - lockAxis, - disabled, - sortable, - draggable, - animation, - autoScroll, - ghostClass, - ghostStyle, - chosenClass, - fallbackOnBody, - scrollThreshold, - delayOnTouchOnly, - }; - - React.useEffect(() => { - setDnd(() => { - return new Sortable(wrapRef.current, { - ...combinedStates, - list, - uniqueKeys, - onDrag: onDrag, - onDrop: onDrop, - }); - }); - - return () => { - dnd?.destroy(); - }; - }, []); - - useCombine(combinedStates, () => { - SortableAttrs.forEach((key) => { - dnd?.option(key, props[key]); - }); - }); - - return [dnd]; -} - -export default useSortable; diff --git a/src/hooks/useVirtual.ts b/src/hooks/useVirtual.ts deleted file mode 100644 index 8b31357..0000000 --- a/src/hooks/useVirtual.ts +++ /dev/null @@ -1,94 +0,0 @@ -import * as React from 'react'; -import useCombine from './useCombine'; -import { Virtual, Range, VirtualAttrs, debounce } from '../core'; -import { VirtualProps } from '../interface'; - -const Emits = { - top: 'onTop', - bottom: 'onBottom', -}; - -function useVirtual( - props: VirtualProps, - rootRef: any, - wrapRef: any, - uniqueKeys: string[], - onUpdate: (range: Range) => void -) { - const { - size = undefined, - keeps = 30, - scroller = undefined, - direction = 'vertical', - dataSource = [], - debounceTime = 0, - throttleTime = 0, - } = props; - - const [virutal, setVirtual] = React.useState(undefined); - const topLoading = React.useRef(false); - const combinedStates = { - size, - keeps, - scroller, - direction, - debounceTime, - throttleTime, - }; - - const handleToTop = debounce(() => { - topLoading.current = true; - props[Emits.top]?.(); - }, 50); - - const handleToBottom = debounce(() => { - props[Emits.bottom]?.(); - }, 50); - - React.useEffect(() => { - setVirtual(() => { - return new Virtual({ - ...combinedStates, - buffer: Math.round(keeps / 3), - wrapper: wrapRef.current, - scroller: scroller || rootRef.current, - uniqueKeys, - onScroll: (event) => { - topLoading.current = false; - if (event.top) { - handleToTop(); - } else if (event.bottom) { - handleToBottom(); - } - }, - onUpdate, - }); - }); - - return () => { - virutal?.removeScrollEventListener(); - }; - }, []); - - const lastLength = React.useRef(null); - React.useEffect(() => { - // if auto scroll to the last offset - if (topLoading.current && props.keepOffset) { - const index = Math.abs(dataSource.length - lastLength.current); - virutal?.scrollToIndex(index); - topLoading.current = false; - } - - lastLength.current = dataSource.length; - }, [dataSource]); - - useCombine(combinedStates, () => { - VirtualAttrs.forEach((key) => { - virutal?.option(key, props[key]); - }); - }); - - return [virutal]; -} - -export default useVirtual; diff --git a/src/index.tsx b/src/index.tsx index 501109d..3d5c3e8 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,31 +1,54 @@ -import React from 'react'; +import * as React from 'react'; +import useCombine from './hooks/useCombine'; import useChildren from './hooks/useChildren'; -import useSortable from './hooks/useSortable'; -import useVirtual from './hooks/useVirtual'; import { VirtualComponentRef, VirtualProps } from './interface'; -import { Virtual, Sortable, Range, getDataKey } from './core'; +import { Range, DropEvent, ScrollEvent, SortableEvent } from './core'; +import { Virtual, Sortable, debounce, getDataKey, VirtualAttrs, SortableAttrs } from './core'; const Emits = { drag: 'onDrag', drop: 'onDrop', + top: 'onTop', + bottom: 'onBottom', }; function VirtualList(props: VirtualProps, ref: React.ref) { const { - keeps = 30, dataKey = '', - sortable = true, - scroller = undefined, - direction = 'vertical', dataSource = [], + tableMode = false, + + wrapTag = 'div', + rootTag = 'div', style = {}, className = '', wrapStyle = {}, wrapClass = '', itemClass = 'virutal-dnd-list-item', - wrapTag: Wrapper = 'div', - rootTag: Rooter = 'div', + + size = undefined, + keeps = 30, + scroller = undefined, + direction = 'vertical', + debounceTime = 0, + throttleTime = 0, + + delay = 0, + group = '', + handle = '', + lockAxis = undefined, + disabled = false, + sortable = true, + draggable = '.virutal-dnd-list-item', + animation = 150, + autoScroll = true, + ghostClass = '', + ghostStyle = undefined, + chosenClass = '', + fallbackOnBody = false, + scrollThreshold = 55, + delayOnTouchOnly = false, } = props; const [range, setRange] = React.useState({ @@ -41,13 +64,6 @@ function VirtualList(props: VirtualProps, ref: React.ref) { const rootRef = React.useRef(null); const wrapRef = React.useRef(null); - const { isHorizontal, itemSizeKey } = React.useMemo(() => { - const isHorizontal = direction !== 'vertical'; - const itemSizeKey = isHorizontal ? 'offsetWidth' : 'offsetHeight'; - - return { isHorizontal, itemSizeKey }; - }, [direction]); - /** * git item size by data-key */ @@ -126,23 +142,46 @@ function VirtualList(props: VirtualProps, ref: React.ref) { scrollToBottom, })); - const list = React.useRef([]); React.useEffect(() => { - updateUniqueKeys(); - updateRange(list.current, dataSource); + installVirtual(); + installSortable(); - list.current = dataSource; + return () => { + virtualRef.current?.removeScrollEventListener(); + sortableRef.current?.destroy(); + }; + }, []); - sortableRef.current?.option('list', dataSource); - }, [dataSource]); - - const updateUniqueKeys = () => { - uniqueKeys.current = dataSource.map((item) => getDataKey(item, dataKey)); - virtualRef.current?.option('uniqueKeys', uniqueKeys.current); - sortableRef.current?.option('uniqueKeys', uniqueKeys.current); + // ========================================== use virtual ========================================== + const topLoading = React.useRef(false); + const virtualRef = React.useRef(undefined); + const virtualCombinedStates = { + size, + keeps, + scroller, + direction, + debounceTime, + throttleTime, + }; + const handleToTop = debounce(() => { + topLoading.current = true; + props[Emits.top]?.(); + }, 50); + + const handleToBottom = debounce(() => { + props[Emits.bottom]?.(); + }, 50); + + const onScroll = (event: ScrollEvent) => { + topLoading.current = false; + if (event.top) { + handleToTop(); + } else if (event.bottom) { + handleToBottom(); + } }; - const onUpdate = (range) => { + const onUpdate = (range: Range) => { setRange((current: Range) => { if (dragging.current && range.start !== current.start) { sortableRef.current.reRendered = true; @@ -151,11 +190,61 @@ function VirtualList(props: VirtualProps, ref: React.ref) { }); }; - const virtualRef = React.useRef(undefined); - const [virtual] = useVirtual(props, rootRef, wrapRef, uniqueKeys.current, onUpdate); - virtualRef.current = virtual; + const installVirtual = () => { + virtualRef.current = new Virtual({ + ...virtualCombinedStates, + buffer: Math.round(keeps / 3), + wrapper: wrapRef.current, + scroller: scroller || rootRef.current, + uniqueKeys: uniqueKeys.current, + onScroll: onScroll, + onUpdate: onUpdate, + }); + }; + + useCombine(virtualCombinedStates, () => { + VirtualAttrs.forEach((key) => { + if (props[key] !== undefined) { + virtualRef.current?.option(key, props[key]); + } + }); + }); + + const lastLength = React.useRef(null); + React.useEffect(() => { + // if auto scroll to the last offset + if (lastLength.current && topLoading.current && props.keepOffset) { + const index = Math.abs(dataSource.length - lastLength.current); + if (index > 0) { + virtualRef.current?.scrollToIndex(index); + } + topLoading.current = false; + } + + lastLength.current = dataSource.length; + }, [dataSource]); + + // ========================================== use dnd ========================================== + const sortableRef = React.useRef(undefined); + const sortableCombinedStates = { + delay, + group, + handle, + lockAxis, + disabled, + sortable, + draggable, + animation, + autoScroll, + ghostClass, + ghostStyle, + chosenClass, + fallbackOnBody, + scrollThreshold, + delayOnTouchOnly, + }; - const onDrag = (event) => { + const onDrag = (event: SortableEvent) => { dragging.current = event.key; if (!sortable) { virtualRef.current.enableScroll(false); @@ -164,17 +253,49 @@ function VirtualList(props: VirtualProps, ref: React.ref) { props[Emits.drag]?.(event); }; - const onDrop = (event) => { + const onDrop = (event: DropEvent) => { dragging.current = ''; virtualRef.current.enableScroll(true); sortableRef.current.option('autoScroll', props.autoScroll); - props[Emits.drop]?.({ ...event, list: [...event.list] }); + const params = { ...event, list: [...event.list] }; + props[Emits.drop]?.(params); }; - const sortableRef = React.useRef(undefined); - const [dnd] = useSortable(dataSource, props, wrapRef, uniqueKeys.current, onDrag, onDrop); - sortableRef.current = dnd; + const installSortable = () => { + sortableRef.current = new Sortable(rootRef.current, { + ...sortableCombinedStates, + list: dataSource, + uniqueKeys: uniqueKeys.current, + onDrag, + onDrop, + }); + }; + + useCombine(sortableCombinedStates, () => { + SortableAttrs.forEach((key) => { + if (props[key] !== undefined) { + sortableRef.current?.option(key, props[key]); + } + }); + }); + + // ========================================== layout ========================================== + const list = React.useRef([]); + React.useEffect(() => { + updateUniqueKeys(); + updateRange(list.current, dataSource); + + list.current = dataSource; + + sortableRef.current?.option('list', dataSource); + }, [dataSource]); + + const updateUniqueKeys = () => { + uniqueKeys.current = dataSource.map((item) => getDataKey(item, dataKey)); + virtualRef.current?.option('uniqueKeys', uniqueKeys.current); + sortableRef.current?.option('uniqueKeys', uniqueKeys.current); + }; const updateRange = (oldlist: T[], newlist: T[]) => { let _range: Range = { ...range }; @@ -197,16 +318,41 @@ function VirtualList(props: VirtualProps, ref: React.ref) { return offset + clientSize + 1 >= scrollSize; }; - const onItemSizeChange = (key: string | number, size: number) => { - const sizes = virtualRef.current.sizes.size; + const onSizeChange = (key: string | number, size: number) => { + const sizes = virtualRef.current?.sizes.size; const renders = Math.min(keeps, dataSource.length); - virtualRef.current.onItemResized(key, size); + virtualRef.current?.onItemResized(key, size); if (sizes === renders - 1) { updateRange(dataSource, dataSource); } }; + const { containerStyle, wrapperStyle, itemSizeKey } = React.useMemo(() => { + const { front, behind } = range; + const isHorizontal = direction !== 'vertical'; + + const overflowStyle = isHorizontal ? 'auto hidden' : 'hidden auto'; + const padding = isHorizontal ? `0px ${behind}px 0px ${front}px` : `${front}px 0px ${behind}px`; + + const containerStyle = { ...style, overflow: tableMode || scroller ? '' : overflowStyle }; + const wrapperStyle = { ...wrapStyle, padding: tableMode ? null : padding }; + const itemSizeKey = isHorizontal ? 'offsetWidth' : 'offsetHeight'; + + return { + containerStyle, + wrapperStyle, + itemSizeKey, + }; + }, [range, style, wrapStyle, scroller, tableMode, direction]); + + const [Container, Wrapper] = React.useMemo(() => { + const container = tableMode ? 'table' : wrapTag; + const wrapper = tableMode ? 'tbody' : wrapTag; + + return [container, wrapper]; + }, [rootTag, wrapTag, tableMode]); + const listChildren = useChildren({ list: dataSource, start: range.start, @@ -215,31 +361,31 @@ function VirtualList(props: VirtualProps, ref: React.ref) { sizeKey: itemSizeKey, children: props.children, dragging: dragging.current, - itemClass: itemClass, - onSizeChange: onItemSizeChange, + itemClass, + onSizeChange, }); - const rooterStyle = React.useMemo(() => { - const overflowStyle = isHorizontal ? 'auto hidden' : 'hidden auto'; - - return { ...style, overflow: scroller ? '' : overflowStyle }; - }, [style, isHorizontal, scroller]); - - const wrapperStyle = React.useMemo(() => { - const { front, behind } = range; - const padding = isHorizontal ? `0px ${behind}px 0px ${front}px` : `${front}px 0px ${behind}px`; - - return { ...wrapStyle, padding }; - }, [wrapStyle, isHorizontal, range]); + const TableSpacer = (offset: number) => { + const style = { padding: 0, border: 0, margin: 0, height: `${offset}px` }; + return ( + + + + ); + }; return ( - + {props.header} + {tableMode && TableSpacer(range.front)} + {listChildren} + + {tableMode && TableSpacer(range.behind)} {props.footer} - + ); } diff --git a/src/interface.ts b/src/interface.ts index cae0aad..8a17f9e 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -32,6 +32,7 @@ export interface VirtualProps { dataKey: string; dataSource: T[]; children: RenderFunc; + tableMode?: boolean; keeps?: number; size?: number; diff --git a/types/index.d.ts b/types/index.d.ts index 98fd916..9e3f3e0 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -28,6 +28,7 @@ interface VirtualProps { dataKey: string; dataSource: T[]; children: RenderFunc; + tableMode?: boolean; keeps?: number; size?: number; group?: Group | string;