This repository has no description
1{{ define "fragments/resizable" }}
2 <script>
3 class ResizablePanel {
4 constructor(resizerElement) {
5 this.resizer = resizerElement;
6 this.isResizing = false;
7 this.type = resizerElement.dataset.resizer;
8 this.targetId = resizerElement.dataset.target;
9 this.target = document.getElementById(this.targetId);
10 this.min = parseInt(resizerElement.dataset.min) || 100;
11 this.max = parseInt(resizerElement.dataset.max) || Infinity;
12
13 this.direction = resizerElement.dataset.direction || 'before'; // 'before' or 'after'
14
15 this.handleMouseDown = this.handleMouseDown.bind(this);
16 this.handleMouseMove = this.handleMouseMove.bind(this);
17 this.handleMouseUp = this.handleMouseUp.bind(this);
18 this.handleDoubleClick = this.handleDoubleClick.bind(this);
19
20 this.init();
21 }
22
23 init() {
24 this.resizer.addEventListener('mousedown', this.handleMouseDown);
25 this.resizer.addEventListener('dblclick', this.handleDoubleClick);
26 }
27
28 handleMouseDown(e) {
29 e.preventDefault();
30 this.isResizing = true;
31 this.resizer.classList.add('resizing');
32 document.body.style.cursor = this.type === 'vertical' ? 'col-resize' : 'row-resize';
33 document.body.style.userSelect = 'none';
34
35 this.startX = e.clientX;
36 this.startY = e.clientY;
37 this.startWidth = this.target.offsetWidth;
38 this.startHeight = this.target.offsetHeight;
39
40 document.addEventListener('mousemove', this.handleMouseMove);
41 document.addEventListener('mouseup', this.handleMouseUp);
42 }
43
44 handleMouseMove(e) {
45 if (!this.isResizing) return;
46
47 if (this.type === 'vertical') {
48 let newWidth;
49
50 if (this.direction === 'after') {
51 const deltaX = this.startX - e.clientX;
52 newWidth = this.startWidth + deltaX;
53 } else {
54 const deltaX = e.clientX - this.startX;
55 newWidth = this.startWidth + deltaX;
56 }
57
58 if (newWidth >= this.min && newWidth <= this.max) {
59 this.target.style.width = newWidth + 'px';
60 this.target.style.flexShrink = '0';
61 }
62 } else {
63 let newHeight;
64
65 if (this.direction === 'after') {
66 const deltaY = this.startY - e.clientY;
67 newHeight = this.startHeight + deltaY;
68 } else {
69 const deltaY = e.clientY - this.startY;
70 newHeight = this.startHeight + deltaY;
71 }
72
73 if (newHeight >= this.min && newHeight <= this.max) {
74 this.target.style.height = newHeight + 'px';
75 }
76 }
77 }
78
79 handleMouseUp() {
80 if (!this.isResizing) return;
81
82 this.isResizing = false;
83 this.resizer.classList.remove('resizing');
84 document.body.style.cursor = '';
85 document.body.style.userSelect = '';
86
87 document.removeEventListener('mousemove', this.handleMouseMove);
88 document.removeEventListener('mouseup', this.handleMouseUp);
89 }
90
91 handleDoubleClick(e) {
92 e.preventDefault();
93 this.target.style.width = '';
94 this.target.style.flexShrink = '';
95 }
96
97 destroy() {
98 this.resizer.removeEventListener('mousedown', this.handleMouseDown);
99 this.resizer.removeEventListener('dblclick', this.handleDoubleClick);
100 document.removeEventListener('mousemove', this.handleMouseMove);
101 document.removeEventListener('mouseup', this.handleMouseUp);
102 }
103 }
104
105 function initializeResizers() {
106 const resizers = document.querySelectorAll('[data-resizer]');
107 const instances = [];
108
109 resizers.forEach(resizer => {
110 instances.push(new ResizablePanel(resizer));
111 });
112
113 return instances;
114 }
115
116 if (document.readyState === 'loading') {
117 document.addEventListener('DOMContentLoaded', initializeResizers);
118 } else {
119 initializeResizers();
120 }
121 </script>
122{{ end }}