@particle-academy/fancy-term 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -0
- package/dist/index.cjs +283 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +146 -2
- package/dist/index.d.ts +146 -2
- package/dist/index.js +280 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -77,6 +77,9 @@ fancy-query's `useFancyStream`.
|
|
|
77
77
|
| `activeShell` | `string` | controlled selected shell id (omit for uncontrolled) |
|
|
78
78
|
| `onShellChange` | `(id, profile) => void` | fired when the user / `setShell` switches |
|
|
79
79
|
| `showShellBar` | `boolean` | render the `<ShellSwitcher>` toolbar above the surface (default `false`) |
|
|
80
|
+
| `clipboard` | `boolean` | enable the copy chord + paste interceptor (default `true`) |
|
|
81
|
+
| `onPaste` | `(payload) => void \| boolean` | every paste; receives `{ text, files, images }` — handle pasted **images** here. Return `false` to suppress the native text paste |
|
|
82
|
+
| `contextMenu` | `false \| Item[] \| (ctx, defaults) => Item[]` | the right-click selection menu (see [Clipboard & context menu](#clipboard--context-menu)) |
|
|
80
83
|
|
|
81
84
|
The ref exposes a `TerminalHandle`:
|
|
82
85
|
|
|
@@ -85,11 +88,56 @@ const term = useRef<TerminalHandle>(null);
|
|
|
85
88
|
// term.current.write / writeln / clear / reset / fit / focus
|
|
86
89
|
// term.current.getBuffer() → the visible buffer as text (what an agent "sees")
|
|
87
90
|
// term.current.getSelection() → current selection
|
|
91
|
+
// term.current.copySelection() → copy the selection to the system clipboard (Promise<boolean>)
|
|
92
|
+
// term.current.paste(text?) → paste text (or the system clipboard) into the terminal
|
|
93
|
+
// term.current.selectAll() / clearSelection()
|
|
88
94
|
// term.current.setShell("pwsh") → switch the active shell (fires onShellChange)
|
|
89
95
|
// term.current.getShell() → the active shell id
|
|
90
96
|
// term.current.xterm → the raw xterm.js instance (escape hatch)
|
|
91
97
|
```
|
|
92
98
|
|
|
99
|
+
## Clipboard & context menu
|
|
100
|
+
|
|
101
|
+
**Copy** — select text, then **Ctrl+Shift+C** (Windows/Linux) or **Cmd+C** (macOS,
|
|
102
|
+
with a selection) copies to the system clipboard. Plain **Ctrl+C** is never
|
|
103
|
+
intercepted — it stays **SIGINT**.
|
|
104
|
+
|
|
105
|
+
**Paste** — text pastes natively. **Images** can't render in a shell, so a pasted
|
|
106
|
+
image is handed to you via `onPaste` to upload / feed an agent / write a path:
|
|
107
|
+
|
|
108
|
+
```tsx
|
|
109
|
+
<Terminal
|
|
110
|
+
output={out}
|
|
111
|
+
onData={(d) => backend.send(d)}
|
|
112
|
+
onPaste={({ text, images }) => {
|
|
113
|
+
for (const img of images) upload(img).then((url) => backend.send(url));
|
|
114
|
+
// return false here to also suppress the native text paste
|
|
115
|
+
}}
|
|
116
|
+
/>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Context menu** — right-click shows Copy / Paste / Select all / Clear by default.
|
|
120
|
+
Customize it with the `contextMenu` prop:
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
// disable it
|
|
124
|
+
<Terminal contextMenu={false} … />
|
|
125
|
+
|
|
126
|
+
// add to the defaults (the function gets the default items)
|
|
127
|
+
<Terminal
|
|
128
|
+
contextMenu={(ctx, defaults) => [
|
|
129
|
+
...defaults,
|
|
130
|
+
{ id: "sep", separator: true },
|
|
131
|
+
{ id: "send-agent", label: "Send selection to agent", icon: "🤖",
|
|
132
|
+
disabled: !ctx.hasSelection, onSelect: (c) => agent.send(c.selection) },
|
|
133
|
+
]}
|
|
134
|
+
…
|
|
135
|
+
/>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Each item is `{ id, label?, icon?, disabled?, separator?, onSelect?(ctx) }`. Set
|
|
139
|
+
`clipboard={false}` to turn off the copy chord + image-paste interception entirely.
|
|
140
|
+
|
|
93
141
|
## Switching shells
|
|
94
142
|
|
|
95
143
|
fancy-term is a **frontend wrapper** — it never spawns a shell. It owns the
|
|
@@ -220,3 +268,9 @@ mutations so every write broadcasts `AgentActivity`, and supports a staged
|
|
|
220
268
|
## License
|
|
221
269
|
|
|
222
270
|
MIT
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## ⭐ Star Fancy UI
|
|
275
|
+
|
|
276
|
+
If this package is useful to you, a quick ⭐ on the repo really helps us build a better kit. Thank you!
|
package/dist/index.cjs
CHANGED
|
@@ -52,6 +52,77 @@ function useTerminalFit(ref, fit, enabled = true) {
|
|
|
52
52
|
}, [ref, enabled]);
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
// src/clipboard.ts
|
|
56
|
+
function isImageFile(f) {
|
|
57
|
+
return typeof f.type === "string" && f.type.startsWith("image/");
|
|
58
|
+
}
|
|
59
|
+
function readDataTransfer(dt) {
|
|
60
|
+
const files = [];
|
|
61
|
+
let text = "";
|
|
62
|
+
if (dt) {
|
|
63
|
+
try {
|
|
64
|
+
text = dt.getData("text/plain") ?? "";
|
|
65
|
+
} catch {
|
|
66
|
+
}
|
|
67
|
+
const items = dt.items;
|
|
68
|
+
if (items) {
|
|
69
|
+
for (let i = 0; i < items.length; i++) {
|
|
70
|
+
const it = items[i];
|
|
71
|
+
if (it && it.kind === "file") {
|
|
72
|
+
const f = it.getAsFile();
|
|
73
|
+
if (f) files.push(f);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (files.length === 0 && dt.files) {
|
|
78
|
+
for (let i = 0; i < dt.files.length; i++) files.push(dt.files[i]);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return { text, files, images: files.filter(isImageFile) };
|
|
82
|
+
}
|
|
83
|
+
async function writeClipboardText(text) {
|
|
84
|
+
try {
|
|
85
|
+
const nav = typeof navigator !== "undefined" ? navigator : void 0;
|
|
86
|
+
if (nav?.clipboard?.writeText) {
|
|
87
|
+
await nav.clipboard.writeText(text);
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
} catch {
|
|
91
|
+
}
|
|
92
|
+
try {
|
|
93
|
+
if (typeof document === "undefined") return false;
|
|
94
|
+
const ta = document.createElement("textarea");
|
|
95
|
+
ta.value = text;
|
|
96
|
+
ta.style.position = "fixed";
|
|
97
|
+
ta.style.left = "-9999px";
|
|
98
|
+
ta.style.opacity = "0";
|
|
99
|
+
document.body.appendChild(ta);
|
|
100
|
+
ta.select();
|
|
101
|
+
const ok = document.execCommand("copy");
|
|
102
|
+
document.body.removeChild(ta);
|
|
103
|
+
return ok;
|
|
104
|
+
} catch {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
async function readClipboardText() {
|
|
109
|
+
try {
|
|
110
|
+
const nav = typeof navigator !== "undefined" ? navigator : void 0;
|
|
111
|
+
if (nav?.clipboard?.readText) return await nav.clipboard.readText();
|
|
112
|
+
} catch {
|
|
113
|
+
}
|
|
114
|
+
return "";
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// src/copy-keybinding.ts
|
|
118
|
+
function shouldCopyEvent(e, hasSelection) {
|
|
119
|
+
if (e.type !== "keydown") return false;
|
|
120
|
+
if (e.key !== "c" && e.key !== "C") return false;
|
|
121
|
+
if (e.ctrlKey && e.shiftKey && !e.metaKey) return true;
|
|
122
|
+
if (e.metaKey && !e.ctrlKey && hasSelection) return true;
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
|
|
55
126
|
// src/hooks/use-terminal.ts
|
|
56
127
|
var DEFAULT_FONT = 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace';
|
|
57
128
|
function readBuffer(term) {
|
|
@@ -94,6 +165,17 @@ function useTerminal(containerRef, options = {}) {
|
|
|
94
165
|
focus: () => xtermRef.current?.focus(),
|
|
95
166
|
getBuffer: () => readBuffer(xtermRef.current),
|
|
96
167
|
getSelection: () => xtermRef.current?.getSelection() ?? "",
|
|
168
|
+
copySelection: async () => {
|
|
169
|
+
const sel = xtermRef.current?.getSelection() ?? "";
|
|
170
|
+
if (!sel) return false;
|
|
171
|
+
return writeClipboardText(sel);
|
|
172
|
+
},
|
|
173
|
+
paste: async (text) => {
|
|
174
|
+
const data = text ?? await readClipboardText();
|
|
175
|
+
if (data) xtermRef.current?.paste(data);
|
|
176
|
+
},
|
|
177
|
+
selectAll: () => xtermRef.current?.selectAll(),
|
|
178
|
+
clearSelection: () => xtermRef.current?.clearSelection(),
|
|
97
179
|
// Shell selection is owned by the <Terminal> component layer (it needs the
|
|
98
180
|
// `shells` list + onShellChange). The headless engine is shell-agnostic, so
|
|
99
181
|
// these are no-ops here and get overridden when <Terminal> composes them.
|
|
@@ -131,9 +213,29 @@ function useTerminal(containerRef, options = {}) {
|
|
|
131
213
|
const resizeSub = term.onResize(
|
|
132
214
|
({ cols, rows }) => optsRef.current.onResize?.({ cols, rows })
|
|
133
215
|
);
|
|
216
|
+
term.attachCustomKeyEventHandler((e) => {
|
|
217
|
+
if (optsRef.current.clipboard === false) return true;
|
|
218
|
+
if (shouldCopyEvent(e, term.hasSelection())) {
|
|
219
|
+
void writeClipboardText(term.getSelection());
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
return true;
|
|
223
|
+
});
|
|
224
|
+
const onPasteEvent = (e) => {
|
|
225
|
+
const o2 = optsRef.current;
|
|
226
|
+
if (o2.clipboard === false) return;
|
|
227
|
+
if (o2.readOnly) {
|
|
228
|
+
e.preventDefault();
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
const payload = readDataTransfer(e.clipboardData);
|
|
232
|
+
if (o2.onPaste?.(payload) === false) e.preventDefault();
|
|
233
|
+
};
|
|
234
|
+
el.addEventListener("paste", onPasteEvent, true);
|
|
134
235
|
if (o.initialOutput) term.write(o.initialOutput);
|
|
135
236
|
if (o.fit ?? true) handle.fit();
|
|
136
237
|
return () => {
|
|
238
|
+
el.removeEventListener("paste", onPasteEvent, true);
|
|
137
239
|
dataSub.dispose();
|
|
138
240
|
resizeSub.dispose();
|
|
139
241
|
term.dispose();
|
|
@@ -364,6 +466,122 @@ function ShellSwitcher({
|
|
|
364
466
|
);
|
|
365
467
|
}
|
|
366
468
|
|
|
469
|
+
// src/menu-position.ts
|
|
470
|
+
function clampMenuPosition(at, menu, viewport, margin = 8) {
|
|
471
|
+
const maxX = Math.max(margin, viewport.width - menu.width - margin);
|
|
472
|
+
const maxY = Math.max(margin, viewport.height - menu.height - margin);
|
|
473
|
+
return {
|
|
474
|
+
x: Math.min(Math.max(margin, at.x), maxX),
|
|
475
|
+
y: Math.min(Math.max(margin, at.y), maxY)
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
function TerminalContextMenu({
|
|
479
|
+
at,
|
|
480
|
+
items,
|
|
481
|
+
ctx,
|
|
482
|
+
onClose
|
|
483
|
+
}) {
|
|
484
|
+
const ref = react.useRef(null);
|
|
485
|
+
const [pos, setPos] = react.useState(at);
|
|
486
|
+
react.useLayoutEffect(() => {
|
|
487
|
+
const el = ref.current;
|
|
488
|
+
if (!el || typeof window === "undefined") return;
|
|
489
|
+
const r = el.getBoundingClientRect();
|
|
490
|
+
setPos(
|
|
491
|
+
clampMenuPosition(
|
|
492
|
+
at,
|
|
493
|
+
{ width: r.width, height: r.height },
|
|
494
|
+
{ width: window.innerWidth, height: window.innerHeight }
|
|
495
|
+
)
|
|
496
|
+
);
|
|
497
|
+
}, [at]);
|
|
498
|
+
react.useEffect(() => {
|
|
499
|
+
const onDown = (e) => {
|
|
500
|
+
if (ref.current && !ref.current.contains(e.target)) onClose();
|
|
501
|
+
};
|
|
502
|
+
const onKey = (e) => {
|
|
503
|
+
if (e.key === "Escape") onClose();
|
|
504
|
+
};
|
|
505
|
+
document.addEventListener("mousedown", onDown, true);
|
|
506
|
+
document.addEventListener("keydown", onKey, true);
|
|
507
|
+
return () => {
|
|
508
|
+
document.removeEventListener("mousedown", onDown, true);
|
|
509
|
+
document.removeEventListener("keydown", onKey, true);
|
|
510
|
+
};
|
|
511
|
+
}, [onClose]);
|
|
512
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
513
|
+
"div",
|
|
514
|
+
{
|
|
515
|
+
ref,
|
|
516
|
+
"data-fancy-terminal-menu": "",
|
|
517
|
+
role: "menu",
|
|
518
|
+
style: {
|
|
519
|
+
position: "fixed",
|
|
520
|
+
left: pos.x,
|
|
521
|
+
top: pos.y,
|
|
522
|
+
zIndex: 2147483e3,
|
|
523
|
+
minWidth: 176,
|
|
524
|
+
padding: 4,
|
|
525
|
+
background: "#18181b",
|
|
526
|
+
border: "1px solid #3f3f46",
|
|
527
|
+
borderRadius: 8,
|
|
528
|
+
boxShadow: "0 10px 32px -8px rgba(0,0,0,.6)",
|
|
529
|
+
color: "#e4e4e7",
|
|
530
|
+
font: '13px/1.4 ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif',
|
|
531
|
+
userSelect: "none"
|
|
532
|
+
},
|
|
533
|
+
children: items.map(
|
|
534
|
+
(it) => it.separator ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
535
|
+
"div",
|
|
536
|
+
{
|
|
537
|
+
role: "separator",
|
|
538
|
+
style: { height: 1, margin: "4px 6px", background: "#3f3f46" }
|
|
539
|
+
},
|
|
540
|
+
it.id
|
|
541
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
542
|
+
"button",
|
|
543
|
+
{
|
|
544
|
+
type: "button",
|
|
545
|
+
role: "menuitem",
|
|
546
|
+
"data-menu-item": it.id,
|
|
547
|
+
disabled: it.disabled,
|
|
548
|
+
onClick: () => {
|
|
549
|
+
if (it.disabled) return;
|
|
550
|
+
it.onSelect?.(ctx);
|
|
551
|
+
onClose();
|
|
552
|
+
},
|
|
553
|
+
onMouseEnter: (e) => {
|
|
554
|
+
if (!it.disabled) e.currentTarget.style.background = "#27272a";
|
|
555
|
+
},
|
|
556
|
+
onMouseLeave: (e) => {
|
|
557
|
+
e.currentTarget.style.background = "transparent";
|
|
558
|
+
},
|
|
559
|
+
style: {
|
|
560
|
+
display: "flex",
|
|
561
|
+
alignItems: "center",
|
|
562
|
+
gap: 9,
|
|
563
|
+
width: "100%",
|
|
564
|
+
textAlign: "left",
|
|
565
|
+
padding: "6px 9px",
|
|
566
|
+
border: "none",
|
|
567
|
+
borderRadius: 5,
|
|
568
|
+
background: "transparent",
|
|
569
|
+
color: it.disabled ? "#52525b" : "inherit",
|
|
570
|
+
cursor: it.disabled ? "default" : "pointer",
|
|
571
|
+
font: "inherit"
|
|
572
|
+
},
|
|
573
|
+
children: [
|
|
574
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { width: 16, textAlign: "center", opacity: 0.8 }, children: it.icon ?? "" }),
|
|
575
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { flex: 1 }, children: it.label })
|
|
576
|
+
]
|
|
577
|
+
},
|
|
578
|
+
it.id
|
|
579
|
+
)
|
|
580
|
+
)
|
|
581
|
+
}
|
|
582
|
+
);
|
|
583
|
+
}
|
|
584
|
+
|
|
367
585
|
// src/output-diff.ts
|
|
368
586
|
function diffOutput(written, next) {
|
|
369
587
|
if (next === written) return null;
|
|
@@ -380,6 +598,28 @@ function decideShellSelect(shells, current, id) {
|
|
|
380
598
|
function decideShellSwitch(current, next) {
|
|
381
599
|
return { changed: current !== next };
|
|
382
600
|
}
|
|
601
|
+
|
|
602
|
+
// src/context-menu.ts
|
|
603
|
+
function defaultMenuItems(ctx, actions) {
|
|
604
|
+
const items = [
|
|
605
|
+
{ id: "copy", label: "Copy", icon: "\u29C9", disabled: !ctx.hasSelection, onSelect: actions.copy }
|
|
606
|
+
];
|
|
607
|
+
if (!ctx.readOnly) {
|
|
608
|
+
items.push({ id: "paste", label: "Paste", icon: "\u2398", onSelect: actions.paste });
|
|
609
|
+
}
|
|
610
|
+
items.push({ id: "select-all", label: "Select all", onSelect: actions.selectAll });
|
|
611
|
+
if (!ctx.readOnly) {
|
|
612
|
+
items.push({ id: "sep-default", separator: true });
|
|
613
|
+
items.push({ id: "clear", label: "Clear", onSelect: actions.clear });
|
|
614
|
+
}
|
|
615
|
+
return items;
|
|
616
|
+
}
|
|
617
|
+
function resolveMenuItems(config, ctx, actions) {
|
|
618
|
+
if (config === false) return null;
|
|
619
|
+
const defaults = defaultMenuItems(ctx, actions);
|
|
620
|
+
const items = config === void 0 || config === true ? defaults : Array.isArray(config) ? config : config(ctx, defaults);
|
|
621
|
+
return items.length > 0 ? items : null;
|
|
622
|
+
}
|
|
383
623
|
var Terminal = react.forwardRef(function Terminal2({
|
|
384
624
|
output,
|
|
385
625
|
theme,
|
|
@@ -399,6 +639,9 @@ var Terminal = react.forwardRef(function Terminal2({
|
|
|
399
639
|
activeShell,
|
|
400
640
|
onShellChange,
|
|
401
641
|
showShellBar = false,
|
|
642
|
+
clipboard,
|
|
643
|
+
onPaste,
|
|
644
|
+
contextMenu,
|
|
402
645
|
className,
|
|
403
646
|
style,
|
|
404
647
|
...rest
|
|
@@ -431,7 +674,9 @@ var Terminal = react.forwardRef(function Terminal2({
|
|
|
431
674
|
// diffing effect below owns the buffer, so don't double-write.
|
|
432
675
|
initialOutput: output === void 0 ? initialOutput : void 0,
|
|
433
676
|
onData,
|
|
434
|
-
onResize
|
|
677
|
+
onResize,
|
|
678
|
+
clipboard,
|
|
679
|
+
onPaste
|
|
435
680
|
});
|
|
436
681
|
react.useImperativeHandle(
|
|
437
682
|
ref,
|
|
@@ -451,18 +696,46 @@ var Terminal = react.forwardRef(function Terminal2({
|
|
|
451
696
|
handle.write(change.write);
|
|
452
697
|
written.current = output;
|
|
453
698
|
}, [output, handle]);
|
|
699
|
+
const [menu, setMenu] = react.useState(null);
|
|
700
|
+
const openMenu = react.useCallback(
|
|
701
|
+
(e) => {
|
|
702
|
+
if (contextMenu === false) return;
|
|
703
|
+
e.preventDefault();
|
|
704
|
+
const selection = handle.getSelection();
|
|
705
|
+
const ctx = {
|
|
706
|
+
hasSelection: selection.length > 0,
|
|
707
|
+
selection,
|
|
708
|
+
readOnly: !!readOnly
|
|
709
|
+
};
|
|
710
|
+
const items = resolveMenuItems(contextMenu, ctx, {
|
|
711
|
+
copy: () => void handle.copySelection(),
|
|
712
|
+
paste: () => void handle.paste(),
|
|
713
|
+
selectAll: () => handle.selectAll(),
|
|
714
|
+
clear: () => handle.clear()
|
|
715
|
+
});
|
|
716
|
+
if (items) setMenu({ at: { x: e.clientX, y: e.clientY }, items, ctx });
|
|
717
|
+
},
|
|
718
|
+
[contextMenu, handle, readOnly]
|
|
719
|
+
);
|
|
720
|
+
const menuNode = menu ? /* @__PURE__ */ jsxRuntime.jsx(TerminalContextMenu, { at: menu.at, items: menu.items, ctx: menu.ctx, onClose: () => setMenu(null) }) : null;
|
|
454
721
|
const surface = /* @__PURE__ */ jsxRuntime.jsx(
|
|
455
722
|
"div",
|
|
456
723
|
{
|
|
457
724
|
ref: containerRef,
|
|
458
725
|
"data-fancy-terminal": "",
|
|
726
|
+
onContextMenu: openMenu,
|
|
459
727
|
"data-readonly": readOnly ? "" : void 0,
|
|
460
728
|
"data-fancy-terminal-shell": shellId ?? void 0,
|
|
461
729
|
style: showShellBar && shells ? { width: "100%", flex: 1, minHeight: 0 } : { width: "100%", height: "100%", ...style },
|
|
462
730
|
...showShellBar && shells ? {} : rest
|
|
463
731
|
}
|
|
464
732
|
);
|
|
465
|
-
if (!showShellBar || !shells)
|
|
733
|
+
if (!showShellBar || !shells) {
|
|
734
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
735
|
+
surface,
|
|
736
|
+
menuNode
|
|
737
|
+
] });
|
|
738
|
+
}
|
|
466
739
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
467
740
|
"div",
|
|
468
741
|
{
|
|
@@ -493,7 +766,8 @@ var Terminal = react.forwardRef(function Terminal2({
|
|
|
493
766
|
)
|
|
494
767
|
}
|
|
495
768
|
),
|
|
496
|
-
surface
|
|
769
|
+
surface,
|
|
770
|
+
menuNode
|
|
497
771
|
]
|
|
498
772
|
}
|
|
499
773
|
);
|
|
@@ -545,8 +819,14 @@ function useTerminalSession(options) {
|
|
|
545
819
|
exports.BUILTIN_SHELLS = BUILTIN_SHELLS;
|
|
546
820
|
exports.ShellSwitcher = ShellSwitcher;
|
|
547
821
|
exports.Terminal = Terminal;
|
|
822
|
+
exports.TerminalContextMenu = TerminalContextMenu;
|
|
823
|
+
exports.clampMenuPosition = clampMenuPosition;
|
|
824
|
+
exports.defaultMenuItems = defaultMenuItems;
|
|
548
825
|
exports.fancyDarkTheme = fancyDarkTheme;
|
|
826
|
+
exports.isImageFile = isImageFile;
|
|
827
|
+
exports.resolveMenuItems = resolveMenuItems;
|
|
549
828
|
exports.resolveShell = resolveShell;
|
|
829
|
+
exports.shouldCopyEvent = shouldCopyEvent;
|
|
550
830
|
exports.useTerminal = useTerminal;
|
|
551
831
|
exports.useTerminalFit = useTerminalFit;
|
|
552
832
|
exports.useTerminalSession = useTerminalSession;
|