resig.js
Version:
Universal reactive signal library with complete platform features: signals, animations, CRDTs, scheduling, DOM integration. Works identically across React, SolidJS, Svelte, Vue, and Qwik.
328 lines (323 loc) • 25.7 kB
JavaScript
/**
* Drag-n-Drop Reorder System
* Uses Block.plug() with operad patterns for compositional drag-drop
*/
import { signal } from '../core/signal';
import { block } from '../blocks';
// Drag container using operad composition
export class DragContainer {
constructor(container, initialItems = [], config) {
this.config = config;
this.items = signal(initialItems);
this.dragState = signal({
isDragging: false,
draggedItem: null,
draggedIndex: -1,
targetIndex: -1,
offset: { x: 0, y: 0 },
});
this.operations = signal([]);
this.containerElement = container;
this.blocks = new Map();
this.setupContainer();
this.bindEvents();
this.render();
}
// Operad composition: plug draggable behavior into blocks
createDraggableBlock(item, index) {
const itemBlock = block('item', 0, (parent, _props, _children) => {
const element = document.createElement('div');
element.innerHTML = this.config.itemRenderer(item, index);
parent.appendChild(element);
return element;
});
// Plug drag behavior into item block using operad composition
const draggableBlock = this.plugDragBehavior(itemBlock, item, index);
return draggableBlock;
}
// Block.plug() implementation for drag behavior
plugDragBehavior(itemBlock, _item, index) {
return block('draggable-item', 0, (parent, _props, _children) => {
const wrapper = document.createElement('div');
wrapper.className = 'draggable-item';
wrapper.setAttribute('data-index', index.toString());
wrapper.setAttribute('draggable', 'true');
const isDragging = this.dragState.value().draggedIndex === index;
wrapper.style.cssText = `
cursor: grab;
transition: transform 0.2s ease;
${isDragging ? 'opacity: 0.5; transform: scale(0.95);' : ''}
`;
const content = itemBlock.render(wrapper);
wrapper.appendChild(content);
parent.appendChild(wrapper);
return wrapper;
});
}
// Setup container with drag-drop styling
setupContainer() {
this.containerElement.style.position = 'relative';
this.containerElement.style.minHeight = '50px';
this.containerElement.classList.add('drag-container');
// Add CSS for drag states
const style = document.createElement('style');
style.textContent = `
.drag-container {
user-select: none;
}
.draggable-item {
position: relative;
z-index: 1;
}
.draggable-item:hover {
cursor: grab;
}
.draggable-item.dragging {
cursor: grabbing;
z-index: 1000;
pointer-events: none;
}
.drag-placeholder {
background: rgba(0, 123, 255, 0.1);
border: 2px dashed rgba(0, 123, 255, 0.3);
border-radius: 4px;
margin: 2px 0;
min-height: 40px;
transition: all 0.2s ease;
}
.drag-ghost {
position: fixed;
pointer-events: none;
z-index: 10000;
opacity: 0.8;
transform: rotate(5deg);
box-shadow: 0 5px 15px rgba(0,0,0,0.3);
}
`;
document.head.appendChild(style);
}
// Bind drag events using operad composition
bindEvents() {
// Dragstart event
this.containerElement.addEventListener('dragstart', (e) => {
const target = e.target;
const draggableItem = target.closest('.draggable-item');
if (!draggableItem)
return;
const index = parseInt(draggableItem.dataset.index || '0');
const item = this.items.value()[index];
// Create drag ghost
this.createDragGhost(draggableItem, e);
// Update drag state
const newState = {
isDragging: true,
draggedItem: item,
draggedIndex: index,
targetIndex: index,
offset: {
x: e.clientX - draggableItem.getBoundingClientRect().left,
y: e.clientY - draggableItem.getBoundingClientRect().top,
},
};
draggableItem.classList.add('dragging');
this.dragState._set(newState);
});
// Dragover event for drop zones
this.containerElement.addEventListener('dragover', (e) => {
e.preventDefault();
const currentState = this.dragState.value();
if (!currentState.isDragging)
return currentState;
const targetIndex = this.getDropIndex(e.clientY);
return {
...currentState,
targetIndex,
};
});
// Drop event
this.containerElement.addEventListener('drop', (e) => {
e.preventDefault();
const currentState = this.dragState.value();
if (!currentState.isDragging || !currentState.draggedItem) {
this.resetDragState();
return;
}
// Create drag operation
const operation = {
source: currentState.draggedIndex,
target: currentState.targetIndex,
item: currentState.draggedItem,
timestamp: Date.now(),
};
// Apply reorder using operad composition
this.applyReorder(operation);
// Clean up
this.removeDragGhost();
document.querySelectorAll('.draggable-item').forEach((el) => {
el.classList.remove('dragging');
});
this.resetDragState();
});
// Dragend event
this.containerElement.addEventListener('dragend', () => {
this.removeDragGhost();
document.querySelectorAll('.draggable-item').forEach((el) => {
el.classList.remove('dragging');
});
this.resetDragState();
});
}
// Create visual drag ghost
createDragGhost(element, e) {
const ghost = element.cloneNode(true);
ghost.classList.add('drag-ghost');
ghost.style.width = element.offsetWidth + 'px';
ghost.style.left = e.clientX - this.dragState.value().offset.x + 'px';
ghost.style.top = e.clientY - this.dragState.value().offset.y + 'px';
document.body.appendChild(ghost);
// Update ghost position on mouse move
const updateGhost = (e) => {
ghost.style.left = e.clientX - this.dragState.value().offset.x + 'px';
ghost.style.top = e.clientY - this.dragState.value().offset.y + 'px';
};
document.addEventListener('dragover', updateGhost);
// Store cleanup function
ghost._cleanup = () => {
document.removeEventListener('dragover', updateGhost);
};
}
// Remove drag ghost
removeDragGhost() {
const ghost = document.querySelector('.drag-ghost');
if (ghost) {
ghost._cleanup?.();
ghost.remove();
}
}
// Calculate drop index based on mouse position
getDropIndex(clientY) {
const items = this.containerElement.querySelectorAll('.draggable-item');
const tolerance = this.config.tolerance || 5;
for (let i = 0; i < items.length; i++) {
const item = items[i];
const rect = item.getBoundingClientRect();
const midpoint = rect.top + rect.height / 2;
if (clientY < midpoint + tolerance) {
return i;
}
}
return items.length;
}
// Apply reorder using operad composition
applyReorder(operation) {
const currentItems = this.items.value();
const newItems = [...currentItems];
// Remove item from source position
const [movedItem] = newItems.splice(operation.source, 1);
// Insert at target position
const insertIndex = operation.target > operation.source
? operation.target - 1
: operation.target;
newItems.splice(insertIndex, 0, movedItem);
// Update items signal
this.items._set(newItems);
// Record operation
this.operations._set([...this.operations.value(), operation]);
// Notify callback
this.config.onReorder?.(newItems, operation);
// Re-render
this.render();
}
// Reset drag state
resetDragState() {
return {
isDragging: false,
draggedItem: null,
draggedIndex: -1,
targetIndex: -1,
offset: { x: 0, y: 0 },
};
}
// Render items using block composition
render() {
const items = this.items.value();
this.blocks.clear();
// Create blocks for each item using operad composition
const itemBlocks = items.map((item, index) => {
const block = this.createDraggableBlock(item, index);
this.blocks.set(index, block);
return block.render(document.createElement('div'));
});
// Render placeholder if dragging
const dragState = this.dragState.value();
if (dragState.isDragging &&
dragState.targetIndex !== dragState.draggedIndex) {
const placeholder = document.createElement('div');
placeholder.className = 'drag-placeholder';
placeholder.innerHTML = '<div class="drag-placeholder"></div>';
itemBlocks.splice(dragState.targetIndex, 0, placeholder);
}
// Clear container and append all blocks
this.containerElement.innerHTML = '';
itemBlocks.forEach((block) => {
if (typeof block === 'string') {
this.containerElement.innerHTML += block;
}
else {
this.containerElement.appendChild(block);
}
});
}
// Public API
getItems() {
return this.items.value();
}
setItems(items) {
this.items._set(items);
this.render();
}
addItem(item, index) {
const currentItems = this.items.value();
const newItems = [...currentItems];
if (index !== undefined) {
newItems.splice(index, 0, item);
}
else {
newItems.push(item);
}
this.items._set(newItems);
this.render();
}
removeItem(index) {
const currentItems = this.items.value();
const newItems = currentItems.filter((_, i) => i !== index);
this.items._set(newItems);
this.render();
}
getOperations() {
return this.operations.value();
}
clearOperations() {
this.operations._set([]);
}
}
// Factory function for creating drag containers
export const createDragContainer = (container, items, config) => {
return new DragContainer(container, items, config);
};
// Operad composition utilities
export const composeDragBehaviors = (behaviors) => {
return (item, index) => {
return behaviors.reduce((acc, behavior) => {
const behaviorBlock = behavior(item, index);
return block('composed', 0, (parent, _props, _children) => {
const accElement = acc.render(parent);
const behaviorElement = behaviorBlock.render(parent);
parent.appendChild(accElement);
parent.appendChild(behaviorElement);
return parent;
});
}, block('empty', 0, (parent, _props, _children) => parent));
};
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJhZy1kcm9wLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2V4dGVuc2lvbnMvZHJhZy1kcm9wLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUVILE9BQU8sRUFBVSxNQUFNLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNoRCxPQUFPLEVBQVMsS0FBSyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBZ0N6QywwQ0FBMEM7QUFDMUMsTUFBTSxPQUFPLGFBQWE7SUFPeEIsWUFDRSxTQUFzQixFQUN0QixlQUFvQixFQUFFLEVBQ2QsTUFLUDtRQUxPLFdBQU0sR0FBTixNQUFNLENBS2I7UUFFRCxJQUFJLENBQUMsS0FBSyxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNsQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sQ0FBQztZQUN0QixVQUFVLEVBQUUsS0FBSztZQUNqQixXQUFXLEVBQUUsSUFBSTtZQUNqQixZQUFZLEVBQUUsQ0FBQyxDQUFDO1lBQ2hCLFdBQVcsRUFBRSxDQUFDLENBQUM7WUFDZixNQUFNLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUU7U0FDdkIsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLFVBQVUsR0FBRyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDN0IsSUFBSSxDQUFDLGdCQUFnQixHQUFHLFNBQVMsQ0FBQztRQUNsQyxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksR0FBRyxFQUFFLENBQUM7UUFFeEIsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3RCLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUNsQixJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7SUFDaEIsQ0FBQztJQUVELDBEQUEwRDtJQUNsRCxvQkFBb0IsQ0FBQyxJQUFPLEVBQUUsS0FBYTtRQUNqRCxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsTUFBTSxF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