@qodalis/cli 2.1.1 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qodalis/cli",
3
- "version": "2.1.1",
3
+ "version": "2.2.0",
4
4
  "description": "Framework-agnostic CLI engine for @qodalis terminal applications.",
5
5
  "author": "Nicolae Lupei, Qodalis Solutions",
6
6
  "license": "MIT",
@@ -30,7 +30,7 @@
30
30
  "./assets/*": "./assets/*"
31
31
  },
32
32
  "dependencies": {
33
- "@qodalis/cli-core": "2.1.1",
33
+ "@qodalis/cli-core": "2.2.0",
34
34
  "@xterm/xterm": "^6.0.0",
35
35
  "@xterm/addon-fit": "^0.11.0",
36
36
  "@xterm/addon-web-links": "^0.12.0",
package/public-api.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { ICliCommandProcessor, ICliCommandParameterDescriptor as ICliCommandParameterDescriptor$1, ICliCommandProcessorRegistry, ICliCommandChildProcessor, CliProcessorMetadata, CliStateConfiguration, ICliExecutionContext, CliProcessCommand, ICliCommandAuthor, ICliCommandControls, CliThemeInfo, ICliExecutionProcess, ICliUserSession, ICliSpinner, ICliPercentageProgressBar, ICliTextAnimator, ICliTerminalWriter, ICliCommandExecutorService, ICliClipboard, ICliStateStore, CliOptions, ICliLogger, ICliServiceProvider, ICliTranslationService, ICliInputReader, ICliBackgroundServiceRegistry, ICliHttpClient, ICliNotifier, ICliManagedInterval, ICliManagedTimer, ICliEventBus, ICliKeyValueStore, CliStateStoreOptions, ICliCompletionProvider, ICliFilePickerProvider, CliFullScreenOptions, ICliProcessRegistry, ICliBackgroundService, ICliServiceContext, ICliBackgroundServiceInfo, ICliServiceLogEntry, CliServiceEventHandler, ICliGlobalParameterHandler, CliForegroundColor, CliBackgroundColor, CliToken, CliProvider, CliTableOptions, CliLogLevel, CliPercentageProgressBarUpdateValueOptions, CliTextAnimatorOptions, ICliModule, CliModuleRegistry, Package, ICliPingServerService, CliLineOptions, CliSelectOption, CliSelectOptions, CliMultiSelectOption, CliMultiSelectOptions, CliNumberOptions, CliDateOptions, CliFilePickerOptions, CliFileResult, ICliProcessRegisterOptions, ICliProcessEntry, ICliDragDropService, CliHttpRequestOptions, CliNotification, ICliPermissionRegistry, CliPermissionDefinition, CliBranding, CliState, CliEngineSnapshot, CliEvent, CliEventType, CliEventMap, CliEmitOptions, CustomEventType, CliEventHandler, CliServerConfig, ICliServerAuthService, CliServerCommandDescriptor, CliServerCapabilities, CliServerResponse, CliServerOutput, CliPanelPosition, CliPanelConfig, CliPanelHideAlignment, ICliPanelRef, CliPanelState } from '@qodalis/cli-core';
1
+ import { ICliCommandProcessor, ICliCommandParameterDescriptor as ICliCommandParameterDescriptor$1, ICliCommandProcessorRegistry, ICliCommandChildProcessor, CliProcessorMetadata, CliStateConfiguration, ICliExecutionContext, CliProcessCommand, ICliCommandAuthor, ICliCommandControls, CliThemeInfo, ICliExecutionProcess, ICliUserSession, ICliSpinner, ICliPercentageProgressBar, ICliTextAnimator, ICliTerminalWriter, ICliCommandExecutorService, ICliClipboard, ICliStateStore, CliOptions, ICliLogger, ICliServiceProvider, ICliTranslationService, ICliInputReader, ICliBackgroundServiceRegistry, ICliHttpClient, ICliNotifier, ICliManagedInterval, ICliManagedTimer, ICliEventBus, ICliKeyValueStore, CliStateStoreOptions, ICliCompletionProvider, ICliFilePickerProvider, CliFullScreenOptions, ICliProcessRegistry, ICliBackgroundService, ICliServiceContext, ICliBackgroundServiceInfo, ICliServiceLogEntry, CliServiceEventHandler, ICliGlobalParameterHandler, CliForegroundColor, CliBackgroundColor, CliToken, CliProvider, CliTableOptions, CliLogLevel, CliPercentageProgressBarUpdateValueOptions, CliTextAnimatorOptions, ICliModule, CliModuleRegistry, Package, ICliPingServerService, CliLineOptions, CliSelectOption, CliSelectOptions, CliMultiSelectOption, CliMultiSelectOptions, CliNumberOptions, CliDateOptions, CliFilePickerOptions, CliFileResult, ICliProcessRegisterOptions, ICliProcessEntry, ICliDragDropService, CliHttpRequestOptions, CliNotification, ICliPermissionRegistry, CliPermissionDefinition, CliBranding, CliState, CliEngineSnapshot, CliEvent, CliEventType, CliEventMap, CliEmitOptions, CustomEventType, CliEventHandler, CliServerConfig, ICliServerAuthService, CliServerCommandDescriptor, CliServerCapabilities, CliServerResponse, CliServerOutput, CliPanelPosition, CliPanelConfig, CliPanelHideAlignment, ICliPanelRef, CliPanelThemeInput, CliPanelState } from '@qodalis/cli-core';
2
2
  export { ICliUserSessionService_TOKEN, ICliUsersStoreService_TOKEN } from '@qodalis/cli-core';
3
3
  import { ITheme, Terminal, ITerminalAddon, ITerminalOptions, ITerminalInitOnlyOptions } from '@xterm/xterm';
4
4
  import * as rxjs from 'rxjs';
@@ -165,7 +165,7 @@ declare const CliKeyValueStore_TOKEN: any;
165
165
  */
166
166
  declare const SyntaxHighlighterRegistry_TOKEN: any;
167
167
 
168
- declare const LIBRARY_VERSION = "2.1.1";
168
+ declare const LIBRARY_VERSION = "2.2.0";
169
169
  declare const API_VERSION = 2;
170
170
 
171
171
  declare class CliAliasCommandProcessor implements ICliCommandProcessor {
@@ -2977,6 +2977,11 @@ declare class CliEngine {
2977
2977
  * Focus the terminal and fit to container.
2978
2978
  */
2979
2979
  focus(): void;
2980
+ /**
2981
+ * Restyle the terminal: its colors and the background around it.
2982
+ * The `theme` command can still change it afterwards.
2983
+ */
2984
+ setTheme(theme: ITheme): void;
2980
2985
  /**
2981
2986
  * Get the underlying xterm.js Terminal instance.
2982
2987
  */
@@ -3695,7 +3700,19 @@ interface CliPanelSnapshot {
3695
3700
  /** Status text is shown in the header for top/bottom, compact dots otherwise. */
3696
3701
  showStatusIndicators: boolean;
3697
3702
  panelResizing: boolean;
3703
+ /** CSS custom properties of the theme, for the wrapper and the hide tab. */
3698
3704
  themeStyles: Record<string, string>;
3705
+ /** Whether the panel is light or dark. */
3706
+ scheme: 'light' | 'dark';
3707
+ /** Theme the host set for the terminals; undefined leaves them alone. */
3708
+ terminalTheme?: ITheme;
3709
+ /**
3710
+ * Height of the on-screen keyboard over the page (0 when closed), from the
3711
+ * visual viewport: the panel moves above it.
3712
+ */
3713
+ keyboardInset: number;
3714
+ /** Height of the visible area (visual viewport), 0 when unknown; caps the panel's height. */
3715
+ visibleHeight: number;
3699
3716
  closable: boolean;
3700
3717
  resizable: boolean;
3701
3718
  hideable: boolean;
@@ -3828,11 +3845,21 @@ declare class CliPanelController implements ICliPanelRef<CliEngine> {
3828
3845
  private documentListenersAttached;
3829
3846
  private rootElement;
3830
3847
  private themeObserver?;
3848
+ /** The host's theme (`config.theme`); undefined leaves the terminals' own theme alone. */
3849
+ private themeInput?;
3850
+ private resolvedTheme;
3851
+ private schemeQuery?;
3852
+ private visualViewport?;
3831
3853
  constructor(options?: CliPanelControllerOptions);
3832
3854
  readonly subscribe: (listener: () => void) => (() => void);
3833
3855
  readonly getSnapshot: () => CliPanelSnapshot;
3834
- /** Apply a new panel configuration (chrome buttons, theme sync). */
3856
+ /** Apply a new panel configuration (chrome buttons, theme, theme sync). */
3835
3857
  setOptions(config: CliPanelConfig | undefined): void;
3858
+ /**
3859
+ * Restyle the panel and every terminal in it (see `CliPanelConfig.theme`).
3860
+ * `undefined` returns to the default palette and leaves the terminals' theme alone.
3861
+ */
3862
+ setTheme(theme: CliPanelThemeInput | undefined): void;
3836
3863
  /** Replace the change callbacks (wrappers call this when their props change). */
3837
3864
  setCallbacks(callbacks: CliPanelCallbacks): void;
3838
3865
  /** Update host-controlled values. Unchanged values are ignored. */
@@ -3892,9 +3919,9 @@ declare class CliPanelController implements ICliPanelRef<CliEngine> {
3892
3919
  toggleServersDropdown(anchor?: Element | null): void;
3893
3920
  /** Close the context menu and every dropdown. */
3894
3921
  closeMenus(): void;
3895
- /** Mouse down on the panel's resize bar. */
3922
+ /** Pointer (mouse, touch or pen) down on the panel's resize bar. */
3896
3923
  startPanelResize(clientX: number, clientY: number): void;
3897
- /** Mouse down on the divider before pane `dividerIndex + 1` of a tab. */
3924
+ /** Pointer down on the divider before pane `dividerIndex + 1` of a tab. */
3898
3925
  startPaneResize(tabId: number, dividerIndex: number, clientX: number, containerWidth: number): void;
3899
3926
  private readonly onPanelResizeMove;
3900
3927
  private readonly onPanelResizeEnd;
@@ -3914,6 +3941,17 @@ declare class CliPanelController implements ICliPanelRef<CliEngine> {
3914
3941
  * Engines are registered after they start, so their theme is set.
3915
3942
  */
3916
3943
  private startThemeSync;
3944
+ private applyTheme;
3945
+ /** Follow the system's light/dark setting while the theme is 'auto'. */
3946
+ private watchSystemScheme;
3947
+ private readonly onSystemSchemeChange;
3948
+ /**
3949
+ * Phone browsers open the keyboard over the page and shrink only the visual
3950
+ * viewport; follow it so the panel stays above the keyboard.
3951
+ */
3952
+ private watchVisualViewport;
3953
+ private unwatchVisualViewport;
3954
+ private readonly onVisualViewportChange;
3917
3955
  private stopThemeSync;
3918
3956
  private ensureInitialized;
3919
3957
  private updateCollapsed;
@@ -4017,6 +4055,7 @@ declare function positionDropdownItemClass(s: CliPanelSnapshot, position: CliPan
4017
4055
  /** Size, visibility and theme variables of the panel wrapper. */
4018
4056
  declare function panelWrapperStyle(s: CliPanelSnapshot): Record<string, string>;
4019
4057
  declare function paneStyle(widthPercent: number): Record<string, string>;
4058
+ /** Menus render outside the panel element, so they carry the theme's variables themselves. */
4020
4059
  declare function contextMenuStyle(s: CliPanelSnapshot): Record<string, string>;
4021
4060
  interface PanelStatusIndicator {
4022
4061
  key: 'execution' | 'services' | 'lastCommand' | 'servers' | 'uptime' | 'notification';
package/public-api.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ICliCommandProcessor, ICliCommandParameterDescriptor as ICliCommandParameterDescriptor$1, ICliCommandProcessorRegistry, ICliCommandChildProcessor, CliProcessorMetadata, CliStateConfiguration, ICliExecutionContext, CliProcessCommand, ICliCommandAuthor, ICliCommandControls, CliThemeInfo, ICliExecutionProcess, ICliUserSession, ICliSpinner, ICliPercentageProgressBar, ICliTextAnimator, ICliTerminalWriter, ICliCommandExecutorService, ICliClipboard, ICliStateStore, CliOptions, ICliLogger, ICliServiceProvider, ICliTranslationService, ICliInputReader, ICliBackgroundServiceRegistry, ICliHttpClient, ICliNotifier, ICliManagedInterval, ICliManagedTimer, ICliEventBus, ICliKeyValueStore, CliStateStoreOptions, ICliCompletionProvider, ICliFilePickerProvider, CliFullScreenOptions, ICliProcessRegistry, ICliBackgroundService, ICliServiceContext, ICliBackgroundServiceInfo, ICliServiceLogEntry, CliServiceEventHandler, ICliGlobalParameterHandler, CliForegroundColor, CliBackgroundColor, CliToken, CliProvider, CliTableOptions, CliLogLevel, CliPercentageProgressBarUpdateValueOptions, CliTextAnimatorOptions, ICliModule, CliModuleRegistry, Package, ICliPingServerService, CliLineOptions, CliSelectOption, CliSelectOptions, CliMultiSelectOption, CliMultiSelectOptions, CliNumberOptions, CliDateOptions, CliFilePickerOptions, CliFileResult, ICliProcessRegisterOptions, ICliProcessEntry, ICliDragDropService, CliHttpRequestOptions, CliNotification, ICliPermissionRegistry, CliPermissionDefinition, CliBranding, CliState, CliEngineSnapshot, CliEvent, CliEventType, CliEventMap, CliEmitOptions, CustomEventType, CliEventHandler, CliServerConfig, ICliServerAuthService, CliServerCommandDescriptor, CliServerCapabilities, CliServerResponse, CliServerOutput, CliPanelPosition, CliPanelConfig, CliPanelHideAlignment, ICliPanelRef, CliPanelState } from '@qodalis/cli-core';
1
+ import { ICliCommandProcessor, ICliCommandParameterDescriptor as ICliCommandParameterDescriptor$1, ICliCommandProcessorRegistry, ICliCommandChildProcessor, CliProcessorMetadata, CliStateConfiguration, ICliExecutionContext, CliProcessCommand, ICliCommandAuthor, ICliCommandControls, CliThemeInfo, ICliExecutionProcess, ICliUserSession, ICliSpinner, ICliPercentageProgressBar, ICliTextAnimator, ICliTerminalWriter, ICliCommandExecutorService, ICliClipboard, ICliStateStore, CliOptions, ICliLogger, ICliServiceProvider, ICliTranslationService, ICliInputReader, ICliBackgroundServiceRegistry, ICliHttpClient, ICliNotifier, ICliManagedInterval, ICliManagedTimer, ICliEventBus, ICliKeyValueStore, CliStateStoreOptions, ICliCompletionProvider, ICliFilePickerProvider, CliFullScreenOptions, ICliProcessRegistry, ICliBackgroundService, ICliServiceContext, ICliBackgroundServiceInfo, ICliServiceLogEntry, CliServiceEventHandler, ICliGlobalParameterHandler, CliForegroundColor, CliBackgroundColor, CliToken, CliProvider, CliTableOptions, CliLogLevel, CliPercentageProgressBarUpdateValueOptions, CliTextAnimatorOptions, ICliModule, CliModuleRegistry, Package, ICliPingServerService, CliLineOptions, CliSelectOption, CliSelectOptions, CliMultiSelectOption, CliMultiSelectOptions, CliNumberOptions, CliDateOptions, CliFilePickerOptions, CliFileResult, ICliProcessRegisterOptions, ICliProcessEntry, ICliDragDropService, CliHttpRequestOptions, CliNotification, ICliPermissionRegistry, CliPermissionDefinition, CliBranding, CliState, CliEngineSnapshot, CliEvent, CliEventType, CliEventMap, CliEmitOptions, CustomEventType, CliEventHandler, CliServerConfig, ICliServerAuthService, CliServerCommandDescriptor, CliServerCapabilities, CliServerResponse, CliServerOutput, CliPanelPosition, CliPanelConfig, CliPanelHideAlignment, ICliPanelRef, CliPanelThemeInput, CliPanelState } from '@qodalis/cli-core';
2
2
  export { ICliUserSessionService_TOKEN, ICliUsersStoreService_TOKEN } from '@qodalis/cli-core';
3
3
  import { ITheme, Terminal, ITerminalAddon, ITerminalOptions, ITerminalInitOnlyOptions } from '@xterm/xterm';
4
4
  import * as rxjs from 'rxjs';
@@ -165,7 +165,7 @@ declare const CliKeyValueStore_TOKEN: any;
165
165
  */
166
166
  declare const SyntaxHighlighterRegistry_TOKEN: any;
167
167
 
168
- declare const LIBRARY_VERSION = "2.1.1";
168
+ declare const LIBRARY_VERSION = "2.2.0";
169
169
  declare const API_VERSION = 2;
170
170
 
171
171
  declare class CliAliasCommandProcessor implements ICliCommandProcessor {
@@ -2977,6 +2977,11 @@ declare class CliEngine {
2977
2977
  * Focus the terminal and fit to container.
2978
2978
  */
2979
2979
  focus(): void;
2980
+ /**
2981
+ * Restyle the terminal: its colors and the background around it.
2982
+ * The `theme` command can still change it afterwards.
2983
+ */
2984
+ setTheme(theme: ITheme): void;
2980
2985
  /**
2981
2986
  * Get the underlying xterm.js Terminal instance.
2982
2987
  */
@@ -3695,7 +3700,19 @@ interface CliPanelSnapshot {
3695
3700
  /** Status text is shown in the header for top/bottom, compact dots otherwise. */
3696
3701
  showStatusIndicators: boolean;
3697
3702
  panelResizing: boolean;
3703
+ /** CSS custom properties of the theme, for the wrapper and the hide tab. */
3698
3704
  themeStyles: Record<string, string>;
3705
+ /** Whether the panel is light or dark. */
3706
+ scheme: 'light' | 'dark';
3707
+ /** Theme the host set for the terminals; undefined leaves them alone. */
3708
+ terminalTheme?: ITheme;
3709
+ /**
3710
+ * Height of the on-screen keyboard over the page (0 when closed), from the
3711
+ * visual viewport: the panel moves above it.
3712
+ */
3713
+ keyboardInset: number;
3714
+ /** Height of the visible area (visual viewport), 0 when unknown; caps the panel's height. */
3715
+ visibleHeight: number;
3699
3716
  closable: boolean;
3700
3717
  resizable: boolean;
3701
3718
  hideable: boolean;
@@ -3828,11 +3845,21 @@ declare class CliPanelController implements ICliPanelRef<CliEngine> {
3828
3845
  private documentListenersAttached;
3829
3846
  private rootElement;
3830
3847
  private themeObserver?;
3848
+ /** The host's theme (`config.theme`); undefined leaves the terminals' own theme alone. */
3849
+ private themeInput?;
3850
+ private resolvedTheme;
3851
+ private schemeQuery?;
3852
+ private visualViewport?;
3831
3853
  constructor(options?: CliPanelControllerOptions);
3832
3854
  readonly subscribe: (listener: () => void) => (() => void);
3833
3855
  readonly getSnapshot: () => CliPanelSnapshot;
3834
- /** Apply a new panel configuration (chrome buttons, theme sync). */
3856
+ /** Apply a new panel configuration (chrome buttons, theme, theme sync). */
3835
3857
  setOptions(config: CliPanelConfig | undefined): void;
3858
+ /**
3859
+ * Restyle the panel and every terminal in it (see `CliPanelConfig.theme`).
3860
+ * `undefined` returns to the default palette and leaves the terminals' theme alone.
3861
+ */
3862
+ setTheme(theme: CliPanelThemeInput | undefined): void;
3836
3863
  /** Replace the change callbacks (wrappers call this when their props change). */
3837
3864
  setCallbacks(callbacks: CliPanelCallbacks): void;
3838
3865
  /** Update host-controlled values. Unchanged values are ignored. */
@@ -3892,9 +3919,9 @@ declare class CliPanelController implements ICliPanelRef<CliEngine> {
3892
3919
  toggleServersDropdown(anchor?: Element | null): void;
3893
3920
  /** Close the context menu and every dropdown. */
3894
3921
  closeMenus(): void;
3895
- /** Mouse down on the panel's resize bar. */
3922
+ /** Pointer (mouse, touch or pen) down on the panel's resize bar. */
3896
3923
  startPanelResize(clientX: number, clientY: number): void;
3897
- /** Mouse down on the divider before pane `dividerIndex + 1` of a tab. */
3924
+ /** Pointer down on the divider before pane `dividerIndex + 1` of a tab. */
3898
3925
  startPaneResize(tabId: number, dividerIndex: number, clientX: number, containerWidth: number): void;
3899
3926
  private readonly onPanelResizeMove;
3900
3927
  private readonly onPanelResizeEnd;
@@ -3914,6 +3941,17 @@ declare class CliPanelController implements ICliPanelRef<CliEngine> {
3914
3941
  * Engines are registered after they start, so their theme is set.
3915
3942
  */
3916
3943
  private startThemeSync;
3944
+ private applyTheme;
3945
+ /** Follow the system's light/dark setting while the theme is 'auto'. */
3946
+ private watchSystemScheme;
3947
+ private readonly onSystemSchemeChange;
3948
+ /**
3949
+ * Phone browsers open the keyboard over the page and shrink only the visual
3950
+ * viewport; follow it so the panel stays above the keyboard.
3951
+ */
3952
+ private watchVisualViewport;
3953
+ private unwatchVisualViewport;
3954
+ private readonly onVisualViewportChange;
3917
3955
  private stopThemeSync;
3918
3956
  private ensureInitialized;
3919
3957
  private updateCollapsed;
@@ -4017,6 +4055,7 @@ declare function positionDropdownItemClass(s: CliPanelSnapshot, position: CliPan
4017
4055
  /** Size, visibility and theme variables of the panel wrapper. */
4018
4056
  declare function panelWrapperStyle(s: CliPanelSnapshot): Record<string, string>;
4019
4057
  declare function paneStyle(widthPercent: number): Record<string, string>;
4058
+ /** Menus render outside the panel element, so they carry the theme's variables themselves. */
4020
4059
  declare function contextMenuStyle(s: CliPanelSnapshot): Record<string, string>;
4021
4060
  interface PanelStatusIndicator {
4022
4061
  key: 'execution' | 'services' | 'lastCommand' | 'servers' | 'uptime' | 'notification';
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.1.1";
522
+ var LIBRARY_VERSION = "2.2.0";
523
523
  var API_VERSION = 2;
524
524
  var ANONYMOUS = "\0anonymous";
525
525
  function aliasOwner(context2) {
@@ -12601,6 +12601,7 @@ var CliThemeCommandProcessor = class {
12601
12601
  }
12602
12602
  async initialize(context2) {
12603
12603
  this.defaultTheme = context2.terminal.options.theme;
12604
+ if (context2.options?.theme !== void 0) return;
12604
12605
  this.applySavedTheme(context2, false);
12605
12606
  context2.state.select(
12606
12607
  (state) => JSON.stringify([
@@ -22871,6 +22872,9 @@ var CliEngine = class {
22871
22872
  this.terminalOptions = getTerminalOptions(
22872
22873
  this.options?.terminalOptions
22873
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
+ }
22874
22878
  const setup = initializeTerminal(
22875
22879
  this.container,
22876
22880
  this.terminalOptions,
@@ -23123,6 +23127,14 @@ var CliEngine = class {
23123
23127
  this.terminal?.focus();
23124
23128
  });
23125
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
+ }
23126
23138
  /**
23127
23139
  * Get the underlying xterm.js Terminal instance.
23128
23140
  */
@@ -23971,6 +23983,23 @@ function sameJson(a, b) {
23971
23983
  return JSON.stringify(a) === JSON.stringify(b);
23972
23984
  }
23973
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
+ }
23974
24003
  function defaultViewport() {
23975
24004
  if (typeof window === "undefined") return { width: 0, height: 0 };
23976
24005
  return { width: window.innerWidth, height: window.innerHeight };
@@ -23989,6 +24018,9 @@ var CliPanelController = class {
23989
24018
  /* ─── Subscription ──────────────────────────────────────── */
23990
24019
  this.subscribe = (listener) => {
23991
24020
  this.listeners.add(listener);
24021
+ this.watchSystemScheme();
24022
+ this.watchVisualViewport();
24023
+ this.onVisualViewportChange();
23992
24024
  return () => {
23993
24025
  this.listeners.delete(listener);
23994
24026
  };
@@ -24025,11 +24057,22 @@ var CliPanelController = class {
24025
24057
  this.closeMenus();
24026
24058
  this.cancelRename();
24027
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
+ };
24028
24067
  const config = options.config ?? {};
24029
24068
  this.callbacks = options.callbacks ?? {};
24030
24069
  this.controlled = options.controlled ?? {};
24031
24070
  this.viewport = options.viewport ?? defaultViewport;
24032
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();
24033
24076
  this.internal = {
24034
24077
  collapsed: config.isCollapsed ?? true,
24035
24078
  hidden: config.isHidden ?? false,
@@ -24056,7 +24099,11 @@ var CliPanelController = class {
24056
24099
  isHorizontal: false,
24057
24100
  showStatusIndicators: true,
24058
24101
  panelResizing: false,
24059
- themeStyles: {},
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(),
24060
24107
  ...this.configFields(config),
24061
24108
  tabs: [],
24062
24109
  activeTabId: 0,
@@ -24074,8 +24121,9 @@ var CliPanelController = class {
24074
24121
  formattedUptime: formatUptime2(0)
24075
24122
  });
24076
24123
  }
24077
- /** Apply a new panel configuration (chrome buttons, theme sync). */
24124
+ /** Apply a new panel configuration (chrome buttons, theme, theme sync). */
24078
24125
  setOptions(config) {
24126
+ if (themeKey(config?.theme) !== themeKey(this.themeInput)) this.setTheme(config?.theme);
24079
24127
  const fields = this.configFields(config ?? {});
24080
24128
  const s = this.snapshot;
24081
24129
  if (fields.closable === s.closable && fields.resizable === s.resizable && fields.hideable === s.hideable && fields.hideAlignment === s.hideAlignment && fields.syncTheme === s.syncTheme) {
@@ -24085,6 +24133,15 @@ var CliPanelController = class {
24085
24133
  if (fields.syncTheme) this.startThemeSync();
24086
24134
  else this.stopThemeSync();
24087
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
+ }
24088
24145
  /** Replace the change callbacks (wrappers call this when their props change). */
24089
24146
  setCallbacks(callbacks) {
24090
24147
  this.callbacks = callbacks;
@@ -24110,6 +24167,9 @@ var CliPanelController = class {
24110
24167
  destroy() {
24111
24168
  this.tracker.destroy();
24112
24169
  this.stopThemeSync();
24170
+ this.schemeQuery?.removeEventListener("change", this.onSystemSchemeChange);
24171
+ this.schemeQuery = void 0;
24172
+ this.unwatchVisualViewport();
24113
24173
  this.endPanelResize();
24114
24174
  this.endPaneResize();
24115
24175
  this.detachDocumentListeners();
@@ -24327,6 +24387,7 @@ var CliPanelController = class {
24327
24387
  if (!this.findTab(tabId)) return;
24328
24388
  this.engines.set(paneId, engine);
24329
24389
  this.tracker.registerEngine(tabId, paneId, engine);
24390
+ if (this.snapshot.terminalTheme) engine.setTheme(this.snapshot.terminalTheme);
24330
24391
  if (this.snapshot.syncTheme) this.startThemeSync();
24331
24392
  }
24332
24393
  getEngine(paneId) {
@@ -24404,7 +24465,7 @@ var CliPanelController = class {
24404
24465
  });
24405
24466
  }
24406
24467
  /* ─── Drag resizing ─────────────────────────────────────── */
24407
- /** Mouse down on the panel's resize bar. */
24468
+ /** Pointer (mouse, touch or pen) down on the panel's resize bar. */
24408
24469
  startPanelResize(clientX, clientY) {
24409
24470
  if (!this.snapshot.resizable || typeof document === "undefined") return;
24410
24471
  if (this.snapshot.collapsed) this.toggle();
@@ -24415,10 +24476,11 @@ var CliPanelController = class {
24415
24476
  startHeight: this.snapshot.height
24416
24477
  };
24417
24478
  this.commit({ panelResizing: true });
24418
- document.addEventListener("mousemove", this.onPanelResizeMove);
24419
- document.addEventListener("mouseup", this.onPanelResizeEnd);
24479
+ document.addEventListener("pointermove", this.onPanelResizeMove);
24480
+ document.addEventListener("pointerup", this.onPanelResizeEnd);
24481
+ document.addEventListener("pointercancel", this.onPanelResizeEnd);
24420
24482
  }
24421
- /** Mouse down on the divider before pane `dividerIndex + 1` of a tab. */
24483
+ /** Pointer down on the divider before pane `dividerIndex + 1` of a tab. */
24422
24484
  startPaneResize(tabId, dividerIndex, clientX, containerWidth) {
24423
24485
  const tab = this.findTab(tabId);
24424
24486
  if (!tab || typeof document === "undefined") return;
@@ -24431,22 +24493,25 @@ var CliPanelController = class {
24431
24493
  };
24432
24494
  this.commit({ paneResizing: true });
24433
24495
  document.body.classList.add(PANE_RESIZING_BODY_CLASS);
24434
- document.addEventListener("mousemove", this.onPaneResizeMove);
24435
- document.addEventListener("mouseup", this.onPaneResizeEnd);
24496
+ document.addEventListener("pointermove", this.onPaneResizeMove);
24497
+ document.addEventListener("pointerup", this.onPaneResizeEnd);
24498
+ document.addEventListener("pointercancel", this.onPaneResizeEnd);
24436
24499
  }
24437
24500
  endPanelResize() {
24438
24501
  if (!this.panelDrag) return;
24439
24502
  this.panelDrag = void 0;
24440
- document.removeEventListener("mousemove", this.onPanelResizeMove);
24441
- document.removeEventListener("mouseup", this.onPanelResizeEnd);
24503
+ document.removeEventListener("pointermove", this.onPanelResizeMove);
24504
+ document.removeEventListener("pointerup", this.onPanelResizeEnd);
24505
+ document.removeEventListener("pointercancel", this.onPanelResizeEnd);
24442
24506
  this.commit({ panelResizing: false });
24443
24507
  }
24444
24508
  endPaneResize() {
24445
24509
  if (!this.paneDrag) return;
24446
24510
  this.paneDrag = void 0;
24447
24511
  document.body.classList.remove(PANE_RESIZING_BODY_CLASS);
24448
- document.removeEventListener("mousemove", this.onPaneResizeMove);
24449
- document.removeEventListener("mouseup", this.onPaneResizeEnd);
24512
+ document.removeEventListener("pointermove", this.onPaneResizeMove);
24513
+ document.removeEventListener("pointerup", this.onPaneResizeEnd);
24514
+ document.removeEventListener("pointercancel", this.onPaneResizeEnd);
24450
24515
  this.commit({ paneResizing: false });
24451
24516
  }
24452
24517
  syncDocumentListeners() {
@@ -24474,7 +24539,7 @@ var CliPanelController = class {
24474
24539
  if (!engine) return;
24475
24540
  const theme = engine.getTerminal().options.theme;
24476
24541
  if (!theme) return;
24477
- const styles = cliCore.derivePanelThemeStyles(theme);
24542
+ const styles = sameTerminalTheme(theme, this.resolvedTheme.terminal) ? this.resolvedTheme.styles : cliCore.derivePanelThemeStyles(theme);
24478
24543
  if (sameRecord(styles, this.snapshot.themeStyles)) return;
24479
24544
  this.commit({ themeStyles: styles });
24480
24545
  }
@@ -24491,6 +24556,44 @@ var CliPanelController = class {
24491
24556
  this.themeObserver = new MutationObserver(() => this.syncThemeFromEngine());
24492
24557
  this.themeObserver.observe(container, { attributes: true, attributeFilter: ["style"] });
24493
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
+ }
24494
24597
  stopThemeSync() {
24495
24598
  this.themeObserver?.disconnect();
24496
24599
  this.themeObserver = void 0;
@@ -24803,6 +24906,8 @@ function positionDropdownItemClass(s, position) {
24803
24906
  }
24804
24907
  function panelWrapperStyle(s) {
24805
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`;
24806
24911
  if (s.hidden) style["display"] = "none";
24807
24912
  return { ...style, ...s.themeStyles };
24808
24913
  }
@@ -24810,7 +24915,7 @@ function paneStyle(widthPercent) {
24810
24915
  return { flex: `${widthPercent} 1 0` };
24811
24916
  }
24812
24917
  function contextMenuStyle(s) {
24813
- 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` };
24814
24919
  }
24815
24920
  function statusIndicators(s) {
24816
24921
  const items = [];
@@ -24927,7 +25032,7 @@ function openStatusDropdown(s) {
24927
25032
  kind: "services",
24928
25033
  header: PANEL_LABELS.servicesHeader,
24929
25034
  emptyText: PANEL_LABELS.servicesEmpty,
24930
- style: s.servicesDropdownStyle,
25035
+ style: { ...s.themeStyles, ...s.servicesDropdownStyle },
24931
25036
  rows: s.global.serviceDetails.map((svc, i) => ({
24932
25037
  key: `${i}-${svc.name}`,
24933
25038
  dotClass: joinClasses("cli-panel-svc-dot", svc.status === "running" ? "svc-running" : "svc-stopped"),
@@ -24943,7 +25048,7 @@ function openStatusDropdown(s) {
24943
25048
  kind: "servers",
24944
25049
  header: PANEL_LABELS.serversHeader,
24945
25050
  emptyText: PANEL_LABELS.serversEmpty,
24946
- style: s.serversDropdownStyle,
25051
+ style: { ...s.themeStyles, ...s.serversDropdownStyle },
24947
25052
  rows: s.global.serverDetails.map((srv, i) => ({
24948
25053
  key: `${i}-${srv.name}`,
24949
25054
  dotClass: joinClasses("cli-panel-svc-dot", srv.connected ? "svc-running" : "svc-stopped"),