@qodalis/cli 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/cli-panel.css +247 -102
- package/package.json +2 -2
- package/public-api.d.mts +50 -5
- package/public-api.d.ts +50 -5
- package/public-api.js +188 -23
- package/public-api.js.map +1 -1
- package/public-api.mjs +189 -24
- package/public-api.mjs.map +1 -1
package/public-api.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createCliToken, CliLogLevel, DefaultThemes, DefaultThemeInfos, CliForegroundColor, DefaultLibraryAuthor, CliIcon, writeWrapped, LIBRARY_VERSION as LIBRARY_VERSION$1, writeUsage, writeExamples, writeHint, joinShellWords, CliKeyData, unquoteRawArgument, resolveConfigurationCategories, ICliTranslationService_TOKEN, splitShellWords, cliAuthorize, CliUsersPermissions, ICliAuthorizationService_TOKEN, quoteShellWord, resolveHeaders, appendQueryParams, buildServerWebSocketUrl, ServerVersionNegotiator, CliHttpError, formatJson, visibleLength, ICliEventBus_TOKEN, stripAnsi, CancellablePromise, isCliAccessDeniedError, getParameterValue, ICliCommandGuard_TOKEN, getRightOfWord, CLI_CONFIGURE_STORE_NAME, CliModuleRegistry, initializeBrowserEnvironment, ICliPermissionRegistry_TOKEN, satisfiesVersionRange, CliServerPermissions, ICliDragDropService_TOKEN, cliAccessMetadataGuards, ICliServerAuthService_TOKEN, loadPanelPosition, savePanelPosition, derivePanelThemeStyles, delay, colorFirstWord, clearTerminalLine, ICliCompletionProvider_TOKEN, ICliServerAuthTokenProvider_TOKEN, truncateToWidth } from '@qodalis/cli-core';
|
|
1
|
+
import { createCliToken, CliLogLevel, DefaultThemes, DefaultThemeInfos, CliForegroundColor, DefaultLibraryAuthor, CliIcon, writeWrapped, LIBRARY_VERSION as LIBRARY_VERSION$1, writeUsage, writeExamples, writeHint, joinShellWords, CliKeyData, unquoteRawArgument, resolveConfigurationCategories, ICliTranslationService_TOKEN, splitShellWords, cliAuthorize, CliUsersPermissions, ICliAuthorizationService_TOKEN, quoteShellWord, resolveHeaders, appendQueryParams, buildServerWebSocketUrl, ServerVersionNegotiator, CliHttpError, formatJson, visibleLength, ICliEventBus_TOKEN, stripAnsi, CancellablePromise, isCliAccessDeniedError, getParameterValue, ICliCommandGuard_TOKEN, getRightOfWord, CLI_CONFIGURE_STORE_NAME, CliModuleRegistry, initializeBrowserEnvironment, ICliPermissionRegistry_TOKEN, satisfiesVersionRange, CliServerPermissions, ICliDragDropService_TOKEN, cliAccessMetadataGuards, resolvePanelTheme, prefersDarkScheme, ICliServerAuthService_TOKEN, loadPanelPosition, savePanelPosition, derivePanelThemeStyles, delay, colorFirstWord, clearTerminalLine, ICliCompletionProvider_TOKEN, ICliServerAuthTokenProvider_TOKEN, truncateToWidth } from '@qodalis/cli-core';
|
|
2
2
|
export { ICliUserSessionService_TOKEN, ICliUsersStoreService_TOKEN } from '@qodalis/cli-core';
|
|
3
3
|
import { Terminal } from '@xterm/xterm';
|
|
4
4
|
import { FitAddon } from '@xterm/addon-fit';
|
|
@@ -518,7 +518,7 @@ var CliKeyValueStore_TOKEN = createCliToken("cli-key-value-store");
|
|
|
518
518
|
var SyntaxHighlighterRegistry_TOKEN = createCliToken("syntax-highlighter-registry");
|
|
519
519
|
|
|
520
520
|
// src/lib/version.ts
|
|
521
|
-
var LIBRARY_VERSION = "2.
|
|
521
|
+
var LIBRARY_VERSION = "2.2.0";
|
|
522
522
|
var API_VERSION = 2;
|
|
523
523
|
var ANONYMOUS = "\0anonymous";
|
|
524
524
|
function aliasOwner(context2) {
|
|
@@ -5397,6 +5397,7 @@ var CliServerConnection = class _CliServerConnection {
|
|
|
5397
5397
|
this._eventServiceRegistered = false;
|
|
5398
5398
|
this._healthCheckTimer = null;
|
|
5399
5399
|
this._healthCheckAttempts = 0;
|
|
5400
|
+
this._needsSignIn = false;
|
|
5400
5401
|
}
|
|
5401
5402
|
static {
|
|
5402
5403
|
this.WS_MAX_RECONNECT_ATTEMPTS = 5;
|
|
@@ -5413,6 +5414,13 @@ var CliServerConnection = class _CliServerConnection {
|
|
|
5413
5414
|
get config() {
|
|
5414
5415
|
return this._config;
|
|
5415
5416
|
}
|
|
5417
|
+
/**
|
|
5418
|
+
* The last connect was refused for want of a sign-in (401 or 403 on the
|
|
5419
|
+
* command list): the server is up, and a sign-in reconnects it.
|
|
5420
|
+
*/
|
|
5421
|
+
get needsSignIn() {
|
|
5422
|
+
return this._needsSignIn;
|
|
5423
|
+
}
|
|
5416
5424
|
get connected() {
|
|
5417
5425
|
return this._connected;
|
|
5418
5426
|
}
|
|
@@ -5452,6 +5460,7 @@ var CliServerConnection = class _CliServerConnection {
|
|
|
5452
5460
|
});
|
|
5453
5461
|
}
|
|
5454
5462
|
async connect() {
|
|
5463
|
+
this._needsSignIn = false;
|
|
5455
5464
|
try {
|
|
5456
5465
|
const baseUrl = this.normalizeUrl(this._config.url);
|
|
5457
5466
|
const negotiated = await ServerVersionNegotiator.discover(
|
|
@@ -5534,6 +5543,7 @@ var CliServerConnection = class _CliServerConnection {
|
|
|
5534
5543
|
const url = `${this._basePath}/commands`;
|
|
5535
5544
|
const response = await this.httpFetch(url);
|
|
5536
5545
|
if (!response.ok) {
|
|
5546
|
+
if (response.status === 401 || response.status === 403) this._needsSignIn = true;
|
|
5537
5547
|
throw new Error(
|
|
5538
5548
|
`Server ${this._config.name} returned ${response.status}`
|
|
5539
5549
|
);
|
|
@@ -6224,6 +6234,10 @@ var CliServerManager = class {
|
|
|
6224
6234
|
);
|
|
6225
6235
|
this.registerProxyProcessors(connection, config.name);
|
|
6226
6236
|
this.emitConnected(connection, false);
|
|
6237
|
+
} else if (connection.needsSignIn) {
|
|
6238
|
+
logger?.info(
|
|
6239
|
+
`Server '${config.name}' needs a sign-in; its commands load once you are signed in.`
|
|
6240
|
+
);
|
|
6227
6241
|
} else {
|
|
6228
6242
|
logger?.warn(
|
|
6229
6243
|
`Could not connect to server '${config.name}' at ${config.url}. Commands from this server will not be available.`
|
|
@@ -12586,6 +12600,7 @@ var CliThemeCommandProcessor = class {
|
|
|
12586
12600
|
}
|
|
12587
12601
|
async initialize(context2) {
|
|
12588
12602
|
this.defaultTheme = context2.terminal.options.theme;
|
|
12603
|
+
if (context2.options?.theme !== void 0) return;
|
|
12589
12604
|
this.applySavedTheme(context2, false);
|
|
12590
12605
|
context2.state.select(
|
|
12591
12606
|
(state) => JSON.stringify([
|
|
@@ -19293,8 +19308,9 @@ var welcomeModule = {
|
|
|
19293
19308
|
);
|
|
19294
19309
|
await configureStore.initialize();
|
|
19295
19310
|
const state = configureStore.getState();
|
|
19296
|
-
|
|
19297
|
-
|
|
19311
|
+
const stored = state?.["system"]?.["welcomeMessage"];
|
|
19312
|
+
if (stored && stored !== "always") {
|
|
19313
|
+
showOption = stored;
|
|
19298
19314
|
}
|
|
19299
19315
|
}
|
|
19300
19316
|
if (showOption) {
|
|
@@ -19307,10 +19323,11 @@ var welcomeModule = {
|
|
|
19307
19323
|
context2.terminal.writeln(config.message);
|
|
19308
19324
|
} else {
|
|
19309
19325
|
const branding = resolveCliBranding(context2.options?.branding);
|
|
19326
|
+
const art = branding.art(context2.terminal.cols);
|
|
19310
19327
|
const lines = [
|
|
19311
19328
|
`\u{1F680} Welcome to ${branding.name} [Version ${context2.writer.wrapInColor(LIBRARY_VERSION, CliForegroundColor.Green)}]`,
|
|
19312
19329
|
`(c) ${(/* @__PURE__ */ new Date()).getFullYear()} Qodalis Solutions. All rights reserved.`,
|
|
19313
|
-
|
|
19330
|
+
art,
|
|
19314
19331
|
"",
|
|
19315
19332
|
`\u{1F4D6} ${context2.writer.wrapInColor("Documentation:", CliForegroundColor.Green)} https://cli.qodalis.com/docs/`,
|
|
19316
19333
|
"",
|
|
@@ -19318,7 +19335,10 @@ var welcomeModule = {
|
|
|
19318
19335
|
""
|
|
19319
19336
|
];
|
|
19320
19337
|
lines.forEach((line2) => {
|
|
19321
|
-
context2.terminal.
|
|
19338
|
+
const wrapped = line2 === art ? [line2] : wrapWelcomeLine(line2, context2.terminal.cols);
|
|
19339
|
+
wrapped.forEach(
|
|
19340
|
+
(part) => context2.terminal.write(part + "\r\n")
|
|
19341
|
+
);
|
|
19322
19342
|
});
|
|
19323
19343
|
}
|
|
19324
19344
|
recordWelcomeMessageDisplay();
|
|
@@ -19350,12 +19370,51 @@ var greetingModule = {
|
|
|
19350
19370
|
if (host.typedDuringBoot || host.isReadingInput || context2.currentLine) {
|
|
19351
19371
|
return;
|
|
19352
19372
|
}
|
|
19353
|
-
|
|
19373
|
+
const buffer = context2.terminal.buffer?.active;
|
|
19374
|
+
const room = context2.terminal.cols - (buffer?.cursorX ?? 0) - 1;
|
|
19375
|
+
const greeting = fitGreeting(getGreetingBasedOnTime(), room);
|
|
19376
|
+
if (!greeting) return;
|
|
19377
|
+
await context2.textAnimator?.showText(greeting, {
|
|
19354
19378
|
speed: 60,
|
|
19355
19379
|
removeAfterTyping: true
|
|
19356
19380
|
});
|
|
19357
19381
|
}
|
|
19358
19382
|
};
|
|
19383
|
+
function fitGreeting(text, room) {
|
|
19384
|
+
const width = (value) => Array.from(value).reduce(
|
|
19385
|
+
(sum, ch) => sum + (ch.codePointAt(0) > 65535 || /\p{Extended_Pictographic}/u.test(ch) ? 2 : ch === "\uFE0F" ? 0 : 1),
|
|
19386
|
+
0
|
|
19387
|
+
);
|
|
19388
|
+
if (width(text) <= room) return text;
|
|
19389
|
+
const words = text.split(" ");
|
|
19390
|
+
let fitted = "";
|
|
19391
|
+
for (const word of words) {
|
|
19392
|
+
const next = fitted ? `${fitted} ${word}` : word;
|
|
19393
|
+
if (width(next) > room) break;
|
|
19394
|
+
fitted = next;
|
|
19395
|
+
}
|
|
19396
|
+
return fitted.split(" ").length >= 3 ? fitted.replace(/[,;:]$/, "") : null;
|
|
19397
|
+
}
|
|
19398
|
+
function wrapWelcomeLine(line2, cols) {
|
|
19399
|
+
const width = Math.max(20, cols - 1);
|
|
19400
|
+
const visible = (value) => Array.from(value.replace(/\x1b\[[0-9;]*m/g, "")).reduce(
|
|
19401
|
+
(sum, ch) => sum + (ch.codePointAt(0) > 65535 ? 2 : ch === "\uFE0F" ? 0 : 1),
|
|
19402
|
+
0
|
|
19403
|
+
);
|
|
19404
|
+
if (visible(line2) <= width) return [line2];
|
|
19405
|
+
const lines = [];
|
|
19406
|
+
let current = "";
|
|
19407
|
+
for (const word of line2.split(" ")) {
|
|
19408
|
+
if (current && visible(current) + 1 + visible(word) > width) {
|
|
19409
|
+
lines.push(current);
|
|
19410
|
+
current = word;
|
|
19411
|
+
} else {
|
|
19412
|
+
current = current ? `${current} ${word}` : word;
|
|
19413
|
+
}
|
|
19414
|
+
}
|
|
19415
|
+
if (current) lines.push(current);
|
|
19416
|
+
return lines;
|
|
19417
|
+
}
|
|
19359
19418
|
function shouldDisplayWelcomeMessage(showOption) {
|
|
19360
19419
|
const lastDisplayed = localStorage.getItem(
|
|
19361
19420
|
"cliWelcomeMessageLastDisplayed"
|
|
@@ -22812,6 +22871,9 @@ var CliEngine = class {
|
|
|
22812
22871
|
this.terminalOptions = getTerminalOptions(
|
|
22813
22872
|
this.options?.terminalOptions
|
|
22814
22873
|
);
|
|
22874
|
+
if (this.options?.theme !== void 0 && !this.options?.terminalOptions?.theme) {
|
|
22875
|
+
this.terminalOptions.theme = resolvePanelTheme(this.options.theme, prefersDarkScheme()).terminal;
|
|
22876
|
+
}
|
|
22815
22877
|
const setup = initializeTerminal(
|
|
22816
22878
|
this.container,
|
|
22817
22879
|
this.terminalOptions,
|
|
@@ -23064,6 +23126,14 @@ var CliEngine = class {
|
|
|
23064
23126
|
this.terminal?.focus();
|
|
23065
23127
|
});
|
|
23066
23128
|
}
|
|
23129
|
+
/**
|
|
23130
|
+
* Restyle the terminal: its colors and the background around it.
|
|
23131
|
+
* The `theme` command can still change it afterwards.
|
|
23132
|
+
*/
|
|
23133
|
+
setTheme(theme) {
|
|
23134
|
+
if (this.terminal) this.terminal.options.theme = theme;
|
|
23135
|
+
this.container.style.background = theme.background ?? "";
|
|
23136
|
+
}
|
|
23067
23137
|
/**
|
|
23068
23138
|
* Get the underlying xterm.js Terminal instance.
|
|
23069
23139
|
*/
|
|
@@ -23912,6 +23982,23 @@ function sameJson(a, b) {
|
|
|
23912
23982
|
return JSON.stringify(a) === JSON.stringify(b);
|
|
23913
23983
|
}
|
|
23914
23984
|
var PANE_RESIZING_BODY_CLASS = "cli-pane-resizing";
|
|
23985
|
+
var DARK_SCHEME_QUERY = "(prefers-color-scheme: dark)";
|
|
23986
|
+
function followsSystem(input) {
|
|
23987
|
+
return input === "auto" || typeof input === "object" && input !== null && input.base === "auto";
|
|
23988
|
+
}
|
|
23989
|
+
function themeKey(input) {
|
|
23990
|
+
return input === void 0 ? "" : JSON.stringify(input);
|
|
23991
|
+
}
|
|
23992
|
+
function sameTerminalTheme(a, b) {
|
|
23993
|
+
return !!a && !!b && a.background === b.background && a.foreground === b.foreground && a.cursor === b.cursor;
|
|
23994
|
+
}
|
|
23995
|
+
var MIN_KEYBOARD_INSET = 80;
|
|
23996
|
+
function visualViewportFields() {
|
|
23997
|
+
const vv = typeof window !== "undefined" ? window.visualViewport : null;
|
|
23998
|
+
if (!vv) return { keyboardInset: 0, visibleHeight: 0 };
|
|
23999
|
+
const inset = Math.round(window.innerHeight - vv.height - vv.offsetTop);
|
|
24000
|
+
return { keyboardInset: inset >= MIN_KEYBOARD_INSET ? inset : 0, visibleHeight: Math.round(vv.height) };
|
|
24001
|
+
}
|
|
23915
24002
|
function defaultViewport() {
|
|
23916
24003
|
if (typeof window === "undefined") return { width: 0, height: 0 };
|
|
23917
24004
|
return { width: window.innerWidth, height: window.innerHeight };
|
|
@@ -23930,6 +24017,9 @@ var CliPanelController = class {
|
|
|
23930
24017
|
/* ─── Subscription ──────────────────────────────────────── */
|
|
23931
24018
|
this.subscribe = (listener) => {
|
|
23932
24019
|
this.listeners.add(listener);
|
|
24020
|
+
this.watchSystemScheme();
|
|
24021
|
+
this.watchVisualViewport();
|
|
24022
|
+
this.onVisualViewportChange();
|
|
23933
24023
|
return () => {
|
|
23934
24024
|
this.listeners.delete(listener);
|
|
23935
24025
|
};
|
|
@@ -23966,11 +24056,22 @@ var CliPanelController = class {
|
|
|
23966
24056
|
this.closeMenus();
|
|
23967
24057
|
this.cancelRename();
|
|
23968
24058
|
};
|
|
24059
|
+
this.onSystemSchemeChange = () => this.applyTheme();
|
|
24060
|
+
this.onVisualViewportChange = () => {
|
|
24061
|
+
const fields = visualViewportFields();
|
|
24062
|
+
const s = this.snapshot;
|
|
24063
|
+
if (fields.keyboardInset === s.keyboardInset && fields.visibleHeight === s.visibleHeight) return;
|
|
24064
|
+
this.commit(fields);
|
|
24065
|
+
};
|
|
23969
24066
|
const config = options.config ?? {};
|
|
23970
24067
|
this.callbacks = options.callbacks ?? {};
|
|
23971
24068
|
this.controlled = options.controlled ?? {};
|
|
23972
24069
|
this.viewport = options.viewport ?? defaultViewport;
|
|
23973
24070
|
this.persistPosition = options.persistPosition ?? true;
|
|
24071
|
+
this.themeInput = config.theme;
|
|
24072
|
+
this.resolvedTheme = resolvePanelTheme(config.theme, prefersDarkScheme());
|
|
24073
|
+
this.watchSystemScheme();
|
|
24074
|
+
this.watchVisualViewport();
|
|
23974
24075
|
this.internal = {
|
|
23975
24076
|
collapsed: config.isCollapsed ?? true,
|
|
23976
24077
|
hidden: config.isHidden ?? false,
|
|
@@ -23997,7 +24098,11 @@ var CliPanelController = class {
|
|
|
23997
24098
|
isHorizontal: false,
|
|
23998
24099
|
showStatusIndicators: true,
|
|
23999
24100
|
panelResizing: false,
|
|
24000
|
-
|
|
24101
|
+
// Without a host theme the stylesheet's colors (and its overrides) apply
|
|
24102
|
+
themeStyles: config.theme === void 0 ? {} : this.resolvedTheme.styles,
|
|
24103
|
+
scheme: this.resolvedTheme.scheme,
|
|
24104
|
+
terminalTheme: config.theme === void 0 ? void 0 : this.resolvedTheme.terminal,
|
|
24105
|
+
...visualViewportFields(),
|
|
24001
24106
|
...this.configFields(config),
|
|
24002
24107
|
tabs: [],
|
|
24003
24108
|
activeTabId: 0,
|
|
@@ -24015,8 +24120,9 @@ var CliPanelController = class {
|
|
|
24015
24120
|
formattedUptime: formatUptime2(0)
|
|
24016
24121
|
});
|
|
24017
24122
|
}
|
|
24018
|
-
/** Apply a new panel configuration (chrome buttons, theme sync). */
|
|
24123
|
+
/** Apply a new panel configuration (chrome buttons, theme, theme sync). */
|
|
24019
24124
|
setOptions(config) {
|
|
24125
|
+
if (themeKey(config?.theme) !== themeKey(this.themeInput)) this.setTheme(config?.theme);
|
|
24020
24126
|
const fields = this.configFields(config ?? {});
|
|
24021
24127
|
const s = this.snapshot;
|
|
24022
24128
|
if (fields.closable === s.closable && fields.resizable === s.resizable && fields.hideable === s.hideable && fields.hideAlignment === s.hideAlignment && fields.syncTheme === s.syncTheme) {
|
|
@@ -24026,6 +24132,15 @@ var CliPanelController = class {
|
|
|
24026
24132
|
if (fields.syncTheme) this.startThemeSync();
|
|
24027
24133
|
else this.stopThemeSync();
|
|
24028
24134
|
}
|
|
24135
|
+
/**
|
|
24136
|
+
* Restyle the panel and every terminal in it (see `CliPanelConfig.theme`).
|
|
24137
|
+
* `undefined` returns to the default palette and leaves the terminals' theme alone.
|
|
24138
|
+
*/
|
|
24139
|
+
setTheme(theme) {
|
|
24140
|
+
this.themeInput = theme;
|
|
24141
|
+
this.watchSystemScheme();
|
|
24142
|
+
this.applyTheme();
|
|
24143
|
+
}
|
|
24029
24144
|
/** Replace the change callbacks (wrappers call this when their props change). */
|
|
24030
24145
|
setCallbacks(callbacks) {
|
|
24031
24146
|
this.callbacks = callbacks;
|
|
@@ -24051,6 +24166,9 @@ var CliPanelController = class {
|
|
|
24051
24166
|
destroy() {
|
|
24052
24167
|
this.tracker.destroy();
|
|
24053
24168
|
this.stopThemeSync();
|
|
24169
|
+
this.schemeQuery?.removeEventListener("change", this.onSystemSchemeChange);
|
|
24170
|
+
this.schemeQuery = void 0;
|
|
24171
|
+
this.unwatchVisualViewport();
|
|
24054
24172
|
this.endPanelResize();
|
|
24055
24173
|
this.endPaneResize();
|
|
24056
24174
|
this.detachDocumentListeners();
|
|
@@ -24087,7 +24205,9 @@ var CliPanelController = class {
|
|
|
24087
24205
|
unhide() {
|
|
24088
24206
|
if (!this.snapshot.hidden) return;
|
|
24089
24207
|
this.updateHidden(false);
|
|
24090
|
-
|
|
24208
|
+
const collapsed = this.snapshot.initialized ? this.preHideCollapsed : false;
|
|
24209
|
+
if (this.snapshot.collapsed !== collapsed) this.updateCollapsed(collapsed);
|
|
24210
|
+
if (!collapsed) this.ensureInitialized();
|
|
24091
24211
|
}
|
|
24092
24212
|
toggleHide() {
|
|
24093
24213
|
if (this.snapshot.hidden) this.unhide();
|
|
@@ -24266,6 +24386,7 @@ var CliPanelController = class {
|
|
|
24266
24386
|
if (!this.findTab(tabId)) return;
|
|
24267
24387
|
this.engines.set(paneId, engine);
|
|
24268
24388
|
this.tracker.registerEngine(tabId, paneId, engine);
|
|
24389
|
+
if (this.snapshot.terminalTheme) engine.setTheme(this.snapshot.terminalTheme);
|
|
24269
24390
|
if (this.snapshot.syncTheme) this.startThemeSync();
|
|
24270
24391
|
}
|
|
24271
24392
|
getEngine(paneId) {
|
|
@@ -24343,7 +24464,7 @@ var CliPanelController = class {
|
|
|
24343
24464
|
});
|
|
24344
24465
|
}
|
|
24345
24466
|
/* ─── Drag resizing ─────────────────────────────────────── */
|
|
24346
|
-
/**
|
|
24467
|
+
/** Pointer (mouse, touch or pen) down on the panel's resize bar. */
|
|
24347
24468
|
startPanelResize(clientX, clientY) {
|
|
24348
24469
|
if (!this.snapshot.resizable || typeof document === "undefined") return;
|
|
24349
24470
|
if (this.snapshot.collapsed) this.toggle();
|
|
@@ -24354,10 +24475,11 @@ var CliPanelController = class {
|
|
|
24354
24475
|
startHeight: this.snapshot.height
|
|
24355
24476
|
};
|
|
24356
24477
|
this.commit({ panelResizing: true });
|
|
24357
|
-
document.addEventListener("
|
|
24358
|
-
document.addEventListener("
|
|
24478
|
+
document.addEventListener("pointermove", this.onPanelResizeMove);
|
|
24479
|
+
document.addEventListener("pointerup", this.onPanelResizeEnd);
|
|
24480
|
+
document.addEventListener("pointercancel", this.onPanelResizeEnd);
|
|
24359
24481
|
}
|
|
24360
|
-
/**
|
|
24482
|
+
/** Pointer down on the divider before pane `dividerIndex + 1` of a tab. */
|
|
24361
24483
|
startPaneResize(tabId, dividerIndex, clientX, containerWidth) {
|
|
24362
24484
|
const tab = this.findTab(tabId);
|
|
24363
24485
|
if (!tab || typeof document === "undefined") return;
|
|
@@ -24370,22 +24492,25 @@ var CliPanelController = class {
|
|
|
24370
24492
|
};
|
|
24371
24493
|
this.commit({ paneResizing: true });
|
|
24372
24494
|
document.body.classList.add(PANE_RESIZING_BODY_CLASS);
|
|
24373
|
-
document.addEventListener("
|
|
24374
|
-
document.addEventListener("
|
|
24495
|
+
document.addEventListener("pointermove", this.onPaneResizeMove);
|
|
24496
|
+
document.addEventListener("pointerup", this.onPaneResizeEnd);
|
|
24497
|
+
document.addEventListener("pointercancel", this.onPaneResizeEnd);
|
|
24375
24498
|
}
|
|
24376
24499
|
endPanelResize() {
|
|
24377
24500
|
if (!this.panelDrag) return;
|
|
24378
24501
|
this.panelDrag = void 0;
|
|
24379
|
-
document.removeEventListener("
|
|
24380
|
-
document.removeEventListener("
|
|
24502
|
+
document.removeEventListener("pointermove", this.onPanelResizeMove);
|
|
24503
|
+
document.removeEventListener("pointerup", this.onPanelResizeEnd);
|
|
24504
|
+
document.removeEventListener("pointercancel", this.onPanelResizeEnd);
|
|
24381
24505
|
this.commit({ panelResizing: false });
|
|
24382
24506
|
}
|
|
24383
24507
|
endPaneResize() {
|
|
24384
24508
|
if (!this.paneDrag) return;
|
|
24385
24509
|
this.paneDrag = void 0;
|
|
24386
24510
|
document.body.classList.remove(PANE_RESIZING_BODY_CLASS);
|
|
24387
|
-
document.removeEventListener("
|
|
24388
|
-
document.removeEventListener("
|
|
24511
|
+
document.removeEventListener("pointermove", this.onPaneResizeMove);
|
|
24512
|
+
document.removeEventListener("pointerup", this.onPaneResizeEnd);
|
|
24513
|
+
document.removeEventListener("pointercancel", this.onPaneResizeEnd);
|
|
24389
24514
|
this.commit({ paneResizing: false });
|
|
24390
24515
|
}
|
|
24391
24516
|
syncDocumentListeners() {
|
|
@@ -24413,7 +24538,7 @@ var CliPanelController = class {
|
|
|
24413
24538
|
if (!engine) return;
|
|
24414
24539
|
const theme = engine.getTerminal().options.theme;
|
|
24415
24540
|
if (!theme) return;
|
|
24416
|
-
const styles = derivePanelThemeStyles(theme);
|
|
24541
|
+
const styles = sameTerminalTheme(theme, this.resolvedTheme.terminal) ? this.resolvedTheme.styles : derivePanelThemeStyles(theme);
|
|
24417
24542
|
if (sameRecord(styles, this.snapshot.themeStyles)) return;
|
|
24418
24543
|
this.commit({ themeStyles: styles });
|
|
24419
24544
|
}
|
|
@@ -24430,6 +24555,44 @@ var CliPanelController = class {
|
|
|
24430
24555
|
this.themeObserver = new MutationObserver(() => this.syncThemeFromEngine());
|
|
24431
24556
|
this.themeObserver.observe(container, { attributes: true, attributeFilter: ["style"] });
|
|
24432
24557
|
}
|
|
24558
|
+
applyTheme() {
|
|
24559
|
+
const resolved = resolvePanelTheme(this.themeInput, prefersDarkScheme());
|
|
24560
|
+
this.resolvedTheme = resolved;
|
|
24561
|
+
const terminalTheme = this.themeInput === void 0 ? void 0 : resolved.terminal;
|
|
24562
|
+
const terminalChanged = !!terminalTheme && !sameTerminalTheme(terminalTheme, this.snapshot.terminalTheme);
|
|
24563
|
+
const themeStyles = this.themeInput === void 0 ? {} : resolved.styles;
|
|
24564
|
+
this.commit({ themeStyles, scheme: resolved.scheme, terminalTheme });
|
|
24565
|
+
if (terminalChanged) this.engines.forEach((engine) => engine.setTheme(terminalTheme));
|
|
24566
|
+
if (this.snapshot.syncTheme) this.syncThemeFromEngine();
|
|
24567
|
+
}
|
|
24568
|
+
/** Follow the system's light/dark setting while the theme is 'auto'. */
|
|
24569
|
+
watchSystemScheme() {
|
|
24570
|
+
const follow = followsSystem(this.themeInput) && typeof window !== "undefined" && !!window.matchMedia;
|
|
24571
|
+
if (follow && !this.schemeQuery) {
|
|
24572
|
+
this.schemeQuery = window.matchMedia(DARK_SCHEME_QUERY);
|
|
24573
|
+
this.schemeQuery.addEventListener?.("change", this.onSystemSchemeChange);
|
|
24574
|
+
} else if (!follow && this.schemeQuery) {
|
|
24575
|
+
this.schemeQuery.removeEventListener?.("change", this.onSystemSchemeChange);
|
|
24576
|
+
this.schemeQuery = void 0;
|
|
24577
|
+
}
|
|
24578
|
+
}
|
|
24579
|
+
/* ─── On-screen keyboard ────────────────────────────────── */
|
|
24580
|
+
/**
|
|
24581
|
+
* Phone browsers open the keyboard over the page and shrink only the visual
|
|
24582
|
+
* viewport; follow it so the panel stays above the keyboard.
|
|
24583
|
+
*/
|
|
24584
|
+
watchVisualViewport() {
|
|
24585
|
+
const vv = typeof window !== "undefined" ? window.visualViewport : null;
|
|
24586
|
+
if (!vv || this.visualViewport) return;
|
|
24587
|
+
this.visualViewport = vv;
|
|
24588
|
+
vv.addEventListener("resize", this.onVisualViewportChange);
|
|
24589
|
+
vv.addEventListener("scroll", this.onVisualViewportChange);
|
|
24590
|
+
}
|
|
24591
|
+
unwatchVisualViewport() {
|
|
24592
|
+
this.visualViewport?.removeEventListener("resize", this.onVisualViewportChange);
|
|
24593
|
+
this.visualViewport?.removeEventListener("scroll", this.onVisualViewportChange);
|
|
24594
|
+
this.visualViewport = void 0;
|
|
24595
|
+
}
|
|
24433
24596
|
stopThemeSync() {
|
|
24434
24597
|
this.themeObserver?.disconnect();
|
|
24435
24598
|
this.themeObserver = void 0;
|
|
@@ -24742,6 +24905,8 @@ function positionDropdownItemClass(s, position) {
|
|
|
24742
24905
|
}
|
|
24743
24906
|
function panelWrapperStyle(s) {
|
|
24744
24907
|
const style = s.isHorizontal ? { width: `${s.width}px` } : { height: `${s.height}px` };
|
|
24908
|
+
if (s.keyboardInset > 0) style["--cli-panel-keyboard-inset"] = `${s.keyboardInset}px`;
|
|
24909
|
+
if (s.visibleHeight > 0) style["--cli-panel-visible-height"] = `${s.visibleHeight}px`;
|
|
24745
24910
|
if (s.hidden) style["display"] = "none";
|
|
24746
24911
|
return { ...style, ...s.themeStyles };
|
|
24747
24912
|
}
|
|
@@ -24749,7 +24914,7 @@ function paneStyle(widthPercent) {
|
|
|
24749
24914
|
return { flex: `${widthPercent} 1 0` };
|
|
24750
24915
|
}
|
|
24751
24916
|
function contextMenuStyle(s) {
|
|
24752
|
-
return { left: `${s.contextMenu.x}px`, top: `${s.contextMenu.y}px` };
|
|
24917
|
+
return { ...s.themeStyles, left: `${s.contextMenu.x}px`, top: `${s.contextMenu.y}px` };
|
|
24753
24918
|
}
|
|
24754
24919
|
function statusIndicators(s) {
|
|
24755
24920
|
const items = [];
|
|
@@ -24866,7 +25031,7 @@ function openStatusDropdown(s) {
|
|
|
24866
25031
|
kind: "services",
|
|
24867
25032
|
header: PANEL_LABELS.servicesHeader,
|
|
24868
25033
|
emptyText: PANEL_LABELS.servicesEmpty,
|
|
24869
|
-
style: s.servicesDropdownStyle,
|
|
25034
|
+
style: { ...s.themeStyles, ...s.servicesDropdownStyle },
|
|
24870
25035
|
rows: s.global.serviceDetails.map((svc, i) => ({
|
|
24871
25036
|
key: `${i}-${svc.name}`,
|
|
24872
25037
|
dotClass: joinClasses("cli-panel-svc-dot", svc.status === "running" ? "svc-running" : "svc-stopped"),
|
|
@@ -24882,7 +25047,7 @@ function openStatusDropdown(s) {
|
|
|
24882
25047
|
kind: "servers",
|
|
24883
25048
|
header: PANEL_LABELS.serversHeader,
|
|
24884
25049
|
emptyText: PANEL_LABELS.serversEmpty,
|
|
24885
|
-
style: s.serversDropdownStyle,
|
|
25050
|
+
style: { ...s.themeStyles, ...s.serversDropdownStyle },
|
|
24886
25051
|
rows: s.global.serverDetails.map((srv, i) => ({
|
|
24887
25052
|
key: `${i}-${srv.name}`,
|
|
24888
25053
|
dotClass: joinClasses("cli-panel-svc-dot", srv.connected ? "svc-running" : "svc-stopped"),
|