@termix-ssh/plugin-sdk 1.0.11 → 1.0.13

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.
Files changed (130) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/PLUGIN-GUIDE.md +178 -54
  3. package/cli/commands/build.mjs +36 -22
  4. package/cli/commands/pack.mjs +12 -2
  5. package/cli/commands/validate.mjs +63 -3
  6. package/cli/lib/plugin-dir.mjs +11 -0
  7. package/cli/lib/tmxplug.mjs +9 -0
  8. package/dist/backend.d.ts +404 -0
  9. package/dist/capabilities.js +7 -0
  10. package/dist/db.js +1 -0
  11. package/dist/desktop.d.ts +0 -243
  12. package/dist/frontend.d.ts +175 -2
  13. package/dist/frontend.js +7 -0
  14. package/dist/host/PluginsTab-OXQQ7M4I.js +3266 -0
  15. package/dist/host/chunk-54KCK6IZ.js +3167 -0
  16. package/dist/host/chunk-CALNJCHN.js +10435 -0
  17. package/dist/host/{chunk-7RRTYD6B.js → chunk-CN5UBTBP.js} +1412 -14
  18. package/dist/host/{chunk-RLQBKJRK.js → chunk-ERGN4YW6.js} +9204 -11492
  19. package/dist/host/{chunk-LSWB3ZZV.js → chunk-T2PZWXFJ.js} +6 -1
  20. package/dist/host/chunk-YGYBM7SQ.js +58 -0
  21. package/dist/host/core-classes.json +1 -1
  22. package/dist/host/{linked-server-UCW74T2V.js → linked-server-5VFO4XQB.js} +2 -2
  23. package/dist/host/{rbac-api-6UYMFIFV.js → rbac-api-5YMBJAO5.js} +2 -2
  24. package/dist/host/testing-host.js +123 -57
  25. package/dist/host/types/src/types/onboarding.d.ts +0 -2
  26. package/dist/host/types/src/types/ui-types.d.ts +2 -1
  27. package/dist/host/types/src/ui/api/audit-log-api.d.ts +36 -0
  28. package/dist/host/types/src/ui/api/credentials-api.d.ts +0 -22
  29. package/dist/host/types/src/ui/api/host-defaults-api.d.ts +42 -0
  30. package/dist/host/types/src/ui/api/host-tags-api.d.ts +2 -0
  31. package/dist/host/types/src/ui/api/look-api.d.ts +40 -0
  32. package/dist/host/types/src/ui/api/open-tabs-api.d.ts +4 -0
  33. package/dist/host/types/src/ui/api/plugins-api.d.ts +30 -0
  34. package/dist/host/types/src/ui/api/private-endpoints-api.d.ts +6 -0
  35. package/dist/host/types/src/ui/api/settings-api.d.ts +0 -6
  36. package/dist/host/types/src/ui/api/ssh-host-management-api.d.ts +0 -28
  37. package/dist/host/types/src/ui/api/tls-api.d.ts +25 -0
  38. package/dist/host/types/src/ui/auth/ElectronLoginForm.d.ts +9 -0
  39. package/dist/host/types/src/ui/components/command.d.ts +78 -0
  40. package/dist/host/types/src/ui/components/folder-style.d.ts +16 -0
  41. package/dist/host/types/src/ui/components/theme-provider.d.ts +2 -1
  42. package/dist/host/types/src/ui/components/version-badge.d.ts +7 -0
  43. package/dist/host/types/src/ui/hooks/use-page-visible-interval.d.ts +10 -0
  44. package/dist/host/types/src/ui/lib/activity-types.d.ts +15 -0
  45. package/dist/host/types/src/ui/lib/app-version.d.ts +2 -0
  46. package/dist/host/types/src/ui/lib/apply-ui-preset.d.ts +19 -0
  47. package/dist/host/types/src/ui/lib/create-id.d.ts +2 -0
  48. package/dist/host/types/src/ui/lib/database-transfer-url.d.ts +8 -0
  49. package/dist/host/types/src/ui/lib/desktop-updates.d.ts +29 -0
  50. package/dist/host/types/src/ui/lib/host-connection-tabs.d.ts +14 -0
  51. package/dist/host/types/src/ui/lib/host-to-ssh-host.d.ts +4 -0
  52. package/dist/host/types/src/ui/lib/issue-url.d.ts +21 -0
  53. package/dist/host/types/src/ui/lib/local-adaptive-preferences.d.ts +9 -0
  54. package/dist/host/types/src/ui/lib/pane-nav-hotkey.d.ts +7 -0
  55. package/dist/host/types/src/ui/lib/plugin-i18n.d.ts +4 -3
  56. package/dist/host/types/src/ui/lib/role-label.d.ts +3 -0
  57. package/dist/host/types/src/ui/look/LookSettings.d.ts +8 -0
  58. package/dist/host/types/src/ui/look/layout-registry.d.ts +34 -0
  59. package/dist/host/types/src/ui/look/look-store.d.ts +29 -0
  60. package/dist/host/types/src/ui/look/resolve-look.d.ts +18 -0
  61. package/dist/host/types/src/ui/look/theme-css.d.ts +7 -0
  62. package/dist/host/types/src/ui/look/theme-registry.d.ts +41 -0
  63. package/dist/host/types/src/ui/look/use-look-theme.d.ts +12 -0
  64. package/dist/host/types/src/ui/main-axios.d.ts +2 -2
  65. package/dist/host/types/src/ui/manage/manage-requests.d.ts +34 -0
  66. package/dist/host/types/src/ui/onboarding/onboarding-registry.d.ts +3 -1
  67. package/dist/host/types/src/ui/plugin-host/loader.d.ts +2 -0
  68. package/dist/host/types/src/ui/plugin-host/scope.d.ts +6 -0
  69. package/dist/host/types/src/ui/plugin-host/sdk-ui.d.ts +101 -0
  70. package/dist/host/types/src/ui/plugin-host/view-ownership.d.ts +1 -1
  71. package/dist/host/types/src/ui/plugins/PluginConsentPrompt.d.ts +20 -0
  72. package/dist/host/types/src/ui/plugins/PluginDetail.d.ts +7 -0
  73. package/dist/host/types/src/ui/plugins/PluginReleaseNotes.d.ts +14 -0
  74. package/dist/host/types/src/ui/plugins/PluginsTab.d.ts +1 -0
  75. package/dist/host/types/src/ui/plugins/RegistriesSection.d.ts +4 -0
  76. package/dist/host/types/src/ui/plugins/plugin-bits.d.ts +23 -0
  77. package/dist/host/types/src/ui/plugins/plugin-model.d.ts +136 -0
  78. package/dist/host/types/src/ui/plugins/use-plugins-manager.d.ts +78 -0
  79. package/dist/host/types/src/ui/settings/appearance/appearance-controls.d.ts +53 -0
  80. package/dist/host/types/src/ui/settings/sync/LinkServerDialog.d.ts +12 -0
  81. package/dist/host/types/src/ui/settings/sync/ProxySettingsFields.d.ts +15 -0
  82. package/dist/host/types/src/ui/settings/sync/saved-servers.d.ts +3 -0
  83. package/dist/host/types/src/ui/shell/controller/ShellControllerProvider.d.ts +20 -0
  84. package/dist/host/types/src/ui/shell/controller/plugin-shell.d.ts +7 -0
  85. package/dist/host/types/src/ui/shell/controller/shell-store.d.ts +4 -0
  86. package/dist/host/types/src/ui/shell/controller/types.d.ts +156 -0
  87. package/dist/host/types/src/ui/shell/controller/use-hosts.d.ts +10 -0
  88. package/dist/host/types/src/ui/shell/controller/use-regions.d.ts +5 -0
  89. package/dist/host/types/src/ui/shell/controller/use-shell-keybindings.d.ts +12 -0
  90. package/dist/host/types/src/ui/shell/controller/use-shell-lifecycle.d.ts +17 -0
  91. package/dist/host/types/src/ui/shell/controller/use-split.d.ts +21 -0
  92. package/dist/host/types/src/ui/shell/controller/use-tabs.d.ts +70 -0
  93. package/dist/host/types/src/ui/shell/controller/use-workspace-layout.d.ts +4 -0
  94. package/dist/host/types/src/ui/shell/reconnect-tabs.d.ts +6 -0
  95. package/dist/host/types/src/ui/shell/shell-layout.d.ts +46 -0
  96. package/dist/host/types/src/ui/shell/split/EmptyPanePicker.d.ts +32 -0
  97. package/dist/host/types/src/ui/shell/split/SplitDropOverlay.d.ts +9 -0
  98. package/dist/host/types/src/ui/shell/split/SplitLayoutMenu.d.ts +16 -0
  99. package/dist/host/types/src/ui/shell/split/SplitView.d.ts +31 -0
  100. package/dist/host/types/src/ui/shell/split/split-drag.d.ts +58 -0
  101. package/dist/host/types/src/ui/shell/split/split-presets.d.ts +28 -0
  102. package/dist/host/types/src/ui/shell/split/split-tabs.d.ts +95 -0
  103. package/dist/host/types/src/ui/shell/split/split-targets.d.ts +30 -0
  104. package/dist/host/types/src/ui/shell/split/split-tree.d.ts +89 -0
  105. package/dist/host/types/src/ui/shell/stage/TabStage.d.ts +9 -0
  106. package/dist/host/types/src/ui/shell/stage/tab-stage-store.d.ts +24 -0
  107. package/dist/host/types/src/ui/shell/tab-close-guards.d.ts +9 -0
  108. package/dist/host/types/src/ui/shell/tab-handles.d.ts +8 -0
  109. package/dist/host/types/src/ui/shell/tabUtils.d.ts +15 -0
  110. package/dist/host/types/src/ui/sidebar/AuthEnrollmentSections.d.ts +5 -0
  111. package/dist/host/types/src/ui/sidebar/HostManagerData.d.ts +4 -0
  112. package/dist/host/types/src/ui/sidebar/build-host-tree.d.ts +25 -0
  113. package/dist/host/types/src/ui/sidebar/host-contributions.d.ts +10 -0
  114. package/dist/host/ui.js +6045 -4055
  115. package/dist/host/{use-permissions-GYCBY2AU.js → use-permissions-ISEDRY3J.js} +2 -2
  116. package/dist/manifest.d.ts +50 -1
  117. package/dist/manifest.js +104 -1
  118. package/dist/ssh-keys.d.ts +29 -0
  119. package/dist/ssh-keys.js +85 -0
  120. package/dist/testing/setup.js +1 -0
  121. package/dist/testing.d.ts +32 -15
  122. package/dist/testing.js +218 -1
  123. package/dist/theme-css.d.ts +11 -0
  124. package/dist/theme-css.js +142 -0
  125. package/dist/vitest-preset.d.ts +18 -0
  126. package/dist/vitest-preset.js +14 -3
  127. package/package.json +5 -1
  128. package/schema/manifest.schema.json +121 -8
  129. package/tsconfig.plugin.json +1 -0
  130. package/dist/host/chunk-YC2MAKSP.js +0 -14
@@ -0,0 +1,53 @@
1
+ import type { FontSizeId, ThemeId, UiFontId } from "../../../types/ui-types";
2
+ import { type ThemeSwatch } from "../../look/theme-registry";
3
+ export declare const DEFAULT_ACCENT = "#f59145";
4
+ /** The built-in themes, with System first. Plugin themes come from useThemeOptions. */
5
+ export declare const THEMES: {
6
+ id: ThemeId;
7
+ preview: string;
8
+ }[];
9
+ export interface ThemeOption {
10
+ id: ThemeId;
11
+ label: string;
12
+ /** Null for System, which previews light and dark side by side. */
13
+ swatch: ThemeSwatch | null;
14
+ }
15
+ /** Every theme to pick from, System first, plugin themes included. */
16
+ export declare function useThemeOptions(): ThemeOption[];
17
+ export declare function isHexColor(value: string): boolean;
18
+ /**
19
+ * Theme, accent, font and language, applied right away and stored the same
20
+ * way the profile settings store them.
21
+ */
22
+ export declare function useAppearanceSettings(): {
23
+ theme: string;
24
+ accent: string;
25
+ fontSize: FontSizeId;
26
+ uiFont: UiFontId;
27
+ language: string;
28
+ setTheme(id: ThemeId): void;
29
+ setAccent(value: string): void;
30
+ setFontSize(id: FontSizeId): void;
31
+ setUiFont(id: UiFontId): void;
32
+ setLanguage(code: string): void;
33
+ };
34
+ export declare function ThemeGrid({ value, onChange, }: {
35
+ value: ThemeId;
36
+ onChange: (id: ThemeId) => void;
37
+ }): import("react").JSX.Element;
38
+ export declare function AccentPicker({ value, onChange, }: {
39
+ value: string;
40
+ onChange: (value: string) => void;
41
+ }): import("react").JSX.Element;
42
+ export declare function FontSizePicker({ value, onChange, }: {
43
+ value: FontSizeId;
44
+ onChange: (id: FontSizeId) => void;
45
+ }): import("react").JSX.Element;
46
+ export declare function UiFontSelect({ value, onChange, }: {
47
+ value: UiFontId;
48
+ onChange: (id: UiFontId) => void;
49
+ }): import("react").JSX.Element;
50
+ export declare function LanguageSelect({ value, onChange, }: {
51
+ value: string;
52
+ onChange: (code: string) => void;
53
+ }): import("react").JSX.Element;
@@ -0,0 +1,12 @@
1
+ import { type SyncStatus } from "../../api/sync-api";
2
+ interface LinkServerDialogProps {
3
+ open: boolean;
4
+ onOpenChange: (open: boolean) => void;
5
+ onLinked: (status: SyncStatus) => void;
6
+ /** Sign back in to the server this desktop is already linked to. */
7
+ relogin?: {
8
+ serverUrl: string;
9
+ };
10
+ }
11
+ export declare function LinkServerDialog({ open, onOpenChange, onLinked, relogin, }: LinkServerDialogProps): import("react").JSX.Element;
12
+ export {};
@@ -0,0 +1,15 @@
1
+ import type { SyncBasicAuth, SyncProxyHeader } from "../../api/sync-api";
2
+ interface ProxySettingsFieldsProps {
3
+ customHeaders: SyncProxyHeader[];
4
+ basicAuth: SyncBasicAuth | null;
5
+ onChange: (next: {
6
+ customHeaders?: SyncProxyHeader[];
7
+ basicAuth?: SyncBasicAuth | null;
8
+ }) => void;
9
+ }
10
+ /**
11
+ * What a reverse proxy in front of the server wants: extra headers (a
12
+ * Cloudflare Access service token, a gateway key) and basic auth.
13
+ */
14
+ export declare function ProxySettingsFields({ customHeaders, basicAuth, onChange, }: ProxySettingsFieldsProps): import("react").JSX.Element;
15
+ export {};
@@ -0,0 +1,3 @@
1
+ export declare function getSavedServerUrls(): string[];
2
+ export declare function rememberServerUrl(url: string): string[];
3
+ export declare function forgetServerUrl(url: string): string[];
@@ -0,0 +1,20 @@
1
+ import { type TabStageStore } from "../stage/tab-stage-store";
2
+ import type { ShellController } from "./types";
3
+ /** The live shell, for core layout code. Throws outside the shell. */
4
+ export declare function useShellController(): ShellController;
5
+ /** The live shell, or null outside it. */
6
+ export declare function useOptionalShellController(): ShellController | null;
7
+ export declare function useTabStageStore(): TabStageStore;
8
+ /**
9
+ * Hands the main area's confirm to code outside it, like closeTab. A layout
10
+ * renders it inside the scope its tab-close questions should show in.
11
+ */
12
+ export declare function ShellConfirmCapture(): null;
13
+ /** Owns every bit of shell state and behaviour a layout draws. */
14
+ export declare function ShellControllerProvider({ username, onLogout, children, }: {
15
+ username: string;
16
+ onLogout: (options?: {
17
+ manual?: boolean;
18
+ }) => void;
19
+ children: React.ReactNode;
20
+ }): import("react").JSX.Element;
@@ -0,0 +1,7 @@
1
+ import type { ShellController as PluginShellController } from "@termix-ssh/plugin-sdk/frontend";
2
+ /**
3
+ * The shell as a plugin layout sees it, through useShell() in the SDK. Inside
4
+ * the shell this reads the controller's context; outside (an overlay a
5
+ * plugin mounted elsewhere) the last published one.
6
+ */
7
+ export declare function usePluginShell(pluginId: string): PluginShellController | null;
@@ -0,0 +1,4 @@
1
+ import type { ShellController } from "./types";
2
+ export declare function publishShellController(next: ShellController | null): void;
3
+ export declare function getShellController(): ShellController | null;
4
+ export declare function useShellSnapshot(): ShellController | null;
@@ -0,0 +1,156 @@
1
+ import type { MutableRefObject } from "react";
2
+ import type { TabHandle } from "@termix-ssh/plugin-sdk/frontend";
3
+ import type { ConfirmOptions, EditingWidth } from "../../components/surface/surface-scope";
4
+ import type { Host, HostFolder, Tab, TabType } from "../../../types/ui-types";
5
+ import type { OpenTabRecord, UserPreferences } from "../../main-axios";
6
+ import type { TabShellCallbacks } from "../tab-registry";
7
+ import type { SplitViewActions } from "../split/SplitView";
8
+ import type { NewTabOption, PickHostTarget } from "../split/EmptyPanePicker";
9
+ import type { SplitSummary, SplitTab, TabSplitAction } from "../split/split-tabs";
10
+ export interface DockRegion {
11
+ view: string;
12
+ open: boolean;
13
+ width: number;
14
+ dragging: boolean;
15
+ editing: EditingWidth;
16
+ setView: (view: string | ((prev: string) => string)) => void;
17
+ setOpen: (open: boolean | ((prev: boolean) => boolean)) => void;
18
+ setWidth: (width: number) => void;
19
+ startResize: (e: React.MouseEvent) => void;
20
+ resetWidth: () => void;
21
+ }
22
+ export interface RightDockRegion {
23
+ view: string | null;
24
+ open: boolean;
25
+ width: number;
26
+ dragging: boolean;
27
+ setView: (view: string | null | ((prev: string | null) => string | null)) => void;
28
+ setWidth: (width: number) => void;
29
+ startResize: (e: React.MouseEvent) => void;
30
+ resetWidth: () => void;
31
+ }
32
+ export interface ShellRegions {
33
+ left: DockRegion;
34
+ right: RightDockRegion;
35
+ /** What clicking a rail item does: toggles or switches the left dock. */
36
+ railClick: (view: string) => void;
37
+ openInRightDock: (view: string) => void;
38
+ toggleRightDock: () => void;
39
+ previousView: () => string | null;
40
+ /** Stable setters a panel reports its wanted sidebar width with. */
41
+ panelEditingSetter: (view: string) => (editing: EditingWidth) => void;
42
+ scopeEditingSetter: (view: string) => (editing: EditingWidth) => void;
43
+ }
44
+ export interface OpenTabOptions {
45
+ data?: Record<string, unknown>;
46
+ label?: string;
47
+ forceNewTab?: boolean;
48
+ }
49
+ export interface RestoreTarget {
50
+ instanceId: string;
51
+ restoredSessionId: string | null;
52
+ savedLabel?: string;
53
+ }
54
+ export interface ShellTabs {
55
+ list: Tab[];
56
+ /** Tabs shown in a tab bar: everything not sitting inside a split. */
57
+ topLevel: Tab[];
58
+ activeId: string;
59
+ active: Tab | undefined;
60
+ ready: boolean;
61
+ /** Tabs panels can type into. */
62
+ terminalTabs: Tab[];
63
+ /** The terminal command panels act on right now. */
64
+ targetTerminal: Tab | undefined;
65
+ showNumbers: boolean;
66
+ background: OpenTabRecord[];
67
+ setBackground: (next: OpenTabRecord[] | ((prev: OpenTabRecord[]) => OpenTabRecord[])) => void;
68
+ setActive: (id: string) => void;
69
+ setList: (next: Tab[] | ((prev: Tab[]) => Tab[])) => void;
70
+ reorder: (topLevel: Tab[]) => void;
71
+ open: (host: Host, type: TabType, restore?: RestoreTarget, options?: OpenTabOptions) => string;
72
+ openSingleton: (type: TabType, pendingEvent?: string, host?: Host, data?: Record<string, unknown>, label?: string) => string | undefined;
73
+ openMultiInstance: (type: TabType, options?: {
74
+ host?: Host;
75
+ data?: Record<string, unknown>;
76
+ label?: string;
77
+ }) => string;
78
+ connectHost: (host: Host, type?: TabType, options?: OpenTabOptions) => void;
79
+ close: (id: string) => Promise<void>;
80
+ rename: (id: string, label: string) => void;
81
+ refresh: (id: string) => void;
82
+ reconnectAll: () => void;
83
+ handleFor: (id: string) => TabHandle | null | undefined;
84
+ }
85
+ export interface EmptyPaneApi {
86
+ freeTabs: Tab[];
87
+ newTabOptions: NewTabOption[];
88
+ pickTab: (splitTabId: string, paneId: string, tabId: string) => void;
89
+ pickHost: (splitTabId: string, paneId: string, host: Host, pick: PickHostTarget) => void;
90
+ openType: (splitTabId: string, paneId: string, type: string) => void;
91
+ closePane: (splitTabId: string, paneId: string) => void;
92
+ }
93
+ export interface ShellSplit {
94
+ active: SplitTab | null;
95
+ /** The pane each on-screen tab sits in, for the active split only. */
96
+ paneIdByTabId: Map<string, string>;
97
+ focusedPaneId: string | null;
98
+ summaries: SplitSummary[];
99
+ activeFull: boolean;
100
+ handleAction: (action: TabSplitAction) => void;
101
+ viewActions: (splitTabId: string) => SplitViewActions;
102
+ emptyPane: EmptyPaneApi;
103
+ }
104
+ export interface ShellHosts {
105
+ list: Host[];
106
+ tree: HostFolder | null;
107
+ loading: boolean;
108
+ loaded: boolean;
109
+ reload: () => Promise<void>;
110
+ edit: (host: Host) => void;
111
+ }
112
+ export interface ShellPalette {
113
+ isOpen: boolean;
114
+ open: () => void;
115
+ close: () => void;
116
+ setOpen: (open: boolean | ((prev: boolean) => boolean)) => void;
117
+ }
118
+ export interface ShellSettingsProps {
119
+ username: string;
120
+ isAdmin: boolean;
121
+ onLogout: (options?: {
122
+ manual?: boolean;
123
+ }) => void;
124
+ userPrefs: UserPreferences;
125
+ onPrefsChange: (updates: Partial<UserPreferences>) => void;
126
+ onOpenHostTab: (host: Host) => void;
127
+ }
128
+ /** Everything the shell knows and can do, minus drawing it. */
129
+ export interface ShellController {
130
+ username: string;
131
+ isAdmin: boolean;
132
+ isMobile: boolean;
133
+ isElectron: boolean;
134
+ pluginsSettled: boolean;
135
+ logout: (options?: {
136
+ manual?: boolean;
137
+ }) => void;
138
+ tabs: ShellTabs;
139
+ split: ShellSplit;
140
+ hosts: ShellHosts;
141
+ regions: ShellRegions;
142
+ palette: ShellPalette;
143
+ fullscreen: {
144
+ active: boolean;
145
+ toggle: () => void;
146
+ };
147
+ /** One stable bag that forwards to the latest shell, for tabs and plugins. */
148
+ callbacks: TabShellCallbacks;
149
+ /** Same, but closes the sidebar on mobile after opening a tab. */
150
+ panelCallbacks: TabShellCallbacks;
151
+ settings: ShellSettingsProps;
152
+ /** Where the main area's confirm is captured, see ShellConfirmCapture. */
153
+ confirmRef: MutableRefObject<((options: ConfirmOptions) => Promise<boolean>) | null>;
154
+ /** Refits every visible terminal, e.g. after a pane resize ends. */
155
+ resizeAllTerminals: () => number;
156
+ }
@@ -0,0 +1,10 @@
1
+ import type { Host, HostFolder } from "../../../types/ui-types";
2
+ /** The saved hosts and their folder tree, kept fresh on change events. */
3
+ export declare function useHostList(): {
4
+ list: Host[];
5
+ listRef: import("react").RefObject<Host[]>;
6
+ tree: HostFolder;
7
+ loading: boolean;
8
+ loaded: boolean;
9
+ reload: () => Promise<void>;
10
+ };
@@ -0,0 +1,5 @@
1
+ import type { ShellRegions } from "./types";
2
+ /** The left sidebar and the right dock: what they show, open state and size. */
3
+ /** A dock's width after Reset width, in Normal-size pixels. */
4
+ export declare const DOCK_DEFAULT_WIDTH = 291;
5
+ export declare function useRegions(isMobile: boolean): ShellRegions;
@@ -0,0 +1,12 @@
1
+ import { type MutableRefObject } from "react";
2
+ import type { TabsState } from "./use-tabs";
3
+ import type { SplitActions } from "./use-split";
4
+ import type { ShellPalette, ShellRegions } from "./types";
5
+ /** Every shell-wide shortcut: custom bindings, palette, panes and tabs. */
6
+ export declare function useShellKeybindings({ tabsState, regions, palette, splitActionsRef, toggleFullscreen, }: {
7
+ tabsState: TabsState;
8
+ regions: ShellRegions;
9
+ palette: ShellPalette;
10
+ splitActionsRef: MutableRefObject<SplitActions | null>;
11
+ toggleFullscreen: () => void;
12
+ }): void;
@@ -0,0 +1,17 @@
1
+ import { type MutableRefObject } from "react";
2
+ import { type UserPreferences } from "../../main-axios";
3
+ import type { TabType } from "../../../types/ui-types";
4
+ /** Who is signed in and what the shell does around the tabs: prefs, health, logout. */
5
+ export declare function useShellLifecycle({ onLogout, openSingletonTabRef, }: {
6
+ onLogout: (options?: {
7
+ manual?: boolean;
8
+ }) => void;
9
+ openSingletonTabRef: MutableRefObject<(type: TabType) => string | undefined>;
10
+ }): {
11
+ isAdmin: boolean;
12
+ userPrefs: UserPreferences;
13
+ setUserPrefs: import("react").Dispatch<import("react").SetStateAction<UserPreferences>>;
14
+ userPrefsLoaded: boolean;
15
+ isAppFullscreen: boolean;
16
+ toggleAppFullscreen: () => Promise<void>;
17
+ };
@@ -0,0 +1,21 @@
1
+ import type { TabShellCallbacks } from "../tab-registry";
2
+ import { type NavDirection } from "../split/split-tree";
3
+ import { type TabsState } from "./use-tabs";
4
+ import type { ShellSplit } from "./types";
5
+ export interface SplitActions {
6
+ splitActive: (edge: "right" | "bottom") => void;
7
+ navigate: (direction: NavDirection) => boolean;
8
+ zoomFocused: () => boolean;
9
+ closeFocusedPane: () => void;
10
+ }
11
+ export declare function useSplit({ tabsState, isMobile, paneEls, callbacks, resizeAllTerminals, }: {
12
+ tabsState: TabsState;
13
+ isMobile: boolean;
14
+ paneEls: Map<string, HTMLDivElement>;
15
+ callbacks: TabShellCallbacks;
16
+ resizeAllTerminals: () => number;
17
+ }): {
18
+ split: ShellSplit;
19
+ splitShapeKey: string;
20
+ splitActionsRef: import("react").RefObject<SplitActions>;
21
+ };
@@ -0,0 +1,70 @@
1
+ import { type MutableRefObject } from "react";
2
+ import type { TabHandle } from "@termix-ssh/plugin-sdk/frontend";
3
+ import type { ConfirmOptions } from "../../components/surface/surface-scope";
4
+ import type { Host, Tab, TabType } from "../../../types/ui-types";
5
+ import { type OpenTabRecord, type UserPreferences } from "../../main-axios";
6
+ import type { OpenTabOptions, RestoreTarget } from "./types";
7
+ export declare function dashboardTab(label: string): Tab;
8
+ /** What the tab code needs from the split code, filled in by useSplit. */
9
+ export interface SplitOps {
10
+ unsplit: (splitTabId: string) => void;
11
+ closePaneOf: (splitTabId: string, paneId: string) => void;
12
+ }
13
+ export declare function useSplitLabel(): (number: number) => string;
14
+ export declare function useTabs({ hosts, hostsRef, hostsLoaded, reloadHosts, userPrefs, userPrefsLoaded, pluginsSettled, confirmRef, layoutDeps, }: {
15
+ hosts: Host[];
16
+ hostsRef: MutableRefObject<Host[]>;
17
+ hostsLoaded: boolean;
18
+ reloadHosts: () => Promise<void>;
19
+ userPrefs: UserPreferences;
20
+ userPrefsLoaded: boolean;
21
+ pluginsSettled: boolean;
22
+ confirmRef: MutableRefObject<((options: ConfirmOptions) => Promise<boolean>) | null>;
23
+ /** Region state whose change also counts as a layout change for plugins. */
24
+ layoutDeps: unknown[];
25
+ }): {
26
+ tabs: Tab[];
27
+ setTabs: import("react").Dispatch<import("react").SetStateAction<Tab[]>>;
28
+ activeTabId: string;
29
+ setActiveTabId: import("react").Dispatch<import("react").SetStateAction<string>>;
30
+ tabsReady: boolean;
31
+ backgroundTabRecords: OpenTabRecord[];
32
+ setBackgroundTabRecords: import("react").Dispatch<import("react").SetStateAction<OpenTabRecord[]>>;
33
+ tabsRef: import("react").RefObject<Tab[]>;
34
+ activeTabIdRef: import("react").RefObject<string>;
35
+ closeActiveTabRef: import("react").RefObject<() => void>;
36
+ reconnectAllRef: import("react").RefObject<() => void>;
37
+ terminalRefs: import("react").RefObject<Map<string, import("react").RefObject<unknown>>>;
38
+ splitOpsRef: import("react").RefObject<SplitOps>;
39
+ suppressPaneTargetRef: import("react").RefObject<boolean>;
40
+ pendingPaneTargetRef: import("react").RefObject<{
41
+ splitTabId: string;
42
+ paneId: string;
43
+ at: number;
44
+ fresh: boolean;
45
+ }>;
46
+ openSingletonTabRef: import("react").RefObject<(type: TabType, pendingEvent?: string, host?: Host, data?: Record<string, unknown>, tabLabel?: string) => string | undefined>;
47
+ hostsRef: MutableRefObject<Host[]>;
48
+ focusedSessionTabId: () => string | null;
49
+ targetPane: (splitTabId: string, paneId: string, fresh?: boolean) => void;
50
+ openTab: (host: Host, type: TabType, restore?: RestoreTarget, options?: OpenTabOptions) => string;
51
+ connectHost: (host: Host, preferredType?: TabType, options?: OpenTabOptions) => void;
52
+ saveQuickConnectHost: (tab: Tab, host: Host) => Promise<void>;
53
+ openMultiInstanceTab: (type: TabType, options?: {
54
+ host?: Host;
55
+ data?: Record<string, unknown>;
56
+ label?: string;
57
+ }) => string;
58
+ openSingletonTab: (type: TabType, pendingEvent?: string, host?: Host, data?: Record<string, unknown>, tabLabel?: string) => string | undefined;
59
+ doCloseTab: (id: string) => void;
60
+ closeTab: (id: string) => Promise<void>;
61
+ renameTab: (tabId: string, newLabel: string) => void;
62
+ refreshTab: (id: string) => void;
63
+ reconnectAllDisconnected: () => void;
64
+ reorderTopLevelTabs: (reordered: Tab[]) => void;
65
+ showTabNumbers: boolean;
66
+ terminalTabs: Tab[];
67
+ targetTerminalTab: Tab;
68
+ handleFor: (id: string) => TabHandle | null | undefined;
69
+ };
70
+ export type TabsState = ReturnType<typeof useTabs>;
@@ -0,0 +1,4 @@
1
+ import { type TabsState } from "./use-tabs";
2
+ import type { ShellRegions } from "./types";
3
+ /** Saving and applying a whole arrangement, for workspaces and plugins. */
4
+ export declare function useWorkspaceLayout(tabsState: TabsState, regions: ShellRegions): void;
@@ -0,0 +1,6 @@
1
+ import type { Tab } from "../../types/ui-types";
2
+ /** Includes hidden tabs and split children; each plugin decides whether it is idle. */
3
+ export declare function reconnectDisconnectedTabs(tabs: readonly Tab[]): {
4
+ reconnected: number;
5
+ failed: number;
6
+ };
@@ -0,0 +1,46 @@
1
+ import type { Host, SplitState, Tab, WorkspacePayload, WorkspaceTabSnapshot } from "../../types/ui-types";
2
+ export declare function isCapturableTabType(type: string): boolean;
3
+ /**
4
+ * Maps live tabs to snapshots, with a fresh slotId per tab. slotId is a
5
+ * stable key within the saved payload, distinct from Tab.id, which is
6
+ * regenerated every time a tab opens.
7
+ */
8
+ export declare function buildLayoutTabSnapshots(tabs: Tab[], genSlotId?: () => string): {
9
+ snapshots: WorkspaceTabSnapshot[];
10
+ slotIdByTabId: Map<string, string>;
11
+ };
12
+ /**
13
+ * The tab's plugin payload. Payloads saved before tabs carried `data` stored
14
+ * the fleet a fleet-inventory tab showed as a field of its own.
15
+ */
16
+ export declare function snapshotData(snapshot: WorkspaceTabSnapshot): Record<string, unknown> | undefined;
17
+ /**
18
+ * How to reopen one saved tab. "singleton" types go through
19
+ * openSingletonTab with an optional host; "host" types need a resolved host
20
+ * to open at all.
21
+ */
22
+ export declare function resolveLayoutTabTarget(snapshot: WorkspaceTabSnapshot, allHosts: Host[]): {
23
+ kind: "singleton";
24
+ host?: Host;
25
+ } | {
26
+ kind: "host";
27
+ host: Host;
28
+ } | {
29
+ kind: "skip";
30
+ };
31
+ export declare function buildLayoutPayload(input: {
32
+ tabs: Tab[];
33
+ activeTabId: string;
34
+ genSlotId?: () => string;
35
+ sidebar?: WorkspacePayload["sidebar"];
36
+ }): WorkspacePayload;
37
+ /**
38
+ * The splits a saved layout describes, with live tab ids. Version 1 payloads
39
+ * held one split as a fixed mode; it comes back with no label or slotId, so
40
+ * the caller names it.
41
+ */
42
+ export declare function resolveLayoutSplits(payload: WorkspacePayload, slotIdToTabId: Map<string, string>): {
43
+ slotId: string | null;
44
+ label: string | null;
45
+ split: SplitState;
46
+ }[];
@@ -0,0 +1,32 @@
1
+ import { type HostActionDef } from "../../sidebar/host-contributions";
2
+ import type { Host, Tab } from "../../../types/ui-types";
3
+ export interface NewTabOption {
4
+ type: string;
5
+ label: string;
6
+ icon?: React.ComponentType<{
7
+ className?: string;
8
+ }>;
9
+ }
10
+ export type PickHostTarget = {
11
+ action: HostActionDef;
12
+ } | {
13
+ action: HostActionDef;
14
+ item: {
15
+ id: string;
16
+ label: string;
17
+ };
18
+ };
19
+ /**
20
+ * What an empty pane shows: the tabs that could move in, new tabs to start,
21
+ * and every host with the ways to open it. Picking anything fills this pane.
22
+ */
23
+ export declare function EmptyPanePicker({ paneIndex, freeTabs, hosts, newTabOptions, onPickTab, onPickHost, onOpenType, onClosePane, }: {
24
+ paneIndex: number;
25
+ freeTabs: Tab[];
26
+ hosts: Host[];
27
+ newTabOptions: NewTabOption[];
28
+ onPickTab: (tabId: string) => void;
29
+ onPickHost: (host: Host, target: PickHostTarget) => void;
30
+ onOpenType: (type: string) => void;
31
+ onClosePane: () => void;
32
+ }): import("react").JSX.Element;
@@ -0,0 +1,9 @@
1
+ import { type RefObject } from "react";
2
+ /**
3
+ * Drop zones over the main area while a tab or pane is dragged. Over a
4
+ * split, each pane offers its four edges (split there) and its center (show
5
+ * it there). Over a plain tab only the edges count, to start a new split.
6
+ */
7
+ export declare function SplitDropOverlay({ containerRef, }: {
8
+ containerRef: RefObject<HTMLElement | null>;
9
+ }): import("react").ReactPortal;
@@ -0,0 +1,16 @@
1
+ import { type SplitPresetId } from "./split-presets";
2
+ import { type PaneEdge } from "./split-tree";
3
+ /** A small drawing of a preset's panes. */
4
+ export declare function PresetThumb({ id }: {
5
+ id: SplitPresetId;
6
+ }): import("react").JSX.Element;
7
+ /**
8
+ * The tab bar's split button: split the active tab right or down, or lay it
9
+ * out as one of the presets.
10
+ */
11
+ export declare function SplitLayoutMenu({ activeIsSplit, canAddPane, onSplit, onPreset, }: {
12
+ activeIsSplit: boolean;
13
+ canAddPane: boolean;
14
+ onSplit: (edge: Extract<PaneEdge, "right" | "bottom">) => void;
15
+ onPreset: (id: SplitPresetId) => void;
16
+ }): import("react").JSX.Element;
@@ -0,0 +1,31 @@
1
+ import React from "react";
2
+ import type { Tab } from "../../../types/ui-types";
3
+ import type { SplitTab } from "./split-tabs";
4
+ import { type PaneEdge } from "./split-tree";
5
+ export interface SplitViewActions {
6
+ focusPane: (paneId: string) => void;
7
+ resize: (nodeId: string, sizes: number[]) => void;
8
+ equalize: (nodeId: string) => void;
9
+ splitPane: (paneId: string, edge: Extract<PaneEdge, "right" | "bottom">) => void;
10
+ closePane: (paneId: string) => void;
11
+ closeSession: (tabId: string) => void;
12
+ moveToTab: (paneId: string) => void;
13
+ showInPane: (paneId: string, tabId: string | null) => void;
14
+ swapPanes: (firstId: string, secondId: string) => void;
15
+ toggleZoom: (paneId: string) => void;
16
+ /** A divider drag finished, so sessions can fit their new size. */
17
+ resizeEnd: () => void;
18
+ }
19
+ /**
20
+ * A split tab's panes. Each pane with a tab renders an empty host element;
21
+ * the shell moves the tab's own DOM node into it, so switching panes never
22
+ * remounts a session.
23
+ */
24
+ export declare function SplitView({ splitTab, tabs, isMobile, actions, onPaneContentRef, renderEmptyPane, }: {
25
+ splitTab: SplitTab;
26
+ tabs: Tab[];
27
+ isMobile: boolean;
28
+ actions: SplitViewActions;
29
+ onPaneContentRef: (paneId: string, el: HTMLDivElement | null) => void;
30
+ renderEmptyPane: (paneId: string, paneIndex: number) => React.ReactNode;
31
+ }): React.JSX.Element;
@@ -0,0 +1,58 @@
1
+ import type { DropTarget } from "./split-tree";
2
+ /**
3
+ * Dragging a tab or a pane onto the main area to split it. The tab bar and
4
+ * pane headers start a drag, the drop overlay over the main area answers
5
+ * where the pointer is, and the shell's handler acts on the drop.
6
+ */
7
+ export type SplitDragSource = {
8
+ kind: "tab";
9
+ tabId: string;
10
+ label: string;
11
+ } | {
12
+ kind: "pane";
13
+ splitTabId: string;
14
+ paneId: string;
15
+ label: string;
16
+ };
17
+ export interface SplitDropHover {
18
+ /** The pane under the pointer, or null over a view that is not split. */
19
+ paneId: string | null;
20
+ target: DropTarget;
21
+ rect: {
22
+ left: number;
23
+ top: number;
24
+ width: number;
25
+ height: number;
26
+ };
27
+ }
28
+ export interface SplitDragState {
29
+ source: SplitDragSource;
30
+ x: number;
31
+ y: number;
32
+ hover: SplitDropHover | null;
33
+ }
34
+ type HitTest = (x: number, y: number, source: SplitDragSource) => SplitDropHover | null;
35
+ type DropHandler = (source: SplitDragSource, hover: SplitDropHover) => void;
36
+ export declare function beginSplitDrag(source: SplitDragSource, x: number, y: number): void;
37
+ export declare function moveSplitDrag(x: number, y: number): void;
38
+ /** Ends the drag, dropping it where it is when `commit` is true. */
39
+ export declare function endSplitDrag(commit: boolean): void;
40
+ export declare function isSplitDragging(): boolean;
41
+ export declare function setSplitDropHitTest(next: HitTest): () => void;
42
+ export declare function setSplitDropHandler(next: DropHandler): () => void;
43
+ export declare function useSplitDrag(): SplitDragState | null;
44
+ /** Which zone of a rect a point falls in: an edge band, else the center. */
45
+ export declare function dropTargetAt(rect: {
46
+ left: number;
47
+ top: number;
48
+ width: number;
49
+ height: number;
50
+ }, x: number, y: number): DropTarget;
51
+ /** The part of a rect a drop target covers, for drawing the highlight. */
52
+ export declare function dropTargetRect(rect: {
53
+ left: number;
54
+ top: number;
55
+ width: number;
56
+ height: number;
57
+ }, target: DropTarget): SplitDropHover["rect"];
58
+ export {};