diff options
Diffstat (limited to 'src/OverlayLayout.mjs')
-rw-r--r-- | src/OverlayLayout.mjs | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/src/OverlayLayout.mjs b/src/OverlayLayout.mjs new file mode 100644 index 0000000..c87033b --- /dev/null +++ b/src/OverlayLayout.mjs | |||
@@ -0,0 +1,80 @@ | |||
1 | import PlainDraggable from 'plain-draggable' | ||
2 | import { onRemove } from './utils' | ||
3 | |||
4 | export class OverlayLayout { | ||
5 | name = "overlay" | ||
6 | |||
7 | enterHandler = (dumbymap) => { | ||
8 | const container = dumbymap.htmlHolder | ||
9 | const moveIntoDraggable = (block) => { | ||
10 | // Create draggable block | ||
11 | const draggableBlock = document.createElement('div') | ||
12 | draggableBlock.classList.add('draggable-block') | ||
13 | |||
14 | // Add draggable part | ||
15 | const draggablePart = document.createElement('div'); | ||
16 | draggablePart.classList.add('draggable') | ||
17 | draggablePart.textContent = '☰' | ||
18 | draggablePart.title = 'Use middle-click to remove block' | ||
19 | draggablePart.onmouseup = (e) => { | ||
20 | if (e.button === 1) { | ||
21 | // Hide block with middle click | ||
22 | draggableBlock.style.display = "none"; | ||
23 | } | ||
24 | } | ||
25 | |||
26 | // Set elements | ||
27 | draggableBlock.appendChild(draggablePart) | ||
28 | draggableBlock.appendChild(block) | ||
29 | container.appendChild(draggableBlock) | ||
30 | |||
31 | // Add draggable instance | ||
32 | const draggableInstance = new PlainDraggable(draggableBlock, { | ||
33 | handle: draggablePart, | ||
34 | snap: { x: { step: 20 }, y: { step: 20 } }, | ||
35 | }) | ||
36 | |||
37 | // Reposition draggable instance when resized | ||
38 | new ResizeObserver(() => { | ||
39 | try { | ||
40 | draggableInstance.position(); | ||
41 | } catch (_) { | ||
42 | null | ||
43 | } | ||
44 | }).observe(draggableBlock); | ||
45 | |||
46 | // Callback for remove | ||
47 | onRemove(draggableBlock, () => { | ||
48 | draggableInstance.remove() | ||
49 | }) | ||
50 | |||
51 | return draggableInstance | ||
52 | } | ||
53 | |||
54 | // Create draggable blocks and set each position by previous one | ||
55 | let [x, y] = [0, 0] | ||
56 | dumbymap.blocks.map(moveIntoDraggable) | ||
57 | .forEach(draggable => { | ||
58 | draggable.left = x | ||
59 | draggable.top = y | ||
60 | const rect = draggable.element.getBoundingClientRect() | ||
61 | x += rect.width + 30 | ||
62 | if (x > window.innerWidth) { | ||
63 | y += 200 | ||
64 | x = x % window.innerWidth | ||
65 | } | ||
66 | }) | ||
67 | } | ||
68 | leaveHandler = (dumbymap) => { | ||
69 | const container = dumbymap.htmlHolder | ||
70 | const resumeFromDraggable = (block) => { | ||
71 | const draggableContainer = block.closest('.draggable-block') | ||
72 | if (!draggableContainer) return | ||
73 | container.appendChild(block) | ||
74 | block.removeAttribute('style') | ||
75 | draggableContainer.remove() | ||
76 | } | ||
77 | dumbymap.blocks.forEach(resumeFromDraggable) | ||
78 | } | ||
79 | } | ||
80 | |||