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