@zenbu-labs/pixel 0.0.0 → 0.0.13

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.
Files changed (153) hide show
  1. package/dist/bin.d.ts +2 -0
  2. package/dist/bin.js +161 -0
  3. package/dist/bootstrap.d.ts +1 -0
  4. package/dist/bootstrap.js +75 -0
  5. package/dist/context-menu.d.ts +20 -0
  6. package/dist/context-menu.js +57 -0
  7. package/dist/debug.d.ts +1 -0
  8. package/dist/debug.js +9 -0
  9. package/dist/devtools-layout.d.ts +21 -0
  10. package/dist/devtools-layout.js +45 -0
  11. package/dist/devtools.d.ts +33 -0
  12. package/dist/devtools.js +125 -0
  13. package/dist/electron/index.d.ts +3 -0
  14. package/dist/electron/index.js +4 -0
  15. package/dist/host/guest.d.ts +5 -0
  16. package/dist/host/guest.js +178 -0
  17. package/dist/host/server.d.ts +91 -0
  18. package/dist/host/server.js +296 -0
  19. package/dist/host/shell.d.ts +35 -0
  20. package/dist/host/shell.js +113 -0
  21. package/dist/host/strip.d.ts +6 -0
  22. package/dist/host/strip.js +63 -0
  23. package/dist/icons.d.ts +30 -0
  24. package/dist/icons.js +58 -0
  25. package/dist/index.d.ts +17 -0
  26. package/dist/index.js +39 -0
  27. package/dist/instances.d.ts +30 -0
  28. package/dist/instances.js +177 -0
  29. package/dist/layout.d.ts +5 -0
  30. package/dist/layout.js +34 -0
  31. package/dist/popup.d.ts +21 -0
  32. package/dist/popup.js +47 -0
  33. package/dist/preload/index.d.ts +15 -0
  34. package/dist/preload/index.js +3 -0
  35. package/dist/react/colors.d.ts +3 -0
  36. package/dist/react/colors.js +25 -0
  37. package/dist/react/components.d.ts +21 -0
  38. package/dist/react/components.js +45 -0
  39. package/dist/react/devtools/app.d.ts +3 -0
  40. package/dist/react/devtools/app.js +89 -0
  41. package/dist/react/devtools/console-capture.d.ts +1 -0
  42. package/dist/react/devtools/console-capture.js +41 -0
  43. package/dist/react/devtools/controller.d.ts +45 -0
  44. package/dist/react/devtools/controller.js +252 -0
  45. package/dist/react/devtools/elements.d.ts +4 -0
  46. package/dist/react/devtools/elements.js +152 -0
  47. package/dist/react/devtools/export-profile.d.ts +2 -0
  48. package/dist/react/devtools/export-profile.js +225 -0
  49. package/dist/react/devtools/fiber-hook.d.ts +1 -0
  50. package/dist/react/devtools/fiber-hook.js +89 -0
  51. package/dist/react/devtools/log-panel.d.ts +4 -0
  52. package/dist/react/devtools/log-panel.js +113 -0
  53. package/dist/react/devtools/profiler.d.ts +11 -0
  54. package/dist/react/devtools/profiler.js +374 -0
  55. package/dist/react/devtools/store.d.ts +27 -0
  56. package/dist/react/devtools/store.js +61 -0
  57. package/dist/react/devtools/stores.d.ts +92 -0
  58. package/dist/react/devtools/stores.js +41 -0
  59. package/dist/react/devtools/theme.d.ts +35 -0
  60. package/dist/react/devtools/theme.js +77 -0
  61. package/dist/react/devtools/ui.d.ts +24 -0
  62. package/dist/react/devtools/ui.js +59 -0
  63. package/dist/react/index.d.ts +110 -0
  64. package/dist/react/index.js +538 -0
  65. package/dist/react/markdown.d.ts +25 -0
  66. package/dist/react/markdown.js +270 -0
  67. package/dist/react/native.d.ts +116 -0
  68. package/dist/react/native.js +56 -0
  69. package/dist/react/reconciler-config.d.ts +241 -0
  70. package/dist/react/reconciler-config.js +412 -0
  71. package/dist/react/styles.d.ts +88 -0
  72. package/dist/react/styles.js +85 -0
  73. package/dist/react/surface.d.ts +55 -0
  74. package/dist/react/surface.js +74 -0
  75. package/dist/registry.d.ts +53 -0
  76. package/dist/registry.js +193 -0
  77. package/dist/root.d.ts +19 -0
  78. package/dist/root.js +342 -0
  79. package/dist/sandbox.d.ts +4 -0
  80. package/dist/sandbox.js +84 -0
  81. package/dist/scale.d.ts +7 -0
  82. package/dist/scale.js +31 -0
  83. package/dist/ssh/index.d.ts +58 -0
  84. package/dist/ssh/index.js +445 -0
  85. package/dist/terminal/applescript.d.ts +2 -0
  86. package/dist/terminal/applescript.js +20 -0
  87. package/dist/terminal/detect.d.ts +10 -0
  88. package/dist/terminal/detect.js +34 -0
  89. package/dist/terminal/graphics.d.ts +9 -0
  90. package/dist/terminal/graphics.js +142 -0
  91. package/dist/terminal/index.d.ts +12 -0
  92. package/dist/terminal/index.js +23 -0
  93. package/dist/terminal/run.d.ts +2 -0
  94. package/dist/terminal/run.js +15 -0
  95. package/dist/terminal/shared.d.ts +20 -0
  96. package/dist/terminal/shared.js +88 -0
  97. package/dist/terminal/terminal.d.ts +66 -0
  98. package/dist/terminal/terminal.js +6 -0
  99. package/dist/terminal/terminals/cmux.d.ts +2 -0
  100. package/dist/terminal/terminals/cmux.js +98 -0
  101. package/dist/terminal/terminals/ghostty-script.d.ts +1 -0
  102. package/dist/terminal/terminals/ghostty-script.js +179 -0
  103. package/dist/terminal/terminals/ghostty.d.ts +2 -0
  104. package/dist/terminal/terminals/ghostty.js +336 -0
  105. package/dist/terminal/terminals/herdr.d.ts +2 -0
  106. package/dist/terminal/terminals/herdr.js +141 -0
  107. package/dist/terminal/terminals/index.d.ts +5 -0
  108. package/dist/terminal/terminals/index.js +26 -0
  109. package/dist/terminal/terminals/kitty.d.ts +2 -0
  110. package/dist/terminal/terminals/kitty.js +209 -0
  111. package/dist/terminal/terminals/supacode.d.ts +2 -0
  112. package/dist/terminal/terminals/supacode.js +79 -0
  113. package/dist/terminal/terminals/tmux.d.ts +2 -0
  114. package/dist/terminal/terminals/tmux.js +132 -0
  115. package/dist/terminal/terminals/tty7.d.ts +2 -0
  116. package/dist/terminal/terminals/tty7.js +58 -0
  117. package/dist/terminal/terminals/vscode.d.ts +2 -0
  118. package/dist/terminal/terminals/vscode.js +13 -0
  119. package/dist/terminal/terminals/wezterm.d.ts +2 -0
  120. package/dist/terminal/terminals/wezterm.js +59 -0
  121. package/dist/theme.d.ts +22 -0
  122. package/dist/theme.js +40 -0
  123. package/dist/web/browser-session.d.ts +13 -0
  124. package/dist/web/browser-session.js +186 -0
  125. package/dist/web/cursor.d.ts +1 -0
  126. package/dist/web/cursor.js +24 -0
  127. package/dist/web/devtools.d.ts +39 -0
  128. package/dist/web/devtools.js +300 -0
  129. package/dist/web/favicon.d.ts +7 -0
  130. package/dist/web/favicon.js +73 -0
  131. package/dist/web/frame-rate.d.ts +1 -0
  132. package/dist/web/frame-rate.js +12 -0
  133. package/dist/web/host.d.ts +123 -0
  134. package/dist/web/host.js +573 -0
  135. package/dist/web/input.d.ts +49 -0
  136. package/dist/web/input.js +468 -0
  137. package/dist/web/offscreen.d.ts +2 -0
  138. package/dist/web/offscreen.js +23 -0
  139. package/dist/web/paint.d.ts +11 -0
  140. package/dist/web/paint.js +128 -0
  141. package/dist/web/popup.d.ts +40 -0
  142. package/dist/web/popup.js +144 -0
  143. package/dist/web/session.d.ts +20 -0
  144. package/dist/web/session.js +110 -0
  145. package/dist/web/types.d.ts +38 -0
  146. package/dist/web/types.js +39 -0
  147. package/dist/web/zoom.d.ts +5 -0
  148. package/dist/web/zoom.js +36 -0
  149. package/dist/webview.d.ts +55 -0
  150. package/dist/webview.js +481 -0
  151. package/package.json +69 -3
  152. package/scripts/apparmor.sh +71 -0
  153. package/scripts/postinstall.mjs +150 -0
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Shell = void 0;
4
+ class Shell {
5
+ ownerLabel;
6
+ guests = [];
7
+ activeIndex = 0;
8
+ restoreFocus = null;
9
+ listeners = new Set();
10
+ snapshot = null;
11
+ constructor(ownerLabel) {
12
+ this.ownerLabel = ownerLabel;
13
+ }
14
+ subscribe = (listener) => {
15
+ this.listeners.add(listener);
16
+ return () => {
17
+ this.listeners.delete(listener);
18
+ };
19
+ };
20
+ get = () => {
21
+ if (!this.snapshot) {
22
+ this.snapshot = {
23
+ tabs: [
24
+ { key: "owner", guest: null, label: this.ownerLabel() },
25
+ ...this.guests.map((guest) => ({
26
+ key: guest.pane,
27
+ guest,
28
+ label: guest.title || guest.name,
29
+ })),
30
+ ],
31
+ active: this.activeIndex,
32
+ };
33
+ }
34
+ return this.snapshot;
35
+ };
36
+ get active() {
37
+ return this.activeIndex;
38
+ }
39
+ guestActive() {
40
+ return this.activeIndex > 0;
41
+ }
42
+ hasGuests() {
43
+ return this.guests.length > 0;
44
+ }
45
+ activeGuest() {
46
+ return this.guests[this.activeIndex - 1] ?? null;
47
+ }
48
+ add(guest) {
49
+ this.guests.push(guest);
50
+ guest.onTitle = () => this.changed();
51
+ this.activate(this.guests.length);
52
+ }
53
+ remove(guest) {
54
+ const at = this.guests.indexOf(guest);
55
+ if (at < 0)
56
+ return;
57
+ this.guests.splice(at, 1);
58
+ const wasActive = this.activeIndex === at + 1;
59
+ if (this.activeIndex > this.guests.length)
60
+ this.activeIndex = this.guests.length;
61
+ if (wasActive && this.activeIndex === 0)
62
+ this.restoreFocus?.();
63
+ this.changed();
64
+ }
65
+ onCloseOwner = null;
66
+ close(index) {
67
+ if (index === 0)
68
+ this.onCloseOwner?.();
69
+ else
70
+ this.guests[index - 1]?.close();
71
+ }
72
+ successor() {
73
+ return this.activeGuest() ?? this.guests[0] ?? null;
74
+ }
75
+ others(except) {
76
+ return this.guests.filter((guest) => guest !== except);
77
+ }
78
+ activate(index) {
79
+ const clamped = Math.max(0, Math.min(index, this.guests.length));
80
+ if (clamped === this.activeIndex)
81
+ return;
82
+ this.activeIndex = clamped;
83
+ if (clamped === 0)
84
+ this.restoreFocus?.();
85
+ this.changed();
86
+ }
87
+ rememberFocus(restore) {
88
+ this.restoreFocus = restore;
89
+ }
90
+ changed() {
91
+ this.snapshot = null;
92
+ for (const listener of this.listeners)
93
+ listener();
94
+ }
95
+ handleKey(event) {
96
+ if (!this.hasGuests() || event.kind === "release")
97
+ return false;
98
+ const { mods, key } = event;
99
+ if (!mods.alt || mods.ctrl || mods.super || mods.shift)
100
+ return false;
101
+ if (/^[1-9]$/.test(key)) {
102
+ this.activate(Number(key) - 1);
103
+ return true;
104
+ }
105
+ if (key === "[" || key === "]") {
106
+ const count = this.guests.length + 1;
107
+ this.activate((this.activeIndex + (key === "]" ? 1 : count - 1)) % count);
108
+ return true;
109
+ }
110
+ return false;
111
+ }
112
+ }
113
+ exports.Shell = Shell;
@@ -0,0 +1,6 @@
1
+ import type { ReactNode } from "react";
2
+ import type { Shell } from "./shell";
3
+ export declare function PaneShell({ shell, children }: {
4
+ shell: Shell;
5
+ children: ReactNode;
6
+ }): import("react").JSX.Element;
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PaneShell = PaneShell;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const icons_1 = require("../icons");
7
+ const react_2 = require("../react");
8
+ const registry_1 = require("../registry");
9
+ const theme_1 = require("../theme");
10
+ const guest_1 = require("./guest");
11
+ function PaneShell({ shell, children }) {
12
+ const registry = (0, react_1.useContext)(registry_1.RootContext);
13
+ if (!registry)
14
+ throw new Error("PaneShell outside a root");
15
+ const { tabs, active } = (0, react_1.useSyncExternalStore)(shell.subscribe, shell.get, shell.get);
16
+ const colors = (0, registry_1.useRegistryColors)(registry);
17
+ const theme = (0, theme_1.makeTheme)(colors);
18
+ const rem = registry.root.info.basePx;
19
+ const [hovered, setHovered] = (0, react_1.useState)(null);
20
+ const closeSlot = rem * 0.95;
21
+ return ((0, jsx_runtime_1.jsxs)(react_2.Box, { style: { flexDirection: "column", width: "100%", height: "100%" }, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { hidden: tabs.length === 1, style: {
22
+ height: Math.round(rem * 1.9),
23
+ alignItems: "center",
24
+ gap: rem * 0.25,
25
+ padding: { left: rem * 0.3, right: rem * 0.3 },
26
+ background: theme.field,
27
+ border: { bottom: [1, theme.hairline] },
28
+ flexShrink: 0,
29
+ }, children: tabs.map((tab, index) => {
30
+ const current = index === active;
31
+ const closable = hovered === tab.key;
32
+ return ((0, jsx_runtime_1.jsxs)(react_2.Box, { style: {
33
+ flexGrow: 1,
34
+ flexBasis: 0,
35
+ minWidth: 0,
36
+ height: Math.round(rem * 1.4),
37
+ alignItems: "center",
38
+ gap: rem * 0.3,
39
+ padding: { left: rem * 0.7, right: rem * 0.35 },
40
+ cornerRadius: rem * 0.45,
41
+ background: current ? theme.hover : undefined,
42
+ hoverBackground: current ? undefined : theme.hover,
43
+ overflow: "hidden",
44
+ }, onClick: () => shell.activate(index), onMouseEnter: () => setHovered(tab.key), onMouseLeave: () => setHovered((key) => (key === tab.key ? null : key)), children: [(0, jsx_runtime_1.jsx)(react_2.Text, { style: {
45
+ flexGrow: 1,
46
+ flexBasis: 0,
47
+ fontSize: rem * 0.82,
48
+ color: current ? theme.fg : theme.muted,
49
+ wrap: false,
50
+ ellipsis: true,
51
+ selectable: false,
52
+ overflow: "hidden",
53
+ }, children: tab.label }), closable ? ((0, jsx_runtime_1.jsx)(react_2.Box, { style: {
54
+ width: closeSlot,
55
+ height: closeSlot,
56
+ alignItems: "center",
57
+ justifyContent: "center",
58
+ cornerRadius: rem * 0.2,
59
+ hoverBackground: theme.hoverStrong,
60
+ flexShrink: 0,
61
+ }, onClick: () => shell.close(index), 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, { style: { width: closeSlot, height: closeSlot, flexShrink: 0 } }))] }, tab.key));
62
+ }) }), (0, jsx_runtime_1.jsx)(react_2.Box, { style: { flexGrow: 1, flexBasis: 0, flexDirection: "column" }, hidden: active !== 0, children: children }), tabs.map((tab, index) => tab.guest && (0, jsx_runtime_1.jsx)(guest_1.GuestView, { guest: tab.guest, active: index === active }, tab.key))] }));
63
+ }
@@ -0,0 +1,30 @@
1
+ import type { Rgba } from "./react";
2
+ export declare const ICONS: {
3
+ back: string;
4
+ forward: string;
5
+ close: string;
6
+ plus: string;
7
+ reload: string;
8
+ search: string;
9
+ download: string;
10
+ cursor: string;
11
+ pen: string;
12
+ arrow: string;
13
+ oval: string;
14
+ text: string;
15
+ crop: string;
16
+ record: string;
17
+ play: string;
18
+ bolt: string;
19
+ camera: string;
20
+ pause: string;
21
+ more: string;
22
+ terminal: string;
23
+ };
24
+ export type IconName = keyof typeof ICONS;
25
+ export declare function Icon({ icon, size, color, weight, }: {
26
+ icon: IconName;
27
+ size: number;
28
+ color: Rgba;
29
+ weight?: number;
30
+ }): import("react").JSX.Element;
package/dist/icons.js ADDED
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ICONS = void 0;
4
+ exports.Icon = Icon;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const react_1 = require("./react");
7
+ function arcPath(cx, cy, r, fromDeg, toDeg) {
8
+ const rad = (deg) => (deg * Math.PI) / 180;
9
+ const segments = Math.max(1, Math.ceil(Math.abs(toDeg - fromDeg) / 90));
10
+ const step = (rad(toDeg) - rad(fromDeg)) / segments;
11
+ const k = (4 / 3) * Math.tan(step / 4);
12
+ const n = (value) => Number(value.toFixed(3));
13
+ const px = (t) => cx + r * Math.cos(t);
14
+ const py = (t) => cy + r * Math.sin(t);
15
+ let a = rad(fromDeg);
16
+ let path = `M ${n(px(a))} ${n(py(a))}`;
17
+ for (let i = 0; i < segments; i++) {
18
+ const b = a + step;
19
+ path +=
20
+ ` C ${n(px(a) - k * r * Math.sin(a))} ${n(py(a) + k * r * Math.cos(a))}` +
21
+ ` ${n(px(b) + k * r * Math.sin(b))} ${n(py(b) - k * r * Math.cos(b))}` +
22
+ ` ${n(px(b))} ${n(py(b))}`;
23
+ a = b;
24
+ }
25
+ return path;
26
+ }
27
+ exports.ICONS = {
28
+ back: "M 14.5 5.5 L 8 12 L 14.5 18.5",
29
+ forward: "M 9.5 5.5 L 16 12 L 9.5 18.5",
30
+ close: "M 7 7 L 17 17 M 17 7 L 7 17",
31
+ plus: "M 12 5.5 L 12 18.5 M 5.5 12 L 18.5 12",
32
+ reload: `${arcPath(12, 12, 7, 0, 270)} C 13.96 5 15.83 5.78 17.24 7.13 L 19 8.89 M 19 5 L 19 8.89 L 15.11 8.89`,
33
+ search: `${arcPath(11, 11, 5.75, 0, 360)} M 15.4 15.4 L 19.25 19.25`,
34
+ download: "M 12 4.5 L 12 14.5 M 7.75 10.5 L 12 14.75 L 16.25 10.5 M 5.5 18.5 L 18.5 18.5",
35
+ cursor: "M 6.5 4.5 L 18 11.8 L 12.6 13.2 L 10.2 19 Z",
36
+ pen: "M 4.5 19.5 L 8.2 18.6 L 18.8 8 L 16 5.2 L 5.4 15.8 L 4.5 19.5 Z",
37
+ arrow: "M 6 18 L 17.5 6.5 M 10.5 6 L 18 6 L 18 13.5",
38
+ oval: arcPath(12, 12, 7.5, 0, 360),
39
+ text: "M 5.5 6 L 18.5 6 M 12 6 L 12 19",
40
+ crop: "M 7 3 L 7 17 L 21 17 M 3 7 L 17 7 L 17 21",
41
+ record: arcPath(12, 12, 4.5, 0, 360),
42
+ play: "M 9 6.5 L 17.5 12 L 9 17.5 Z",
43
+ bolt: "M 13.2 3.5 L 6.5 13.5 L 11.2 13.5 L 10.4 20.5 L 17.5 10.2 L 12.4 10.2 Z",
44
+ camera: "M 4 8.2 L 8.3 8.2 L 9.8 6 L 14.2 6 L 15.7 8.2 L 20 8.2 L 20 18 L 4 18 Z " +
45
+ arcPath(12, 12.9, 3.1, 0, 360),
46
+ pause: "M 9.2 6.8 L 9.2 17.2 M 14.8 6.8 L 14.8 17.2",
47
+ more: arcPath(5.5, 12, 0.7, 0, 360) +
48
+ " " +
49
+ arcPath(12, 12, 0.7, 0, 360) +
50
+ " " +
51
+ arcPath(18.5, 12, 0.7, 0, 360),
52
+ terminal: "M 5 3 L 19 3 C 20.104 3 21 3.896 21 5 L 21 19 C 21 20.104 20.104 21 19 21 " +
53
+ "L 5 21 C 3.896 21 3 20.104 3 19 L 3 5 C 3 3.896 3.896 3 5 3 Z " +
54
+ "M 7 11 L 9 9 L 7 7 M 11 13 L 15 13",
55
+ };
56
+ function Icon({ icon, size, color, weight = 2.2, }) {
57
+ return ((0, jsx_runtime_1.jsx)(react_1.Path, { d: exports.ICONS[icon], viewBox: 24, stroke: { width: weight, color, cap: "round", join: "round" }, style: { width: size, height: size, flexShrink: 0 } }));
58
+ }
@@ -0,0 +1,17 @@
1
+ /// <reference path="../electron/electron.d.ts" preserve="true" />
2
+ export { createRoot } from "./root";
3
+ export type { LoadOptions, Root, RootOptions } from "./root";
4
+ export type { Instance } from "./instances";
5
+ export { findOwner, listInstances } from "./instances";
6
+ export { WebView } from "./webview";
7
+ export type { DownloadProgress, OpenWindowDecision, OpenWindowPolicy, BrowserWindowOptions, WebViewHandle, WebViewProps, WebViewRecording, WebViewState, } from "./webview";
8
+ export { DevTools } from "./devtools";
9
+ export type { DevToolsProps } from "./devtools";
10
+ export type { DevtoolsDock } from "./web/types";
11
+ export type { ZoomDirection } from "./web/zoom";
12
+ export type { TerminalTheme } from "./web/session";
13
+ export { QUIT_URL, defaultOpenWindow } from "./web/host";
14
+ export { Box, Text, Input, Image, MarkedText, Path, Markdown, appLog, useTerminalColors, setClipboard, setPointerShape, requestClipboardImage, highlight, diff, parseMarkdown, HIGHLIGHT_CAPTURES, Surface, SurfaceCapture, captureFilmstrip, encodeRecording, } from "./react";
15
+ 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";
16
+ export { makeTheme } from "./theme";
17
+ export type { Theme } from "./theme";
package/dist/index.js ADDED
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.makeTheme = 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.DevTools = exports.WebView = exports.listInstances = exports.findOwner = exports.createRoot = void 0;
4
+ /// <reference path="../electron/electron.d.ts" preserve="true" />
5
+ var root_1 = require("./root");
6
+ Object.defineProperty(exports, "createRoot", { enumerable: true, get: function () { return root_1.createRoot; } });
7
+ var instances_1 = require("./instances");
8
+ Object.defineProperty(exports, "findOwner", { enumerable: true, get: function () { return instances_1.findOwner; } });
9
+ Object.defineProperty(exports, "listInstances", { enumerable: true, get: function () { return instances_1.listInstances; } });
10
+ var webview_1 = require("./webview");
11
+ Object.defineProperty(exports, "WebView", { enumerable: true, get: function () { return webview_1.WebView; } });
12
+ var devtools_1 = require("./devtools");
13
+ Object.defineProperty(exports, "DevTools", { enumerable: true, get: function () { return devtools_1.DevTools; } });
14
+ var host_1 = require("./web/host");
15
+ Object.defineProperty(exports, "QUIT_URL", { enumerable: true, get: function () { return host_1.QUIT_URL; } });
16
+ Object.defineProperty(exports, "defaultOpenWindow", { enumerable: true, get: function () { return host_1.defaultOpenWindow; } });
17
+ var react_1 = require("./react");
18
+ Object.defineProperty(exports, "Box", { enumerable: true, get: function () { return react_1.Box; } });
19
+ Object.defineProperty(exports, "Text", { enumerable: true, get: function () { return react_1.Text; } });
20
+ Object.defineProperty(exports, "Input", { enumerable: true, get: function () { return react_1.Input; } });
21
+ Object.defineProperty(exports, "Image", { enumerable: true, get: function () { return react_1.Image; } });
22
+ Object.defineProperty(exports, "MarkedText", { enumerable: true, get: function () { return react_1.MarkedText; } });
23
+ Object.defineProperty(exports, "Path", { enumerable: true, get: function () { return react_1.Path; } });
24
+ Object.defineProperty(exports, "Markdown", { enumerable: true, get: function () { return react_1.Markdown; } });
25
+ Object.defineProperty(exports, "appLog", { enumerable: true, get: function () { return react_1.appLog; } });
26
+ Object.defineProperty(exports, "useTerminalColors", { enumerable: true, get: function () { return react_1.useTerminalColors; } });
27
+ Object.defineProperty(exports, "setClipboard", { enumerable: true, get: function () { return react_1.setClipboard; } });
28
+ Object.defineProperty(exports, "setPointerShape", { enumerable: true, get: function () { return react_1.setPointerShape; } });
29
+ Object.defineProperty(exports, "requestClipboardImage", { enumerable: true, get: function () { return react_1.requestClipboardImage; } });
30
+ Object.defineProperty(exports, "highlight", { enumerable: true, get: function () { return react_1.highlight; } });
31
+ Object.defineProperty(exports, "diff", { enumerable: true, get: function () { return react_1.diff; } });
32
+ Object.defineProperty(exports, "parseMarkdown", { enumerable: true, get: function () { return react_1.parseMarkdown; } });
33
+ Object.defineProperty(exports, "HIGHLIGHT_CAPTURES", { enumerable: true, get: function () { return react_1.HIGHLIGHT_CAPTURES; } });
34
+ Object.defineProperty(exports, "Surface", { enumerable: true, get: function () { return react_1.Surface; } });
35
+ Object.defineProperty(exports, "SurfaceCapture", { enumerable: true, get: function () { return react_1.SurfaceCapture; } });
36
+ Object.defineProperty(exports, "captureFilmstrip", { enumerable: true, get: function () { return react_1.captureFilmstrip; } });
37
+ Object.defineProperty(exports, "encodeRecording", { enumerable: true, get: function () { return react_1.encodeRecording; } });
38
+ var theme_1 = require("./theme");
39
+ Object.defineProperty(exports, "makeTheme", { enumerable: true, get: function () { return theme_1.makeTheme; } });
@@ -0,0 +1,30 @@
1
+ export declare const PROTOCOL = 1;
2
+ export interface Instance {
3
+ tty: string;
4
+ pid: number;
5
+ socket: string;
6
+ protocol: number;
7
+ name: string;
8
+ title: string | null;
9
+ cwd: string;
10
+ startedAt: number;
11
+ }
12
+ export declare function instancesDir(env?: NodeJS.ProcessEnv): string;
13
+ export declare function instanceKey(tty: string): string;
14
+ export declare function listInstances(env?: NodeJS.ProcessEnv): Instance[];
15
+ export declare function findOwner(tty: string, env?: NodeJS.ProcessEnv): Instance | null;
16
+ export declare function announceGuest(owner: Instance, name: string): {
17
+ pane: string;
18
+ end(): void;
19
+ };
20
+ export declare function markHandoff(tty: string, env?: NodeJS.ProcessEnv): void;
21
+ export declare function clearHandoff(tty: string, env?: NodeJS.ProcessEnv): void;
22
+ export declare function waitForOwners(tty: string, env?: NodeJS.ProcessEnv): Promise<void>;
23
+ export declare class InstanceRecord {
24
+ private readonly file;
25
+ private readonly record;
26
+ constructor(record: Instance, env?: NodeJS.ProcessEnv);
27
+ setTitle(title: string | null): void;
28
+ withdraw(): void;
29
+ private write;
30
+ }
@@ -0,0 +1,177 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.InstanceRecord = exports.PROTOCOL = void 0;
7
+ exports.instancesDir = instancesDir;
8
+ exports.instanceKey = instanceKey;
9
+ exports.listInstances = listInstances;
10
+ exports.findOwner = findOwner;
11
+ exports.announceGuest = announceGuest;
12
+ exports.markHandoff = markHandoff;
13
+ exports.clearHandoff = clearHandoff;
14
+ exports.waitForOwners = waitForOwners;
15
+ const node_crypto_1 = require("node:crypto");
16
+ const node_fs_1 = __importDefault(require("node:fs"));
17
+ const node_net_1 = __importDefault(require("node:net"));
18
+ const node_os_1 = __importDefault(require("node:os"));
19
+ const node_path_1 = __importDefault(require("node:path"));
20
+ exports.PROTOCOL = 1;
21
+ function instancesDir(env = process.env) {
22
+ const state = env.XDG_STATE_HOME ?? node_path_1.default.join(node_os_1.default.homedir(), ".local", "state");
23
+ return node_path_1.default.join(state, "pixel", "instances");
24
+ }
25
+ function instanceKey(tty) {
26
+ return tty.replace(/[^\w-]/g, "_");
27
+ }
28
+ function alive(pid) {
29
+ try {
30
+ process.kill(pid, 0);
31
+ return true;
32
+ }
33
+ catch {
34
+ return false;
35
+ }
36
+ }
37
+ function readInstance(file) {
38
+ try {
39
+ const parsed = JSON.parse(node_fs_1.default.readFileSync(file, "utf8"));
40
+ if (typeof parsed.tty !== "string" ||
41
+ typeof parsed.pid !== "number" ||
42
+ typeof parsed.socket !== "string" ||
43
+ typeof parsed.protocol !== "number") {
44
+ return null;
45
+ }
46
+ return {
47
+ tty: parsed.tty,
48
+ pid: parsed.pid,
49
+ socket: parsed.socket,
50
+ protocol: parsed.protocol,
51
+ name: typeof parsed.name === "string" ? parsed.name : "app",
52
+ title: typeof parsed.title === "string" ? parsed.title : null,
53
+ cwd: typeof parsed.cwd === "string" ? parsed.cwd : "",
54
+ startedAt: typeof parsed.startedAt === "number" ? parsed.startedAt : 0,
55
+ };
56
+ }
57
+ catch {
58
+ return null;
59
+ }
60
+ }
61
+ function listInstances(env = process.env) {
62
+ const dir = instancesDir(env);
63
+ let names;
64
+ try {
65
+ names = node_fs_1.default.readdirSync(dir);
66
+ }
67
+ catch {
68
+ return [];
69
+ }
70
+ const live = [];
71
+ for (const name of names) {
72
+ if (!name.endsWith(".json"))
73
+ continue;
74
+ const file = node_path_1.default.join(dir, name);
75
+ const record = readInstance(file);
76
+ if (!record || !alive(record.pid) || !node_fs_1.default.existsSync(record.socket)) {
77
+ node_fs_1.default.rmSync(file, { force: true });
78
+ continue;
79
+ }
80
+ live.push(record);
81
+ }
82
+ return live.sort((a, b) => b.startedAt - a.startedAt);
83
+ }
84
+ function findOwner(tty, env = process.env) {
85
+ return (listInstances(env).find((record) => record.tty === tty && record.protocol === exports.PROTOCOL && record.pid !== process.pid) ?? null);
86
+ }
87
+ // Tells an owner that an app is on its way so the tab shows up before the
88
+ // app's electron has booted; the connection stays open for the app's lifetime
89
+ // and its close before the app joins means the launch failed.
90
+ function announceGuest(owner, name) {
91
+ const pane = (0, node_crypto_1.randomBytes)(8).toString("hex");
92
+ const socket = node_net_1.default.connect(owner.socket);
93
+ socket.on("error", () => { });
94
+ socket.on("connect", () => {
95
+ socket.write(`${JSON.stringify({ type: "announce", pane, name, pid: process.pid })}\n`);
96
+ });
97
+ return {
98
+ pane,
99
+ end: () => socket.destroy(),
100
+ };
101
+ }
102
+ function handoffMarker(tty, env = process.env) {
103
+ return node_path_1.default.join(instancesDir(env), `${instanceKey(tty)}.handoff`);
104
+ }
105
+ function markHandoff(tty, env = process.env) {
106
+ try {
107
+ node_fs_1.default.mkdirSync(instancesDir(env), { recursive: true });
108
+ node_fs_1.default.writeFileSync(handoffMarker(tty, env), String(Date.now()));
109
+ }
110
+ catch { }
111
+ }
112
+ function clearHandoff(tty, env = process.env) {
113
+ try {
114
+ node_fs_1.default.rmSync(handoffMarker(tty, env), { force: true });
115
+ }
116
+ catch { }
117
+ }
118
+ function handoffPending(tty, env = process.env) {
119
+ try {
120
+ return Date.now() - Number(node_fs_1.default.readFileSync(handoffMarker(tty, env), "utf8")) < 20000;
121
+ }
122
+ catch {
123
+ return false;
124
+ }
125
+ }
126
+ async function waitForOwners(tty, env = process.env) {
127
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
128
+ for (;;) {
129
+ const owner = findOwner(tty, env);
130
+ if (!owner) {
131
+ if (!handoffPending(tty, env))
132
+ return;
133
+ await sleep(50);
134
+ continue;
135
+ }
136
+ await new Promise((resolve) => {
137
+ const socket = node_net_1.default.connect(owner.socket);
138
+ const done = () => {
139
+ socket.destroy();
140
+ resolve();
141
+ };
142
+ socket.on("error", done);
143
+ socket.on("close", done);
144
+ socket.on("end", done);
145
+ });
146
+ }
147
+ }
148
+ class InstanceRecord {
149
+ file;
150
+ record;
151
+ constructor(record, env = process.env) {
152
+ this.record = record;
153
+ this.file = node_path_1.default.join(instancesDir(env), `${instanceKey(record.tty)}.json`);
154
+ node_fs_1.default.mkdirSync(node_path_1.default.dirname(this.file), { recursive: true });
155
+ this.write();
156
+ }
157
+ setTitle(title) {
158
+ if (this.record.title === title)
159
+ return;
160
+ this.record.title = title;
161
+ this.write();
162
+ }
163
+ withdraw() {
164
+ node_fs_1.default.rmSync(this.file, { force: true });
165
+ }
166
+ write() {
167
+ const tmp = `${this.file}.${process.pid}.tmp`;
168
+ try {
169
+ node_fs_1.default.writeFileSync(tmp, `${JSON.stringify(this.record)}\n`);
170
+ node_fs_1.default.renameSync(tmp, this.file);
171
+ }
172
+ catch {
173
+ node_fs_1.default.rmSync(tmp, { force: true });
174
+ }
175
+ }
176
+ }
177
+ exports.InstanceRecord = InstanceRecord;
@@ -0,0 +1,5 @@
1
+ import type { RefObject } from "react";
2
+ import type { NodeHandle } from "./react";
3
+ import type { ViewRegistry } from "./registry";
4
+ import type { Rect } from "./devtools-layout";
5
+ export declare function useNodeRect(node: RefObject<NodeHandle | null>, registry: ViewRegistry): Rect | null;
package/dist/layout.js ADDED
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useNodeRect = useNodeRect;
4
+ const react_1 = require("react");
5
+ const debug_1 = require("./debug");
6
+ function useNodeRect(node, registry) {
7
+ const [rect, setRect] = (0, react_1.useState)(null);
8
+ // subscribed before the query below goes out, or the reply can land first and be missed
9
+ (0, react_1.useLayoutEffect)(() => registry.layout.subscribe(() => {
10
+ const id = node.current?.id;
11
+ const snapshot = registry.layout.get();
12
+ (0, debug_1.debug)("layout reply", { id, nodes: snapshot.rects.size, found: id != null ? snapshot.rects.get(id) : null });
13
+ if (id == null)
14
+ return;
15
+ const found = snapshot.rects.get(id);
16
+ if (!found)
17
+ return;
18
+ setRect((prev) => prev &&
19
+ prev.x === found.x &&
20
+ prev.y === found.y &&
21
+ prev.width === found.w &&
22
+ prev.height === found.h
23
+ ? prev
24
+ : { x: found.x, y: found.y, width: found.w, height: found.h });
25
+ }), [node, registry]);
26
+ (0, react_1.useEffect)(() => {
27
+ const ask = () => registry.queryLayout();
28
+ registry.resizeListeners.add(ask);
29
+ return () => {
30
+ registry.resizeListeners.delete(ask);
31
+ };
32
+ }, [registry]);
33
+ return rect;
34
+ }
@@ -0,0 +1,21 @@
1
+ import type { PointerEvent, Surface, WheelEvent } from "./react";
2
+ import type { Theme } from "./theme";
3
+ import type { Rect } from "./devtools-layout";
4
+ export interface PopupView {
5
+ title: string;
6
+ host: string;
7
+ loading: boolean;
8
+ width: number;
9
+ height: number;
10
+ }
11
+ export declare function PopupCard({ view, page, rem, theme, surface, onPointer, onWheel, onHover, onClose, }: {
12
+ view: PopupView;
13
+ page: Rect;
14
+ rem: number;
15
+ theme: Theme;
16
+ surface: Surface;
17
+ onPointer(event: PointerEvent): void;
18
+ onWheel(event: WheelEvent): void;
19
+ onHover(hovering: boolean): void;
20
+ onClose(): void;
21
+ }): import("react").JSX.Element;
package/dist/popup.js ADDED
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PopupCard = PopupCard;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const react_2 = require("./react");
7
+ const icons_1 = require("./icons");
8
+ function PopupCard({ view, page, rem, theme, surface, onPointer, onWheel, onHover, onClose, }) {
9
+ const [closeHover, setCloseHover] = (0, react_1.useState)(false);
10
+ const headerH = Math.round(rem * 1.7);
11
+ const cardH = headerH + view.height;
12
+ const left = page.x + Math.round((page.width - view.width) / 2);
13
+ const top = page.y + Math.max(Math.round(rem * 0.5), Math.round((page.height - cardH) / 2));
14
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_2.Box, { style: {
15
+ position: "absolute",
16
+ inset: { top: page.y, left: page.x },
17
+ width: page.width,
18
+ height: page.height,
19
+ background: [8, 9, 12, 150],
20
+ }, onPointer: (event) => {
21
+ if (event.kind === "down")
22
+ onClose();
23
+ }, onWheel: () => { } }), (0, jsx_runtime_1.jsxs)(react_2.Box, { style: {
24
+ position: "absolute",
25
+ inset: { top, left },
26
+ width: view.width,
27
+ flexDirection: "column",
28
+ background: theme.bg,
29
+ cornerRadius: rem * 0.5,
30
+ border: { width: 1, color: theme.fieldBorder },
31
+ overflow: "hidden",
32
+ }, onPointer: () => { }, onWheel: () => { }, children: [(0, jsx_runtime_1.jsxs)(react_2.Box, { style: {
33
+ height: headerH,
34
+ alignItems: "center",
35
+ gap: rem * 0.5,
36
+ padding: { left: rem * 0.65, right: rem * 0.35 },
37
+ background: theme.field,
38
+ border: { bottom: [1, theme.hairline] },
39
+ }, children: [(0, jsx_runtime_1.jsx)(react_2.Text, { style: { fontSize: rem * 0.78, wrap: false, selectable: false }, children: view.title || (view.loading ? "loading…" : view.host) }), (0, jsx_runtime_1.jsx)(react_2.Box, { style: { flexGrow: 1, flexBasis: 0 } }), (0, jsx_runtime_1.jsx)(react_2.Text, { style: { fontSize: rem * 0.72, color: theme.muted, wrap: false, selectable: false }, children: view.host }), (0, jsx_runtime_1.jsx)(react_2.Box, { style: {
40
+ width: rem * 1.15,
41
+ height: rem * 1.15,
42
+ alignItems: "center",
43
+ justifyContent: "center",
44
+ cornerRadius: rem * 0.3,
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) })] })] }));
47
+ }