v0.4.0 f6d8405

resizable.ts RawHistoryFolder

1import type { Action } from 'svelte/action';
2
3interface ResizableParameters {
4	enabled?: boolean;
5	minWidth?: number;
6	minHeight?: number;
7	maxWidth?: number;
8	maxHeight?: number;
9}
10
11interface ResizableAttributes {
12	onresizestart?: (e: CustomEvent<{ width: number; height: number }>) => void;
13	onresizemove?: (e: CustomEvent<{ width: number; height: number }>) => void;
14	onresizeend?: (e: CustomEvent<{ width: number; height: number }>) => void;
15}
16
17export const resizable: Action<HTMLElement, ResizableParameters, ResizableAttributes> = (
18	node,
19	params = {}
20) => {
21	let isResizing = false;
22	let startWidth = 0;
23	let startHeight = 0;
24	let startX = 0;
25	let startY = 0;
26
27	const {
28		enabled = true,
29		minWidth = 200,
30		minHeight = 200,
31		maxWidth = window.innerWidth,
32		maxHeight = window.innerHeight
33	} = params;
34
35	// Create and append resize handle
36	const handle = document.createElement('div');
37	handle.className = 'resize-handle';
38	Object.assign(handle.style, {
39		position: 'absolute',
40		bottom: '0',
41		right: '0',
42		width: '15px',
43		height: '15px',
44		cursor: 'se-resize',
45		zIndex: '1000'
46	});
47	node.appendChild(handle);
48
49	// Ensure parent element has position
50	if (getComputedStyle(node).position === 'static') {
51		node.style.position = 'relative';
52	}
53
54	function onMouseDown(event: MouseEvent) {
55		if (!enabled) return;
56
57		isResizing = true;
58		startX = event.clientX;
59		startY = event.clientY;
60		startWidth = node.offsetWidth;
61		startHeight = node.offsetHeight;
62
63		node.dispatchEvent(
64			new CustomEvent('resizestart', {
65				detail: { width: startWidth, height: startHeight }
66			})
67		);
68
69		event.preventDefault();
70	}
71
72	function onMouseMove(event: MouseEvent) {
73		if (!isResizing || !enabled) return;
74
75		const deltaX = event.clientX - startX;
76		const deltaY = event.clientY - startY;
77
78		const newWidth = Math.min(maxWidth, Math.max(minWidth, startWidth + deltaX));
79		const newHeight = Math.min(maxHeight, Math.max(minHeight, startHeight + deltaY));
80
81		node.style.width = `${newWidth}px`;
82		node.style.height = `${newHeight}px`;
83
84		node.dispatchEvent(
85			new CustomEvent('resizemove', {
86				detail: { width: newWidth, height: newHeight }
87			})
88		);
89	}
90
91	function onMouseUp() {
92		if (!isResizing) return;
93
94		isResizing = false;
95		node.dispatchEvent(
96			new CustomEvent('resizeend', {
97				detail: {
98					width: node.offsetWidth,
99					height: node.offsetHeight
100				}
101			})
102		);
103	}
104
105	handle.addEventListener('mousedown', onMouseDown);
106	window.addEventListener('mousemove', onMouseMove);
107	window.addEventListener('mouseup', onMouseUp);
108
109	return {
110		update(newParams: ResizableParameters) {
111			Object.assign(params, newParams);
112		},
113		destroy() {
114			handle.removeEventListener('mousedown', onMouseDown);
115			window.removeEventListener('mousemove', onMouseMove);
116			window.removeEventListener('mouseup', onMouseUp);
117			node.removeChild(handle);
118		}
119	};
120};

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 3

Tags 8

↑↓ moveenter openesc close