@zenbu-labs/pixel 0.2.1 → 0.2.2

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/dist/bin.js CHANGED
@@ -95,15 +95,12 @@ async function main() {
95
95
  const tty = process.env.PIXEL_TTY ?? ownTty();
96
96
  const owner = (0, instances_1.findOwner)(tty);
97
97
  const announced = owner ? (0, instances_1.announceGuest)(owner, appName(appDir(entry))) : null;
98
+ let unsupported = false;
98
99
  if (!owner && !process.env.PIXEL_EMBED) {
99
100
  if (!process.stdin.isTTY || !process.stdout.isTTY) {
100
101
  fail("tty required");
101
102
  }
102
- const check = await (0, terminal_1.checkTerminal)((0, terminal_1.detect)());
103
- if (check.graphics === "unsupported") {
104
- process.stderr.write((0, terminal_1.unsupportedGraphicsMessage)(process.stderr.isTTY === true));
105
- return 1;
106
- }
103
+ unsupported = (await (0, terminal_1.checkTerminal)((0, terminal_1.detect)())).graphics === "unsupported";
107
104
  }
108
105
  const electron = electronBinary();
109
106
  const chromiumArgs = [];
@@ -125,6 +122,10 @@ async function main() {
125
122
  const env = { ...process.env };
126
123
  delete env.ELECTRON_RUN_AS_NODE;
127
124
  env.PIXEL_TTY = tty;
125
+ if (unsupported)
126
+ env[terminal_1.UNSUPPORTED_ENV] = "1";
127
+ else
128
+ delete env[terminal_1.UNSUPPORTED_ENV];
128
129
  if (announced)
129
130
  env.PIXEL_PANE = announced.pane;
130
131
  else
package/dist/root.d.ts CHANGED
@@ -1,11 +1,13 @@
1
1
  import type { ReactNode } from "react";
2
2
  import type { EngineKeyEvent, PixelRoot, RootOptions as EngineRootOptions } from "./react";
3
3
  import type { WebViewHandle, WebViewProps } from "./webview";
4
+ import type { Terminal } from "./terminal";
4
5
  export interface RootOptions extends Omit<EngineRootOptions, "keyEventTypes" | "onKey" | "onEngineExit" | "onLayout" | "host" | "onHostClosed" | "onHandoff"> {
5
6
  name?: string;
6
7
  onKey?: (event: EngineKeyEvent) => boolean | void;
7
8
  onQuit?: (view: WebViewHandle | null) => void;
8
9
  onExit?: (code: number) => void;
10
+ onUnsupportedTerminal?: (terminal: Terminal | null) => string;
9
11
  }
10
12
  export type LoadOptions = Omit<WebViewProps, "src" | "style" | "hidden" | "autoFocus">;
11
13
  export interface Root extends Omit<PixelRoot, "render" | "flushSync" | "stop" | "retarget"> {
package/dist/root.js CHANGED
@@ -66,6 +66,12 @@ function createRoot(options = {}) {
66
66
  }
67
67
  const env = options.sessionEnv ?? process.env;
68
68
  const terminal = (0, terminal_1.detect)(env);
69
+ if (env[terminal_1.UNSUPPORTED_ENV]) {
70
+ const message = options.onUnsupportedTerminal?.(terminal) ?? "pixel: this terminal doesn't support graphics\n";
71
+ node_fs_1.default.writeSync(1, message);
72
+ electron_1.app.exit(1);
73
+ throw new Error("this terminal doesn't support graphics");
74
+ }
69
75
  const tty = options.tty ?? env.PIXEL_TTY ?? ownTty();
70
76
  const embed = env.PIXEL_EMBED ?? null;
71
77
  let owner = tty && !embed ? (0, instances_1.findOwner)(tty) : null;
@@ -1,9 +1,9 @@
1
1
  import type { Terminal } from "./terminal";
2
2
  export type GraphicsSupport = "supported" | "unsupported" | "unknown";
3
3
  export declare const SKIP_ENV = "PIXEL_SKIP_GRAPHICS_CHECK";
4
+ export declare const UNSUPPORTED_ENV = "PIXEL_UNSUPPORTED_TERMINAL";
4
5
  export declare function probeGraphics(terminal: Terminal | null): Promise<GraphicsSupport>;
5
6
  export declare function panePixels(): Promise<{
6
7
  width: number;
7
8
  height: number;
8
9
  } | null>;
9
- export declare function unsupportedGraphicsMessage(color?: boolean): string;
@@ -3,12 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.SKIP_ENV = void 0;
6
+ exports.UNSUPPORTED_ENV = exports.SKIP_ENV = void 0;
7
7
  exports.probeGraphics = probeGraphics;
8
8
  exports.panePixels = panePixels;
9
- exports.unsupportedGraphicsMessage = unsupportedGraphicsMessage;
10
9
  const node_fs_1 = __importDefault(require("node:fs"));
11
10
  exports.SKIP_ENV = "PIXEL_SKIP_GRAPHICS_CHECK";
11
+ exports.UNSUPPORTED_ENV = "PIXEL_UNSUPPORTED_TERMINAL";
12
12
  const PROBE_ID = 4207;
13
13
  const PROBE_TIMEOUT_MS = 500;
14
14
  function passthrough(seq) {
@@ -28,6 +28,14 @@ function graphicsReply(buffer) {
28
28
  return null;
29
29
  return rest.startsWith("OK");
30
30
  }
31
+ const SAVE_CURSOR = "\x1b7";
32
+ // Terminals without graphics support may print the probe's payload as plain text.
33
+ function eraseEchoedProbe() {
34
+ try {
35
+ node_fs_1.default.writeSync(1, "\x1b8\x1b[J");
36
+ }
37
+ catch { }
38
+ }
31
39
  function probeGraphics(terminal) {
32
40
  const stdin = process.stdin;
33
41
  if (!stdin.isTTY || !process.stdout.isTTY || !stdin.setRawMode) {
@@ -52,6 +60,8 @@ function probeGraphics(terminal) {
52
60
  catch { }
53
61
  if (!stdin.isPaused())
54
62
  stdin.pause();
63
+ if (graphics !== "supported")
64
+ eraseEchoedProbe();
55
65
  resolve(graphics);
56
66
  };
57
67
  const onData = (chunk) => {
@@ -72,7 +82,7 @@ function probeGraphics(terminal) {
72
82
  stdin.on("data", onData);
73
83
  timer = setTimeout(() => finish("unknown"), PROBE_TIMEOUT_MS);
74
84
  try {
75
- node_fs_1.default.writeSync(1, probeSequence(terminal?.wrapper === "tmux"));
85
+ node_fs_1.default.writeSync(1, `${SAVE_CURSOR}${probeSequence(terminal?.wrapper === "tmux")}`);
76
86
  }
77
87
  catch {
78
88
  finish("unknown");
@@ -127,16 +137,3 @@ function panePixels() {
127
137
  }
128
138
  });
129
139
  }
130
- function unsupportedGraphicsMessage(color = false) {
131
- const sgr = (code, text) => (color ? `\x1b[${code}m${text}\x1b[0m` : text);
132
- return [
133
- "",
134
- ` ${sgr("1", "Unsupported terminal: this terminal cannot display graphics")}`,
135
- "",
136
- ` ${sgr("2", "We recommend Ghostty:")}`,
137
- ` ${sgr("4", "https://ghostty.org/download")}`,
138
- "",
139
- ` ${sgr("2", "Note: any terminal that supports the kitty graphics protocol is supported")}`,
140
- "",
141
- ].join("\n");
142
- }
@@ -9,4 +9,4 @@ export { cannotOpenPanes, checkTerminal, detect } from "./detect";
9
9
  export type { GraphicsSupport } from "./graphics";
10
10
  export type { Instance } from "../instances";
11
11
  export { findOwner, listInstances, PROTOCOL as EMBED_PROTOCOL } from "../instances";
12
- export { probeGraphics, unsupportedGraphicsMessage, SKIP_ENV as GRAPHICS_SKIP_ENV } from "./graphics";
12
+ export { probeGraphics, SKIP_ENV as GRAPHICS_SKIP_ENV, UNSUPPORTED_ENV } from "./graphics";
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.GRAPHICS_SKIP_ENV = exports.unsupportedGraphicsMessage = exports.probeGraphics = exports.EMBED_PROTOCOL = exports.listInstances = exports.findOwner = exports.detect = exports.checkTerminal = exports.cannotOpenPanes = exports.shellLiteral = exports.PASTE_KEY = exports.callerTty = exports.bracketedPaste = exports.shellIn = exports.canSplit = void 0;
3
+ exports.UNSUPPORTED_ENV = exports.GRAPHICS_SKIP_ENV = exports.probeGraphics = exports.EMBED_PROTOCOL = exports.listInstances = exports.findOwner = exports.detect = exports.checkTerminal = exports.cannotOpenPanes = exports.shellLiteral = exports.PASTE_KEY = exports.callerTty = exports.bracketedPaste = exports.shellIn = exports.canSplit = void 0;
4
4
  var terminal_1 = require("./terminal");
5
5
  Object.defineProperty(exports, "canSplit", { enumerable: true, get: function () { return terminal_1.canSplit; } });
6
6
  var run_1 = require("./run");
@@ -20,5 +20,5 @@ Object.defineProperty(exports, "listInstances", { enumerable: true, get: functio
20
20
  Object.defineProperty(exports, "EMBED_PROTOCOL", { enumerable: true, get: function () { return instances_1.PROTOCOL; } });
21
21
  var graphics_1 = require("./graphics");
22
22
  Object.defineProperty(exports, "probeGraphics", { enumerable: true, get: function () { return graphics_1.probeGraphics; } });
23
- Object.defineProperty(exports, "unsupportedGraphicsMessage", { enumerable: true, get: function () { return graphics_1.unsupportedGraphicsMessage; } });
24
23
  Object.defineProperty(exports, "GRAPHICS_SKIP_ENV", { enumerable: true, get: function () { return graphics_1.SKIP_ENV; } });
24
+ Object.defineProperty(exports, "UNSUPPORTED_ENV", { enumerable: true, get: function () { return graphics_1.UNSUPPORTED_ENV; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zenbu-labs/pixel",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Build graphical applications in the terminal",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -58,10 +58,10 @@
58
58
  "react": "^18.3.1"
59
59
  },
60
60
  "optionalDependencies": {
61
- "@zenbu-labs/pixel-native-darwin-arm64": "0.2.1",
62
- "@zenbu-labs/pixel-native-darwin-x64": "0.2.1",
63
- "@zenbu-labs/pixel-native-linux-arm64": "0.2.1",
64
- "@zenbu-labs/pixel-native-linux-x64": "0.2.1"
61
+ "@zenbu-labs/pixel-native-darwin-arm64": "0.2.2",
62
+ "@zenbu-labs/pixel-native-darwin-x64": "0.2.2",
63
+ "@zenbu-labs/pixel-native-linux-arm64": "0.2.2",
64
+ "@zenbu-labs/pixel-native-linux-x64": "0.2.2"
65
65
  },
66
66
  "devDependencies": {
67
67
  "@types/node": "^22.0.0",