@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,15 @@
1
+ /// <reference path="../../electron/electron.d.ts" preserve="true" />
2
+ /** [placeholder copy: The terminal's colours as rgb triples. `ansi` has 16 slots and is null where the terminal did not report a colour.] */
3
+ export interface TerminalTheme {
4
+ background: number[];
5
+ foreground: number[];
6
+ ansi: (number[] | null)[];
7
+ }
8
+ export interface PixelApi {
9
+ theme(): TerminalTheme | null;
10
+ onTheme(subscriber: (theme: TerminalTheme) => void): () => void;
11
+ quit(): void;
12
+ }
13
+ declare global {
14
+ var pixel: PixelApi;
15
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /// <reference path="../../electron/electron.d.ts" preserve="true" />
@@ -0,0 +1,3 @@
1
+ import type { TerminalColors } from "./native";
2
+ export declare function publishColors(colors: TerminalColors): void;
3
+ export declare function useTerminalColors(): TerminalColors;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.publishColors = publishColors;
4
+ exports.useTerminalColors = useTerminalColors;
5
+ const react_1 = require("react");
6
+ const UNKNOWN = { foreground: null, background: null, palette: [] };
7
+ let snapshot = UNKNOWN;
8
+ const listeners = new Set();
9
+ function publishColors(colors) {
10
+ snapshot = colors;
11
+ for (const listener of listeners)
12
+ listener();
13
+ }
14
+ function subscribe(listener) {
15
+ listeners.add(listener);
16
+ return () => {
17
+ listeners.delete(listener);
18
+ };
19
+ }
20
+ function read() {
21
+ return snapshot;
22
+ }
23
+ function useTerminalColors() {
24
+ return (0, react_1.useSyncExternalStore)(subscribe, read);
25
+ }
@@ -0,0 +1,21 @@
1
+ import { type ForwardRefExoticComponent, type RefAttributes } from "react";
2
+ import type { BoxProps, ImageProps, InputProps, MarkedTextProps, PathProps, TextProps } from "./reconciler-config";
3
+ export interface NodeHandle {
4
+ id: number;
5
+ focus(): void;
6
+ blur(): void;
7
+ scrollTo(offset: number, smooth?: boolean): void;
8
+ scrollIntoView(smooth?: boolean): void;
9
+ splice(start: number, end: number, text: string): void;
10
+ selectAll(): void;
11
+ addMark(mark: number, offset?: number): void;
12
+ removeMark(mark: number): void;
13
+ }
14
+ type Host<P> = ForwardRefExoticComponent<P & RefAttributes<NodeHandle>>;
15
+ export declare const Box: Host<BoxProps>;
16
+ export declare const Text: Host<TextProps>;
17
+ export declare const Path: Host<PathProps>;
18
+ export declare const Input: ForwardRefExoticComponent<InputProps & RefAttributes<NodeHandle>>;
19
+ export declare const MarkedText: ForwardRefExoticComponent<MarkedTextProps & RefAttributes<NodeHandle>>;
20
+ export declare const Image: ForwardRefExoticComponent<ImageProps & RefAttributes<NodeHandle>>;
21
+ export {};
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Image = exports.MarkedText = exports.Input = exports.Path = exports.Text = exports.Box = void 0;
4
+ const react_1 = require("react");
5
+ exports.Box = "box";
6
+ exports.Text = "text";
7
+ exports.Path = "shape-path";
8
+ function markWidgets(marks, renderMark) {
9
+ if (!renderMark)
10
+ return null;
11
+ return marks.map((mark) => (0, react_1.createElement)("box", { key: mark.id, mark: mark.id }, renderMark(mark.id)));
12
+ }
13
+ const InputHost = "input";
14
+ exports.Input = (0, react_1.forwardRef)(function Input(props, ref) {
15
+ const { renderMark, onChange, ...rest } = props;
16
+ const [marks, setMarks] = (0, react_1.useState)(props.defaultMarks ?? []);
17
+ return (0, react_1.createElement)(InputHost, {
18
+ ...rest,
19
+ ref,
20
+ onChange: (text, change) => {
21
+ setMarks(change.marks);
22
+ onChange?.(text, change);
23
+ },
24
+ }, markWidgets(marks, renderMark));
25
+ });
26
+ const MarkedTextHost = "marked-text";
27
+ exports.MarkedText = (0, react_1.forwardRef)(function MarkedText(props, ref) {
28
+ const { renderMark, ...rest } = props;
29
+ return (0, react_1.createElement)(MarkedTextHost, { ...rest, ref }, markWidgets(props.marks, renderMark));
30
+ });
31
+ function slotted(kind, content) {
32
+ if (content == null || typeof content === "boolean")
33
+ return null;
34
+ if ((0, react_1.isValidElement)(content) && typeof content.type === "string") {
35
+ return (0, react_1.cloneElement)(content, {
36
+ key: kind,
37
+ slot: kind,
38
+ });
39
+ }
40
+ return (0, react_1.createElement)("box", { key: kind, slot: kind }, content);
41
+ }
42
+ exports.Image = (0, react_1.forwardRef)(function Image(props, ref) {
43
+ const { placeholder, error, ...rest } = props;
44
+ return (0, react_1.createElement)("image", { ...rest, ref }, slotted("placeholder", placeholder), slotted("error", error));
45
+ });
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ export declare function handleDevtoolsKey(key: string): boolean;
3
+ export declare function DevtoolsApp(): React.JSX.Element;
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleDevtoolsKey = handleDevtoolsKey;
4
+ exports.DevtoolsApp = DevtoolsApp;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const react_1 = require("react");
7
+ const components_1 = require("../components");
8
+ const controller_1 = require("./controller");
9
+ const elements_1 = require("./elements");
10
+ const log_panel_1 = require("./log-panel");
11
+ const profiler_1 = require("./profiler");
12
+ const stores_1 = require("./stores");
13
+ const store_1 = require("./store");
14
+ const theme_1 = require("./theme");
15
+ const TABS = [
16
+ { id: "elements", label: "Elements" },
17
+ { id: "console", label: "Console" },
18
+ { id: "profiler", label: "Profiler" },
19
+ ];
20
+ function handleDevtoolsKey(key) {
21
+ const state = stores_1.devtoolsStore.get();
22
+ if (!state.open)
23
+ return false;
24
+ if (key === "escape" && stores_1.inspectorStore.get().picking) {
25
+ (0, controller_1.setPicking)(false);
26
+ return true;
27
+ }
28
+ if (state.tab === "profiler") {
29
+ return (0, profiler_1.profilerHandleKey)(key);
30
+ }
31
+ return false;
32
+ }
33
+ function Tab(props) {
34
+ const { id, label, active, rem } = props;
35
+ return ((0, jsx_runtime_1.jsx)(components_1.Box, { style: {
36
+ padding: { left: rem * 0.7, right: rem * 0.7, top: rem * 0.3, bottom: rem * 0.3 },
37
+ background: active ? theme_1.theme.bg : undefined,
38
+ hoverBackground: active ? theme_1.theme.bg : theme_1.theme.chromeActive,
39
+ }, onClick: () => stores_1.devtoolsStore.update((s) => ({ ...s, tab: id })), children: (0, jsx_runtime_1.jsx)(components_1.Text, { style: {
40
+ color: active ? theme_1.theme.text : theme_1.theme.dim,
41
+ fontSize: rem * 0.74,
42
+ wrap: false,
43
+ }, children: label }) }));
44
+ }
45
+ function TabBar(props) {
46
+ const { tab, rem } = props;
47
+ return ((0, jsx_runtime_1.jsxs)(components_1.Box, { style: {
48
+ flexDirection: "row",
49
+ alignItems: "center",
50
+ background: theme_1.theme.chrome,
51
+ flexShrink: 0,
52
+ justifyContent: "space-between",
53
+ }, children: [(0, jsx_runtime_1.jsx)(components_1.Box, { style: { flexDirection: "row", alignItems: "center" }, children: TABS.map((entry) => ((0, jsx_runtime_1.jsx)(Tab, { id: entry.id, label: entry.label, active: tab === entry.id, rem: rem }, entry.id))) }), (0, jsx_runtime_1.jsx)(components_1.Box, { style: {
54
+ padding: { left: rem * 0.6, right: rem * 0.6, top: rem * 0.3, bottom: rem * 0.3 },
55
+ hoverBackground: theme_1.theme.chromeActive,
56
+ }, onClick: controller_1.closeDevtools, children: (0, jsx_runtime_1.jsx)(components_1.Text, { style: { color: theme_1.theme.dim, fontSize: rem * 0.8, wrap: false }, children: "\u00D7" }) })] }));
57
+ }
58
+ function StatusBar(props) {
59
+ const { rem } = props;
60
+ const layout = (0, store_1.useStore)(stores_1.layoutStore);
61
+ const profiler = (0, store_1.useStore)(stores_1.profilerStore);
62
+ const devtools = (0, store_1.useStore)(stores_1.devtoolsStore);
63
+ return ((0, jsx_runtime_1.jsxs)(components_1.Box, { style: {
64
+ flexDirection: "row",
65
+ alignItems: "center",
66
+ justifyContent: "space-between",
67
+ background: theme_1.theme.chrome,
68
+ padding: { left: rem * 0.5, right: rem * 0.5, top: rem * 0.12, bottom: rem * 0.12 },
69
+ flexShrink: 0,
70
+ }, children: [(0, jsx_runtime_1.jsx)(components_1.Text, { style: { color: theme_1.theme.faint, fontSize: rem * 0.64, wrap: false }, children: `${layout.stats.fps.toFixed(0)} fps · ${layout.stats.frameMs.toFixed(1)} ms/frame · ${layout.rects.size} nodes` }), (0, jsx_runtime_1.jsxs)(components_1.Box, { style: { flexDirection: "row", gap: rem * 0.6 }, children: [devtools.cpuRate > 1 && ((0, jsx_runtime_1.jsx)(components_1.Text, { style: { color: theme_1.theme.warn, fontSize: rem * 0.64, wrap: false }, children: `cpu ${devtools.cpuRate}x` })), profiler.recording && ((0, jsx_runtime_1.jsx)(components_1.Text, { style: { color: theme_1.theme.danger, fontSize: rem * 0.64, wrap: false }, children: "recording" }))] })] }));
71
+ }
72
+ function DevtoolsApp() {
73
+ const state = (0, store_1.useStore)(stores_1.devtoolsStore);
74
+ const rem = Math.max(state.basePx, 10);
75
+ (0, react_1.useEffect)(() => {
76
+ if (!state.open)
77
+ return;
78
+ (0, controller_1.requestLayout)();
79
+ const timer = setInterval(controller_1.requestLayout, 400);
80
+ return () => clearInterval(timer);
81
+ }, [state.open]);
82
+ return ((0, jsx_runtime_1.jsxs)(components_1.Box, { style: {
83
+ flexDirection: "column",
84
+ width: "100%",
85
+ flexGrow: 1,
86
+ background: theme_1.theme.bg,
87
+ color: theme_1.theme.text,
88
+ }, children: [(0, jsx_runtime_1.jsx)(TabBar, { tab: state.tab, rem: rem }), state.tab === "elements" && (0, jsx_runtime_1.jsx)(elements_1.ElementsPanel, { rem: rem }), state.tab === "console" && (0, jsx_runtime_1.jsx)(log_panel_1.LogPanel, { rem: rem }), state.tab === "profiler" && (0, jsx_runtime_1.jsx)(profiler_1.ProfilerPanel, { rem: rem }), (0, jsx_runtime_1.jsx)(StatusBar, { rem: rem })] }));
89
+ }
@@ -0,0 +1 @@
1
+ export declare function installConsoleCapture(): void;
@@ -0,0 +1,41 @@
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.installConsoleCapture = installConsoleCapture;
7
+ const node_util_1 = __importDefault(require("node:util"));
8
+ const stores_1 = require("./stores");
9
+ let installed = false;
10
+ function installConsoleCapture() {
11
+ if (installed)
12
+ return;
13
+ installed = true;
14
+ const capture = (level) => (...args) => {
15
+ stores_1.consoleLogs.push(level, "console", node_util_1.default.format(...args));
16
+ };
17
+ console.log = capture("info");
18
+ console.info = capture("info");
19
+ console.warn = capture("warn");
20
+ console.error = capture("error");
21
+ console.debug = capture("debug");
22
+ console.trace = (...args) => {
23
+ const stack = new Error().stack?.split("\n").slice(2).join("\n") ?? "";
24
+ stores_1.consoleLogs.push("debug", "console", `Trace: ${node_util_1.default.format(...args)}\n${stack}`);
25
+ };
26
+ const captureStream = (stream, level, target) => {
27
+ stream.write = ((chunk, encodingOrCb, cb) => {
28
+ const text = typeof chunk === "string"
29
+ ? chunk
30
+ : Buffer.from(chunk).toString(typeof encodingOrCb === "string" ? encodingOrCb : "utf8");
31
+ const trimmed = text.replace(/\n$/, "");
32
+ if (trimmed.length > 0)
33
+ stores_1.consoleLogs.push(level, target, trimmed);
34
+ const callback = typeof encodingOrCb === "function" ? encodingOrCb : cb;
35
+ callback?.(null);
36
+ return true;
37
+ });
38
+ };
39
+ captureStream(process.stdout, "info", "stdout");
40
+ captureStream(process.stderr, "error", "stderr");
41
+ }
@@ -0,0 +1,45 @@
1
+ import { Bridge, Instance } from "../reconciler-config";
2
+ export declare const DEFAULT_SPLIT = 0.58;
3
+ export declare function engineOp(op: Record<string, unknown>): void;
4
+ export declare function attachDevtools(bridge: Bridge): void;
5
+ export declare function openDevtools(selectId?: number): void;
6
+ export declare function closeDevtools(): void;
7
+ export declare function toggleDevtools(): void;
8
+ export declare function unmountDevtools(): void;
9
+ export declare function findInstance(id: number): Instance | null;
10
+ export declare function selectNode(id: number, reveal?: boolean): void;
11
+ export type HighlightArea = "content" | "padding" | "border" | "margin";
12
+ export declare function setHighlight(id: number | null, area?: HighlightArea): void;
13
+ export declare function setPicking(on: boolean): void;
14
+ export declare function toggleExpanded(id: number): void;
15
+ export declare function setCpuThrottle(rate: number): void;
16
+ export declare function requestLayout(): void;
17
+ export declare function startRecording(): void;
18
+ export declare function stopRecording(): void;
19
+ export declare function clearRecording(): void;
20
+ interface EngineProfileEvent {
21
+ epochMs: number;
22
+ spans: Array<{
23
+ name: string;
24
+ start: number;
25
+ dur: number;
26
+ depth: number;
27
+ view: number;
28
+ arg?: number | null;
29
+ label?: string | null;
30
+ }>;
31
+ counters?: Array<{
32
+ name: string;
33
+ at: number;
34
+ value: number;
35
+ }>;
36
+ marks?: Array<{
37
+ name: string;
38
+ label: string;
39
+ start: number;
40
+ dur: number;
41
+ view: number;
42
+ }>;
43
+ }
44
+ export declare function onEngineProfile(data: EngineProfileEvent): void;
45
+ export {};
@@ -0,0 +1,252 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_SPLIT = void 0;
4
+ exports.engineOp = engineOp;
5
+ exports.attachDevtools = attachDevtools;
6
+ exports.openDevtools = openDevtools;
7
+ exports.closeDevtools = closeDevtools;
8
+ exports.toggleDevtools = toggleDevtools;
9
+ exports.unmountDevtools = unmountDevtools;
10
+ exports.findInstance = findInstance;
11
+ exports.selectNode = selectNode;
12
+ exports.setHighlight = setHighlight;
13
+ exports.setPicking = setPicking;
14
+ exports.toggleExpanded = toggleExpanded;
15
+ exports.setCpuThrottle = setCpuThrottle;
16
+ exports.requestLayout = requestLayout;
17
+ exports.startRecording = startRecording;
18
+ exports.stopRecording = stopRecording;
19
+ exports.clearRecording = clearRecording;
20
+ exports.onEngineProfile = onEngineProfile;
21
+ const react_1 = require("react");
22
+ const constants_1 = require("react-reconciler/constants");
23
+ const reconciler_config_1 = require("../reconciler-config");
24
+ const app_1 = require("./app");
25
+ const stores_1 = require("./stores");
26
+ exports.DEFAULT_SPLIT = 0.58;
27
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
+ let devtoolsRoot = null;
29
+ function engineOp(op) {
30
+ const b = (0, reconciler_config_1.devtoolsBridge)();
31
+ b.push(reconciler_config_1.DEVTOOLS_VIEW, op);
32
+ b.flush();
33
+ }
34
+ function mountDevtools() {
35
+ if (devtoolsRoot)
36
+ return;
37
+ const b = (0, reconciler_config_1.devtoolsBridge)();
38
+ const container = { bridge: b, view: reconciler_config_1.DEVTOOLS_VIEW, children: [] };
39
+ b.containers[reconciler_config_1.DEVTOOLS_VIEW] = container;
40
+ devtoolsRoot = reconciler_config_1.reconciler.createContainer(container, constants_1.ConcurrentRoot, null, false, null, "pixel-devtools", () => { }, null);
41
+ reconciler_config_1.reconciler.updateContainer((0, react_1.createElement)(app_1.DevtoolsApp), devtoolsRoot, null, null);
42
+ }
43
+ // Moves the devtools to another root: whatever is open on the previous one is
44
+ // closed there first, since the engine split and the mounted tree are per bridge.
45
+ function attachDevtools(bridge) {
46
+ if ((0, reconciler_config_1.devtoolsBridge)() === bridge)
47
+ return;
48
+ if (stores_1.devtoolsStore.get().open)
49
+ closeDevtools();
50
+ unmountDevtools();
51
+ (0, reconciler_config_1.setDevtoolsBridge)(bridge);
52
+ }
53
+ function openDevtools(selectId) {
54
+ mountDevtools();
55
+ stores_1.devtoolsStore.update((s) => ({ ...s, open: true }));
56
+ if (selectId != null)
57
+ selectNode(selectId, true);
58
+ engineOp({ op: "setSplit", fraction: exports.DEFAULT_SPLIT });
59
+ }
60
+ function closeDevtools() {
61
+ stores_1.devtoolsStore.update((s) => ({ ...s, open: false }));
62
+ setHighlight(null);
63
+ engineOp({ op: "setSplit", fraction: null });
64
+ }
65
+ function toggleDevtools() {
66
+ if (stores_1.devtoolsStore.get().open)
67
+ closeDevtools();
68
+ else
69
+ openDevtools();
70
+ }
71
+ function unmountDevtools() {
72
+ if (!devtoolsRoot)
73
+ return;
74
+ reconciler_config_1.reconciler.flushSync(() => {
75
+ reconciler_config_1.reconciler.updateContainer(null, devtoolsRoot, null, null);
76
+ });
77
+ devtoolsRoot = null;
78
+ (0, reconciler_config_1.devtoolsBridge)().containers[reconciler_config_1.DEVTOOLS_VIEW] = null;
79
+ }
80
+ function findInstance(id) {
81
+ const container = (0, reconciler_config_1.devtoolsBridge)().containers[reconciler_config_1.APP_VIEW];
82
+ if (!container)
83
+ return null;
84
+ const stack = [...container.children];
85
+ while (stack.length) {
86
+ const instance = stack.pop();
87
+ if (instance.id === id)
88
+ return instance;
89
+ stack.push(...instance.children);
90
+ }
91
+ return null;
92
+ }
93
+ function isInstance(node) {
94
+ return node.type !== undefined;
95
+ }
96
+ function selectNode(id, reveal = false) {
97
+ stores_1.inspectorStore.update((state) => {
98
+ const expanded = new Set(state.expanded);
99
+ if (reveal) {
100
+ let node = findInstance(id)?.parent ?? null;
101
+ while (node && isInstance(node)) {
102
+ expanded.add(node.id);
103
+ node = node.parent;
104
+ }
105
+ }
106
+ return { ...state, selectedId: id, expanded, picking: false };
107
+ });
108
+ }
109
+ let highlightTimer = null;
110
+ function setHighlight(id, area) {
111
+ if (highlightTimer) {
112
+ clearTimeout(highlightTimer);
113
+ highlightTimer = null;
114
+ }
115
+ engineOp({ op: "highlight", view: reconciler_config_1.APP_VIEW, id, area });
116
+ }
117
+ function setPicking(on) {
118
+ stores_1.inspectorStore.update((s) => ({ ...s, picking: on }));
119
+ engineOp({ op: "setInspectMode", on });
120
+ }
121
+ function toggleExpanded(id) {
122
+ stores_1.inspectorStore.update((state) => {
123
+ const expanded = new Set(state.expanded);
124
+ if (expanded.has(id))
125
+ expanded.delete(id);
126
+ else
127
+ expanded.add(id);
128
+ return { ...state, expanded };
129
+ });
130
+ }
131
+ function setCpuThrottle(rate) {
132
+ stores_1.devtoolsStore.update((s) => ({ ...s, cpuRate: rate }));
133
+ engineOp({ op: "setCpuThrottle", rate });
134
+ }
135
+ function requestLayout() {
136
+ const b = (0, reconciler_config_1.devtoolsBridge)();
137
+ b.push(reconciler_config_1.APP_VIEW, { op: "queryLayout" });
138
+ b.flush();
139
+ }
140
+ const STALL_TICK_MS = 25;
141
+ const STALL_REPORT_MS = 60;
142
+ let stallTimer = null;
143
+ let lastTick = 0;
144
+ function startStallWatch() {
145
+ lastTick = performance.timeOrigin + performance.now();
146
+ stallTimer = setInterval(() => {
147
+ const now = performance.timeOrigin + performance.now();
148
+ const gap = now - lastTick;
149
+ if (gap > STALL_REPORT_MS) {
150
+ stores_1.pendingSpans.push({
151
+ name: `js event-loop stall (${Math.round(gap)}ms)`,
152
+ start: lastTick,
153
+ dur: gap,
154
+ depth: 1,
155
+ lane: "bridge",
156
+ });
157
+ }
158
+ lastTick = now;
159
+ }, STALL_TICK_MS);
160
+ }
161
+ function stopStallWatch() {
162
+ if (stallTimer) {
163
+ clearInterval(stallTimer);
164
+ stallTimer = null;
165
+ }
166
+ }
167
+ function startRecording() {
168
+ stores_1.pendingSpans.length = 0;
169
+ stores_1.profilerStore.set({
170
+ recording: true,
171
+ pendingStop: false,
172
+ session: null,
173
+ startedAt: Date.now(),
174
+ });
175
+ startStallWatch();
176
+ engineOp({ op: "profileStart" });
177
+ }
178
+ function stopRecording() {
179
+ stopStallWatch();
180
+ stores_1.profilerStore.update((s) => ({ ...s, recording: false, pendingStop: true }));
181
+ engineOp({ op: "profileStop" });
182
+ }
183
+ function clearRecording() {
184
+ stopStallWatch();
185
+ stores_1.pendingSpans.length = 0;
186
+ stores_1.profilerStore.set({ recording: false, pendingStop: false, session: null, startedAt: 0 });
187
+ }
188
+ const IMAGE_LANE_NAMES = new Set(["image.wait", "image.decode", "image.encode"]);
189
+ function packImageRows(spans) {
190
+ const waits = spans.filter((s) => s.lane === "images" && s.name === "image.wait");
191
+ const rowEnds = [];
192
+ const rowByArg = new Map();
193
+ for (const wait of waits) {
194
+ let row = rowEnds.findIndex((end) => wait.start >= end + 0.1);
195
+ if (row === -1) {
196
+ row = rowEnds.length;
197
+ rowEnds.push(0);
198
+ }
199
+ rowEnds[row] = wait.start + wait.dur;
200
+ wait.depth = row * 2;
201
+ if (wait.arg != null)
202
+ rowByArg.set(wait.arg, row * 2);
203
+ }
204
+ for (const span of spans) {
205
+ if (span.lane === "images" && span.name !== "image.wait") {
206
+ span.depth = (span.arg != null ? rowByArg.get(span.arg) ?? 0 : 0) + 1;
207
+ }
208
+ }
209
+ }
210
+ function onEngineProfile(data) {
211
+ const engineSpans = data.spans.map((s) => ({
212
+ name: s.name,
213
+ start: data.epochMs + s.start,
214
+ dur: s.dur,
215
+ depth: s.depth,
216
+ lane: IMAGE_LANE_NAMES.has(s.name)
217
+ ? "images"
218
+ : s.view === reconciler_config_1.DEVTOOLS_VIEW
219
+ ? "devtools-engine"
220
+ : "engine",
221
+ arg: s.arg ?? undefined,
222
+ label: s.label ?? undefined,
223
+ }));
224
+ const spans = [...stores_1.pendingSpans, ...engineSpans].sort((a, b) => a.start - b.start);
225
+ packImageRows(spans);
226
+ stores_1.pendingSpans.length = 0;
227
+ if (spans.length === 0) {
228
+ stores_1.profilerStore.update((s) => ({ ...s, pendingStop: false, session: null }));
229
+ return;
230
+ }
231
+ let start = Infinity;
232
+ let end = -Infinity;
233
+ for (const span of spans) {
234
+ start = Math.min(start, span.start);
235
+ end = Math.max(end, span.start + span.dur);
236
+ }
237
+ const frames = engineSpans.filter((s) => s.name === "frame" && s.depth === 0);
238
+ const counters = (data.counters ?? []).map((c) => ({
239
+ name: c.name,
240
+ at: data.epochMs + c.at,
241
+ value: c.value,
242
+ }));
243
+ const marks = (data.marks ?? []).map((m) => ({
244
+ name: m.view === reconciler_config_1.DEVTOOLS_VIEW ? `[devtools] ${m.label}` : m.label,
245
+ start: data.epochMs + m.start,
246
+ dur: m.dur,
247
+ depth: 0,
248
+ lane: "interaction",
249
+ }));
250
+ const session = { spans, frames, start, end, counters, marks };
251
+ stores_1.profilerStore.update((s) => ({ ...s, pendingStop: false, session }));
252
+ }
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ export declare function ElementsPanel(props: {
3
+ rem: number;
4
+ }): React.JSX.Element;