-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathCodeMenuFrame.tsx
More file actions
64 lines (60 loc) · 2.77 KB
/
Copy pathCodeMenuFrame.tsx
File metadata and controls
64 lines (60 loc) · 2.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/** Wrap a `<FileDiff>` or `<FileView>` from `@kolu/solid-pierre` with the
* kolu line-selection + right-click "Copy path[:line]" affordance. The
* `<CodeContextMenu>` portal is mounted as a sibling and triggered from
* the host div's `contextmenu` event; the `LineSelection` protocol is
* threaded into the inner viewer via the children render fn so the
* selection range stays in sync with what the menu offers. */
import type { SelectedLineRange } from "@kolu/solid-pierre";
import type { Component, JSX } from "solid-js";
import {
CodeContextMenu,
type CodeContextMenuController,
type CodeContextMenuItem,
} from "../ui/CodeContextMenu";
import { type LineSelection, useLineSelection } from "../ui/useLineSelection";
export type CodeMenuFrameProps = {
/** File path the line refs are anchored to — drives both the menu copy
* text and the line-selection effect that drops the range on file
* change. */
path: string;
/** Render the inner Pierre viewer. Pass `selection.handleSelect` to its
* `onLineSelected` prop so range updates reach the menu. */
children: (selection: LineSelection) => JSX.Element;
/** Externally-supplied initial range — seeds the line-selection
* controller so a terminal `path:line` click drives both the
* Pierre highlight AND the right-click menu's "Copy path:N" item. */
initialSelectedLines?: SelectedLineRange | null;
/** Forward selection changes to a parent (e.g. CodeTab's comments
* tray composer). Fires on every commit, including null. */
onSelectionChange?: (range: SelectedLineRange | null) => void;
/** Extra context-menu items contributed by the caller — appended
* after the built-in "Copy path" / "Copy path:N" entries. Receives
* the current selection range (null when nothing is selected). */
extraMenuItems?: (range: SelectedLineRange | null) => CodeContextMenuItem[];
};
export const CodeMenuFrame: Component<CodeMenuFrameProps> = (props) => {
let menuCtrl: CodeContextMenuController | undefined;
const selection = useLineSelection(() => props.path, {
initialRange: () => props.initialSelectedLines,
onChange: (range) => props.onSelectionChange?.(range),
extraItems: (range) => props.extraMenuItems?.(range) ?? [],
});
return (
<div
// Attach contextmenu via addEventListener so the host div doesn't
// carry interactive JSX props — the inner Pierre canvas is the
// actual interactive surface; the host is layout only.
ref={(el) => el.addEventListener("contextmenu", (e) => menuCtrl?.open(e))}
class="flex flex-col h-full w-full"
>
{props.children(selection)}
<CodeContextMenu
getItems={selection.buildItems}
ref={(c) => {
menuCtrl = c;
}}
/>
</div>
);
};
export default CodeMenuFrame;