import * as FormSupport from '../Form/FormSupport.es';
import Component from 'metal-jsx';
import {Config} from 'metal-state';
import {DragDrop} from 'metal-drag-drop';
import {focusedFieldStructure, pageStructure, ruleStructure} from '../../util/config.es';
const withMoveableFields = ChildComponent => {
class MoveableFields extends Component {
static PROPS = {
/**
* @default
* @instance
* @memberof FormBuilder
* @type {?number}
*/
activePage: Config.number().value(0),
/**
* @default undefined
* @instance
* @memberof FormBuilder
* @type {?string}
*/
defaultLanguageId: Config.string(),
/**
* @default undefined
* @instance
* @memberof FormBuilder
* @type {?string}
*/
editingLanguageId: Config.string(),
/**
* @default []
* @instance
* @memberof Sidebar
* @type {?(array|undefined)}
*/
fieldTypes: Config.array().value([]),
/**
* @default {}
* @instance
* @memberof FormBuilder
* @type {?object}
*/
focusedField: focusedFieldStructure.value({}),
/**
* @default []
* @instance
* @memberof FormBuilder
* @type {?array<object>}
*/
pages: Config.arrayOf(pageStructure).value([]),
/**
* @instance
* @memberof FormBuilder
* @type {string}
*/
paginationMode: Config.string().required(),
/**
* @instance
* @memberof FormBuilder
* @type {string}
*/
rules: Config.arrayOf(ruleStructure).required(),
/**
* @default undefined
* @instance
* @memberof FormRenderer
* @type {!string}
*/
spritemap: Config.string().required()
}
attached() {
this.createDragAndDrop();
}
createDragAndDrop() {
this._dragAndDrop = new DragDrop(
{
sources: '.moveable .ddm-drag',
targets: '.moveable .ddm-target',
useShim: false
}
);
this._dragAndDrop.on(
DragDrop.Events.END,
this._handleDragAndDropEnd.bind(this)
);
this._dragAndDrop.on(DragDrop.Events.DRAG, this._handleDragStarted.bind(this));
}
disposeDragAndDrop() {
if (this._dragAndDrop) {
this._dragAndDrop.dispose();
}
}
disposeInternal() {
super.disposeInternal();
this.disposeDragAndDrop();
}
isDragEnabled() {
const {defaultLanguageId, editingLanguageId} = this.props;
return defaultLanguageId === editingLanguageId;
}
render() {
return (
<div class={this.isDragEnabled() ? 'moveable' : ''}>
<ChildComponent {...this.props} />
</div>
);
}
willReceiveProps() {
this._dragAndDrop.setState(
{
targets: this._dragAndDrop.setterTargetsFn_('.moveable .ddm-target')
}
);
}
_handleDragAndDropEnd({source, target}) {
const lastParent = document.querySelector('.ddm-parent-dragging');
if (lastParent) {
lastParent.classList.remove('ddm-parent-dragging');
lastParent.removeAttribute('style');
}
if (target) {
const sourceIndex = FormSupport.getIndexes(
source.parentElement.parentElement
);
const targetIndex = FormSupport.getIndexes(target.parentElement);
source.innerHTML = '';
const addedToPlaceholder = !([].concat(target.parentElement.parentElement.classList)).includes('position-relative');
this._handleFieldMoved(
{
addedToPlaceholder,
source: sourceIndex,
target: targetIndex
}
);
}
this._refreshDragAndDrop();
}
_handleDragStarted({source}) {
const {height} = source.getBoundingClientRect();
const {parentElement} = source;
parentElement.setAttribute('style', `height: ${height}px !important;`);
parentElement.classList.add('ddm-parent-dragging');
}
_handleFieldMoved(event) {
const {store} = this.context;
store.emit('fieldMoved', event);
}
_refreshDragAndDrop() {
this.disposeDragAndDrop();
this.createDragAndDrop();
}
}
return MoveableFields;
};
export default withMoveableFields;