x-shell.js 0.1.1 → 1.0.0-rc.1

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.
@@ -37,6 +37,15 @@ let XShellTerminal = class XShellTerminal extends LitElement {
37
37
  this.noHeader = false;
38
38
  this.autoConnect = false;
39
39
  this.autoSpawn = false;
40
+ // Docker container properties
41
+ this.container = '';
42
+ this.containerShell = '';
43
+ this.containerUser = '';
44
+ this.containerCwd = '';
45
+ // UI panel options
46
+ this.showConnectionPanel = false;
47
+ this.showSettings = false;
48
+ this.showStatusBar = false;
40
49
  // Terminal appearance
41
50
  this.fontSize = 14;
42
51
  this.fontFamily = 'Menlo, Monaco, "Courier New", monospace';
@@ -49,6 +58,17 @@ let XShellTerminal = class XShellTerminal extends LitElement {
49
58
  this.loading = false;
50
59
  this.error = null;
51
60
  this.sessionInfo = null;
61
+ // Connection panel state
62
+ this.containers = [];
63
+ this.serverInfo = null;
64
+ this.selectedContainer = '';
65
+ this.selectedShell = '/bin/sh';
66
+ this.connectionMode = 'docker';
67
+ // Settings state
68
+ this.settingsMenuOpen = false;
69
+ // Status bar state
70
+ this.statusMessage = '';
71
+ this.statusType = 'info';
52
72
  // xterm.js module (loaded dynamically)
53
73
  this.xtermModule = null;
54
74
  this.fitAddonModule = null;
@@ -89,6 +109,31 @@ let XShellTerminal = class XShellTerminal extends LitElement {
89
109
  throw new Error('Failed to load xterm.js. Make sure it is available.');
90
110
  }
91
111
  }
112
+ // Inject xterm CSS into shadow DOM (required because CSS doesn't cross shadow boundaries)
113
+ await this.injectXtermCSS();
114
+ }
115
+ /**
116
+ * Inject xterm.js CSS into shadow DOM
117
+ */
118
+ async injectXtermCSS() {
119
+ if (!this.shadowRoot)
120
+ return;
121
+ // Check if already injected
122
+ if (this.shadowRoot.querySelector('#xterm-styles'))
123
+ return;
124
+ try {
125
+ // Fetch xterm CSS from CDN
126
+ const response = await fetch('https://cdn.jsdelivr.net/npm/xterm@5.3.0/css/xterm.css');
127
+ const css = await response.text();
128
+ // Create style element and inject into shadow DOM
129
+ const style = document.createElement('style');
130
+ style.id = 'xterm-styles';
131
+ style.textContent = css;
132
+ this.shadowRoot.prepend(style);
133
+ }
134
+ catch (e) {
135
+ console.warn('[x-shell] Failed to load xterm CSS:', e);
136
+ }
92
137
  }
93
138
  /**
94
139
  * Connect to the terminal server
@@ -119,6 +164,7 @@ let XShellTerminal = class XShellTerminal extends LitElement {
119
164
  });
120
165
  this.client.onError((err) => {
121
166
  this.error = err.message;
167
+ this.setStatus(err.message, 'error');
122
168
  this.dispatchEvent(new CustomEvent('error', { detail: { error: err }, bubbles: true, composed: true }));
123
169
  });
124
170
  this.client.onData((data) => {
@@ -137,8 +183,24 @@ let XShellTerminal = class XShellTerminal extends LitElement {
137
183
  });
138
184
  this.client.onSpawned((info) => {
139
185
  this.sessionInfo = info;
186
+ this.setStatus(`Session started: ${info.container || info.shell}`, 'success');
140
187
  this.dispatchEvent(new CustomEvent('spawned', { detail: { session: info }, bubbles: true, composed: true }));
141
188
  });
189
+ // Server info and container list handlers
190
+ this.client.onServerInfo((info) => {
191
+ this.serverInfo = info;
192
+ if (info.dockerEnabled) {
193
+ this.connectionMode = 'docker';
194
+ this.client?.requestContainerList();
195
+ }
196
+ this.selectedShell = info.defaultShell;
197
+ });
198
+ this.client.onContainerList((containers) => {
199
+ this.containers = containers;
200
+ if (containers.length > 0 && !this.selectedContainer) {
201
+ this.selectedContainer = containers[0].name;
202
+ }
203
+ });
142
204
  await this.client.connect();
143
205
  }
144
206
  catch (err) {
@@ -178,6 +240,11 @@ let XShellTerminal = class XShellTerminal extends LitElement {
178
240
  cols: this.terminal?.cols || this.cols,
179
241
  rows: this.terminal?.rows || this.rows,
180
242
  env: options?.env,
243
+ // Docker container options
244
+ container: options?.container || this.container || undefined,
245
+ containerShell: options?.containerShell || this.containerShell || undefined,
246
+ containerUser: options?.containerUser || this.containerUser || undefined,
247
+ containerCwd: options?.containerCwd || this.containerCwd || undefined,
181
248
  };
182
249
  const info = await this.client.spawn(spawnOptions);
183
250
  this.sessionActive = true;
@@ -186,9 +253,11 @@ let XShellTerminal = class XShellTerminal extends LitElement {
186
253
  if (this.terminal) {
187
254
  this.terminal.focus();
188
255
  }
256
+ return info;
189
257
  }
190
258
  catch (err) {
191
259
  this.error = err instanceof Error ? err.message : 'Failed to spawn session';
260
+ throw err;
192
261
  }
193
262
  finally {
194
263
  this.loading = false;
@@ -251,21 +320,29 @@ let XShellTerminal = class XShellTerminal extends LitElement {
251
320
  * Get terminal theme based on component theme
252
321
  */
253
322
  getTerminalTheme() {
254
- // These will be overridden by CSS variables in the actual implementation
255
- // For now, provide sensible defaults based on theme attribute
256
- if (this.theme === 'light') {
323
+ // Determine effective theme (handle 'auto' by checking system preference)
324
+ let effectiveTheme = this.theme;
325
+ if (this.theme === 'auto') {
326
+ effectiveTheme = window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark';
327
+ }
328
+ if (effectiveTheme === 'light') {
257
329
  return {
258
330
  background: '#ffffff',
259
331
  foreground: '#1f2937',
260
332
  cursor: '#1f2937',
333
+ cursorAccent: '#ffffff',
261
334
  selection: '#b4d5fe',
335
+ selectionForeground: '#1f2937',
262
336
  };
263
337
  }
338
+ // Dark theme
264
339
  return {
265
340
  background: '#1e1e1e',
266
341
  foreground: '#cccccc',
267
342
  cursor: '#ffffff',
343
+ cursorAccent: '#1e1e1e',
268
344
  selection: '#264f78',
345
+ selectionForeground: '#ffffff',
269
346
  };
270
347
  }
271
348
  /**
@@ -328,6 +405,263 @@ let XShellTerminal = class XShellTerminal extends LitElement {
328
405
  }
329
406
  this.fitAddon = null;
330
407
  }
408
+ /**
409
+ * Set status message
410
+ */
411
+ setStatus(message, type = 'info') {
412
+ this.statusMessage = message;
413
+ this.statusType = type;
414
+ // Auto-clear success/info messages after 5 seconds
415
+ if (type !== 'error') {
416
+ setTimeout(() => {
417
+ if (this.statusMessage === message) {
418
+ this.statusMessage = '';
419
+ }
420
+ }, 5000);
421
+ }
422
+ }
423
+ /**
424
+ * Clear status message
425
+ */
426
+ clearStatus() {
427
+ this.statusMessage = '';
428
+ this.statusType = 'info';
429
+ }
430
+ /**
431
+ * Handle theme change
432
+ */
433
+ handleThemeChange(e) {
434
+ const select = e.target;
435
+ this.theme = select.value;
436
+ // Apply theme to xterm.js terminal
437
+ this.applyTerminalTheme();
438
+ this.dispatchEvent(new CustomEvent('theme-change', {
439
+ detail: { theme: this.theme },
440
+ bubbles: true,
441
+ composed: true
442
+ }));
443
+ }
444
+ /**
445
+ * Apply current theme to xterm.js terminal
446
+ */
447
+ applyTerminalTheme() {
448
+ if (!this.terminal)
449
+ return;
450
+ const terminalTheme = this.getTerminalTheme();
451
+ this.terminal.options.theme = terminalTheme;
452
+ }
453
+ /**
454
+ * Apply current font size to xterm.js terminal
455
+ */
456
+ applyTerminalFontSize() {
457
+ if (!this.terminal)
458
+ return;
459
+ this.terminal.options.fontSize = this.fontSize;
460
+ // Re-fit the terminal after font size change
461
+ if (this.fitAddon) {
462
+ this.fitAddon.fit();
463
+ }
464
+ }
465
+ /**
466
+ * Handle connection mode change
467
+ */
468
+ handleModeChange(e) {
469
+ const select = e.target;
470
+ this.connectionMode = select.value;
471
+ if (this.connectionMode === 'docker' && this.client && this.connected) {
472
+ this.client.requestContainerList();
473
+ }
474
+ }
475
+ /**
476
+ * Handle connect from connection panel
477
+ */
478
+ async handlePanelConnect() {
479
+ if (!this.connected) {
480
+ await this.connect();
481
+ }
482
+ if (this.connected) {
483
+ const options = {};
484
+ if (this.connectionMode === 'docker' && this.selectedContainer) {
485
+ options.container = this.selectedContainer;
486
+ options.containerShell = this.selectedShell || '/bin/sh';
487
+ }
488
+ else {
489
+ options.shell = this.selectedShell || undefined;
490
+ }
491
+ await this.spawn(options);
492
+ }
493
+ }
494
+ /**
495
+ * Toggle settings menu
496
+ */
497
+ toggleSettingsMenu() {
498
+ this.settingsMenuOpen = !this.settingsMenuOpen;
499
+ }
500
+ /**
501
+ * Render connection panel
502
+ */
503
+ renderConnectionPanel() {
504
+ if (!this.showConnectionPanel)
505
+ return nothing;
506
+ const runningContainers = this.containers.filter(c => c.state === 'running');
507
+ return html `
508
+ <div class="connection-panel">
509
+ <div class="connection-panel-title">
510
+ <span>Connection</span>
511
+ ${this.serverInfo?.dockerEnabled
512
+ ? html `<span style="font-size: 11px; color: var(--xs-status-connected);">Docker enabled</span>`
513
+ : nothing}
514
+ </div>
515
+ <div class="connection-form">
516
+ <div class="form-group">
517
+ <label>Mode</label>
518
+ <select
519
+ .value=${this.connectionMode}
520
+ @change=${this.handleModeChange}
521
+ ?disabled=${this.sessionActive}
522
+ >
523
+ <option value="local">Local Shell</option>
524
+ ${this.serverInfo?.dockerEnabled
525
+ ? html `<option value="docker">Docker Container</option>`
526
+ : nothing}
527
+ </select>
528
+ </div>
529
+
530
+ ${this.connectionMode === 'docker' ? html `
531
+ <div class="form-group">
532
+ <label>Container</label>
533
+ <select
534
+ .value=${this.selectedContainer}
535
+ @change=${(e) => this.selectedContainer = e.target.value}
536
+ ?disabled=${this.sessionActive}
537
+ >
538
+ ${runningContainers.length === 0
539
+ ? html `<option value="">No containers running</option>`
540
+ : runningContainers.map(c => html `
541
+ <option value=${c.name}>${c.name} (${c.image})</option>
542
+ `)}
543
+ </select>
544
+ </div>
545
+ ` : nothing}
546
+
547
+ <div class="form-group">
548
+ <label>Shell</label>
549
+ <select
550
+ .value=${this.selectedShell}
551
+ @change=${(e) => this.selectedShell = e.target.value}
552
+ ?disabled=${this.sessionActive}
553
+ >
554
+ ${this.serverInfo?.allowedShells.length
555
+ ? this.serverInfo.allowedShells.map(s => html `<option value=${s}>${s}</option>`)
556
+ : html `
557
+ <option value="/bin/bash">/bin/bash</option>
558
+ <option value="/bin/sh">/bin/sh</option>
559
+ <option value="/bin/zsh">/bin/zsh</option>
560
+ `}
561
+ </select>
562
+ </div>
563
+
564
+ <div class="form-group">
565
+ ${!this.connected
566
+ ? html `<button class="btn-primary" @click=${this.handlePanelConnect} ?disabled=${this.loading}>
567
+ ${this.loading ? 'Connecting...' : 'Connect'}
568
+ </button>`
569
+ : !this.sessionActive
570
+ ? html `<button class="btn-primary" @click=${this.handlePanelConnect} ?disabled=${this.loading}>
571
+ ${this.loading ? 'Starting...' : 'Start Session'}
572
+ </button>`
573
+ : html `<button class="btn-danger" @click=${this.kill}>
574
+ Stop Session
575
+ </button>`}
576
+ </div>
577
+ </div>
578
+ </div>
579
+ `;
580
+ }
581
+ /**
582
+ * Render settings dropdown
583
+ */
584
+ renderSettingsDropdown() {
585
+ if (!this.showSettings)
586
+ return nothing;
587
+ return html `
588
+ <div class="settings-dropdown">
589
+ <button @click=${this.toggleSettingsMenu} title="Settings">
590
+ ⚙️
591
+ </button>
592
+ ${this.settingsMenuOpen ? html `
593
+ <div class="settings-menu">
594
+ <div class="settings-menu-item">
595
+ <span>Theme</span>
596
+ <select
597
+ .value=${this.theme}
598
+ @change=${this.handleThemeChange}
599
+ >
600
+ <option value="dark">Dark</option>
601
+ <option value="light">Light</option>
602
+ <option value="auto">Auto</option>
603
+ </select>
604
+ </div>
605
+ <div class="settings-divider"></div>
606
+ <div class="settings-menu-item">
607
+ <span>Font Size</span>
608
+ <select
609
+ .value=${String(this.fontSize)}
610
+ @change=${(e) => {
611
+ this.fontSize = parseInt(e.target.value);
612
+ this.applyTerminalFontSize();
613
+ }}
614
+ >
615
+ <option value="12">12px</option>
616
+ <option value="14">14px</option>
617
+ <option value="16">16px</option>
618
+ <option value="18">18px</option>
619
+ </select>
620
+ </div>
621
+ <div class="settings-divider"></div>
622
+ <div class="settings-menu-item" @click=${this.clear}>
623
+ <span>Clear Terminal</span>
624
+ </div>
625
+ </div>
626
+ ` : nothing}
627
+ </div>
628
+ `;
629
+ }
630
+ /**
631
+ * Render status bar
632
+ */
633
+ renderStatusBar() {
634
+ if (!this.showStatusBar)
635
+ return nothing;
636
+ return html `
637
+ <div class="status-bar">
638
+ <div class="status-bar-left">
639
+ <span class="status-dot ${this.connected ? 'connected' : ''}"></span>
640
+ <span>${this.connected
641
+ ? (this.sessionActive ? 'Session active' : 'Connected')
642
+ : 'Disconnected'}</span>
643
+ ${this.sessionInfo ? html `
644
+ <span style="color: var(--xs-text-muted)">|</span>
645
+ <span>${this.sessionInfo.container || this.sessionInfo.shell}</span>
646
+ <span style="color: var(--xs-text-muted)">${this.sessionInfo.cols}x${this.sessionInfo.rows}</span>
647
+ ` : nothing}
648
+ </div>
649
+ <div class="status-bar-right">
650
+ ${this.statusMessage ? html `
651
+ <span class="${this.statusType === 'error' ? 'status-bar-error' : this.statusType === 'success' ? 'status-bar-success' : ''}">
652
+ ${this.statusType === 'error' ? '⚠️' : this.statusType === 'success' ? '✓' : ''}
653
+ ${this.statusMessage}
654
+ </span>
655
+ <button
656
+ style="background: none; border: none; cursor: pointer; padding: 0; font-size: 10px;"
657
+ @click=${this.clearStatus}
658
+ title="Dismiss"
659
+ >✕</button>
660
+ ` : nothing}
661
+ </div>
662
+ </div>
663
+ `;
664
+ }
331
665
  render() {
332
666
  return html `
333
667
  ${this.noHeader
@@ -338,29 +672,38 @@ let XShellTerminal = class XShellTerminal extends LitElement {
338
672
  <span>Terminal</span>
339
673
  ${this.sessionInfo
340
674
  ? html `<span style="font-weight: normal; font-size: 12px; color: var(--xs-text-muted)">
341
- ${this.sessionInfo.shell}
675
+ ${this.sessionInfo.container
676
+ ? `${this.sessionInfo.container} (${this.sessionInfo.shell})`
677
+ : this.sessionInfo.shell}
342
678
  </span>`
343
679
  : nothing}
344
680
  </div>
345
681
  <div class="header-actions">
346
- ${!this.connected
682
+ ${!this.showConnectionPanel ? html `
683
+ ${!this.connected
347
684
  ? html `<button @click=${this.connect} ?disabled=${this.loading}>
348
- ${this.loading ? 'Connecting...' : 'Connect'}
349
- </button>`
685
+ ${this.loading ? 'Connecting...' : 'Connect'}
686
+ </button>`
350
687
  : !this.sessionActive
351
688
  ? html `<button @click=${() => this.spawn()} ?disabled=${this.loading}>
352
- ${this.loading ? 'Spawning...' : 'Start'}
353
- </button>`
689
+ ${this.loading ? 'Spawning...' : 'Start'}
690
+ </button>`
354
691
  : html `<button @click=${this.kill}>Stop</button>`}
692
+ ` : nothing}
355
693
  <button @click=${this.clear} ?disabled=${!this.sessionActive}>Clear</button>
356
- <div class="status">
357
- <span class="status-dot ${this.connected ? 'connected' : ''}"></span>
358
- <span>${this.connected ? 'Connected' : 'Disconnected'}</span>
359
- </div>
694
+ ${this.renderSettingsDropdown()}
695
+ ${!this.showStatusBar ? html `
696
+ <div class="status">
697
+ <span class="status-dot ${this.connected ? 'connected' : ''}"></span>
698
+ <span>${this.connected ? 'Connected' : 'Disconnected'}</span>
699
+ </div>
700
+ ` : nothing}
360
701
  </div>
361
702
  </div>
362
703
  `}
363
704
 
705
+ ${this.renderConnectionPanel()}
706
+
364
707
  <div class="terminal-container">
365
708
  ${this.loading && !this.terminal
366
709
  ? html `<div class="loading"><span class="loading-spinner">⏳</span> Loading...</div>`
@@ -368,6 +711,8 @@ let XShellTerminal = class XShellTerminal extends LitElement {
368
711
  ? html `<div class="error">❌ ${this.error}</div>`
369
712
  : nothing}
370
713
  </div>
714
+
715
+ ${this.renderStatusBar()}
371
716
  `;
372
717
  }
373
718
  };
@@ -474,6 +819,139 @@ XShellTerminal.styles = [
474
819
  :host([no-header]) .header {
475
820
  display: none;
476
821
  }
822
+
823
+ /* Connection panel */
824
+ .connection-panel {
825
+ padding: 12px;
826
+ background: var(--xs-bg-header);
827
+ border-bottom: 1px solid var(--xs-border);
828
+ }
829
+
830
+ .connection-panel-title {
831
+ font-weight: 600;
832
+ margin-bottom: 12px;
833
+ display: flex;
834
+ align-items: center;
835
+ gap: 8px;
836
+ }
837
+
838
+ .connection-form {
839
+ display: grid;
840
+ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
841
+ gap: 10px;
842
+ align-items: end;
843
+ }
844
+
845
+ .form-group {
846
+ display: flex;
847
+ flex-direction: column;
848
+ gap: 4px;
849
+ }
850
+
851
+ .form-group label {
852
+ font-size: 11px;
853
+ text-transform: uppercase;
854
+ color: var(--xs-text-muted);
855
+ letter-spacing: 0.5px;
856
+ }
857
+
858
+ .form-group select,
859
+ .form-group input {
860
+ padding: 6px 10px;
861
+ border: 1px solid var(--xs-border);
862
+ border-radius: 4px;
863
+ background: var(--xs-bg);
864
+ color: var(--xs-text);
865
+ font-size: 13px;
866
+ }
867
+
868
+ .form-group select:focus,
869
+ .form-group input:focus {
870
+ outline: none;
871
+ border-color: var(--xs-status-connected);
872
+ }
873
+
874
+ /* Settings dropdown */
875
+ .settings-dropdown {
876
+ position: relative;
877
+ }
878
+
879
+ .settings-menu {
880
+ position: absolute;
881
+ top: 100%;
882
+ right: 0;
883
+ margin-top: 4px;
884
+ min-width: 180px;
885
+ background: var(--xs-bg-header);
886
+ border: 1px solid var(--xs-border);
887
+ border-radius: 4px;
888
+ box-shadow: 0 4px 12px rgba(0,0,0,0.3);
889
+ z-index: 100;
890
+ padding: 8px 0;
891
+ }
892
+
893
+ .settings-menu-item {
894
+ display: flex;
895
+ align-items: center;
896
+ justify-content: space-between;
897
+ padding: 8px 12px;
898
+ font-size: 13px;
899
+ cursor: pointer;
900
+ }
901
+
902
+ .settings-menu-item:hover {
903
+ background: var(--xs-btn-hover);
904
+ }
905
+
906
+ .settings-menu-item select {
907
+ padding: 4px 8px;
908
+ border: 1px solid var(--xs-border);
909
+ border-radius: 3px;
910
+ background: var(--xs-bg);
911
+ color: var(--xs-text);
912
+ font-size: 12px;
913
+ }
914
+
915
+ .settings-divider {
916
+ height: 1px;
917
+ background: var(--xs-border);
918
+ margin: 4px 0;
919
+ }
920
+
921
+ /* Status bar */
922
+ .status-bar {
923
+ display: flex;
924
+ align-items: center;
925
+ justify-content: space-between;
926
+ padding: 4px 12px;
927
+ background: var(--xs-bg-header);
928
+ border-top: 1px solid var(--xs-border);
929
+ font-size: 12px;
930
+ color: var(--xs-text-muted);
931
+ }
932
+
933
+ .status-bar-left {
934
+ display: flex;
935
+ align-items: center;
936
+ gap: 12px;
937
+ }
938
+
939
+ .status-bar-right {
940
+ display: flex;
941
+ align-items: center;
942
+ gap: 8px;
943
+ }
944
+
945
+ .status-bar-error {
946
+ color: #ef4444;
947
+ display: flex;
948
+ align-items: center;
949
+ gap: 4px;
950
+ }
951
+
952
+ .status-bar-success {
953
+ color: var(--xs-status-connected);
954
+ }
477
955
  `,
478
956
  ];
479
957
  __decorate([
@@ -503,6 +981,27 @@ __decorate([
503
981
  __decorate([
504
982
  property({ type: Boolean, attribute: 'auto-spawn' })
505
983
  ], XShellTerminal.prototype, "autoSpawn", void 0);
984
+ __decorate([
985
+ property({ type: String })
986
+ ], XShellTerminal.prototype, "container", void 0);
987
+ __decorate([
988
+ property({ type: String, attribute: 'container-shell' })
989
+ ], XShellTerminal.prototype, "containerShell", void 0);
990
+ __decorate([
991
+ property({ type: String, attribute: 'container-user' })
992
+ ], XShellTerminal.prototype, "containerUser", void 0);
993
+ __decorate([
994
+ property({ type: String, attribute: 'container-cwd' })
995
+ ], XShellTerminal.prototype, "containerCwd", void 0);
996
+ __decorate([
997
+ property({ type: Boolean, attribute: 'show-connection-panel' })
998
+ ], XShellTerminal.prototype, "showConnectionPanel", void 0);
999
+ __decorate([
1000
+ property({ type: Boolean, attribute: 'show-settings' })
1001
+ ], XShellTerminal.prototype, "showSettings", void 0);
1002
+ __decorate([
1003
+ property({ type: Boolean, attribute: 'show-status-bar' })
1004
+ ], XShellTerminal.prototype, "showStatusBar", void 0);
506
1005
  __decorate([
507
1006
  property({ type: Number, attribute: 'font-size' })
508
1007
  ], XShellTerminal.prototype, "fontSize", void 0);
@@ -533,6 +1032,30 @@ __decorate([
533
1032
  __decorate([
534
1033
  state()
535
1034
  ], XShellTerminal.prototype, "sessionInfo", void 0);
1035
+ __decorate([
1036
+ state()
1037
+ ], XShellTerminal.prototype, "containers", void 0);
1038
+ __decorate([
1039
+ state()
1040
+ ], XShellTerminal.prototype, "serverInfo", void 0);
1041
+ __decorate([
1042
+ state()
1043
+ ], XShellTerminal.prototype, "selectedContainer", void 0);
1044
+ __decorate([
1045
+ state()
1046
+ ], XShellTerminal.prototype, "selectedShell", void 0);
1047
+ __decorate([
1048
+ state()
1049
+ ], XShellTerminal.prototype, "connectionMode", void 0);
1050
+ __decorate([
1051
+ state()
1052
+ ], XShellTerminal.prototype, "settingsMenuOpen", void 0);
1053
+ __decorate([
1054
+ state()
1055
+ ], XShellTerminal.prototype, "statusMessage", void 0);
1056
+ __decorate([
1057
+ state()
1058
+ ], XShellTerminal.prototype, "statusType", void 0);
536
1059
  XShellTerminal = __decorate([
537
1060
  customElement('x-shell-terminal')
538
1061
  ], XShellTerminal);