@voltius/plugin-types 0.15.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 +21 -0
- package/README.md +27 -0
- package/index.d.ts +738 -0
- package/package.json +37 -0
- package/ui.d.ts +9 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Voltius
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# @voltius/plugin-types
|
|
2
|
+
|
|
3
|
+
TypeScript definitions for the [Voltius](https://github.com/VoltiusApp/voltius) plugin API.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install --save-dev @voltius/plugin-types
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import type { PluginAPI } from "@voltius/plugin-types";
|
|
11
|
+
|
|
12
|
+
export default function register(api: PluginAPI): () => void {
|
|
13
|
+
const dispose = api.ui.registerRightPanelSection({ /* ... */ });
|
|
14
|
+
return () => dispose();
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Types only — there is no runtime code. The host provides the implementation.
|
|
19
|
+
|
|
20
|
+
**Versions track the app.** `@voltius/plugin-types@0.14.1` describes the API in Voltius 0.14.1.
|
|
21
|
+
|
|
22
|
+
`ui.d.ts` declares the `@voltius/ui` module (the host components plugins may import). It is
|
|
23
|
+
included automatically; you do not need to reference it.
|
|
24
|
+
|
|
25
|
+
Generated from `src/plugins/api.ts` — see
|
|
26
|
+
[developing plugins](https://docs.voltius.app/plugins/developing) and the
|
|
27
|
+
[template repo](https://github.com/VoltiusApp/voltius-plugin-template).
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,738 @@
|
|
|
1
|
+
// GENERATED by scripts/gen-plugin-types.mjs — do not edit by hand.
|
|
2
|
+
// Source of truth: src/plugins/api.ts in VoltiusApp/voltius.
|
|
3
|
+
/// <reference path="./ui.d.ts" />
|
|
4
|
+
import type { ReactNode } from "react";
|
|
5
|
+
|
|
6
|
+
export interface SerialConnectParams {
|
|
7
|
+
sessionId: string;
|
|
8
|
+
port: string;
|
|
9
|
+
baud: number;
|
|
10
|
+
dataBits?: number;
|
|
11
|
+
parity?: string;
|
|
12
|
+
stopBits?: number;
|
|
13
|
+
flowControl?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface JumpHost {
|
|
17
|
+
id: string;
|
|
18
|
+
// Live reference to a managed connection. Host/port/username/credentials are
|
|
19
|
+
// resolved dynamically from this connection at use time — see resolveJumpHosts.
|
|
20
|
+
connection_id: string;
|
|
21
|
+
// Snapshot fields, kept only as a fallback when the referenced connection is
|
|
22
|
+
// missing (deleted) or for jump hosts imported from external formats (e.g.
|
|
23
|
+
// Termius) that have no managed connection. Not written for managed references.
|
|
24
|
+
host?: string;
|
|
25
|
+
port?: number;
|
|
26
|
+
username?: string;
|
|
27
|
+
identity_id?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface TerminalTheme {
|
|
31
|
+
background: string;
|
|
32
|
+
foreground: string;
|
|
33
|
+
cursor: string;
|
|
34
|
+
selectionBackground: string;
|
|
35
|
+
black: string; red: string; green: string; yellow: string;
|
|
36
|
+
blue: string; magenta: string; cyan: string; white: string;
|
|
37
|
+
brightBlack: string; brightRed: string; brightGreen: string;
|
|
38
|
+
brightYellow: string; brightBlue: string; brightMagenta: string;
|
|
39
|
+
brightCyan: string; brightWhite: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface UITheme {
|
|
43
|
+
bgTerminal: string; // titlebar + terminal bg
|
|
44
|
+
bgStatusBar: string; // terminal status bar bg
|
|
45
|
+
bgBase: string; // homepage/main bg
|
|
46
|
+
bgToolbar: string; // toolbar/sidebar surfaces
|
|
47
|
+
bgCard: string; // host cards
|
|
48
|
+
bgCardHover: string; // host cards hovered
|
|
49
|
+
bgCardAvatar: string; // host card default avatar bg
|
|
50
|
+
bgInput: string; // inputs/search
|
|
51
|
+
bgInputHover: string; // buttons/inputs hovered
|
|
52
|
+
bgElevated: string; // hover states / elevated surfaces
|
|
53
|
+
bgModal: string; // omni/modal bg
|
|
54
|
+
border: string;
|
|
55
|
+
borderHover: string;
|
|
56
|
+
textDim: string; // dimmest (placeholders)
|
|
57
|
+
textMuted: string; // icons, secondary
|
|
58
|
+
textSecondary: string;
|
|
59
|
+
textPrimary: string;
|
|
60
|
+
textBright: string;
|
|
61
|
+
accent: string;
|
|
62
|
+
accentHover: string;
|
|
63
|
+
tabBg: string; // inactive SSH tab background
|
|
64
|
+
tabActiveBg: string;
|
|
65
|
+
tabActiveText: string;
|
|
66
|
+
tabActiveBorder: string;
|
|
67
|
+
vaultTabBg: string; // vault/home tab — inactive background
|
|
68
|
+
vaultTabActiveBg: string; // vault/home tab — active background
|
|
69
|
+
statusConnected: string;
|
|
70
|
+
statusError: string;
|
|
71
|
+
statusConnecting: string;
|
|
72
|
+
statusWarning: string;
|
|
73
|
+
textNotice: string; // notice/info boxes text and icon
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface AppTheme {
|
|
77
|
+
id: string;
|
|
78
|
+
name: string;
|
|
79
|
+
builtIn: boolean;
|
|
80
|
+
uiFontFamily: string;
|
|
81
|
+
uiFontSize: number;
|
|
82
|
+
terminalFontFamily: string;
|
|
83
|
+
terminalFontSize: number;
|
|
84
|
+
ui: UITheme;
|
|
85
|
+
terminal: TerminalTheme;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export type Locale = "en" | "fr" | "ru" | "zh";
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
// ─── Types exposés aux plugins ─────────────────────────────────────────────
|
|
92
|
+
|
|
93
|
+
export interface PluginConnection {
|
|
94
|
+
id: string;
|
|
95
|
+
name?: string;
|
|
96
|
+
host: string;
|
|
97
|
+
port: number;
|
|
98
|
+
username: string;
|
|
99
|
+
auth_type: "password" | "key";
|
|
100
|
+
tags: string[];
|
|
101
|
+
identity_id?: string;
|
|
102
|
+
jump_hosts?: JumpHost[];
|
|
103
|
+
// Display-only fields — already present at runtime (runtime.ts:389 returns
|
|
104
|
+
// full Connection records cast to PluginConnection[]); exposed here so the
|
|
105
|
+
// agent UI can render a real per-host avatar. Optional and additive.
|
|
106
|
+
connection_type?: "ssh" | "serial" | "ftp";
|
|
107
|
+
icon?: string;
|
|
108
|
+
distro?: string;
|
|
109
|
+
serial_port?: string;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface PluginConnectionInput {
|
|
113
|
+
name?: string;
|
|
114
|
+
host: string;
|
|
115
|
+
port: number;
|
|
116
|
+
username: string;
|
|
117
|
+
auth_type: "password" | "key";
|
|
118
|
+
tags?: string[];
|
|
119
|
+
identity_id?: string;
|
|
120
|
+
jump_hosts?: JumpHost[];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export interface PluginKey {
|
|
124
|
+
id: string;
|
|
125
|
+
name?: string;
|
|
126
|
+
key_type?: string;
|
|
127
|
+
tags: string[];
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export interface PluginIdentity {
|
|
131
|
+
id: string;
|
|
132
|
+
name?: string;
|
|
133
|
+
username: string;
|
|
134
|
+
key_id?: string;
|
|
135
|
+
tags: string[];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export interface OmniCommand {
|
|
139
|
+
id: string;
|
|
140
|
+
label: string;
|
|
141
|
+
icon: string;
|
|
142
|
+
keywords?: string[];
|
|
143
|
+
section?: string;
|
|
144
|
+
/** Optional keyboard shortcut. Format: "ctrl+k", "meta+shift+p". First-registered wins on conflict. */
|
|
145
|
+
keybinding?: string;
|
|
146
|
+
/** ID of a core shortcut to resolve as the hint (reactive, updates when user rebinds). */
|
|
147
|
+
shortcutId?: string;
|
|
148
|
+
execute: () => void | Promise<void>;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** A label that may be a function, re-resolved by the host on locale change.
|
|
152
|
+
* A plain string is frozen at registration time. */
|
|
153
|
+
export type PluginLabel = string | (() => string);
|
|
154
|
+
|
|
155
|
+
export interface SettingsPage {
|
|
156
|
+
id: string;
|
|
157
|
+
label: PluginLabel;
|
|
158
|
+
icon: string;
|
|
159
|
+
component: React.FC;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export interface RightPanelSection {
|
|
163
|
+
id: string;
|
|
164
|
+
label: PluginLabel;
|
|
165
|
+
icon: string;
|
|
166
|
+
component: React.FC;
|
|
167
|
+
/** Opt-in: this section drives the terminal status bar's high-CPU indicator
|
|
168
|
+
* and its metrics stream. Explicit flag rather than an id check, so a plugin
|
|
169
|
+
* can't inherit the host integration by squatting another plugin's section id. */
|
|
170
|
+
providesHostMetrics?: boolean;
|
|
171
|
+
/** Opt-in: this section owns an in-panel search bar that Ctrl+F should focus
|
|
172
|
+
* when the section is open, via the "voltius:focus-panel-search" event. */
|
|
173
|
+
providesPanelSearch?: boolean;
|
|
174
|
+
/** Rail position, ascending. Sections without one sort last; ties break on `id`.
|
|
175
|
+
* Registration order is NOT stable — it follows the on-disk read order of the
|
|
176
|
+
* seeded plugin directory and changes after any uninstall/reinstall — so a
|
|
177
|
+
* section that wants a fixed rail slot must declare it here. */
|
|
178
|
+
order?: number;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** Nav-stack entries a plugin may push via `pushMobileScreen`. Each member's
|
|
182
|
+
* `kind` must exist as a "panel-<kind>" variant of mobileNavCore's MobileScreen
|
|
183
|
+
* union — runtime.ts's translator switch is exhaustively checked against that
|
|
184
|
+
* union, so adding a member here without a matching host variant is a type
|
|
185
|
+
* error, not a silent no-op at runtime. */
|
|
186
|
+
export type PluginMobileNavEntry = {
|
|
187
|
+
kind: "docker-logs";
|
|
188
|
+
sessionId: string;
|
|
189
|
+
containerId: string;
|
|
190
|
+
containerName: string;
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
/** Props the host passes into a registered mobile screen's `render`. Extra
|
|
194
|
+
* navigation params (e.g. docker-logs' containerId/containerName) ride along
|
|
195
|
+
* as additional keys — see `pushMobileScreen`. */
|
|
196
|
+
export interface MobileScreenProps {
|
|
197
|
+
sessionId: string;
|
|
198
|
+
/** Pop this screen off the mobile nav stack. MobilePanelHeader itself can't
|
|
199
|
+
* cross the plugin boundary (it reaches into the host's nav store), so the
|
|
200
|
+
* screen must render its own header chrome and wire this to its back button. */
|
|
201
|
+
onBack: () => void;
|
|
202
|
+
[key: string]: unknown;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export interface MobileScreen {
|
|
206
|
+
id: string;
|
|
207
|
+
/** Screen key MobileShell looks up on navigation, e.g. "docker", "metrics". */
|
|
208
|
+
kind: string;
|
|
209
|
+
render: React.FC<MobileScreenProps>;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export interface GlobalPanel {
|
|
213
|
+
id: string;
|
|
214
|
+
/** Rendered at shell level (not session-scoped). Host drives open/close. */
|
|
215
|
+
component: React.FC<{ open: boolean; onClose: () => void }>;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export interface PluginSession {
|
|
219
|
+
id: string;
|
|
220
|
+
connectionId: string;
|
|
221
|
+
connectionName: string;
|
|
222
|
+
status: string;
|
|
223
|
+
type: string;
|
|
224
|
+
/** Local sessions only: the shell path/name to use for a spawned exec PTY. */
|
|
225
|
+
localShell?: string;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export type PluginTheme = AppTheme;
|
|
229
|
+
|
|
230
|
+
// ─── Notification types ────────────────────────────────────────────────────
|
|
231
|
+
|
|
232
|
+
export type ToastSeverity = 'info' | 'success' | 'warning' | 'error';
|
|
233
|
+
|
|
234
|
+
export interface ToastOptions {
|
|
235
|
+
severity?: ToastSeverity;
|
|
236
|
+
duration?: number;
|
|
237
|
+
action?: { label: string; onClick: () => void };
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export interface ProgressOptions {
|
|
241
|
+
indeterminate?: boolean;
|
|
242
|
+
cancellable?: boolean;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export interface ProgressHandle {
|
|
246
|
+
update(value: number, message?: string): void;
|
|
247
|
+
finish(message?: string): void;
|
|
248
|
+
error(message: string): void;
|
|
249
|
+
cancel(): void;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export interface BannerOptions {
|
|
253
|
+
severity?: ToastSeverity;
|
|
254
|
+
actions?: Array<{ label: string; onClick: () => void }>;
|
|
255
|
+
dismissable?: boolean;
|
|
256
|
+
flashToast?: boolean;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
export interface BannerHandle {
|
|
260
|
+
dismiss(): void;
|
|
261
|
+
update(message: string): void;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// ─── UI Contribution types ─────────────────────────────────────────────────
|
|
265
|
+
|
|
266
|
+
/** A single action item contributed by a plugin to a UI slot. */
|
|
267
|
+
export interface ContributedAction {
|
|
268
|
+
label: string;
|
|
269
|
+
icon?: string;
|
|
270
|
+
onClick: () => void;
|
|
271
|
+
divider?: boolean;
|
|
272
|
+
danger?: boolean;
|
|
273
|
+
/** Keyboard shortcut hint displayed on the right in context menus */
|
|
274
|
+
shortcut?: string;
|
|
275
|
+
/** If provided, item is only shown when this returns true. Errors are treated as false. */
|
|
276
|
+
when?: (context: unknown) => boolean;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/** Named UI slots where plugins can inject actions. */
|
|
280
|
+
export type UISlot =
|
|
281
|
+
| "connection.contextMenu"
|
|
282
|
+
| "connection.panelActions"
|
|
283
|
+
| "key.contextMenu"
|
|
284
|
+
| "key.panelActions"
|
|
285
|
+
| "identity.contextMenu"
|
|
286
|
+
| "identity.panelActions"
|
|
287
|
+
| "portForwardingRule.contextMenu"
|
|
288
|
+
| "home.bgContextMenu"
|
|
289
|
+
| "keychain.bgContextMenu"
|
|
290
|
+
| "home.toolbar.hostMenu"
|
|
291
|
+
| "settings.vaults";
|
|
292
|
+
|
|
293
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
294
|
+
export type UIContributionFactory = (ctx: any) => ContributedAction[];
|
|
295
|
+
|
|
296
|
+
export type UIStatusBarSlot = "terminal.statusBar.right" | "titlebar.right";
|
|
297
|
+
|
|
298
|
+
export interface TerminalStatusBarContributionContext {
|
|
299
|
+
sessionId: string;
|
|
300
|
+
sessionType: "ssh" | "local" | "serial";
|
|
301
|
+
connectionId: string;
|
|
302
|
+
connectionName?: string;
|
|
303
|
+
sessionStatus: "connecting" | "connected" | "disconnected" | "error";
|
|
304
|
+
connection?: PluginConnection;
|
|
305
|
+
serialConfig?: SerialConnectParams;
|
|
306
|
+
dimensions?: { cols: number; rows: number };
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export type UIStatusBarContributionFactory = (ctx: TerminalStatusBarContributionContext) => ReactNode;
|
|
310
|
+
|
|
311
|
+
export type StreamKind = "metrics" | "processes" | "docker-logs" | "docker-stack-logs";
|
|
312
|
+
|
|
313
|
+
export interface StreamsAPI {
|
|
314
|
+
/** Start a session-scoped stream. Returns a streamId. */
|
|
315
|
+
start(kind: StreamKind, opts: Record<string, unknown>): Promise<string>;
|
|
316
|
+
/** Stop a stream. No-op for an unknown id. */
|
|
317
|
+
stop(streamId: string): Promise<void>;
|
|
318
|
+
/** Subscribe to a started stream's snapshots. Resolves to an unsubscribe fn. */
|
|
319
|
+
on<T>(streamId: string, cb: (snapshot: T) => void): Promise<() => void>;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/** Host metrics — built on top of api.streams' "metrics" kind. GATED (metrics:read). */
|
|
323
|
+
export interface MetricsAPI {
|
|
324
|
+
start(sessionId: string, isRemote: boolean): Promise<string>;
|
|
325
|
+
stop(streamId: string): Promise<void>;
|
|
326
|
+
onSnapshot<T>(streamId: string, cb: (snapshot: T) => void): Promise<() => void>;
|
|
327
|
+
getSystemInfo(sessionId: string, sessionType: string, sessionName?: string): Promise<unknown>;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/** Process listing/kill — built on top of api.streams' "processes" kind. GATED, split
|
|
331
|
+
* two ways: processes:read covers start/onSnapshot/stop; processes:manage covers kill. */
|
|
332
|
+
export interface ProcessesAPI {
|
|
333
|
+
start(sessionId: string, isRemote: boolean): Promise<string>;
|
|
334
|
+
stop(streamId: string): Promise<void>;
|
|
335
|
+
onSnapshot<T>(streamId: string, cb: (snapshot: T) => void): Promise<() => void>;
|
|
336
|
+
kill(sessionId: string, pid: number, isRemote: boolean, force: boolean): Promise<void>;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/** Not gated — a pure KDF over caller-supplied input, grants no access to host secrets. */
|
|
340
|
+
export interface CryptoAPI {
|
|
341
|
+
/** Derive a 32-byte key from a passphrase and hex salt. Returns hex. */
|
|
342
|
+
deriveKey(passphrase: string, saltHex: string): Promise<string>;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/** Locales the host ships. A plugin's catalog may cover any subset — "en" should
|
|
346
|
+
* always be present, since it is the fallback when the active locale is missing.
|
|
347
|
+
* Re-exports the host's own `Locale` union (type-only, erased at build — this
|
|
348
|
+
* doesn't pull `@/stores/localeStore` into the plugin bundle) so a future host
|
|
349
|
+
* locale addition flows through here automatically instead of drifting out of sync. */
|
|
350
|
+
export type PluginLocale = Locale;
|
|
351
|
+
|
|
352
|
+
/** A flat key → template map for one locale. Values may contain "{{var}}" placeholders. */
|
|
353
|
+
export type PluginLocaleCatalog = Record<string, string>;
|
|
354
|
+
|
|
355
|
+
export type PluginI18nCatalog = Partial<Record<PluginLocale, PluginLocaleCatalog>>;
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Not gated — reading/resolving UI strings grants no host access. Each plugin owns
|
|
359
|
+
* its own catalog (registered here, not in the host's locale files) so a third-party
|
|
360
|
+
* plugin can ship translations exactly the way a first-party one does.
|
|
361
|
+
*/
|
|
362
|
+
export interface I18nAPI {
|
|
363
|
+
/** Register (or replace) this plugin's translation catalog. Call once at load,
|
|
364
|
+
* before rendering anything that resolves keys. */
|
|
365
|
+
register(catalog: PluginI18nCatalog): void;
|
|
366
|
+
/** Resolve `key` against the host's active locale. Falls back to the "en" entry,
|
|
367
|
+
* then to `key` itself (visible, never blank) if neither has it. */
|
|
368
|
+
t(key: string, vars?: Record<string, string | number>): string;
|
|
369
|
+
/** The host's current active locale. */
|
|
370
|
+
getLocale(): PluginLocale;
|
|
371
|
+
/** Fires whenever the host's active locale changes. Re-call `t()` and re-render
|
|
372
|
+
* on each firing — this does not itself trigger a React re-render. Returns an
|
|
373
|
+
* unsubscribe function. */
|
|
374
|
+
onLocaleChange(cb: (locale: PluginLocale) => void): () => void;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/** Proxmox VE LXC management. GATED, split two ways: proxmox:read covers
|
|
378
|
+
* list/snapshots.list; proxmox:manage covers everything else. Only functions
|
|
379
|
+
* against SSH sessions. */
|
|
380
|
+
export interface ProxmoxAPI {
|
|
381
|
+
lxc: {
|
|
382
|
+
list(sessionId: string): Promise<unknown[]>;
|
|
383
|
+
action(sessionId: string, vmid: number, action: string): Promise<void>;
|
|
384
|
+
/** Opens a pct-exec shell into the container and returns the new session's id.
|
|
385
|
+
* vmName is display-only — used for the resulting terminal tab's label. */
|
|
386
|
+
openShell(sessionId: string, vmid: number, vmName?: string): Promise<string>;
|
|
387
|
+
snapshots: {
|
|
388
|
+
list(sessionId: string, vmid: number): Promise<unknown[]>;
|
|
389
|
+
create(sessionId: string, vmid: number, name: string, description?: string): Promise<void>;
|
|
390
|
+
rollback(sessionId: string, vmid: number, name: string): Promise<void>;
|
|
391
|
+
remove(sessionId: string, vmid: number, name: string): Promise<void>;
|
|
392
|
+
};
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/** Where a docker command runs. Replaces the repeated (sessionId, isRemote, localShell)
|
|
397
|
+
* triple the underlying commands take — a transposed boolean in a positional call is
|
|
398
|
+
* silent; this shape makes every call site self-describing and tsc-checked. */
|
|
399
|
+
export interface DockerTarget {
|
|
400
|
+
sessionId: string;
|
|
401
|
+
isRemote: boolean;
|
|
402
|
+
localShell: string | null;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Docker container/image/volume/network/stack management. GATED, split two ways
|
|
407
|
+
* (kipavy ruling): docker:read covers every list/services/checkUpdate verb and all
|
|
408
|
+
* of logs.*; docker:manage covers everything that mutates or destroys, including
|
|
409
|
+
* exec.open (an interactive shell inside a container is full control, not a read).
|
|
410
|
+
*/
|
|
411
|
+
export interface DockerAPI {
|
|
412
|
+
containers: {
|
|
413
|
+
list(t: DockerTarget): Promise<unknown[]>;
|
|
414
|
+
action(t: DockerTarget, containerId: string, action: string): Promise<void>;
|
|
415
|
+
/** Reconstructs the `docker run` command for the container. `command` is the
|
|
416
|
+
* container's image ref, passed through to the backend command as `image`. */
|
|
417
|
+
runCommand(t: DockerTarget, containerId: string, command: string): Promise<string>;
|
|
418
|
+
};
|
|
419
|
+
images: {
|
|
420
|
+
list(t: DockerTarget): Promise<unknown[]>;
|
|
421
|
+
remove(t: DockerTarget, imageId: string): Promise<void>;
|
|
422
|
+
pull(t: DockerTarget, image: string): Promise<void>;
|
|
423
|
+
checkUpdate(t: DockerTarget, imageId: string): Promise<unknown>;
|
|
424
|
+
/** Pulls `image` and, when `recreate` is set, recreates the containers using it. */
|
|
425
|
+
update(t: DockerTarget, imageId: string, recreate: boolean): Promise<unknown>;
|
|
426
|
+
recreateContainers(t: DockerTarget, imageId: string): Promise<unknown>;
|
|
427
|
+
prune(t: DockerTarget): Promise<string>;
|
|
428
|
+
};
|
|
429
|
+
volumes: {
|
|
430
|
+
list(t: DockerTarget): Promise<unknown[]>;
|
|
431
|
+
remove(t: DockerTarget, name: string): Promise<void>;
|
|
432
|
+
prune(t: DockerTarget): Promise<string>;
|
|
433
|
+
};
|
|
434
|
+
networks: {
|
|
435
|
+
list(t: DockerTarget): Promise<unknown[]>;
|
|
436
|
+
remove(t: DockerTarget, id: string): Promise<void>;
|
|
437
|
+
prune(t: DockerTarget): Promise<string>;
|
|
438
|
+
};
|
|
439
|
+
stacks: {
|
|
440
|
+
list(t: DockerTarget): Promise<unknown[]>;
|
|
441
|
+
services(t: DockerTarget, stack: string): Promise<unknown[]>;
|
|
442
|
+
action(t: DockerTarget, stack: string, action: string): Promise<void>;
|
|
443
|
+
update(t: DockerTarget, stack: string): Promise<void>;
|
|
444
|
+
};
|
|
445
|
+
logs: {
|
|
446
|
+
start(t: DockerTarget, containerId: string, tail: number): Promise<string>;
|
|
447
|
+
startStack(t: DockerTarget, stack: string, tail: number): Promise<string>;
|
|
448
|
+
stop(streamId: string): Promise<void>;
|
|
449
|
+
/** Payload is a DockerLogLine ({ line, stream }), not a bare string — kept generic like StreamsAPI.on. */
|
|
450
|
+
on<T>(streamId: string, cb: (payload: T) => void): Promise<() => void>;
|
|
451
|
+
};
|
|
452
|
+
system: { prune(t: DockerTarget): Promise<string> };
|
|
453
|
+
exec: {
|
|
454
|
+
/** Opens an interactive shell into the container and returns the new session's id.
|
|
455
|
+
* containerName is display-only — used for the resulting terminal tab's label. */
|
|
456
|
+
open(t: DockerTarget, containerId: string, containerName?: string): Promise<string>;
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// ─── API principale ────────────────────────────────────────────────────────
|
|
461
|
+
|
|
462
|
+
export interface PluginAPI {
|
|
463
|
+
pluginId: string;
|
|
464
|
+
/** Returns true if this plugin is currently enabled in the registry. */
|
|
465
|
+
isActive(): boolean;
|
|
466
|
+
|
|
467
|
+
// SSH keys (requires keys:*)
|
|
468
|
+
keys: {
|
|
469
|
+
list(): Promise<PluginKey[]>;
|
|
470
|
+
/** Creates a key entry and stores private/public content in the vault. */
|
|
471
|
+
create(data: { name?: string; key_type?: string; tags?: string[] }, privateKey: string, publicKey?: string): Promise<PluginKey>;
|
|
472
|
+
delete(id: string): Promise<void>;
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
// Identities (requires identities:*)
|
|
476
|
+
identities: {
|
|
477
|
+
list(): Promise<PluginIdentity[]>;
|
|
478
|
+
create(data: { name?: string; username: string; key_id?: string; tags?: string[] }): Promise<PluginIdentity>;
|
|
479
|
+
delete(id: string): Promise<void>;
|
|
480
|
+
};
|
|
481
|
+
|
|
482
|
+
// Connections (requires connections:*)
|
|
483
|
+
connections: {
|
|
484
|
+
list(): Promise<PluginConnection[]>;
|
|
485
|
+
get(id: string): Promise<PluginConnection | null>;
|
|
486
|
+
create(data: PluginConnectionInput): Promise<PluginConnection>;
|
|
487
|
+
update(id: string, data: Partial<PluginConnectionInput>): Promise<void>;
|
|
488
|
+
delete(id: string): Promise<void>;
|
|
489
|
+
bulkImport(items: PluginConnectionInput[]): Promise<PluginConnection[]>;
|
|
490
|
+
subscribe(cb: (connections: PluginConnection[]) => void): () => void;
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
// Vault — plugin-scoped secrets (requires vault:*)
|
|
494
|
+
vault: {
|
|
495
|
+
get(key: string): Promise<string | null>;
|
|
496
|
+
set(key: string, value: string): Promise<void>;
|
|
497
|
+
delete(key: string): Promise<void>;
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
// Themes (requires "themes")
|
|
501
|
+
themes: {
|
|
502
|
+
register(theme: PluginTheme): void;
|
|
503
|
+
unregister(id: string): void;
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
// OmniSearch (requires "omni-commands")
|
|
507
|
+
omni: {
|
|
508
|
+
register(command: OmniCommand): () => void;
|
|
509
|
+
unregister(id: string): void;
|
|
510
|
+
};
|
|
511
|
+
|
|
512
|
+
// UI — extension points
|
|
513
|
+
ui: {
|
|
514
|
+
registerSettingsPage(page: SettingsPage): () => void;
|
|
515
|
+
registerRightPanelSection(section: RightPanelSection): () => void;
|
|
516
|
+
/** Mount a global, shell-level panel (not session-scoped). Returns cleanup. */
|
|
517
|
+
registerGlobalPanel(panel: GlobalPanel): () => void;
|
|
518
|
+
/** Contribute a full-screen mobile view for `screen.kind`. Uninstalling or
|
|
519
|
+
* disabling the plugin removes it, same as registerRightPanelSection does
|
|
520
|
+
* on desktop. Returns cleanup. */
|
|
521
|
+
registerMobileScreen(screen: MobileScreen): () => void;
|
|
522
|
+
/** Push another mobile screen onto the nav stack (e.g. docker's container
|
|
523
|
+
* list pushing its logs view). Writes to the mobile nav store regardless
|
|
524
|
+
* of platform — harmless on desktop, since MobileShell is never mounted
|
|
525
|
+
* there. */
|
|
526
|
+
pushMobileScreen(entry: PluginMobileNavEntry): void;
|
|
527
|
+
/** Switch the mobile shell to its terminal tab — e.g. after opening an exec
|
|
528
|
+
* shell. Writes to the mobile nav store regardless of platform — harmless
|
|
529
|
+
* on desktop, since MobileShell is never mounted there. */
|
|
530
|
+
focusMobileTerminal(): void;
|
|
531
|
+
/** Inject action items into a named UI slot. Returns a cleanup function. */
|
|
532
|
+
registerContribution<C = unknown>(slot: UISlot, fn: (ctx: C) => ContributedAction[]): () => void;
|
|
533
|
+
/** Render a React widget in the terminal status bar's right-side slot. Returns a cleanup function. */
|
|
534
|
+
registerStatusBarItem(slot: UIStatusBarSlot, fn: UIStatusBarContributionFactory): () => void;
|
|
535
|
+
unregister(id: string): void;
|
|
536
|
+
/** Switch the app's active navigation section. */
|
|
537
|
+
setActiveNav(id: string): void;
|
|
538
|
+
/** Publish a plain, serialisable state snapshot for host UI to read, keyed
|
|
539
|
+
* by `<pluginId>::<key>`. Host surfaces subscribe to this instead of
|
|
540
|
+
* importing the plugin's runtime module. Cleared on unload/disable. */
|
|
541
|
+
publishState(key: string, value: unknown): void;
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
// Plugin-scoped key-value storage
|
|
545
|
+
storage: {
|
|
546
|
+
get<T>(key: string): Promise<T | null>;
|
|
547
|
+
set<T>(key: string, value: T): Promise<void>;
|
|
548
|
+
delete(key: string): Promise<void>;
|
|
549
|
+
};
|
|
550
|
+
|
|
551
|
+
// HTTP (requiert "http")
|
|
552
|
+
http: {
|
|
553
|
+
get<T>(url: string, opts?: RequestInit): Promise<T>;
|
|
554
|
+
post<T>(url: string, body: unknown, opts?: RequestInit): Promise<T>;
|
|
555
|
+
/** Streaming request. Returns a Response with a ReadableStream body (for SSE/LLM streaming). */
|
|
556
|
+
stream(url: string, init?: RequestInit): Promise<Response>;
|
|
557
|
+
};
|
|
558
|
+
|
|
559
|
+
// Filesystem restricted to home (requires "fs")
|
|
560
|
+
fs: {
|
|
561
|
+
readText(path: string): Promise<string>;
|
|
562
|
+
writeText(path: string, content: string): Promise<void>;
|
|
563
|
+
exists(path: string): Promise<boolean>;
|
|
564
|
+
/** Polling-based file watch. Calls cb when content changes. Returns cleanup fn. */
|
|
565
|
+
watch(path: string, cb: () => void, opts?: { intervalMs?: number }): () => void;
|
|
566
|
+
};
|
|
567
|
+
|
|
568
|
+
// Event bus (always available)
|
|
569
|
+
events: {
|
|
570
|
+
on(event: string, handler: (data: unknown) => void): () => void;
|
|
571
|
+
emit(event: string, data?: unknown): void;
|
|
572
|
+
};
|
|
573
|
+
|
|
574
|
+
// Notifications (requires "notifications")
|
|
575
|
+
notifications: {
|
|
576
|
+
toast(message: string, opts?: ToastOptions): void;
|
|
577
|
+
progress(title: string, opts?: ProgressOptions): ProgressHandle;
|
|
578
|
+
banner(message: string, opts?: BannerOptions): BannerHandle;
|
|
579
|
+
};
|
|
580
|
+
|
|
581
|
+
// Plugin-scoped logger
|
|
582
|
+
log: {
|
|
583
|
+
info(msg: string, ...args: unknown[]): void;
|
|
584
|
+
warn(msg: string, ...args: unknown[]): void;
|
|
585
|
+
error(msg: string, ...args: unknown[]): void;
|
|
586
|
+
};
|
|
587
|
+
|
|
588
|
+
// Sessions (requires sessions:read / sessions:write)
|
|
589
|
+
sessions: {
|
|
590
|
+
/** Returns current sessions snapshot. */
|
|
591
|
+
list(): PluginSession[];
|
|
592
|
+
/** The session backing the active terminal tab, or null if there is none. */
|
|
593
|
+
getActive(): PluginSession | null;
|
|
594
|
+
/** Fires when a session becomes connected. */
|
|
595
|
+
onConnected(cb: (session: PluginSession) => void): () => void;
|
|
596
|
+
/** Fires when a connected session is removed or disconnected. */
|
|
597
|
+
onDisconnected(cb: (session: PluginSession) => void): () => void;
|
|
598
|
+
/** Fires when the user switches to a different terminal tab. */
|
|
599
|
+
onActivated(cb: (session: PluginSession) => void): () => void;
|
|
600
|
+
/** Send a command to a session. Runtime appends \n. Requires sessions:write. */
|
|
601
|
+
sendCommand(sessionId: string, cmd: string): Promise<void>;
|
|
602
|
+
/** Open (connect) a saved connection by id. Resolves to the new sessionId. Requires sessions:write. */
|
|
603
|
+
open(connectionId: string): Promise<string>;
|
|
604
|
+
/** Close (disconnect) a session by id. Requires sessions:write. */
|
|
605
|
+
close(sessionId: string): Promise<void>;
|
|
606
|
+
};
|
|
607
|
+
|
|
608
|
+
// Terminal output — GATED (first-party only). Requires terminal:read / terminal:stream.
|
|
609
|
+
terminal: {
|
|
610
|
+
/** Last `maxLines` lines of a session's buffer as text (default 200). */
|
|
611
|
+
readSnapshot(sessionId: string, maxLines?: number): string;
|
|
612
|
+
/** The session's current selection as text, or "" if nothing is selected. */
|
|
613
|
+
readSelection(sessionId: string): string;
|
|
614
|
+
/** Subscribe to live decoded output for a session. Resolves to an unsubscribe fn. */
|
|
615
|
+
onOutput(sessionId: string, cb: (text: string) => void): Promise<() => void>;
|
|
616
|
+
};
|
|
617
|
+
|
|
618
|
+
// Keychain — GATED (first-party only). OS-local, never synced.
|
|
619
|
+
// Requires keychain:read / keychain:write.
|
|
620
|
+
keychain: {
|
|
621
|
+
/** Read a value from the OS keychain. Returns null if unset. */
|
|
622
|
+
get(key: string): Promise<string | null>;
|
|
623
|
+
/** Write a value to the OS keychain. */
|
|
624
|
+
set(key: string, value: string): Promise<void>;
|
|
625
|
+
/** Delete a value from the OS keychain (no-op if absent). */
|
|
626
|
+
delete(key: string): Promise<void>;
|
|
627
|
+
};
|
|
628
|
+
|
|
629
|
+
// Session-scoped streams (metrics, processes, docker logs) — GATED per kind.
|
|
630
|
+
streams: StreamsAPI;
|
|
631
|
+
|
|
632
|
+
// Host metrics domain wrapper over streams — GATED (metrics:read).
|
|
633
|
+
metrics: MetricsAPI;
|
|
634
|
+
|
|
635
|
+
// Process listing/kill domain wrapper over streams — GATED, split
|
|
636
|
+
// processes:read (start/onSnapshot/stop) / processes:manage (kill).
|
|
637
|
+
processes: ProcessesAPI;
|
|
638
|
+
|
|
639
|
+
// Key derivation (requires crypto:derive). Not gated — pure KDF over caller input.
|
|
640
|
+
crypto: CryptoAPI;
|
|
641
|
+
|
|
642
|
+
// Plugin-owned UI translation catalog (requires "ui"). Not gated.
|
|
643
|
+
i18n: I18nAPI;
|
|
644
|
+
|
|
645
|
+
// Proxmox VE LXC management — GATED, split
|
|
646
|
+
// proxmox:read (list/snapshots.list) / proxmox:manage (everything else).
|
|
647
|
+
proxmox: ProxmoxAPI;
|
|
648
|
+
|
|
649
|
+
// Docker container/image/volume/network/stack management — GATED, split
|
|
650
|
+
// docker:read (list/services/checkUpdate/logs.*) / docker:manage (everything else).
|
|
651
|
+
docker: DockerAPI;
|
|
652
|
+
|
|
653
|
+
// Lifecycle hooks (always available)
|
|
654
|
+
lifecycle: {
|
|
655
|
+
/** Fires when an SSH/local session transitions to "connected". */
|
|
656
|
+
onConnectionEstablished(cb: (conn: PluginConnection) => void): () => void;
|
|
657
|
+
/** Fires when a connected session is removed or becomes disconnected. */
|
|
658
|
+
onConnectionClosed(cb: (conn: PluginConnection) => void): () => void;
|
|
659
|
+
/** Fires when the user switches to a different terminal tab. */
|
|
660
|
+
onSessionActivated(cb: (session: PluginSession) => void): () => void;
|
|
661
|
+
/** Fires when this plugin's own storage.set() is called. */
|
|
662
|
+
onSettingsChanged(cb: (key: string, value: unknown) => void): () => void;
|
|
663
|
+
/** Fires before the app closes. Must resolve within 5 seconds. */
|
|
664
|
+
onBeforeQuit(cb: () => void | Promise<void>): () => void;
|
|
665
|
+
/** Resolves once the login-time server sync has completed (or immediately for local/offline users). */
|
|
666
|
+
waitForLoginSync(): Promise<void>;
|
|
667
|
+
};
|
|
668
|
+
|
|
669
|
+
// Sync / blob storage (requires sync:read / sync:write)
|
|
670
|
+
sync: {
|
|
671
|
+
/** Read a plugin-scoped blob from local storage. Returns null if not set. */
|
|
672
|
+
getBlob(key: string): Promise<Uint8Array | null>;
|
|
673
|
+
/** Write a plugin-scoped blob to local storage. Max 1 MB. */
|
|
674
|
+
setBlob(key: string, data: Uint8Array): Promise<void>;
|
|
675
|
+
/**
|
|
676
|
+
* Register a callback that fires after a sync completes and the stored
|
|
677
|
+
* blob for `key` has changed. Note: cross-device sync of plugin blobs
|
|
678
|
+
* requires future Tauri backend support — currently fires on local changes only.
|
|
679
|
+
*/
|
|
680
|
+
onRemoteChange(key: string, cb: (data: Uint8Array) => void): () => void;
|
|
681
|
+
/** Reload a named in-app store (e.g. "connections", "identities", "keys"). */
|
|
682
|
+
triggerReload(storeKey: string): Promise<void>;
|
|
683
|
+
/**
|
|
684
|
+
* Export the full app state (connections, keys, identities, secrets) as a
|
|
685
|
+
* base64-encoded XChaCha20-Poly1305 encrypted blob — same format as cloud sync.
|
|
686
|
+
* encKey: 64-char hex string (32 bytes). Requires sync:write.
|
|
687
|
+
*/
|
|
688
|
+
exportState(encKey: string, deviceId: string): Promise<string>;
|
|
689
|
+
/**
|
|
690
|
+
* CRDT-merge one or more remote encrypted blobs into local state, then
|
|
691
|
+
* reload all entity stores. blobs: base64-encoded (same format as exportState).
|
|
692
|
+
* Requires sync:write.
|
|
693
|
+
*/
|
|
694
|
+
importStates(encKey: string, blobs: string[]): Promise<void>;
|
|
695
|
+
};
|
|
696
|
+
|
|
697
|
+
// Inter-plugin communication (always available)
|
|
698
|
+
plugins: {
|
|
699
|
+
/** Publish this plugin's public API surface so other plugins can consume it. */
|
|
700
|
+
expose(publicApi: unknown): void;
|
|
701
|
+
/** Get another plugin's exposed API. Returns null if not loaded or not exposed. */
|
|
702
|
+
getApi(pluginId: string): unknown | null;
|
|
703
|
+
};
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
export type PluginRegisterFn = (api: PluginAPI) => (() => void) | void;
|
|
707
|
+
|
|
708
|
+
// ─── Settings schema ───────────────────────────────────────────────────────
|
|
709
|
+
|
|
710
|
+
export interface PluginConfigField {
|
|
711
|
+
type: "string" | "number" | "boolean" | "select";
|
|
712
|
+
default: unknown;
|
|
713
|
+
description: string;
|
|
714
|
+
/** Overrides the auto-derived label (the host humanizes the key by default). */
|
|
715
|
+
label?: string;
|
|
716
|
+
options?: string[]; // for select
|
|
717
|
+
secret?: boolean; // render as password input
|
|
718
|
+
min?: number; // for number: minimum (also clamps on save)
|
|
719
|
+
max?: number; // for number: maximum (also clamps on save)
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
export interface PluginManifest {
|
|
723
|
+
id: string;
|
|
724
|
+
name: string;
|
|
725
|
+
version: string;
|
|
726
|
+
/** Minimum app version required to run this plugin. Falls back to the app version
|
|
727
|
+
* at build time when the manifest omits it. */
|
|
728
|
+
minAppVersion?: string;
|
|
729
|
+
description?: string;
|
|
730
|
+
permissions: string[];
|
|
731
|
+
defaultEnabled?: boolean;
|
|
732
|
+
/** Hidden in the plugin list on mobile (uses host-only resources, e.g. local fs). */
|
|
733
|
+
desktopOnly?: boolean;
|
|
734
|
+
contributes?: {
|
|
735
|
+
configuration?: Record<string, PluginConfigField>;
|
|
736
|
+
};
|
|
737
|
+
}
|
|
738
|
+
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@voltius/plugin-types",
|
|
3
|
+
"version": "0.15.0",
|
|
4
|
+
"description": "TypeScript definitions for the Voltius plugin API",
|
|
5
|
+
"types": "index.d.ts",
|
|
6
|
+
"files": [
|
|
7
|
+
"index.d.ts",
|
|
8
|
+
"ui.d.ts",
|
|
9
|
+
"README.md",
|
|
10
|
+
"LICENSE"
|
|
11
|
+
],
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/VoltiusApp/voltius.git",
|
|
16
|
+
"directory": "packages/plugin-types"
|
|
17
|
+
},
|
|
18
|
+
"homepage": "https://docs.voltius.app/plugins/developing",
|
|
19
|
+
"keywords": [
|
|
20
|
+
"voltius",
|
|
21
|
+
"plugin",
|
|
22
|
+
"types",
|
|
23
|
+
"ssh",
|
|
24
|
+
"sftp"
|
|
25
|
+
],
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"@types/react": ">=18"
|
|
31
|
+
},
|
|
32
|
+
"peerDependenciesMeta": {
|
|
33
|
+
"@types/react": {
|
|
34
|
+
"optional": true
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
package/ui.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Components the host exposes to plugins. Externalized at build time so you use
|
|
2
|
+
// the host's own instances — see the build script in package.json.
|
|
3
|
+
declare module "@voltius/ui" {
|
|
4
|
+
import type { ComponentType, ReactNode } from "react";
|
|
5
|
+
export const Icon: ComponentType<{ icon: string; width?: number | string; className?: string }>;
|
|
6
|
+
export const InfoTooltip: ComponentType<{ text: string; children?: ReactNode }>;
|
|
7
|
+
export const BottomSheet: ComponentType<{ title?: string; onClose: () => void; children?: ReactNode }>;
|
|
8
|
+
export function useAutosave<T>(value: T, save: (v: T) => void | Promise<void>, delayMs?: number): void;
|
|
9
|
+
}
|