pi-extension-utils 0.7.4 → 0.7.6
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/README.md +1 -1
- package/dist/src/ui/client.js +79 -8
- package/docs/client.md +5 -1
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/src/ui/client.js
CHANGED
|
@@ -14,6 +14,39 @@ export function createTuiModeCapture() {
|
|
|
14
14
|
},
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
|
+
function getLayoutRootTui(tui) {
|
|
18
|
+
if ((typeof tui !== "object" && typeof tui !== "function") || tui === null)
|
|
19
|
+
return undefined;
|
|
20
|
+
if (!("layoutRoot" in tui) || typeof tui.setLayoutRoot !== "function")
|
|
21
|
+
return undefined;
|
|
22
|
+
return tui;
|
|
23
|
+
}
|
|
24
|
+
// Pi 0.84 exposes setLayoutRoot() but no getter. Its TypeScript-private
|
|
25
|
+
// layoutRoot remains a runtime property; keep that compatibility bridge here.
|
|
26
|
+
function getLayoutRoot(tui) {
|
|
27
|
+
return tui.layoutRoot;
|
|
28
|
+
}
|
|
29
|
+
function createOverlayInputProxy(component) {
|
|
30
|
+
const target = component;
|
|
31
|
+
const proxy = {
|
|
32
|
+
render: () => [],
|
|
33
|
+
invalidate: () => target.invalidate?.(),
|
|
34
|
+
handleInput: (data) => target.handleInput?.(data),
|
|
35
|
+
get wantsKeyRelease() {
|
|
36
|
+
return target.wantsKeyRelease;
|
|
37
|
+
},
|
|
38
|
+
dispose: () => target.dispose?.(),
|
|
39
|
+
};
|
|
40
|
+
if (((typeof target === "object" && target !== null) || typeof target === "function") && "focused" in target) {
|
|
41
|
+
Object.defineProperty(proxy, "focused", {
|
|
42
|
+
get: () => target.focused,
|
|
43
|
+
set: (focused) => {
|
|
44
|
+
target.focused = focused;
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
return proxy;
|
|
49
|
+
}
|
|
17
50
|
export function createUiClient(fullscreen, ctx, capture = createTuiModeCapture()) {
|
|
18
51
|
return {
|
|
19
52
|
async fullscreen(factory) {
|
|
@@ -22,20 +55,53 @@ export function createUiClient(fullscreen, ctx, capture = createTuiModeCapture()
|
|
|
22
55
|
throw new Error("pi-extension-utils: ui.fullscreen requires an interactive UI (ctx.ui.custom is unavailable)");
|
|
23
56
|
}
|
|
24
57
|
const lease = fullscreen.acquire();
|
|
58
|
+
let restoreLayoutRoot;
|
|
59
|
+
let closed = false;
|
|
60
|
+
const close = () => {
|
|
61
|
+
closed = true;
|
|
62
|
+
restoreLayoutRoot?.();
|
|
63
|
+
};
|
|
25
64
|
try {
|
|
26
65
|
const wrapped = (tui, theme, keybindings, done) => {
|
|
27
66
|
capture.noteTui(tui);
|
|
28
|
-
|
|
67
|
+
const mount = (component) => {
|
|
68
|
+
const layoutTui = capture.isFullscreenTui() ? getLayoutRootTui(tui) : undefined;
|
|
69
|
+
if (!layoutTui)
|
|
70
|
+
return component;
|
|
71
|
+
if (closed)
|
|
72
|
+
return createOverlayInputProxy(component);
|
|
73
|
+
const priorRoot = getLayoutRoot(layoutTui);
|
|
74
|
+
let restored = false;
|
|
75
|
+
restoreLayoutRoot = () => {
|
|
76
|
+
if (restored)
|
|
77
|
+
return;
|
|
78
|
+
restored = true;
|
|
79
|
+
priorRoot?.invalidate?.();
|
|
80
|
+
layoutTui.setLayoutRoot(priorRoot);
|
|
81
|
+
layoutTui.requestRender?.(true);
|
|
82
|
+
};
|
|
83
|
+
layoutTui.setLayoutRoot(component);
|
|
84
|
+
layoutTui.requestRender?.(true);
|
|
85
|
+
return createOverlayInputProxy(component);
|
|
86
|
+
};
|
|
87
|
+
const component = factory(tui, theme, keybindings, (result) => {
|
|
88
|
+
close();
|
|
89
|
+
done(result);
|
|
90
|
+
});
|
|
91
|
+
if (component && typeof component.then === "function") {
|
|
92
|
+
return Promise.resolve(component).then(mount);
|
|
93
|
+
}
|
|
94
|
+
return mount(component);
|
|
29
95
|
};
|
|
30
96
|
// In the fullscreen TUI a plain custom component mounts inside the
|
|
31
|
-
// bottom dock
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
//
|
|
97
|
+
// bottom dock. Use the overlay path for focus/lifecycle, then let the
|
|
98
|
+
// wrapped factory replace a capable viewport TUI's layout root. The
|
|
99
|
+
// returned empty input proxy keeps the host overlay from rendering the
|
|
100
|
+
// same dashboard a second time.
|
|
35
101
|
// Before any wrapped factory has rendered, the mode is unknown. Default
|
|
36
102
|
// that cold-start case to an overlay: it is the only mount that remains
|
|
37
|
-
//
|
|
38
|
-
//
|
|
103
|
+
// safe in the alt-screen TUI. Preserve the legacy editor-slot mount only
|
|
104
|
+
// when regular mode was positively seen.
|
|
39
105
|
const options = capture.isRegularTui()
|
|
40
106
|
? undefined
|
|
41
107
|
: {
|
|
@@ -45,7 +111,12 @@ export function createUiClient(fullscreen, ctx, capture = createTuiModeCapture()
|
|
|
45
111
|
return await ui.custom(wrapped, options);
|
|
46
112
|
}
|
|
47
113
|
finally {
|
|
48
|
-
|
|
114
|
+
try {
|
|
115
|
+
close();
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
lease.release();
|
|
119
|
+
}
|
|
49
120
|
}
|
|
50
121
|
},
|
|
51
122
|
};
|
package/docs/client.md
CHANGED
|
@@ -44,9 +44,13 @@ await client.ui.fullscreen((tui, theme, keybindings, done) => new MyComponent(tu
|
|
|
44
44
|
|
|
45
45
|
- acquires a fullscreen lease
|
|
46
46
|
- blanks coordinated widgets
|
|
47
|
-
-
|
|
47
|
+
- preserves the regular-TUI editor-slot mount
|
|
48
|
+
- temporarily replaces a capable fullscreen viewport TUI's layout root with the dashboard; restoration invalidates the prior root when supported, reinstalls that exact root, then forces a redraw
|
|
49
|
+
- uses the overlay path as the safe cold-start/fallback mount without rendering the real dashboard twice
|
|
48
50
|
- releases the lease in `finally`
|
|
49
51
|
|
|
52
|
+
Pi 0.84.x exposes the layout-root setter but no public getter, so exact restoration uses its runtime `layoutRoot` property through an isolated structural bridge. If a fullscreen TUI does not expose that setter/property shape, `ui.fullscreen()` safely falls back to the full-size overlay; that fallback cannot guarantee that terminal image placements from the transcript are cleared.
|
|
53
|
+
|
|
50
54
|
Use `client.fullscreen.acquire()` only when you need manual lease control.
|
|
51
55
|
|
|
52
56
|
## Pane overlay
|