v0.1.3 ff61cc9

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

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