| import Sortable from "sortablejs"; | 
| import { insertNodeAt, camelize, console, removeNode } from "./util/helper"; | 
|   | 
| function buildAttribute(object, propName, value) { | 
|   if (value === undefined) { | 
|     return object; | 
|   } | 
|   object = object || {}; | 
|   object[propName] = value; | 
|   return object; | 
| } | 
|   | 
| function computeVmIndex(vnodes, element) { | 
|   return vnodes.map(elt => elt.elm).indexOf(element); | 
| } | 
|   | 
| function computeIndexes(slots, children, isTransition, footerOffset) { | 
|   if (!slots) { | 
|     return []; | 
|   } | 
|   | 
|   const elmFromNodes = slots.map(elt => elt.elm); | 
|   const footerIndex = children.length - footerOffset; | 
|   const rawIndexes = [...children].map((elt, idx) => | 
|     idx >= footerIndex ? elmFromNodes.length : elmFromNodes.indexOf(elt) | 
|   ); | 
|   return isTransition ? rawIndexes.filter(ind => ind !== -1) : rawIndexes; | 
| } | 
|   | 
| function emit(evtName, evtData) { | 
|   this.$nextTick(() => this.$emit(evtName.toLowerCase(), evtData)); | 
| } | 
|   | 
| function delegateAndEmit(evtName) { | 
|   return evtData => { | 
|     if (this.realList !== null) { | 
|       this["onDrag" + evtName](evtData); | 
|     } | 
|     emit.call(this, evtName, evtData); | 
|   }; | 
| } | 
|   | 
| function isTransitionName(name) { | 
|   return ["transition-group", "TransitionGroup"].includes(name); | 
| } | 
|   | 
| function isTransition(slots) { | 
|   if (!slots || slots.length !== 1) { | 
|     return false; | 
|   } | 
|   const [{ componentOptions }] = slots; | 
|   if (!componentOptions) { | 
|     return false; | 
|   } | 
|   return isTransitionName(componentOptions.tag); | 
| } | 
|   | 
| function getSlot(slot, scopedSlot, key) { | 
|   return slot[key] || (scopedSlot[key] ? scopedSlot[key]() : undefined); | 
| } | 
|   | 
| function computeChildrenAndOffsets(children, slot, scopedSlot) { | 
|   let headerOffset = 0; | 
|   let footerOffset = 0; | 
|   const header = getSlot(slot, scopedSlot, "header"); | 
|   if (header) { | 
|     headerOffset = header.length; | 
|     children = children ? [...header, ...children] : [...header]; | 
|   } | 
|   const footer = getSlot(slot, scopedSlot, "footer"); | 
|   if (footer) { | 
|     footerOffset = footer.length; | 
|     children = children ? [...children, ...footer] : [...footer]; | 
|   } | 
|   return { children, headerOffset, footerOffset }; | 
| } | 
|   | 
| function getComponentAttributes($attrs, componentData) { | 
|   let attributes = null; | 
|   const update = (name, value) => { | 
|     attributes = buildAttribute(attributes, name, value); | 
|   }; | 
|   const attrs = Object.keys($attrs) | 
|     .filter(key => key === "id" || key.startsWith("data-")) | 
|     .reduce((res, key) => { | 
|       res[key] = $attrs[key]; | 
|       return res; | 
|     }, {}); | 
|   update("attrs", attrs); | 
|   | 
|   if (!componentData) { | 
|     return attributes; | 
|   } | 
|   const { on, props, attrs: componentDataAttrs } = componentData; | 
|   update("on", on); | 
|   update("props", props); | 
|   Object.assign(attributes.attrs, componentDataAttrs); | 
|   return attributes; | 
| } | 
|   | 
| const eventsListened = ["Start", "Add", "Remove", "Update", "End"]; | 
| const eventsToEmit = ["Choose", "Unchoose", "Sort", "Filter", "Clone"]; | 
| const readonlyProperties = ["Move", ...eventsListened, ...eventsToEmit].map( | 
|   evt => "on" + evt | 
| ); | 
| var draggingElement = null; | 
|   | 
| const props = { | 
|   options: Object, | 
|   list: { | 
|     type: Array, | 
|     required: false, | 
|     default: null | 
|   }, | 
|   value: { | 
|     type: Array, | 
|     required: false, | 
|     default: null | 
|   }, | 
|   noTransitionOnDrag: { | 
|     type: Boolean, | 
|     default: false | 
|   }, | 
|   clone: { | 
|     type: Function, | 
|     default: original => { | 
|       return original; | 
|     } | 
|   }, | 
|   element: { | 
|     type: String, | 
|     default: "div" | 
|   }, | 
|   tag: { | 
|     type: String, | 
|     default: null | 
|   }, | 
|   move: { | 
|     type: Function, | 
|     default: null | 
|   }, | 
|   componentData: { | 
|     type: Object, | 
|     required: false, | 
|     default: null | 
|   } | 
| }; | 
|   | 
| const draggableComponent = { | 
|   name: "draggable", | 
|   | 
|   inheritAttrs: false, | 
|   | 
|   props, | 
|   | 
|   data() { | 
|     return { | 
|       transitionMode: false, | 
|       noneFunctionalComponentMode: false | 
|     }; | 
|   }, | 
|   | 
|   render(h) { | 
|     const slots = this.$slots.default; | 
|     this.transitionMode = isTransition(slots); | 
|     const { children, headerOffset, footerOffset } = computeChildrenAndOffsets( | 
|       slots, | 
|       this.$slots, | 
|       this.$scopedSlots | 
|     ); | 
|     this.headerOffset = headerOffset; | 
|     this.footerOffset = footerOffset; | 
|     const attributes = getComponentAttributes(this.$attrs, this.componentData); | 
|     return h(this.getTag(), attributes, children); | 
|   }, | 
|   | 
|   created() { | 
|     if (this.list !== null && this.value !== null) { | 
|       console.error( | 
|         "Value and list props are mutually exclusive! Please set one or another." | 
|       ); | 
|     } | 
|   | 
|     if (this.element !== "div") { | 
|       console.warn( | 
|         "Element props is deprecated please use tag props instead. See https://github.com/SortableJS/Vue.Draggable/blob/master/documentation/migrate.md#element-props" | 
|       ); | 
|     } | 
|   | 
|     if (this.options !== undefined) { | 
|       console.warn( | 
|         "Options props is deprecated, add sortable options directly as vue.draggable item, or use v-bind. See https://github.com/SortableJS/Vue.Draggable/blob/master/documentation/migrate.md#options-props" | 
|       ); | 
|     } | 
|   }, | 
|   | 
|   mounted() { | 
|     this.noneFunctionalComponentMode = | 
|       this.getTag().toLowerCase() !== this.$el.nodeName.toLowerCase() && | 
|       !this.getIsFunctional(); | 
|     if (this.noneFunctionalComponentMode && this.transitionMode) { | 
|       throw new Error( | 
|         `Transition-group inside component is not supported. Please alter tag value or remove transition-group. Current tag value: ${this.getTag()}` | 
|       ); | 
|     } | 
|     const optionsAdded = {}; | 
|     eventsListened.forEach(elt => { | 
|       optionsAdded["on" + elt] = delegateAndEmit.call(this, elt); | 
|     }); | 
|   | 
|     eventsToEmit.forEach(elt => { | 
|       optionsAdded["on" + elt] = emit.bind(this, elt); | 
|     }); | 
|   | 
|     const attributes = Object.keys(this.$attrs).reduce((res, key) => { | 
|       res[camelize(key)] = this.$attrs[key]; | 
|       return res; | 
|     }, {}); | 
|   | 
|     const options = Object.assign({}, this.options, attributes, optionsAdded, { | 
|       onMove: (evt, originalEvent) => { | 
|         return this.onDragMove(evt, originalEvent); | 
|       } | 
|     }); | 
|     !("draggable" in options) && (options.draggable = ">*"); | 
|     this._sortable = new Sortable(this.rootContainer, options); | 
|     this.computeIndexes(); | 
|   }, | 
|   | 
|   beforeDestroy() { | 
|     if (this._sortable !== undefined) this._sortable.destroy(); | 
|   }, | 
|   | 
|   computed: { | 
|     rootContainer() { | 
|       return this.transitionMode ? this.$el.children[0] : this.$el; | 
|     }, | 
|   | 
|     realList() { | 
|       return this.list ? this.list : this.value; | 
|     } | 
|   }, | 
|   | 
|   watch: { | 
|     options: { | 
|       handler(newOptionValue) { | 
|         this.updateOptions(newOptionValue); | 
|       }, | 
|       deep: true | 
|     }, | 
|   | 
|     $attrs: { | 
|       handler(newOptionValue) { | 
|         this.updateOptions(newOptionValue); | 
|       }, | 
|       deep: true | 
|     }, | 
|   | 
|     realList() { | 
|       this.computeIndexes(); | 
|     } | 
|   }, | 
|   | 
|   methods: { | 
|     getIsFunctional() { | 
|       const { fnOptions } = this._vnode; | 
|       return fnOptions && fnOptions.functional; | 
|     }, | 
|   | 
|     getTag() { | 
|       return this.tag || this.element; | 
|     }, | 
|   | 
|     updateOptions(newOptionValue) { | 
|       for (var property in newOptionValue) { | 
|         const value = camelize(property); | 
|         if (readonlyProperties.indexOf(value) === -1) { | 
|           this._sortable.option(value, newOptionValue[property]); | 
|         } | 
|       } | 
|     }, | 
|   | 
|     getChildrenNodes() { | 
|       if (this.noneFunctionalComponentMode) { | 
|         return this.$children[0].$slots.default; | 
|       } | 
|       const rawNodes = this.$slots.default; | 
|       return this.transitionMode ? rawNodes[0].child.$slots.default : rawNodes; | 
|     }, | 
|   | 
|     computeIndexes() { | 
|       this.$nextTick(() => { | 
|         this.visibleIndexes = computeIndexes( | 
|           this.getChildrenNodes(), | 
|           this.rootContainer.children, | 
|           this.transitionMode, | 
|           this.footerOffset | 
|         ); | 
|       }); | 
|     }, | 
|   | 
|     getUnderlyingVm(htmlElt) { | 
|       const index = computeVmIndex(this.getChildrenNodes() || [], htmlElt); | 
|       if (index === -1) { | 
|         //Edge case during move callback: related element might be | 
|         //an element different from collection | 
|         return null; | 
|       } | 
|       const element = this.realList[index]; | 
|       return { index, element }; | 
|     }, | 
|   | 
|     getUnderlyingPotencialDraggableComponent({ __vue__: vue }) { | 
|       if ( | 
|         !vue || | 
|         !vue.$options || | 
|         !isTransitionName(vue.$options._componentTag) | 
|       ) { | 
|         if ( | 
|           !("realList" in vue) && | 
|           vue.$children.length === 1 && | 
|           "realList" in vue.$children[0] | 
|         ) | 
|           return vue.$children[0]; | 
|   | 
|         return vue; | 
|       } | 
|       return vue.$parent; | 
|     }, | 
|   | 
|     emitChanges(evt) { | 
|       this.$nextTick(() => { | 
|         this.$emit("change", evt); | 
|       }); | 
|     }, | 
|   | 
|     alterList(onList) { | 
|       if (this.list) { | 
|         onList(this.list); | 
|         return; | 
|       } | 
|       const newList = [...this.value]; | 
|       onList(newList); | 
|       this.$emit("input", newList); | 
|     }, | 
|   | 
|     spliceList() { | 
|       const spliceList = list => list.splice(...arguments); | 
|       this.alterList(spliceList); | 
|     }, | 
|   | 
|     updatePosition(oldIndex, newIndex) { | 
|       const updatePosition = list => | 
|         list.splice(newIndex, 0, list.splice(oldIndex, 1)[0]); | 
|       this.alterList(updatePosition); | 
|     }, | 
|   | 
|     getRelatedContextFromMoveEvent({ to, related }) { | 
|       const component = this.getUnderlyingPotencialDraggableComponent(to); | 
|       if (!component) { | 
|         return { component }; | 
|       } | 
|       const list = component.realList; | 
|       const context = { list, component }; | 
|       if (to !== related && list && component.getUnderlyingVm) { | 
|         const destination = component.getUnderlyingVm(related); | 
|         if (destination) { | 
|           return Object.assign(destination, context); | 
|         } | 
|       } | 
|       return context; | 
|     }, | 
|   | 
|     getVmIndex(domIndex) { | 
|       const indexes = this.visibleIndexes; | 
|       const numberIndexes = indexes.length; | 
|       return domIndex > numberIndexes - 1 ? numberIndexes : indexes[domIndex]; | 
|     }, | 
|   | 
|     getComponent() { | 
|       return this.$slots.default[0].componentInstance; | 
|     }, | 
|   | 
|     resetTransitionData(index) { | 
|       if (!this.noTransitionOnDrag || !this.transitionMode) { | 
|         return; | 
|       } | 
|       var nodes = this.getChildrenNodes(); | 
|       nodes[index].data = null; | 
|       const transitionContainer = this.getComponent(); | 
|       transitionContainer.children = []; | 
|       transitionContainer.kept = undefined; | 
|     }, | 
|   | 
|     onDragStart(evt) { | 
|       this.context = this.getUnderlyingVm(evt.item); | 
|       evt.item._underlying_vm_ = this.clone(this.context.element); | 
|       draggingElement = evt.item; | 
|     }, | 
|   | 
|     onDragAdd(evt) { | 
|       const element = evt.item._underlying_vm_; | 
|       if (element === undefined) { | 
|         return; | 
|       } | 
|       removeNode(evt.item); | 
|       const newIndex = this.getVmIndex(evt.newIndex); | 
|       this.spliceList(newIndex, 0, element); | 
|       this.computeIndexes(); | 
|       const added = { element, newIndex }; | 
|       this.emitChanges({ added }); | 
|     }, | 
|   | 
|     onDragRemove(evt) { | 
|       insertNodeAt(this.rootContainer, evt.item, evt.oldIndex); | 
|       if (evt.pullMode === "clone") { | 
|         removeNode(evt.clone); | 
|         return; | 
|       } | 
|       const oldIndex = this.context.index; | 
|       this.spliceList(oldIndex, 1); | 
|       const removed = { element: this.context.element, oldIndex }; | 
|       this.resetTransitionData(oldIndex); | 
|       this.emitChanges({ removed }); | 
|     }, | 
|   | 
|     onDragUpdate(evt) { | 
|       removeNode(evt.item); | 
|       insertNodeAt(evt.from, evt.item, evt.oldIndex); | 
|       const oldIndex = this.context.index; | 
|       const newIndex = this.getVmIndex(evt.newIndex); | 
|       this.updatePosition(oldIndex, newIndex); | 
|       const moved = { element: this.context.element, oldIndex, newIndex }; | 
|       this.emitChanges({ moved }); | 
|     }, | 
|   | 
|     updateProperty(evt, propertyName) { | 
|       evt.hasOwnProperty(propertyName) && | 
|         (evt[propertyName] += this.headerOffset); | 
|     }, | 
|   | 
|     computeFutureIndex(relatedContext, evt) { | 
|       if (!relatedContext.element) { | 
|         return 0; | 
|       } | 
|       const domChildren = [...evt.to.children].filter( | 
|         el => el.style["display"] !== "none" | 
|       ); | 
|       const currentDOMIndex = domChildren.indexOf(evt.related); | 
|       const currentIndex = relatedContext.component.getVmIndex(currentDOMIndex); | 
|       const draggedInList = domChildren.indexOf(draggingElement) !== -1; | 
|       return draggedInList || !evt.willInsertAfter | 
|         ? currentIndex | 
|         : currentIndex + 1; | 
|     }, | 
|   | 
|     onDragMove(evt, originalEvent) { | 
|       const onMove = this.move; | 
|       if (!onMove || !this.realList) { | 
|         return true; | 
|       } | 
|   | 
|       const relatedContext = this.getRelatedContextFromMoveEvent(evt); | 
|       const draggedContext = this.context; | 
|       const futureIndex = this.computeFutureIndex(relatedContext, evt); | 
|       Object.assign(draggedContext, { futureIndex }); | 
|       const sendEvt = Object.assign({}, evt, { | 
|         relatedContext, | 
|         draggedContext | 
|       }); | 
|       return onMove(sendEvt, originalEvent); | 
|     }, | 
|   | 
|     onDragEnd() { | 
|       this.computeIndexes(); | 
|       draggingElement = null; | 
|     } | 
|   } | 
| }; | 
|   | 
| if (typeof window !== "undefined" && "Vue" in window) { | 
|   window.Vue.component("draggable", draggableComponent); | 
| } | 
|   | 
| export default draggableComponent; |