@termix-ssh/plugin-sdk 1.0.18 → 1.0.20
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/CHANGELOG.md +18 -0
- package/PLUGIN-GUIDE.md +5 -1
- package/dist/desktop.d.ts +9 -0
- package/dist/frontend.d.ts +36 -3
- package/dist/frontend.js +26 -3
- package/dist/host/{PluginsTab-YAGYRBIE.js → PluginsTab-ZSMTJ5C5.js} +26 -44
- package/dist/host/{chunk-446UEDSK.js → chunk-CITUENSU.js} +17 -2
- package/dist/host/{chunk-LQKK2JJA.js → chunk-EYONBBRJ.js} +1550 -1507
- package/dist/host/{chunk-J2AILBXM.js → chunk-J3ZQPBDK.js} +144 -95
- package/dist/host/core-classes.json +1 -1
- package/dist/host/testing-host.js +2 -2
- package/dist/host/types/src/ui/components/data-view.d.ts +7 -2
- package/dist/host/types/src/ui/components/panel-layout.d.ts +9 -2
- package/dist/host/types/src/ui/plugin-host/sdk-ui.d.ts +1 -1
- package/dist/host/types/src/ui/shell/companions.d.ts +20 -0
- package/dist/host/ui.js +3 -3
- package/dist/manifest.d.ts +1 -1
- package/dist/manifest.js +1 -1
- package/dist/testing/setup.js +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.20
|
|
4
|
+
|
|
5
|
+
Plugin API 1.12.0.
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- `columns` and `onColumns` on `ViewToggle` show a cards per row picker: Auto fits as many as the pane has room for, or pick 1 to 6
|
|
10
|
+
- `size` and `minCardWidth` on `DataView`, so a card grid follows that pick, and the `GridSize` type
|
|
11
|
+
- `usePluginPanelView` also keeps `columns`, the cards per row pick, with `setColumns`
|
|
12
|
+
|
|
13
|
+
## 1.0.19
|
|
14
|
+
|
|
15
|
+
Plugin API 1.11.0.
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- `app.registerCompanionLayout` and `useCompanions`, so a plugin can let each host turn the panel bar on or off, move it and choose which panels show and in what order
|
|
20
|
+
|
|
3
21
|
## 1.0.18
|
|
4
22
|
|
|
5
23
|
Plugin API 1.10.0.
|
package/PLUGIN-GUIDE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Termix plugin guide
|
|
2
2
|
|
|
3
|
-
SDK 1.0.
|
|
3
|
+
SDK 1.0.20 | Plugin API 1.12.0
|
|
4
4
|
|
|
5
5
|
This guide is for anyone, person or AI coding tool, building a Termix plugin. It ships inside
|
|
6
6
|
`@termix-ssh/plugin-sdk`, so the copy in your `node_modules` always matches the SDK you have installed.
|
|
@@ -496,6 +496,7 @@ your plugin's error boundary and Suspense.
|
|
|
496
496
|
| `registerRailItem` | A sidebar rail button |
|
|
497
497
|
| `registerTab`, `registerPanel` | A tab type or sidebar panel (id in `contributes.tabs` / `panels`) |
|
|
498
498
|
| `registerCompanion`, `toggleCompanion` | A panel beside any host tab, bound to its host and handle |
|
|
499
|
+
| `registerCompanionLayout` | Per host on/off, side, order and hidden panels for a tab type |
|
|
499
500
|
| `registerDashboardCard` | A dashboard card (`contributes.dashboardCards`) |
|
|
500
501
|
| `registerHostAction` | A host button, palette entry or default connect |
|
|
501
502
|
| `registerHostEditorSection` | Your own host editor section (host settings get one for free) |
|
|
@@ -642,6 +643,9 @@ exports with props is `ui.api.txt` in the Termix repo
|
|
|
642
643
|
`PanePrompt` for small prompts.
|
|
643
644
|
- Every tab or panel sits in `PanelShell`. Lists use `PanelList` and `ListRow`, add with `AddButton`,
|
|
644
645
|
forms end with `FormFooter`, empty lists show `EmptyState`.
|
|
646
|
+
- Card grids use `DataView` with `ViewToggle`. Pass `columns` and `onColumns` to `ViewToggle` and the same
|
|
647
|
+
value as `size` to `DataView`, so users can pick Auto (as many as fit) or a fixed number of cards per
|
|
648
|
+
row. `usePluginPanelView` keeps the choice as `columns`. Older Termix versions ignore both props.
|
|
645
649
|
- Forms: `TextField`, `NumberField`, `SelectField`, `SwitchRow`, `SecretField`, `SettingRow` and friends.
|
|
646
650
|
- Host sessions use `ConnectionGate` for the whole connect flow (host keys, TOTP, passphrases, errors).
|
|
647
651
|
- Mobile: check `useIsMobile()` and give small screens a layout that works. The desktop app always uses the
|
package/dist/desktop.d.ts
CHANGED
|
@@ -33,6 +33,15 @@ export interface ElectronAPI {
|
|
|
33
33
|
getAppVersion: () => Promise<string>;
|
|
34
34
|
setZoomFactor?: (factor: number) => void;
|
|
35
35
|
getPlatform: () => Promise<string>;
|
|
36
|
+
/** Whether the app-drawn title bar shows in this window. */
|
|
37
|
+
getTitleBarVisible?: () => Promise<boolean>;
|
|
38
|
+
/** Calls back when the title bar shows or hides; returns an unsubscribe. */
|
|
39
|
+
onTitleBarVisibleChange?: (callback: (visible: boolean) => void) => () => void;
|
|
40
|
+
/** Keeps the window controls the system draws in the colors of the theme. */
|
|
41
|
+
setTitleBarOverlay?: (colors: {
|
|
42
|
+
color?: string;
|
|
43
|
+
symbolColor?: string;
|
|
44
|
+
}) => Promise<void>;
|
|
36
45
|
getSetting?: (key: string) => Promise<string | null | undefined>;
|
|
37
46
|
setSetting?: (key: string, value: string) => Promise<void>;
|
|
38
47
|
getServerConfig: () => Promise<ServerConfig>;
|
package/dist/frontend.d.ts
CHANGED
|
@@ -783,6 +783,24 @@ export interface CompanionDefaults {
|
|
|
783
783
|
/** Show the edge button that opens and closes it. Default true. */
|
|
784
784
|
edgeButton?: boolean;
|
|
785
785
|
}
|
|
786
|
+
/** A panel a tab type can show beside it, for a picker. */
|
|
787
|
+
export interface CompanionInfo {
|
|
788
|
+
/** The id registerCompanionLayout's hidden and order lists use. */
|
|
789
|
+
id: string;
|
|
790
|
+
titleKey: string;
|
|
791
|
+
icon?: IconComponent;
|
|
792
|
+
}
|
|
793
|
+
/** How a host wants the panel bar beside a tab. */
|
|
794
|
+
export interface CompanionLayout {
|
|
795
|
+
/** False removes the bar and its panels. */
|
|
796
|
+
enabled?: boolean;
|
|
797
|
+
/** Where a panel opens until the user moves it. */
|
|
798
|
+
side?: "left" | "right" | "bottom";
|
|
799
|
+
/** Companion ids in bar order. */
|
|
800
|
+
order?: string[];
|
|
801
|
+
/** Companion ids left out. */
|
|
802
|
+
hidden?: string[];
|
|
803
|
+
}
|
|
786
804
|
export interface CompanionProps {
|
|
787
805
|
/** The tab it sits beside. */
|
|
788
806
|
tab: PluginTabRecord;
|
|
@@ -1044,6 +1062,11 @@ export interface TermixApp extends TermixAppInfo {
|
|
|
1044
1062
|
* it; the tab keeps running underneath.
|
|
1045
1063
|
*/
|
|
1046
1064
|
registerCompanion: (id: string, component: ComponentType<CompanionProps>, options?: CompanionOptions) => Disposer;
|
|
1065
|
+
/**
|
|
1066
|
+
* Lets a plugin decide, per host, how the panel bar looks on one tab type.
|
|
1067
|
+
* Read from the host payload, so it must not call hooks.
|
|
1068
|
+
*/
|
|
1069
|
+
registerCompanionLayout: (tabType: string, resolve: (host: PluginHostRecord | undefined) => CompanionLayout) => Disposer;
|
|
1047
1070
|
/** Opens a companion on a tab, or closes it when it is showing. */
|
|
1048
1071
|
toggleCompanion: (tab: PluginTabRecord, id?: string) => void;
|
|
1049
1072
|
registerHostEditorSection: (section: HostEditorSectionContribution) => Disposer;
|
|
@@ -1220,6 +1243,7 @@ export interface PluginHostBridge {
|
|
|
1220
1243
|
hostProtocols: (host: PluginHostRecord) => string[];
|
|
1221
1244
|
useHostStatus: (hostId: number | undefined) => HostStatusInfo | null;
|
|
1222
1245
|
useHostActions: () => HostActionContribution[];
|
|
1246
|
+
useCompanions: (tabType: string) => CompanionInfo[];
|
|
1223
1247
|
useActivityTypes: () => string[];
|
|
1224
1248
|
activityTarget: (type: string) => ActivityTargetInfo | undefined;
|
|
1225
1249
|
useExtensions: (pointId: string) => ExtensionContribution[];
|
|
@@ -1402,17 +1426,21 @@ export declare function usePluginUiPreferences<T extends Record<string, unknown>
|
|
|
1402
1426
|
values: T;
|
|
1403
1427
|
set: <K extends keyof T & string>(key: K, value: T[K] | null) => void;
|
|
1404
1428
|
};
|
|
1429
|
+
type PanelGridSize = "auto" | "1" | "2" | "3" | "4" | "5" | "6";
|
|
1405
1430
|
/**
|
|
1406
|
-
* Grid or list and row
|
|
1407
|
-
* Appearance area as `<prefix>viewMode
|
|
1408
|
-
* keys in contributes.uiPresets so each
|
|
1431
|
+
* Grid or list, row density and cards per row for one of this plugin's
|
|
1432
|
+
* views, kept in its Appearance area as `<prefix>viewMode`, `<prefix>density`
|
|
1433
|
+
* and `<prefix>columns`. Declare those keys in contributes.uiPresets so each
|
|
1434
|
+
* preset level can pick a default. Hand columns to ViewToggle and DataView.
|
|
1409
1435
|
*/
|
|
1410
1436
|
export declare function usePluginPanelView(prefix?: string): {
|
|
1411
1437
|
view: "grid" | "list";
|
|
1412
1438
|
density: "comfortable" | "compact";
|
|
1413
1439
|
compact: boolean;
|
|
1440
|
+
columns: PanelGridSize;
|
|
1414
1441
|
setView: (view: "grid" | "list") => void;
|
|
1415
1442
|
setDensity: (density: "comfortable" | "compact") => void;
|
|
1443
|
+
setColumns: (columns: PanelGridSize) => void;
|
|
1416
1444
|
};
|
|
1417
1445
|
export declare function useTabs(): TabsApi;
|
|
1418
1446
|
/**
|
|
@@ -1445,6 +1473,11 @@ export declare function useSlotContributions(slotId: string, context?: Record<st
|
|
|
1445
1473
|
* connect widget, say. Reactive: it re-renders as plugins enable and disable.
|
|
1446
1474
|
*/
|
|
1447
1475
|
export declare function useHostActions(): HostActionContribution[];
|
|
1476
|
+
/**
|
|
1477
|
+
* Every panel that can open beside a tab of this type, for a settings screen
|
|
1478
|
+
* that lets the user hide or reorder them. Reactive.
|
|
1479
|
+
*/
|
|
1480
|
+
export declare function useCompanions(tabType: string): CompanionInfo[];
|
|
1448
1481
|
/**
|
|
1449
1482
|
* Recent-activity types every registered tab claims (registerTab's
|
|
1450
1483
|
* activityTypes), core's and plugins'. For a filter that lists what a user
|
package/dist/frontend.js
CHANGED
|
@@ -165,21 +165,37 @@ export function usePluginUiPreferences() {
|
|
|
165
165
|
const bridge = requireHost();
|
|
166
166
|
return bridge.usePluginUiPreferences(bridge.usePluginId());
|
|
167
167
|
}
|
|
168
|
+
const PANEL_GRID_SIZES = [
|
|
169
|
+
"auto",
|
|
170
|
+
"1",
|
|
171
|
+
"2",
|
|
172
|
+
"3",
|
|
173
|
+
"4",
|
|
174
|
+
"5",
|
|
175
|
+
"6",
|
|
176
|
+
];
|
|
168
177
|
/**
|
|
169
|
-
* Grid or list and row
|
|
170
|
-
* Appearance area as `<prefix>viewMode
|
|
171
|
-
* keys in contributes.uiPresets so each
|
|
178
|
+
* Grid or list, row density and cards per row for one of this plugin's
|
|
179
|
+
* views, kept in its Appearance area as `<prefix>viewMode`, `<prefix>density`
|
|
180
|
+
* and `<prefix>columns`. Declare those keys in contributes.uiPresets so each
|
|
181
|
+
* preset level can pick a default. Hand columns to ViewToggle and DataView.
|
|
172
182
|
*/
|
|
173
183
|
export function usePluginPanelView(prefix = "") {
|
|
174
184
|
const { values, set } = usePluginUiPreferences();
|
|
175
185
|
const view = values[`${prefix}viewMode`] === "list" ? "list" : "grid";
|
|
176
186
|
const density = values[`${prefix}density`] === "compact" ? "compact" : "comfortable";
|
|
187
|
+
const saved = values[`${prefix}columns`];
|
|
188
|
+
const columns = typeof saved === "string" && PANEL_GRID_SIZES.includes(saved)
|
|
189
|
+
? saved
|
|
190
|
+
: "auto";
|
|
177
191
|
return {
|
|
178
192
|
view,
|
|
179
193
|
density,
|
|
180
194
|
compact: density === "compact",
|
|
195
|
+
columns,
|
|
181
196
|
setView: (next) => set(`${prefix}viewMode`, next),
|
|
182
197
|
setDensity: (next) => set(`${prefix}density`, next),
|
|
198
|
+
setColumns: (next) => set(`${prefix}columns`, next),
|
|
183
199
|
};
|
|
184
200
|
}
|
|
185
201
|
export function useTabs() {
|
|
@@ -220,6 +236,13 @@ export function useSlotContributions(slotId, context) {
|
|
|
220
236
|
export function useHostActions() {
|
|
221
237
|
return requireHost().useHostActions();
|
|
222
238
|
}
|
|
239
|
+
/**
|
|
240
|
+
* Every panel that can open beside a tab of this type, for a settings screen
|
|
241
|
+
* that lets the user hide or reorder them. Reactive.
|
|
242
|
+
*/
|
|
243
|
+
export function useCompanions(tabType) {
|
|
244
|
+
return requireHost().useCompanions(tabType);
|
|
245
|
+
}
|
|
223
246
|
/**
|
|
224
247
|
* Recent-activity types every registered tab claims (registerTab's
|
|
225
248
|
* activityTypes), core's and plugins'. For a filter that lists what a user
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
sortPlugins,
|
|
30
30
|
uploadEntry,
|
|
31
31
|
youtubeEmbedUrl
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-CITUENSU.js";
|
|
33
33
|
import {
|
|
34
34
|
ArrowDownWideNarrow,
|
|
35
35
|
BookOpen,
|
|
@@ -38,7 +38,6 @@ import {
|
|
|
38
38
|
Check,
|
|
39
39
|
ChevronLeft,
|
|
40
40
|
ChevronRight,
|
|
41
|
-
Columns3,
|
|
42
41
|
DEVELOPER_MODE_CHANGED_EVENT,
|
|
43
42
|
Database,
|
|
44
43
|
DocsLink,
|
|
@@ -47,6 +46,7 @@ import {
|
|
|
47
46
|
Facts,
|
|
48
47
|
FakeSwitch,
|
|
49
48
|
FlaskConical,
|
|
49
|
+
GRID_SIZES,
|
|
50
50
|
Globe,
|
|
51
51
|
GroupHeading,
|
|
52
52
|
InlineView,
|
|
@@ -107,7 +107,7 @@ import {
|
|
|
107
107
|
updatePlugin,
|
|
108
108
|
uploadPlugin,
|
|
109
109
|
useConfirm
|
|
110
|
-
} from "./chunk-
|
|
110
|
+
} from "./chunk-EYONBBRJ.js";
|
|
111
111
|
import "./chunk-7LEJ3HYF.js";
|
|
112
112
|
import {
|
|
113
113
|
__toESM,
|
|
@@ -1845,7 +1845,6 @@ function usePluginsManager() {
|
|
|
1845
1845
|
|
|
1846
1846
|
// src/ui/plugins/PluginsTab.tsx
|
|
1847
1847
|
import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1848
|
-
var GRID_SIZES = ["auto", "2", "3", "4", "5", "6"];
|
|
1849
1848
|
function useStoredChoice(key, allowed, fallback) {
|
|
1850
1849
|
const [value, setValue] = useState5(() => {
|
|
1851
1850
|
try {
|
|
@@ -2075,45 +2074,15 @@ function LayoutControls({
|
|
|
2075
2074
|
onView,
|
|
2076
2075
|
onColumns
|
|
2077
2076
|
}) {
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
SelectTrigger,
|
|
2088
|
-
{
|
|
2089
|
-
size: "sm",
|
|
2090
|
-
className: "w-auto gap-1.5 text-xs",
|
|
2091
|
-
title: t("plugins.manager.columns.title"),
|
|
2092
|
-
"aria-label": t("plugins.manager.columns.title"),
|
|
2093
|
-
children: [
|
|
2094
|
-
/* @__PURE__ */ jsx6(Columns3, { className: "size-3.5 text-muted-foreground" }),
|
|
2095
|
-
/* @__PURE__ */ jsx6(SelectValue, {})
|
|
2096
|
-
]
|
|
2097
|
-
}
|
|
2098
|
-
),
|
|
2099
|
-
/* @__PURE__ */ jsx6(SelectContent, { children: GRID_SIZES.map((size) => /* @__PURE__ */ jsx6(SelectItem, { value: size, className: "text-xs", children: size === "auto" ? t("plugins.manager.columns.auto") : t("plugins.manager.columns.count", { count: Number(size) }) }, size)) })
|
|
2100
|
-
]
|
|
2101
|
-
}
|
|
2102
|
-
),
|
|
2103
|
-
/* @__PURE__ */ jsx6(ViewToggle, { view: layout.view, onView })
|
|
2104
|
-
] });
|
|
2105
|
-
}
|
|
2106
|
-
function gridStyle(columns) {
|
|
2107
|
-
if (columns === "auto") {
|
|
2108
|
-
return {
|
|
2109
|
-
gridTemplateColumns: "repeat(auto-fill, minmax(min(100%, 400px), 1fr))"
|
|
2110
|
-
};
|
|
2111
|
-
}
|
|
2112
|
-
const n = Number(columns);
|
|
2113
|
-
const gaps = (n - 1) * 12;
|
|
2114
|
-
return {
|
|
2115
|
-
gridTemplateColumns: `repeat(auto-fill, minmax(max(220px, calc((100% - ${gaps}px) / ${n} - 0.5px)), 1fr))`
|
|
2116
|
-
};
|
|
2077
|
+
return /* @__PURE__ */ jsx6(
|
|
2078
|
+
ViewToggle,
|
|
2079
|
+
{
|
|
2080
|
+
view: layout.view,
|
|
2081
|
+
onView,
|
|
2082
|
+
columns: layout.columns,
|
|
2083
|
+
onColumns
|
|
2084
|
+
}
|
|
2085
|
+
);
|
|
2117
2086
|
}
|
|
2118
2087
|
function PluginCollection({
|
|
2119
2088
|
plugins,
|
|
@@ -2137,7 +2106,20 @@ function PluginCollection({
|
|
|
2137
2106
|
}
|
|
2138
2107
|
);
|
|
2139
2108
|
}
|
|
2140
|
-
return /* @__PURE__ */ jsx6(
|
|
2109
|
+
return /* @__PURE__ */ jsx6(
|
|
2110
|
+
DataView,
|
|
2111
|
+
{
|
|
2112
|
+
items: plugins,
|
|
2113
|
+
view: "grid",
|
|
2114
|
+
getKey: (p) => p.id,
|
|
2115
|
+
renderCard,
|
|
2116
|
+
columns: {},
|
|
2117
|
+
size: layout.columns,
|
|
2118
|
+
minCardWidth: 400,
|
|
2119
|
+
listColumns,
|
|
2120
|
+
empty: null
|
|
2121
|
+
}
|
|
2122
|
+
);
|
|
2141
2123
|
}
|
|
2142
2124
|
function NameCell({ plugin, muted }) {
|
|
2143
2125
|
return /* @__PURE__ */ jsxs6("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
@@ -6,8 +6,9 @@ import {
|
|
|
6
6
|
Plus,
|
|
7
7
|
Trash,
|
|
8
8
|
cn,
|
|
9
|
+
gridSizeStyle,
|
|
9
10
|
useAreaPreferences
|
|
10
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-EYONBBRJ.js";
|
|
11
12
|
import {
|
|
12
13
|
isElectron
|
|
13
14
|
} from "./chunk-7LEJ3HYF.js";
|
|
@@ -2219,6 +2220,8 @@ function DataView({
|
|
|
2219
2220
|
getKey,
|
|
2220
2221
|
renderCard,
|
|
2221
2222
|
columns,
|
|
2223
|
+
size,
|
|
2224
|
+
minCardWidth,
|
|
2222
2225
|
listColumns,
|
|
2223
2226
|
onRowClick,
|
|
2224
2227
|
isRowActive,
|
|
@@ -2229,7 +2232,19 @@ function DataView({
|
|
|
2229
2232
|
return /* @__PURE__ */ jsx3("div", { className: "flex flex-1 items-center justify-center", children: empty });
|
|
2230
2233
|
}
|
|
2231
2234
|
if (view === "grid") {
|
|
2232
|
-
return /* @__PURE__ */ jsx3(
|
|
2235
|
+
return /* @__PURE__ */ jsx3(
|
|
2236
|
+
"div",
|
|
2237
|
+
{
|
|
2238
|
+
className: cn(
|
|
2239
|
+
"grid",
|
|
2240
|
+
PANEL.gap,
|
|
2241
|
+
!size && gridClass(columns),
|
|
2242
|
+
className
|
|
2243
|
+
),
|
|
2244
|
+
style: size ? gridSizeStyle(size, minCardWidth) : void 0,
|
|
2245
|
+
children: items.map((item) => /* @__PURE__ */ jsx3("div", { className: "flex flex-col *:flex-1", children: renderCard(item) }, getKey(item)))
|
|
2246
|
+
}
|
|
2247
|
+
);
|
|
2233
2248
|
}
|
|
2234
2249
|
const template = listColumns.map((c) => c.width).join(" ");
|
|
2235
2250
|
const rowHeight = density === "compact" ? "h-7" : "h-9";
|