@termix-ssh/plugin-sdk 1.0.2 → 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 +20 -0
- package/LICENSE +202 -0
- package/README.md +3 -2
- 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/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-LKYAVM4T.js → chunk-F5RZH6HE.js} +13 -2
- package/dist/host/{chunk-XKMRKQFN.js → chunk-O2OHNVFX.js} +1 -1
- package/dist/host/{chunk-SS43S6VI.js → chunk-RU4E5XLY.js} +453 -287
- package/dist/host/core-classes.json +1 -0
- package/dist/host/{linked-server-DW5P3NLZ.js → linked-server-4VWYYABP.js} +1 -1
- package/dist/host/{rbac-api-JKISXZEP.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 +6 -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/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/ui.js +6 -3
- package/dist/host/{use-permissions-5CZEA3P4.js → use-permissions-KIQCJ35M.js} +1 -1
- package/dist/manifest.d.ts +7 -1
- package/dist/manifest.js +48 -1
- package/dist/openapi.d.ts +43 -0
- package/dist/openapi.js +60 -0
- package/dist/testing/setup.js +1 -0
- package/package.json +10 -1
- package/schema/manifest.schema.json +21 -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",
|
|
@@ -52229,7 +52522,11 @@ var en_default = {
|
|
|
52229
52522
|
waitingForStable: "Back on stable. Stays on {{version}} until a stable release is newer.",
|
|
52230
52523
|
versionLabel: "{{version}} (beta)",
|
|
52231
52524
|
sendFeedback: "Send beta feedback"
|
|
52232
|
-
}
|
|
52525
|
+
},
|
|
52526
|
+
documentation: "Documentation",
|
|
52527
|
+
envVars: "Environment variables",
|
|
52528
|
+
envRequired: "Required",
|
|
52529
|
+
envDefault: "Default: {{value}}"
|
|
52233
52530
|
}
|
|
52234
52531
|
},
|
|
52235
52532
|
settings: {
|
|
@@ -52514,6 +52811,7 @@ var en_default = {
|
|
|
52514
52811
|
collapse: "Collapse",
|
|
52515
52812
|
expand: "Expand",
|
|
52516
52813
|
cannotBeUndone: "This cannot be undone.",
|
|
52814
|
+
hostNotFound: "Couldn't find that host. Try refreshing the list.",
|
|
52517
52815
|
hostCount_one: "{{count}} host",
|
|
52518
52816
|
hostCount_other: "{{count}} hosts",
|
|
52519
52817
|
credentialCount_one: "{{count}} credential",
|
|
@@ -52676,23 +52974,23 @@ import { useMemo as useMemo14, useSyncExternalStore as useSyncExternalStore3 } f
|
|
|
52676
52974
|
|
|
52677
52975
|
// src/ui/contexts/UiPreferencesContext.tsx
|
|
52678
52976
|
import {
|
|
52679
|
-
createContext as
|
|
52977
|
+
createContext as createContext8,
|
|
52680
52978
|
useCallback as useCallback19,
|
|
52681
|
-
useContext as
|
|
52979
|
+
useContext as useContext7,
|
|
52682
52980
|
useEffect as useEffect28,
|
|
52683
52981
|
useMemo as useMemo13,
|
|
52684
52982
|
useRef as useRef30,
|
|
52685
52983
|
useState as useState26
|
|
52686
52984
|
} from "react";
|
|
52687
|
-
import { jsx as
|
|
52688
|
-
var UiPreferencesContext =
|
|
52985
|
+
import { jsx as jsx33 } from "react/jsx-runtime";
|
|
52986
|
+
var UiPreferencesContext = createContext8(
|
|
52689
52987
|
null
|
|
52690
52988
|
);
|
|
52691
52989
|
function useUiPreferencesContext() {
|
|
52692
|
-
return
|
|
52990
|
+
return useContext7(UiPreferencesContext);
|
|
52693
52991
|
}
|
|
52694
52992
|
function useAreaPreferences(area) {
|
|
52695
|
-
const ctx =
|
|
52993
|
+
const ctx = useContext7(UiPreferencesContext);
|
|
52696
52994
|
if (!ctx) return PRESETS.balanced[area];
|
|
52697
52995
|
return ctx.resolve(area);
|
|
52698
52996
|
}
|
|
@@ -52713,8 +53011,8 @@ registeredRailItems.subscribe(() => {
|
|
|
52713
53011
|
|
|
52714
53012
|
// src/ui/components/tab-strip.tsx
|
|
52715
53013
|
import { useEffect as useEffect29, useRef as useRef31, useState as useState27 } from "react";
|
|
52716
|
-
import { useTranslation as
|
|
52717
|
-
import { jsx as
|
|
53014
|
+
import { useTranslation as useTranslation5 } from "react-i18next";
|
|
53015
|
+
import { jsx as jsx34, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
52718
53016
|
function TabStrip({
|
|
52719
53017
|
tabs,
|
|
52720
53018
|
activeTab,
|
|
@@ -52725,7 +53023,7 @@ function TabStrip({
|
|
|
52725
53023
|
className
|
|
52726
53024
|
}) {
|
|
52727
53025
|
const ref = useRef31(null);
|
|
52728
|
-
const { t } =
|
|
53026
|
+
const { t } = useTranslation5();
|
|
52729
53027
|
const [scroll, setScroll] = useState27({ left: false, right: false });
|
|
52730
53028
|
useEffect29(() => {
|
|
52731
53029
|
const el = ref.current;
|
|
@@ -52757,7 +53055,7 @@ function TabStrip({
|
|
|
52757
53055
|
}, []);
|
|
52758
53056
|
const renderTab = (tab) => {
|
|
52759
53057
|
const active = isActive ? isActive(tab.id) : activeTab === tab.id;
|
|
52760
|
-
return /* @__PURE__ */
|
|
53058
|
+
return /* @__PURE__ */ jsxs10(
|
|
52761
53059
|
"button",
|
|
52762
53060
|
{
|
|
52763
53061
|
type: "button",
|
|
@@ -52766,14 +53064,14 @@ function TabStrip({
|
|
|
52766
53064
|
children: [
|
|
52767
53065
|
tab.icon,
|
|
52768
53066
|
tab.label,
|
|
52769
|
-
tab.count !== void 0 && /* @__PURE__ */
|
|
53067
|
+
tab.count !== void 0 && /* @__PURE__ */ jsx34("span", { className: "text-[10px] tabular-nums opacity-60", children: tab.count })
|
|
52770
53068
|
]
|
|
52771
53069
|
},
|
|
52772
53070
|
tab.id
|
|
52773
53071
|
);
|
|
52774
53072
|
};
|
|
52775
53073
|
const overflow = scroll.left || scroll.right;
|
|
52776
|
-
return /* @__PURE__ */
|
|
53074
|
+
return /* @__PURE__ */ jsxs10(
|
|
52777
53075
|
"div",
|
|
52778
53076
|
{
|
|
52779
53077
|
className: cn(
|
|
@@ -52782,7 +53080,7 @@ function TabStrip({
|
|
|
52782
53080
|
className
|
|
52783
53081
|
),
|
|
52784
53082
|
children: [
|
|
52785
|
-
overflow && /* @__PURE__ */
|
|
53083
|
+
overflow && /* @__PURE__ */ jsx34(
|
|
52786
53084
|
"button",
|
|
52787
53085
|
{
|
|
52788
53086
|
type: "button",
|
|
@@ -52794,11 +53092,11 @@ function TabStrip({
|
|
|
52794
53092
|
left: -ref.current.clientWidth * 0.75,
|
|
52795
53093
|
behavior: "smooth"
|
|
52796
53094
|
}),
|
|
52797
|
-
children: /* @__PURE__ */
|
|
53095
|
+
children: /* @__PURE__ */ jsx34(ChevronLeft, { className: "size-4" })
|
|
52798
53096
|
}
|
|
52799
53097
|
),
|
|
52800
|
-
/* @__PURE__ */
|
|
52801
|
-
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(
|
|
52802
53100
|
"button",
|
|
52803
53101
|
{
|
|
52804
53102
|
type: "button",
|
|
@@ -52810,17 +53108,17 @@ function TabStrip({
|
|
|
52810
53108
|
left: ref.current.clientWidth * 0.75,
|
|
52811
53109
|
behavior: "smooth"
|
|
52812
53110
|
}),
|
|
52813
|
-
children: /* @__PURE__ */
|
|
53111
|
+
children: /* @__PURE__ */ jsx34(ChevronRight, { className: "size-4" })
|
|
52814
53112
|
}
|
|
52815
53113
|
),
|
|
52816
|
-
trailing && /* @__PURE__ */
|
|
53114
|
+
trailing && /* @__PURE__ */ jsx34("div", { className: "flex shrink-0 items-center gap-1 px-1", children: trailing })
|
|
52817
53115
|
]
|
|
52818
53116
|
}
|
|
52819
53117
|
);
|
|
52820
53118
|
}
|
|
52821
53119
|
|
|
52822
53120
|
// src/ui/sidebar/HostManagerTabs.tsx
|
|
52823
|
-
import { jsx as
|
|
53121
|
+
import { jsx as jsx35 } from "react/jsx-runtime";
|
|
52824
53122
|
var sections = createRegistry(byOrderThenId);
|
|
52825
53123
|
var registerHostEditorSection = sections.register;
|
|
52826
53124
|
var unregisterHostEditorSection = sections.unregister;
|
|
@@ -53243,8 +53541,8 @@ function sectionPosition(section, order2 = 0) {
|
|
|
53243
53541
|
}
|
|
53244
53542
|
|
|
53245
53543
|
// src/ui/components/theme-provider.tsx
|
|
53246
|
-
import { createContext as
|
|
53247
|
-
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";
|
|
53248
53546
|
var ALL_THEME_CLASSES = [
|
|
53249
53547
|
"light",
|
|
53250
53548
|
"dark",
|
|
@@ -53261,7 +53559,7 @@ var initialState = {
|
|
|
53261
53559
|
setTheme: () => null,
|
|
53262
53560
|
setThemePreview: () => null
|
|
53263
53561
|
};
|
|
53264
|
-
var ThemeProviderContext =
|
|
53562
|
+
var ThemeProviderContext = createContext9(initialState);
|
|
53265
53563
|
function ThemeProvider({
|
|
53266
53564
|
children,
|
|
53267
53565
|
defaultTheme = "dark",
|
|
@@ -53293,10 +53591,10 @@ function ThemeProvider({
|
|
|
53293
53591
|
setPreviewTheme(preview);
|
|
53294
53592
|
}
|
|
53295
53593
|
};
|
|
53296
|
-
return /* @__PURE__ */
|
|
53594
|
+
return /* @__PURE__ */ jsx36(ThemeProviderContext.Provider, { ...props, value, children });
|
|
53297
53595
|
}
|
|
53298
53596
|
var useTheme = () => {
|
|
53299
|
-
const context =
|
|
53597
|
+
const context = useContext8(ThemeProviderContext);
|
|
53300
53598
|
if (context === void 0)
|
|
53301
53599
|
throw new Error("useTheme must be used within a ThemeProvider");
|
|
53302
53600
|
return context;
|
|
@@ -53504,162 +53802,13 @@ async function getPlugins() {
|
|
|
53504
53802
|
}
|
|
53505
53803
|
var PLUGINS_CHANGED_EVENT = "termix:plugins-changed";
|
|
53506
53804
|
|
|
53507
|
-
// src/ui/plugin-host/scope.tsx
|
|
53508
|
-
import {
|
|
53509
|
-
Component as Component2,
|
|
53510
|
-
createContext as createContext9,
|
|
53511
|
-
Suspense,
|
|
53512
|
-
useContext as useContext8
|
|
53513
|
-
} from "react";
|
|
53514
|
-
|
|
53515
|
-
// src/ui/plugin-host/host-scope.ts
|
|
53516
|
-
function isHostLike(value) {
|
|
53517
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
53518
|
-
if (!("id" in value)) return false;
|
|
53519
|
-
return "pluginSettings" in value || "ip" in value && "port" in value;
|
|
53520
|
-
}
|
|
53521
|
-
var cache = /* @__PURE__ */ new WeakMap();
|
|
53522
|
-
function scopeHost(value, pluginId) {
|
|
53523
|
-
if (!isHostLike(value)) return value;
|
|
53524
|
-
const full = shellHost(value.id)?.pluginSettings ?? value.pluginSettings;
|
|
53525
|
-
let perPlugin = cache.get(value);
|
|
53526
|
-
const hit = perPlugin?.get(pluginId);
|
|
53527
|
-
if (hit && hit.source === full) return hit.scoped;
|
|
53528
|
-
const own = full?.[pluginId];
|
|
53529
|
-
const scoped = { ...value, pluginSettings: own ? { [pluginId]: own } : {} };
|
|
53530
|
-
if (!perPlugin) {
|
|
53531
|
-
perPlugin = /* @__PURE__ */ new Map();
|
|
53532
|
-
cache.set(value, perPlugin);
|
|
53533
|
-
}
|
|
53534
|
-
perPlugin.set(pluginId, { source: full, scoped });
|
|
53535
|
-
return scoped;
|
|
53536
|
-
}
|
|
53537
|
-
function scopeHostArgs(args, pluginId) {
|
|
53538
|
-
return args.map(
|
|
53539
|
-
(arg) => isHostLike(arg) ? scopeHost(arg, pluginId) : scopeHostFields(arg, pluginId)
|
|
53540
|
-
);
|
|
53541
|
-
}
|
|
53542
|
-
var HOST_FIELDS = ["host", "sshHost", "hostConfig"];
|
|
53543
|
-
function scopeHostFields(value, pluginId) {
|
|
53544
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return value;
|
|
53545
|
-
const record = value;
|
|
53546
|
-
let next = null;
|
|
53547
|
-
for (const field of HOST_FIELDS) {
|
|
53548
|
-
if (!(field in record)) continue;
|
|
53549
|
-
const scoped = scopeHost(record[field], pluginId);
|
|
53550
|
-
if (scoped === record[field]) continue;
|
|
53551
|
-
next ??= { ...record };
|
|
53552
|
-
next[field] = scoped;
|
|
53553
|
-
}
|
|
53554
|
-
return next ?? value;
|
|
53555
|
-
}
|
|
53556
|
-
function scopeHostCallback(fn, pluginId) {
|
|
53557
|
-
if (!fn) return fn;
|
|
53558
|
-
return ((...args) => fn(...scopeHostArgs(args, pluginId)));
|
|
53559
|
-
}
|
|
53560
|
-
|
|
53561
|
-
// src/ui/plugin-host/scope.tsx
|
|
53562
|
-
import { useTranslation as useTranslation4 } from "react-i18next";
|
|
53563
|
-
import { jsx as jsx35, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
53564
|
-
var PluginScopeContext = createContext9(null);
|
|
53565
|
-
function usePluginScope() {
|
|
53566
|
-
return useContext8(PluginScopeContext);
|
|
53567
|
-
}
|
|
53568
|
-
function CrashNotice({
|
|
53569
|
-
pluginId,
|
|
53570
|
-
onRetry
|
|
53571
|
-
}) {
|
|
53572
|
-
const { t } = useTranslation4();
|
|
53573
|
-
const name = getPluginRecord(pluginId)?.summary.name ?? pluginId;
|
|
53574
|
-
return /* @__PURE__ */ jsxs10("div", { className: "flex flex-col items-center justify-center gap-2 p-4 text-center text-sm text-muted-foreground", children: [
|
|
53575
|
-
/* @__PURE__ */ jsx35("span", { children: t("plugins.runtime.crashed", { name }) }),
|
|
53576
|
-
/* @__PURE__ */ jsx35(
|
|
53577
|
-
"button",
|
|
53578
|
-
{
|
|
53579
|
-
type: "button",
|
|
53580
|
-
className: "text-xs underline underline-offset-2 hover:text-foreground",
|
|
53581
|
-
onClick: onRetry,
|
|
53582
|
-
children: t("plugins.runtime.retry")
|
|
53583
|
-
}
|
|
53584
|
-
)
|
|
53585
|
-
] });
|
|
53586
|
-
}
|
|
53587
|
-
var PluginErrorBoundary = class extends Component2 {
|
|
53588
|
-
state = { error: false };
|
|
53589
|
-
static getDerivedStateFromError() {
|
|
53590
|
-
return { error: true };
|
|
53591
|
-
}
|
|
53592
|
-
componentDidCatch(error, info) {
|
|
53593
|
-
console.error(
|
|
53594
|
-
`[plugins] ${this.props.pluginId} crashed while rendering`,
|
|
53595
|
-
error,
|
|
53596
|
-
info.componentStack
|
|
53597
|
-
);
|
|
53598
|
-
}
|
|
53599
|
-
render() {
|
|
53600
|
-
if (this.state.error) {
|
|
53601
|
-
return /* @__PURE__ */ jsx35(
|
|
53602
|
-
CrashNotice,
|
|
53603
|
-
{
|
|
53604
|
-
pluginId: this.props.pluginId,
|
|
53605
|
-
onRetry: () => this.setState({ error: false })
|
|
53606
|
-
}
|
|
53607
|
-
);
|
|
53608
|
-
}
|
|
53609
|
-
return this.props.children;
|
|
53610
|
-
}
|
|
53611
|
-
};
|
|
53612
|
-
function PluginScope({
|
|
53613
|
-
pluginId,
|
|
53614
|
-
children
|
|
53615
|
-
}) {
|
|
53616
|
-
return /* @__PURE__ */ jsx35(PluginScopeContext.Provider, { value: pluginId, children: /* @__PURE__ */ jsx35(PluginErrorBoundary, { pluginId, children: /* @__PURE__ */ jsx35(Suspense, { fallback: null, children }) }) });
|
|
53617
|
-
}
|
|
53618
|
-
function withPluginScope(pluginId, Inner) {
|
|
53619
|
-
function Scoped(props) {
|
|
53620
|
-
return /* @__PURE__ */ jsx35(PluginScope, { pluginId, children: /* @__PURE__ */ jsx35(Inner, { ...scopeHostFields(props, pluginId) }) });
|
|
53621
|
-
}
|
|
53622
|
-
Scoped.displayName = `Plugin(${pluginId}:${Inner.displayName ?? Inner.name ?? "Component"})`;
|
|
53623
|
-
return Scoped;
|
|
53624
|
-
}
|
|
53625
|
-
var IconBoundary = class extends Component2 {
|
|
53626
|
-
state = { error: false };
|
|
53627
|
-
static getDerivedStateFromError() {
|
|
53628
|
-
return { error: true };
|
|
53629
|
-
}
|
|
53630
|
-
componentDidCatch(error) {
|
|
53631
|
-
console.error(`[plugins] ${this.props.pluginId} icon failed`, error);
|
|
53632
|
-
}
|
|
53633
|
-
render() {
|
|
53634
|
-
return this.state.error ? null : this.props.children;
|
|
53635
|
-
}
|
|
53636
|
-
};
|
|
53637
|
-
function withIconBoundary(pluginId, Icon2) {
|
|
53638
|
-
if (!Icon2) return void 0;
|
|
53639
|
-
function SafeIcon(props) {
|
|
53640
|
-
return /* @__PURE__ */ jsx35(IconBoundary, { pluginId, children: /* @__PURE__ */ jsx35(Icon2, { ...props }) });
|
|
53641
|
-
}
|
|
53642
|
-
SafeIcon.displayName = `PluginIcon(${pluginId})`;
|
|
53643
|
-
return SafeIcon;
|
|
53644
|
-
}
|
|
53645
|
-
function guardCallback(pluginId, fn, fallback) {
|
|
53646
|
-
if (!fn) return void 0;
|
|
53647
|
-
return (...args) => {
|
|
53648
|
-
try {
|
|
53649
|
-
return fn(...args);
|
|
53650
|
-
} catch (error) {
|
|
53651
|
-
console.error(`[plugins] ${pluginId} callback failed`, error);
|
|
53652
|
-
return fallback;
|
|
53653
|
-
}
|
|
53654
|
-
};
|
|
53655
|
-
}
|
|
53656
|
-
|
|
53657
53805
|
// src/ui/hooks/useSshAuthProviders.ts
|
|
53658
53806
|
import { useEffect as useEffect32, useMemo as useMemo15, useState as useState30 } from "react";
|
|
53659
53807
|
|
|
53660
53808
|
// src/ui/api/auth-methods-api.ts
|
|
53661
53809
|
function remember(data) {
|
|
53662
53810
|
if (data?.token) localStorage.setItem("jwt", data.token);
|
|
53811
|
+
if (data?.trustToken) localStorage.setItem(TRUST_TOKEN_KEY, data.trustToken);
|
|
53663
53812
|
if (data?.success && !data.requires_totp) markUserAuthenticated();
|
|
53664
53813
|
return data;
|
|
53665
53814
|
}
|
|
@@ -53813,7 +53962,7 @@ function contextKey(context) {
|
|
|
53813
53962
|
try {
|
|
53814
53963
|
return JSON.stringify(context);
|
|
53815
53964
|
} catch {
|
|
53816
|
-
return
|
|
53965
|
+
return Object.entries(context).map(([key, value]) => `${key}:${value == null ? "-" : typeof value}`).join(",");
|
|
53817
53966
|
}
|
|
53818
53967
|
}
|
|
53819
53968
|
|
|
@@ -53828,7 +53977,7 @@ import {
|
|
|
53828
53977
|
useSyncExternalStore as useSyncExternalStore6,
|
|
53829
53978
|
useState as useState31
|
|
53830
53979
|
} from "react";
|
|
53831
|
-
import { jsx as
|
|
53980
|
+
import { jsx as jsx37 } from "react/jsx-runtime";
|
|
53832
53981
|
var StatusStoreContext = createContext10(null);
|
|
53833
53982
|
var ServerStatusContext = createContext10(null);
|
|
53834
53983
|
var activeStore = null;
|
|
@@ -53950,6 +54099,9 @@ var pluginHostBridge = {
|
|
|
53950
54099
|
}
|
|
53951
54100
|
return pluginId;
|
|
53952
54101
|
},
|
|
54102
|
+
useDocsUrl(pluginId, page, anchor) {
|
|
54103
|
+
return usePluginDocsUrl(pluginId, page, anchor);
|
|
54104
|
+
},
|
|
53953
54105
|
useTranslation(pluginId) {
|
|
53954
54106
|
const { t, i18n: i18n2 } = useI18nTranslation(pluginId);
|
|
53955
54107
|
return {
|
|
@@ -54176,6 +54328,18 @@ function pluginKey(pluginId, key) {
|
|
|
54176
54328
|
|
|
54177
54329
|
// src/ui/plugin-host/app.ts
|
|
54178
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
|
+
}
|
|
54179
54343
|
function createPluginApp(pluginId, manifest, contributes, options2 = {}) {
|
|
54180
54344
|
const bag = [];
|
|
54181
54345
|
let disposed = false;
|
|
@@ -54580,6 +54744,7 @@ function createPluginApp(pluginId, manifest, contributes, options2 = {}) {
|
|
|
54580
54744
|
onReady: (listener) => track(tabsApi.onReady(listener))
|
|
54581
54745
|
},
|
|
54582
54746
|
confirm: (options3) => shell.confirm(options3),
|
|
54747
|
+
docs: createDocsApi(manifest),
|
|
54583
54748
|
desktop: {
|
|
54584
54749
|
available: isElectron(),
|
|
54585
54750
|
remoteServerUrl,
|
|
@@ -54622,8 +54787,8 @@ function createPluginApp(pluginId, manifest, contributes, options2 = {}) {
|
|
|
54622
54787
|
|
|
54623
54788
|
// src/ui/shell/ActionSlot.tsx
|
|
54624
54789
|
import React50 from "react";
|
|
54625
|
-
import { useTranslation as
|
|
54626
|
-
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";
|
|
54627
54792
|
function ActionSlot({
|
|
54628
54793
|
slotId,
|
|
54629
54794
|
context,
|
|
@@ -54633,17 +54798,17 @@ function ActionSlot({
|
|
|
54633
54798
|
hideLabels,
|
|
54634
54799
|
when
|
|
54635
54800
|
}) {
|
|
54636
|
-
const { t } =
|
|
54801
|
+
const { t } = useTranslation6();
|
|
54637
54802
|
const contributions2 = useActionSlot(slotId, when).filter(
|
|
54638
54803
|
(contribution) => contribution.kind !== "component"
|
|
54639
54804
|
);
|
|
54640
54805
|
if (!enabled || contributions2.length === 0) return null;
|
|
54641
|
-
return /* @__PURE__ */
|
|
54806
|
+
return /* @__PURE__ */ jsx38(Fragment14, { children: contributions2.map((contribution) => {
|
|
54642
54807
|
const invoke = () => {
|
|
54643
54808
|
void invokeAction(contribution.actionId, ...context?.() ?? []);
|
|
54644
54809
|
};
|
|
54645
54810
|
if (renderItem) {
|
|
54646
|
-
return /* @__PURE__ */
|
|
54811
|
+
return /* @__PURE__ */ jsx38(React50.Fragment, { children: renderItem(contribution, invoke) }, contribution.actionId);
|
|
54647
54812
|
}
|
|
54648
54813
|
const Icon2 = contribution.icon;
|
|
54649
54814
|
const label = t(contribution.titleKey);
|
|
@@ -54656,7 +54821,7 @@ function ActionSlot({
|
|
|
54656
54821
|
title: label,
|
|
54657
54822
|
onClick: invoke,
|
|
54658
54823
|
children: [
|
|
54659
|
-
Icon2 && /* @__PURE__ */
|
|
54824
|
+
Icon2 && /* @__PURE__ */ jsx38(Icon2, { className: "size-4 shrink-0" }),
|
|
54660
54825
|
!hideLabels && label
|
|
54661
54826
|
]
|
|
54662
54827
|
},
|
|
@@ -54673,37 +54838,37 @@ function ComponentSlot({
|
|
|
54673
54838
|
(contribution) => contribution.kind === "component" && contribution.component
|
|
54674
54839
|
);
|
|
54675
54840
|
if (contributions2.length === 0) return null;
|
|
54676
|
-
return /* @__PURE__ */
|
|
54841
|
+
return /* @__PURE__ */ jsx38(Fragment14, { children: contributions2.map((contribution) => {
|
|
54677
54842
|
const Contributed = contribution.component;
|
|
54678
|
-
return /* @__PURE__ */
|
|
54843
|
+
return /* @__PURE__ */ jsx38(Contributed, { ...props ?? {} }, contribution.actionId);
|
|
54679
54844
|
}) });
|
|
54680
54845
|
}
|
|
54681
54846
|
|
|
54682
54847
|
// src/ui/plugin-host/PluginViewPlaceholder.tsx
|
|
54683
|
-
import { useTranslation as
|
|
54848
|
+
import { useTranslation as useTranslation7 } from "react-i18next";
|
|
54684
54849
|
|
|
54685
54850
|
// src/ui/plugins/open-plugins.ts
|
|
54686
54851
|
var OPEN_PLUGINS_EVENT = "termix:open-plugins";
|
|
54687
54852
|
|
|
54688
54853
|
// src/ui/plugin-host/PluginViewPlaceholder.tsx
|
|
54689
|
-
import { jsx as
|
|
54854
|
+
import { jsx as jsx39, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
54690
54855
|
function PluginViewPlaceholder({
|
|
54691
54856
|
kind,
|
|
54692
54857
|
viewId,
|
|
54693
54858
|
compact = false
|
|
54694
54859
|
}) {
|
|
54695
|
-
const { t } =
|
|
54860
|
+
const { t } = useTranslation7();
|
|
54696
54861
|
usePluginStore();
|
|
54697
54862
|
const { has } = usePermissions();
|
|
54698
54863
|
const { status, owner } = unregisteredViewStatus(kind, viewId);
|
|
54699
54864
|
const name = owner?.summary.name ?? viewId;
|
|
54700
54865
|
if (status === "loading") {
|
|
54701
|
-
return /* @__PURE__ */
|
|
54866
|
+
return /* @__PURE__ */ jsx39(
|
|
54702
54867
|
"div",
|
|
54703
54868
|
{
|
|
54704
54869
|
className: "flex h-full w-full items-center justify-center",
|
|
54705
54870
|
"aria-label": t("plugins.runtime.loading", { name }),
|
|
54706
|
-
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" })
|
|
54707
54872
|
}
|
|
54708
54873
|
);
|
|
54709
54874
|
}
|
|
@@ -54716,10 +54881,10 @@ function PluginViewPlaceholder({
|
|
|
54716
54881
|
"data-status": status,
|
|
54717
54882
|
className: `flex h-full w-full flex-col items-center justify-center gap-2 text-center ${compact ? "p-3" : "p-6"}`,
|
|
54718
54883
|
children: [
|
|
54719
|
-
/* @__PURE__ */
|
|
54720
|
-
/* @__PURE__ */
|
|
54721
|
-
/* @__PURE__ */
|
|
54722
|
-
!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(
|
|
54723
54888
|
Button,
|
|
54724
54889
|
{
|
|
54725
54890
|
variant: "outline",
|
|
@@ -54825,6 +54990,7 @@ export {
|
|
|
54825
54990
|
notifyShellReady,
|
|
54826
54991
|
resetShellBridge,
|
|
54827
54992
|
usePluginScope,
|
|
54993
|
+
DocsLink,
|
|
54828
54994
|
PANEL,
|
|
54829
54995
|
PanelShell,
|
|
54830
54996
|
BackButton,
|