@zenbu-labs/pixel 0.0.23 → 0.2.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.
@@ -1,21 +1,20 @@
1
1
  import type { RefObject } from "react";
2
2
  import type { Rect } from "./devtools-layout";
3
- import type { DragEvent, PointerEvent, Style, Surface, WheelEvent } from "./react";
3
+ import type { DragEvent, PointerEvent, PointerShape, Style, Surface, WheelEvent } from "./react";
4
4
  import type { Theme } from "./theme";
5
5
  import type { DevtoolsDock } from "./web/types";
6
6
  import type { WebViewHandle } from "./webview";
7
- export declare function DevtoolsDockPane({ rect, dock, rem, theme, surface, dividerEngaged, onPointer, onWheel, onHover, onDividerDrag, onDividerHover, }: {
7
+ export declare function DevtoolsDockPane({ rect, dock, rem, theme, surface, dividerEngaged, pointerShape, onPointer, onWheel, onDividerDrag, }: {
8
8
  rect: Rect;
9
9
  dock: DevtoolsDock;
10
10
  rem: number;
11
11
  theme: Theme;
12
12
  surface: Surface;
13
13
  dividerEngaged: boolean;
14
+ pointerShape: PointerShape;
14
15
  onPointer(event: PointerEvent): void;
15
16
  onWheel(event: WheelEvent): void;
16
- onHover(hovering: boolean): void;
17
17
  onDividerDrag(event: DragEvent): void;
18
- onDividerHover(hovering: boolean): void;
19
18
  }): import("react").JSX.Element;
20
19
  export interface DevToolsProps {
21
20
  target: RefObject<WebViewHandle | null> | WebViewHandle;
package/dist/devtools.js CHANGED
@@ -10,7 +10,7 @@ const registry_1 = require("./registry");
10
10
  const types_1 = require("./web/types");
11
11
  const DIVIDER_ACTIVE = [58, 96, 168, 255];
12
12
  const DIVIDER_GRIP = [118, 122, 132, 255];
13
- function DevtoolsDockPane({ rect, dock, rem, theme, surface, dividerEngaged, onPointer, onWheel, onHover, onDividerDrag, onDividerHover, }) {
13
+ function DevtoolsDockPane({ rect, dock, rem, theme, surface, dividerEngaged, pointerShape, onPointer, onWheel, onDividerDrag, }) {
14
14
  const horizontal = dock === "bottom";
15
15
  const grab = Math.max(8, Math.round(rem * 0.5));
16
16
  const divider = horizontal
@@ -25,14 +25,16 @@ function DevtoolsDockPane({ rect, dock, rem, theme, surface, dividerEngaged, onP
25
25
  width: rect.width,
26
26
  height: rect.height,
27
27
  background: theme.bg,
28
- }, onPointer: onPointer, onWheel: onWheel, onMouseEnter: () => onHover(true), onMouseLeave: () => onHover(false) }), (0, jsx_runtime_1.jsx)(react_2.Box, { style: {
28
+ pointerShape,
29
+ }, onPointer: onPointer, onWheel: onWheel }), (0, jsx_runtime_1.jsx)(react_2.Box, { style: {
29
30
  position: "absolute",
30
31
  inset: { top: divider.y, left: divider.x },
31
32
  width: divider.width,
32
33
  height: divider.height,
33
34
  background: dividerEngaged ? [...DIVIDER_ACTIVE] : undefined,
34
35
  cornerRadius: 2,
35
- }, onDrag: onDividerDrag, onMouseEnter: () => onDividerHover(true), onMouseLeave: () => onDividerHover(false), children: [-7, 0, 7].map((offset) => ((0, jsx_runtime_1.jsx)(react_2.Box, { style: {
36
+ pointerShape: horizontal ? "ns-resize" : "ew-resize",
37
+ }, onDrag: onDividerDrag, children: [-7, 0, 7].map((offset) => ((0, jsx_runtime_1.jsx)(react_2.Box, { style: {
36
38
  position: "absolute",
37
39
  inset: gripAlong(offset),
38
40
  width: 2,
@@ -54,6 +56,7 @@ function DevTools({ target, style, dock = "right", panel, onAction, keepFrame =
54
56
  const rect = (0, layout_1.useNodeRect)(boxRef, registry);
55
57
  const surface = (0, react_1.useRef)(null);
56
58
  const opened = (0, react_1.useRef)(null);
59
+ const [pointerShape, setPointerShape] = (0, react_1.useState)("default");
57
60
  const scale = registry.displayScale;
58
61
  (0, react_1.useLayoutEffect)(() => {
59
62
  surface.current = registry.root.createSurface();
@@ -62,6 +65,7 @@ function DevTools({ target, style, dock = "right", panel, onAction, keepFrame =
62
65
  if (entry?.externalDevtools) {
63
66
  entry.externalDevtools = false;
64
67
  entry.externalDevtoolsAction = null;
68
+ entry.externalDevtoolsCursor = null;
65
69
  entry.host?.closeDevtools();
66
70
  }
67
71
  opened.current = null;
@@ -80,8 +84,14 @@ function DevTools({ target, style, dock = "right", panel, onAction, keepFrame =
80
84
  opened.current.externalDevtools = false;
81
85
  opened.current.host?.closeDevtools();
82
86
  }
87
+ if (opened.current !== entry) {
88
+ if (opened.current)
89
+ opened.current.externalDevtoolsCursor = null;
90
+ setPointerShape(host.devtools?.cursorShape ?? "default");
91
+ }
83
92
  opened.current = entry;
84
93
  entry.externalDevtoolsAction = (action) => onAction?.(action);
94
+ entry.externalDevtoolsCursor = setPointerShape;
85
95
  if (!host.devtools) {
86
96
  entry.externalDevtools = true;
87
97
  host.openDevtools(surface.current, layout, dock);
@@ -108,6 +118,7 @@ function DevTools({ target, style, dock = "right", panel, onAction, keepFrame =
108
118
  width: size.width,
109
119
  height: size.height,
110
120
  cornerRadius: style?.cornerRadius,
121
+ pointerShape,
111
122
  }, onPointer: (event) => {
112
123
  const host = entry?.host;
113
124
  if (!entry || !host?.devtools)
@@ -120,5 +131,5 @@ function DevTools({ target, style, dock = "right", panel, onAction, keepFrame =
120
131
  return;
121
132
  registry.focus(entry, "devtools");
122
133
  host.devtools.input.wheel(event);
123
- }, onMouseEnter: () => registry.setPointerShape(entry?.host?.devtools?.cursorShape ?? "default"), onMouseLeave: () => registry.setPointerShape("default") })) }));
134
+ } })) }));
124
135
  }
@@ -19,7 +19,7 @@ function GuestView({ guest, active }) {
19
19
  const boxRef = (0, react_1.useRef)(null);
20
20
  const rect = (0, layout_1.useNodeRect)(boxRef, registry);
21
21
  const surface = (0, react_1.useRef)(null);
22
- const hovered = (0, react_1.useRef)(false);
22
+ const [pointerShape, setPointerShape] = (0, react_1.useState)("default");
23
23
  const wheel = (0, react_1.useRef)({ x: 0, y: 0 });
24
24
  const greeted = (0, react_1.useRef)(false);
25
25
  const entry = (0, react_1.useMemo)(() => ({
@@ -28,6 +28,7 @@ function GuestView({ guest, active }) {
28
28
  devtoolsEnabled: false,
29
29
  externalDevtools: false,
30
30
  externalDevtoolsAction: null,
31
+ externalDevtoolsCursor: null,
31
32
  toggleDevtools: () => { },
32
33
  handleKey: (event) => {
33
34
  guest.send({ type: "key", ...event });
@@ -67,8 +68,7 @@ function GuestView({ guest, active }) {
67
68
  });
68
69
  };
69
70
  guest.onPointer = (shape) => {
70
- if (hovered.current)
71
- registry.setPointerShape(shape);
71
+ setPointerShape(shape);
72
72
  };
73
73
  guest.onClipboard = (text) => registry.root.setClipboard(text);
74
74
  return () => {
@@ -166,13 +166,9 @@ function GuestView({ guest, active }) {
166
166
  inset: { top: 0, left: 0 },
167
167
  width: snapped.width,
168
168
  height: snapped.height,
169
+ pointerShape,
169
170
  }, onPointer: (event) => {
170
171
  registry.focus(entry);
171
172
  forward(event, event.kind);
172
- }, onMouseMove: (event) => forward(event, "move"), onWheel: scroll, onMouseEnter: () => {
173
- hovered.current = true;
174
- }, onMouseLeave: () => {
175
- hovered.current = false;
176
- registry.setPointerShape("default");
177
- } })) }));
173
+ }, onMouseMove: (event) => forward(event, "move"), onWheel: scroll })) }));
178
174
  }
package/dist/index.d.ts CHANGED
@@ -13,8 +13,8 @@ export type { DevtoolsDock } from "./web/types";
13
13
  export type { ZoomDirection } from "./web/zoom";
14
14
  export type { TerminalTheme } from "./web/session";
15
15
  export { QUIT_URL, defaultOpenWindow } from "./web/host";
16
- export { Box, Text, Input, Image, MarkedText, Path, Markdown, appLog, useTerminalColors, setClipboard, setPointerShape, requestClipboardImage, highlight, diff, parseMarkdown, HIGHLIGHT_CAPTURES, Surface, SurfaceCapture, captureFilmstrip, encodeRecording, engineLogs, useStore, } from "./react";
16
+ export { Box, Text, Input, Image, MarkedText, Path, Markdown, Link, appLog, useTerminalColors, setClipboard, requestClipboardImage, highlight, diff, parseMarkdown, HIGHLIGHT_CAPTURES, Surface, SurfaceCapture, captureFilmstrip, encodeRecording, engineLogs, useStore, } from "./react";
17
17
  export type { LogRow, LogBuffer } from "./react";
18
- export type { BoxProps, TextProps, TextSpan, InputProps, InputGutter, ImageProps, ImageAdvancedProps, MarkedTextProps, MarkRef, PathProps, ShapeStroke, ClickEvent, DragEvent, EventMods, MouseMoveEvent, ScrollEvent, WheelEvent, PointerEvent, PastedImage, PasteSource, CaretInfo, ChangeInfo, ChangeSource, ContainerSelection, SelectionPart, NodeHandle, Color, Edges, InsetEdges, InsetValue, ScrollbarStyle, Style, EngineInfo, EngineKeyEvent, KeyMods, Rgba, TerminalColors, SurfaceFrame, SurfaceTexture, CaptureStats, CaptureFrameMeta, CaptureIndex, MarkdownProps, MarkdownTheme, MarkdownBlock, HighlightSpan, DiffRow, } from "./react";
18
+ export type { BoxProps, TextProps, TextSpan, InputProps, InputGutter, ImageProps, ImageAdvancedProps, MarkedTextProps, MarkRef, PathProps, ShapeStroke, ClickEvent, DragEvent, EventMods, MouseMoveEvent, ScrollEvent, WheelEvent, PointerEvent, PastedImage, PasteSource, CaretInfo, ChangeInfo, ChangeSource, ContainerSelection, SelectionPart, NodeHandle, Color, Edges, InsetEdges, InsetValue, PointerShape, ScrollbarStyle, Style, EngineInfo, EngineKeyEvent, KeyMods, Rgba, TerminalColors, SurfaceFrame, SurfaceTexture, CaptureStats, CaptureFrameMeta, CaptureIndex, MarkdownProps, MarkdownTheme, LinkProps, MarkdownBlock, HighlightSpan, DiffRow, } from "./react";
19
19
  export { makeTheme } from "./theme";
20
20
  export type { Theme } from "./theme";
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.makeTheme = exports.useStore = exports.engineLogs = exports.encodeRecording = exports.captureFilmstrip = exports.SurfaceCapture = exports.Surface = exports.HIGHLIGHT_CAPTURES = exports.parseMarkdown = exports.diff = exports.highlight = exports.requestClipboardImage = exports.setPointerShape = exports.setClipboard = exports.useTerminalColors = exports.appLog = exports.Markdown = exports.Path = exports.MarkedText = exports.Image = exports.Input = exports.Text = exports.Box = exports.defaultOpenWindow = exports.QUIT_URL = exports.useRect = exports.DevTools = exports.WebView = exports.listInstances = exports.findOwner = exports.createRoot = void 0;
3
+ exports.makeTheme = exports.useStore = exports.engineLogs = exports.encodeRecording = exports.captureFilmstrip = exports.SurfaceCapture = exports.Surface = exports.HIGHLIGHT_CAPTURES = exports.parseMarkdown = exports.diff = exports.highlight = exports.requestClipboardImage = exports.setClipboard = exports.useTerminalColors = exports.appLog = exports.Link = exports.Markdown = exports.Path = exports.MarkedText = exports.Image = exports.Input = exports.Text = exports.Box = exports.defaultOpenWindow = exports.QUIT_URL = exports.useRect = exports.DevTools = exports.WebView = exports.listInstances = exports.findOwner = exports.createRoot = void 0;
4
4
  /// <reference path="../electron/electron.d.ts" preserve="true" />
5
5
  var root_1 = require("./root");
6
6
  Object.defineProperty(exports, "createRoot", { enumerable: true, get: function () { return root_1.createRoot; } });
@@ -24,10 +24,10 @@ Object.defineProperty(exports, "Image", { enumerable: true, get: function () { r
24
24
  Object.defineProperty(exports, "MarkedText", { enumerable: true, get: function () { return react_1.MarkedText; } });
25
25
  Object.defineProperty(exports, "Path", { enumerable: true, get: function () { return react_1.Path; } });
26
26
  Object.defineProperty(exports, "Markdown", { enumerable: true, get: function () { return react_1.Markdown; } });
27
+ Object.defineProperty(exports, "Link", { enumerable: true, get: function () { return react_1.Link; } });
27
28
  Object.defineProperty(exports, "appLog", { enumerable: true, get: function () { return react_1.appLog; } });
28
29
  Object.defineProperty(exports, "useTerminalColors", { enumerable: true, get: function () { return react_1.useTerminalColors; } });
29
30
  Object.defineProperty(exports, "setClipboard", { enumerable: true, get: function () { return react_1.setClipboard; } });
30
- Object.defineProperty(exports, "setPointerShape", { enumerable: true, get: function () { return react_1.setPointerShape; } });
31
31
  Object.defineProperty(exports, "requestClipboardImage", { enumerable: true, get: function () { return react_1.requestClipboardImage; } });
32
32
  Object.defineProperty(exports, "highlight", { enumerable: true, get: function () { return react_1.highlight; } });
33
33
  Object.defineProperty(exports, "diff", { enumerable: true, get: function () { return react_1.diff; } });
package/dist/popup.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { PointerEvent, Surface, WheelEvent } from "./react";
1
+ import type { PointerEvent, PointerShape, Surface, WheelEvent } from "./react";
2
2
  import type { Theme } from "./theme";
3
3
  import type { Rect } from "./devtools-layout";
4
4
  export interface PopupView {
@@ -8,14 +8,14 @@ export interface PopupView {
8
8
  width: number;
9
9
  height: number;
10
10
  }
11
- export declare function PopupCard({ view, page, rem, theme, surface, onPointer, onWheel, onHover, onClose, }: {
11
+ export declare function PopupCard({ view, page, rem, theme, surface, pointerShape, onPointer, onWheel, onClose, }: {
12
12
  view: PopupView;
13
13
  page: Rect;
14
14
  rem: number;
15
15
  theme: Theme;
16
16
  surface: Surface;
17
+ pointerShape: PointerShape;
17
18
  onPointer(event: PointerEvent): void;
18
19
  onWheel(event: WheelEvent): void;
19
- onHover(hovering: boolean): void;
20
20
  onClose(): void;
21
21
  }): import("react").JSX.Element;
package/dist/popup.js CHANGED
@@ -5,7 +5,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const react_2 = require("./react");
7
7
  const icons_1 = require("./icons");
8
- function PopupCard({ view, page, rem, theme, surface, onPointer, onWheel, onHover, onClose, }) {
8
+ function PopupCard({ view, page, rem, theme, surface, pointerShape, onPointer, onWheel, onClose, }) {
9
9
  const [closeHover, setCloseHover] = (0, react_1.useState)(false);
10
10
  const headerH = Math.round(rem * 1.7);
11
11
  const cardH = headerH + view.height;
@@ -43,5 +43,5 @@ function PopupCard({ view, page, rem, theme, surface, onPointer, onWheel, onHove
43
43
  justifyContent: "center",
44
44
  cornerRadius: rem * 0.3,
45
45
  background: closeHover ? theme.hover : undefined,
46
- }, onClick: onClose, onMouseEnter: () => setCloseHover(true), onMouseLeave: () => setCloseHover(false), children: (0, jsx_runtime_1.jsx)(icons_1.Icon, { icon: "close", size: rem * 0.8, color: theme.muted }) })] }), (0, jsx_runtime_1.jsx)(react_2.Box, { surface: surface, style: { width: view.width, height: view.height, background: theme.bg }, onPointer: onPointer, onWheel: onWheel, onMouseEnter: () => onHover(true), onMouseLeave: () => onHover(false) })] })] }));
46
+ }, onClick: onClose, onMouseEnter: () => setCloseHover(true), onMouseLeave: () => setCloseHover(false), children: (0, jsx_runtime_1.jsx)(icons_1.Icon, { icon: "close", size: rem * 0.8, color: theme.muted }) })] }), (0, jsx_runtime_1.jsx)(react_2.Box, { surface: surface, style: { width: view.width, height: view.height, background: theme.bg, pointerShape }, onPointer: onPointer, onWheel: onWheel })] })] }));
47
47
  }
@@ -15,7 +15,7 @@ export { useStore } from "./devtools/store";
15
15
  export type { LogRow, LogBuffer } from "./devtools/store";
16
16
  export type { DevtoolsTab, LayoutSnapshot, ProfileSession } from "./devtools/stores";
17
17
  export type { BoxProps, TextProps, TextSpan, InputGutter, InputProps, MarkRef, PasteSource, PastedImage, CaretInfo, ChangeInfo, ChangeSource, ImageProps, ImageAdvancedProps, MarkedTextProps, ClickEvent, ContainerSelection, DragEvent, EventMods, MouseMoveEvent, ScrollEvent, SelectionPart, WheelEvent, PointerEvent, ShapeStroke, PathProps, } from "./reconciler-config";
18
- export type { Color, Edges, InsetEdges, InsetValue, ScrollbarStyle, Style } from "./styles";
18
+ export type { Color, Edges, InsetEdges, InsetValue, PointerShape, ScrollbarStyle, Style } from "./styles";
19
19
  export type { DiffEmphasis, DiffRow, EngineInfo, HighlightSpan, HostOptions, MarkdownBlock, MarkdownCell, MarkdownRow, MarkdownSpan, Rgba, SurfaceShm, TerminalColors, } from "./native";
20
20
  export { HIGHLIGHT_CAPTURES, captureFilmstrip, diff, encodeRecording, highlight, parseMarkdown } from "./native";
21
21
  export { useTerminalColors } from "./colors";
@@ -23,6 +23,8 @@ export { Surface, SurfaceCapture } from "./surface";
23
23
  export type { SurfaceFrame, SurfaceTexture, CaptureStats, CaptureFrameMeta, CaptureIndex, } from "./surface";
24
24
  export { Markdown } from "./markdown";
25
25
  export type { MarkdownProps, MarkdownTheme } from "./markdown";
26
+ export { Link } from "./link";
27
+ export type { LinkProps } from "./link";
26
28
  export { openDevtools, closeDevtools, toggleDevtools, requestLayout, engineOp };
27
29
  /**
28
30
  *
@@ -30,7 +32,6 @@ export { openDevtools, closeDevtools, toggleDevtools, requestLayout, engineOp };
30
32
  * this is dumb we can abstract this with a more cannonical capture/bubble phase
31
33
  */
32
34
  export declare function setKeyCapture(keys: string[]): void;
33
- export declare function setPointerShape(shape: string): void;
34
35
  export declare function requestClipboardImage(): void;
35
36
  export declare function setClipboard(text: string): void;
36
37
  export interface KeyMods {
@@ -99,7 +100,6 @@ export interface PixelRoot {
99
100
  highlightTransmits(): boolean;
100
101
  nudgeResize(): void;
101
102
  queryLayout(): void;
102
- setPointerShape(shape: string): void;
103
103
  setClearColor(color: Rgba): void;
104
104
  setKeyCapture(keys: string[]): void;
105
105
  requestClipboardImage(): void;
@@ -1,9 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.inspectorStore = exports.engineOp = exports.requestLayout = exports.toggleDevtools = exports.closeDevtools = exports.openDevtools = exports.Markdown = exports.SurfaceCapture = exports.Surface = exports.useTerminalColors = exports.parseMarkdown = exports.highlight = exports.encodeRecording = exports.diff = exports.captureFilmstrip = exports.HIGHLIGHT_CAPTURES = exports.useStore = exports.engineLogs = exports.profilerStore = exports.layoutStore = exports.Path = exports.MarkedText = exports.Image = exports.Input = exports.Text = exports.Box = void 0;
3
+ exports.inspectorStore = exports.engineOp = exports.requestLayout = exports.toggleDevtools = exports.closeDevtools = exports.openDevtools = exports.Link = exports.Markdown = exports.SurfaceCapture = exports.Surface = exports.useTerminalColors = exports.parseMarkdown = exports.highlight = exports.encodeRecording = exports.diff = exports.captureFilmstrip = exports.HIGHLIGHT_CAPTURES = exports.useStore = exports.engineLogs = exports.profilerStore = exports.layoutStore = exports.Path = exports.MarkedText = exports.Image = exports.Input = exports.Text = exports.Box = void 0;
4
4
  exports.appLog = appLog;
5
5
  exports.setKeyCapture = setKeyCapture;
6
- exports.setPointerShape = setPointerShape;
7
6
  exports.requestClipboardImage = requestClipboardImage;
8
7
  exports.setClipboard = setClipboard;
9
8
  exports.createRoot = createRoot;
@@ -56,6 +55,8 @@ Object.defineProperty(exports, "Surface", { enumerable: true, get: function () {
56
55
  Object.defineProperty(exports, "SurfaceCapture", { enumerable: true, get: function () { return surface_2.SurfaceCapture; } });
57
56
  var markdown_1 = require("./markdown");
58
57
  Object.defineProperty(exports, "Markdown", { enumerable: true, get: function () { return markdown_1.Markdown; } });
58
+ var link_1 = require("./link");
59
+ Object.defineProperty(exports, "Link", { enumerable: true, get: function () { return link_1.Link; } });
59
60
  /**
60
61
  *
61
62
  * i think this api exists to support capturing a click to focus the input,
@@ -66,11 +67,6 @@ function setKeyCapture(keys) {
66
67
  bridge.push(reconciler_config_1.APP_VIEW, { op: "setKeyCapture", keys });
67
68
  bridge.flush();
68
69
  }
69
- function setPointerShape(shape) {
70
- const bridge = (0, reconciler_config_1.getBridge)();
71
- bridge.push(reconciler_config_1.APP_VIEW, { op: "setPointerShape", shape });
72
- bridge.flush();
73
- }
74
70
  function requestClipboardImage() {
75
71
  const bridge = (0, reconciler_config_1.getBridge)();
76
72
  bridge.push(reconciler_config_1.APP_VIEW, { op: "requestClipboardImage" });
@@ -555,10 +551,6 @@ function createRoot(options = {}) {
555
551
  bridge.push(reconciler_config_1.APP_VIEW, { op: "queryLayout" });
556
552
  bridge.flush();
557
553
  },
558
- setPointerShape(shape) {
559
- bridge.push(reconciler_config_1.APP_VIEW, { op: "setPointerShape", shape });
560
- bridge.flush();
561
- },
562
554
  setClearColor(color) {
563
555
  bridge.push(reconciler_config_1.APP_VIEW, { op: "setClearColor", color });
564
556
  bridge.flush();
@@ -0,0 +1,10 @@
1
+ import type { ReactNode } from "react";
2
+ import type { ClickEvent } from "./reconciler-config";
3
+ import type { Style } from "./styles";
4
+ export interface LinkProps {
5
+ href: string;
6
+ children: ReactNode;
7
+ style?: Style;
8
+ onClick?(event: ClickEvent): void;
9
+ }
10
+ export declare function Link({ href, children, style, onClick }: LinkProps): import("react").JSX.Element;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Link = Link;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const electron_1 = require("electron");
6
+ const components_1 = require("./components");
7
+ function Link({ href, children, style, onClick }) {
8
+ const plain = typeof children === "string" || typeof children === "number";
9
+ return ((0, jsx_runtime_1.jsx)(components_1.Box, { style: { ...(plain ? undefined : style), pointerShape: "pointer" }, onClick: (event) => (onClick ? onClick(event) : void electron_1.shell.openExternal(href)), children: plain ? (0, jsx_runtime_1.jsx)(components_1.Text, { style: { selectable: false, ...style }, children: children }) : children }));
10
+ }
@@ -23,6 +23,7 @@ export interface ScrollbarStyle {
23
23
  trackColor?: Color;
24
24
  }
25
25
  export type BorderSide = [width: number, color: Color];
26
+ export type PointerShape = "default" | "pointer" | "text" | "crosshair" | "wait" | "help" | "progress" | "cell" | "vertical-text" | "context-menu" | "alias" | "copy" | "move" | "no-drop" | "not-allowed" | "grab" | "grabbing" | "all-scroll" | "zoom-in" | "zoom-out" | "e-resize" | "n-resize" | "ne-resize" | "nw-resize" | "s-resize" | "se-resize" | "sw-resize" | "w-resize" | "ns-resize" | "ew-resize" | "nesw-resize" | "nwse-resize";
26
27
  export interface GradientStop {
27
28
  at: number;
28
29
  color: Color;
@@ -84,6 +85,7 @@ export interface Style {
84
85
  * makes the highlight extend to the entire available space of the selection container instead of just the text
85
86
  */
86
87
  selectionMode?: "text" | "unified";
88
+ pointerShape?: PointerShape;
87
89
  }
88
90
  export declare function parseColor(color: Color | undefined): Rgba | undefined;
89
91
  export declare function serializeStyle(style: Style): Record<string, unknown>;
@@ -73,6 +73,7 @@ function serializeStyle(style) {
73
73
  opaque: style.opaque,
74
74
  selectionColor: parseColor(style.selectionColor),
75
75
  selectionMode: style.selectionMode,
76
+ pointerShape: style.pointerShape,
76
77
  scrollbar: style.scrollbar && {
77
78
  width: style.scrollbar.width,
78
79
  hoverWidth: style.scrollbar.hoverWidth,
@@ -1,4 +1,4 @@
1
- import type { EngineKeyEvent, LayoutSnapshot, PastedImage, PixelRoot, TerminalColors } from "./react";
1
+ import type { EngineKeyEvent, LayoutSnapshot, PastedImage, PixelRoot, PointerShape, TerminalColors } from "./react";
2
2
  import type { Store } from "./react/devtools/store";
3
3
  import type { PageHost } from "./web/host";
4
4
  import type { TerminalTheme } from "./web/session";
@@ -8,6 +8,7 @@ export interface ViewEntry {
8
8
  devtoolsEnabled: boolean;
9
9
  externalDevtools: boolean;
10
10
  externalDevtoolsAction: ((action: "close" | "dock-bottom" | "dock-right") => void) | null;
11
+ externalDevtoolsCursor: ((shape: PointerShape) => void) | null;
11
12
  toggleDevtools(): void;
12
13
  handleKey(event: EngineKeyEvent): boolean;
13
14
  paste?(text: string): void;
@@ -26,7 +27,6 @@ export declare class ViewRegistry {
26
27
  readonly resizeListeners: Set<() => void>;
27
28
  readonly layout: Store<LayoutSnapshot>;
28
29
  readonly colors: Store<TerminalColors>;
29
- private sentCursor;
30
30
  constructor(root: PixelRoot, displayScale: number, noSuper: boolean, hooks: RegistryHooks);
31
31
  register(entry: ViewEntry): void;
32
32
  unregister(entry: ViewEntry): void;
@@ -35,7 +35,6 @@ export declare class ViewRegistry {
35
35
  blur(entry: ViewEntry): void;
36
36
  private setActive;
37
37
  quit(entry: ViewEntry | null): void;
38
- setPointerShape(shape: string): void;
39
38
  queryLayout(): void;
40
39
  background(): string;
41
40
  theme(): TerminalTheme | null;
package/dist/registry.js CHANGED
@@ -20,7 +20,6 @@ class ViewRegistry {
20
20
  at: 0,
21
21
  });
22
22
  colors;
23
- sentCursor = null;
24
23
  constructor(root, displayScale, noSuper, hooks) {
25
24
  this.root = root;
26
25
  this.displayScale = displayScale;
@@ -73,12 +72,6 @@ class ViewRegistry {
73
72
  quit(entry) {
74
73
  this.hooks.quit(entry);
75
74
  }
76
- setPointerShape(shape) {
77
- if (shape === this.sentCursor)
78
- return;
79
- this.sentCursor = shape;
80
- this.root.setPointerShape(shape);
81
- }
82
75
  queryLayout() {
83
76
  this.root.queryLayout();
84
77
  }
package/dist/root.js CHANGED
@@ -95,11 +95,6 @@ function createRoot(options = {}) {
95
95
  }
96
96
  }
97
97
  (0, session_1.flushSessions)();
98
- try {
99
- // wait whats going on here
100
- engineRoot.setPointerShape("text");
101
- }
102
- catch { }
103
98
  try {
104
99
  engineRoot.stop();
105
100
  }
@@ -3,7 +3,7 @@ export type { Detect, Direction, ListPanesOptions, Pane, PaneContext, PaneDetail
3
3
  export { canSplit } from "./terminal";
4
4
  export type { Run } from "./run";
5
5
  export { shellIn } from "./run";
6
- export { bracketedPaste, callerTty, shellLiteral } from "./shared";
6
+ export { bracketedPaste, callerTty, PASTE_KEY, shellLiteral } from "./shared";
7
7
  export type { TerminalCheck } from "./detect";
8
8
  export { cannotOpenPanes, checkTerminal, detect } from "./detect";
9
9
  export type { GraphicsSupport } 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.callerTty = exports.bracketedPaste = exports.shellIn = exports.canSplit = void 0;
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;
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");
@@ -8,6 +8,7 @@ Object.defineProperty(exports, "shellIn", { enumerable: true, get: function () {
8
8
  var shared_1 = require("./shared");
9
9
  Object.defineProperty(exports, "bracketedPaste", { enumerable: true, get: function () { return shared_1.bracketedPaste; } });
10
10
  Object.defineProperty(exports, "callerTty", { enumerable: true, get: function () { return shared_1.callerTty; } });
11
+ Object.defineProperty(exports, "PASTE_KEY", { enumerable: true, get: function () { return shared_1.PASTE_KEY; } });
11
12
  Object.defineProperty(exports, "shellLiteral", { enumerable: true, get: function () { return shared_1.shellLiteral; } });
12
13
  var detect_1 = require("./detect");
13
14
  Object.defineProperty(exports, "cannotOpenPanes", { enumerable: true, get: function () { return detect_1.cannotOpenPanes; } });
@@ -17,4 +17,5 @@ export declare function paneById(panes: () => Promise<Pane[]>, id: string | null
17
17
  export declare function shellQuote(argv: string[]): string;
18
18
  export declare const sleep: (ms: number) => Promise<unknown>;
19
19
  export declare function shellLiteral(text: string): string;
20
+ export declare const PASTE_KEY = "\u0016";
20
21
  export declare function bracketedPaste(text: string): string;
@@ -3,7 +3,7 @@ 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.sleep = void 0;
6
+ exports.PASTE_KEY = exports.sleep = void 0;
7
7
  exports.adjacentPane = adjacentPane;
8
8
  exports.callerTty = callerTty;
9
9
  exports.setPaneWorkingDirectory = setPaneWorkingDirectory;
@@ -81,6 +81,7 @@ exports.sleep = sleep;
81
81
  function shellLiteral(text) {
82
82
  return `'${text.replace(/['\\]/g, (char) => (char === "'" ? "'\\''" : "'\\\\'"))}'`;
83
83
  }
84
+ exports.PASTE_KEY = "\x16";
84
85
  function bracketedPaste(text) {
85
86
  if (!text.includes("\n"))
86
87
  return text;
@@ -60,6 +60,7 @@ export interface Terminal {
60
60
  listPanes?(options?: ListPanesOptions): Promise<PaneDetails[]>;
61
61
  neighbor?(from: Pane, direction: Direction): Promise<Pane | null>;
62
62
  sendText?(pane: string, text: string): Promise<void>;
63
+ pasteKey?(pane: string): Promise<void>;
63
64
  focusPane?(pane: string): Promise<void>;
64
65
  }
65
66
  export type Detect = (env: NodeJS.ProcessEnv, run: Run) => Terminal | null;
@@ -83,6 +83,9 @@ const cmux = (env, run) => {
83
83
  async sendText(pane, text) {
84
84
  await cmux(["rpc", "terminal.paste", JSON.stringify({ text, surface_id: pane, submit_key: "none" })]);
85
85
  },
86
+ async pasteKey(pane) {
87
+ await cmux(["send", "--surface", pane, "--", shared_1.PASTE_KEY]);
88
+ },
86
89
  async focusPane(pane) {
87
90
  await cmux(["focus-panel", "--panel", pane]);
88
91
  },
@@ -309,6 +309,9 @@ const ghostty = (env, run) => {
309
309
  if (result !== "ok")
310
310
  throw new Error(`Ghostty could not type into pane ${pane}`);
311
311
  },
312
+ async pasteKey(pane) {
313
+ await ghosttyCommand("action", [pane, "text:\\x16"]);
314
+ },
312
315
  async neighbor(from, direction) {
313
316
  const [window, tab] = from.tab.split(":");
314
317
  const result = (await ghosttyCommand("neighbor", [window, tab, from.id, direction])).trim();
@@ -125,6 +125,9 @@ const herdr = (env, run) => {
125
125
  async sendText(pane, text) {
126
126
  await herdr(["pane", "send-text", pane, (0, shared_1.bracketedPaste)(text)]);
127
127
  },
128
+ async pasteKey(pane) {
129
+ await herdr(["pane", "send-text", pane, shared_1.PASTE_KEY]);
130
+ },
128
131
  focusPane,
129
132
  async split({ from, direction, command, size }) {
130
133
  const native = NATIVE_DIRECTION[direction];
@@ -192,6 +192,9 @@ const kitty = (env, run) => {
192
192
  await kitten(target, text);
193
193
  }
194
194
  },
195
+ async pasteKey(pane) {
196
+ await kitten(["send-text", "--match", `id:${pane}`, "--stdin"], shared_1.PASTE_KEY);
197
+ },
195
198
  async focusPane(pane) {
196
199
  await kitten(["focus-window", "--match", `id:${pane}`]);
197
200
  },
@@ -55,6 +55,10 @@ const supacode = (env, run) => {
55
55
  const { worktree, tab } = await home(pane);
56
56
  await supacode(["surface", "focus", "-w", worktree, "-t", tab, "-s", pane, "--input", text, "--timeout", "5"]);
57
57
  },
58
+ async pasteKey(pane) {
59
+ const { worktree, tab } = await home(pane);
60
+ await supacode(["surface", "focus", "-w", worktree, "-t", tab, "-s", pane, "--input", shared_1.PASTE_KEY, "--timeout", "5"]);
61
+ },
58
62
  async focusPane(pane) {
59
63
  const { worktree, tab } = await home(pane);
60
64
  await supacode(["surface", "focus", "-w", worktree, "-t", tab, "-s", pane, "--timeout", "5"]);
@@ -88,6 +88,9 @@ const tmux = (env, run) => {
88
88
  await run("tmux", ["load-buffer", "-b", "pixel-send", "-"], text);
89
89
  await tmux(["paste-buffer", "-p", "-d", "-b", "pixel-send", "-t", pane]);
90
90
  },
91
+ async pasteKey(pane) {
92
+ await tmux(["send-keys", "-t", pane, "C-v"]);
93
+ },
91
94
  async focusPane(pane) {
92
95
  const client = await userClient();
93
96
  if (client) {
@@ -44,6 +44,9 @@ const tty7 = (env, run) => {
44
44
  async sendText(pane, text) {
45
45
  await tty7(["send", `%${pane}`, (0, shared_1.bracketedPaste)(text)]);
46
46
  },
47
+ async pasteKey(pane) {
48
+ await tty7(["send", `%${pane}`, shared_1.PASTE_KEY]);
49
+ },
47
50
  async split({ from, direction, command, size }) {
48
51
  if (direction !== "right" && direction !== "down") {
49
52
  throw new Error("tty7 only splits right and down");
@@ -48,6 +48,9 @@ const wezterm = (env, run) => {
48
48
  async sendText(pane, text) {
49
49
  await wezterm(["cli", "send-text", "--pane-id", pane], text);
50
50
  },
51
+ async pasteKey(pane) {
52
+ await wezterm(["cli", "send-text", "--no-paste", "--pane-id", pane], shared_1.PASTE_KEY);
53
+ },
51
54
  async focusPane(pane) {
52
55
  await wezterm(["cli", "activate-pane", "--pane-id", pane]);
53
56
  },
@@ -1 +1,2 @@
1
- export declare function cursorShapeFor(type: string): string;
1
+ import type { PointerShape } from "../react";
2
+ export declare function cursorShapeFor(type: string): PointerShape;
@@ -1,5 +1,5 @@
1
1
  import type { WebContents } from "electron";
2
- import type { Surface } from "../react";
2
+ import type { PointerShape, Surface } from "../react";
3
3
  import type { DevtoolsDock } from "./types";
4
4
  import { PageInput } from "./input";
5
5
  import type { SurfaceLayout } from "./types";
@@ -19,7 +19,7 @@ export declare class DevtoolsWindow {
19
19
  private cdpAttached;
20
20
  private destroyed;
21
21
  private pendingPanel;
22
- cursorShape: string;
22
+ cursorShape: PointerShape;
23
23
  onCursorChange: ((shape: string) => void) | null;
24
24
  private readonly onDisplayChange;
25
25
  constructor(pageContents: WebContents, surface: Surface, layout: SurfaceLayout, dock: DevtoolsDock, background: string, renderScale: number, onAction: (action: DevtoolsAction) => void, onClosed: () => void);
@@ -1,4 +1,4 @@
1
- import type { EngineKeyEvent, PastedImage, PointerEvent, Surface, WheelEvent } from "../react";
1
+ import type { EngineKeyEvent, PastedImage, PointerEvent, PointerShape, Surface, WheelEvent } from "../react";
2
2
  import type { DownloadProgress } from "./browser-session";
3
3
  import { DevtoolsWindow } from "./devtools";
4
4
  import type { DevtoolsAction } from "./devtools";
@@ -50,7 +50,7 @@ export declare class PageHost {
50
50
  private readonly bitmaps;
51
51
  private lastFrameSize;
52
52
  onFrameSubmitted: (() => void) | null;
53
- cursorShape: string;
53
+ cursorShape: PointerShape;
54
54
  onCursorChange: ((shape: string) => void) | null;
55
55
  onOpenWindow: OpenWindowPolicy | null;
56
56
  onQuit: (() => void) | null;
@@ -1,5 +1,5 @@
1
1
  import type { BrowserWindow } from "electron";
2
- import type { Surface } from "../react";
2
+ import type { PointerShape, Surface } from "../react";
3
3
  import { PageInput } from "./input";
4
4
  import type { ZoomDirection } from "./zoom";
5
5
  export interface PopupState {
@@ -11,7 +11,7 @@ export interface PopupState {
11
11
  }
12
12
  export declare class PopupWindow {
13
13
  readonly input: PageInput;
14
- cursorShape: string;
14
+ cursorShape: PointerShape;
15
15
  onCursorChange: (() => void) | null;
16
16
  private readonly window;
17
17
  private readonly surface;
package/dist/webview.js CHANGED
@@ -38,17 +38,19 @@ exports.WebView = (0, react_1.forwardRef)(function WebView(props, ref) {
38
38
  const stateRef = (0, react_1.useRef)((0, types_1.initialWebViewState)(props.src));
39
39
  const propsRef = (0, react_1.useRef)(props);
40
40
  propsRef.current = props;
41
- const hover = (0, react_1.useRef)({ page: false, popup: false, devtools: false, divider: false });
42
41
  const dragging = (0, react_1.useRef)(false);
43
42
  const lastDragResize = (0, react_1.useRef)(0);
44
43
  const pendingInspect = (0, react_1.useRef)(null);
45
44
  const frameListeners = (0, react_1.useRef)(new Set());
46
45
  const changeListeners = (0, react_1.useRef)(new Set());
47
46
  const [popup, setPopup] = (0, react_1.useState)(null);
47
+ const [pointerShapes, setPointerShapes] = (0, react_1.useState)({
48
+ page: "default",
49
+ devtools: "default",
50
+ popup: "default",
51
+ });
48
52
  const [devtoolsOpen, setDevtoolsOpen] = (0, react_1.useState)(false);
49
53
  const [dock, setDock] = (0, react_1.useState)(typeof props.devtools === "string" ? props.devtools : "right");
50
- const dockRef = (0, react_1.useRef)(dock);
51
- dockRef.current = dock;
52
54
  const [fraction, setFraction] = (0, react_1.useState)(0.4);
53
55
  const [dividerEngaged, setDividerEngaged] = (0, react_1.useState)(false);
54
56
  const [menu, setMenu] = (0, react_1.useState)(null);
@@ -61,6 +63,7 @@ exports.WebView = (0, react_1.forwardRef)(function WebView(props, ref) {
61
63
  devtoolsEnabled: false,
62
64
  externalDevtools: false,
63
65
  externalDevtoolsAction: null,
66
+ externalDevtoolsCursor: null,
64
67
  toggleDevtools: () => { },
65
68
  handleKey: () => false,
66
69
  }), []);
@@ -90,21 +93,12 @@ exports.WebView = (0, react_1.forwardRef)(function WebView(props, ref) {
90
93
  const keepFrame = () => dragging.current || propsRef.current.keepFrame !== false;
91
94
  const syncCursor = () => {
92
95
  const host = hostRef.current;
93
- const h = hover.current;
94
- const shape = h.divider
95
- ? dockRef.current === "bottom"
96
- ? "ns-resize"
97
- : "ew-resize"
98
- : h.devtools
99
- ? host?.devtools?.cursorShape ?? "default"
100
- : host?.popup
101
- ? h.popup
102
- ? host.popup.cursorShape
103
- : "default"
104
- : h.page
105
- ? host?.cursorShape ?? "default"
106
- : "default";
107
- registry.setPointerShape(shape);
96
+ setPointerShapes({
97
+ page: host?.cursorShape ?? "default",
98
+ devtools: host?.devtools?.cursorShape ?? "default",
99
+ popup: host?.popup?.cursorShape ?? "default",
100
+ });
101
+ entry.externalDevtoolsCursor?.(host?.devtools?.cursorShape ?? "default");
108
102
  };
109
103
  const readPopup = (host) => {
110
104
  const top = host.popup;
@@ -432,6 +426,7 @@ exports.WebView = (0, react_1.forwardRef)(function WebView(props, ref) {
432
426
  cornerRadius: props.style?.cornerRadius,
433
427
  background: props.browserWindowOptions?.transparent ? undefined : theme.bg,
434
428
  opaque: !props.browserWindowOptions?.transparent,
429
+ pointerShape: pointerShapes.page,
435
430
  }, onPointer: (event) => {
436
431
  if (menuRef.current) {
437
432
  if (event.kind === "down")
@@ -445,13 +440,7 @@ exports.WebView = (0, react_1.forwardRef)(function WebView(props, ref) {
445
440
  }, onWheel: (event) => {
446
441
  registry.focus(entry);
447
442
  hostRef.current?.wheel(event);
448
- }, onMouseEnter: () => {
449
- hover.current.page = true;
450
- syncCursor();
451
- }, onMouseLeave: () => {
452
- hover.current.page = false;
453
- syncCursor();
454
- } })), devtoolsRect && surfaces.current && ((0, jsx_runtime_1.jsx)(devtools_1.DevtoolsDockPane, { rect: devtoolsRect, dock: dock, rem: rem, theme: theme, surface: surfaces.current.devtools, dividerEngaged: dividerEngaged, onPointer: (event) => {
443
+ } })), devtoolsRect && surfaces.current && ((0, jsx_runtime_1.jsx)(devtools_1.DevtoolsDockPane, { rect: devtoolsRect, dock: dock, rem: rem, theme: theme, surface: surfaces.current.devtools, dividerEngaged: dividerEngaged, pointerShape: pointerShapes.devtools, onPointer: (event) => {
455
444
  const host = hostRef.current;
456
445
  if (!host?.devtools)
457
446
  return;
@@ -463,20 +452,11 @@ exports.WebView = (0, react_1.forwardRef)(function WebView(props, ref) {
463
452
  return;
464
453
  registry.focus(entry, "devtools");
465
454
  host.devtools.input.wheel(event);
466
- }, onHover: (hovering) => {
467
- hover.current.devtools = hovering;
468
- syncCursor();
469
- }, onDividerDrag: onDividerDrag, onDividerHover: (hovering) => {
470
- hover.current.divider = hovering;
471
- syncCursor();
472
- } })), popupView && page && surfaces.current && ((0, jsx_runtime_1.jsx)(popup_1.PopupCard, { view: popupView, page: page, rem: rem, theme: theme, surface: surfaces.current.popup, onPointer: (event) => {
455
+ }, onDividerDrag: onDividerDrag })), popupView && page && surfaces.current && ((0, jsx_runtime_1.jsx)(popup_1.PopupCard, { view: popupView, page: page, rem: rem, theme: theme, surface: surfaces.current.popup, pointerShape: pointerShapes.popup, onPointer: (event) => {
473
456
  registry.focus(entry, "popup");
474
457
  hostRef.current?.popup?.input.pointer(event);
475
458
  }, onWheel: (event) => {
476
459
  registry.focus(entry, "popup");
477
460
  hostRef.current?.popup?.input.wheel(event);
478
- }, onHover: (hovering) => {
479
- hover.current.popup = hovering;
480
- syncCursor();
481
461
  }, onClose: () => hostRef.current?.popup?.close() })), menu && rect && ((0, jsx_runtime_1.jsx)(context_menu_1.ContextMenu, { x: menu.x, y: menu.y, bounds: { width: rect.width, height: rect.height }, items: menu.items, rem: rem, theme: theme, onAction: runMenu, onClose: () => setMenu(null) }))] }));
482
462
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zenbu-labs/pixel",
3
- "version": "0.0.23",
3
+ "version": "0.2.0",
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.0.23",
62
- "@zenbu-labs/pixel-native-darwin-x64": "0.0.23",
63
- "@zenbu-labs/pixel-native-linux-arm64": "0.0.23",
64
- "@zenbu-labs/pixel-native-linux-x64": "0.0.23"
61
+ "@zenbu-labs/pixel-native-darwin-arm64": "0.2.0",
62
+ "@zenbu-labs/pixel-native-darwin-x64": "0.2.0",
63
+ "@zenbu-labs/pixel-native-linux-arm64": "0.2.0",
64
+ "@zenbu-labs/pixel-native-linux-x64": "0.2.0"
65
65
  },
66
66
  "devDependencies": {
67
67
  "@types/node": "^22.0.0",