Skip to content

Commit f008cc5

Browse files
committed
add: missed a file, lol.
1 parent 6b883cd commit f008cc5

1 file changed

Lines changed: 102 additions & 0 deletions

File tree

  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/editor/extensions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { StateEffect, StateField, type Extension, RangeSet, Transaction } from '@codemirror/state';
2+
import { Decoration, EditorView, GutterMarker, gutterLineClass } from '@codemirror/view';
3+
4+
class HoveredLineGutterMarker extends GutterMarker {
5+
elementClass = 'cm-hovered-lineGutter';
6+
}
7+
8+
const hoveredGutterMarker = new HoveredLineGutterMarker();
9+
10+
const setHoveredLine = StateEffect.define<number | null>();
11+
12+
const hoveredLineField = StateField.define<number | null>({
13+
create: () => null,
14+
update: (value, tr) => {
15+
for (const e of tr.effects) if (e.is(setHoveredLine)) return e.value;
16+
if (value === null) return null;
17+
if (tr.docChanged) {
18+
return tr.changes.mapPos(value);
19+
}
20+
return value;
21+
},
22+
provide: (f) => [
23+
gutterLineClass.compute([f], (state) => {
24+
const linePos = state.field(f);
25+
if (linePos === null) return RangeSet.empty;
26+
try {
27+
return RangeSet.of([hoveredGutterMarker.range(state.doc.lineAt(linePos).from)]);
28+
} catch {
29+
return RangeSet.empty;
30+
}
31+
}),
32+
EditorView.decorations.compute([f], (state) => {
33+
const linePos = state.field(f);
34+
if (linePos === null) return Decoration.none;
35+
try {
36+
return Decoration.set([
37+
Decoration.line({ class: 'cm-hovered-line' }).range(
38+
state.doc.lineAt(linePos).from
39+
)
40+
]);
41+
} catch {
42+
return Decoration.none;
43+
}
44+
})
45+
]
46+
});
47+
48+
export function createLineHoverPlugin(): Extension {
49+
return [
50+
hoveredLineField,
51+
EditorView.domEventHandlers({
52+
mousemove(e, view) {
53+
const currentHovered = view.state.field(hoveredLineField);
54+
const pos =
55+
view.posAtCoords({ x: e.clientX, y: e.clientY }) ??
56+
(() => {
57+
const rect = view.contentDOM.getBoundingClientRect();
58+
if (e.clientY < rect.top || e.clientY > rect.bottom) {
59+
return null;
60+
}
61+
return view.posAtCoords({ x: rect.left + 2, y: e.clientY });
62+
})();
63+
64+
if (pos === null) {
65+
if (currentHovered !== null) {
66+
view.dispatch({
67+
effects: setHoveredLine.of(null),
68+
annotations: Transaction.userEvent.of('appwrite:hover')
69+
});
70+
}
71+
return false;
72+
}
73+
74+
const linePos = view.state.doc.lineAt(pos).from;
75+
if (currentHovered !== linePos) {
76+
view.dispatch({
77+
effects: setHoveredLine.of(linePos),
78+
annotations: Transaction.userEvent.of('appwrite:hover')
79+
});
80+
}
81+
return false;
82+
},
83+
mouseleave(_, view) {
84+
if (view.state.field(hoveredLineField) !== null) {
85+
view.dispatch({
86+
effects: setHoveredLine.of(null),
87+
annotations: Transaction.userEvent.of('appwrite:hover')
88+
});
89+
}
90+
return false;
91+
}
92+
}),
93+
EditorView.updateListener.of((update) => {
94+
if (!update.viewportChanged) return;
95+
if (update.state.field(hoveredLineField) === null) return;
96+
update.view.dispatch({
97+
effects: setHoveredLine.of(null),
98+
annotations: Transaction.userEvent.of('appwrite:hover')
99+
});
100+
})
101+
];
102+
}

0 commit comments

Comments
 (0)