@particle-academy/fancy-term 0.4.0 → 0.4.1
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 +5 -0
- package/dist/index.cjs +29 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -2
- package/dist/index.d.ts +28 -2
- package/dist/index.js +29 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -142,6 +142,11 @@ Customize it with the `contextMenu` prop:
|
|
|
142
142
|
Each item is `{ id, label?, icon?, disabled?, separator?, onSelect?(ctx) }`. Set
|
|
143
143
|
`clipboard={false}` to turn off the copy chord + image-paste interception entirely.
|
|
144
144
|
|
|
145
|
+
`ctx.selection` is **snapshotted before the right-click lands** and the built-in
|
|
146
|
+
Copy writes that snapshot (through the active clipboard provider) — so it still
|
|
147
|
+
copies over a mouse-reporting TUI (Claude Code, tmux, vim with mouse mode),
|
|
148
|
+
where the app's redraw clears xterm's live selection before you can click Copy.
|
|
149
|
+
|
|
145
150
|
### OSC 52 (terminal-program clipboard)
|
|
146
151
|
|
|
147
152
|
Modern TUIs — Claude Code, tmux, vim/neovim — copy their own selection with an
|
package/dist/index.cjs
CHANGED
|
@@ -769,6 +769,12 @@ function resolveMenuItems(config, ctx, actions) {
|
|
|
769
769
|
const items = config === void 0 || config === true ? defaults : Array.isArray(config) ? config : config(ctx, defaults);
|
|
770
770
|
return items.length > 0 ? items : null;
|
|
771
771
|
}
|
|
772
|
+
|
|
773
|
+
// src/selection-snapshot.ts
|
|
774
|
+
function nextSelectionSnapshot(prev, event, liveSelection) {
|
|
775
|
+
if (event.type === "mousedown" && event.button === 0) return "";
|
|
776
|
+
return liveSelection || prev;
|
|
777
|
+
}
|
|
772
778
|
var Terminal = react.forwardRef(function Terminal2({
|
|
773
779
|
output,
|
|
774
780
|
theme,
|
|
@@ -869,25 +875,42 @@ var Terminal = react.forwardRef(function Terminal2({
|
|
|
869
875
|
written.current = output;
|
|
870
876
|
}, [output, handle]);
|
|
871
877
|
const [menu, setMenu] = react.useState(null);
|
|
878
|
+
const selectionSnapshot = react.useRef("");
|
|
879
|
+
const trackSelection = react.useCallback(
|
|
880
|
+
(e) => {
|
|
881
|
+
selectionSnapshot.current = nextSelectionSnapshot(
|
|
882
|
+
selectionSnapshot.current,
|
|
883
|
+
{ type: e.type, button: e.button },
|
|
884
|
+
handle.getSelection()
|
|
885
|
+
);
|
|
886
|
+
},
|
|
887
|
+
[handle]
|
|
888
|
+
);
|
|
872
889
|
const openMenu = react.useCallback(
|
|
873
890
|
(e) => {
|
|
874
891
|
if (contextMenu === false) return;
|
|
875
892
|
e.preventDefault();
|
|
876
|
-
const selection = handle.getSelection();
|
|
893
|
+
const selection = handle.getSelection() || selectionSnapshot.current;
|
|
877
894
|
const ctx = {
|
|
878
895
|
hasSelection: selection.length > 0,
|
|
879
896
|
selection,
|
|
880
897
|
readOnly: !!readOnly
|
|
881
898
|
};
|
|
882
899
|
const items = resolveMenuItems(contextMenu, ctx, {
|
|
883
|
-
|
|
900
|
+
// Copy writes the SNAPSHOTTED selection through the active clipboard
|
|
901
|
+
// provider — never a click-time re-read, which copies "" over a TUI
|
|
902
|
+
// (falling back to the live selection only when the snapshot is empty).
|
|
903
|
+
copy: (c) => {
|
|
904
|
+
const text = c.selection || handle.getSelection();
|
|
905
|
+
if (text) void providerWrite(resolveClipboard(clipboard).provider, text);
|
|
906
|
+
},
|
|
884
907
|
paste: () => void handle.paste(),
|
|
885
908
|
selectAll: () => handle.selectAll(),
|
|
886
909
|
clear: () => handle.clear()
|
|
887
910
|
});
|
|
888
911
|
if (items) setMenu({ at: { x: e.clientX, y: e.clientY }, items, ctx });
|
|
889
912
|
},
|
|
890
|
-
[contextMenu, handle, readOnly]
|
|
913
|
+
[contextMenu, handle, readOnly, clipboard]
|
|
891
914
|
);
|
|
892
915
|
const menuNode = menu ? /* @__PURE__ */ jsxRuntime.jsx(TerminalContextMenu, { at: menu.at, items: menu.items, ctx: menu.ctx, onClose: () => setMenu(null) }) : null;
|
|
893
916
|
const surface = /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -895,6 +918,8 @@ var Terminal = react.forwardRef(function Terminal2({
|
|
|
895
918
|
{
|
|
896
919
|
ref: containerRef,
|
|
897
920
|
"data-fancy-terminal": "",
|
|
921
|
+
onMouseDownCapture: trackSelection,
|
|
922
|
+
onMouseUpCapture: trackSelection,
|
|
898
923
|
onContextMenu: openMenu,
|
|
899
924
|
"data-readonly": readOnly ? "" : void 0,
|
|
900
925
|
"data-fancy-terminal-shell": shellId ?? void 0,
|
|
@@ -1009,6 +1034,7 @@ exports.encodeBase64 = encodeBase64;
|
|
|
1009
1034
|
exports.fancyDarkTheme = fancyDarkTheme;
|
|
1010
1035
|
exports.isImageFile = isImageFile;
|
|
1011
1036
|
exports.navigatorClipboard = navigatorClipboard;
|
|
1037
|
+
exports.nextSelectionSnapshot = nextSelectionSnapshot;
|
|
1012
1038
|
exports.osc52Response = osc52Response;
|
|
1013
1039
|
exports.parseOsc52 = parseOsc52;
|
|
1014
1040
|
exports.registerOsc52 = registerOsc52;
|