pi-extension-utils 0.7.5 → 0.7.7
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/dist/src/ui/client.js +1 -0
- package/dist/src/widgets/client.js +72 -10
- package/docs/client.md +1 -1
- package/docs/widgets.md +1 -1
- package/package.json +1 -1
package/dist/src/ui/client.js
CHANGED
|
@@ -22,11 +22,59 @@ export function connectWidgetCoordinator(pi, opts) {
|
|
|
22
22
|
factory: record.factory,
|
|
23
23
|
});
|
|
24
24
|
}
|
|
25
|
+
function emitHello() {
|
|
26
|
+
pi.events.emit(EVENTS.hello, basePayload(clientId));
|
|
27
|
+
}
|
|
28
|
+
function createWidgetRecord(placement, key, factory, order) {
|
|
29
|
+
const record = {
|
|
30
|
+
placement,
|
|
31
|
+
key,
|
|
32
|
+
factory,
|
|
33
|
+
fallbackFactory: (tui, theme) => {
|
|
34
|
+
const mount = {
|
|
35
|
+
tui,
|
|
36
|
+
theme,
|
|
37
|
+
component: record.factory(tui, theme),
|
|
38
|
+
disposed: false,
|
|
39
|
+
};
|
|
40
|
+
record.fallbackMount = mount;
|
|
41
|
+
return {
|
|
42
|
+
render: (width) => (mount.disposed ? [] : mount.component.render(width)),
|
|
43
|
+
invalidate: () => {
|
|
44
|
+
if (!mount.disposed)
|
|
45
|
+
mount.component.invalidate?.();
|
|
46
|
+
},
|
|
47
|
+
dispose: () => {
|
|
48
|
+
if (mount.disposed)
|
|
49
|
+
return;
|
|
50
|
+
mount.disposed = true;
|
|
51
|
+
mount.component.dispose?.();
|
|
52
|
+
if (record.fallbackMount === mount)
|
|
53
|
+
record.fallbackMount = undefined;
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
order,
|
|
58
|
+
};
|
|
59
|
+
return record;
|
|
60
|
+
}
|
|
61
|
+
function updateFallback(record) {
|
|
62
|
+
const mount = record.fallbackMount;
|
|
63
|
+
if (!mount || mount.disposed) {
|
|
64
|
+
restoreFallback(record);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
mount.disposed = true;
|
|
68
|
+
mount.component.dispose?.();
|
|
69
|
+
mount.component = record.factory(mount.tui, mount.theme);
|
|
70
|
+
mount.disposed = false;
|
|
71
|
+
mount.tui?.requestRender?.();
|
|
72
|
+
}
|
|
25
73
|
function clearFallback(record) {
|
|
26
74
|
opts.ctx.ui.setWidget(record.key, undefined, { placement: record.placement });
|
|
27
75
|
}
|
|
28
76
|
function restoreFallback(record) {
|
|
29
|
-
opts.ctx.ui.setWidget(record.key, record.
|
|
77
|
+
opts.ctx.ui.setWidget(record.key, record.fallbackFactory, { placement: record.placement });
|
|
30
78
|
}
|
|
31
79
|
function attach() {
|
|
32
80
|
if (disposed || coordinated)
|
|
@@ -45,7 +93,7 @@ export function connectWidgetCoordinator(pi, opts) {
|
|
|
45
93
|
return;
|
|
46
94
|
attach();
|
|
47
95
|
});
|
|
48
|
-
|
|
96
|
+
emitHello();
|
|
49
97
|
const fullscreen = {
|
|
50
98
|
acquire() {
|
|
51
99
|
const token = `${clientId}-lease-${nextLeaseId++}`;
|
|
@@ -59,6 +107,8 @@ export function connectWidgetCoordinator(pi, opts) {
|
|
|
59
107
|
for (const record of widgets.values())
|
|
60
108
|
clearFallback(record);
|
|
61
109
|
}
|
|
110
|
+
if (!coordinated)
|
|
111
|
+
emitHello();
|
|
62
112
|
return {
|
|
63
113
|
release() {
|
|
64
114
|
if (released)
|
|
@@ -84,19 +134,31 @@ export function connectWidgetCoordinator(pi, opts) {
|
|
|
84
134
|
set(placement, key, factory, setOpts = {}) {
|
|
85
135
|
if (disposed)
|
|
86
136
|
return;
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
137
|
+
const id = widgetId(placement, key);
|
|
138
|
+
const wrappedFactory = opts.tui ? withTuiCapture(factory, opts.tui) : factory;
|
|
139
|
+
let record = widgets.get(id);
|
|
140
|
+
const isNew = !record;
|
|
141
|
+
if (record) {
|
|
142
|
+
record.factory = wrappedFactory;
|
|
143
|
+
record.order = setOpts.order ?? 0;
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
record = createWidgetRecord(placement, key, wrappedFactory, setOpts.order ?? 0);
|
|
147
|
+
widgets.set(id, record);
|
|
148
|
+
}
|
|
94
149
|
if (coordinated) {
|
|
95
150
|
emitRegister(record);
|
|
96
151
|
}
|
|
97
152
|
else if (leases.size === 0) {
|
|
98
|
-
|
|
153
|
+
if (isNew) {
|
|
154
|
+
restoreFallback(record);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
updateFallback(record);
|
|
158
|
+
}
|
|
99
159
|
}
|
|
160
|
+
if (!coordinated)
|
|
161
|
+
emitHello();
|
|
100
162
|
},
|
|
101
163
|
remove(placement, key) {
|
|
102
164
|
const id = widgetId(placement, key);
|
package/docs/client.md
CHANGED
|
@@ -45,7 +45,7 @@ await client.ui.fullscreen((tui, theme, keybindings, done) => new MyComponent(tu
|
|
|
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
|
|
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
49
|
- uses the overlay path as the safe cold-start/fallback mount without rendering the real dashboard twice
|
|
50
50
|
- releases the lease in `finally`
|
|
51
51
|
|
package/docs/widgets.md
CHANGED
|
@@ -50,7 +50,7 @@ await client.ui.fullscreen((tui, theme, keybindings, done) => new MyComponent(tu
|
|
|
50
50
|
|
|
51
51
|
## Fallback
|
|
52
52
|
|
|
53
|
-
If the host is not ready yet, widget
|
|
53
|
+
If the host is not ready yet, each logical widget registers one stable proxy through the extension's own `ctx.ui.setWidget`. Later `widgets.set` calls replace the proxy's delegated component and request a redraw without re-registering the raw widget, preserving cross-extension insertion order on Pi versions that delete before setting. Set and fullscreen-acquire activity also retry the hello handshake without a polling timer. When the host announces readiness, the client clears the fallback widget and re-registers through the coordinator.
|
|
54
54
|
|
|
55
55
|
## Example
|
|
56
56
|
|