@tomino/dynamic-form-semantic-ui
Version:
Semantic UI form renderer based on dynamic form generation
289 lines (283 loc) • 9.58 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const common_1 = require("../common");
const dropZone = `
opacity: 0.3;
min-width: 100px;
display: block;
position: absolute;
overflow: hidden;
white-space: nowrap;
text-wrap: ellipsis;
font-size: 10px;
`;
const horizontalDropZone = `
${dropZone}
display: flex !important;
align-items: center !important;
height: 100%;
top: 0px;
`;
const placeholder = (size, dropStyle) => common_1.css `
transition: margin 0.2s cubic-bezier(0.215, 0.61, 0.355, 1) !important;
position: relative;
/* padding-top: 5px; */
/* padding-bottom: 5px; */
&.onMiddle {
outline: dashed 2px #ccc;
}
&.onBottom {
margin-bottom: ${size}px !important;
::after {
${dropZone}
${dropStyle}
content: attr(data-after);
bottom: -${size - (size - 20) / 2}px;
}
}
&.onTop {
margin-top: ${size}px !important;
::before {
${dropZone}
${dropStyle}
content: attr(data-before);
top: -${size - (size - 20) / 2}px;
}
}
&.onRight {
margin-right: 110px !important;
::after {
${horizontalDropZone}
${dropStyle}
content: attr(data-after);
right: -105px;
}
}
&.onLeft {
margin-left: 110px !important;
::before {
${horizontalDropZone}
${dropStyle}
content: attr(data-before);
left: -105px;
}
}
label: placeholder;
`;
function findVerticalIndex(e, rects, i) {
return (rects[i].getBoundingClientRect().top + window.scrollY < e.pageY &&
(!rects[i + 1] || rects[i + 1].getBoundingClientRect().top + window.scrollY > e.pageY));
}
function findHorizontalIndex(e, rects, i) {
let rect = rects[i].getBoundingClientRect();
return (rect.top + window.scrollY < e.pageY &&
rect.top + rect.height + window.scrollY > e.pageY &&
rect.left + window.scrollX < e.pageX &&
(!rects[i + 1] ||
rect.left + rect.width + window.scrollX > e.pageX ||
rects[i + 1].getBoundingClientRect().left + window.scrollX > e.pageX));
}
function findVerticalPosition(e, rect, previousEnd) {
let offset = 8;
return rect.bottom + window.scrollY < e.pageY
? 'bottom'
: previousEnd + window.scrollY + offset > e.pageY
? 'top'
: 'middle';
}
function findHorizontalPosition(e, rect) {
let offset = rect.width > 100 ? 20 : rect.width / 2;
return rect.left + window.scrollX + offset > e.pageX
? 'top'
: rect.left + window.scrollX + rect.width - offset < e.pageX
? 'bottom'
: 'middle';
}
let config = {};
function clear(id) {
for (let el of config[id].active) {
el.classList.remove('onBottom', 'onTop', 'onLeft', 'onRight', 'onMiddle');
}
config[id].active = [];
}
function cleanup(id, context, e, endDragHandler) {
config[id].currentStacks = [];
for (let pad of config[id].padMap) {
pad.style.paddingBottom = null;
pad.style.paddingTop = null;
}
config[id].padMap = [];
if (endDragHandler) {
endDragHandler(e);
}
if (context) {
context.dragItem = null;
}
}
function clearAll(context) {
for (let key of Object.keys(config)) {
clear(key);
cleanup(key, context);
}
}
exports.clearAll = clearAll;
class DragDrop {
constructor(layout, owner, processor, dropStyle, uid = 'global', dropHandler, endDragHandler, allowParenting, height = 40, context = null) {
this.add = true;
this.initialised = false;
this.init = (container) => {
let items = this.processor.children(this.owner);
let nodes = Array.from(container.childNodes);
let id = this.processor.id(this.owner);
container.setAttribute('data-drag', id);
for (let i = 0; i < items.length; i++) {
let element = nodes[i];
let item = items[i];
if (!item || !element) {
continue;
}
let id = this.processor.id(item);
element.setAttribute('data-drag', id);
if (!element.classList.contains(this.placeholderClass)) {
element.classList.add(this.placeholderClass);
}
let name = this.processor.name(item);
element.setAttribute('data-after', '🔰 After ' + name);
element.setAttribute('data-before', '🔰 Before ' + name);
}
};
this.onDragOver = (e) => {
e.preventDefault();
if (this.processor.disableDrop && this.processor.disableDrop(this.owner, this.context)) {
return;
}
if (this.config.padMap.indexOf(e.currentTarget) === -1) {
e.currentTarget.style[this.paddingElement] = '5px';
this.config.padMap.push(e.currentTarget);
}
if (!this.initialised) {
this.init(e.currentTarget);
this.initialised = true;
}
let id = e.currentTarget.getAttribute('data-drag');
if (this.add) {
this.config.currentStacks.push(id);
this.add = false;
}
let elements = (e.currentTarget.childNodes || []);
if (!elements || elements.length === 0) {
return;
}
const currentIndex = this.config.currentStacks.findIndex(s => s === id);
if (currentIndex != 0) {
return;
}
const index = this.findRect(e, elements);
if (index === -1) {
return;
}
let element = elements[index];
if (!element || element.getAttribute('data-no-drop')) {
return;
}
let previous = element.previousSibling;
let next = element.nextSibling;
let previousEnd = (previous
? previous.getBoundingClientRect().bottom
: element.parentElement.getBoundingClientRect().top) + window.scrollY;
let nextStart = (next
? next.getBoundingClientRect().top
: element.parentElement.getBoundingClientRect().bottom) + window.scrollY;
let pos = this.findPosition(e, element.getBoundingClientRect(), previousEnd, nextStart);
let className;
if (index === 0 && pos === 'top') {
className = this.startClass;
}
else if (pos === 'bottom') {
className = this.endClass;
}
else if (index > 0 && pos === 'top') {
className = this.endClass;
element = element.previousSibling;
}
else if (this.allowParenting && pos === 'middle') {
className = 'onMiddle';
}
if (element.classList.contains(className)) {
return;
}
this.config.drops = { index, position: pos };
this.clear();
element.classList.add(className);
this.config.active.push(element);
};
this.onDragEnd = (e) => {
this.dragEnd(e);
};
this.onDragLeave = () => {
this.config.currentStacks = [];
this.add = true;
};
this.onDrop = (e) => {
let id = e.currentTarget.getAttribute('data-drag');
let currentIndex = this.config.currentStacks.findIndex(s => s === id);
if (currentIndex === 0) {
if (this.dropHandler) {
this.initialised = false;
this.dropHandler(this.config.drops.index + (this.config.drops.position === 'bottom' ? 1 : 0), this.config.drops.position);
}
this.dragEnd(e);
}
};
this.startClass = layout === 'row' ? 'onLeft' : 'onTop';
this.endClass = layout === 'row' ? 'onRight' : 'onBottom';
this.findIndex = layout === 'row' ? findHorizontalIndex : findVerticalIndex;
this.findPosition = layout === 'row' ? findHorizontalPosition : findVerticalPosition;
this.paddingElement = layout === 'row' ? 'paddingRight' : 'paddingBottom';
this.processor = processor;
this.owner = owner;
this.uid = uid;
this.dropHandler = dropHandler;
this.endDragHandler = endDragHandler;
this.context = context;
this.allowParenting = allowParenting;
this.placeholderClass = placeholder(height, dropStyle);
if (!config[this.uid]) {
config[this.uid] = {
currentStacks: [],
active: [],
drops: null,
padMap: []
};
}
}
get config() {
return config[this.uid];
}
findRect(e, elements) {
for (let i = 0; i < elements.length; i++) {
if (this.findIndex(e, elements, i)) {
return i;
}
}
return -1;
}
clear() {
clear(this.uid);
}
dragEnd(e) {
this.add = true;
this.clear();
cleanup(this.uid, this.context, e, this.endDragHandler);
}
props() {
return {
onDragOver: this.onDragOver,
onDragEnd: this.onDragEnd,
onDrop: this.onDrop,
onDragLeave: this.onDragLeave
};
}
}
exports.DragDrop = DragDrop;
//# sourceMappingURL=drag_drop.js.map