@zenbu-labs/pixel 0.1.0 → 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, Link, 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, LinkProps, 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.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;
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; } });
@@ -28,7 +28,6 @@ Object.defineProperty(exports, "Link", { enumerable: true, get: function () { re
28
28
  Object.defineProperty(exports, "appLog", { enumerable: true, get: function () { return react_1.appLog; } });
29
29
  Object.defineProperty(exports, "useTerminalColors", { enumerable: true, get: function () { return react_1.useTerminalColors; } });
30
30
  Object.defineProperty(exports, "setClipboard", { enumerable: true, get: function () { return react_1.setClipboard; } });
31
- Object.defineProperty(exports, "setPointerShape", { enumerable: true, get: function () { return react_1.setPointerShape; } });
32
31
  Object.defineProperty(exports, "requestClipboardImage", { enumerable: true, get: function () { return react_1.requestClipboardImage; } });
33
32
  Object.defineProperty(exports, "highlight", { enumerable: true, get: function () { return react_1.highlight; } });
34
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";
@@ -32,7 +32,6 @@ export { openDevtools, closeDevtools, toggleDevtools, requestLayout, engineOp };
32
32
  * this is dumb we can abstract this with a more cannonical capture/bubble phase
33
33
  */
34
34
  export declare function setKeyCapture(keys: string[]): void;
35
- export declare function setPointerShape(shape: string): void;
36
35
  export declare function requestClipboardImage(): void;
37
36
  export declare function setClipboard(text: string): void;
38
37
  export interface KeyMods {
@@ -101,7 +100,6 @@ export interface PixelRoot {
101
100
  highlightTransmits(): boolean;
102
101
  nudgeResize(): void;
103
102
  queryLayout(): void;
104
- setPointerShape(shape: string): void;
105
103
  setClearColor(color: Rgba): void;
106
104
  setKeyCapture(keys: string[]): void;
107
105
  requestClipboardImage(): void;
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
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;
@@ -68,11 +67,6 @@ function setKeyCapture(keys) {
68
67
  bridge.push(reconciler_config_1.APP_VIEW, { op: "setKeyCapture", keys });
69
68
  bridge.flush();
70
69
  }
71
- function setPointerShape(shape) {
72
- const bridge = (0, reconciler_config_1.getBridge)();
73
- bridge.push(reconciler_config_1.APP_VIEW, { op: "setPointerShape", shape });
74
- bridge.flush();
75
- }
76
70
  function requestClipboardImage() {
77
71
  const bridge = (0, reconciler_config_1.getBridge)();
78
72
  bridge.push(reconciler_config_1.APP_VIEW, { op: "requestClipboardImage" });
@@ -557,10 +551,6 @@ function createRoot(options = {}) {
557
551
  bridge.push(reconciler_config_1.APP_VIEW, { op: "queryLayout" });
558
552
  bridge.flush();
559
553
  },
560
- setPointerShape(shape) {
561
- bridge.push(reconciler_config_1.APP_VIEW, { op: "setPointerShape", shape });
562
- bridge.flush();
563
- },
564
554
  setClearColor(color) {
565
555
  bridge.push(reconciler_config_1.APP_VIEW, { op: "setClearColor", color });
566
556
  bridge.flush();
@@ -4,8 +4,7 @@ exports.Link = Link;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const electron_1 = require("electron");
6
6
  const components_1 = require("./components");
7
- const index_1 = require("./index");
8
7
  function Link({ href, children, style, onClick }) {
9
8
  const plain = typeof children === "string" || typeof children === "number";
10
- return ((0, jsx_runtime_1.jsx)(components_1.Box, { style: plain ? undefined : style, onClick: (event) => (onClick ? onClick(event) : void electron_1.shell.openExternal(href)), onMouseEnter: () => (0, index_1.setPointerShape)("pointer"), onMouseLeave: () => (0, index_1.setPointerShape)("default"), children: plain ? (0, jsx_runtime_1.jsx)(components_1.Text, { style: { selectable: false, ...style }, children: children }) : children }));
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 }));
11
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
  }
@@ -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.1.0",
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.1.0",
62
- "@zenbu-labs/pixel-native-darwin-x64": "0.1.0",
63
- "@zenbu-labs/pixel-native-linux-arm64": "0.1.0",
64
- "@zenbu-labs/pixel-native-linux-x64": "0.1.0"
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",