@termix-ssh/plugin-sdk 1.0.1 → 1.0.4
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 +74 -0
- package/LICENSE +202 -0
- package/README.md +4 -3
- package/cli/commands/build.mjs +37 -12
- package/cli/commands/dev.mjs +1 -1
- package/cli/commands/openapi.mjs +39 -0
- package/cli/commands/validate.mjs +67 -0
- package/cli/index.mjs +3 -0
- package/cli/lib/css-classes.mjs +37 -0
- package/dist/changelog.d.ts +3 -8
- package/dist/changelog.js +6 -14
- package/dist/docs.d.ts +28 -0
- package/dist/docs.js +39 -0
- package/dist/frontend.d.ts +17 -0
- package/dist/frontend.js +8 -0
- package/dist/host/{chunk-COGRSHKO.js → chunk-F5RZH6HE.js} +13 -2
- package/dist/host/{chunk-3KG44G55.js → chunk-O2OHNVFX.js} +1 -1
- package/dist/host/{chunk-7GL25GFS.js → chunk-RU4E5XLY.js} +531 -300
- package/dist/host/core-classes.json +1 -0
- package/dist/host/{linked-server-BD573BEG.js → linked-server-4VWYYABP.js} +1 -1
- package/dist/host/{rbac-api-7GHDJLU4.js → rbac-api-WIJVZH3M.js} +1 -1
- package/dist/host/testing-host.js +3 -3
- package/dist/host/types/src/ui/api/plugins-api.d.ts +23 -0
- package/dist/host/types/src/ui/api/system-status-api.d.ts +24 -0
- package/dist/host/types/src/ui/components/docs-link.d.ts +25 -0
- package/dist/host/types/src/ui/components/panel-layout.d.ts +3 -1
- package/dist/host/types/src/ui/hooks/use-installed-plugins.d.ts +6 -0
- package/dist/host/types/src/ui/lib/docs.d.ts +10 -0
- package/dist/host/types/src/ui/main-axios.d.ts +1 -0
- package/dist/host/types/src/ui/plugin-host/sdk-ui.d.ts +1 -0
- package/dist/host/types/src/ui/settings/settings-fields-util.d.ts +10 -0
- package/dist/host/ui.js +139 -110
- package/dist/host/{use-permissions-SKWXHWDJ.js → use-permissions-KIQCJ35M.js} +1 -1
- package/dist/manifest.d.ts +16 -1
- package/dist/manifest.js +84 -1
- package/dist/openapi.d.ts +43 -0
- package/dist/openapi.js +60 -0
- package/dist/testing/setup.js +1 -0
- package/package.json +12 -2
- package/schema/manifest.schema.json +27 -0
|
@@ -2,10 +2,11 @@ const __termixNoGlob = () => ({});
|
|
|
2
2
|
import {
|
|
3
3
|
hasPermission,
|
|
4
4
|
usePermissions
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-O2OHNVFX.js";
|
|
6
6
|
import {
|
|
7
7
|
PRESETS,
|
|
8
8
|
SYNC_CHANGED_EVENT,
|
|
9
|
+
TRUST_TOKEN_KEY,
|
|
9
10
|
authApi,
|
|
10
11
|
buildOriginWsUrl,
|
|
11
12
|
byOrderThenId,
|
|
@@ -38,7 +39,7 @@ import {
|
|
|
38
39
|
usePluginStore,
|
|
39
40
|
useTabTypes,
|
|
40
41
|
websocketAuthProtocols
|
|
41
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-F5RZH6HE.js";
|
|
42
43
|
import {
|
|
43
44
|
__export,
|
|
44
45
|
define_import_meta_env_default
|
|
@@ -14572,9 +14573,6 @@ function resetShellBridge() {
|
|
|
14572
14573
|
setShellHosts([], false);
|
|
14573
14574
|
}
|
|
14574
14575
|
|
|
14575
|
-
// src/ui/components/panel-layout.tsx
|
|
14576
|
-
import { Children as Children5, Fragment as Fragment11, useRef as useRef28 } from "react";
|
|
14577
|
-
|
|
14578
14576
|
// node_modules/lucide-react/dist/esm/icons/index.mjs
|
|
14579
14577
|
var icons_exports = {};
|
|
14580
14578
|
__export(icons_exports, {
|
|
@@ -48949,9 +48947,294 @@ var __iconData1857 = {
|
|
|
48949
48947
|
__iconData1857.node;
|
|
48950
48948
|
var ZoomOut = createLucideIcon(__iconData1857);
|
|
48951
48949
|
|
|
48952
|
-
// src/ui/components/
|
|
48950
|
+
// src/ui/components/docs-link.tsx
|
|
48951
|
+
import { useTranslation as useTranslation2 } from "react-i18next";
|
|
48952
|
+
|
|
48953
|
+
// packages/plugin-sdk/dist/docs.js
|
|
48954
|
+
function pluginDocsUrl(value) {
|
|
48955
|
+
if (typeof value !== "string")
|
|
48956
|
+
return null;
|
|
48957
|
+
try {
|
|
48958
|
+
const url = new URL(value.trim());
|
|
48959
|
+
if (url.protocol !== "https:")
|
|
48960
|
+
return null;
|
|
48961
|
+
return url.toString().replace(/\/$/, "");
|
|
48962
|
+
} catch {
|
|
48963
|
+
return null;
|
|
48964
|
+
}
|
|
48965
|
+
}
|
|
48966
|
+
function pluginDocsPage(base, page, anchor) {
|
|
48967
|
+
const clean = (page ?? "").replace(/^\/+|\/+$/g, "");
|
|
48968
|
+
const url = clean ? `${base}/${clean}` : base;
|
|
48969
|
+
return anchor ? `${url}#${anchor.replace(/^#/, "")}` : url;
|
|
48970
|
+
}
|
|
48971
|
+
|
|
48972
|
+
// src/ui/lib/docs-pages.json
|
|
48973
|
+
var docs_pages_default = {
|
|
48974
|
+
home: "",
|
|
48975
|
+
install: "install",
|
|
48976
|
+
updating: "install/updating",
|
|
48977
|
+
betas: "configure/betas",
|
|
48978
|
+
envVars: "configure/environment-variables",
|
|
48979
|
+
https: "configure/https",
|
|
48980
|
+
database: "configure/database",
|
|
48981
|
+
reverseProxy: "configure/reverse-proxy",
|
|
48982
|
+
desktopSync: "configure/desktop-sync",
|
|
48983
|
+
interface: "guide/interface",
|
|
48984
|
+
dashboard: "guide/dashboard",
|
|
48985
|
+
manage: "guide/manage",
|
|
48986
|
+
hosts: "guide/hosts",
|
|
48987
|
+
portKnocking: "guide/hosts#port-knocking",
|
|
48988
|
+
hostDefaults: "guide/host-defaults",
|
|
48989
|
+
credentials: "guide/credentials",
|
|
48990
|
+
sharing: "guide/sharing",
|
|
48991
|
+
account: "guide/account",
|
|
48992
|
+
accountSecurity: "guide/account#security",
|
|
48993
|
+
accountData: "guide/account#your-data",
|
|
48994
|
+
apiKeys: "guide/api-keys",
|
|
48995
|
+
commandPalette: "guide/command-palette",
|
|
48996
|
+
settings: "guide/settings",
|
|
48997
|
+
interfaceSettings: "guide/settings#interface",
|
|
48998
|
+
appearance: "guide/settings#appearance",
|
|
48999
|
+
keybindings: "guide/settings#keybindings",
|
|
49000
|
+
users: "guide/users",
|
|
49001
|
+
sessions: "guide/users#sessions",
|
|
49002
|
+
roles: "guide/roles",
|
|
49003
|
+
adminGeneral: "guide/admin-settings",
|
|
49004
|
+
branding: "guide/admin-settings#branding",
|
|
49005
|
+
adminDatabase: "guide/admin-settings#database",
|
|
49006
|
+
adminSsl: "configure/https",
|
|
49007
|
+
auditLog: "guide/audit-log",
|
|
49008
|
+
importExport: "guide/import-export",
|
|
49009
|
+
plugins: "guide/plugins",
|
|
49010
|
+
pluginCatalog: "plugins",
|
|
49011
|
+
cli: "cli",
|
|
49012
|
+
develop: "develop"
|
|
49013
|
+
};
|
|
49014
|
+
|
|
49015
|
+
// src/ui/lib/docs.ts
|
|
49016
|
+
var DOCS_URL = "https://docs.termix.site";
|
|
49017
|
+
function docsUrl(page = "home") {
|
|
49018
|
+
const path2 = docs_pages_default[page] ?? "";
|
|
49019
|
+
return path2 ? `${DOCS_URL}/${path2}` : `${DOCS_URL}/`;
|
|
49020
|
+
}
|
|
49021
|
+
|
|
49022
|
+
// src/ui/plugin-host/scope.tsx
|
|
49023
|
+
import {
|
|
49024
|
+
Component as Component2,
|
|
49025
|
+
createContext as createContext6,
|
|
49026
|
+
Suspense,
|
|
49027
|
+
useContext as useContext5
|
|
49028
|
+
} from "react";
|
|
49029
|
+
|
|
49030
|
+
// src/ui/plugin-host/host-scope.ts
|
|
49031
|
+
function isHostLike(value) {
|
|
49032
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
49033
|
+
if (!("id" in value)) return false;
|
|
49034
|
+
return "pluginSettings" in value || "ip" in value && "port" in value;
|
|
49035
|
+
}
|
|
49036
|
+
var cache = /* @__PURE__ */ new WeakMap();
|
|
49037
|
+
function scopeHost(value, pluginId) {
|
|
49038
|
+
if (!isHostLike(value)) return value;
|
|
49039
|
+
const full = shellHost(value.id)?.pluginSettings ?? value.pluginSettings;
|
|
49040
|
+
let perPlugin = cache.get(value);
|
|
49041
|
+
const hit = perPlugin?.get(pluginId);
|
|
49042
|
+
if (hit && hit.source === full) return hit.scoped;
|
|
49043
|
+
const own = full?.[pluginId];
|
|
49044
|
+
const scoped = { ...value, pluginSettings: own ? { [pluginId]: own } : {} };
|
|
49045
|
+
if (!perPlugin) {
|
|
49046
|
+
perPlugin = /* @__PURE__ */ new Map();
|
|
49047
|
+
cache.set(value, perPlugin);
|
|
49048
|
+
}
|
|
49049
|
+
perPlugin.set(pluginId, { source: full, scoped });
|
|
49050
|
+
return scoped;
|
|
49051
|
+
}
|
|
49052
|
+
function scopeHostArgs(args, pluginId) {
|
|
49053
|
+
return args.map(
|
|
49054
|
+
(arg) => isHostLike(arg) ? scopeHost(arg, pluginId) : scopeHostFields(arg, pluginId)
|
|
49055
|
+
);
|
|
49056
|
+
}
|
|
49057
|
+
var HOST_FIELDS = ["host", "sshHost", "hostConfig"];
|
|
49058
|
+
function scopeHostFields(value, pluginId) {
|
|
49059
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return value;
|
|
49060
|
+
const record = value;
|
|
49061
|
+
let next = null;
|
|
49062
|
+
for (const field of HOST_FIELDS) {
|
|
49063
|
+
if (!(field in record)) continue;
|
|
49064
|
+
const scoped = scopeHost(record[field], pluginId);
|
|
49065
|
+
if (scoped === record[field]) continue;
|
|
49066
|
+
next ??= { ...record };
|
|
49067
|
+
next[field] = scoped;
|
|
49068
|
+
}
|
|
49069
|
+
return next ?? value;
|
|
49070
|
+
}
|
|
49071
|
+
function scopeHostCallback(fn, pluginId) {
|
|
49072
|
+
if (!fn) return fn;
|
|
49073
|
+
return ((...args) => fn(...scopeHostArgs(args, pluginId)));
|
|
49074
|
+
}
|
|
49075
|
+
|
|
49076
|
+
// src/ui/plugin-host/scope.tsx
|
|
48953
49077
|
import { useTranslation } from "react-i18next";
|
|
48954
|
-
import {
|
|
49078
|
+
import { jsx as jsx29, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
49079
|
+
var PluginScopeContext = createContext6(null);
|
|
49080
|
+
function usePluginScope() {
|
|
49081
|
+
return useContext5(PluginScopeContext);
|
|
49082
|
+
}
|
|
49083
|
+
function CrashNotice({
|
|
49084
|
+
pluginId,
|
|
49085
|
+
onRetry
|
|
49086
|
+
}) {
|
|
49087
|
+
const { t } = useTranslation();
|
|
49088
|
+
const name = getPluginRecord(pluginId)?.summary.name ?? pluginId;
|
|
49089
|
+
return /* @__PURE__ */ jsxs7("div", { className: "flex flex-col items-center justify-center gap-2 p-4 text-center text-sm text-muted-foreground", children: [
|
|
49090
|
+
/* @__PURE__ */ jsx29("span", { children: t("plugins.runtime.crashed", { name }) }),
|
|
49091
|
+
/* @__PURE__ */ jsx29(
|
|
49092
|
+
"button",
|
|
49093
|
+
{
|
|
49094
|
+
type: "button",
|
|
49095
|
+
className: "text-xs underline underline-offset-2 hover:text-foreground",
|
|
49096
|
+
onClick: onRetry,
|
|
49097
|
+
children: t("plugins.runtime.retry")
|
|
49098
|
+
}
|
|
49099
|
+
)
|
|
49100
|
+
] });
|
|
49101
|
+
}
|
|
49102
|
+
var PluginErrorBoundary = class extends Component2 {
|
|
49103
|
+
state = { error: false };
|
|
49104
|
+
static getDerivedStateFromError() {
|
|
49105
|
+
return { error: true };
|
|
49106
|
+
}
|
|
49107
|
+
componentDidCatch(error, info) {
|
|
49108
|
+
console.error(
|
|
49109
|
+
`[plugins] ${this.props.pluginId} crashed while rendering`,
|
|
49110
|
+
error,
|
|
49111
|
+
info.componentStack
|
|
49112
|
+
);
|
|
49113
|
+
}
|
|
49114
|
+
render() {
|
|
49115
|
+
if (this.state.error) {
|
|
49116
|
+
return /* @__PURE__ */ jsx29(
|
|
49117
|
+
CrashNotice,
|
|
49118
|
+
{
|
|
49119
|
+
pluginId: this.props.pluginId,
|
|
49120
|
+
onRetry: () => this.setState({ error: false })
|
|
49121
|
+
}
|
|
49122
|
+
);
|
|
49123
|
+
}
|
|
49124
|
+
return this.props.children;
|
|
49125
|
+
}
|
|
49126
|
+
};
|
|
49127
|
+
function PluginScope({
|
|
49128
|
+
pluginId,
|
|
49129
|
+
children
|
|
49130
|
+
}) {
|
|
49131
|
+
return /* @__PURE__ */ jsx29(PluginScopeContext.Provider, { value: pluginId, children: /* @__PURE__ */ jsx29(PluginErrorBoundary, { pluginId, children: /* @__PURE__ */ jsx29(Suspense, { fallback: null, children }) }) });
|
|
49132
|
+
}
|
|
49133
|
+
function withPluginScope(pluginId, Inner) {
|
|
49134
|
+
function Scoped(props) {
|
|
49135
|
+
return /* @__PURE__ */ jsx29(PluginScope, { pluginId, children: /* @__PURE__ */ jsx29(Inner, { ...scopeHostFields(props, pluginId) }) });
|
|
49136
|
+
}
|
|
49137
|
+
Scoped.displayName = `Plugin(${pluginId}:${Inner.displayName ?? Inner.name ?? "Component"})`;
|
|
49138
|
+
return Scoped;
|
|
49139
|
+
}
|
|
49140
|
+
var IconBoundary = class extends Component2 {
|
|
49141
|
+
state = { error: false };
|
|
49142
|
+
static getDerivedStateFromError() {
|
|
49143
|
+
return { error: true };
|
|
49144
|
+
}
|
|
49145
|
+
componentDidCatch(error) {
|
|
49146
|
+
console.error(`[plugins] ${this.props.pluginId} icon failed`, error);
|
|
49147
|
+
}
|
|
49148
|
+
render() {
|
|
49149
|
+
return this.state.error ? null : this.props.children;
|
|
49150
|
+
}
|
|
49151
|
+
};
|
|
49152
|
+
function withIconBoundary(pluginId, Icon2) {
|
|
49153
|
+
if (!Icon2) return void 0;
|
|
49154
|
+
function SafeIcon(props) {
|
|
49155
|
+
return /* @__PURE__ */ jsx29(IconBoundary, { pluginId, children: /* @__PURE__ */ jsx29(Icon2, { ...props }) });
|
|
49156
|
+
}
|
|
49157
|
+
SafeIcon.displayName = `PluginIcon(${pluginId})`;
|
|
49158
|
+
return SafeIcon;
|
|
49159
|
+
}
|
|
49160
|
+
function guardCallback(pluginId, fn, fallback) {
|
|
49161
|
+
if (!fn) return void 0;
|
|
49162
|
+
return (...args) => {
|
|
49163
|
+
try {
|
|
49164
|
+
return fn(...args);
|
|
49165
|
+
} catch (error) {
|
|
49166
|
+
console.error(`[plugins] ${pluginId} callback failed`, error);
|
|
49167
|
+
return fallback;
|
|
49168
|
+
}
|
|
49169
|
+
};
|
|
49170
|
+
}
|
|
49171
|
+
|
|
49172
|
+
// src/ui/components/docs-link.tsx
|
|
49173
|
+
import { jsx as jsx30 } from "react/jsx-runtime";
|
|
49174
|
+
function usePluginDocsUrl(pluginId, page, anchor) {
|
|
49175
|
+
const { records } = usePluginStore();
|
|
49176
|
+
const base = pluginId ? records.get(pluginId)?.summary.docs : void 0;
|
|
49177
|
+
return base ? pluginDocsPage(base, page, anchor) : null;
|
|
49178
|
+
}
|
|
49179
|
+
function DocsLink({
|
|
49180
|
+
core,
|
|
49181
|
+
page,
|
|
49182
|
+
anchor,
|
|
49183
|
+
href,
|
|
49184
|
+
variant = "text",
|
|
49185
|
+
children,
|
|
49186
|
+
className
|
|
49187
|
+
}) {
|
|
49188
|
+
const { t } = useTranslation2();
|
|
49189
|
+
const pluginId = usePluginScope();
|
|
49190
|
+
const pluginUrl = usePluginDocsUrl(
|
|
49191
|
+
page !== void 0 ? pluginId : null,
|
|
49192
|
+
page,
|
|
49193
|
+
anchor
|
|
49194
|
+
);
|
|
49195
|
+
const url = href ?? (core ? withAnchor(docsUrl(core), anchor) : null) ?? pluginUrl;
|
|
49196
|
+
if (!url) return null;
|
|
49197
|
+
const label = t("common.docs");
|
|
49198
|
+
if (variant === "icon") {
|
|
49199
|
+
return /* @__PURE__ */ jsx30(
|
|
49200
|
+
"a",
|
|
49201
|
+
{
|
|
49202
|
+
href: url,
|
|
49203
|
+
target: "_blank",
|
|
49204
|
+
rel: "noopener noreferrer",
|
|
49205
|
+
title: label,
|
|
49206
|
+
"aria-label": label,
|
|
49207
|
+
className: cn(
|
|
49208
|
+
"flex size-7 shrink-0 items-center justify-center text-muted-foreground transition-colors hover:bg-muted/40 hover:text-foreground",
|
|
49209
|
+
className
|
|
49210
|
+
),
|
|
49211
|
+
children: /* @__PURE__ */ jsx30(BookOpen, { className: "size-3.5" })
|
|
49212
|
+
}
|
|
49213
|
+
);
|
|
49214
|
+
}
|
|
49215
|
+
return /* @__PURE__ */ jsx30(
|
|
49216
|
+
"a",
|
|
49217
|
+
{
|
|
49218
|
+
href: url,
|
|
49219
|
+
target: "_blank",
|
|
49220
|
+
rel: "noopener noreferrer",
|
|
49221
|
+
className: cn(
|
|
49222
|
+
"shrink-0 text-[10px] text-accent-brand hover:underline",
|
|
49223
|
+
className
|
|
49224
|
+
),
|
|
49225
|
+
children: children ?? label
|
|
49226
|
+
}
|
|
49227
|
+
);
|
|
49228
|
+
}
|
|
49229
|
+
function withAnchor(url, anchor) {
|
|
49230
|
+
if (!anchor) return url;
|
|
49231
|
+
return `${url.split("#")[0]}#${anchor.replace(/^#/, "")}`;
|
|
49232
|
+
}
|
|
49233
|
+
|
|
49234
|
+
// src/ui/components/panel-layout.tsx
|
|
49235
|
+
import { Children as Children5, Fragment as Fragment11, useRef as useRef28 } from "react";
|
|
49236
|
+
import { useTranslation as useTranslation3 } from "react-i18next";
|
|
49237
|
+
import { Fragment as Fragment12, jsx as jsx31, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
48955
49238
|
var PANEL = {
|
|
48956
49239
|
body: "p-2.5",
|
|
48957
49240
|
gap: "gap-2",
|
|
@@ -48970,10 +49253,11 @@ function PanelShell({
|
|
|
48970
49253
|
tabs,
|
|
48971
49254
|
footer,
|
|
48972
49255
|
scroll = true,
|
|
49256
|
+
docs,
|
|
48973
49257
|
className,
|
|
48974
49258
|
children
|
|
48975
49259
|
}) {
|
|
48976
|
-
const body = /* @__PURE__ */
|
|
49260
|
+
const body = /* @__PURE__ */ jsx31(
|
|
48977
49261
|
"div",
|
|
48978
49262
|
{
|
|
48979
49263
|
className: cn(
|
|
@@ -48984,43 +49268,49 @@ function PanelShell({
|
|
|
48984
49268
|
children
|
|
48985
49269
|
}
|
|
48986
49270
|
);
|
|
48987
|
-
const bands = /* @__PURE__ */
|
|
48988
|
-
toolbar && /* @__PURE__ */
|
|
49271
|
+
const bands = /* @__PURE__ */ jsxs8(Fragment12, { children: [
|
|
49272
|
+
toolbar && /* @__PURE__ */ jsx31(
|
|
48989
49273
|
"div",
|
|
48990
49274
|
{
|
|
48991
49275
|
className: `flex shrink-0 items-center gap-2 border-b border-border ${PANEL.band}`,
|
|
48992
49276
|
children: toolbar
|
|
48993
49277
|
}
|
|
48994
49278
|
),
|
|
48995
|
-
tabs && /* @__PURE__ */
|
|
49279
|
+
tabs && /* @__PURE__ */ jsx31("div", { className: "shrink-0 border-b border-border px-1", children: tabs })
|
|
48996
49280
|
] });
|
|
48997
|
-
const foot = footer && /* @__PURE__ */
|
|
49281
|
+
const foot = footer && /* @__PURE__ */ jsx31("div", { className: "flex shrink-0 items-center gap-2 border-t border-border px-3 py-2", children: footer });
|
|
48998
49282
|
if (!chrome) {
|
|
48999
|
-
return /* @__PURE__ */
|
|
49283
|
+
return /* @__PURE__ */ jsxs8("div", { className: "flex min-h-0 flex-1 flex-col", children: [
|
|
49000
49284
|
bands,
|
|
49001
49285
|
body,
|
|
49002
49286
|
foot
|
|
49003
49287
|
] });
|
|
49004
49288
|
}
|
|
49005
|
-
return /* @__PURE__ */
|
|
49006
|
-
/* @__PURE__ */
|
|
49289
|
+
return /* @__PURE__ */ jsxs8("div", { className: "flex h-full min-h-0 flex-1 flex-col overflow-hidden bg-background", children: [
|
|
49290
|
+
/* @__PURE__ */ jsxs8(
|
|
49007
49291
|
"header",
|
|
49008
49292
|
{
|
|
49009
49293
|
className: `flex ${PANEL.header} shrink-0 flex-row items-center border-b border-border`,
|
|
49010
49294
|
children: [
|
|
49011
|
-
leading && /* @__PURE__ */
|
|
49012
|
-
|
|
49013
|
-
/* @__PURE__ */
|
|
49014
|
-
|
|
49015
|
-
|
|
49016
|
-
|
|
49017
|
-
|
|
49018
|
-
|
|
49019
|
-
|
|
49020
|
-
|
|
49295
|
+
leading && /* @__PURE__ */ jsx31("div", { className: "flex h-full shrink-0 border-r border-border", children: leading }),
|
|
49296
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex min-w-0 flex-1 items-center gap-2 px-3", children: [
|
|
49297
|
+
icon && /* @__PURE__ */ jsx31("span", { className: "shrink-0 text-accent-brand", children: icon }),
|
|
49298
|
+
/* @__PURE__ */ jsx31("span", { className: "truncate text-base font-bold tracking-tight", children: title }),
|
|
49299
|
+
status && /* @__PURE__ */ jsxs8(Fragment12, { children: [
|
|
49300
|
+
/* @__PURE__ */ jsx31(
|
|
49301
|
+
Separator4,
|
|
49302
|
+
{
|
|
49303
|
+
orientation: "vertical",
|
|
49304
|
+
className: "h-4 data-[orientation=vertical]:self-center"
|
|
49305
|
+
}
|
|
49306
|
+
),
|
|
49307
|
+
/* @__PURE__ */ jsx31("span", { className: "truncate text-[10px] font-semibold uppercase tracking-widest text-muted-foreground", children: status })
|
|
49021
49308
|
] })
|
|
49022
49309
|
] }),
|
|
49023
|
-
actions4 && /* @__PURE__ */
|
|
49310
|
+
(actions4 || docs) && /* @__PURE__ */ jsxs8("div", { className: "flex shrink-0 items-center gap-1 px-2", children: [
|
|
49311
|
+
actions4,
|
|
49312
|
+
docs && /* @__PURE__ */ jsx31(DocsLink, { href: docs, variant: "icon" })
|
|
49313
|
+
] })
|
|
49024
49314
|
]
|
|
49025
49315
|
}
|
|
49026
49316
|
),
|
|
@@ -49034,9 +49324,9 @@ function BackButton({
|
|
|
49034
49324
|
label,
|
|
49035
49325
|
className
|
|
49036
49326
|
}) {
|
|
49037
|
-
const { t } =
|
|
49327
|
+
const { t } = useTranslation3();
|
|
49038
49328
|
const text = label ?? t("common.back");
|
|
49039
|
-
return /* @__PURE__ */
|
|
49329
|
+
return /* @__PURE__ */ jsx31(
|
|
49040
49330
|
"button",
|
|
49041
49331
|
{
|
|
49042
49332
|
type: "button",
|
|
@@ -49047,7 +49337,7 @@ function BackButton({
|
|
|
49047
49337
|
"flex h-full w-12.5 shrink-0 items-center justify-center text-muted-foreground transition-colors hover:bg-muted/40 hover:text-foreground focus-visible:ring-1 focus-visible:ring-ring",
|
|
49048
49338
|
className
|
|
49049
49339
|
),
|
|
49050
|
-
children: /* @__PURE__ */
|
|
49340
|
+
children: /* @__PURE__ */ jsx31(ArrowLeft, { className: "size-4" })
|
|
49051
49341
|
}
|
|
49052
49342
|
);
|
|
49053
49343
|
}
|
|
@@ -49063,10 +49353,10 @@ function PanelSearch({
|
|
|
49063
49353
|
inputRef,
|
|
49064
49354
|
className
|
|
49065
49355
|
}) {
|
|
49066
|
-
const { t } =
|
|
49356
|
+
const { t } = useTranslation3();
|
|
49067
49357
|
const localRef = useRef28(null);
|
|
49068
49358
|
const text = placeholder ?? t("common.search");
|
|
49069
|
-
return /* @__PURE__ */
|
|
49359
|
+
return /* @__PURE__ */ jsxs8(
|
|
49070
49360
|
"div",
|
|
49071
49361
|
{
|
|
49072
49362
|
className: cn(
|
|
@@ -49075,8 +49365,8 @@ function PanelSearch({
|
|
|
49075
49365
|
className
|
|
49076
49366
|
),
|
|
49077
49367
|
children: [
|
|
49078
|
-
/* @__PURE__ */
|
|
49079
|
-
/* @__PURE__ */
|
|
49368
|
+
/* @__PURE__ */ jsx31(Search, { className: "pointer-events-none absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" }),
|
|
49369
|
+
/* @__PURE__ */ jsx31(
|
|
49080
49370
|
"input",
|
|
49081
49371
|
{
|
|
49082
49372
|
ref: (el) => {
|
|
@@ -49106,7 +49396,7 @@ function PanelSearch({
|
|
|
49106
49396
|
className: "h-8 w-full min-w-0 border border-input bg-transparent pl-8 pr-7 text-xs outline-none transition-colors placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-1 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 dark:bg-input/30"
|
|
49107
49397
|
}
|
|
49108
49398
|
),
|
|
49109
|
-
value && /* @__PURE__ */
|
|
49399
|
+
value && /* @__PURE__ */ jsx31(
|
|
49110
49400
|
"button",
|
|
49111
49401
|
{
|
|
49112
49402
|
type: "button",
|
|
@@ -49117,7 +49407,7 @@ function PanelSearch({
|
|
|
49117
49407
|
localRef.current?.focus();
|
|
49118
49408
|
},
|
|
49119
49409
|
className: "absolute right-1.5 top-1/2 flex size-5 -translate-y-1/2 items-center justify-center text-muted-foreground hover:text-foreground",
|
|
49120
|
-
children: /* @__PURE__ */
|
|
49410
|
+
children: /* @__PURE__ */ jsx31(X, { className: "size-3" })
|
|
49121
49411
|
}
|
|
49122
49412
|
)
|
|
49123
49413
|
]
|
|
@@ -49130,14 +49420,14 @@ function Segmented({
|
|
|
49130
49420
|
options: options2,
|
|
49131
49421
|
className
|
|
49132
49422
|
}) {
|
|
49133
|
-
return /* @__PURE__ */
|
|
49423
|
+
return /* @__PURE__ */ jsx31(
|
|
49134
49424
|
"div",
|
|
49135
49425
|
{
|
|
49136
49426
|
role: "radiogroup",
|
|
49137
49427
|
className: cn("flex items-center border border-border", className),
|
|
49138
49428
|
children: options2.map((option, i) => {
|
|
49139
49429
|
const active = option.value === value;
|
|
49140
|
-
return /* @__PURE__ */
|
|
49430
|
+
return /* @__PURE__ */ jsxs8(
|
|
49141
49431
|
"button",
|
|
49142
49432
|
{
|
|
49143
49433
|
type: "button",
|
|
@@ -49153,7 +49443,7 @@ function Segmented({
|
|
|
49153
49443
|
children: [
|
|
49154
49444
|
option.icon,
|
|
49155
49445
|
option.label,
|
|
49156
|
-
option.count !== void 0 && /* @__PURE__ */
|
|
49446
|
+
option.count !== void 0 && /* @__PURE__ */ jsx31("span", { className: "text-[10px] tabular-nums opacity-60", children: option.count })
|
|
49157
49447
|
]
|
|
49158
49448
|
},
|
|
49159
49449
|
option.value
|
|
@@ -49168,35 +49458,35 @@ function ViewToggle({
|
|
|
49168
49458
|
density,
|
|
49169
49459
|
onDensity
|
|
49170
49460
|
}) {
|
|
49171
|
-
const { t } =
|
|
49172
|
-
return /* @__PURE__ */
|
|
49173
|
-
/* @__PURE__ */
|
|
49461
|
+
const { t } = useTranslation3();
|
|
49462
|
+
return /* @__PURE__ */ jsxs8("div", { className: "flex items-center border border-border", children: [
|
|
49463
|
+
/* @__PURE__ */ jsx31(
|
|
49174
49464
|
ToggleButton,
|
|
49175
49465
|
{
|
|
49176
49466
|
active: view === "grid",
|
|
49177
49467
|
onClick: () => onView("grid"),
|
|
49178
49468
|
title: t("panel.gridView"),
|
|
49179
|
-
children: /* @__PURE__ */
|
|
49469
|
+
children: /* @__PURE__ */ jsx31(Grid3x3, { className: "size-4" })
|
|
49180
49470
|
}
|
|
49181
49471
|
),
|
|
49182
|
-
/* @__PURE__ */
|
|
49472
|
+
/* @__PURE__ */ jsx31(
|
|
49183
49473
|
ToggleButton,
|
|
49184
49474
|
{
|
|
49185
49475
|
active: view === "list",
|
|
49186
49476
|
onClick: () => onView("list"),
|
|
49187
49477
|
title: t("panel.listView"),
|
|
49188
49478
|
bordered: true,
|
|
49189
|
-
children: /* @__PURE__ */
|
|
49479
|
+
children: /* @__PURE__ */ jsx31(List2, { className: "size-4" })
|
|
49190
49480
|
}
|
|
49191
49481
|
),
|
|
49192
|
-
density && onDensity && /* @__PURE__ */
|
|
49482
|
+
density && onDensity && /* @__PURE__ */ jsx31(
|
|
49193
49483
|
ToggleButton,
|
|
49194
49484
|
{
|
|
49195
49485
|
active: density === "compact",
|
|
49196
49486
|
onClick: () => onDensity(density === "compact" ? "comfortable" : "compact"),
|
|
49197
49487
|
title: density === "compact" ? t("panel.comfortableRows") : t("panel.compactRows"),
|
|
49198
49488
|
bordered: true,
|
|
49199
|
-
children: /* @__PURE__ */
|
|
49489
|
+
children: /* @__PURE__ */ jsx31(Rows3, { className: "size-4" })
|
|
49200
49490
|
}
|
|
49201
49491
|
)
|
|
49202
49492
|
] });
|
|
@@ -49208,7 +49498,7 @@ function ToggleButton({
|
|
|
49208
49498
|
bordered,
|
|
49209
49499
|
children
|
|
49210
49500
|
}) {
|
|
49211
|
-
return /* @__PURE__ */
|
|
49501
|
+
return /* @__PURE__ */ jsx31(
|
|
49212
49502
|
"button",
|
|
49213
49503
|
{
|
|
49214
49504
|
type: "button",
|
|
@@ -49231,9 +49521,9 @@ function Facts({
|
|
|
49231
49521
|
}) {
|
|
49232
49522
|
const items = Children5.toArray(children).filter(Boolean);
|
|
49233
49523
|
if (items.length === 0) return null;
|
|
49234
|
-
return /* @__PURE__ */
|
|
49235
|
-
i > 0 && /* @__PURE__ */
|
|
49236
|
-
/* @__PURE__ */
|
|
49524
|
+
return /* @__PURE__ */ jsx31("span", { className: cn("flex min-w-0 items-center gap-2", className), children: items.map((child, i) => /* @__PURE__ */ jsxs8(Fragment11, { children: [
|
|
49525
|
+
i > 0 && /* @__PURE__ */ jsx31("span", { "aria-hidden": true, className: "h-3 w-px shrink-0 bg-border" }),
|
|
49526
|
+
/* @__PURE__ */ jsx31("span", { className: "min-w-0 truncate", children: child })
|
|
49237
49527
|
] }, i)) });
|
|
49238
49528
|
}
|
|
49239
49529
|
function GroupHeading({
|
|
@@ -49242,10 +49532,10 @@ function GroupHeading({
|
|
|
49242
49532
|
action,
|
|
49243
49533
|
className
|
|
49244
49534
|
}) {
|
|
49245
|
-
return /* @__PURE__ */
|
|
49246
|
-
/* @__PURE__ */
|
|
49247
|
-
count3 !== void 0 && /* @__PURE__ */
|
|
49248
|
-
/* @__PURE__ */
|
|
49535
|
+
return /* @__PURE__ */ jsxs8("div", { className: cn("flex items-center gap-2", className), children: [
|
|
49536
|
+
/* @__PURE__ */ jsx31("span", { className: "text-[10px] font-semibold uppercase tracking-widest text-muted-foreground", children: title }),
|
|
49537
|
+
count3 !== void 0 && /* @__PURE__ */ jsx31("span", { className: "text-[10px] tabular-nums text-muted-foreground/60", children: count3 }),
|
|
49538
|
+
/* @__PURE__ */ jsx31("div", { className: "h-px flex-1 bg-border" }),
|
|
49249
49539
|
action
|
|
49250
49540
|
] });
|
|
49251
49541
|
}
|
|
@@ -49257,9 +49547,9 @@ var PROMPT_DESTRUCTIVE_BUTTON = "inline-flex h-7 items-center justify-center gap
|
|
|
49257
49547
|
|
|
49258
49548
|
// src/ui/components/surface/surface-scope.tsx
|
|
49259
49549
|
import {
|
|
49260
|
-
createContext as
|
|
49550
|
+
createContext as createContext7,
|
|
49261
49551
|
useCallback as useCallback18,
|
|
49262
|
-
useContext as
|
|
49552
|
+
useContext as useContext6,
|
|
49263
49553
|
useEffect as useEffect27,
|
|
49264
49554
|
useId as useId2,
|
|
49265
49555
|
useLayoutEffect as useLayoutEffect5,
|
|
@@ -49268,9 +49558,9 @@ import {
|
|
|
49268
49558
|
useState as useState25
|
|
49269
49559
|
} from "react";
|
|
49270
49560
|
import { createPortal as createPortal3 } from "react-dom";
|
|
49271
|
-
import { useTranslation as
|
|
49272
|
-
import { Fragment as Fragment13, jsx as
|
|
49273
|
-
var ScopeContext =
|
|
49561
|
+
import { useTranslation as useTranslation4 } from "react-i18next";
|
|
49562
|
+
import { Fragment as Fragment13, jsx as jsx32, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
49563
|
+
var ScopeContext = createContext7(null);
|
|
49274
49564
|
function widest(widths) {
|
|
49275
49565
|
if (widths.includes("wide")) return "wide";
|
|
49276
49566
|
return widths.some(Boolean);
|
|
@@ -49339,7 +49629,7 @@ function SurfaceScope({
|
|
|
49339
49629
|
[kind, overlay, openView, closeView, views, confirm, close]
|
|
49340
49630
|
);
|
|
49341
49631
|
const current = confirms[0];
|
|
49342
|
-
return /* @__PURE__ */
|
|
49632
|
+
return /* @__PURE__ */ jsx32(ScopeContext.Provider, { value, children: /* @__PURE__ */ jsxs9(
|
|
49343
49633
|
"div",
|
|
49344
49634
|
{
|
|
49345
49635
|
className: cn(
|
|
@@ -49348,7 +49638,7 @@ function SurfaceScope({
|
|
|
49348
49638
|
),
|
|
49349
49639
|
children: [
|
|
49350
49640
|
children,
|
|
49351
|
-
/* @__PURE__ */
|
|
49641
|
+
/* @__PURE__ */ jsx32(
|
|
49352
49642
|
"div",
|
|
49353
49643
|
{
|
|
49354
49644
|
ref: setOverlay,
|
|
@@ -49358,7 +49648,7 @@ function SurfaceScope({
|
|
|
49358
49648
|
)
|
|
49359
49649
|
}
|
|
49360
49650
|
),
|
|
49361
|
-
current && /* @__PURE__ */
|
|
49651
|
+
current && /* @__PURE__ */ jsx32(
|
|
49362
49652
|
ConfirmCard,
|
|
49363
49653
|
{
|
|
49364
49654
|
options: current,
|
|
@@ -49371,13 +49661,13 @@ function SurfaceScope({
|
|
|
49371
49661
|
) });
|
|
49372
49662
|
}
|
|
49373
49663
|
function useSurfaceKind() {
|
|
49374
|
-
return
|
|
49664
|
+
return useContext6(ScopeContext)?.kind ?? null;
|
|
49375
49665
|
}
|
|
49376
49666
|
function useSurfaceClose() {
|
|
49377
|
-
return
|
|
49667
|
+
return useContext6(ScopeContext)?.close ?? null;
|
|
49378
49668
|
}
|
|
49379
49669
|
function useConfirm() {
|
|
49380
|
-
const scope =
|
|
49670
|
+
const scope = useContext6(ScopeContext);
|
|
49381
49671
|
return useCallback18(
|
|
49382
49672
|
(options2) => {
|
|
49383
49673
|
if (scope) return scope.confirm(options2);
|
|
@@ -49391,7 +49681,7 @@ function ConfirmCard({
|
|
|
49391
49681
|
options: options2,
|
|
49392
49682
|
onSettle
|
|
49393
49683
|
}) {
|
|
49394
|
-
const { t } =
|
|
49684
|
+
const { t } = useTranslation4();
|
|
49395
49685
|
const confirmRef = useRef29(null);
|
|
49396
49686
|
const titleId = useId2();
|
|
49397
49687
|
const destructive = options2.destructive ?? true;
|
|
@@ -49416,7 +49706,7 @@ function ConfirmCard({
|
|
|
49416
49706
|
if (previous && document.contains(previous)) previous.focus();
|
|
49417
49707
|
};
|
|
49418
49708
|
}, []);
|
|
49419
|
-
return /* @__PURE__ */
|
|
49709
|
+
return /* @__PURE__ */ jsx32(
|
|
49420
49710
|
PanePrompt,
|
|
49421
49711
|
{
|
|
49422
49712
|
open: true,
|
|
@@ -49427,8 +49717,8 @@ function ConfirmCard({
|
|
|
49427
49717
|
description: options2.description,
|
|
49428
49718
|
tone: destructive ? "destructive" : "default",
|
|
49429
49719
|
onCancel: () => onSettle(false),
|
|
49430
|
-
actions: /* @__PURE__ */
|
|
49431
|
-
/* @__PURE__ */
|
|
49720
|
+
actions: /* @__PURE__ */ jsxs9(Fragment13, { children: [
|
|
49721
|
+
/* @__PURE__ */ jsx32(
|
|
49432
49722
|
"button",
|
|
49433
49723
|
{
|
|
49434
49724
|
type: "button",
|
|
@@ -49437,7 +49727,7 @@ function ConfirmCard({
|
|
|
49437
49727
|
children: options2.cancelLabel ?? t("common.cancel")
|
|
49438
49728
|
}
|
|
49439
49729
|
),
|
|
49440
|
-
/* @__PURE__ */
|
|
49730
|
+
/* @__PURE__ */ jsxs9(
|
|
49441
49731
|
"button",
|
|
49442
49732
|
{
|
|
49443
49733
|
ref: confirmRef,
|
|
@@ -49446,7 +49736,7 @@ function ConfirmCard({
|
|
|
49446
49736
|
className: destructive ? PROMPT_DESTRUCTIVE_BUTTON : PROMPT_PRIMARY_BUTTON,
|
|
49447
49737
|
children: [
|
|
49448
49738
|
options2.confirmLabel ?? (destructive ? t("common.delete") : t("common.confirm")),
|
|
49449
|
-
/* @__PURE__ */
|
|
49739
|
+
/* @__PURE__ */ jsx32("span", { "aria-hidden": true, className: "ml-1.5 opacity-60", children: "\u21B5" })
|
|
49450
49740
|
]
|
|
49451
49741
|
}
|
|
49452
49742
|
)
|
|
@@ -49473,31 +49763,31 @@ function PanePrompt({
|
|
|
49473
49763
|
const fallbackId = useId2();
|
|
49474
49764
|
if (!open) return null;
|
|
49475
49765
|
const headingId = titleId ?? fallbackId;
|
|
49476
|
-
return /* @__PURE__ */
|
|
49766
|
+
return /* @__PURE__ */ jsx32(
|
|
49477
49767
|
"div",
|
|
49478
49768
|
{
|
|
49479
49769
|
className: cn(
|
|
49480
|
-
"motion-
|
|
49481
|
-
layer === "connection" ? "z-500 bg-canvas" : "z-50 bg-background/
|
|
49770
|
+
"motion-fade-enter absolute inset-0 flex items-center justify-center overflow-y-auto p-4",
|
|
49771
|
+
layer === "connection" ? "z-500 bg-canvas" : "z-50 bg-background/85"
|
|
49482
49772
|
),
|
|
49483
49773
|
style: layer === "connection" && backgroundColor ? { backgroundColor } : void 0,
|
|
49484
49774
|
onMouseDown: (e) => {
|
|
49485
49775
|
if (e.target === e.currentTarget) onCancel?.();
|
|
49486
49776
|
},
|
|
49487
|
-
children: /* @__PURE__ */
|
|
49777
|
+
children: /* @__PURE__ */ jsxs9(
|
|
49488
49778
|
"div",
|
|
49489
49779
|
{
|
|
49490
49780
|
role,
|
|
49491
49781
|
"aria-modal": "true",
|
|
49492
49782
|
"aria-labelledby": labelledBy ?? headingId,
|
|
49493
49783
|
className: cn(
|
|
49494
|
-
"my-auto flex w-full max-w-sm flex-col border bg-popover shadow-xl",
|
|
49784
|
+
"motion-context-enter my-auto flex w-full max-w-sm flex-col border bg-popover shadow-xl",
|
|
49495
49785
|
tone === "destructive" ? "border-destructive/40" : "border-border",
|
|
49496
49786
|
className
|
|
49497
49787
|
),
|
|
49498
49788
|
children: [
|
|
49499
|
-
/* @__PURE__ */
|
|
49500
|
-
icon && /* @__PURE__ */
|
|
49789
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-start gap-2.5 px-4 pt-4", children: [
|
|
49790
|
+
icon && /* @__PURE__ */ jsx32(
|
|
49501
49791
|
"span",
|
|
49502
49792
|
{
|
|
49503
49793
|
className: cn(
|
|
@@ -49507,8 +49797,8 @@ function PanePrompt({
|
|
|
49507
49797
|
children: icon
|
|
49508
49798
|
}
|
|
49509
49799
|
),
|
|
49510
|
-
/* @__PURE__ */
|
|
49511
|
-
/* @__PURE__ */
|
|
49800
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex min-w-0 flex-col gap-1", children: [
|
|
49801
|
+
/* @__PURE__ */ jsx32(
|
|
49512
49802
|
"p",
|
|
49513
49803
|
{
|
|
49514
49804
|
id: headingId,
|
|
@@ -49516,12 +49806,12 @@ function PanePrompt({
|
|
|
49516
49806
|
children: title
|
|
49517
49807
|
}
|
|
49518
49808
|
),
|
|
49519
|
-
description && /* @__PURE__ */
|
|
49809
|
+
description && /* @__PURE__ */ jsx32("div", { className: "text-xs leading-snug text-muted-foreground", children: description })
|
|
49520
49810
|
] })
|
|
49521
49811
|
] }),
|
|
49522
|
-
children && /* @__PURE__ */
|
|
49523
|
-
actions4 && /* @__PURE__ */
|
|
49524
|
-
!actions4 && /* @__PURE__ */
|
|
49812
|
+
children && /* @__PURE__ */ jsx32("div", { className: "px-4 pt-3", children }),
|
|
49813
|
+
actions4 && /* @__PURE__ */ jsx32("div", { className: "flex justify-end gap-2 px-4 py-3", children: actions4 }),
|
|
49814
|
+
!actions4 && /* @__PURE__ */ jsx32("div", { className: "h-4" })
|
|
49525
49815
|
]
|
|
49526
49816
|
}
|
|
49527
49817
|
)
|
|
@@ -49544,7 +49834,7 @@ function InlineView({
|
|
|
49544
49834
|
className,
|
|
49545
49835
|
children
|
|
49546
49836
|
}) {
|
|
49547
|
-
const scope =
|
|
49837
|
+
const scope = useContext6(ScopeContext);
|
|
49548
49838
|
const id = useId2();
|
|
49549
49839
|
const { openView, closeView } = scope ?? {};
|
|
49550
49840
|
useLayoutEffect5(() => {
|
|
@@ -49558,7 +49848,7 @@ function InlineView({
|
|
|
49558
49848
|
}, [onBeforeClose, onOpenChange]);
|
|
49559
49849
|
if (!open) return null;
|
|
49560
49850
|
const padded = scope?.kind === "tab" || scope?.kind === "pane";
|
|
49561
|
-
const view = /* @__PURE__ */
|
|
49851
|
+
const view = /* @__PURE__ */ jsx32(
|
|
49562
49852
|
"div",
|
|
49563
49853
|
{
|
|
49564
49854
|
className: cn(
|
|
@@ -49571,10 +49861,10 @@ function InlineView({
|
|
|
49571
49861
|
void requestClose();
|
|
49572
49862
|
}
|
|
49573
49863
|
},
|
|
49574
|
-
children: /* @__PURE__ */
|
|
49864
|
+
children: /* @__PURE__ */ jsx32(
|
|
49575
49865
|
PanelShell,
|
|
49576
49866
|
{
|
|
49577
|
-
leading: /* @__PURE__ */
|
|
49867
|
+
leading: /* @__PURE__ */ jsx32(BackButton, { onClick: () => void requestClose() }),
|
|
49578
49868
|
icon,
|
|
49579
49869
|
title,
|
|
49580
49870
|
status,
|
|
@@ -49582,7 +49872,7 @@ function InlineView({
|
|
|
49582
49872
|
toolbar,
|
|
49583
49873
|
footer,
|
|
49584
49874
|
scroll,
|
|
49585
|
-
children: bare ? children : /* @__PURE__ */
|
|
49875
|
+
children: bare ? children : /* @__PURE__ */ jsx32(
|
|
49586
49876
|
"div",
|
|
49587
49877
|
{
|
|
49588
49878
|
className: cn(
|
|
@@ -49601,7 +49891,7 @@ function InlineView({
|
|
|
49601
49891
|
if (scope?.overlay) return createPortal3(view, scope.overlay);
|
|
49602
49892
|
if (scope) return null;
|
|
49603
49893
|
return createPortal3(
|
|
49604
|
-
/* @__PURE__ */
|
|
49894
|
+
/* @__PURE__ */ jsx32("div", { className: "fixed inset-0 z-50 bg-background", children: view }),
|
|
49605
49895
|
document.body
|
|
49606
49896
|
);
|
|
49607
49897
|
}
|
|
@@ -50252,7 +50542,8 @@ var en_default = {
|
|
|
50252
50542
|
mobileSidebarDescription: "Displays the mobile sidebar.",
|
|
50253
50543
|
toggleSidebar: "Toggle Sidebar",
|
|
50254
50544
|
search: "Search...",
|
|
50255
|
-
new: "New"
|
|
50545
|
+
new: "New",
|
|
50546
|
+
docs: "Docs"
|
|
50256
50547
|
},
|
|
50257
50548
|
onboarding: {
|
|
50258
50549
|
stepCounter: "Step {{current}} of {{total}}",
|
|
@@ -50296,7 +50587,8 @@ var en_default = {
|
|
|
50296
50587
|
desktopLocalBody: "Everything is stored here. Nothing to set up.",
|
|
50297
50588
|
desktopLinkTitle: "With my Termix server",
|
|
50298
50589
|
desktopLinkBody: "Sign in to your server to use the same hosts and settings on every device.",
|
|
50299
|
-
desktopLinked: "Linked to {{server}}"
|
|
50590
|
+
desktopLinked: "Linked to {{server}}",
|
|
50591
|
+
pluginsDocsLink: "Read about each one"
|
|
50300
50592
|
},
|
|
50301
50593
|
nav: {
|
|
50302
50594
|
home: "Home",
|
|
@@ -50974,7 +51266,8 @@ var en_default = {
|
|
|
50974
51266
|
select: "Select",
|
|
50975
51267
|
toggleWith: "Toggle with",
|
|
50976
51268
|
pluginActions: "More actions",
|
|
50977
|
-
noTargetTab: "No terminal tab is open"
|
|
51269
|
+
noTargetTab: "No terminal tab is open",
|
|
51270
|
+
documentation: "Documentation"
|
|
50978
51271
|
},
|
|
50979
51272
|
splitScreen: {
|
|
50980
51273
|
title: "Split screen",
|
|
@@ -51082,7 +51375,7 @@ var en_default = {
|
|
|
51082
51375
|
empty: "No cards. Use Add below to place cards."
|
|
51083
51376
|
},
|
|
51084
51377
|
auth: {
|
|
51085
|
-
tagline: "Self-hosted
|
|
51378
|
+
tagline: "Self-hosted, plugin-based server management",
|
|
51086
51379
|
loginTitle: "Welcome back",
|
|
51087
51380
|
registerTitle: "Create Account",
|
|
51088
51381
|
forgotPassword: "Forgot Password?",
|
|
@@ -51216,7 +51509,7 @@ var en_default = {
|
|
|
51216
51509
|
title: "Dashboard",
|
|
51217
51510
|
loading: "Loading dashboard...",
|
|
51218
51511
|
github: "GitHub",
|
|
51219
|
-
|
|
51512
|
+
reportBug: "Report a bug",
|
|
51220
51513
|
discord: "Discord",
|
|
51221
51514
|
docs: "Docs",
|
|
51222
51515
|
donate: "Donate",
|
|
@@ -51732,10 +52025,6 @@ var en_default = {
|
|
|
51732
52025
|
twoFaOn: "On",
|
|
51733
52026
|
twoFaOff: "Off",
|
|
51734
52027
|
versionLabel: "Version",
|
|
51735
|
-
betaProgramTitle: "Beta Program",
|
|
51736
|
-
betaProgramDescription: "Try upcoming features early with the weekly rolling :beta Docker tag. Unstable, not for production.",
|
|
51737
|
-
betaProgramFeedback: "Found a bug? Report it here.",
|
|
51738
|
-
betaProgramLearnMore: "Learn More",
|
|
51739
52028
|
cliTitle: "Termix CLI",
|
|
51740
52029
|
cliDescription: "Open terminals, run commands and move files from your own shell.",
|
|
51741
52030
|
cliLearnMore: "Learn More",
|
|
@@ -51870,7 +52159,13 @@ var en_default = {
|
|
|
51870
52159
|
linkedProfileDescription: "This device uses your account on the server and keeps a copy of your data, so it still works offline.",
|
|
51871
52160
|
manageSync: "Manage sync",
|
|
51872
52161
|
setUpSync: "Link to a server",
|
|
51873
|
-
settingsTabsAndShortcuts: "Tabs and Shortcuts"
|
|
52162
|
+
settingsTabsAndShortcuts: "Tabs and Shortcuts",
|
|
52163
|
+
onBetaTitle: "You are on a beta",
|
|
52164
|
+
onBetaDescription: "Thanks for testing. Tell us what breaks.",
|
|
52165
|
+
tryBetaTitle: "Try new features early",
|
|
52166
|
+
tryBetaDescription: "Join the beta program in Updates.",
|
|
52167
|
+
sendBetaFeedback: "Send beta feedback",
|
|
52168
|
+
openUpdates: "Updates"
|
|
51874
52169
|
}
|
|
51875
52170
|
}
|
|
51876
52171
|
},
|
|
@@ -52152,8 +52447,9 @@ var en_default = {
|
|
|
52152
52447
|
releaseNotes: "Release notes",
|
|
52153
52448
|
noReleaseNotes: "No notes for this version.",
|
|
52154
52449
|
viewRelease: "View on GitHub",
|
|
52155
|
-
|
|
52156
|
-
|
|
52450
|
+
showOlderReleases: "Older releases ({{count}})",
|
|
52451
|
+
hideOlderReleases: "Hide older releases",
|
|
52452
|
+
showMoreChanges: "Show {{count}} more",
|
|
52157
52453
|
videoTitle: "{{name}} video",
|
|
52158
52454
|
changeTypes: {
|
|
52159
52455
|
added: "Added",
|
|
@@ -52165,6 +52461,7 @@ var en_default = {
|
|
|
52165
52461
|
},
|
|
52166
52462
|
installedBadge: "Installed",
|
|
52167
52463
|
incompatible: "Needs a newer Termix",
|
|
52464
|
+
features: "Features",
|
|
52168
52465
|
whatItCanDo: "What it can do",
|
|
52169
52466
|
addsToTermix: "Adds to Termix",
|
|
52170
52467
|
addsToTermixHint: "Uninstall and every one of these goes away.",
|
|
@@ -52209,7 +52506,27 @@ var en_default = {
|
|
|
52209
52506
|
unverifiedHint: "Installed from a file. Termix did not check or sign it.",
|
|
52210
52507
|
reportIssue: "Report an issue",
|
|
52211
52508
|
reportTo: "Report to {{author}}",
|
|
52212
|
-
|
|
52509
|
+
requestFeature: "Request a feature",
|
|
52510
|
+
openSettings: "Open its settings",
|
|
52511
|
+
beta: {
|
|
52512
|
+
badge: "Beta",
|
|
52513
|
+
badgeHint: "This is a beta version. It can have bugs.",
|
|
52514
|
+
try: "Try beta {{version}}",
|
|
52515
|
+
confirmTitle: "Use betas for {{name}}?",
|
|
52516
|
+
confirmBody: "Betas get new features and fixes first, but they can have bugs. You can switch back to stable at any time.",
|
|
52517
|
+
confirmInstall: "Install {{version}}",
|
|
52518
|
+
confirmSwitch: "Use betas",
|
|
52519
|
+
leftWhileOnBeta: "{{name}} stays on {{version}} until a stable release is newer.",
|
|
52520
|
+
channel: "Beta versions",
|
|
52521
|
+
channelHint: "Get new versions early. They can have bugs.",
|
|
52522
|
+
waitingForStable: "Back on stable. Stays on {{version}} until a stable release is newer.",
|
|
52523
|
+
versionLabel: "{{version}} (beta)",
|
|
52524
|
+
sendFeedback: "Send beta feedback"
|
|
52525
|
+
},
|
|
52526
|
+
documentation: "Documentation",
|
|
52527
|
+
envVars: "Environment variables",
|
|
52528
|
+
envRequired: "Required",
|
|
52529
|
+
envDefault: "Default: {{value}}"
|
|
52213
52530
|
}
|
|
52214
52531
|
},
|
|
52215
52532
|
settings: {
|
|
@@ -52248,7 +52565,39 @@ var en_default = {
|
|
|
52248
52565
|
instanceSettings: "Server settings",
|
|
52249
52566
|
nothingHere: "Nothing to set here.",
|
|
52250
52567
|
searchPage: "Search this page",
|
|
52251
|
-
noPageMatches: "Nothing on this page matches."
|
|
52568
|
+
noPageMatches: "Nothing on this page matches.",
|
|
52569
|
+
updates: {
|
|
52570
|
+
title: "Updates",
|
|
52571
|
+
betaProgram: "Beta program",
|
|
52572
|
+
betaIntro: "Betas are early builds of the next Termix version. They come out on Tuesdays and Fridays when there is something new to try. They can have bugs, and your feedback is what makes the stable release better.",
|
|
52573
|
+
termixBetas: "Termix betas",
|
|
52574
|
+
termixBetasHint: "Tell me about new betas, not only stable releases.",
|
|
52575
|
+
runningBetaBuild: "You are running a beta build. To leave, switch back to a stable image or installer.",
|
|
52576
|
+
howToInstall: "How to get the beta",
|
|
52577
|
+
desktopInstall: "Download the beta installer and install it over this one.",
|
|
52578
|
+
downloadBeta: "Download {{version}}",
|
|
52579
|
+
dockerInstall: "Change your image to the beta tag and restart the container:",
|
|
52580
|
+
copy: "Copy",
|
|
52581
|
+
copied: "Copied",
|
|
52582
|
+
copyFailed: "Could not copy",
|
|
52583
|
+
learnMore: "Learn more about betas",
|
|
52584
|
+
feedback: "Feedback",
|
|
52585
|
+
feedbackHint: "Found a bug or have an idea? It goes straight to the developers with your version filled in.",
|
|
52586
|
+
sendFeedback: "Send beta feedback",
|
|
52587
|
+
releases: "Releases",
|
|
52588
|
+
thisVersion: "This version",
|
|
52589
|
+
newestStable: "Newest stable",
|
|
52590
|
+
newestBeta: "Newest beta",
|
|
52591
|
+
noRelease: "None right now",
|
|
52592
|
+
pluginBetas: "Plugin betas",
|
|
52593
|
+
pluginBetasIntro: "Each plugin can use betas on its own. To try one, open it and press Try beta.",
|
|
52594
|
+
openPlugins: "Open Plugins",
|
|
52595
|
+
waitingForStable: "Back on stable. Stays on {{version}} until a stable release is newer.",
|
|
52596
|
+
backToStable: "Back to stable",
|
|
52597
|
+
allPluginsBeta: "Use betas for all plugins",
|
|
52598
|
+
allPluginsStable: "All plugins back to stable",
|
|
52599
|
+
saveFailed: "Could not save the change"
|
|
52600
|
+
}
|
|
52252
52601
|
},
|
|
52253
52602
|
managerCard: {
|
|
52254
52603
|
refresh: "Refresh",
|
|
@@ -52462,6 +52811,7 @@ var en_default = {
|
|
|
52462
52811
|
collapse: "Collapse",
|
|
52463
52812
|
expand: "Expand",
|
|
52464
52813
|
cannotBeUndone: "This cannot be undone.",
|
|
52814
|
+
hostNotFound: "Couldn't find that host. Try refreshing the list.",
|
|
52465
52815
|
hostCount_one: "{{count}} host",
|
|
52466
52816
|
hostCount_other: "{{count}} hosts",
|
|
52467
52817
|
credentialCount_one: "{{count}} credential",
|
|
@@ -52593,7 +52943,9 @@ i18n.use(localeBackend).use(Browser).use(initReactI18next).init({
|
|
|
52593
52943
|
escapeValue: false
|
|
52594
52944
|
},
|
|
52595
52945
|
react: {
|
|
52596
|
-
useSuspense: false
|
|
52946
|
+
useSuspense: false,
|
|
52947
|
+
// Repaint when a plugin enabled later loads its strings.
|
|
52948
|
+
bindI18n: "languageChanged loaded"
|
|
52597
52949
|
}
|
|
52598
52950
|
});
|
|
52599
52951
|
async function changeAppLanguage(language) {
|
|
@@ -52622,23 +52974,23 @@ import { useMemo as useMemo14, useSyncExternalStore as useSyncExternalStore3 } f
|
|
|
52622
52974
|
|
|
52623
52975
|
// src/ui/contexts/UiPreferencesContext.tsx
|
|
52624
52976
|
import {
|
|
52625
|
-
createContext as
|
|
52977
|
+
createContext as createContext8,
|
|
52626
52978
|
useCallback as useCallback19,
|
|
52627
|
-
useContext as
|
|
52979
|
+
useContext as useContext7,
|
|
52628
52980
|
useEffect as useEffect28,
|
|
52629
52981
|
useMemo as useMemo13,
|
|
52630
52982
|
useRef as useRef30,
|
|
52631
52983
|
useState as useState26
|
|
52632
52984
|
} from "react";
|
|
52633
|
-
import { jsx as
|
|
52634
|
-
var UiPreferencesContext =
|
|
52985
|
+
import { jsx as jsx33 } from "react/jsx-runtime";
|
|
52986
|
+
var UiPreferencesContext = createContext8(
|
|
52635
52987
|
null
|
|
52636
52988
|
);
|
|
52637
52989
|
function useUiPreferencesContext() {
|
|
52638
|
-
return
|
|
52990
|
+
return useContext7(UiPreferencesContext);
|
|
52639
52991
|
}
|
|
52640
52992
|
function useAreaPreferences(area) {
|
|
52641
|
-
const ctx =
|
|
52993
|
+
const ctx = useContext7(UiPreferencesContext);
|
|
52642
52994
|
if (!ctx) return PRESETS.balanced[area];
|
|
52643
52995
|
return ctx.resolve(area);
|
|
52644
52996
|
}
|
|
@@ -52659,8 +53011,8 @@ registeredRailItems.subscribe(() => {
|
|
|
52659
53011
|
|
|
52660
53012
|
// src/ui/components/tab-strip.tsx
|
|
52661
53013
|
import { useEffect as useEffect29, useRef as useRef31, useState as useState27 } from "react";
|
|
52662
|
-
import { useTranslation as
|
|
52663
|
-
import { jsx as
|
|
53014
|
+
import { useTranslation as useTranslation5 } from "react-i18next";
|
|
53015
|
+
import { jsx as jsx34, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
52664
53016
|
function TabStrip({
|
|
52665
53017
|
tabs,
|
|
52666
53018
|
activeTab,
|
|
@@ -52671,7 +53023,7 @@ function TabStrip({
|
|
|
52671
53023
|
className
|
|
52672
53024
|
}) {
|
|
52673
53025
|
const ref = useRef31(null);
|
|
52674
|
-
const { t } =
|
|
53026
|
+
const { t } = useTranslation5();
|
|
52675
53027
|
const [scroll, setScroll] = useState27({ left: false, right: false });
|
|
52676
53028
|
useEffect29(() => {
|
|
52677
53029
|
const el = ref.current;
|
|
@@ -52703,7 +53055,7 @@ function TabStrip({
|
|
|
52703
53055
|
}, []);
|
|
52704
53056
|
const renderTab = (tab) => {
|
|
52705
53057
|
const active = isActive ? isActive(tab.id) : activeTab === tab.id;
|
|
52706
|
-
return /* @__PURE__ */
|
|
53058
|
+
return /* @__PURE__ */ jsxs10(
|
|
52707
53059
|
"button",
|
|
52708
53060
|
{
|
|
52709
53061
|
type: "button",
|
|
@@ -52712,14 +53064,14 @@ function TabStrip({
|
|
|
52712
53064
|
children: [
|
|
52713
53065
|
tab.icon,
|
|
52714
53066
|
tab.label,
|
|
52715
|
-
tab.count !== void 0 && /* @__PURE__ */
|
|
53067
|
+
tab.count !== void 0 && /* @__PURE__ */ jsx34("span", { className: "text-[10px] tabular-nums opacity-60", children: tab.count })
|
|
52716
53068
|
]
|
|
52717
53069
|
},
|
|
52718
53070
|
tab.id
|
|
52719
53071
|
);
|
|
52720
53072
|
};
|
|
52721
53073
|
const overflow = scroll.left || scroll.right;
|
|
52722
|
-
return /* @__PURE__ */
|
|
53074
|
+
return /* @__PURE__ */ jsxs10(
|
|
52723
53075
|
"div",
|
|
52724
53076
|
{
|
|
52725
53077
|
className: cn(
|
|
@@ -52728,7 +53080,7 @@ function TabStrip({
|
|
|
52728
53080
|
className
|
|
52729
53081
|
),
|
|
52730
53082
|
children: [
|
|
52731
|
-
overflow && /* @__PURE__ */
|
|
53083
|
+
overflow && /* @__PURE__ */ jsx34(
|
|
52732
53084
|
"button",
|
|
52733
53085
|
{
|
|
52734
53086
|
type: "button",
|
|
@@ -52740,11 +53092,11 @@ function TabStrip({
|
|
|
52740
53092
|
left: -ref.current.clientWidth * 0.75,
|
|
52741
53093
|
behavior: "smooth"
|
|
52742
53094
|
}),
|
|
52743
|
-
children: /* @__PURE__ */
|
|
53095
|
+
children: /* @__PURE__ */ jsx34(ChevronLeft, { className: "size-4" })
|
|
52744
53096
|
}
|
|
52745
53097
|
),
|
|
52746
|
-
/* @__PURE__ */
|
|
52747
|
-
overflow && /* @__PURE__ */
|
|
53098
|
+
/* @__PURE__ */ jsx34("div", { ref, className: "min-w-0 flex-1 overflow-x-auto scrollbar-none", children: /* @__PURE__ */ jsx34("div", { className: "flex min-w-max", children: tabs.map(renderTab) }) }),
|
|
53099
|
+
overflow && /* @__PURE__ */ jsx34(
|
|
52748
53100
|
"button",
|
|
52749
53101
|
{
|
|
52750
53102
|
type: "button",
|
|
@@ -52756,17 +53108,17 @@ function TabStrip({
|
|
|
52756
53108
|
left: ref.current.clientWidth * 0.75,
|
|
52757
53109
|
behavior: "smooth"
|
|
52758
53110
|
}),
|
|
52759
|
-
children: /* @__PURE__ */
|
|
53111
|
+
children: /* @__PURE__ */ jsx34(ChevronRight, { className: "size-4" })
|
|
52760
53112
|
}
|
|
52761
53113
|
),
|
|
52762
|
-
trailing && /* @__PURE__ */
|
|
53114
|
+
trailing && /* @__PURE__ */ jsx34("div", { className: "flex shrink-0 items-center gap-1 px-1", children: trailing })
|
|
52763
53115
|
]
|
|
52764
53116
|
}
|
|
52765
53117
|
);
|
|
52766
53118
|
}
|
|
52767
53119
|
|
|
52768
53120
|
// src/ui/sidebar/HostManagerTabs.tsx
|
|
52769
|
-
import { jsx as
|
|
53121
|
+
import { jsx as jsx35 } from "react/jsx-runtime";
|
|
52770
53122
|
var sections = createRegistry(byOrderThenId);
|
|
52771
53123
|
var registerHostEditorSection = sections.register;
|
|
52772
53124
|
var unregisterHostEditorSection = sections.unregister;
|
|
@@ -53072,7 +53424,7 @@ function createPluginApi(pluginId) {
|
|
|
53072
53424
|
get(target, property, receiver) {
|
|
53073
53425
|
const value = Reflect.get(target, property, receiver);
|
|
53074
53426
|
if (typeof value !== "function") return value;
|
|
53075
|
-
if (property === "get" || property === "delete" || property === "head" || property === "options" || property === "post" || property === "put" || property === "patch") {
|
|
53427
|
+
if (property === "get" || property === "delete" || property === "head" || property === "options" || property === "post" || property === "put" || property === "patch" || property === "postForm" || property === "putForm" || property === "patchForm") {
|
|
53076
53428
|
return (url, ...rest) => value.call(
|
|
53077
53429
|
target,
|
|
53078
53430
|
`${prefix}${url.startsWith("/") ? url : `/${url}`}`,
|
|
@@ -53189,8 +53541,8 @@ function sectionPosition(section, order2 = 0) {
|
|
|
53189
53541
|
}
|
|
53190
53542
|
|
|
53191
53543
|
// src/ui/components/theme-provider.tsx
|
|
53192
|
-
import { createContext as
|
|
53193
|
-
import { jsx as
|
|
53544
|
+
import { createContext as createContext9, useContext as useContext8, useEffect as useEffect30, useState as useState28 } from "react";
|
|
53545
|
+
import { jsx as jsx36 } from "react/jsx-runtime";
|
|
53194
53546
|
var ALL_THEME_CLASSES = [
|
|
53195
53547
|
"light",
|
|
53196
53548
|
"dark",
|
|
@@ -53207,7 +53559,7 @@ var initialState = {
|
|
|
53207
53559
|
setTheme: () => null,
|
|
53208
53560
|
setThemePreview: () => null
|
|
53209
53561
|
};
|
|
53210
|
-
var ThemeProviderContext =
|
|
53562
|
+
var ThemeProviderContext = createContext9(initialState);
|
|
53211
53563
|
function ThemeProvider({
|
|
53212
53564
|
children,
|
|
53213
53565
|
defaultTheme = "dark",
|
|
@@ -53239,10 +53591,10 @@ function ThemeProvider({
|
|
|
53239
53591
|
setPreviewTheme(preview);
|
|
53240
53592
|
}
|
|
53241
53593
|
};
|
|
53242
|
-
return /* @__PURE__ */
|
|
53594
|
+
return /* @__PURE__ */ jsx36(ThemeProviderContext.Provider, { ...props, value, children });
|
|
53243
53595
|
}
|
|
53244
53596
|
var useTheme = () => {
|
|
53245
|
-
const context =
|
|
53597
|
+
const context = useContext8(ThemeProviderContext);
|
|
53246
53598
|
if (context === void 0)
|
|
53247
53599
|
throw new Error("useTheme must be used within a ThemeProvider");
|
|
53248
53600
|
return context;
|
|
@@ -53448,156 +53800,7 @@ async function getPlugins() {
|
|
|
53448
53800
|
const response = await rbacApi.get("/plugins");
|
|
53449
53801
|
return Array.isArray(response.data) ? response.data : [];
|
|
53450
53802
|
}
|
|
53451
|
-
|
|
53452
|
-
// src/ui/plugin-host/scope.tsx
|
|
53453
|
-
import {
|
|
53454
|
-
Component as Component2,
|
|
53455
|
-
createContext as createContext9,
|
|
53456
|
-
Suspense,
|
|
53457
|
-
useContext as useContext8
|
|
53458
|
-
} from "react";
|
|
53459
|
-
|
|
53460
|
-
// src/ui/plugin-host/host-scope.ts
|
|
53461
|
-
function isHostLike(value) {
|
|
53462
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
53463
|
-
if (!("id" in value)) return false;
|
|
53464
|
-
return "pluginSettings" in value || "ip" in value && "port" in value;
|
|
53465
|
-
}
|
|
53466
|
-
var cache = /* @__PURE__ */ new WeakMap();
|
|
53467
|
-
function scopeHost(value, pluginId) {
|
|
53468
|
-
if (!isHostLike(value)) return value;
|
|
53469
|
-
const full = shellHost(value.id)?.pluginSettings ?? value.pluginSettings;
|
|
53470
|
-
let perPlugin = cache.get(value);
|
|
53471
|
-
const hit = perPlugin?.get(pluginId);
|
|
53472
|
-
if (hit && hit.source === full) return hit.scoped;
|
|
53473
|
-
const own = full?.[pluginId];
|
|
53474
|
-
const scoped = { ...value, pluginSettings: own ? { [pluginId]: own } : {} };
|
|
53475
|
-
if (!perPlugin) {
|
|
53476
|
-
perPlugin = /* @__PURE__ */ new Map();
|
|
53477
|
-
cache.set(value, perPlugin);
|
|
53478
|
-
}
|
|
53479
|
-
perPlugin.set(pluginId, { source: full, scoped });
|
|
53480
|
-
return scoped;
|
|
53481
|
-
}
|
|
53482
|
-
function scopeHostArgs(args, pluginId) {
|
|
53483
|
-
return args.map(
|
|
53484
|
-
(arg) => isHostLike(arg) ? scopeHost(arg, pluginId) : scopeHostFields(arg, pluginId)
|
|
53485
|
-
);
|
|
53486
|
-
}
|
|
53487
|
-
var HOST_FIELDS = ["host", "sshHost", "hostConfig"];
|
|
53488
|
-
function scopeHostFields(value, pluginId) {
|
|
53489
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return value;
|
|
53490
|
-
const record = value;
|
|
53491
|
-
let next = null;
|
|
53492
|
-
for (const field of HOST_FIELDS) {
|
|
53493
|
-
if (!(field in record)) continue;
|
|
53494
|
-
const scoped = scopeHost(record[field], pluginId);
|
|
53495
|
-
if (scoped === record[field]) continue;
|
|
53496
|
-
next ??= { ...record };
|
|
53497
|
-
next[field] = scoped;
|
|
53498
|
-
}
|
|
53499
|
-
return next ?? value;
|
|
53500
|
-
}
|
|
53501
|
-
function scopeHostCallback(fn, pluginId) {
|
|
53502
|
-
if (!fn) return fn;
|
|
53503
|
-
return ((...args) => fn(...scopeHostArgs(args, pluginId)));
|
|
53504
|
-
}
|
|
53505
|
-
|
|
53506
|
-
// src/ui/plugin-host/scope.tsx
|
|
53507
|
-
import { useTranslation as useTranslation4 } from "react-i18next";
|
|
53508
|
-
import { jsx as jsx35, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
53509
|
-
var PluginScopeContext = createContext9(null);
|
|
53510
|
-
function usePluginScope() {
|
|
53511
|
-
return useContext8(PluginScopeContext);
|
|
53512
|
-
}
|
|
53513
|
-
function CrashNotice({
|
|
53514
|
-
pluginId,
|
|
53515
|
-
onRetry
|
|
53516
|
-
}) {
|
|
53517
|
-
const { t } = useTranslation4();
|
|
53518
|
-
const name = getPluginRecord(pluginId)?.summary.name ?? pluginId;
|
|
53519
|
-
return /* @__PURE__ */ jsxs10("div", { className: "flex flex-col items-center justify-center gap-2 p-4 text-center text-sm text-muted-foreground", children: [
|
|
53520
|
-
/* @__PURE__ */ jsx35("span", { children: t("plugins.runtime.crashed", { name }) }),
|
|
53521
|
-
/* @__PURE__ */ jsx35(
|
|
53522
|
-
"button",
|
|
53523
|
-
{
|
|
53524
|
-
type: "button",
|
|
53525
|
-
className: "text-xs underline underline-offset-2 hover:text-foreground",
|
|
53526
|
-
onClick: onRetry,
|
|
53527
|
-
children: t("plugins.runtime.retry")
|
|
53528
|
-
}
|
|
53529
|
-
)
|
|
53530
|
-
] });
|
|
53531
|
-
}
|
|
53532
|
-
var PluginErrorBoundary = class extends Component2 {
|
|
53533
|
-
state = { error: false };
|
|
53534
|
-
static getDerivedStateFromError() {
|
|
53535
|
-
return { error: true };
|
|
53536
|
-
}
|
|
53537
|
-
componentDidCatch(error, info) {
|
|
53538
|
-
console.error(
|
|
53539
|
-
`[plugins] ${this.props.pluginId} crashed while rendering`,
|
|
53540
|
-
error,
|
|
53541
|
-
info.componentStack
|
|
53542
|
-
);
|
|
53543
|
-
}
|
|
53544
|
-
render() {
|
|
53545
|
-
if (this.state.error) {
|
|
53546
|
-
return /* @__PURE__ */ jsx35(
|
|
53547
|
-
CrashNotice,
|
|
53548
|
-
{
|
|
53549
|
-
pluginId: this.props.pluginId,
|
|
53550
|
-
onRetry: () => this.setState({ error: false })
|
|
53551
|
-
}
|
|
53552
|
-
);
|
|
53553
|
-
}
|
|
53554
|
-
return this.props.children;
|
|
53555
|
-
}
|
|
53556
|
-
};
|
|
53557
|
-
function PluginScope({
|
|
53558
|
-
pluginId,
|
|
53559
|
-
children
|
|
53560
|
-
}) {
|
|
53561
|
-
return /* @__PURE__ */ jsx35(PluginScopeContext.Provider, { value: pluginId, children: /* @__PURE__ */ jsx35(PluginErrorBoundary, { pluginId, children: /* @__PURE__ */ jsx35(Suspense, { fallback: null, children }) }) });
|
|
53562
|
-
}
|
|
53563
|
-
function withPluginScope(pluginId, Inner) {
|
|
53564
|
-
function Scoped(props) {
|
|
53565
|
-
return /* @__PURE__ */ jsx35(PluginScope, { pluginId, children: /* @__PURE__ */ jsx35(Inner, { ...scopeHostFields(props, pluginId) }) });
|
|
53566
|
-
}
|
|
53567
|
-
Scoped.displayName = `Plugin(${pluginId}:${Inner.displayName ?? Inner.name ?? "Component"})`;
|
|
53568
|
-
return Scoped;
|
|
53569
|
-
}
|
|
53570
|
-
var IconBoundary = class extends Component2 {
|
|
53571
|
-
state = { error: false };
|
|
53572
|
-
static getDerivedStateFromError() {
|
|
53573
|
-
return { error: true };
|
|
53574
|
-
}
|
|
53575
|
-
componentDidCatch(error) {
|
|
53576
|
-
console.error(`[plugins] ${this.props.pluginId} icon failed`, error);
|
|
53577
|
-
}
|
|
53578
|
-
render() {
|
|
53579
|
-
return this.state.error ? null : this.props.children;
|
|
53580
|
-
}
|
|
53581
|
-
};
|
|
53582
|
-
function withIconBoundary(pluginId, Icon2) {
|
|
53583
|
-
if (!Icon2) return void 0;
|
|
53584
|
-
function SafeIcon(props) {
|
|
53585
|
-
return /* @__PURE__ */ jsx35(IconBoundary, { pluginId, children: /* @__PURE__ */ jsx35(Icon2, { ...props }) });
|
|
53586
|
-
}
|
|
53587
|
-
SafeIcon.displayName = `PluginIcon(${pluginId})`;
|
|
53588
|
-
return SafeIcon;
|
|
53589
|
-
}
|
|
53590
|
-
function guardCallback(pluginId, fn, fallback) {
|
|
53591
|
-
if (!fn) return void 0;
|
|
53592
|
-
return (...args) => {
|
|
53593
|
-
try {
|
|
53594
|
-
return fn(...args);
|
|
53595
|
-
} catch (error) {
|
|
53596
|
-
console.error(`[plugins] ${pluginId} callback failed`, error);
|
|
53597
|
-
return fallback;
|
|
53598
|
-
}
|
|
53599
|
-
};
|
|
53600
|
-
}
|
|
53803
|
+
var PLUGINS_CHANGED_EVENT = "termix:plugins-changed";
|
|
53601
53804
|
|
|
53602
53805
|
// src/ui/hooks/useSshAuthProviders.ts
|
|
53603
53806
|
import { useEffect as useEffect32, useMemo as useMemo15, useState as useState30 } from "react";
|
|
@@ -53605,6 +53808,7 @@ import { useEffect as useEffect32, useMemo as useMemo15, useState as useState30
|
|
|
53605
53808
|
// src/ui/api/auth-methods-api.ts
|
|
53606
53809
|
function remember(data) {
|
|
53607
53810
|
if (data?.token) localStorage.setItem("jwt", data.token);
|
|
53811
|
+
if (data?.trustToken) localStorage.setItem(TRUST_TOKEN_KEY, data.trustToken);
|
|
53608
53812
|
if (data?.success && !data.requires_totp) markUserAuthenticated();
|
|
53609
53813
|
return data;
|
|
53610
53814
|
}
|
|
@@ -53758,7 +53962,7 @@ function contextKey(context) {
|
|
|
53758
53962
|
try {
|
|
53759
53963
|
return JSON.stringify(context);
|
|
53760
53964
|
} catch {
|
|
53761
|
-
return
|
|
53965
|
+
return Object.entries(context).map(([key, value]) => `${key}:${value == null ? "-" : typeof value}`).join(",");
|
|
53762
53966
|
}
|
|
53763
53967
|
}
|
|
53764
53968
|
|
|
@@ -53773,7 +53977,7 @@ import {
|
|
|
53773
53977
|
useSyncExternalStore as useSyncExternalStore6,
|
|
53774
53978
|
useState as useState31
|
|
53775
53979
|
} from "react";
|
|
53776
|
-
import { jsx as
|
|
53980
|
+
import { jsx as jsx37 } from "react/jsx-runtime";
|
|
53777
53981
|
var StatusStoreContext = createContext10(null);
|
|
53778
53982
|
var ServerStatusContext = createContext10(null);
|
|
53779
53983
|
var activeStore = null;
|
|
@@ -53895,6 +54099,9 @@ var pluginHostBridge = {
|
|
|
53895
54099
|
}
|
|
53896
54100
|
return pluginId;
|
|
53897
54101
|
},
|
|
54102
|
+
useDocsUrl(pluginId, page, anchor) {
|
|
54103
|
+
return usePluginDocsUrl(pluginId, page, anchor);
|
|
54104
|
+
},
|
|
53898
54105
|
useTranslation(pluginId) {
|
|
53899
54106
|
const { t, i18n: i18n2 } = useI18nTranslation(pluginId);
|
|
53900
54107
|
return {
|
|
@@ -53912,13 +54119,22 @@ var pluginHostBridge = {
|
|
|
53912
54119
|
useEffect34(() => {
|
|
53913
54120
|
let cancelled = false;
|
|
53914
54121
|
if (scope === "host" && !Number.isFinite(numericHostId)) return;
|
|
53915
|
-
SETTINGS_READERS[scope](pluginId, numericHostId).then((values) => {
|
|
54122
|
+
const read = () => SETTINGS_READERS[scope](pluginId, numericHostId).then((values) => {
|
|
53916
54123
|
if (!cancelled) setState({ values, loaded: true });
|
|
53917
54124
|
}).catch(() => {
|
|
53918
54125
|
if (!cancelled) setState((prev) => ({ ...prev, loaded: true }));
|
|
53919
54126
|
});
|
|
54127
|
+
void read();
|
|
54128
|
+
const onChanged = (event) => {
|
|
54129
|
+
const detail = event.detail;
|
|
54130
|
+
if (detail?.pluginId !== pluginId || detail.scope !== scope) return;
|
|
54131
|
+
if (scope === "host" && detail.hostId !== numericHostId) return;
|
|
54132
|
+
void read();
|
|
54133
|
+
};
|
|
54134
|
+
window.addEventListener(PLUGIN_SETTINGS_CHANGED_EVENT, onChanged);
|
|
53920
54135
|
return () => {
|
|
53921
54136
|
cancelled = true;
|
|
54137
|
+
window.removeEventListener(PLUGIN_SETTINGS_CHANGED_EVENT, onChanged);
|
|
53922
54138
|
};
|
|
53923
54139
|
}, [pluginId, scope, numericHostId]);
|
|
53924
54140
|
const save = useCallback21(
|
|
@@ -54112,6 +54328,18 @@ function pluginKey(pluginId, key) {
|
|
|
54112
54328
|
|
|
54113
54329
|
// src/ui/plugin-host/app.ts
|
|
54114
54330
|
var ONBOARDING_ID = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
54331
|
+
function createDocsApi(manifest) {
|
|
54332
|
+
const url = pluginDocsUrl(manifest?.docs);
|
|
54333
|
+
const page = (name, anchor) => url ? pluginDocsPage(url, name, anchor) : null;
|
|
54334
|
+
return {
|
|
54335
|
+
url,
|
|
54336
|
+
page,
|
|
54337
|
+
open(name, anchor) {
|
|
54338
|
+
const target = page(name, anchor);
|
|
54339
|
+
if (target) window.open(target, "_blank", "noopener,noreferrer");
|
|
54340
|
+
}
|
|
54341
|
+
};
|
|
54342
|
+
}
|
|
54115
54343
|
function createPluginApp(pluginId, manifest, contributes, options2 = {}) {
|
|
54116
54344
|
const bag = [];
|
|
54117
54345
|
let disposed = false;
|
|
@@ -54516,6 +54744,7 @@ function createPluginApp(pluginId, manifest, contributes, options2 = {}) {
|
|
|
54516
54744
|
onReady: (listener) => track(tabsApi.onReady(listener))
|
|
54517
54745
|
},
|
|
54518
54746
|
confirm: (options3) => shell.confirm(options3),
|
|
54747
|
+
docs: createDocsApi(manifest),
|
|
54519
54748
|
desktop: {
|
|
54520
54749
|
available: isElectron(),
|
|
54521
54750
|
remoteServerUrl,
|
|
@@ -54558,8 +54787,8 @@ function createPluginApp(pluginId, manifest, contributes, options2 = {}) {
|
|
|
54558
54787
|
|
|
54559
54788
|
// src/ui/shell/ActionSlot.tsx
|
|
54560
54789
|
import React50 from "react";
|
|
54561
|
-
import { useTranslation as
|
|
54562
|
-
import { Fragment as Fragment14, jsx as
|
|
54790
|
+
import { useTranslation as useTranslation6 } from "react-i18next";
|
|
54791
|
+
import { Fragment as Fragment14, jsx as jsx38, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
54563
54792
|
function ActionSlot({
|
|
54564
54793
|
slotId,
|
|
54565
54794
|
context,
|
|
@@ -54569,17 +54798,17 @@ function ActionSlot({
|
|
|
54569
54798
|
hideLabels,
|
|
54570
54799
|
when
|
|
54571
54800
|
}) {
|
|
54572
|
-
const { t } =
|
|
54801
|
+
const { t } = useTranslation6();
|
|
54573
54802
|
const contributions2 = useActionSlot(slotId, when).filter(
|
|
54574
54803
|
(contribution) => contribution.kind !== "component"
|
|
54575
54804
|
);
|
|
54576
54805
|
if (!enabled || contributions2.length === 0) return null;
|
|
54577
|
-
return /* @__PURE__ */
|
|
54806
|
+
return /* @__PURE__ */ jsx38(Fragment14, { children: contributions2.map((contribution) => {
|
|
54578
54807
|
const invoke = () => {
|
|
54579
54808
|
void invokeAction(contribution.actionId, ...context?.() ?? []);
|
|
54580
54809
|
};
|
|
54581
54810
|
if (renderItem) {
|
|
54582
|
-
return /* @__PURE__ */
|
|
54811
|
+
return /* @__PURE__ */ jsx38(React50.Fragment, { children: renderItem(contribution, invoke) }, contribution.actionId);
|
|
54583
54812
|
}
|
|
54584
54813
|
const Icon2 = contribution.icon;
|
|
54585
54814
|
const label = t(contribution.titleKey);
|
|
@@ -54592,7 +54821,7 @@ function ActionSlot({
|
|
|
54592
54821
|
title: label,
|
|
54593
54822
|
onClick: invoke,
|
|
54594
54823
|
children: [
|
|
54595
|
-
Icon2 && /* @__PURE__ */
|
|
54824
|
+
Icon2 && /* @__PURE__ */ jsx38(Icon2, { className: "size-4 shrink-0" }),
|
|
54596
54825
|
!hideLabels && label
|
|
54597
54826
|
]
|
|
54598
54827
|
},
|
|
@@ -54609,37 +54838,37 @@ function ComponentSlot({
|
|
|
54609
54838
|
(contribution) => contribution.kind === "component" && contribution.component
|
|
54610
54839
|
);
|
|
54611
54840
|
if (contributions2.length === 0) return null;
|
|
54612
|
-
return /* @__PURE__ */
|
|
54841
|
+
return /* @__PURE__ */ jsx38(Fragment14, { children: contributions2.map((contribution) => {
|
|
54613
54842
|
const Contributed = contribution.component;
|
|
54614
|
-
return /* @__PURE__ */
|
|
54843
|
+
return /* @__PURE__ */ jsx38(Contributed, { ...props ?? {} }, contribution.actionId);
|
|
54615
54844
|
}) });
|
|
54616
54845
|
}
|
|
54617
54846
|
|
|
54618
54847
|
// src/ui/plugin-host/PluginViewPlaceholder.tsx
|
|
54619
|
-
import { useTranslation as
|
|
54848
|
+
import { useTranslation as useTranslation7 } from "react-i18next";
|
|
54620
54849
|
|
|
54621
54850
|
// src/ui/plugins/open-plugins.ts
|
|
54622
54851
|
var OPEN_PLUGINS_EVENT = "termix:open-plugins";
|
|
54623
54852
|
|
|
54624
54853
|
// src/ui/plugin-host/PluginViewPlaceholder.tsx
|
|
54625
|
-
import { jsx as
|
|
54854
|
+
import { jsx as jsx39, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
54626
54855
|
function PluginViewPlaceholder({
|
|
54627
54856
|
kind,
|
|
54628
54857
|
viewId,
|
|
54629
54858
|
compact = false
|
|
54630
54859
|
}) {
|
|
54631
|
-
const { t } =
|
|
54860
|
+
const { t } = useTranslation7();
|
|
54632
54861
|
usePluginStore();
|
|
54633
54862
|
const { has } = usePermissions();
|
|
54634
54863
|
const { status, owner } = unregisteredViewStatus(kind, viewId);
|
|
54635
54864
|
const name = owner?.summary.name ?? viewId;
|
|
54636
54865
|
if (status === "loading") {
|
|
54637
|
-
return /* @__PURE__ */
|
|
54866
|
+
return /* @__PURE__ */ jsx39(
|
|
54638
54867
|
"div",
|
|
54639
54868
|
{
|
|
54640
54869
|
className: "flex h-full w-full items-center justify-center",
|
|
54641
54870
|
"aria-label": t("plugins.runtime.loading", { name }),
|
|
54642
|
-
children: /* @__PURE__ */
|
|
54871
|
+
children: /* @__PURE__ */ jsx39("div", { className: "size-5 rounded-full border-2 border-muted-foreground/30 border-t-muted-foreground/70 animate-spin" })
|
|
54643
54872
|
}
|
|
54644
54873
|
);
|
|
54645
54874
|
}
|
|
@@ -54652,10 +54881,10 @@ function PluginViewPlaceholder({
|
|
|
54652
54881
|
"data-status": status,
|
|
54653
54882
|
className: `flex h-full w-full flex-col items-center justify-center gap-2 text-center ${compact ? "p-3" : "p-6"}`,
|
|
54654
54883
|
children: [
|
|
54655
|
-
/* @__PURE__ */
|
|
54656
|
-
/* @__PURE__ */
|
|
54657
|
-
/* @__PURE__ */
|
|
54658
|
-
!compact && status !== "failed" && has("admin.plugins.manage") && /* @__PURE__ */
|
|
54884
|
+
/* @__PURE__ */ jsx39(CircleSlash, { className: "size-6 text-muted-foreground/40" }),
|
|
54885
|
+
/* @__PURE__ */ jsx39("span", { className: "text-sm font-semibold text-muted-foreground", children: title }),
|
|
54886
|
+
/* @__PURE__ */ jsx39("span", { className: "text-xs text-muted-foreground/70", children: hint }),
|
|
54887
|
+
!compact && status !== "failed" && has("admin.plugins.manage") && /* @__PURE__ */ jsx39(
|
|
54659
54888
|
Button,
|
|
54660
54889
|
{
|
|
54661
54890
|
variant: "outline",
|
|
@@ -54761,6 +54990,7 @@ export {
|
|
|
54761
54990
|
notifyShellReady,
|
|
54762
54991
|
resetShellBridge,
|
|
54763
54992
|
usePluginScope,
|
|
54993
|
+
DocsLink,
|
|
54764
54994
|
PANEL,
|
|
54765
54995
|
PanelShell,
|
|
54766
54996
|
BackButton,
|
|
@@ -54797,6 +55027,7 @@ export {
|
|
|
54797
55027
|
isRedactedSecret,
|
|
54798
55028
|
isFieldActive,
|
|
54799
55029
|
getPlugins,
|
|
55030
|
+
PLUGINS_CHANGED_EVENT,
|
|
54800
55031
|
useAreaPreferences,
|
|
54801
55032
|
getPanel,
|
|
54802
55033
|
listPanels,
|