Updated to work with live site Added components from somewhere fixed some css background image

This commit is contained in:
Ben Parsons 2020-08-20 19:56:24 +10:00
commit a046f7c3f2
16 changed files with 885 additions and 4 deletions

View file

@ -0,0 +1,249 @@
<script>
import {quintOut} from "svelte/easing";
import {crossfade} from "svelte/transition";
import {flip} from "svelte/animate";
// FLIP ANIMATION
const [send, receive] = crossfade({
duration: d => Math.sqrt(d * 200),
fallback(node, params) {
const style = getComputedStyle(node);
const transform = style.transform === "none" ? "" : style.transform;
return {
duration: 600,
easing: quintOut,
css: t => `
transform: ${transform} scale(${t});
opacity: ${t}
`
};
}
});
// DRAG AND DROP
let isOver = false;
let isDragging = false;
const getDraggedParent = (node) => {
return node.dataset && node.dataset.index
? node.dataset
: getDraggedParent(node.parentNode)
};
const click = ev => {
dispatch("slotclick", {
source: ev.target.parentElement.dataset.index,
sourceItem: list[ev.target.parentElement.dataset.index]
});
};
const start = ev => {
isDragging = true;
ev.dataTransfer.setData("source", ev.target.dataset.index);
};
const over = ev => {
ev.preventDefault();
let dragged = getDraggedParent(ev.target);
if (isOver !== dragged.id) isOver = JSON.parse(dragged.id);
};
const leave = ev => {
let dragged = getDraggedParent(ev.target);
if (isOver === dragged.id) isOver = false;
};
const drop = ev => {
isOver = false;
ev.preventDefault();
let dragged = getDraggedParent(ev.target);
let from = ev.dataTransfer.getData("source");
let to = dragged.index;
reorder({from, to});
isDragging = false;
};
// DISPATCH REORDER
import {createEventDispatcher, onMount, afterUpdate, beforeUpdate, tick} from "svelte";
const dispatch = createEventDispatcher();
const reorder = ({from, to}) => {
let newList = [...list];
let temp = newList[from];
newList[from] = newList[to];
newList[to] = temp;
//newList[from] = [newList[to], (newList[to] = newList[from])][0];
dispatch("sort", {data: newList, from: from, to: to});
};
// UTILS
const getKey = item => (key ? item[key] : item);
// PROPS
export let list;
export let key;
export let ulclass;
export let breakon;
export let breakComponent;
// return `<><li class='${breakClass}' style='height:100%; grid-column: span 5;'><div style='width:100%;height:inherit;'></li>`;
// export let breakPosition = "beforebegin";
let breakClass = "group-break";
const Elements = () => document.getElementsByClassName(key);
const removeOldBreaks = (parent) => {
if (breakon == null) return;
if (isDragging) return;
if (parent.length) {
const old = parent[0].getElementsByClassName(breakClass);
for (let i = 0; i < old.length; i = 0) {
old[i].remove(); // removing the node from the DOM also removes it from this array (WTF??)
}
}
};
let lastCollection;
let updatingBreakPoints = false;
const updateBreak = () => {
if (isDragging || updatingBreakPoints) return;
if (breakon == null) return;
try {
updatingBreakPoints = true;
let breaks = 0;
let last = null;
let carry = 0;
let elements = Elements();
for (let x = 0; x < list.length; x++) {
if (last != null) {
if (list[x][breakon] > last) {
if (elements.length) {
let targetIndex = x + breaks;
if (list.length !== elements[0].children.length - breaks) {
if (lastCollection)
if (lastCollection.length)
targetIndex += lastCollection.length;
}
// elements[0].children[targetIndex].insertAdjacentHTML(breakPosition, breakHtml(carry + 1));
breaks++;
carry = 0;
}
} else {
carry++;
}
}
last = list[x][breakon] > last ? list[x][breakon] : last;
}
lastCollection = list;
} finally {
updatingBreakPoints = false;
}
};
//beforeUpdate(() => {updateBreak()});
let updating = false;
afterUpdate(async () => {
if (isDragging) return;
if (breakon == null) return;
updating = true;
removeOldBreaks(Elements());
await tick();
updateBreak();
updating = false;
});
const getClass = () => {
let ret = "";
if (key)
ret += ` ${key}`;
if (ulclass)
ret += ` ${ulclass}`;
return ret;
}
</script>
<style>
ul {
display: inline-grid;
list-style: none;
padding: 0;
width: 100%;
}
li {
display: inline-block;
border: 2px dotted transparent;
transition: border 0.1s linear;
width: 100%;
height: 100%;
margin: .5%;
}
.startsNewGroup {
grid-column-start: 1;
}
.small {
grid-column-end: span 1;
grid-row: span 1;
}
.medium {
grid-column-end: span 2;
grid-row: span 1;
}
.large {
grid-column-end: span 2;
/*grid-row: span 2; large buttons are double height, but they also push the row below them down (they dont fit around eachother like css-grid) */
}
.over {
border-color: rgba(48, 12, 200, 0.2);
}
</style>
{#if list && list.length}
<ul class={getClass()}>
{#each list as item, index (getKey(item))}
<li
class:small={item.displayTileSize === 2}
class:medium={item.displayTileSize === 3}
class:large={item.displayTileSize === 4}
class:startsNewGroup={item.startsNewGroup}
class:endsGroup={item.endsGroup}
data-index={index}
data-item={JSON.stringify(item)}
data-id={JSON.stringify(getKey(item))}
draggable="true"
on:dragstart={start}
on:dragover={over}
on:dragleave={leave}
on:drop={drop}
on:click={click}
in:receive={{ key: getKey(item) }}
out:send={{ key: getKey(item) }}
animate:flip={{ duration: 300 }}
class:over={getKey(item) === isOver}>
<slot {item} {index}>
<p>{getKey(item)}</p>
</slot>
</li>
{/each}
</ul>
{/if}