@ghia/react 0.0.0-stage → 0.11.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.
- package/LICENSE +201 -0
- package/dist/automation/client.d.ts +2 -0
- package/dist/automation/client.d.ts.map +1 -0
- package/dist/automation/client.js +2 -0
- package/dist/automation/client.js.map +1 -0
- package/dist/automation/index.d.ts +2 -0
- package/dist/automation/index.d.ts.map +1 -0
- package/dist/automation/index.js +2 -0
- package/dist/automation/index.js.map +1 -0
- package/dist/automation/protocol.d.ts +2 -0
- package/dist/automation/protocol.d.ts.map +1 -0
- package/dist/automation/protocol.js +2 -0
- package/dist/automation/protocol.js.map +1 -0
- package/dist/components/animate-presence.d.ts +35 -0
- package/dist/components/animate-presence.d.ts.map +1 -0
- package/dist/components/animate-presence.js +184 -0
- package/dist/components/animate-presence.js.map +1 -0
- package/dist/components/button.d.ts +32 -0
- package/dist/components/button.d.ts.map +1 -0
- package/dist/components/button.js +62 -0
- package/dist/components/button.js.map +1 -0
- package/dist/components/combobox.d.ts +63 -0
- package/dist/components/combobox.d.ts.map +1 -0
- package/dist/components/combobox.js +279 -0
- package/dist/components/combobox.js.map +1 -0
- package/dist/components/dialog.d.ts +49 -0
- package/dist/components/dialog.d.ts.map +1 -0
- package/dist/components/dialog.js +157 -0
- package/dist/components/dialog.js.map +1 -0
- package/dist/components/floating.d.ts +54 -0
- package/dist/components/floating.d.ts.map +1 -0
- package/dist/components/floating.js +199 -0
- package/dist/components/floating.js.map +1 -0
- package/dist/components/index.d.ts +135 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +190 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/layout-group.d.ts +10 -0
- package/dist/components/layout-group.d.ts.map +1 -0
- package/dist/components/layout-group.js +10 -0
- package/dist/components/layout-group.js.map +1 -0
- package/dist/components/motion-config.d.ts +24 -0
- package/dist/components/motion-config.d.ts.map +1 -0
- package/dist/components/motion-config.js +31 -0
- package/dist/components/motion-config.js.map +1 -0
- package/dist/components/reorder.d.ts +44 -0
- package/dist/components/reorder.d.ts.map +1 -0
- package/dist/components/reorder.js +123 -0
- package/dist/components/reorder.js.map +1 -0
- package/dist/components/select.d.ts +61 -0
- package/dist/components/select.d.ts.map +1 -0
- package/dist/components/select.js +267 -0
- package/dist/components/select.js.map +1 -0
- package/dist/components/tooltip.d.ts +30 -0
- package/dist/components/tooltip.d.ts.map +1 -0
- package/dist/components/tooltip.js +138 -0
- package/dist/components/tooltip.js.map +1 -0
- package/dist/components/universal-style.d.ts +12 -0
- package/dist/components/universal-style.d.ts.map +1 -0
- package/dist/components/universal-style.js +45 -0
- package/dist/components/universal-style.js.map +1 -0
- package/dist/components/variant-context.d.ts +4 -0
- package/dist/components/variant-context.d.ts.map +1 -0
- package/dist/components/variant-context.js +4 -0
- package/dist/components/variant-context.js.map +1 -0
- package/dist/cpu-throttle.d.ts +3 -0
- package/dist/cpu-throttle.d.ts.map +1 -0
- package/dist/cpu-throttle.js +2 -0
- package/dist/cpu-throttle.js.map +1 -0
- package/dist/floating.d.ts +4 -0
- package/dist/floating.d.ts.map +1 -0
- package/dist/floating.js +3 -0
- package/dist/floating.js.map +1 -0
- package/dist/hooks/index.d.ts +6 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +6 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/use-gpuix.d.ts +17 -0
- package/dist/hooks/use-gpuix.d.ts.map +1 -0
- package/dist/hooks/use-gpuix.js +22 -0
- package/dist/hooks/use-gpuix.js.map +1 -0
- package/dist/hooks/use-media-query.d.ts +15 -0
- package/dist/hooks/use-media-query.d.ts.map +1 -0
- package/dist/hooks/use-media-query.js +30 -0
- package/dist/hooks/use-media-query.js.map +1 -0
- package/dist/hooks/use-motion-value.d.ts +31 -0
- package/dist/hooks/use-motion-value.d.ts.map +1 -0
- package/dist/hooks/use-motion-value.js +105 -0
- package/dist/hooks/use-motion-value.js.map +1 -0
- package/dist/hooks/use-text-search.d.ts +16 -0
- package/dist/hooks/use-text-search.d.ts.map +1 -0
- package/dist/hooks/use-text-search.js +17 -0
- package/dist/hooks/use-text-search.js.map +1 -0
- package/dist/hooks/use-window-size.d.ts +11 -0
- package/dist/hooks/use-window-size.d.ts.map +1 -0
- package/dist/hooks/use-window-size.js +20 -0
- package/dist/hooks/use-window-size.js.map +1 -0
- package/dist/idle-gc.d.ts +3 -0
- package/dist/idle-gc.d.ts.map +1 -0
- package/dist/idle-gc.js +2 -0
- package/dist/idle-gc.js.map +1 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/reconciler/event-registry.d.ts +10 -0
- package/dist/reconciler/event-registry.d.ts.map +1 -0
- package/dist/reconciler/event-registry.js +32 -0
- package/dist/reconciler/event-registry.js.map +1 -0
- package/dist/reconciler/host-config.d.ts +68 -0
- package/dist/reconciler/host-config.d.ts.map +1 -0
- package/dist/reconciler/host-config.js +539 -0
- package/dist/reconciler/host-config.js.map +1 -0
- package/dist/reconciler/index.d.ts +3 -0
- package/dist/reconciler/index.d.ts.map +1 -0
- package/dist/reconciler/index.js +3 -0
- package/dist/reconciler/index.js.map +1 -0
- package/dist/reconciler/motion-bindings.d.ts +5 -0
- package/dist/reconciler/motion-bindings.d.ts.map +1 -0
- package/dist/reconciler/motion-bindings.js +10 -0
- package/dist/reconciler/motion-bindings.js.map +1 -0
- package/dist/reconciler/portal.d.ts +24 -0
- package/dist/reconciler/portal.d.ts.map +1 -0
- package/dist/reconciler/portal.js +32 -0
- package/dist/reconciler/portal.js.map +1 -0
- package/dist/reconciler/reconciler.d.ts +14 -0
- package/dist/reconciler/reconciler.d.ts.map +1 -0
- package/dist/reconciler/reconciler.js +126 -0
- package/dist/reconciler/reconciler.js.map +1 -0
- package/dist/reconciler/renderer.d.ts +42 -0
- package/dist/reconciler/renderer.d.ts.map +1 -0
- package/dist/reconciler/renderer.js +320 -0
- package/dist/reconciler/renderer.js.map +1 -0
- package/dist/testing.d.ts +14 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +43 -0
- package/dist/testing.js.map +1 -0
- package/dist/types/host.d.ts +215 -0
- package/dist/types/host.d.ts.map +1 -0
- package/dist/types/host.js +3 -0
- package/dist/types/host.js.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/jsx-dev-runtime.d.ts +143 -0
- package/jsx-dev-runtime.js +3 -0
- package/jsx-runtime.d.ts +145 -0
- package/jsx-runtime.js +1 -0
- package/package.json +102 -3
- package/README.md +0 -3
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { portalContainerFor } from "./host-config.js";
|
|
2
|
+
const REACT_PORTAL_TYPE = Symbol.for("react.portal");
|
|
3
|
+
/**
|
|
4
|
+
* Render `children` as children of `target`, an element that is already
|
|
5
|
+
* mounted, in the order React places them. The content keeps the context of the
|
|
6
|
+
* component that called `createPortal`, as in React DOM.
|
|
7
|
+
*
|
|
8
|
+
* Take `target` from a `ref` and render the portal once it is set: a portal
|
|
9
|
+
* into an element that is not mounted yet has nowhere to attach.
|
|
10
|
+
*
|
|
11
|
+
* ```tsx
|
|
12
|
+
* const [layer, setLayer] = useState<PublicInstance | null>(null)
|
|
13
|
+
* return (
|
|
14
|
+
* <>
|
|
15
|
+
* <div ref={setLayer} style={{ position: "absolute", inset: 0 }} />
|
|
16
|
+
* {layer && createPortal(<Toast />, layer)}
|
|
17
|
+
* </>
|
|
18
|
+
* )
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* `target` must belong to the same root as the caller.
|
|
22
|
+
*/
|
|
23
|
+
export function createPortal(children, target, key) {
|
|
24
|
+
return {
|
|
25
|
+
$$typeof: REACT_PORTAL_TYPE,
|
|
26
|
+
key: key == null ? null : String(key),
|
|
27
|
+
children,
|
|
28
|
+
containerInfo: portalContainerFor(target),
|
|
29
|
+
implementation: null,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=portal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portal.js","sourceRoot":"","sources":["../../src/reconciler/portal.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAErD,MAAM,iBAAiB,GAAG,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAA;AAEpD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,YAAY,CAC1B,QAAmB,EACnB,MAAsB,EACtB,GAAmB;IAEnB,OAAO;QACL,QAAQ,EAAE,iBAAiB;QAC3B,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;QACrC,QAAQ;QACR,aAAa,EAAE,kBAAkB,CAAC,MAAM,CAAC;QACzC,cAAc,EAAE,IAAI;KACG,CAAA;AAC3B,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import ReactReconciler from "react-reconciler";
|
|
3
|
+
import type { NativeRenderer, RootEventHandlers } from "../types/host.js";
|
|
4
|
+
export declare const reconciler: ReactReconciler.Reconciler<unknown, unknown, unknown, unknown, unknown>;
|
|
5
|
+
export declare const flushSync: {
|
|
6
|
+
(): void;
|
|
7
|
+
<R>(fn: () => R): R;
|
|
8
|
+
};
|
|
9
|
+
export interface Root {
|
|
10
|
+
render: (node: ReactNode) => void;
|
|
11
|
+
unmount: () => void;
|
|
12
|
+
}
|
|
13
|
+
export declare function createRoot(renderer: NativeRenderer, rootEventHandlers?: RootEventHandlers): Root;
|
|
14
|
+
//# sourceMappingURL=reconciler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconciler.d.ts","sourceRoot":"","sources":["../../src/reconciler/reconciler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,eAAe,MAAM,kBAAkB,CAAA;AAS9C,OAAO,KAAK,EAEV,cAAc,EACd,iBAAiB,EAClB,MAAM,kBAAkB,CAAA;AAYzB,eAAO,MAAM,UAAU,yEAAqC,CAAA;AAgC5D,eAAO,MAAM,SAAS;;;CAA6C,CAAA;AAEnE,MAAM,WAAW,IAAI;IACnB,MAAM,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACjC,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAED,wBAAgB,UAAU,CACxB,QAAQ,EAAE,cAAc,EACxB,iBAAiB,GAAE,iBAAsB,GACxC,IAAI,CAwHN"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import ReactReconciler from "react-reconciler";
|
|
3
|
+
import { ConcurrentRoot } from "react-reconciler/constants.js";
|
|
4
|
+
import { createMutationQueue, installElementSource, syncWindowEventListeners, } from "@ghia/native/host";
|
|
5
|
+
import { GpuixContext } from "../hooks/use-gpuix.js";
|
|
6
|
+
import { attachRoot, detachRoot, idAllocatorFor, unregisterEventHandlers, } from "./event-registry.js";
|
|
7
|
+
import { hostConfig, publicInstanceById } from "./host-config.js";
|
|
8
|
+
import { releaseMotionBindings } from "./motion-bindings.js";
|
|
9
|
+
// Cast to any because @types/react-reconciler is out of date with react-reconciler 0.31.0
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
11
|
+
export const reconciler = ReactReconciler(hostConfig);
|
|
12
|
+
/**
|
|
13
|
+
* Register with the React DevTools global hook.
|
|
14
|
+
*
|
|
15
|
+
* This is not only for DevTools, and it is not optional. React Fast Refresh
|
|
16
|
+
* reaches a renderer through the same hook: `react-refresh` patches
|
|
17
|
+
* `hook.inject`, keeps the `scheduleRefresh` and `setRefreshHandler` helpers
|
|
18
|
+
* this call passes in, and drives hot updates through them.
|
|
19
|
+
*
|
|
20
|
+
* Drop this call and there is **no error and no page reload**. Bun still marks
|
|
21
|
+
* the edited module self-accepting and still calls `performReactRefresh()`,
|
|
22
|
+
* which iterates zero mounted roots and schedules nothing. The bundle updates
|
|
23
|
+
* and the painted UI silently stays stale.
|
|
24
|
+
*
|
|
25
|
+
* The hook has to already exist when this module evaluates. Bun's HMR runtime
|
|
26
|
+
* calls `injectIntoGlobalHook(window)` during bundle init, so it does in the
|
|
27
|
+
* dev server, and `injectIntoDevTools()` is a no-op returning `false` in plain
|
|
28
|
+
* Node. Do not test that return value: it ends in `hook.checkDCE ? true : false`
|
|
29
|
+
* and `react-refresh` installs no `checkDCE`, so a working injection still
|
|
30
|
+
* reports `false`. `fast-refresh.test.tsx` asserts the observable behaviour.
|
|
31
|
+
*/
|
|
32
|
+
try {
|
|
33
|
+
// @ts-expect-error the types for `react-reconciler` are not up to date with the library
|
|
34
|
+
reconciler.injectIntoDevTools();
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// No DevTools hook in this process.
|
|
38
|
+
}
|
|
39
|
+
const _r = reconciler;
|
|
40
|
+
export const flushSync = _r.flushSyncFromReconciler ?? _r.flushSync;
|
|
41
|
+
export function createRoot(renderer, rootEventHandlers = {}) {
|
|
42
|
+
let container = null;
|
|
43
|
+
const ids = idAllocatorFor(renderer);
|
|
44
|
+
const onUncaughtError = rootEventHandlers.onUncaughtError ??
|
|
45
|
+
((error) => {
|
|
46
|
+
console.error(error);
|
|
47
|
+
});
|
|
48
|
+
let gpuixContainer;
|
|
49
|
+
const batchedRenderer = createMutationQueue(renderer, (destroyedIds) => {
|
|
50
|
+
for (const id of destroyedIds) {
|
|
51
|
+
unregisterEventHandlers(gpuixContainer.eventHandlers, id);
|
|
52
|
+
gpuixContainer.instances.delete(id);
|
|
53
|
+
}
|
|
54
|
+
releaseMotionBindings(gpuixContainer, destroyedIds);
|
|
55
|
+
});
|
|
56
|
+
gpuixContainer = {
|
|
57
|
+
nativeRenderer: renderer,
|
|
58
|
+
renderer: batchedRenderer,
|
|
59
|
+
ids,
|
|
60
|
+
eventHandlers: new Map(),
|
|
61
|
+
motionBindings: new Map(),
|
|
62
|
+
motionReleases: [],
|
|
63
|
+
instances: new Map(),
|
|
64
|
+
windowKeyEventHandlers: rootEventHandlers,
|
|
65
|
+
windowKeyEventId: 0,
|
|
66
|
+
windowSelectionEventId: 0,
|
|
67
|
+
windowAppearanceEventId: 0,
|
|
68
|
+
onEvent: rootEventHandlers.onEvent,
|
|
69
|
+
onUncaughtError,
|
|
70
|
+
};
|
|
71
|
+
attachRoot(renderer, gpuixContainer);
|
|
72
|
+
// Sent on every root, so a remount without the option restores the default.
|
|
73
|
+
batchedRenderer.setKeyboardFocusDim(rootEventHandlers.keyboardFocusDim !== false);
|
|
74
|
+
const windowKeyEventId = gpuixContainer.windowKeyEventId;
|
|
75
|
+
const windowSelectionEventId = gpuixContainer.windowSelectionEventId;
|
|
76
|
+
const windowAppearanceEventId = gpuixContainer.windowAppearanceEventId;
|
|
77
|
+
let stopWindowEventListeners;
|
|
78
|
+
let stopElementSource;
|
|
79
|
+
try {
|
|
80
|
+
renderer.setWindowKeyEvents?.(
|
|
81
|
+
// Always on: the Tab and Escape defaults run on the key event, and
|
|
82
|
+
// `window` listeners can be added at any time.
|
|
83
|
+
true, true, windowKeyEventId);
|
|
84
|
+
renderer.setWindowSelectionChange?.(Boolean(rootEventHandlers.onSelectionChange), windowSelectionEventId);
|
|
85
|
+
renderer.setWindowAppearanceChange?.(Boolean(rootEventHandlers.onAppearanceChange), windowAppearanceEventId);
|
|
86
|
+
stopWindowEventListeners = syncWindowEventListeners(renderer);
|
|
87
|
+
stopElementSource = installElementSource(renderer, (id) => publicInstanceById(gpuixContainer, id));
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
detachRoot(renderer, gpuixContainer);
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
const cleanup = () => {
|
|
94
|
+
if (container) {
|
|
95
|
+
// Must be sync. A late unmount destroy()s remounted ids and the window goes black.
|
|
96
|
+
flushSync(() => {
|
|
97
|
+
reconciler.updateContainer(null, container, null, () => { });
|
|
98
|
+
});
|
|
99
|
+
container = null;
|
|
100
|
+
}
|
|
101
|
+
if (detachRoot(renderer, gpuixContainer)) {
|
|
102
|
+
renderer.setWindowKeyEvents?.(false, false, windowKeyEventId);
|
|
103
|
+
stopWindowEventListeners?.();
|
|
104
|
+
stopElementSource?.();
|
|
105
|
+
renderer.setWindowSelectionChange?.(false, windowSelectionEventId);
|
|
106
|
+
renderer.setWindowAppearanceChange?.(false, windowAppearanceEventId);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
110
|
+
container = reconciler.createContainer(gpuixContainer, ConcurrentRoot, null, false, null, "", onUncaughtError, console.error, console.error, null);
|
|
111
|
+
// One object for the life of the root. A fresh `{ renderer }` per `render()`
|
|
112
|
+
// call is a context change, which re-renders every `useGpuix()` consumer, and
|
|
113
|
+
// through them busts `memo` below it, on every re-render of the root.
|
|
114
|
+
const contextValue = { renderer, mutations: batchedRenderer };
|
|
115
|
+
return {
|
|
116
|
+
render: (node) => {
|
|
117
|
+
const activeContainer = container;
|
|
118
|
+
if (!activeContainer) {
|
|
119
|
+
throw new Error("Cannot render an unmounted GPUIX root");
|
|
120
|
+
}
|
|
121
|
+
reconciler.updateContainer(React.createElement(GpuixContext.Provider, { value: contextValue }, node), activeContainer, null, () => { });
|
|
122
|
+
},
|
|
123
|
+
unmount: cleanup,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=reconciler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconciler.js","sourceRoot":"","sources":["../../src/reconciler/reconciler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { GpuixRenderer } from "@ghia/native";
|
|
3
|
+
import type { EventPayload, WindowOptions } from "@ghia/native";
|
|
4
|
+
import { App as AutomationApp } from "@ghia/native/automation";
|
|
5
|
+
import { startFrameLoop as startNativeFrameLoop, type WindowFontsOption } from "@ghia/native/runtime";
|
|
6
|
+
import { type Root } from "./reconciler.js";
|
|
7
|
+
import type { DebugFrameOverlayMode, NativeRenderer, WindowKeyEventHandlers } from "../types/host.js";
|
|
8
|
+
import type { LiveAutomationRenderer } from "@ghia/native/automation";
|
|
9
|
+
export { createRoot, flushSync, reconciler } from "./reconciler.js";
|
|
10
|
+
export type { Root } from "./reconciler.js";
|
|
11
|
+
/** Keep bun alive after an uncaught throw. A dead process stops AppKit pumps. */
|
|
12
|
+
export declare function installRuntimeErrorHandlers(): void;
|
|
13
|
+
export declare function createRenderer(onEvent?: (event: import("@ghia/native").EventPayload) => void): GpuixRenderer;
|
|
14
|
+
export interface FrameLoop {
|
|
15
|
+
stop: () => void;
|
|
16
|
+
}
|
|
17
|
+
export declare const enableAutomation: (renderer: LiveAutomationRenderer) => void;
|
|
18
|
+
/**
|
|
19
|
+
* Drive GPUI until the last window closes, then run `onTerminated`.
|
|
20
|
+
*
|
|
21
|
+
* macOS wakes JS only when the main run loop has work, with no fallback timer, so an idle
|
|
22
|
+
* window is not ticked at all. Explicit `frameMs` uses timer polling instead, as Windows and Linux do.
|
|
23
|
+
* The pump never blocks JavaScript I/O and keeps running after a tick throws.
|
|
24
|
+
*/
|
|
25
|
+
export declare function startFrameLoop(renderer: Parameters<typeof startNativeFrameLoop>[0], options?: {
|
|
26
|
+
frameMs?: number;
|
|
27
|
+
onTerminated?: () => void;
|
|
28
|
+
}): FrameLoop;
|
|
29
|
+
declare global {
|
|
30
|
+
var gpuix: AutomationApp | undefined;
|
|
31
|
+
}
|
|
32
|
+
export declare function installBrowserAutomation(renderer: LiveAutomationRenderer): AutomationApp;
|
|
33
|
+
export interface RenderOptions extends WindowOptions, WindowFontsOption, WindowKeyEventHandlers {
|
|
34
|
+
onEvent?: (event: EventPayload) => void;
|
|
35
|
+
renderer?: NativeRenderer;
|
|
36
|
+
/** GPUI scene overlay. Does not go through React or layout. */
|
|
37
|
+
debugFrameOverlay?: DebugFrameOverlayMode;
|
|
38
|
+
}
|
|
39
|
+
export declare function resetRender(): void;
|
|
40
|
+
/** Mount the app. Under `bun --hot`, later calls remount on the same native window. */
|
|
41
|
+
export declare function render(node: ReactNode, options?: RenderOptions): Root;
|
|
42
|
+
//# sourceMappingURL=renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/reconciler/renderer.ts"],"names":[],"mappings":"AAAA,OAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC/D,OAAO,EAAE,GAAG,IAAI,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAC9D,OAAO,EAIL,cAAc,IAAI,oBAAoB,EACtC,KAAK,iBAAiB,EACvB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAyB,KAAK,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAClE,OAAO,KAAK,EACV,qBAAqB,EACrB,cAAc,EACd,sBAAsB,EACvB,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AAErE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AACnE,YAAY,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAe3C,iFAAiF;AACjF,wBAAgB,2BAA2B,IAAI,IAAI,CAWlD;AAWD,wBAAgB,cAAc,CAC5B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,cAAc,EAAE,YAAY,KAAK,IAAI,GAC7D,aAAa,CAOf;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,IAAI,CAAA;CACjB;AAED,eAAO,MAAM,gBAAgB,EAAE,CAAC,QAAQ,EAAE,sBAAsB,KAAK,IAC7C,CAAA;AAExB;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC,CAAC,CAAC,EACpD,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,IAAI,CAAA;CAAO,GAC5D,SAAS,CAKX;AAKD,OAAO,CAAC,MAAM,CAAC;IACb,IAAI,KAAK,EAAE,aAAa,GAAG,SAAS,CAAA;CACrC;AAED,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,sBAAsB,GAC/B,aAAa,CAOf;AAmPD,MAAM,WAAW,aACf,SAAQ,aAAa,EACnB,iBAAiB,EACjB,sBAAsB;IACxB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAA;IACvC,QAAQ,CAAC,EAAE,cAAc,CAAA;IACzB,+DAA+D;IAC/D,iBAAiB,CAAC,EAAE,qBAAqB,CAAA;CAC1C;AAED,wBAAgB,WAAW,IAAI,IAAI,CASlC;AAED,uFAAuF;AACvF,wBAAgB,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,GAAE,aAAkB,GAAG,IAAI,CA+DzE"}
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import React, {} from "react";
|
|
2
|
+
import { GpuixRenderer } from "@ghia/native";
|
|
3
|
+
import { App as AutomationApp } from "@ghia/native/automation";
|
|
4
|
+
import { createNativeRenderer, enableAutomation as enableNativeAutomation, installBrowserAutomation as installNativeBrowserAutomation, startFrameLoop as startNativeFrameLoop, } from "@ghia/native/runtime";
|
|
5
|
+
import { createRoot, flushSync } from "./reconciler.js";
|
|
6
|
+
export { createRoot, flushSync, reconciler } from "./reconciler.js";
|
|
7
|
+
const RUNTIME_ERROR_HANDLERS_KEY = "__gpuixRuntimeErrorHandlers";
|
|
8
|
+
function runtimeErrorHandlers() {
|
|
9
|
+
return Reflect.get(globalThis, RUNTIME_ERROR_HANDLERS_KEY);
|
|
10
|
+
}
|
|
11
|
+
/** Keep bun alive after an uncaught throw. A dead process stops AppKit pumps. */
|
|
12
|
+
export function installRuntimeErrorHandlers() {
|
|
13
|
+
if (typeof process === "undefined" || runtimeErrorHandlers())
|
|
14
|
+
return;
|
|
15
|
+
const handlers = {
|
|
16
|
+
uncaughtException: scheduleRuntimeError,
|
|
17
|
+
unhandledRejection: (reason) => {
|
|
18
|
+
scheduleRuntimeError(thrownToError(reason));
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
process.on("uncaughtException", handlers.uncaughtException);
|
|
22
|
+
process.on("unhandledRejection", handlers.unhandledRejection);
|
|
23
|
+
Reflect.set(globalThis, RUNTIME_ERROR_HANDLERS_KEY, handlers);
|
|
24
|
+
}
|
|
25
|
+
function uninstallRuntimeErrorHandlers() {
|
|
26
|
+
if (typeof process === "undefined")
|
|
27
|
+
return;
|
|
28
|
+
const handlers = runtimeErrorHandlers();
|
|
29
|
+
if (!handlers)
|
|
30
|
+
return;
|
|
31
|
+
process.off("uncaughtException", handlers.uncaughtException);
|
|
32
|
+
process.off("unhandledRejection", handlers.unhandledRejection);
|
|
33
|
+
Reflect.deleteProperty(globalThis, RUNTIME_ERROR_HANDLERS_KEY);
|
|
34
|
+
}
|
|
35
|
+
export function createRenderer(onEvent) {
|
|
36
|
+
return createNativeRenderer({
|
|
37
|
+
onEvent,
|
|
38
|
+
onError: (error) => {
|
|
39
|
+
scheduleRuntimeError(thrownToError(error));
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
export const enableAutomation = enableNativeAutomation;
|
|
44
|
+
/**
|
|
45
|
+
* Drive GPUI until the last window closes, then run `onTerminated`.
|
|
46
|
+
*
|
|
47
|
+
* macOS wakes JS only when the main run loop has work, with no fallback timer, so an idle
|
|
48
|
+
* window is not ticked at all. Explicit `frameMs` uses timer polling instead, as Windows and Linux do.
|
|
49
|
+
* The pump never blocks JavaScript I/O and keeps running after a tick throws.
|
|
50
|
+
*/
|
|
51
|
+
export function startFrameLoop(renderer, options = {}) {
|
|
52
|
+
return startNativeFrameLoop(renderer, {
|
|
53
|
+
...options,
|
|
54
|
+
onError: (error) => scheduleRuntimeError(thrownToError(error)),
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
const RENDER_HOST_KEY = "__gpuixRenderHost";
|
|
58
|
+
const BROWSER_AUTOMATION_KEY = "gpuix";
|
|
59
|
+
export function installBrowserAutomation(renderer) {
|
|
60
|
+
const existing = Reflect.get(globalThis, BROWSER_AUTOMATION_KEY);
|
|
61
|
+
if (existing instanceof AutomationApp)
|
|
62
|
+
return existing;
|
|
63
|
+
const automation = installNativeBrowserAutomation(renderer);
|
|
64
|
+
Reflect.set(globalThis, BROWSER_AUTOMATION_KEY, automation);
|
|
65
|
+
return automation;
|
|
66
|
+
}
|
|
67
|
+
function formatRuntimeError(thrown, componentStack) {
|
|
68
|
+
let message;
|
|
69
|
+
let stack;
|
|
70
|
+
if (thrown instanceof Error) {
|
|
71
|
+
message = thrown.message || thrown.name;
|
|
72
|
+
stack = thrown.stack ?? `${thrown.name}: ${thrown.message}`;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
message = thrown;
|
|
76
|
+
stack = thrown;
|
|
77
|
+
}
|
|
78
|
+
if (!message)
|
|
79
|
+
message = "Unknown error";
|
|
80
|
+
const extra = componentStack?.trim();
|
|
81
|
+
if (extra && !stack.includes(extra))
|
|
82
|
+
stack = `${stack}\n${extra}`;
|
|
83
|
+
if (!stack.includes(message))
|
|
84
|
+
stack = `${message}\n${stack}`;
|
|
85
|
+
return { message, stack };
|
|
86
|
+
}
|
|
87
|
+
function thrownToError(thrown) {
|
|
88
|
+
if (thrown instanceof Error)
|
|
89
|
+
return thrown;
|
|
90
|
+
if (typeof thrown === "string")
|
|
91
|
+
return thrown;
|
|
92
|
+
try {
|
|
93
|
+
return String(thrown);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return "Unknown error";
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const OVERLAY_MONO = "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace";
|
|
100
|
+
function overlayStackLines(error) {
|
|
101
|
+
const lines = error.stack.length === 0 ? [error.message] : error.stack.split("\n");
|
|
102
|
+
const frames = lines.flatMap((line) => {
|
|
103
|
+
const trimmed = line.trim();
|
|
104
|
+
if (trimmed.length === 0)
|
|
105
|
+
return [];
|
|
106
|
+
if (trimmed === error.message)
|
|
107
|
+
return [];
|
|
108
|
+
if (trimmed === `Error: ${error.message}`)
|
|
109
|
+
return [];
|
|
110
|
+
if (/^at\s/.test(line))
|
|
111
|
+
return [` ${line}`];
|
|
112
|
+
return [line];
|
|
113
|
+
});
|
|
114
|
+
return frames.length > 0 ? frames : [error.message];
|
|
115
|
+
}
|
|
116
|
+
function runtimeErrorOverlay(error, onReload) {
|
|
117
|
+
const lines = overlayStackLines(error);
|
|
118
|
+
return React.createElement("div", {
|
|
119
|
+
testId: "runtime-error-overlay",
|
|
120
|
+
style: {
|
|
121
|
+
display: "flex",
|
|
122
|
+
flexDirection: "column",
|
|
123
|
+
width: "100%",
|
|
124
|
+
height: "100%",
|
|
125
|
+
padding: 32,
|
|
126
|
+
paddingBottom: 40,
|
|
127
|
+
gap: 20,
|
|
128
|
+
backgroundColor: "#000000e6",
|
|
129
|
+
pointerEvents: "auto",
|
|
130
|
+
},
|
|
131
|
+
}, React.createElement("text", {
|
|
132
|
+
style: {
|
|
133
|
+
fontSize: 32,
|
|
134
|
+
fontWeight: 700,
|
|
135
|
+
color: "#e83b46",
|
|
136
|
+
flexShrink: 0,
|
|
137
|
+
},
|
|
138
|
+
}, "Uncaught runtime errors:"), React.createElement("div", {
|
|
139
|
+
testId: "runtime-error-stack",
|
|
140
|
+
style: {
|
|
141
|
+
display: "flex",
|
|
142
|
+
flexDirection: "column",
|
|
143
|
+
flexGrow: 0,
|
|
144
|
+
flexShrink: 1,
|
|
145
|
+
minHeight: 0,
|
|
146
|
+
overflowY: "scroll",
|
|
147
|
+
padding: 16,
|
|
148
|
+
paddingBottom: 24,
|
|
149
|
+
backgroundColor: "#ce11261a",
|
|
150
|
+
borderRadius: 4,
|
|
151
|
+
gap: 4,
|
|
152
|
+
},
|
|
153
|
+
}, React.createElement("text", {
|
|
154
|
+
style: {
|
|
155
|
+
fontSize: 20,
|
|
156
|
+
fontWeight: 700,
|
|
157
|
+
color: "#e83b46",
|
|
158
|
+
marginBottom: 12,
|
|
159
|
+
flexShrink: 0,
|
|
160
|
+
},
|
|
161
|
+
}, error.message), ...lines.map((line) => React.createElement("text", {
|
|
162
|
+
style: {
|
|
163
|
+
fontSize: 13,
|
|
164
|
+
lineHeight: "20px",
|
|
165
|
+
color: "#fccfcf",
|
|
166
|
+
fontFamily: OVERLAY_MONO,
|
|
167
|
+
whiteSpace: "nowrap",
|
|
168
|
+
},
|
|
169
|
+
}, line))), React.createElement("div", {
|
|
170
|
+
testId: "runtime-error-reload",
|
|
171
|
+
onClick: onReload,
|
|
172
|
+
style: {
|
|
173
|
+
alignSelf: "flex-start",
|
|
174
|
+
padding: 10,
|
|
175
|
+
paddingLeft: 16,
|
|
176
|
+
paddingRight: 16,
|
|
177
|
+
borderRadius: 4,
|
|
178
|
+
backgroundColor: "#e83b46",
|
|
179
|
+
hover: { backgroundColor: "#c92a34" },
|
|
180
|
+
},
|
|
181
|
+
}, React.createElement("text", { style: { fontSize: 14, fontWeight: 700, color: "#ffffff" } }, "Reload")));
|
|
182
|
+
}
|
|
183
|
+
function mountRoot(args) {
|
|
184
|
+
const { slot, node, options } = args;
|
|
185
|
+
const { onEvent, onKeyDown, onKeyUp, onSelectionChange, onAppearanceChange, tabNavigation, keyboardFocusDim, } = options;
|
|
186
|
+
const host = slot.renderer;
|
|
187
|
+
if (!host)
|
|
188
|
+
throw new Error("GPUIX renderer is not initialized");
|
|
189
|
+
if (slot.root)
|
|
190
|
+
slot.root.unmount();
|
|
191
|
+
const root = createRoot(host, {
|
|
192
|
+
onEvent,
|
|
193
|
+
onKeyDown,
|
|
194
|
+
onKeyUp,
|
|
195
|
+
onSelectionChange,
|
|
196
|
+
onAppearanceChange,
|
|
197
|
+
tabNavigation,
|
|
198
|
+
keyboardFocusDim,
|
|
199
|
+
onUncaughtError: (error, errorInfo) => {
|
|
200
|
+
scheduleRuntimeError(error, errorInfo.componentStack);
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
slot.root = root;
|
|
204
|
+
slot.overlayShown = false;
|
|
205
|
+
flushSync(() => {
|
|
206
|
+
root.render(node);
|
|
207
|
+
});
|
|
208
|
+
return root;
|
|
209
|
+
}
|
|
210
|
+
function reloadApp(slot) {
|
|
211
|
+
if (slot.lastNode === undefined)
|
|
212
|
+
return;
|
|
213
|
+
mountRoot({ slot, node: slot.lastNode, options: slot.lastOptions ?? {} });
|
|
214
|
+
}
|
|
215
|
+
function showRuntimeError(error, componentStack) {
|
|
216
|
+
const formatted = formatRuntimeError(error, componentStack);
|
|
217
|
+
console.error("[gpuix] runtime error:", formatted.stack);
|
|
218
|
+
const slot = Reflect.get(globalThis, RENDER_HOST_KEY);
|
|
219
|
+
if (!slot?.root || slot.overlayShown)
|
|
220
|
+
return;
|
|
221
|
+
slot.overlayShown = true;
|
|
222
|
+
try {
|
|
223
|
+
mountRoot({
|
|
224
|
+
slot,
|
|
225
|
+
node: runtimeErrorOverlay(formatted, () => reloadApp(slot)),
|
|
226
|
+
options: slot.lastOptions ?? {},
|
|
227
|
+
});
|
|
228
|
+
slot.overlayShown = true;
|
|
229
|
+
}
|
|
230
|
+
catch (overlayError) {
|
|
231
|
+
slot.overlayShown = false;
|
|
232
|
+
console.error("[gpuix] failed to show runtime error overlay:", overlayError);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function scheduleRuntimeError(error, componentStack) {
|
|
236
|
+
const slot = Reflect.get(globalThis, RENDER_HOST_KEY);
|
|
237
|
+
if (!slot?.root)
|
|
238
|
+
return;
|
|
239
|
+
const failedRoot = slot.root;
|
|
240
|
+
queueMicrotask(() => {
|
|
241
|
+
const current = Reflect.get(globalThis, RENDER_HOST_KEY);
|
|
242
|
+
if (!current?.root || current.root !== failedRoot)
|
|
243
|
+
return;
|
|
244
|
+
showRuntimeError(thrownToError(error), componentStack);
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
function renderSlot() {
|
|
248
|
+
const existing = Reflect.get(globalThis, RENDER_HOST_KEY);
|
|
249
|
+
if (existing) {
|
|
250
|
+
return existing;
|
|
251
|
+
}
|
|
252
|
+
const created = {};
|
|
253
|
+
Reflect.set(globalThis, RENDER_HOST_KEY, created);
|
|
254
|
+
return created;
|
|
255
|
+
}
|
|
256
|
+
export function resetRender() {
|
|
257
|
+
const slot = Reflect.get(globalThis, RENDER_HOST_KEY);
|
|
258
|
+
slot?.loop?.stop();
|
|
259
|
+
slot?.root?.unmount();
|
|
260
|
+
const automation = Reflect.get(globalThis, BROWSER_AUTOMATION_KEY);
|
|
261
|
+
void automation?.close();
|
|
262
|
+
Reflect.deleteProperty(globalThis, BROWSER_AUTOMATION_KEY);
|
|
263
|
+
Reflect.deleteProperty(globalThis, RENDER_HOST_KEY);
|
|
264
|
+
uninstallRuntimeErrorHandlers();
|
|
265
|
+
}
|
|
266
|
+
/** Mount the app. Under `bun --hot`, later calls remount on the same native window. */
|
|
267
|
+
export function render(node, options = {}) {
|
|
268
|
+
const { onEvent, onKeyDown, onKeyUp, onSelectionChange, onAppearanceChange, tabNavigation, keyboardFocusDim, renderer: injected, debugFrameOverlay, ...windowOptions } = options;
|
|
269
|
+
const slot = renderSlot();
|
|
270
|
+
const remount = slot.root != null;
|
|
271
|
+
if (!slot.renderer) {
|
|
272
|
+
if (injected) {
|
|
273
|
+
slot.renderer = injected;
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
const renderer = createRenderer();
|
|
277
|
+
renderer.init(windowOptions);
|
|
278
|
+
slot.renderer = renderer;
|
|
279
|
+
console.log("[gpuix] created native window");
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
const host = slot.renderer;
|
|
283
|
+
if (!host) {
|
|
284
|
+
throw new Error("GPUIX renderer is not initialized");
|
|
285
|
+
}
|
|
286
|
+
installRuntimeErrorHandlers();
|
|
287
|
+
if (!injected && host instanceof GpuixRenderer && !slot.loop) {
|
|
288
|
+
slot.loop = startFrameLoop(host, {
|
|
289
|
+
onTerminated: () => {
|
|
290
|
+
if (typeof process !== "undefined")
|
|
291
|
+
process.exit(0);
|
|
292
|
+
},
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
if (typeof window !== "undefined" &&
|
|
296
|
+
host instanceof GpuixRenderer &&
|
|
297
|
+
!Reflect.has(globalThis, BROWSER_AUTOMATION_KEY)) {
|
|
298
|
+
installBrowserAutomation(host);
|
|
299
|
+
}
|
|
300
|
+
if (debugFrameOverlay) {
|
|
301
|
+
host.setDebugFrameOverlay?.(debugFrameOverlay);
|
|
302
|
+
}
|
|
303
|
+
if (slot.root) {
|
|
304
|
+
console.log("[gpuix] remount: unmount previous tree");
|
|
305
|
+
}
|
|
306
|
+
slot.lastNode = node;
|
|
307
|
+
slot.lastOptions = {
|
|
308
|
+
onEvent,
|
|
309
|
+
onKeyDown,
|
|
310
|
+
onKeyUp,
|
|
311
|
+
onSelectionChange,
|
|
312
|
+
onAppearanceChange,
|
|
313
|
+
tabNavigation,
|
|
314
|
+
keyboardFocusDim,
|
|
315
|
+
};
|
|
316
|
+
const root = mountRoot({ slot, node, options: slot.lastOptions });
|
|
317
|
+
console.log(remount ? "[gpuix] remount complete" : "[gpuix] mount complete");
|
|
318
|
+
return root;
|
|
319
|
+
}
|
|
320
|
+
//# sourceMappingURL=renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer.js","sourceRoot":"","sources":["../../src/reconciler/renderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { TestRenderer, hasNativeTestRenderer, type TestWindowOptions } from "@ghia/native/testing";
|
|
3
|
+
import { type Root } from "./reconciler/reconciler.js";
|
|
4
|
+
import { type RootEventHandlers } from "@ghia/native/host";
|
|
5
|
+
export * from "@ghia/native/testing";
|
|
6
|
+
export interface TestRoot {
|
|
7
|
+
root: Root;
|
|
8
|
+
renderer: TestRenderer;
|
|
9
|
+
render: (node: ReactNode) => void;
|
|
10
|
+
unmount: () => void;
|
|
11
|
+
}
|
|
12
|
+
export declare function createTestRoot(options?: TestWindowOptions & Pick<RootEventHandlers, "onUncaughtError">): TestRoot;
|
|
13
|
+
export { TestRenderer, hasNativeTestRenderer };
|
|
14
|
+
//# sourceMappingURL=testing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,OAAO,EACL,YAAY,EACZ,qBAAqB,EACrB,KAAK,iBAAiB,EACvB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAyB,KAAK,IAAI,EAAE,MAAM,4BAA4B,CAAA;AAC7E,OAAO,EAEL,KAAK,iBAAiB,EAEvB,MAAM,mBAAmB,CAAA;AAG1B,cAAc,sBAAsB,CAAA;AAEpC,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,IAAI,CAAA;IACV,QAAQ,EAAE,YAAY,CAAA;IACtB,MAAM,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACjC,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAED,wBAAgB,cAAc,CAC5B,OAAO,GAAE,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,EAAE,iBAAiB,CAAM,GAC3E,QAAQ,CAkCV;AAED,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,CAAA"}
|
package/dist/testing.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { TestRenderer, hasNativeTestRenderer, } from "@ghia/native/testing";
|
|
2
|
+
import { createRoot, flushSync } from "./reconciler/reconciler.js";
|
|
3
|
+
import { createRendererState, } from "@ghia/native/host";
|
|
4
|
+
import { handleGpuixEvent } from "./reconciler/event-registry.js";
|
|
5
|
+
export * from "@ghia/native/testing";
|
|
6
|
+
export function createTestRoot(options = {}) {
|
|
7
|
+
let renderer;
|
|
8
|
+
renderer = new TestRenderer({
|
|
9
|
+
...options,
|
|
10
|
+
dispatchEvent: (event) => {
|
|
11
|
+
flushSync(() => handleGpuixEvent(event, renderer));
|
|
12
|
+
},
|
|
13
|
+
dispatchSyncEvent: (event) => {
|
|
14
|
+
let result;
|
|
15
|
+
flushSync(() => {
|
|
16
|
+
result = createRendererState(renderer).dispatchSync(event);
|
|
17
|
+
});
|
|
18
|
+
if (!result)
|
|
19
|
+
throw new Error("flushSync did not run the dispatch");
|
|
20
|
+
return result;
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
const root = createRoot(renderer, {
|
|
24
|
+
onKeyDown: options.onKeyDown,
|
|
25
|
+
onKeyUp: options.onKeyUp,
|
|
26
|
+
onSelectionChange: options.onSelectionChange,
|
|
27
|
+
onAppearanceChange: options.onAppearanceChange,
|
|
28
|
+
tabNavigation: options.tabNavigation,
|
|
29
|
+
keyboardFocusDim: options.keyboardFocusDim,
|
|
30
|
+
onUncaughtError: options.onUncaughtError,
|
|
31
|
+
});
|
|
32
|
+
const render = (node) => {
|
|
33
|
+
flushSync(() => root.render(node));
|
|
34
|
+
renderer.flush();
|
|
35
|
+
};
|
|
36
|
+
const unmount = () => {
|
|
37
|
+
root.unmount();
|
|
38
|
+
renderer.dispose();
|
|
39
|
+
};
|
|
40
|
+
return { root, renderer, render, unmount };
|
|
41
|
+
}
|
|
42
|
+
export { TestRenderer, hasNativeTestRenderer };
|
|
43
|
+
//# sourceMappingURL=testing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,YAAY,EACZ,qBAAqB,GAEtB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,UAAU,EAAE,SAAS,EAAa,MAAM,4BAA4B,CAAA;AAC7E,OAAO,EACL,mBAAmB,GAGpB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AAEjE,cAAc,sBAAsB,CAAA;AASpC,MAAM,UAAU,cAAc,CAC5B,UAA0E,EAAE;IAE5E,IAAI,QAAuB,CAAA;IAC3B,QAAQ,GAAG,IAAI,YAAY,CAAC;QAC1B,GAAG,OAAO;QACV,aAAa,EAAE,CAAC,KAAmB,EAAE,EAAE;YACrC,SAAS,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAA;QACpD,CAAC;QACD,iBAAiB,EAAE,CAAC,KAAmB,EAAE,EAAE;YACzC,IAAI,MAAsC,CAAA;YAC1C,SAAS,CAAC,GAAG,EAAE;gBACb,MAAM,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAA;YAC5D,CAAC,CAAC,CAAA;YACF,IAAI,CAAC,MAAM;gBAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;YAClE,OAAO,MAAM,CAAA;QACf,CAAC;KACF,CAAC,CAAA;IACF,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,EAAE;QAChC,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,iBAAiB,EAAE,OAAO,CAAC,iBAAiB;QAC5C,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;QAC9C,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;QAC1C,eAAe,EAAE,OAAO,CAAC,eAAe;KACzC,CAAC,CAAA;IACF,MAAM,MAAM,GAAG,CAAC,IAAe,EAAQ,EAAE;QACvC,SAAS,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;QAClC,QAAQ,CAAC,KAAK,EAAE,CAAA;IAClB,CAAC,CAAA;IACD,MAAM,OAAO,GAAG,GAAS,EAAE;QACzB,IAAI,CAAC,OAAO,EAAE,CAAA;QACd,QAAQ,CAAC,OAAO,EAAE,CAAA;IACpB,CAAC,CAAA;IACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,CAAA;AAC5C,CAAC;AAED,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,CAAA"}
|