Add column editor animations and drag & drop
This commit is contained in:
@@ -11,9 +11,12 @@
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(col, i) in columns">
|
||||
<transition-group name="col-list" tag="tbody" ref="col-list">
|
||||
<tr v-for="(col, i) in columns" :key="col.id" :ref="'col' + i" :class="{dragging: col._dragging}">
|
||||
<td class="btn-group">
|
||||
<button class="btn btn-outline-secondary drag-btn" @mousedown="beginDrag(i, $event)">
|
||||
<v-icon class="fa-bars" alt="Drag" />
|
||||
</button>
|
||||
<a href="" :class="['btn', 'btn-outline-secondary', {disabled: i==0}]" @click.prevent="move(i, -1)">
|
||||
<v-icon class="fa-chevron-up" alt="Move Up" />
|
||||
</a><a href="" :class="['btn', 'btn-outline-secondary', {disabled: i == (columns.length-1)}]" @click.prevent="move(i, 1)">
|
||||
@@ -36,7 +39,7 @@
|
||||
</td>
|
||||
|
||||
<td class="text-nowrap">
|
||||
<a href="" :class="['mr-1', 'btn', 'btn-outline-secondary', {disabled: i==0}]" @click.prevent="delCol(i)">
|
||||
<a href="" :class="['mr-1', 'btn', 'btn-outline-secondary', 'delete-btn', {disabled: i==0}]" @click.prevent="delCol(i)">
|
||||
<v-icon class="fa-trash-o" alt="Delete column" />
|
||||
</a><!--
|
||||
--><a href="" class="btn btn-outline-secondary" v-if="i === columns.length - 1"
|
||||
@@ -45,7 +48,7 @@
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</transition-group>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
@@ -61,6 +64,58 @@
|
||||
@include pr(1);
|
||||
@include py(1);
|
||||
}
|
||||
|
||||
tr.dragging {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
background-color: $body-bg;
|
||||
}
|
||||
tr.dragging .drag-btn {
|
||||
// fake hover
|
||||
background-color: $secondary;
|
||||
color: color-yiq($secondary);
|
||||
}
|
||||
|
||||
.col-list-enter-active {
|
||||
transition: all .3s cubic-bezier(.2, .3, 0, 1);
|
||||
}
|
||||
|
||||
.col-list-enter {
|
||||
opacity: 0;
|
||||
transform: translateY(100%);
|
||||
}
|
||||
.col-list-leave {
|
||||
// approximate position of delete button
|
||||
clip-path: circle(calc(100% + 5em) at calc(100% - 4em) 50%);
|
||||
}
|
||||
.col-list-leave-active .delete-btn {
|
||||
animation: col-list-leave-delete-btn .3s forwards;
|
||||
}
|
||||
.col-list-leave-active {
|
||||
transition: all .3s cubic-bezier(.4, .1, .6, .9);
|
||||
}
|
||||
.col-list-leave-to {
|
||||
clip-path: circle(0 at calc(100% - 4em) 50%);
|
||||
}
|
||||
|
||||
@keyframes col-list-leave-delete-btn {
|
||||
0% {
|
||||
transition-timing-function: cubic-bezier(.2, .4, .6, .9);
|
||||
}
|
||||
50% {
|
||||
transition-timing-function: cubic-bezier(.5, 0, .8, .5);
|
||||
transform: scale(1.1);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: scale(0);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.col-list-move {
|
||||
transition: transform .3s cubic-bezier(.2, .3, 0, 1);
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
@@ -83,6 +138,7 @@ export default {
|
||||
},
|
||||
addCol() {
|
||||
this.columns.push({
|
||||
id: Math.random().toString(),
|
||||
name: '',
|
||||
type: 'string',
|
||||
title: '',
|
||||
@@ -93,6 +149,44 @@ export default {
|
||||
let next = this.columns[i+dir];
|
||||
this.$set(this.columns, i, next);
|
||||
this.$set(this.columns, i+dir, cur);
|
||||
},
|
||||
beginDrag(i, evt) {
|
||||
const column = this.columns[i];
|
||||
column._dragging = true;
|
||||
this.$set(this.columns, i, column); // notify vue
|
||||
|
||||
let currentIndex = i;
|
||||
|
||||
const dragMoveListener = e => {
|
||||
let cursorIndex = 0;
|
||||
|
||||
// find cursor index by going through the list and adding the li
|
||||
// heights (can’t use their positions because they may be animating at
|
||||
// that moment)
|
||||
let accumY = this.$refs['col-list'].$el.getBoundingClientRect().top;
|
||||
for (let i = 0; i < this.columns.length; i++) {
|
||||
if (e.clientY > accumY) {
|
||||
cursorIndex = i;
|
||||
}
|
||||
accumY += $(this.$refs['col' + i]).outerHeight(true);
|
||||
}
|
||||
|
||||
if (cursorIndex !== currentIndex) {
|
||||
this.move(currentIndex, cursorIndex - currentIndex);
|
||||
currentIndex = cursorIndex;
|
||||
}
|
||||
}
|
||||
|
||||
const dragEndListener = e => {
|
||||
column._dragging = false;
|
||||
this.$set(this.columns, currentIndex, column); // notify vue
|
||||
|
||||
$(window).off('mousemove', dragMoveListener);
|
||||
$(window).off('mouseup', dragEndListener);
|
||||
};
|
||||
|
||||
$(window).on('mousemove', dragMoveListener);
|
||||
$(window).on('mouseup', dragEndListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user