@cmusei/console-forge 0.20.5 → 0.21.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.
Files changed (54) hide show
  1. package/fesm2022/cmusei-console-forge.mjs +382 -355
  2. package/fesm2022/cmusei-console-forge.mjs.map +1 -1
  3. package/package.json +5 -5
  4. package/types/cmusei-console-forge.d.ts +343 -0
  5. package/index.d.ts +0 -5
  6. package/lib/components/console/console.component.d.ts +0 -59
  7. package/lib/components/console-status/console-status.component.d.ts +0 -12
  8. package/lib/components/console-tile/console-tile.component.d.ts +0 -20
  9. package/lib/components/console-toolbar/console-toolbar.component.d.ts +0 -53
  10. package/lib/components/console-toolbar-default/console-toolbar-default-button/console-toolbar-default-button.component.d.ts +0 -13
  11. package/lib/components/console-toolbar-default/console-toolbar-default.component.d.ts +0 -43
  12. package/lib/config/console-forge-config.d.ts +0 -28
  13. package/lib/config/provide-console-forge.d.ts +0 -4
  14. package/lib/directives/apply-toolbar-theme.directive.d.ts +0 -8
  15. package/lib/directives/class-on-hover.directive.d.ts +0 -10
  16. package/lib/injection/window.injection-token.d.ts +0 -2
  17. package/lib/models/console-client-type.d.ts +0 -1
  18. package/lib/models/console-component-config.d.ts +0 -30
  19. package/lib/models/console-component-network-config.d.ts +0 -5
  20. package/lib/models/console-connection-options.d.ts +0 -7
  21. package/lib/models/console-connection-status.d.ts +0 -1
  22. package/lib/models/console-credentials.d.ts +0 -4
  23. package/lib/models/console-network-connection-request.d.ts +0 -4
  24. package/lib/models/console-network-disconnection-request.d.ts +0 -7
  25. package/lib/models/console-power-request.d.ts +0 -1
  26. package/lib/models/console-supported-features.d.ts +0 -40
  27. package/lib/models/console-toolbar-component-base.d.ts +0 -5
  28. package/lib/models/console-toolbar-context.d.ts +0 -39
  29. package/lib/models/console-toolbar-position.d.ts +0 -1
  30. package/lib/models/console-toolbar-theme.d.ts +0 -1
  31. package/lib/models/console-user-settings.d.ts +0 -13
  32. package/lib/models/log-level.d.ts +0 -6
  33. package/lib/services/blob-downloader.service.d.ts +0 -7
  34. package/lib/services/browser-notifications/browser-notifications.service.d.ts +0 -10
  35. package/lib/services/browser-notifications/send-browser-notification.d.ts +0 -9
  36. package/lib/services/canvas-recorder/canvas-recorder.service.d.ts +0 -14
  37. package/lib/services/canvas-recorder/canvas-recording-settings.d.ts +0 -9
  38. package/lib/services/canvas-recorder/canvas-recording.d.ts +0 -12
  39. package/lib/services/canvas.service.d.ts +0 -9
  40. package/lib/services/clipboard/clipboard.helpers.d.ts +0 -8
  41. package/lib/services/clipboard/clipboard.service.d.ts +0 -15
  42. package/lib/services/console-clients/console-client-factory.service.d.ts +0 -9
  43. package/lib/services/console-clients/console-client.service.d.ts +0 -24
  44. package/lib/services/console-clients/vmware/vmware-console-client.service.d.ts +0 -41
  45. package/lib/services/console-clients/vnc-console-client/vnc-console-client.service.d.ts +0 -36
  46. package/lib/services/full-screen.service.d.ts +0 -13
  47. package/lib/services/logger.service.d.ts +0 -9
  48. package/lib/services/object.helpers.d.ts +0 -4
  49. package/lib/services/pico-css.service.d.ts +0 -8
  50. package/lib/services/user-settings.service.d.ts +0 -15
  51. package/lib/services/uuid.service.d.ts +0 -6
  52. package/lib/shims/vmware-mks.models.d.ts +0 -34
  53. package/lib/shims/vmware-wmks.shim.d.ts +0 -61
  54. package/public-api.d.ts +0 -20
@@ -1,12 +1,19 @@
1
- import * as i1$1 from '@angular/common';
1
+ import * as i1 from '@angular/common';
2
2
  import { DOCUMENT, CommonModule } from '@angular/common';
3
3
  import * as i0 from '@angular/core';
4
- import { input, inject, ElementRef, HostListener, Directive, Injectable, output, Component, InjectionToken, signal, effect, model, viewChild, ViewEncapsulation, Injector, computed, untracked, makeEnvironmentProviders } from '@angular/core';
5
- import NoVncClient from '@novnc/novnc/core/rfb';
6
- import * as i1 from '@angular/forms';
7
- import { FormsModule } from '@angular/forms';
4
+ import { InjectionToken, inject, Injectable, signal, effect, Injector, input, output, computed, untracked, Component, ElementRef, Directive, ViewEncapsulation, viewChild, HostListener, model, makeEnvironmentProviders } from '@angular/core';
5
+ import NoVncClient from '@novnc/novnc/lib/rfb';
8
6
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
9
7
  import { Subject, debounceTime } from 'rxjs';
8
+ import * as i1$1 from '@angular/forms';
9
+ import { FormsModule } from '@angular/forms';
10
+
11
+ // ===BEGIN LICENSE===
12
+ // Copyright 2025 Carnegie Mellon University. All rights reserved.
13
+ // Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
14
+ // ===END LICENSE===
15
+ class ConsoleForgeConfig {
16
+ }
10
17
 
11
18
  // ===BEGIN LICENSE===
12
19
  // Copyright 2025 Carnegie Mellon University. All rights reserved.
@@ -20,87 +27,6 @@ var LogLevel;
20
27
  LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
21
28
  })(LogLevel || (LogLevel = {}));
22
29
 
23
- // ===BEGIN LICENSE===
24
- // Copyright 2025 Carnegie Mellon University. All rights reserved.
25
- // Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
26
- // ===END LICENSE===
27
- class ClassOnHoverDirective {
28
- applyClasses = input.required();
29
- directiveHost = inject(ElementRef);
30
- handleMouseEnter() {
31
- if (this.directiveHost?.nativeElement) {
32
- this.directiveHost.nativeElement.classList.add(this.applyClasses());
33
- }
34
- }
35
- handleMouseLeave() {
36
- if (this.directiveHost?.nativeElement) {
37
- this.directiveHost.nativeElement.classList.remove(this.applyClasses());
38
- }
39
- }
40
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ClassOnHoverDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
41
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.14", type: ClassOnHoverDirective, isStandalone: true, selector: "[cfClassOnHover]", inputs: { applyClasses: { classPropertyName: "applyClasses", publicName: "applyClasses", isSignal: true, isRequired: true, transformFunction: null } }, host: { listeners: { "mouseenter": "handleMouseEnter()", "mouseleave": "handleMouseLeave()" } }, ngImport: i0 });
42
- }
43
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ClassOnHoverDirective, decorators: [{
44
- type: Directive,
45
- args: [{ selector: '[cfClassOnHover]' }]
46
- }], propDecorators: { handleMouseEnter: [{
47
- type: HostListener,
48
- args: ["mouseenter"]
49
- }], handleMouseLeave: [{
50
- type: HostListener,
51
- args: ["mouseleave"]
52
- }] } });
53
-
54
- class PicoCssService {
55
- sheet;
56
- loading;
57
- loadStyleSheet() {
58
- if (this.sheet)
59
- return Promise.resolve(this.sheet);
60
- if (!this.loading) {
61
- this.loading = fetch('assets/pico.min.css')
62
- .then(r => r.text())
63
- .then(css => {
64
- const sheet = new CSSStyleSheet();
65
- sheet.replaceSync(css);
66
- this.sheet = sheet;
67
- });
68
- }
69
- return this.loading.then(() => this.sheet);
70
- }
71
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: PicoCssService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
72
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: PicoCssService, providedIn: 'root' });
73
- }
74
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: PicoCssService, decorators: [{
75
- type: Injectable,
76
- args: [{ providedIn: 'root' }]
77
- }] });
78
-
79
- // ===BEGIN LICENSE===
80
- // Copyright 2025 Carnegie Mellon University. All rights reserved.
81
- // Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
82
- // ===END LICENSE===
83
- class ConsoleToolbarDefaultButtonComponent {
84
- clicked = output();
85
- disabled = input(false);
86
- label = input();
87
- isOngoing = input(false);
88
- picoCssService = inject(PicoCssService);
89
- hostElement = inject((ElementRef));
90
- async ngAfterViewInit() {
91
- const sheet = await this.picoCssService.loadStyleSheet();
92
- if (this.hostElement.nativeElement.shadowRoot) {
93
- this.hostElement.nativeElement.shadowRoot.adoptedStyleSheets = [sheet];
94
- }
95
- }
96
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleToolbarDefaultButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
97
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: ConsoleToolbarDefaultButtonComponent, isStandalone: true, selector: "cf-console-toolbar-default-button", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, isOngoing: { classPropertyName: "isOngoing", publicName: "isOngoing", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clicked: "clicked" }, ngImport: i0, template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n<div class=\"svg-button\" cfClassOnHover applyClasses=\"hovered\" [ariaDisabled]=\"disabled()\"\n [class.cursor-pointer]=\"!disabled()\" [class.disabled]=\"disabled()\" [class.ongoing]=\"isOngoing()\"\n (click)=\"!disabled() && clicked.emit()\">\n <div class=\"svg-container\">\n <ng-content></ng-content>\n </div>\n\n @if (label()) {\n <div class=\"button-label\">{{ label() }}</div>\n }\n</div>\n", styles: [":host{background-color:transparent;display:block}@keyframes glow-button-color{0%{color:var(--pico-muted-color);fill:var(--pico-muted-color);stroke:var(--pico-muted-color)}35%{color:#ee402e;fill:#ee402e;stroke:#ee402e}65%{color:#ee402e;fill:#ee402e;stroke:#ee402e}to{color:var(--pico-muted-color);fill:var(--pico-muted-color);stroke:var(--pico-muted-color)}}.svg-button{border:none;border-width:0!important;color:var(--pico-color);display:flex;font-weight:400;align-items:center;flex-direction:column;justify-content:center;margin:0}.svg-button:hover:not(.disabled){color:var(--pico-primary);fill:var(--pico-primary);stroke:var(--pico-primary);transition:all .3s ease}.svg-button.ongoing{animation:glow-button-color 2s infinite}.svg-button.disabled{color:var(--pico-muted-color)}.svg-container{height:var(--svg-icon-height);width:var(--svg-icon-width)}.button-label{font-size:.8rem;margin:0;text-align:center}.cursor-pointer{cursor:pointer}::ng-deep svg{height:56px;width:56px;padding:16px}::ng-deep svg,::ng-deep path,::ng-deep rect{fill:var(--pico-color);stroke:var(--pico-color)}::ng-deep svg.disabled,::ng-deep path.disabled,::ng-deep rect.disabled{fill:var(--pico-muted-color);stroke:var(--pico-muted-color)}::ng-deep svg:hover,::ng-deep path:hover,::ng-deep rect:hover{color:var(--pico-color);transition:fill .3s ease}::ng-deep .hovered:not(.disabled) svg,::ng-deep .hovered:not(.disabled) path,::ng-deep .hovered:not(.disabled) rect{fill:var(--pico-primary);stroke:var(--pico-primary);transition:all .3s ease}::ng-deep .ongoing:not(.disabled) svg,::ng-deep .ongoing:not(.disabled) path,::ng-deep .ongoing:not(.disabled) rect,::ng-deep .ongoing:not(.disabled) .svg-button{animation:glow-button-color 2s infinite}\n"], dependencies: [{ kind: "directive", type: ClassOnHoverDirective, selector: "[cfClassOnHover]", inputs: ["applyClasses"] }] });
98
- }
99
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleToolbarDefaultButtonComponent, decorators: [{
100
- type: Component,
101
- args: [{ selector: 'cf-console-toolbar-default-button', imports: [ClassOnHoverDirective], template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n<div class=\"svg-button\" cfClassOnHover applyClasses=\"hovered\" [ariaDisabled]=\"disabled()\"\n [class.cursor-pointer]=\"!disabled()\" [class.disabled]=\"disabled()\" [class.ongoing]=\"isOngoing()\"\n (click)=\"!disabled() && clicked.emit()\">\n <div class=\"svg-container\">\n <ng-content></ng-content>\n </div>\n\n @if (label()) {\n <div class=\"button-label\">{{ label() }}</div>\n }\n</div>\n", styles: [":host{background-color:transparent;display:block}@keyframes glow-button-color{0%{color:var(--pico-muted-color);fill:var(--pico-muted-color);stroke:var(--pico-muted-color)}35%{color:#ee402e;fill:#ee402e;stroke:#ee402e}65%{color:#ee402e;fill:#ee402e;stroke:#ee402e}to{color:var(--pico-muted-color);fill:var(--pico-muted-color);stroke:var(--pico-muted-color)}}.svg-button{border:none;border-width:0!important;color:var(--pico-color);display:flex;font-weight:400;align-items:center;flex-direction:column;justify-content:center;margin:0}.svg-button:hover:not(.disabled){color:var(--pico-primary);fill:var(--pico-primary);stroke:var(--pico-primary);transition:all .3s ease}.svg-button.ongoing{animation:glow-button-color 2s infinite}.svg-button.disabled{color:var(--pico-muted-color)}.svg-container{height:var(--svg-icon-height);width:var(--svg-icon-width)}.button-label{font-size:.8rem;margin:0;text-align:center}.cursor-pointer{cursor:pointer}::ng-deep svg{height:56px;width:56px;padding:16px}::ng-deep svg,::ng-deep path,::ng-deep rect{fill:var(--pico-color);stroke:var(--pico-color)}::ng-deep svg.disabled,::ng-deep path.disabled,::ng-deep rect.disabled{fill:var(--pico-muted-color);stroke:var(--pico-muted-color)}::ng-deep svg:hover,::ng-deep path:hover,::ng-deep rect:hover{color:var(--pico-color);transition:fill .3s ease}::ng-deep .hovered:not(.disabled) svg,::ng-deep .hovered:not(.disabled) path,::ng-deep .hovered:not(.disabled) rect{fill:var(--pico-primary);stroke:var(--pico-primary);transition:all .3s ease}::ng-deep .ongoing:not(.disabled) svg,::ng-deep .ongoing:not(.disabled) path,::ng-deep .ongoing:not(.disabled) rect,::ng-deep .ongoing:not(.disabled) .svg-button{animation:glow-button-color 2s infinite}\n"] }]
102
- }] });
103
-
104
30
  // ===BEGIN LICENSE===
105
31
  // Copyright 2025 Carnegie Mellon University. All rights reserved.
106
32
  // Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
@@ -158,10 +84,10 @@ class LoggerService {
158
84
  return console.log;
159
85
  }
160
86
  }
161
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: LoggerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
162
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: LoggerService, providedIn: 'root' });
87
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: LoggerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
88
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: LoggerService, providedIn: 'root' });
163
89
  }
164
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: LoggerService, decorators: [{
90
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: LoggerService, decorators: [{
165
91
  type: Injectable,
166
92
  args: [{ providedIn: 'root' }]
167
93
  }] });
@@ -181,7 +107,7 @@ class UserSettingsService {
181
107
  dockTo: "left",
182
108
  preferTheme: undefined
183
109
  }
184
- });
110
+ }, ...(ngDevMode ? [{ debugName: "_settings" }] : /* istanbul ignore next */ []));
185
111
  settings = this._settings.asReadonly();
186
112
  logger = inject(LoggerService);
187
113
  settingsKey = "consoleForge:userSettings";
@@ -214,10 +140,10 @@ class UserSettingsService {
214
140
  ...update
215
141
  }));
216
142
  }
217
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UserSettingsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
218
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UserSettingsService, providedIn: 'root' });
143
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: UserSettingsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
144
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: UserSettingsService, providedIn: 'root' });
219
145
  }
220
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UserSettingsService, decorators: [{
146
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: UserSettingsService, decorators: [{
221
147
  type: Injectable,
222
148
  args: [{ providedIn: 'root' }]
223
149
  }], ctorParameters: () => [] });
@@ -255,13 +181,20 @@ class ClipboardService {
255
181
  cfConfig = inject(ConsoleForgeConfig);
256
182
  document = inject(DOCUMENT);
257
183
  userSettings = inject(UserSettingsService);
258
- _localClipboardContentWritten = signal(undefined);
184
+ _localClipboardContentWritten = signal(undefined, ...(ngDevMode ? [{ debugName: "_localClipboardContentWritten" }] : /* istanbul ignore next */ []));
259
185
  localClipboardContentWritten = this._localClipboardContentWritten.asReadonly();
260
186
  copyBlob(blob) {
261
- return this.writeToClipboard(new ClipboardItem({ [blob.type]: blob }));
262
- }
263
- copyText(text) {
264
- return this.writeToClipboard(getClipboardItemFromText(text));
187
+ // We don't have any cases where we autocopy blobs for now, so we just pass false here
188
+ return this.writeToClipboard(new ClipboardItem({ [blob.type]: blob }), false);
189
+ }
190
+ /**
191
+ * Copy text to the local user's clipboard.
192
+ * @param text Copy this text content to the local user's clipboard
193
+ * @param isAutoCopy Express whether this copy operation is something manually initiated by the user, or is an automatic copy triggered by, for example, a console client's clipboard events.
194
+ * @returns
195
+ */
196
+ copyText(text, isAutoCopy) {
197
+ return this.writeToClipboard(getClipboardItemFromText(text), isAutoCopy);
265
198
  }
266
199
  async readText() {
267
200
  const clipboard = this.getClipboard();
@@ -276,204 +209,34 @@ class ClipboardService {
276
209
  }
277
210
  return this.document?.defaultView?.navigator?.clipboard;
278
211
  }
279
- writeToClipboard(item) {
212
+ writeToClipboard(item, isAutoCopy) {
280
213
  const clipboard = this.getClipboard();
281
214
  if (!clipboard) {
282
215
  throw new Error("Can't access the clipboard to write content");
283
216
  }
284
- if (!this.userSettings.settings().console.allowCopyToLocalClipboard) {
217
+ if (isAutoCopy && !this.userSettings.settings().console.allowCopyToLocalClipboard) {
285
218
  throw new Error("User has disabled ConsoleForge's access to their local clipboard.");
286
219
  }
287
220
  clipboard.write([item]);
288
221
  this._localClipboardContentWritten.update(() => item);
289
222
  }
290
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ClipboardService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
291
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ClipboardService, providedIn: 'root' });
223
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ClipboardService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
224
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ClipboardService, providedIn: 'root' });
292
225
  }
293
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ClipboardService, decorators: [{
226
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ClipboardService, decorators: [{
294
227
  type: Injectable,
295
228
  args: [{ providedIn: 'root' }]
296
229
  }] });
297
230
 
298
- class ApplyToolbarThemeDirective {
299
- hostElement = inject((ElementRef));
300
- userSettings = inject(UserSettingsService).settings;
301
- constructor() {
302
- effect(() => {
303
- this.hostElement.nativeElement.setAttribute("data-theme", this.userSettings().toolbar.preferTheme);
304
- });
305
- }
306
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ApplyToolbarThemeDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
307
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.14", type: ApplyToolbarThemeDirective, isStandalone: true, selector: "[cfApplyToolbarTheme]", ngImport: i0 });
308
- }
309
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ApplyToolbarThemeDirective, decorators: [{
310
- type: Directive,
311
- args: [{ selector: '[cfApplyToolbarTheme]' }]
312
- }], ctorParameters: () => [] });
313
-
314
- // ===BEGIN LICENSE===
315
- // Copyright 2025 Carnegie Mellon University. All rights reserved.
316
- // Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
317
- // ===END LICENSE===
318
- class ConsoleToolbarDefaultComponent {
319
- consoleContext = input.required();
320
- // component state
321
- isClipboardDialogOpen = false;
322
- isKeyboardDialogOpen = false;
323
- isNetworkDialogOpen = false;
324
- isPowerDialogOpen = false;
325
- isSettingsDialogOpen = false;
326
- keyboardInputText = model("");
327
- // protected readonly selected = model<string>();
328
- // services and viewkids
329
- cfConfig = inject(ConsoleForgeConfig);
330
- clipboardService = inject(ClipboardService);
331
- clipboardTextInput = viewChild("clipboardText");
332
- picoCssService = inject(PicoCssService);
333
- hostElement = inject((ElementRef));
334
- // trying this out. when the network configuration (which is passed into the library by the end dev)
335
- // changes, we need to update the model that holds the current network, so let's make a computed
336
- // signal that represents that change so we can be sure our effect only happens when we want it to
337
- // private readonly currentNetwork = (() => this.consoleContext()?.networks?.config()?.current || "");
338
- constructor() {
339
- // when the network config is changed, select the current network if exists
340
- // effect(() => {
341
- // this.selectedNetworkForChange.update(() => this.currentNetwork());
342
- // });
343
- }
344
- async ngAfterViewInit() {
345
- // apply pico to this component
346
- const sheet = await this.picoCssService.loadStyleSheet();
347
- if (this.hostElement.nativeElement.shadowRoot) {
348
- this.hostElement.nativeElement.shadowRoot.adoptedStyleSheets = [sheet];
349
- }
350
- }
351
- handleChangeToolbarPosition(position) {
352
- this.consoleContext().userSettings.patch({ toolbar: { dockTo: position } });
353
- }
354
- handleClipboardDialogOpenClose(isOpen) {
355
- this.isClipboardDialogOpen = isOpen;
356
- if (isOpen) {
357
- // Is there a better way to ensure .focus works other than timeouting it?
358
- setTimeout(() => this.clipboardTextInput()?.nativeElement?.focus(), 100);
359
- }
360
- }
361
- handleClipboardCopyLastText(text) {
362
- this.clipboardService.copyText(text);
363
- }
364
- handleNetworkChangeRequested(request) {
365
- if (!request.network) {
366
- this.consoleContext().networks.disconnectRequested({ nic: request.nic });
367
- }
368
- else {
369
- this.consoleContext().networks.connectionRequested(request);
370
- }
371
- this.isNetworkDialogOpen = false;
372
- }
373
- handleNetworkDisconnectAllRequested() {
374
- this.consoleContext().networks.disconnectRequested({});
375
- this.isNetworkDialogOpen = false;
376
- }
377
- handleNetworkDialogOpenClose(isOpen) {
378
- this.isNetworkDialogOpen = isOpen;
379
- }
380
- handleRecordToggle() {
381
- if (this.consoleContext().state.activeConsoleRecording()) {
382
- this.consoleContext().console.recordScreenStop();
383
- }
384
- else {
385
- this.consoleContext().console.recordScreenStart();
386
- }
387
- }
388
- async handleSendClipboardText(event, text) {
389
- event.preventDefault();
390
- if (text) {
391
- await this.consoleContext().clipboard.sendTextToConsoleClipboard(text);
392
- }
393
- this.isClipboardDialogOpen = false;
394
- }
395
- async handlSendKeyboardCtrlAltDel() {
396
- await this.consoleContext().console.sendCtrlAltDel();
397
- this.isKeyboardDialogOpen = false;
398
- }
399
- async handleSendKeyboardInput(event, text) {
400
- // prevent the form submit default
401
- event.preventDefault();
402
- if (text) {
403
- await this.consoleContext().console.sendKeyboardInput(text);
404
- }
405
- this.keyboardInputText.update(() => "");
406
- this.isKeyboardDialogOpen = false;
407
- }
408
- async handleSendPowerRequest(request) {
409
- await this.consoleContext().console.sendPowerRequest(request);
410
- this.isPowerDialogOpen = false;
411
- }
412
- handleSettingsDialogOpenClose(isOpen) {
413
- this.isSettingsDialogOpen = isOpen;
414
- }
415
- handleSettingsAllowLocalClipboardWrite(allow) {
416
- this.consoleContext().userSettings.patch({ console: { allowCopyToLocalClipboard: allow } });
417
- }
418
- handleSettingsAttemptRemoteSessionResize(attempt) {
419
- this.consoleContext().userSettings.patch({ console: { attemptRemoteSessionResize: attempt } });
420
- }
421
- handleSettingsScaleToContainerHostSize(scaleToCanvasHostSize) {
422
- this.consoleContext().userSettings.patch({ console: { scaleToCanvasHostSize } });
423
- }
424
- handleToolbarThemeChange(theme) {
425
- this.consoleContext().userSettings.patch({ toolbar: { preferTheme: theme } });
426
- }
427
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleToolbarDefaultComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
428
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: ConsoleToolbarDefaultComponent, isStandalone: true, selector: "cf-console-toolbar-default", inputs: { consoleContext: { classPropertyName: "consoleContext", publicName: "consoleContext", isSignal: true, isRequired: true, transformFunction: null }, keyboardInputText: { classPropertyName: "keyboardInputText", publicName: "keyboardInputText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { keyboardInputText: "keyboardInputTextChange" }, viewQueries: [{ propertyName: "clipboardTextInput", first: true, predicate: ["clipboardText"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n@if (consoleContext()) {\n<div class=\"toolbar-container\" cfApplyToolbarTheme\n [class.horizontal]=\"consoleContext().userSettings.settings().toolbar.dockTo == 'top' || consoleContext().userSettings.settings().toolbar.dockTo == 'bottom' \">\n <div class=\"button-container\">\n <cf-console-toolbar-default-button label=\"Settings\" (clicked)=\"handleSettingsDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M12.0002 8C9.79111 8 8.00024 9.79086 8.00024 12C8.00024 14.2091 9.79111 16 12.0002 16C14.2094 16 16.0002 14.2091 16.0002 12C16.0002 9.79086 14.2094 8 12.0002 8ZM10.0002 12C10.0002 10.8954 10.8957 10 12.0002 10C13.1048 10 14.0002 10.8954 14.0002 12C14.0002 13.1046 13.1048 14 12.0002 14C10.8957 14 10.0002 13.1046 10.0002 12Z\"\n fill=\"#000000\"></path>\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M11.2867 0.5C9.88583 0.5 8.6461 1.46745 8.37171 2.85605L8.29264 3.25622C8.10489 4.20638 7.06195 4.83059 6.04511 4.48813L5.64825 4.35447C4.32246 3.90796 2.83873 4.42968 2.11836 5.63933L1.40492 6.83735C0.67773 8.05846 0.954349 9.60487 2.03927 10.5142L2.35714 10.7806C3.12939 11.4279 3.12939 12.5721 2.35714 13.2194L2.03927 13.4858C0.954349 14.3951 0.67773 15.9415 1.40492 17.1626L2.11833 18.3606C2.83872 19.5703 4.3225 20.092 5.64831 19.6455L6.04506 19.5118C7.06191 19.1693 8.1049 19.7935 8.29264 20.7437L8.37172 21.1439C8.6461 22.5325 9.88584 23.5 11.2867 23.5H12.7136C14.1146 23.5 15.3543 22.5325 15.6287 21.1438L15.7077 20.7438C15.8954 19.7936 16.9384 19.1693 17.9553 19.5118L18.3521 19.6455C19.6779 20.092 21.1617 19.5703 21.8821 18.3606L22.5955 17.1627C23.3227 15.9416 23.046 14.3951 21.9611 13.4858L21.6432 13.2194C20.8709 12.5722 20.8709 11.4278 21.6432 10.7806L21.9611 10.5142C23.046 9.60489 23.3227 8.05845 22.5955 6.83732L21.8821 5.63932C21.1617 4.42968 19.678 3.90795 18.3522 4.35444L17.9552 4.48814C16.9384 4.83059 15.8954 4.20634 15.7077 3.25617L15.6287 2.85616C15.3543 1.46751 14.1146 0.5 12.7136 0.5H11.2867ZM10.3338 3.24375C10.4149 2.83334 10.7983 2.5 11.2867 2.5H12.7136C13.2021 2.5 13.5855 2.83336 13.6666 3.24378L13.7456 3.64379C14.1791 5.83811 16.4909 7.09167 18.5935 6.38353L18.9905 6.24984C19.4495 6.09527 19.9394 6.28595 20.1637 6.66264L20.8771 7.86064C21.0946 8.22587 21.0208 8.69271 20.6764 8.98135L20.3586 9.24773C18.6325 10.6943 18.6325 13.3057 20.3586 14.7523L20.6764 15.0186C21.0208 15.3073 21.0946 15.7741 20.8771 16.1394L20.1637 17.3373C19.9394 17.714 19.4495 17.9047 18.9905 17.7501L18.5936 17.6164C16.4909 16.9082 14.1791 18.1618 13.7456 20.3562L13.6666 20.7562C13.5855 21.1666 13.2021 21.5 12.7136 21.5H11.2867C10.7983 21.5 10.4149 21.1667 10.3338 20.7562L10.2547 20.356C9.82113 18.1617 7.50931 16.9082 5.40665 17.6165L5.0099 17.7501C4.55092 17.9047 4.06104 17.714 3.83671 17.3373L3.1233 16.1393C2.9058 15.7741 2.97959 15.3073 3.32398 15.0186L3.64185 14.7522C5.36782 13.3056 5.36781 10.6944 3.64185 9.24779L3.32398 8.98137C2.97959 8.69273 2.9058 8.2259 3.1233 7.86067L3.83674 6.66266C4.06106 6.28596 4.55093 6.09528 5.0099 6.24986L5.40676 6.38352C7.50938 7.09166 9.82112 5.83819 10.2547 3.64392L10.3338 3.24375Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if(consoleContext().state.isManualReconnectAvailable())\n {\n <cf-console-toolbar-default-button label=\"Reconnect\"\n (clicked)=\"consoleContext().console.sendReconnectRequest()\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C16.3556 22 20.0584 19.2159 21.4307 15.3332C21.6148 14.8125 21.3418 14.2412 20.8211 14.0572C20.3004 13.8731 19.7291 14.146 19.545 14.6668C18.4463 17.7753 15.4817 20 12 20C7.58172 20 4 16.4183 4 12C4 7.58172 7.58172 4 12 4C13.5516 4 14.8662 4.56117 16.1162 5.4406C16.9569 6.03212 17.7348 6.74106 18.5242 7.5H15.5C14.9477 7.5 14.5 7.94772 14.5 8.5C14.5 9.05228 14.9477 9.5 15.5 9.5H21C21.5523 9.5 22 9.05228 22 8.5V3C22 2.44772 21.5523 2 21 2C20.4477 2 20 2.44772 20 3V6.14371C19.1517 5.32583 18.2456 4.49337 17.267 3.80489C15.7949 2.76916 14.0847 2 12 2Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (!consoleContext().state.isViewOnly() && consoleContext().state.isConnected()) {\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button label=\"Keyboard\" (clicked)=\"isKeyboardDialogOpen = true\">\n <svg fill=\"#000000\" viewBox=\"0 0 1920 1920\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M1807.059 1637.706c0 31.059-25.299 56.47-56.47 56.47H169.411c-31.172 0-56.47-25.411-56.47-56.47v-903.53c0-31.058 25.298-56.47 56.47-56.47h1581.176c31.172 0 56.47 25.412 56.47 56.47v903.53Zm-56.47-1072.941h-729.262c14.908-86.965 65.958-113.506 133.384-147.163 89.336-44.611 200.583-100.291 200.583-304.602h-112.941c0 134.513-57.939 163.426-138.24 203.633-80.301 40.094-177.544 90.24-196.518 248.132H169.412C76.009 564.765 0 640.775 0 734.176v903.53c0 93.402 76.01 169.412 169.412 169.412h1581.176c93.403 0 169.412-76.01 169.412-169.412v-903.53c0-93.402-76.01-169.411-169.412-169.411Zm-564.707 677.647H734.118c-31.172 0-56.47 25.299-56.47 56.47v112.942c0 31.171 25.298 56.47 56.47 56.47h451.764c31.172 0 56.47-25.299 56.47-56.47v-112.942c0-31.171-25.298-56.47-56.47-56.47m338.824 0h-112.941c-31.172 0-56.47 25.299-56.47 56.47v112.942c0 31.171 25.298 56.47 56.47 56.47h112.94c31.173 0 56.471-25.299 56.471-56.47v-112.942c0-31.171-25.298-56.47-56.47-56.47m-1016.47 0H395.293c-31.172 0-56.47 25.299-56.47 56.47v112.942c0 31.171 25.298 56.47 56.47 56.47h112.941c31.172 0 56.47-25.299 56.47-56.47v-112.942c0-31.171-25.298-56.47-56.47-56.47m0-338.824h-112.94c-31.173 0-56.471 25.3-56.471 56.47V1073c0 31.172 25.298 56.47 56.47 56.47h112.941c31.172 0 56.47-25.298 56.47-56.47V960.059c0-31.172-25.298-56.47-56.47-56.47m225.883 225.882h112.94c31.173 0 56.471-25.3 56.471-56.471V960.059c0-31.172-25.298-56.47-56.47-56.47h-112.94c-31.172 0-56.47 25.298-56.47 56.47V1073c0 31.172 25.298 56.47 56.47 56.47m451.764-225.882h-112.94c-31.173 0-56.471 25.3-56.471 56.47V1073c0 31.172 25.298 56.47 56.47 56.47h112.941c31.172 0 56.47-25.298 56.47-56.47V960.059c0-31.172-25.298-56.47-56.47-56.47m338.824 0h-112.941c-31.172 0-56.47 25.298-56.47 56.47V1073c0 31.172 25.298 56.47 56.47 56.47h112.94c31.173 0 56.471-25.298 56.471-56.47V960.059c0-31.172-25.298-56.47-56.47-56.47\"\n fill-rule=\"evenodd\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if(!cfConfig.disabledFeatures.clipboard) {\n <cf-console-toolbar-default-button [disabled]=\"!consoleContext().state.isConnected()\" label=\"Clipboard\"\n (clicked)=\"handleClipboardDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" preserveAspectRatio=\"none\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M19.5 16.5L19.5 4.5L18.75 3.75H9L8.25 4.5L8.25 7.5L5.25 7.5L4.5 8.25V20.25L5.25 21H15L15.75 20.25V17.25H18.75L19.5 16.5ZM15.75 15.75L15.75 8.25L15 7.5L9.75 7.5V5.25L18 5.25V15.75H15.75ZM6 9L14.25 9L14.25 19.5L6 19.5L6 9Z\"\n fill=\"#080341\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (consoleContext().networks.config()?.networks?.length) {\n <cf-console-toolbar-default-button label=\"Networks ({{ consoleContext().networks.config()?.networks?.length }})\"\n (clicked)=\"handleNetworkDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M3 12H21M12 8V12M6.5 12V16M17.5 12V16M10.1 8H13.9C14.4601 8 14.7401 8 14.954 7.89101C15.1422 7.79513 15.2951 7.64215 15.391 7.45399C15.5 7.24008 15.5 6.96005 15.5 6.4V4.6C15.5 4.03995 15.5 3.75992 15.391 3.54601C15.2951 3.35785 15.1422 3.20487 14.954 3.10899C14.7401 3 14.4601 3 13.9 3H10.1C9.53995 3 9.25992 3 9.04601 3.10899C8.85785 3.20487 8.70487 3.35785 8.60899 3.54601C8.5 3.75992 8.5 4.03995 8.5 4.6V6.4C8.5 6.96005 8.5 7.24008 8.60899 7.45399C8.70487 7.64215 8.85785 7.79513 9.04601 7.89101C9.25992 8 9.53995 8 10.1 8ZM15.6 21H19.4C19.9601 21 20.2401 21 20.454 20.891C20.6422 20.7951 20.7951 20.6422 20.891 20.454C21 20.2401 21 19.9601 21 19.4V17.6C21 17.0399 21 16.7599 20.891 16.546C20.7951 16.3578 20.6422 16.2049 20.454 16.109C20.2401 16 19.9601 16 19.4 16H15.6C15.0399 16 14.7599 16 14.546 16.109C14.3578 16.2049 14.2049 16.3578 14.109 16.546C14 16.7599 14 17.0399 14 17.6V19.4C14 19.9601 14 20.2401 14.109 20.454C14.2049 20.6422 14.3578 20.7951 14.546 20.891C14.7599 21 15.0399 21 15.6 21ZM4.6 21H8.4C8.96005 21 9.24008 21 9.45399 20.891C9.64215 20.7951 9.79513 20.6422 9.89101 20.454C10 20.2401 10 19.9601 10 19.4V17.6C10 17.0399 10 16.7599 9.89101 16.546C9.79513 16.3578 9.64215 16.2049 9.45399 16.109C9.24008 16 8.96005 16 8.4 16H4.6C4.03995 16 3.75992 16 3.54601 16.109C3.35785 16.2049 3.20487 16.3578 3.10899 16.546C3 16.7599 3 17.0399 3 17.6V19.4C3 19.9601 3 20.2401 3.10899 20.454C3.20487 20.6422 3.35785 20.7951 3.54601 20.891C3.75992 21 4.03995 21 4.6 21Z\"\n stroke=\"#000000\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (consoleContext().console.supportedFeatures().powerManagement) {\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button label=\"Power\" (clicked)=\"isPowerDialogOpen = true\">\n <svg width=\"800px\" height=\"800px\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M13 3C13 2.44772 12.5523 2 12 2C11.4477 2 11 2.44772 11 3V13C11 13.5523 11.4477 14 12 14C12.5523 14 13 13.5523 13 13V3Z\"\n fill=\"none\" />\n <path\n d=\"M6.2798 6.70707C6.67031 6.31653 6.67028 5.68337 6.27973 5.29286C5.88919 4.90235 5.25603 4.90238 4.86552 5.29293C3.09635 7.06226 2 9.49298 2 12.1764C2 17.6204 6.49591 22 12 22C17.5041 22 22 17.6204 22 12.1764C22 9.49298 20.9036 7.06226 19.1345 5.29293C18.744 4.90238 18.1108 4.90235 17.7203 5.29286C17.3297 5.68337 17.3297 6.31653 17.7202 6.70707C19.1338 8.12083 20 10.0503 20 12.1764C20 16.4787 16.437 20 12 20C7.56296 20 4 16.4787 4 12.1764C4 10.0503 4.86618 8.12083 6.2798 6.70707Z\"\n fill=\"none\" />\n </svg>\n </cf-console-toolbar-default-button> }\n }\n\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button (clicked)=\"consoleContext().console.copyScreenshot()\"\n [disabled]=\"!consoleContext().state.isConnected()\" label=\"Screenshot\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M9.15023 3.01742C9.13605 3.03985 9.12278 3.0676 9.11298 3.09958C9.11044 3.10789 9.10778 3.11617 9.10502 3.12442L8.36963 5.31787C8.23301 5.72537 7.85129 6 7.4215 6H3C2.44772 6 2 6.44772 2 7V20C2 20.5523 2.44771 21 3 21H21C21.5523 21 22 20.5523 22 20V7C22 6.44771 21.5523 6 21 6H16.331C15.9011 6 15.5194 5.72528 15.3828 5.31769L14.6479 3.12423C14.6452 3.11605 14.6425 3.10783 14.64 3.09958C14.6302 3.0676 14.6169 3.03985 14.6027 3.01742C14.5986 3.01089 14.5946 3.00509 14.5908 3H9.16221C9.1584 3.00509 9.15437 3.01089 9.15023 3.01742ZM7.20525 2.49911C7.43535 1.76672 8.10563 1 9.06392 1H14.6891C15.6474 1 16.3177 1.76679 16.5478 2.49922L17.0506 4H21C22.6569 4 24 5.34315 24 7V20C24 21.6569 22.6569 23 21 23H3C1.34315 23 0 21.6569 0 20V7C0 5.34315 1.34315 4 3 4H6.70206L7.20525 2.49911ZM7 13C7 10.2386 9.23858 8 12 8C14.7614 8 17 10.2386 17 13C17 15.7614 14.7614 18 12 18C9.23858 18 7 15.7614 7 13ZM12 10C10.3431 10 9 11.3431 9 13C9 14.6569 10.3431 16 12 16C13.6569 16 15 14.6569 15 13C15 11.3431 13.6569 10 12 10Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if (!cfConfig.disabledFeatures.consoleScreenRecord) {\n <cf-console-toolbar-default-button (clicked)=\"handleRecordToggle()\"\n [disabled]=\"!consoleContext().state.isRecordingAvailable()\"\n [isOngoing]=\"!!consoleContext().state.activeConsoleRecording()\" label=\"Record\">\n @if (!consoleContext().state.activeConsoleRecording()) {\n <svg viewBox=\"0 0 20 20\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\" fill=\"#000000\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <title>record [#979]</title>\n <desc>Created with Sketch.</desc>\n <defs> </defs>\n <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <g id=\"Dribbble-Light-Preview\" transform=\"translate(-100.000000, -3879.000000)\" fill=\"#000000\">\n <g id=\"icons\" transform=\"translate(56.000000, 160.000000)\">\n <path\n d=\"M56,3719 L56,3721 L62,3721 L62,3727 L64,3727 L64,3719 L56,3719 Z M58,3729.151 C58,3726.942 56.209,3725.151 54,3725.151 C51.791,3725.151 50,3726.942 50,3729.151 C50,3731.36 51.791,3733.151 54,3733.151 C56.209,3733.151 58,3731.36 58,3729.151 L58,3729.151 Z M62,3737 L56,3737 L56,3739 L64,3739 L64,3731 L62,3731 L62,3737 Z M46,3731 L44,3731 L44,3739 L52,3739 L52,3737 L46,3737 L46,3731 Z M46,3727 L44,3727 L44,3719 L52,3719 L52,3721 L46,3721 L46,3727 Z\"\n id=\"record-[#979]\"> </path>\n </g>\n </g>\n </g>\n </g>\n </svg>\n } @else {\n <svg viewBox=\"0 -0.5 21 21\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\" fill=\"#000000\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <g id=\"Dribbble-Light-Preview\" transform=\"translate(-59.000000, -440.000000)\" fill=\"#000000\">\n <g id=\"icons\" transform=\"translate(56.000000, 160.000000)\">\n <path\n d=\"M9.3,294 L17.7,294 L17.7,286 L9.3,286 L9.3,294 Z M15.6,280 L15.6,282 L21.9,282 L21.9,288 L24,288 L24,280 L15.6,280 Z M21.9,298 L15.6,298 L15.6,300 L24,300 L24,292 L21.9,292 L21.9,298 Z M5.1,292 L3,292 L3,300 L11.4,300 L11.4,298 L5.1,298 L5.1,292 Z M5.1,288 L3,288 L3,280 L11.4,280 L11.4,282 L5.1,282 L5.1,288 Z\"\n id=\"stop-[#1470]\"> </path>\n </g>\n </g>\n </g>\n </g>\n </svg>\n }\n </cf-console-toolbar-default-button>\n }\n\n <cf-console-toolbar-default-button (clicked)=\"consoleContext().console.toggleFullscreen()\" label=\"Fullscreen\">\n @if (consoleContext().state.isFullscreenAvailable()) {\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M4 2C2.89543 2 2 2.89543 2 4V8C2 8.55228 2.44772 9 3 9C3.55228 9 4 8.55228 4 8V4H8C8.55228 4 9 3.55228 9 3C9 2.44772 8.55228 2 8 2H4Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M20 2C21.1046 2 22 2.89543 22 4V8C22 8.55228 21.5523 9 21 9C20.4477 9 20 8.55228 20 8V4H16C15.4477 4 15 3.55228 15 3C15 2.44772 15.4477 2 16 2H20Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M20 22C21.1046 22 22 21.1046 22 20V16C22 15.4477 21.5523 15 21 15C20.4477 15 20 15.4477 20 16V20H16C15.4477 20 15 20.4477 15 21C15 21.5523 15.4477 22 16 22H20Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M2 20C2 21.1046 2.89543 22 4 22H8C8.55228 22 9 21.5523 9 21C9 20.4477 8.55228 20 8 20H4V16C4 15.4477 3.55228 15 3 15C2.44772 15 2 15.4477 2 16V20Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n } @else {\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M7 9C8.10457 9 9 8.10457 9 7V3C9 2.44772 8.55228 2 8 2C7.44772 2 7 2.44772 7 3V7H3C2.44772 7 2 7.44772 2 8C2 8.55228 2.44772 9 3 9H7Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M17 9C15.8954 9 15 8.10457 15 7V3C15 2.44772 15.4477 2 16 2C16.5523 2 17 2.44772 17 3V7H21C21.5523 7 22 7.44772 22 8C22 8.55228 21.5523 9 21 9H17Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M17 15C15.8954 15 15 15.8954 15 17V21C15 21.5523 15.4477 22 16 22C16.5523 22 17 21.5523 17 21V17H21C21.5523 17 22 16.5523 22 16C22 15.4477 21.5523 15 21 15H17Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M9 17C9 15.8954 8.10457 15 7 15H3C2.44772 15 2 15.4477 2 16C2 16.5523 2.44772 17 3 17H7V21C7 21.5523 7.44772 22 8 22C8.55228 22 9 21.5523 9 21V17Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n }\n </cf-console-toolbar-default-button>\n </div>\n\n <dialog [open]=\"isClipboardDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleClipboardDialogOpenClose(false)\"></button>\n <p>\n <strong>Clipboard</strong>\n </p>\n </header>\n\n @if (consoleContext().console.supportedFeatures().clipboardRemoteWrite) {\n <div class=\"dialog-section\">\n <h2>Send Text to Console Clipboard</h2>\n <form (submit)=\"handleSendClipboardText($event, clipboardText.value)\">\n <fieldset role=\"group\">\n <input type=\"text\" class=\"clipboard-text\" aria-label=\"Clipboard text\"\n placeholder=\"Enter text to send to the console's clipboard\" #clipboardText autofocus>\n <button type=\"submit\"\n [disabled]=\"!clipboardText.value || !consoleContext().state.isConnected\">Send</button>\n </fieldset>\n </form>\n </div>\n }\n\n @if(!consoleContext().userSettings.settings().console.allowCopyToLocalClipboard ||\n !consoleContext().console.supportedFeatures().clipboardAutomaticLocalCopy) {\n <div class=\"dialog-section\">\n <h2>Console Clipboard Content</h2>\n <form (submit)=\"handleClipboardCopyLastText(consoleLastClipboardText.value)\">\n <fieldset role=\"group\">\n <input type=\"text\" class=\"clipboard-text\" aria-label=\"Clipboard text\" disabled\n [value]=\"consoleContext().clipboard.consoleClipboardText()\"\n placeholder=\"The console's clipboard content will appear here\" #consoleLastClipboardText>\n <button type=\"submit\" [disabled]=\"!consoleLastClipboardText.value\">Copy</button>\n </fieldset>\n </form>\n </div>\n }\n </article>\n </dialog>\n\n <dialog [open]=\"isKeyboardDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"isKeyboardDialogOpen = false\"></button>\n <p>\n <strong>Send Keystrokes</strong>\n </p>\n </header>\n\n <div class=\"dialog-section\">\n <h2>Send Keystrokes to Console</h2>\n <form (submit)=\"handleSendKeyboardInput($event, keyboardInputText())\">\n <fieldset role=\"group\">\n <input type=\"text\" name=\"keyboardInputText\" class=\"clipboard-text\" aria-label=\"Clipboard text\"\n placeholder=\"Enter text to send as keyboard input to the console\" autofocus\n [(ngModel)]=\"keyboardInputText\">\n <button type=\"submit\"\n [disabled]=\"!keyboardInputText() || !consoleContext().state.isConnected\">Send</button>\n </fieldset>\n </form>\n </div>\n\n <div class=\"dialog-section\">\n <h2>Special Key Combinations</h2>\n\n <div class=\"dialog-button-group\">\n <button type=\"button\" aria-label=\"Send Ctrl+Alt+Delete\" (click)=\"handlSendKeyboardCtrlAltDel()\">\n Ctrl + Alt + Delete\n </button>\n </div>\n </div>\n </article>\n </dialog>\n\n <dialog [open]=\"isNetworkDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleNetworkDialogOpenClose(false)\"></button>\n <p>\n <strong>Networks</strong>\n </p>\n </header>\n\n <form>\n @for (nic of consoleContext().networks.config()?.nics; track nic)\n {\n <label for=\"nic-{{ nic }}-select\">{{ nic }}</label>\n <fieldset role=\"group\">\n <select #availableNetworksSelect name=\"nic-{{ nic }}-select\"\n aria-label=\"Select a network to connect to\">\n\n @if (!cfConfig.disabledFeatures.networkDisconnection)\n {\n <option [selected]=\"!consoleContext().networks.config()?.currentConnections?.[nic]\" value=\"\">\n [Disconnected]\n </option>\n }\n\n @for(network of consoleContext().networks.config()?.networks; track network) {\n <option [value]=\"network\"\n [selected]=\"consoleContext().networks.config()?.currentConnections?.[nic] === network\">\n {{ network }}\n </option>\n }\n </select>\n\n <button type=\"button\"\n (click)=\"handleNetworkChangeRequested({ network: availableNetworksSelect.value, nic: nic })\">\n {{ availableNetworksSelect.value ? \"Connect\" : \"Disconnect\" }}\n </button>\n </fieldset>\n }\n\n @if (!cfConfig.disabledFeatures.networkDisconnection)\n {\n <hr />\n <div class=\"dialog-button-group\">\n <button class=\"secondary\" type=\"button\" (click)=\"handleNetworkDisconnectAllRequested()\">\n Disconnect All Network Interfaces\n </button>\n </div>\n }\n </form>\n </article>\n </dialog>\n\n <dialog [open]=\"isPowerDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"isPowerDialogOpen = false\"></button>\n <p>\n <strong>Power</strong>\n </p>\n </header>\n\n <div class=\"dialog-button-group\">\n <button type=\"button\" (click)=\"handleSendPowerRequest('reboot')\">Request Reboot</button>\n <button type=\"button\" (click)=\"handleSendPowerRequest('shutdown')\">Request Shutdown</button>\n <hr />\n <button class=\"secondary\" type=\"button\" (click)=\"handleSendPowerRequest('rebootHard')\">\n Request Hard Reboot\n </button>\n </div>\n </article>\n </dialog>\n\n <dialog [open]=\"isSettingsDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleSettingsDialogOpenClose(false)\"></button>\n <p>\n <strong>Settings</strong>\n </p>\n </header>\n\n <div class=\"settings-form\">\n <h4>Behavior</h4>\n <fieldset>\n <label>\n <input #inputAllowLocalClipboardWrite type=\"checkbox\" name=\"allowLocalClipboardWrite\"\n [checked]=\"consoleContext().userSettings.settings().console.allowCopyToLocalClipboard\"\n (change)=\"handleSettingsAllowLocalClipboardWrite(inputAllowLocalClipboardWrite.checked)\" />\n Allow the remote machine to copy text to my local clipboard\n </label>\n <label>\n <input #inputAttemptRemoteSessionResize type=\"checkbox\" name=\"attemptRemoteSessionResize\"\n [checked]=\"consoleContext().userSettings.settings().console.attemptRemoteSessionResize\"\n (change)=\"handleSettingsAttemptRemoteSessionResize(inputAttemptRemoteSessionResize.checked)\" />\n Attempt to resize the remote session to match local resolution\n </label>\n <label>\n <input #inputScaleToContainerSize type=\"checkbox\" name=\"scaleToContainerSize\"\n [checked]=\"consoleContext().userSettings.settings().console.scaleToCanvasHostSize\"\n (change)=\"handleSettingsScaleToContainerHostSize(inputScaleToContainerSize.checked)\" />\n Scale to maximum available size\n </label>\n </fieldset>\n\n <div class=\"settings-toolbar-dock\">\n <h4>Toolbar Position</h4>\n <div role=\"group\">\n <button (click)=\"handleChangeToolbarPosition('left')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'left'\">Left</button>\n <button (click)=\"handleChangeToolbarPosition('right')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'right'\">Right</button>\n <button (click)=\"handleChangeToolbarPosition('top')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'top'\">Top</button>\n <button (click)=\"handleChangeToolbarPosition('bottom')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'bottom'\">Bottom</button>\n </div>\n </div>\n\n <div class=\"settings-theme\">\n <h4>Theme</h4>\n <div role=\"group\">\n <button (click)=\"handleToolbarThemeChange('light')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.preferTheme === 'light'\">Light</button>\n <button (click)=\"handleToolbarThemeChange('dark')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.preferTheme === 'dark'\">Dark</button>\n <button (click)=\"handleToolbarThemeChange(undefined)\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.preferTheme === undefined\">\n My Default\n </button>\n </div>\n </div>\n </div>\n </article>\n </dialog>\n</div>\n}\n", styles: [":host{display:block;height:100%;width:100%;max-width:100%}fieldset legend{font-weight:700}.toolbar-container{background-color:var(--pico-background-color);padding:4px;height:100%;display:flex;align-items:center;justify-content:center}.toolbar-container .button-container{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px}.toolbar-container .buttons-divider{border-top:1px solid var(--pico-color);margin:.25rem 0;width:100%}.toolbar-container.horizontal{width:100%}.toolbar-container.horizontal .button-container{flex-direction:row}.toolbar-container.horizontal .buttons-divider{align-self:stretch;border-left:1px solid var(--pico-color);height:auto;margin:0 1rem;width:1px}.toolbar-position-buttons{display:flex;gap:4px}.toolbar-position-buttons button{flex-grow:1}.settings-toolbar-dock{margin-top:1rem}dialog h2{font-size:1.1rem;font-weight:700}dialog .dialog-section:not(:last-of-type){margin-bottom:1.5rem}dialog .dialog-button-group button{display:block;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: ApplyToolbarThemeDirective, selector: "[cfApplyToolbarTheme]" }, { kind: "component", type: ConsoleToolbarDefaultButtonComponent, selector: "cf-console-toolbar-default-button", inputs: ["disabled", "label", "isOngoing"], outputs: ["clicked"] }], encapsulation: i0.ViewEncapsulation.ShadowDom });
429
- }
430
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleToolbarDefaultComponent, decorators: [{
431
- type: Component,
432
- args: [{ selector: 'cf-console-toolbar-default', imports: [
433
- FormsModule,
434
- ApplyToolbarThemeDirective,
435
- ConsoleToolbarDefaultButtonComponent
436
- ], standalone: true, encapsulation: ViewEncapsulation.ShadowDom, template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n@if (consoleContext()) {\n<div class=\"toolbar-container\" cfApplyToolbarTheme\n [class.horizontal]=\"consoleContext().userSettings.settings().toolbar.dockTo == 'top' || consoleContext().userSettings.settings().toolbar.dockTo == 'bottom' \">\n <div class=\"button-container\">\n <cf-console-toolbar-default-button label=\"Settings\" (clicked)=\"handleSettingsDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M12.0002 8C9.79111 8 8.00024 9.79086 8.00024 12C8.00024 14.2091 9.79111 16 12.0002 16C14.2094 16 16.0002 14.2091 16.0002 12C16.0002 9.79086 14.2094 8 12.0002 8ZM10.0002 12C10.0002 10.8954 10.8957 10 12.0002 10C13.1048 10 14.0002 10.8954 14.0002 12C14.0002 13.1046 13.1048 14 12.0002 14C10.8957 14 10.0002 13.1046 10.0002 12Z\"\n fill=\"#000000\"></path>\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M11.2867 0.5C9.88583 0.5 8.6461 1.46745 8.37171 2.85605L8.29264 3.25622C8.10489 4.20638 7.06195 4.83059 6.04511 4.48813L5.64825 4.35447C4.32246 3.90796 2.83873 4.42968 2.11836 5.63933L1.40492 6.83735C0.67773 8.05846 0.954349 9.60487 2.03927 10.5142L2.35714 10.7806C3.12939 11.4279 3.12939 12.5721 2.35714 13.2194L2.03927 13.4858C0.954349 14.3951 0.67773 15.9415 1.40492 17.1626L2.11833 18.3606C2.83872 19.5703 4.3225 20.092 5.64831 19.6455L6.04506 19.5118C7.06191 19.1693 8.1049 19.7935 8.29264 20.7437L8.37172 21.1439C8.6461 22.5325 9.88584 23.5 11.2867 23.5H12.7136C14.1146 23.5 15.3543 22.5325 15.6287 21.1438L15.7077 20.7438C15.8954 19.7936 16.9384 19.1693 17.9553 19.5118L18.3521 19.6455C19.6779 20.092 21.1617 19.5703 21.8821 18.3606L22.5955 17.1627C23.3227 15.9416 23.046 14.3951 21.9611 13.4858L21.6432 13.2194C20.8709 12.5722 20.8709 11.4278 21.6432 10.7806L21.9611 10.5142C23.046 9.60489 23.3227 8.05845 22.5955 6.83732L21.8821 5.63932C21.1617 4.42968 19.678 3.90795 18.3522 4.35444L17.9552 4.48814C16.9384 4.83059 15.8954 4.20634 15.7077 3.25617L15.6287 2.85616C15.3543 1.46751 14.1146 0.5 12.7136 0.5H11.2867ZM10.3338 3.24375C10.4149 2.83334 10.7983 2.5 11.2867 2.5H12.7136C13.2021 2.5 13.5855 2.83336 13.6666 3.24378L13.7456 3.64379C14.1791 5.83811 16.4909 7.09167 18.5935 6.38353L18.9905 6.24984C19.4495 6.09527 19.9394 6.28595 20.1637 6.66264L20.8771 7.86064C21.0946 8.22587 21.0208 8.69271 20.6764 8.98135L20.3586 9.24773C18.6325 10.6943 18.6325 13.3057 20.3586 14.7523L20.6764 15.0186C21.0208 15.3073 21.0946 15.7741 20.8771 16.1394L20.1637 17.3373C19.9394 17.714 19.4495 17.9047 18.9905 17.7501L18.5936 17.6164C16.4909 16.9082 14.1791 18.1618 13.7456 20.3562L13.6666 20.7562C13.5855 21.1666 13.2021 21.5 12.7136 21.5H11.2867C10.7983 21.5 10.4149 21.1667 10.3338 20.7562L10.2547 20.356C9.82113 18.1617 7.50931 16.9082 5.40665 17.6165L5.0099 17.7501C4.55092 17.9047 4.06104 17.714 3.83671 17.3373L3.1233 16.1393C2.9058 15.7741 2.97959 15.3073 3.32398 15.0186L3.64185 14.7522C5.36782 13.3056 5.36781 10.6944 3.64185 9.24779L3.32398 8.98137C2.97959 8.69273 2.9058 8.2259 3.1233 7.86067L3.83674 6.66266C4.06106 6.28596 4.55093 6.09528 5.0099 6.24986L5.40676 6.38352C7.50938 7.09166 9.82112 5.83819 10.2547 3.64392L10.3338 3.24375Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if(consoleContext().state.isManualReconnectAvailable())\n {\n <cf-console-toolbar-default-button label=\"Reconnect\"\n (clicked)=\"consoleContext().console.sendReconnectRequest()\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C16.3556 22 20.0584 19.2159 21.4307 15.3332C21.6148 14.8125 21.3418 14.2412 20.8211 14.0572C20.3004 13.8731 19.7291 14.146 19.545 14.6668C18.4463 17.7753 15.4817 20 12 20C7.58172 20 4 16.4183 4 12C4 7.58172 7.58172 4 12 4C13.5516 4 14.8662 4.56117 16.1162 5.4406C16.9569 6.03212 17.7348 6.74106 18.5242 7.5H15.5C14.9477 7.5 14.5 7.94772 14.5 8.5C14.5 9.05228 14.9477 9.5 15.5 9.5H21C21.5523 9.5 22 9.05228 22 8.5V3C22 2.44772 21.5523 2 21 2C20.4477 2 20 2.44772 20 3V6.14371C19.1517 5.32583 18.2456 4.49337 17.267 3.80489C15.7949 2.76916 14.0847 2 12 2Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (!consoleContext().state.isViewOnly() && consoleContext().state.isConnected()) {\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button label=\"Keyboard\" (clicked)=\"isKeyboardDialogOpen = true\">\n <svg fill=\"#000000\" viewBox=\"0 0 1920 1920\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M1807.059 1637.706c0 31.059-25.299 56.47-56.47 56.47H169.411c-31.172 0-56.47-25.411-56.47-56.47v-903.53c0-31.058 25.298-56.47 56.47-56.47h1581.176c31.172 0 56.47 25.412 56.47 56.47v903.53Zm-56.47-1072.941h-729.262c14.908-86.965 65.958-113.506 133.384-147.163 89.336-44.611 200.583-100.291 200.583-304.602h-112.941c0 134.513-57.939 163.426-138.24 203.633-80.301 40.094-177.544 90.24-196.518 248.132H169.412C76.009 564.765 0 640.775 0 734.176v903.53c0 93.402 76.01 169.412 169.412 169.412h1581.176c93.403 0 169.412-76.01 169.412-169.412v-903.53c0-93.402-76.01-169.411-169.412-169.411Zm-564.707 677.647H734.118c-31.172 0-56.47 25.299-56.47 56.47v112.942c0 31.171 25.298 56.47 56.47 56.47h451.764c31.172 0 56.47-25.299 56.47-56.47v-112.942c0-31.171-25.298-56.47-56.47-56.47m338.824 0h-112.941c-31.172 0-56.47 25.299-56.47 56.47v112.942c0 31.171 25.298 56.47 56.47 56.47h112.94c31.173 0 56.471-25.299 56.471-56.47v-112.942c0-31.171-25.298-56.47-56.47-56.47m-1016.47 0H395.293c-31.172 0-56.47 25.299-56.47 56.47v112.942c0 31.171 25.298 56.47 56.47 56.47h112.941c31.172 0 56.47-25.299 56.47-56.47v-112.942c0-31.171-25.298-56.47-56.47-56.47m0-338.824h-112.94c-31.173 0-56.471 25.3-56.471 56.47V1073c0 31.172 25.298 56.47 56.47 56.47h112.941c31.172 0 56.47-25.298 56.47-56.47V960.059c0-31.172-25.298-56.47-56.47-56.47m225.883 225.882h112.94c31.173 0 56.471-25.3 56.471-56.471V960.059c0-31.172-25.298-56.47-56.47-56.47h-112.94c-31.172 0-56.47 25.298-56.47 56.47V1073c0 31.172 25.298 56.47 56.47 56.47m451.764-225.882h-112.94c-31.173 0-56.471 25.3-56.471 56.47V1073c0 31.172 25.298 56.47 56.47 56.47h112.941c31.172 0 56.47-25.298 56.47-56.47V960.059c0-31.172-25.298-56.47-56.47-56.47m338.824 0h-112.941c-31.172 0-56.47 25.298-56.47 56.47V1073c0 31.172 25.298 56.47 56.47 56.47h112.94c31.173 0 56.471-25.298 56.471-56.47V960.059c0-31.172-25.298-56.47-56.47-56.47\"\n fill-rule=\"evenodd\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if(!cfConfig.disabledFeatures.clipboard) {\n <cf-console-toolbar-default-button [disabled]=\"!consoleContext().state.isConnected()\" label=\"Clipboard\"\n (clicked)=\"handleClipboardDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" preserveAspectRatio=\"none\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M19.5 16.5L19.5 4.5L18.75 3.75H9L8.25 4.5L8.25 7.5L5.25 7.5L4.5 8.25V20.25L5.25 21H15L15.75 20.25V17.25H18.75L19.5 16.5ZM15.75 15.75L15.75 8.25L15 7.5L9.75 7.5V5.25L18 5.25V15.75H15.75ZM6 9L14.25 9L14.25 19.5L6 19.5L6 9Z\"\n fill=\"#080341\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (consoleContext().networks.config()?.networks?.length) {\n <cf-console-toolbar-default-button label=\"Networks ({{ consoleContext().networks.config()?.networks?.length }})\"\n (clicked)=\"handleNetworkDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M3 12H21M12 8V12M6.5 12V16M17.5 12V16M10.1 8H13.9C14.4601 8 14.7401 8 14.954 7.89101C15.1422 7.79513 15.2951 7.64215 15.391 7.45399C15.5 7.24008 15.5 6.96005 15.5 6.4V4.6C15.5 4.03995 15.5 3.75992 15.391 3.54601C15.2951 3.35785 15.1422 3.20487 14.954 3.10899C14.7401 3 14.4601 3 13.9 3H10.1C9.53995 3 9.25992 3 9.04601 3.10899C8.85785 3.20487 8.70487 3.35785 8.60899 3.54601C8.5 3.75992 8.5 4.03995 8.5 4.6V6.4C8.5 6.96005 8.5 7.24008 8.60899 7.45399C8.70487 7.64215 8.85785 7.79513 9.04601 7.89101C9.25992 8 9.53995 8 10.1 8ZM15.6 21H19.4C19.9601 21 20.2401 21 20.454 20.891C20.6422 20.7951 20.7951 20.6422 20.891 20.454C21 20.2401 21 19.9601 21 19.4V17.6C21 17.0399 21 16.7599 20.891 16.546C20.7951 16.3578 20.6422 16.2049 20.454 16.109C20.2401 16 19.9601 16 19.4 16H15.6C15.0399 16 14.7599 16 14.546 16.109C14.3578 16.2049 14.2049 16.3578 14.109 16.546C14 16.7599 14 17.0399 14 17.6V19.4C14 19.9601 14 20.2401 14.109 20.454C14.2049 20.6422 14.3578 20.7951 14.546 20.891C14.7599 21 15.0399 21 15.6 21ZM4.6 21H8.4C8.96005 21 9.24008 21 9.45399 20.891C9.64215 20.7951 9.79513 20.6422 9.89101 20.454C10 20.2401 10 19.9601 10 19.4V17.6C10 17.0399 10 16.7599 9.89101 16.546C9.79513 16.3578 9.64215 16.2049 9.45399 16.109C9.24008 16 8.96005 16 8.4 16H4.6C4.03995 16 3.75992 16 3.54601 16.109C3.35785 16.2049 3.20487 16.3578 3.10899 16.546C3 16.7599 3 17.0399 3 17.6V19.4C3 19.9601 3 20.2401 3.10899 20.454C3.20487 20.6422 3.35785 20.7951 3.54601 20.891C3.75992 21 4.03995 21 4.6 21Z\"\n stroke=\"#000000\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (consoleContext().console.supportedFeatures().powerManagement) {\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button label=\"Power\" (clicked)=\"isPowerDialogOpen = true\">\n <svg width=\"800px\" height=\"800px\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M13 3C13 2.44772 12.5523 2 12 2C11.4477 2 11 2.44772 11 3V13C11 13.5523 11.4477 14 12 14C12.5523 14 13 13.5523 13 13V3Z\"\n fill=\"none\" />\n <path\n d=\"M6.2798 6.70707C6.67031 6.31653 6.67028 5.68337 6.27973 5.29286C5.88919 4.90235 5.25603 4.90238 4.86552 5.29293C3.09635 7.06226 2 9.49298 2 12.1764C2 17.6204 6.49591 22 12 22C17.5041 22 22 17.6204 22 12.1764C22 9.49298 20.9036 7.06226 19.1345 5.29293C18.744 4.90238 18.1108 4.90235 17.7203 5.29286C17.3297 5.68337 17.3297 6.31653 17.7202 6.70707C19.1338 8.12083 20 10.0503 20 12.1764C20 16.4787 16.437 20 12 20C7.56296 20 4 16.4787 4 12.1764C4 10.0503 4.86618 8.12083 6.2798 6.70707Z\"\n fill=\"none\" />\n </svg>\n </cf-console-toolbar-default-button> }\n }\n\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button (clicked)=\"consoleContext().console.copyScreenshot()\"\n [disabled]=\"!consoleContext().state.isConnected()\" label=\"Screenshot\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M9.15023 3.01742C9.13605 3.03985 9.12278 3.0676 9.11298 3.09958C9.11044 3.10789 9.10778 3.11617 9.10502 3.12442L8.36963 5.31787C8.23301 5.72537 7.85129 6 7.4215 6H3C2.44772 6 2 6.44772 2 7V20C2 20.5523 2.44771 21 3 21H21C21.5523 21 22 20.5523 22 20V7C22 6.44771 21.5523 6 21 6H16.331C15.9011 6 15.5194 5.72528 15.3828 5.31769L14.6479 3.12423C14.6452 3.11605 14.6425 3.10783 14.64 3.09958C14.6302 3.0676 14.6169 3.03985 14.6027 3.01742C14.5986 3.01089 14.5946 3.00509 14.5908 3H9.16221C9.1584 3.00509 9.15437 3.01089 9.15023 3.01742ZM7.20525 2.49911C7.43535 1.76672 8.10563 1 9.06392 1H14.6891C15.6474 1 16.3177 1.76679 16.5478 2.49922L17.0506 4H21C22.6569 4 24 5.34315 24 7V20C24 21.6569 22.6569 23 21 23H3C1.34315 23 0 21.6569 0 20V7C0 5.34315 1.34315 4 3 4H6.70206L7.20525 2.49911ZM7 13C7 10.2386 9.23858 8 12 8C14.7614 8 17 10.2386 17 13C17 15.7614 14.7614 18 12 18C9.23858 18 7 15.7614 7 13ZM12 10C10.3431 10 9 11.3431 9 13C9 14.6569 10.3431 16 12 16C13.6569 16 15 14.6569 15 13C15 11.3431 13.6569 10 12 10Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if (!cfConfig.disabledFeatures.consoleScreenRecord) {\n <cf-console-toolbar-default-button (clicked)=\"handleRecordToggle()\"\n [disabled]=\"!consoleContext().state.isRecordingAvailable()\"\n [isOngoing]=\"!!consoleContext().state.activeConsoleRecording()\" label=\"Record\">\n @if (!consoleContext().state.activeConsoleRecording()) {\n <svg viewBox=\"0 0 20 20\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\" fill=\"#000000\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <title>record [#979]</title>\n <desc>Created with Sketch.</desc>\n <defs> </defs>\n <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <g id=\"Dribbble-Light-Preview\" transform=\"translate(-100.000000, -3879.000000)\" fill=\"#000000\">\n <g id=\"icons\" transform=\"translate(56.000000, 160.000000)\">\n <path\n d=\"M56,3719 L56,3721 L62,3721 L62,3727 L64,3727 L64,3719 L56,3719 Z M58,3729.151 C58,3726.942 56.209,3725.151 54,3725.151 C51.791,3725.151 50,3726.942 50,3729.151 C50,3731.36 51.791,3733.151 54,3733.151 C56.209,3733.151 58,3731.36 58,3729.151 L58,3729.151 Z M62,3737 L56,3737 L56,3739 L64,3739 L64,3731 L62,3731 L62,3737 Z M46,3731 L44,3731 L44,3739 L52,3739 L52,3737 L46,3737 L46,3731 Z M46,3727 L44,3727 L44,3719 L52,3719 L52,3721 L46,3721 L46,3727 Z\"\n id=\"record-[#979]\"> </path>\n </g>\n </g>\n </g>\n </g>\n </svg>\n } @else {\n <svg viewBox=\"0 -0.5 21 21\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\" fill=\"#000000\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <g id=\"Dribbble-Light-Preview\" transform=\"translate(-59.000000, -440.000000)\" fill=\"#000000\">\n <g id=\"icons\" transform=\"translate(56.000000, 160.000000)\">\n <path\n d=\"M9.3,294 L17.7,294 L17.7,286 L9.3,286 L9.3,294 Z M15.6,280 L15.6,282 L21.9,282 L21.9,288 L24,288 L24,280 L15.6,280 Z M21.9,298 L15.6,298 L15.6,300 L24,300 L24,292 L21.9,292 L21.9,298 Z M5.1,292 L3,292 L3,300 L11.4,300 L11.4,298 L5.1,298 L5.1,292 Z M5.1,288 L3,288 L3,280 L11.4,280 L11.4,282 L5.1,282 L5.1,288 Z\"\n id=\"stop-[#1470]\"> </path>\n </g>\n </g>\n </g>\n </g>\n </svg>\n }\n </cf-console-toolbar-default-button>\n }\n\n <cf-console-toolbar-default-button (clicked)=\"consoleContext().console.toggleFullscreen()\" label=\"Fullscreen\">\n @if (consoleContext().state.isFullscreenAvailable()) {\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M4 2C2.89543 2 2 2.89543 2 4V8C2 8.55228 2.44772 9 3 9C3.55228 9 4 8.55228 4 8V4H8C8.55228 4 9 3.55228 9 3C9 2.44772 8.55228 2 8 2H4Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M20 2C21.1046 2 22 2.89543 22 4V8C22 8.55228 21.5523 9 21 9C20.4477 9 20 8.55228 20 8V4H16C15.4477 4 15 3.55228 15 3C15 2.44772 15.4477 2 16 2H20Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M20 22C21.1046 22 22 21.1046 22 20V16C22 15.4477 21.5523 15 21 15C20.4477 15 20 15.4477 20 16V20H16C15.4477 20 15 20.4477 15 21C15 21.5523 15.4477 22 16 22H20Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M2 20C2 21.1046 2.89543 22 4 22H8C8.55228 22 9 21.5523 9 21C9 20.4477 8.55228 20 8 20H4V16C4 15.4477 3.55228 15 3 15C2.44772 15 2 15.4477 2 16V20Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n } @else {\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M7 9C8.10457 9 9 8.10457 9 7V3C9 2.44772 8.55228 2 8 2C7.44772 2 7 2.44772 7 3V7H3C2.44772 7 2 7.44772 2 8C2 8.55228 2.44772 9 3 9H7Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M17 9C15.8954 9 15 8.10457 15 7V3C15 2.44772 15.4477 2 16 2C16.5523 2 17 2.44772 17 3V7H21C21.5523 7 22 7.44772 22 8C22 8.55228 21.5523 9 21 9H17Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M17 15C15.8954 15 15 15.8954 15 17V21C15 21.5523 15.4477 22 16 22C16.5523 22 17 21.5523 17 21V17H21C21.5523 17 22 16.5523 22 16C22 15.4477 21.5523 15 21 15H17Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M9 17C9 15.8954 8.10457 15 7 15H3C2.44772 15 2 15.4477 2 16C2 16.5523 2.44772 17 3 17H7V21C7 21.5523 7.44772 22 8 22C8.55228 22 9 21.5523 9 21V17Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n }\n </cf-console-toolbar-default-button>\n </div>\n\n <dialog [open]=\"isClipboardDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleClipboardDialogOpenClose(false)\"></button>\n <p>\n <strong>Clipboard</strong>\n </p>\n </header>\n\n @if (consoleContext().console.supportedFeatures().clipboardRemoteWrite) {\n <div class=\"dialog-section\">\n <h2>Send Text to Console Clipboard</h2>\n <form (submit)=\"handleSendClipboardText($event, clipboardText.value)\">\n <fieldset role=\"group\">\n <input type=\"text\" class=\"clipboard-text\" aria-label=\"Clipboard text\"\n placeholder=\"Enter text to send to the console's clipboard\" #clipboardText autofocus>\n <button type=\"submit\"\n [disabled]=\"!clipboardText.value || !consoleContext().state.isConnected\">Send</button>\n </fieldset>\n </form>\n </div>\n }\n\n @if(!consoleContext().userSettings.settings().console.allowCopyToLocalClipboard ||\n !consoleContext().console.supportedFeatures().clipboardAutomaticLocalCopy) {\n <div class=\"dialog-section\">\n <h2>Console Clipboard Content</h2>\n <form (submit)=\"handleClipboardCopyLastText(consoleLastClipboardText.value)\">\n <fieldset role=\"group\">\n <input type=\"text\" class=\"clipboard-text\" aria-label=\"Clipboard text\" disabled\n [value]=\"consoleContext().clipboard.consoleClipboardText()\"\n placeholder=\"The console's clipboard content will appear here\" #consoleLastClipboardText>\n <button type=\"submit\" [disabled]=\"!consoleLastClipboardText.value\">Copy</button>\n </fieldset>\n </form>\n </div>\n }\n </article>\n </dialog>\n\n <dialog [open]=\"isKeyboardDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"isKeyboardDialogOpen = false\"></button>\n <p>\n <strong>Send Keystrokes</strong>\n </p>\n </header>\n\n <div class=\"dialog-section\">\n <h2>Send Keystrokes to Console</h2>\n <form (submit)=\"handleSendKeyboardInput($event, keyboardInputText())\">\n <fieldset role=\"group\">\n <input type=\"text\" name=\"keyboardInputText\" class=\"clipboard-text\" aria-label=\"Clipboard text\"\n placeholder=\"Enter text to send as keyboard input to the console\" autofocus\n [(ngModel)]=\"keyboardInputText\">\n <button type=\"submit\"\n [disabled]=\"!keyboardInputText() || !consoleContext().state.isConnected\">Send</button>\n </fieldset>\n </form>\n </div>\n\n <div class=\"dialog-section\">\n <h2>Special Key Combinations</h2>\n\n <div class=\"dialog-button-group\">\n <button type=\"button\" aria-label=\"Send Ctrl+Alt+Delete\" (click)=\"handlSendKeyboardCtrlAltDel()\">\n Ctrl + Alt + Delete\n </button>\n </div>\n </div>\n </article>\n </dialog>\n\n <dialog [open]=\"isNetworkDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleNetworkDialogOpenClose(false)\"></button>\n <p>\n <strong>Networks</strong>\n </p>\n </header>\n\n <form>\n @for (nic of consoleContext().networks.config()?.nics; track nic)\n {\n <label for=\"nic-{{ nic }}-select\">{{ nic }}</label>\n <fieldset role=\"group\">\n <select #availableNetworksSelect name=\"nic-{{ nic }}-select\"\n aria-label=\"Select a network to connect to\">\n\n @if (!cfConfig.disabledFeatures.networkDisconnection)\n {\n <option [selected]=\"!consoleContext().networks.config()?.currentConnections?.[nic]\" value=\"\">\n [Disconnected]\n </option>\n }\n\n @for(network of consoleContext().networks.config()?.networks; track network) {\n <option [value]=\"network\"\n [selected]=\"consoleContext().networks.config()?.currentConnections?.[nic] === network\">\n {{ network }}\n </option>\n }\n </select>\n\n <button type=\"button\"\n (click)=\"handleNetworkChangeRequested({ network: availableNetworksSelect.value, nic: nic })\">\n {{ availableNetworksSelect.value ? \"Connect\" : \"Disconnect\" }}\n </button>\n </fieldset>\n }\n\n @if (!cfConfig.disabledFeatures.networkDisconnection)\n {\n <hr />\n <div class=\"dialog-button-group\">\n <button class=\"secondary\" type=\"button\" (click)=\"handleNetworkDisconnectAllRequested()\">\n Disconnect All Network Interfaces\n </button>\n </div>\n }\n </form>\n </article>\n </dialog>\n\n <dialog [open]=\"isPowerDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"isPowerDialogOpen = false\"></button>\n <p>\n <strong>Power</strong>\n </p>\n </header>\n\n <div class=\"dialog-button-group\">\n <button type=\"button\" (click)=\"handleSendPowerRequest('reboot')\">Request Reboot</button>\n <button type=\"button\" (click)=\"handleSendPowerRequest('shutdown')\">Request Shutdown</button>\n <hr />\n <button class=\"secondary\" type=\"button\" (click)=\"handleSendPowerRequest('rebootHard')\">\n Request Hard Reboot\n </button>\n </div>\n </article>\n </dialog>\n\n <dialog [open]=\"isSettingsDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleSettingsDialogOpenClose(false)\"></button>\n <p>\n <strong>Settings</strong>\n </p>\n </header>\n\n <div class=\"settings-form\">\n <h4>Behavior</h4>\n <fieldset>\n <label>\n <input #inputAllowLocalClipboardWrite type=\"checkbox\" name=\"allowLocalClipboardWrite\"\n [checked]=\"consoleContext().userSettings.settings().console.allowCopyToLocalClipboard\"\n (change)=\"handleSettingsAllowLocalClipboardWrite(inputAllowLocalClipboardWrite.checked)\" />\n Allow the remote machine to copy text to my local clipboard\n </label>\n <label>\n <input #inputAttemptRemoteSessionResize type=\"checkbox\" name=\"attemptRemoteSessionResize\"\n [checked]=\"consoleContext().userSettings.settings().console.attemptRemoteSessionResize\"\n (change)=\"handleSettingsAttemptRemoteSessionResize(inputAttemptRemoteSessionResize.checked)\" />\n Attempt to resize the remote session to match local resolution\n </label>\n <label>\n <input #inputScaleToContainerSize type=\"checkbox\" name=\"scaleToContainerSize\"\n [checked]=\"consoleContext().userSettings.settings().console.scaleToCanvasHostSize\"\n (change)=\"handleSettingsScaleToContainerHostSize(inputScaleToContainerSize.checked)\" />\n Scale to maximum available size\n </label>\n </fieldset>\n\n <div class=\"settings-toolbar-dock\">\n <h4>Toolbar Position</h4>\n <div role=\"group\">\n <button (click)=\"handleChangeToolbarPosition('left')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'left'\">Left</button>\n <button (click)=\"handleChangeToolbarPosition('right')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'right'\">Right</button>\n <button (click)=\"handleChangeToolbarPosition('top')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'top'\">Top</button>\n <button (click)=\"handleChangeToolbarPosition('bottom')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'bottom'\">Bottom</button>\n </div>\n </div>\n\n <div class=\"settings-theme\">\n <h4>Theme</h4>\n <div role=\"group\">\n <button (click)=\"handleToolbarThemeChange('light')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.preferTheme === 'light'\">Light</button>\n <button (click)=\"handleToolbarThemeChange('dark')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.preferTheme === 'dark'\">Dark</button>\n <button (click)=\"handleToolbarThemeChange(undefined)\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.preferTheme === undefined\">\n My Default\n </button>\n </div>\n </div>\n </div>\n </article>\n </dialog>\n</div>\n}\n", styles: [":host{display:block;height:100%;width:100%;max-width:100%}fieldset legend{font-weight:700}.toolbar-container{background-color:var(--pico-background-color);padding:4px;height:100%;display:flex;align-items:center;justify-content:center}.toolbar-container .button-container{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px}.toolbar-container .buttons-divider{border-top:1px solid var(--pico-color);margin:.25rem 0;width:100%}.toolbar-container.horizontal{width:100%}.toolbar-container.horizontal .button-container{flex-direction:row}.toolbar-container.horizontal .buttons-divider{align-self:stretch;border-left:1px solid var(--pico-color);height:auto;margin:0 1rem;width:1px}.toolbar-position-buttons{display:flex;gap:4px}.toolbar-position-buttons button{flex-grow:1}.settings-toolbar-dock{margin-top:1rem}dialog h2{font-size:1.1rem;font-weight:700}dialog .dialog-section:not(:last-of-type){margin-bottom:1.5rem}dialog .dialog-button-group button{display:block;width:100%}\n"] }]
437
- }], ctorParameters: () => [] });
438
-
439
- // ===BEGIN LICENSE===
440
- // Copyright 2025 Carnegie Mellon University. All rights reserved.
441
- // Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
442
- // ===END LICENSE===
443
- class ConsoleForgeConfig {
444
- }
445
- const defaultCfConfig = {
446
- canvasRecording: {
447
- autoDownloadCompletedRecordings: true,
448
- chunkLength: 1000,
449
- frameRate: 25,
450
- maxDuration: 10000,
451
- mimeType: "video/webm"
452
- },
453
- consoleBackgroundStyle: "rgb(40, 40, 40)",
454
- disabledFeatures: {
455
- clipboard: false,
456
- consoleScreenRecord: false,
457
- manualConsoleReconnect: false,
458
- networkDisconnection: false,
459
- },
460
- logThreshold: LogLevel.WARNING,
461
- showBrowserNotificationsOnConsoleEvents: true,
462
- toolbar: {
463
- component: ConsoleToolbarDefaultComponent,
464
- disabled: false
465
- }
466
- };
467
-
468
231
  // ===BEGIN LICENSE===
469
232
  // Copyright 2025 Carnegie Mellon University. All rights reserved.
470
233
  // Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
471
234
  // ===END LICENSE===
472
235
  class VncConsoleClientService {
473
236
  clientType = "vnc";
474
- _consoleClipboardUpdated = signal("");
237
+ _consoleClipboardUpdated = signal("", ...(ngDevMode ? [{ debugName: "_consoleClipboardUpdated" }] : /* istanbul ignore next */ []));
475
238
  consoleClipboardUpdated = this._consoleClipboardUpdated.asReadonly();
476
- _connectionStatus = signal("disconnected");
239
+ _connectionStatus = signal("disconnected", ...(ngDevMode ? [{ debugName: "_connectionStatus" }] : /* istanbul ignore next */ []));
477
240
  connectionStatus = this._connectionStatus.asReadonly();
478
241
  _supportedFeatures = signal({
479
242
  clipboardAutomaticLocalCopy: true,
@@ -482,7 +245,7 @@ class VncConsoleClientService {
482
245
  powerManagement: false,
483
246
  requireReconnectOnExitingFullscreen: true,
484
247
  viewOnlyMode: true
485
- });
248
+ }, ...(ngDevMode ? [{ debugName: "_supportedFeatures" }] : /* istanbul ignore next */ []));
486
249
  supportedFeatures = this._supportedFeatures.asReadonly();
487
250
  // injected services
488
251
  cfConfig = inject(ConsoleForgeConfig);
@@ -531,7 +294,7 @@ class VncConsoleClientService {
531
294
  this.logger.log(LogLevel.DEBUG, "Client instantiated. Configuring...");
532
295
  this.doPreConnectionConfig(client);
533
296
  this.logger.log(LogLevel.DEBUG, "Pre-connection config done.");
534
- client.addEventListener("disconnect", event => {
297
+ client.addEventListener("disconnect", (event) => {
535
298
  if (isResolved) {
536
299
  return;
537
300
  }
@@ -644,8 +407,8 @@ class VncConsoleClientService {
644
407
  this._connectionStatus.update(() => "connected");
645
408
  this.logger.log(LogLevel.INFO, "Connected!");
646
409
  });
647
- client.addEventListener("disconnect", ev => this.handleDisconnect(ev.detail.clean));
648
- client.addEventListener("clipboard", ev => {
410
+ client.addEventListener("disconnect", (ev) => this.handleDisconnect(ev.detail.clean));
411
+ client.addEventListener("clipboard", (ev) => {
649
412
  // emit the event
650
413
  this._consoleClipboardUpdated.update(() => ev.detail.text);
651
414
  // if enabled at the app level and permitted by the user, automatically copy text to local clipboard
@@ -659,7 +422,7 @@ class VncConsoleClientService {
659
422
  return;
660
423
  }
661
424
  if (ev.detail.text) {
662
- this.clipboardService.copyText(ev.detail.text);
425
+ this.clipboardService.copyText(ev.detail.text, true);
663
426
  }
664
427
  });
665
428
  }
@@ -694,10 +457,10 @@ class VncConsoleClientService {
694
457
  this.logger.log(LogLevel.WARNING, "Couldn't update VNC client settings from user settings.", err);
695
458
  }
696
459
  }
697
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: VncConsoleClientService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
698
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: VncConsoleClientService, providedIn: 'root' });
460
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: VncConsoleClientService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
461
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: VncConsoleClientService, providedIn: 'root' });
699
462
  }
700
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: VncConsoleClientService, decorators: [{
463
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: VncConsoleClientService, decorators: [{
701
464
  type: Injectable,
702
465
  args: [{ providedIn: 'root' }]
703
466
  }], ctorParameters: () => [] });
@@ -766,10 +529,10 @@ class UuidService {
766
529
  }
767
530
  return crypto.randomUUID();
768
531
  }
769
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UuidService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
770
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UuidService, providedIn: 'root' });
532
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: UuidService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
533
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: UuidService, providedIn: 'root' });
771
534
  }
772
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UuidService, decorators: [{
535
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: UuidService, decorators: [{
773
536
  type: Injectable,
774
537
  args: [{ providedIn: 'root' }]
775
538
  }] });
@@ -788,9 +551,9 @@ class VmWareConsoleClientService {
788
551
  window = inject(WINDOW);
789
552
  wmksClient;
790
553
  clientType = "vmware";
791
- _connectionStatus = signal("disconnected");
554
+ _connectionStatus = signal("disconnected", ...(ngDevMode ? [{ debugName: "_connectionStatus" }] : /* istanbul ignore next */ []));
792
555
  connectionStatus = this._connectionStatus.asReadonly();
793
- _consoleClipboardUpdated = signal("");
556
+ _consoleClipboardUpdated = signal("", ...(ngDevMode ? [{ debugName: "_consoleClipboardUpdated" }] : /* istanbul ignore next */ []));
794
557
  consoleClipboardUpdated = this._consoleClipboardUpdated.asReadonly();
795
558
  _supportedFeatures = signal({
796
559
  clipboardAutomaticLocalCopy: false,
@@ -798,7 +561,7 @@ class VmWareConsoleClientService {
798
561
  onScreenKeyboard: true,
799
562
  powerManagement: false,
800
563
  viewOnlyMode: false
801
- });
564
+ }, ...(ngDevMode ? [{ debugName: "_supportedFeatures" }] : /* istanbul ignore next */ []));
802
565
  supportedFeatures = this._supportedFeatures.asReadonly();
803
566
  _needsCanvasSizeUpdate = new Subject();
804
567
  _needsCanvasSizeUpdateSub = this._needsCanvasSizeUpdate.pipe(debounceTime(250), takeUntilDestroyed()).subscribe(() => {
@@ -865,7 +628,7 @@ class VmWareConsoleClientService {
865
628
  this._consoleClipboardUpdated.update(() => data);
866
629
  // if enabled in config and permitted by the user, copy text to local clipboard
867
630
  if (!this.cfConfig.disabledFeatures.clipboard && this.userSettings.settings().console.allowCopyToLocalClipboard) {
868
- this.clipboardService.copyText(data);
631
+ this.clipboardService.copyText(data, true);
869
632
  }
870
633
  })
871
634
  .register(WmksEvents.ERROR, (ev, data) => {
@@ -929,7 +692,9 @@ class VmWareConsoleClientService {
929
692
  return Promise.reject(`Power management request aren't supported for VMWare consoles. (rejected request: "${request}")`);
930
693
  }
931
694
  setIsViewOnly(isViewOnly) {
932
- this.logger.log(LogLevel.INFO, "A 'view-only' request was issued, but this isn't directly supported at the protocol level for VMWare. The ConsoleComponent will do its best to make the console canvas view-only. Request:", isViewOnly);
695
+ if (isViewOnly) {
696
+ this.logger.log(LogLevel.INFO, "A 'view-only' request was issued, but this isn't directly supported at the protocol level for VMWare. The ConsoleComponent will do its best to make the console canvas view-only. Request:", isViewOnly);
697
+ }
933
698
  return Promise.resolve();
934
699
  }
935
700
  dispose() {
@@ -981,10 +746,10 @@ class VmWareConsoleClientService {
981
746
  this.wmksClient.setOption("rescale", settings.console.scaleToCanvasHostSize);
982
747
  this.wmksClient.updateScreen();
983
748
  }
984
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: VmWareConsoleClientService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
985
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: VmWareConsoleClientService, providedIn: 'root' });
749
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: VmWareConsoleClientService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
750
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: VmWareConsoleClientService, providedIn: 'root' });
986
751
  }
987
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: VmWareConsoleClientService, decorators: [{
752
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: VmWareConsoleClientService, decorators: [{
988
753
  type: Injectable,
989
754
  args: [{ providedIn: 'root' }]
990
755
  }], ctorParameters: () => [] });
@@ -1015,10 +780,10 @@ class ConsoleClientFactoryService {
1015
780
  throw new Error(`Console type ${consoleClientType} NYI`);
1016
781
  }
1017
782
  }
1018
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleClientFactoryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1019
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleClientFactoryService, providedIn: 'root' });
783
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ConsoleClientFactoryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
784
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ConsoleClientFactoryService, providedIn: 'root' });
1020
785
  }
1021
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleClientFactoryService, decorators: [{
786
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ConsoleClientFactoryService, decorators: [{
1022
787
  type: Injectable,
1023
788
  args: [{ providedIn: 'root' }]
1024
789
  }] });
@@ -1029,9 +794,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
1029
794
  // ===END LICENSE===
1030
795
  class FullScreenService {
1031
796
  doc = inject(DOCUMENT);
1032
- _isAvailable = signal(this.doc.fullscreenEnabled);
797
+ _isAvailable = signal(this.doc.fullscreenEnabled, ...(ngDevMode ? [{ debugName: "_isAvailable" }] : /* istanbul ignore next */ []));
1033
798
  isAvailable = this._isAvailable.asReadonly();
1034
- _isActive = signal(false);
799
+ _isActive = signal(false, ...(ngDevMode ? [{ debugName: "_isActive" }] : /* istanbul ignore next */ []));
1035
800
  isActive = this._isActive.asReadonly();
1036
801
  constructor() {
1037
802
  this.doc.addEventListener("fullscreenchange", () => {
@@ -1048,10 +813,10 @@ class FullScreenService {
1048
813
  async tryFullscreen(element) {
1049
814
  return element.requestFullscreen({ navigationUI: "hide" });
1050
815
  }
1051
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: FullScreenService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1052
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: FullScreenService, providedIn: 'root' });
816
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: FullScreenService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
817
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: FullScreenService, providedIn: 'root' });
1053
818
  }
1054
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: FullScreenService, decorators: [{
819
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: FullScreenService, decorators: [{
1055
820
  type: Injectable,
1056
821
  args: [{ providedIn: 'root' }]
1057
822
  }], ctorParameters: () => [] });
@@ -1123,7 +888,7 @@ class CanvasRecorderService {
1123
888
  uuids = inject(UuidService);
1124
889
  window = inject(WINDOW);
1125
890
  activeRecordings = new Set();
1126
- _isRecording = signal(false);
891
+ _isRecording = signal(false, ...(ngDevMode ? [{ debugName: "_isRecording" }] : /* istanbul ignore next */ []));
1127
892
  isRecording = this._isRecording.asReadonly();
1128
893
  startRecord(canvas) {
1129
894
  if (this.cfConfig.disabledFeatures.consoleScreenRecord) {
@@ -1146,10 +911,10 @@ class CanvasRecorderService {
1146
911
  this.activeRecordings.delete(recording);
1147
912
  this._isRecording.set(this.activeRecordings.size > 0);
1148
913
  }
1149
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: CanvasRecorderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1150
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: CanvasRecorderService, providedIn: 'root' });
914
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CanvasRecorderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
915
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CanvasRecorderService, providedIn: 'root' });
1151
916
  }
1152
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: CanvasRecorderService, decorators: [{
917
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CanvasRecorderService, decorators: [{
1153
918
  type: Injectable,
1154
919
  args: [{ providedIn: 'root' }]
1155
920
  }] });
@@ -1161,7 +926,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
1161
926
  // EXPLICITLY not provided in root - this is provided by ConsoleComponent,
1162
927
  // and each should get its own
1163
928
  class CanvasService {
1164
- _canvas = signal(null);
929
+ _canvas = signal(null, ...(ngDevMode ? [{ debugName: "_canvas" }] : /* istanbul ignore next */ []));
1165
930
  canvas = this._canvas.asReadonly();
1166
931
  clearCanvas() {
1167
932
  this._canvas.update(() => null);
@@ -1169,10 +934,10 @@ class CanvasService {
1169
934
  setCanvas(canvas) {
1170
935
  this._canvas.update(() => canvas);
1171
936
  }
1172
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: CanvasService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1173
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: CanvasService });
937
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CanvasService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
938
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CanvasService });
1174
939
  }
1175
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: CanvasService, decorators: [{
940
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CanvasService, decorators: [{
1176
941
  type: Injectable
1177
942
  }] });
1178
943
 
@@ -1193,10 +958,10 @@ class BlobDownloaderService {
1193
958
  this.doc.body.removeChild(a);
1194
959
  URL.revokeObjectURL(url); // free memory
1195
960
  }
1196
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BlobDownloaderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1197
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BlobDownloaderService, providedIn: 'root' });
961
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: BlobDownloaderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
962
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: BlobDownloaderService, providedIn: 'root' });
1198
963
  }
1199
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BlobDownloaderService, decorators: [{
964
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: BlobDownloaderService, decorators: [{
1200
965
  type: Injectable,
1201
966
  args: [{ providedIn: 'root' }]
1202
967
  }] });
@@ -1206,10 +971,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
1206
971
  // Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
1207
972
  // ===END LICENSE===
1208
973
  class ConsoleToolbarComponent {
1209
- consoleClient = input.required();
1210
- consoleNetworkConfig = input();
1211
- customToolbarComponent = input();
1212
- isViewOnly = input.required();
974
+ consoleClient = input.required(...(ngDevMode ? [{ debugName: "consoleClient" }] : /* istanbul ignore next */ []));
975
+ consoleNetworkConfig = input(...(ngDevMode ? [undefined, { debugName: "consoleNetworkConfig" }] : /* istanbul ignore next */ []));
976
+ customToolbarComponent = input(...(ngDevMode ? [undefined, { debugName: "customToolbarComponent" }] : /* istanbul ignore next */ []));
977
+ isViewOnly = input.required(...(ngDevMode ? [{ debugName: "isViewOnly" }] : /* istanbul ignore next */ []));
1213
978
  canvasRecordingStarted = output();
1214
979
  canvasRecordingFinished = output();
1215
980
  ctrlAltDelSent = output();
@@ -1230,11 +995,11 @@ class ConsoleToolbarComponent {
1230
995
  userSettings = inject(UserSettingsService);
1231
996
  window = inject(WINDOW);
1232
997
  // component state
1233
- activeConsoleRecording = signal(undefined);
1234
- isConnected = computed(() => this.consoleClient()?.connectionStatus() === "connected");
1235
- isManualConsoleReconnectAvailable = computed(() => !this.config.disabledFeatures.manualConsoleReconnect && this.consoleClient()?.connectionStatus() !== "connecting");
998
+ activeConsoleRecording = signal(undefined, ...(ngDevMode ? [{ debugName: "activeConsoleRecording" }] : /* istanbul ignore next */ []));
999
+ isConnected = computed(() => this.consoleClient()?.connectionStatus() === "connected", ...(ngDevMode ? [{ debugName: "isConnected" }] : /* istanbul ignore next */ []));
1000
+ isManualConsoleReconnectAvailable = computed(() => !this.config.disabledFeatures.manualConsoleReconnect && this.consoleClient()?.connectionStatus() !== "connecting", ...(ngDevMode ? [{ debugName: "isManualConsoleReconnectAvailable" }] : /* istanbul ignore next */ []));
1236
1001
  toolbarComponentContext;
1237
- toolbarComponent = computed(() => this.customToolbarComponent() || this.config.toolbar.component);
1002
+ toolbarComponent = computed(() => this.customToolbarComponent() || this.config.toolbar.component, ...(ngDevMode ? [{ debugName: "toolbarComponent" }] : /* istanbul ignore next */ []));
1238
1003
  constructor() {
1239
1004
  this.toolbarComponentContext = {
1240
1005
  clipboard: {
@@ -1346,11 +1111,16 @@ class ConsoleToolbarComponent {
1346
1111
  }
1347
1112
  this.logger.log(LogLevel.DEBUG, "Recording stopped.");
1348
1113
  const recording = await this.activeConsoleRecording().recording.stop();
1114
+ // try to cancel the timeout of the extant recording if it's there
1115
+ if (this.activeConsoleRecording()?.timeoutRef) {
1116
+ this.window.clearTimeout(this.activeConsoleRecording().timeoutRef);
1117
+ }
1349
1118
  this.activeConsoleRecording.update(() => undefined);
1350
1119
  // if configured, automatically offer a download
1351
1120
  if (recording && this.config.canvasRecording.autoDownloadCompletedRecordings) {
1352
1121
  this.blobDownloader.download(recording, "your-console-recording.webm");
1353
1122
  }
1123
+ // emit the recording
1354
1124
  this.canvasRecordingFinished.emit(recording);
1355
1125
  this.logger.log(LogLevel.DEBUG, "Recording emitted.");
1356
1126
  return recording;
@@ -1370,13 +1140,13 @@ class ConsoleToolbarComponent {
1370
1140
  this.consoleClient().sendClipboardText(text);
1371
1141
  }
1372
1142
  }
1373
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1374
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: ConsoleToolbarComponent, isStandalone: true, selector: "cf-console-toolbar", inputs: { consoleClient: { classPropertyName: "consoleClient", publicName: "consoleClient", isSignal: true, isRequired: true, transformFunction: null }, consoleNetworkConfig: { classPropertyName: "consoleNetworkConfig", publicName: "consoleNetworkConfig", isSignal: true, isRequired: false, transformFunction: null }, customToolbarComponent: { classPropertyName: "customToolbarComponent", publicName: "customToolbarComponent", isSignal: true, isRequired: false, transformFunction: null }, isViewOnly: { classPropertyName: "isViewOnly", publicName: "isViewOnly", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { canvasRecordingStarted: "canvasRecordingStarted", canvasRecordingFinished: "canvasRecordingFinished", ctrlAltDelSent: "ctrlAltDelSent", keyboardInputSent: "keyboardInputSent", networkConnectionRequested: "networkConnectionRequested", networkDisconnectRequested: "networkDisconnectRequested", powerRequestSent: "powerRequestSent", reconnectRequestSent: "reconnectRequestSent", screenshotCopied: "screenshotCopied", toggleFullscreen: "toggleFullscreen" }, ngImport: i0, template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n@if (toolbarComponent()) {\n<ng-container *ngComponentOutlet=\"toolbarComponent()!; inputs: { 'consoleContext': toolbarComponentContext }\" />\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }] });
1143
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ConsoleToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1144
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ConsoleToolbarComponent, isStandalone: true, selector: "cf-console-toolbar", inputs: { consoleClient: { classPropertyName: "consoleClient", publicName: "consoleClient", isSignal: true, isRequired: true, transformFunction: null }, consoleNetworkConfig: { classPropertyName: "consoleNetworkConfig", publicName: "consoleNetworkConfig", isSignal: true, isRequired: false, transformFunction: null }, customToolbarComponent: { classPropertyName: "customToolbarComponent", publicName: "customToolbarComponent", isSignal: true, isRequired: false, transformFunction: null }, isViewOnly: { classPropertyName: "isViewOnly", publicName: "isViewOnly", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { canvasRecordingStarted: "canvasRecordingStarted", canvasRecordingFinished: "canvasRecordingFinished", ctrlAltDelSent: "ctrlAltDelSent", keyboardInputSent: "keyboardInputSent", networkConnectionRequested: "networkConnectionRequested", networkDisconnectRequested: "networkDisconnectRequested", powerRequestSent: "powerRequestSent", reconnectRequestSent: "reconnectRequestSent", screenshotCopied: "screenshotCopied", toggleFullscreen: "toggleFullscreen" }, ngImport: i0, template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n@if (toolbarComponent()) {\n<ng-container *ngComponentOutlet=\"toolbarComponent()!; inputs: { 'consoleContext': toolbarComponentContext }\" />\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }] });
1375
1145
  }
1376
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleToolbarComponent, decorators: [{
1146
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ConsoleToolbarComponent, decorators: [{
1377
1147
  type: Component,
1378
1148
  args: [{ selector: 'cf-console-toolbar', imports: [CommonModule], template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n@if (toolbarComponent()) {\n<ng-container *ngComponentOutlet=\"toolbarComponent()!; inputs: { 'consoleContext': toolbarComponentContext }\" />\n}\n" }]
1379
- }], ctorParameters: () => [] });
1149
+ }], ctorParameters: () => [], propDecorators: { consoleClient: [{ type: i0.Input, args: [{ isSignal: true, alias: "consoleClient", required: true }] }], consoleNetworkConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "consoleNetworkConfig", required: false }] }], customToolbarComponent: [{ type: i0.Input, args: [{ isSignal: true, alias: "customToolbarComponent", required: false }] }], isViewOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "isViewOnly", required: true }] }], canvasRecordingStarted: [{ type: i0.Output, args: ["canvasRecordingStarted"] }], canvasRecordingFinished: [{ type: i0.Output, args: ["canvasRecordingFinished"] }], ctrlAltDelSent: [{ type: i0.Output, args: ["ctrlAltDelSent"] }], keyboardInputSent: [{ type: i0.Output, args: ["keyboardInputSent"] }], networkConnectionRequested: [{ type: i0.Output, args: ["networkConnectionRequested"] }], networkDisconnectRequested: [{ type: i0.Output, args: ["networkDisconnectRequested"] }], powerRequestSent: [{ type: i0.Output, args: ["powerRequestSent"] }], reconnectRequestSent: [{ type: i0.Output, args: ["reconnectRequestSent"] }], screenshotCopied: [{ type: i0.Output, args: ["screenshotCopied"] }], toggleFullscreen: [{ type: i0.Output, args: ["toggleFullscreen"] }] } });
1380
1150
 
1381
1151
  // ===BEGIN LICENSE===
1382
1152
  // Copyright 2025 Carnegie Mellon University. All rights reserved.
@@ -1406,20 +1176,61 @@ class BrowserNotificationsService {
1406
1176
  };
1407
1177
  }
1408
1178
  }
1409
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BrowserNotificationsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1410
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BrowserNotificationsService, providedIn: 'root' });
1179
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: BrowserNotificationsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1180
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: BrowserNotificationsService, providedIn: 'root' });
1181
+ }
1182
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: BrowserNotificationsService, decorators: [{
1183
+ type: Injectable,
1184
+ args: [{ providedIn: 'root' }]
1185
+ }] });
1186
+
1187
+ class PicoCssService {
1188
+ sheet;
1189
+ loading;
1190
+ loadStyleSheet() {
1191
+ if (this.sheet)
1192
+ return Promise.resolve(this.sheet);
1193
+ if (!this.loading) {
1194
+ this.loading = fetch('assets/pico.min.css')
1195
+ .then(r => r.text())
1196
+ .then(css => {
1197
+ const sheet = new CSSStyleSheet();
1198
+ sheet.replaceSync(css);
1199
+ this.sheet = sheet;
1200
+ });
1201
+ }
1202
+ return this.loading.then(() => this.sheet);
1203
+ }
1204
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: PicoCssService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1205
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: PicoCssService, providedIn: 'root' });
1411
1206
  }
1412
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BrowserNotificationsService, decorators: [{
1207
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: PicoCssService, decorators: [{
1413
1208
  type: Injectable,
1414
1209
  args: [{ providedIn: 'root' }]
1415
1210
  }] });
1416
1211
 
1212
+ class ApplyToolbarThemeDirective {
1213
+ hostElement = inject((ElementRef));
1214
+ userSettings = inject(UserSettingsService).settings;
1215
+ constructor() {
1216
+ effect(() => {
1217
+ this.hostElement.nativeElement.setAttribute("data-theme", this.userSettings().toolbar.preferTheme);
1218
+ });
1219
+ }
1220
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ApplyToolbarThemeDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1221
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.5", type: ApplyToolbarThemeDirective, isStandalone: true, selector: "[cfApplyToolbarTheme]", ngImport: i0 });
1222
+ }
1223
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ApplyToolbarThemeDirective, decorators: [{
1224
+ type: Directive,
1225
+ args: [{ selector: '[cfApplyToolbarTheme]' }]
1226
+ }], ctorParameters: () => [] });
1227
+
1417
1228
  // ===BEGIN LICENSE===
1418
1229
  // Copyright 2025 Carnegie Mellon University. All rights reserved.
1419
1230
  // Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
1420
1231
  // ===END LICENSE===
1421
1232
  class ConsoleStatusComponent {
1422
- status = input("disconnected");
1233
+ status = input("disconnected", ...(ngDevMode ? [{ debugName: "status" }] : /* istanbul ignore next */ []));
1423
1234
  reconnectRequest = output();
1424
1235
  picoCssService = inject(PicoCssService);
1425
1236
  hostElement = inject((ElementRef));
@@ -1430,13 +1241,13 @@ class ConsoleStatusComponent {
1430
1241
  this.hostElement.nativeElement.shadowRoot.adoptedStyleSheets = [sheet];
1431
1242
  }
1432
1243
  }
1433
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleStatusComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1434
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: ConsoleStatusComponent, isStandalone: true, selector: "cf-console-status", inputs: { status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { reconnectRequest: "reconnectRequest" }, ngImport: i0, template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n<div cfApplyToolbarTheme>\n @if (status() === \"connecting\") {\n <progress></progress>\n }\n @else if(!status() || status() == \"disconnected\") {\n <div class=\"disconnected-banner\" (click)=\"reconnectRequest.emit()\">\n Console disconnected\n </div>\n }\n</div>\n", styles: [".disconnected-banner{background-color:var(--pico-form-element-invalid-active-border-color);color:var(--pico-primary-inverse);cursor:pointer;font-weight:700;padding:4px 0;text-align:center}progress{width:100%;margin:0!important}\n"], dependencies: [{ kind: "directive", type: ApplyToolbarThemeDirective, selector: "[cfApplyToolbarTheme]" }], encapsulation: i0.ViewEncapsulation.ShadowDom });
1244
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ConsoleStatusComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1245
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ConsoleStatusComponent, isStandalone: true, selector: "cf-console-status", inputs: { status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { reconnectRequest: "reconnectRequest" }, ngImport: i0, template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n<div cfApplyToolbarTheme>\n @if (status() === \"connecting\") {\n <progress></progress>\n }\n @else if(status() === \"disconnected\") {\n <div class=\"disconnected-banner\" (click)=\"reconnectRequest.emit()\">\n Console disconnected\n </div>\n }\n</div>\n", styles: [".disconnected-banner{background-color:var(--pico-form-element-invalid-active-border-color);color:var(--pico-primary-inverse);cursor:pointer;font-weight:700;padding:4px 0;text-align:center}progress{width:100%;margin:0!important}\n"], dependencies: [{ kind: "directive", type: ApplyToolbarThemeDirective, selector: "[cfApplyToolbarTheme]" }], encapsulation: i0.ViewEncapsulation.ShadowDom });
1435
1246
  }
1436
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleStatusComponent, decorators: [{
1247
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ConsoleStatusComponent, decorators: [{
1437
1248
  type: Component,
1438
- args: [{ selector: 'cf-console-status', imports: [ApplyToolbarThemeDirective], encapsulation: ViewEncapsulation.ShadowDom, template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n<div cfApplyToolbarTheme>\n @if (status() === \"connecting\") {\n <progress></progress>\n }\n @else if(!status() || status() == \"disconnected\") {\n <div class=\"disconnected-banner\" (click)=\"reconnectRequest.emit()\">\n Console disconnected\n </div>\n }\n</div>\n", styles: [".disconnected-banner{background-color:var(--pico-form-element-invalid-active-border-color);color:var(--pico-primary-inverse);cursor:pointer;font-weight:700;padding:4px 0;text-align:center}progress{width:100%;margin:0!important}\n"] }]
1439
- }] });
1249
+ args: [{ selector: 'cf-console-status', imports: [ApplyToolbarThemeDirective], encapsulation: ViewEncapsulation.ShadowDom, template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n<div cfApplyToolbarTheme>\n @if (status() === \"connecting\") {\n <progress></progress>\n }\n @else if(status() === \"disconnected\") {\n <div class=\"disconnected-banner\" (click)=\"reconnectRequest.emit()\">\n Console disconnected\n </div>\n }\n</div>\n", styles: [".disconnected-banner{background-color:var(--pico-form-element-invalid-active-border-color);color:var(--pico-primary-inverse);cursor:pointer;font-weight:700;padding:4px 0;text-align:center}progress{width:100%;margin:0!important}\n"] }]
1250
+ }], propDecorators: { status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], reconnectRequest: [{ type: i0.Output, args: ["reconnectRequest"] }] } });
1440
1251
 
1441
1252
  // ===BEGIN LICENSE===
1442
1253
  // Copyright 2025 Carnegie Mellon University. All rights reserved.
@@ -1444,12 +1255,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
1444
1255
  // ===END LICENSE===
1445
1256
  class ConsoleComponent {
1446
1257
  // component I/O
1447
- autoConnect = input(true);
1448
- config = input.required();
1449
- isViewOnly = input(false);
1450
- networkConfig = input();
1451
- toolbarComponent = input();
1452
- toolbarDisabled = input(false);
1258
+ autoConnect = input(true, ...(ngDevMode ? [{ debugName: "autoConnect" }] : /* istanbul ignore next */ []));
1259
+ config = input.required(...(ngDevMode ? [{ debugName: "config" }] : /* istanbul ignore next */ []));
1260
+ isViewOnly = input(false, ...(ngDevMode ? [{ debugName: "isViewOnly" }] : /* istanbul ignore next */ []));
1261
+ networkConfig = input(...(ngDevMode ? [undefined, { debugName: "networkConfig" }] : /* istanbul ignore next */ []));
1262
+ toolbarComponent = input(...(ngDevMode ? [undefined, { debugName: "toolbarComponent" }] : /* istanbul ignore next */ []));
1263
+ toolbarDisabled = input(false, ...(ngDevMode ? [{ debugName: "toolbarDisabled" }] : /* istanbul ignore next */ []));
1453
1264
  connectionStatusChanged = output();
1454
1265
  consoleClipboardUpdated = output();
1455
1266
  consoleRecorded = output();
@@ -1475,8 +1286,8 @@ class ConsoleComponent {
1475
1286
  componentContainer = viewChild.required("componentContainer");
1476
1287
  consoleHostElement = viewChild.required("consoleHost");
1477
1288
  // other component state
1478
- consoleClient = signal(undefined);
1479
- consoleClientConnectionStatus = computed(() => this.consoleClient()?.connectionStatus());
1289
+ consoleClient = signal(undefined, ...(ngDevMode ? [{ debugName: "consoleClient" }] : /* istanbul ignore next */ []));
1290
+ consoleClientConnectionStatus = computed(() => this.consoleClient()?.connectionStatus(), ...(ngDevMode ? [{ debugName: "consoleClientConnectionStatus" }] : /* istanbul ignore next */ []));
1480
1291
  consoleHostBackgroundStyle = this.consoleForgeConfig.consoleBackgroundStyle;
1481
1292
  consoleHostElementId = `cf-console-${this.uuids.get()}`;
1482
1293
  isRecording = inject(CanvasRecorderService).isRecording;
@@ -1485,7 +1296,7 @@ class ConsoleComponent {
1485
1296
  return !(this.toolbarDisabled() || this.consoleForgeConfig.toolbar.disabled) &&
1486
1297
  // AND if a toolbar component has been specified either here or globally
1487
1298
  (this.toolbarComponent() || this.consoleForgeConfig.toolbar.component);
1488
- });
1299
+ }, ...(ngDevMode ? [{ debugName: "toolbarEnabled" }] : /* istanbul ignore next */ []));
1489
1300
  userSettings = this.userSettingsService.settings;
1490
1301
  constructor() {
1491
1302
  // when config is provided and autoconnect is on, attempt to automatically connect
@@ -1625,13 +1436,13 @@ class ConsoleComponent {
1625
1436
  }
1626
1437
  return this.document.querySelector(`#${this.consoleHostElementId} canvas`) || undefined;
1627
1438
  }
1628
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1629
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: ConsoleComponent, isStandalone: true, selector: "cf-console", inputs: { autoConnect: { classPropertyName: "autoConnect", publicName: "autoConnect", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, isViewOnly: { classPropertyName: "isViewOnly", publicName: "isViewOnly", isSignal: true, isRequired: false, transformFunction: null }, networkConfig: { classPropertyName: "networkConfig", publicName: "networkConfig", isSignal: true, isRequired: false, transformFunction: null }, toolbarComponent: { classPropertyName: "toolbarComponent", publicName: "toolbarComponent", isSignal: true, isRequired: false, transformFunction: null }, toolbarDisabled: { classPropertyName: "toolbarDisabled", publicName: "toolbarDisabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { connectionStatusChanged: "connectionStatusChanged", consoleClipboardUpdated: "consoleClipboardUpdated", consoleRecorded: "consoleRecorded", ctrlAltDelSent: "ctrlAltDelSent", localClipboardUpdated: "localClipboardUpdated", networkConnectionRequested: "networkConnectionRequested", networkDisconnectRequested: "networkDisconnectRequested", powerRequestSent: "powerRequestSent", reconnectRequest: "reconnectRequest", screenshotCopied: "screenshotCopied" }, providers: [
1439
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ConsoleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1440
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ConsoleComponent, isStandalone: true, selector: "cf-console", inputs: { autoConnect: { classPropertyName: "autoConnect", publicName: "autoConnect", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, isViewOnly: { classPropertyName: "isViewOnly", publicName: "isViewOnly", isSignal: true, isRequired: false, transformFunction: null }, networkConfig: { classPropertyName: "networkConfig", publicName: "networkConfig", isSignal: true, isRequired: false, transformFunction: null }, toolbarComponent: { classPropertyName: "toolbarComponent", publicName: "toolbarComponent", isSignal: true, isRequired: false, transformFunction: null }, toolbarDisabled: { classPropertyName: "toolbarDisabled", publicName: "toolbarDisabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { connectionStatusChanged: "connectionStatusChanged", consoleClipboardUpdated: "consoleClipboardUpdated", consoleRecorded: "consoleRecorded", ctrlAltDelSent: "ctrlAltDelSent", localClipboardUpdated: "localClipboardUpdated", networkConnectionRequested: "networkConnectionRequested", networkDisconnectRequested: "networkDisconnectRequested", powerRequestSent: "powerRequestSent", reconnectRequest: "reconnectRequest", screenshotCopied: "screenshotCopied" }, providers: [
1630
1441
  // the console component has access to the canvas which is injected by
1631
1442
  CanvasService
1632
1443
  ], viewQueries: [{ propertyName: "componentContainer", first: true, predicate: ["componentContainer"], descendants: true, isSignal: true }, { propertyName: "consoleHostElement", first: true, predicate: ["consoleHost"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n<div #componentContainer class=\"console-component flex\"\n [class.console-client-type-vnc]=\"consoleClient()?.clientType == 'vnc'\"\n [class.console-client-type-vmware]=\"consoleClient()?.clientType == 'vmware'\"\n [class.flex-column]=\"userSettings().toolbar.dockTo === 'top' || userSettings().toolbar.dockTo === 'bottom'\">\n\n @if (toolbarEnabled()) {\n <cf-console-toolbar\n [class.flex-order-1]=\"userSettings().toolbar.dockTo === 'right' || userSettings().toolbar.dockTo === 'bottom'\"\n [consoleClient]=\"consoleClient()!\" [consoleNetworkConfig]=\"networkConfig()\" [isViewOnly]=\"isViewOnly()\"\n (canvasRecordingFinished)=\"consoleRecorded.emit($event)\"\n (canvasRecordingStarted)=\"handleConsoleRecordingStarted()\" [customToolbarComponent]=\"toolbarComponent()\"\n (ctrlAltDelSent)=\"handleCtrlAltDelSent()\" (networkConnectionRequested)=\"networkConnectionRequested.emit($event)\"\n (powerRequestSent)=\"powerRequestSent.emit($event)\"\n (networkDisconnectRequested)=\"networkDisconnectRequested.emit($event)\"\n (reconnectRequestSent)=\"handleReconnectRequest()\" (screenshotCopied)=\"handleScreenshotCopied($event)\"\n (toggleFullscreen)=\"handleFullscreen()\"></cf-console-toolbar>\n }\n\n <div class=\"console-host-container\" [style.background]=\"consoleHostBackgroundStyle\"\n [class.flex-order-0]=\"userSettings().toolbar.dockTo === 'right' || userSettings().toolbar.dockTo === 'bottom'\">\n <cf-console-status [status]=\"consoleClient()?.connectionStatus()\"\n (reconnectRequest)=\"reconnectRequest.emit(this.config())\"></cf-console-status>\n\n <div #consoleHost [id]=\"consoleHostElementId\" class=\"console-host\" [class.recording]=\"isRecording()\"\n [class.view-only]=\"isViewOnly()\">\n </div>\n </div>\n</div>\n", styles: [".console-component{max-width:100vw;max-height:100vh;width:100%;height:100%}cf-console-toolbar{display:block;flex:0 1 auto;max-height:100%;max-width:100%}cf-console-status{width:100%}:fullscreen{width:100vw!important;height:100vh!important;max-width:100vw!important;max-height:100vh!important}:fullscreen cf-console-toolbar{z-index:5}.console-host-container{align-items:center;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;max-height:100%;max-width:100%;justify-content:center}.console-host{max-width:100%;max-height:100%;width:100%;aspect-ratio:16/9;margin:0 auto;overflow:hidden}.console-host.recording{outline:4px solid #ee402e}.flex{display:flex;flex-direction:row}.flex.flex-column{flex-direction:column}.flex-order-0{order:0}.flex-order-1{order:1}.console-component.console-client-type-vmware:not(:fullscreen) ::ng-deep canvas{aspect-ratio:16/9!important;max-height:100%!important;max-width:100%!important}.console-component.console-client-type-vmware .console-host{display:flex;justify-content:center;aspect-ratio:16/9;position:relative}.console-component.console-client-type-vmware .console-host.view-only ::ng-deep canvas{cursor:not-allowed;pointer-events:none!important}\n"], dependencies: [{ kind: "component", type: ConsoleStatusComponent, selector: "cf-console-status", inputs: ["status"], outputs: ["reconnectRequest"] }, { kind: "component", type: ConsoleToolbarComponent, selector: "cf-console-toolbar", inputs: ["consoleClient", "consoleNetworkConfig", "customToolbarComponent", "isViewOnly"], outputs: ["canvasRecordingStarted", "canvasRecordingFinished", "ctrlAltDelSent", "keyboardInputSent", "networkConnectionRequested", "networkDisconnectRequested", "powerRequestSent", "reconnectRequestSent", "screenshotCopied", "toggleFullscreen"] }] });
1633
1444
  }
1634
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleComponent, decorators: [{
1445
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ConsoleComponent, decorators: [{
1635
1446
  type: Component,
1636
1447
  args: [{ selector: 'cf-console', standalone: true, imports: [
1637
1448
  ConsoleStatusComponent,
@@ -1640,19 +1451,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
1640
1451
  // the console component has access to the canvas which is injected by
1641
1452
  CanvasService
1642
1453
  ], template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n<div #componentContainer class=\"console-component flex\"\n [class.console-client-type-vnc]=\"consoleClient()?.clientType == 'vnc'\"\n [class.console-client-type-vmware]=\"consoleClient()?.clientType == 'vmware'\"\n [class.flex-column]=\"userSettings().toolbar.dockTo === 'top' || userSettings().toolbar.dockTo === 'bottom'\">\n\n @if (toolbarEnabled()) {\n <cf-console-toolbar\n [class.flex-order-1]=\"userSettings().toolbar.dockTo === 'right' || userSettings().toolbar.dockTo === 'bottom'\"\n [consoleClient]=\"consoleClient()!\" [consoleNetworkConfig]=\"networkConfig()\" [isViewOnly]=\"isViewOnly()\"\n (canvasRecordingFinished)=\"consoleRecorded.emit($event)\"\n (canvasRecordingStarted)=\"handleConsoleRecordingStarted()\" [customToolbarComponent]=\"toolbarComponent()\"\n (ctrlAltDelSent)=\"handleCtrlAltDelSent()\" (networkConnectionRequested)=\"networkConnectionRequested.emit($event)\"\n (powerRequestSent)=\"powerRequestSent.emit($event)\"\n (networkDisconnectRequested)=\"networkDisconnectRequested.emit($event)\"\n (reconnectRequestSent)=\"handleReconnectRequest()\" (screenshotCopied)=\"handleScreenshotCopied($event)\"\n (toggleFullscreen)=\"handleFullscreen()\"></cf-console-toolbar>\n }\n\n <div class=\"console-host-container\" [style.background]=\"consoleHostBackgroundStyle\"\n [class.flex-order-0]=\"userSettings().toolbar.dockTo === 'right' || userSettings().toolbar.dockTo === 'bottom'\">\n <cf-console-status [status]=\"consoleClient()?.connectionStatus()\"\n (reconnectRequest)=\"reconnectRequest.emit(this.config())\"></cf-console-status>\n\n <div #consoleHost [id]=\"consoleHostElementId\" class=\"console-host\" [class.recording]=\"isRecording()\"\n [class.view-only]=\"isViewOnly()\">\n </div>\n </div>\n</div>\n", styles: [".console-component{max-width:100vw;max-height:100vh;width:100%;height:100%}cf-console-toolbar{display:block;flex:0 1 auto;max-height:100%;max-width:100%}cf-console-status{width:100%}:fullscreen{width:100vw!important;height:100vh!important;max-width:100vw!important;max-height:100vh!important}:fullscreen cf-console-toolbar{z-index:5}.console-host-container{align-items:center;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;max-height:100%;max-width:100%;justify-content:center}.console-host{max-width:100%;max-height:100%;width:100%;aspect-ratio:16/9;margin:0 auto;overflow:hidden}.console-host.recording{outline:4px solid #ee402e}.flex{display:flex;flex-direction:row}.flex.flex-column{flex-direction:column}.flex-order-0{order:0}.flex-order-1{order:1}.console-component.console-client-type-vmware:not(:fullscreen) ::ng-deep canvas{aspect-ratio:16/9!important;max-height:100%!important;max-width:100%!important}.console-component.console-client-type-vmware .console-host{display:flex;justify-content:center;aspect-ratio:16/9;position:relative}.console-component.console-client-type-vmware .console-host.view-only ::ng-deep canvas{cursor:not-allowed;pointer-events:none!important}\n"] }]
1643
- }], ctorParameters: () => [] });
1454
+ }], ctorParameters: () => [], propDecorators: { autoConnect: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoConnect", required: false }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], isViewOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "isViewOnly", required: false }] }], networkConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "networkConfig", required: false }] }], toolbarComponent: [{ type: i0.Input, args: [{ isSignal: true, alias: "toolbarComponent", required: false }] }], toolbarDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "toolbarDisabled", required: false }] }], connectionStatusChanged: [{ type: i0.Output, args: ["connectionStatusChanged"] }], consoleClipboardUpdated: [{ type: i0.Output, args: ["consoleClipboardUpdated"] }], consoleRecorded: [{ type: i0.Output, args: ["consoleRecorded"] }], ctrlAltDelSent: [{ type: i0.Output, args: ["ctrlAltDelSent"] }], localClipboardUpdated: [{ type: i0.Output, args: ["localClipboardUpdated"] }], networkConnectionRequested: [{ type: i0.Output, args: ["networkConnectionRequested"] }], networkDisconnectRequested: [{ type: i0.Output, args: ["networkDisconnectRequested"] }], powerRequestSent: [{ type: i0.Output, args: ["powerRequestSent"] }], reconnectRequest: [{ type: i0.Output, args: ["reconnectRequest"] }], screenshotCopied: [{ type: i0.Output, args: ["screenshotCopied"] }], componentContainer: [{ type: i0.ViewChild, args: ["componentContainer", { isSignal: true }] }], consoleHostElement: [{ type: i0.ViewChild, args: ["consoleHost", { isSignal: true }] }] } });
1644
1455
 
1645
1456
  class ConsoleTileComponent {
1646
- config = input();
1457
+ config = input(...(ngDevMode ? [undefined, { debugName: "config" }] : /* istanbul ignore next */ []));
1647
1458
  clicked = output();
1459
+ connectionStatus = output();
1648
1460
  reconnectRequest = output();
1649
1461
  cfConfig = inject(ConsoleForgeConfig);
1650
1462
  consoleClientFactory = inject(ConsoleClientFactoryService);
1651
- consoleHostElement = viewChild("consoleHost");
1463
+ consoleHostElement = viewChild("consoleHost", ...(ngDevMode ? [{ debugName: "consoleHostElement" }] : /* istanbul ignore next */ []));
1652
1464
  logger = inject(LoggerService);
1653
1465
  uuids = inject(UuidService);
1654
1466
  consoleClient;
1655
- consoleClientType = computed(() => this.config()?.consoleClientType || this.cfConfig.defaultConsoleClientType);
1467
+ consoleClientType = computed(() => this.config()?.consoleClientType || this.cfConfig.defaultConsoleClientType, ...(ngDevMode ? [{ debugName: "consoleClientType" }] : /* istanbul ignore next */ []));
1656
1468
  // even though nothing here explicitly references this, every console host element needs an ID
1657
1469
  // because the vmware client relies on the ID, not the element reference, to create its canvas
1658
1470
  consoleHostElementId = "console-host-tile-" + this.uuids.get();
@@ -1668,6 +1480,13 @@ class ConsoleTileComponent {
1668
1480
  this.connect(consoleHostElement.nativeElement);
1669
1481
  this.logger.log(LogLevel.DEBUG, "Reconnected console tile with config", config);
1670
1482
  });
1483
+ // emit console connection status changes
1484
+ effect(() => {
1485
+ const status = this.consoleClient?.connectionStatus();
1486
+ if (status) {
1487
+ this.connectionStatus.emit(status);
1488
+ }
1489
+ });
1671
1490
  }
1672
1491
  async connect(hostElement) {
1673
1492
  const connectionConfig = this.config();
@@ -1685,20 +1504,228 @@ class ConsoleTileComponent {
1685
1504
  });
1686
1505
  this.consoleClient.setIsViewOnly(true);
1687
1506
  }
1688
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleTileComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1689
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.2.14", type: ConsoleTileComponent, isStandalone: true, selector: "cf-console-tile", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clicked: "clicked", reconnectRequest: "reconnectRequest" }, viewQueries: [{ propertyName: "consoleHostElement", first: true, predicate: ["consoleHost"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"console-tile-component\">\n <cf-console-status [status]=\"consoleClient?.connectionStatus()\"\n (reconnectRequest)=\"reconnectRequest.emit(this.config())\"></cf-console-status>\n\n <div #consoleHost [id]=\"consoleHostElementId\" class=\"console-host\"\n [class.clickable]=\"consoleClient?.connectionStatus() == 'connected'\"\n [class.console-client-type-vnc]=\"consoleClientType() == 'vnc'\"\n [class.console-client-type-vmware]=\"consoleClientType() == 'vmware'\" (click)=\"clicked.emit(config())\">\n </div>\n</div>\n", styles: ["::ng-deep canvas{cursor:not-allowed!important;pointer-events:none!important;width:100%!important;height:100%!important}.console-tile-component{height:100%;width:100%;max-height:100%;max-width:100%}.console-host{max-width:100%;max-height:100%;width:100%;aspect-ratio:16/9;margin:0 auto;overflow:hidden}.console-host.clickable{cursor:pointer}.console-host.console-client-type-vmware{position:relative}\n"], dependencies: [{ kind: "component", type: ConsoleStatusComponent, selector: "cf-console-status", inputs: ["status"], outputs: ["reconnectRequest"] }] });
1507
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ConsoleTileComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1508
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.5", type: ConsoleTileComponent, isStandalone: true, selector: "cf-console-tile", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clicked: "clicked", connectionStatus: "connectionStatus", reconnectRequest: "reconnectRequest" }, viewQueries: [{ propertyName: "consoleHostElement", first: true, predicate: ["consoleHost"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"console-tile-component\">\n <cf-console-status [status]=\"consoleClient?.connectionStatus()\"\n (reconnectRequest)=\"reconnectRequest.emit(this.config())\"></cf-console-status>\n\n <div #consoleHost [id]=\"consoleHostElementId\" class=\"console-host\"\n [class.clickable]=\"consoleClient?.connectionStatus() == 'connected'\"\n [class.console-client-type-vnc]=\"consoleClientType() == 'vnc'\"\n [class.console-client-type-vmware]=\"consoleClientType() == 'vmware'\" (click)=\"clicked.emit(config())\">\n </div>\n</div>\n", styles: ["::ng-deep canvas{cursor:not-allowed!important;pointer-events:none!important;width:100%!important;height:100%!important}.console-tile-component{height:100%;width:100%;max-height:100%;max-width:100%}.console-host{max-width:100%;max-height:100%;width:100%;aspect-ratio:16/9;margin:0 auto;overflow:hidden}.console-host.clickable{cursor:pointer}.console-host.console-client-type-vmware{position:relative}.console-host .feedback-container{display:none!important}\n"], dependencies: [{ kind: "component", type: ConsoleStatusComponent, selector: "cf-console-status", inputs: ["status"], outputs: ["reconnectRequest"] }] });
1690
1509
  }
1691
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleTileComponent, decorators: [{
1510
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ConsoleTileComponent, decorators: [{
1692
1511
  type: Component,
1693
1512
  args: [{ selector: 'cf-console-tile', imports: [
1694
1513
  ConsoleStatusComponent
1695
- ], template: "<div class=\"console-tile-component\">\n <cf-console-status [status]=\"consoleClient?.connectionStatus()\"\n (reconnectRequest)=\"reconnectRequest.emit(this.config())\"></cf-console-status>\n\n <div #consoleHost [id]=\"consoleHostElementId\" class=\"console-host\"\n [class.clickable]=\"consoleClient?.connectionStatus() == 'connected'\"\n [class.console-client-type-vnc]=\"consoleClientType() == 'vnc'\"\n [class.console-client-type-vmware]=\"consoleClientType() == 'vmware'\" (click)=\"clicked.emit(config())\">\n </div>\n</div>\n", styles: ["::ng-deep canvas{cursor:not-allowed!important;pointer-events:none!important;width:100%!important;height:100%!important}.console-tile-component{height:100%;width:100%;max-height:100%;max-width:100%}.console-host{max-width:100%;max-height:100%;width:100%;aspect-ratio:16/9;margin:0 auto;overflow:hidden}.console-host.clickable{cursor:pointer}.console-host.console-client-type-vmware{position:relative}\n"] }]
1696
- }], ctorParameters: () => [] });
1514
+ ], template: "<div class=\"console-tile-component\">\n <cf-console-status [status]=\"consoleClient?.connectionStatus()\"\n (reconnectRequest)=\"reconnectRequest.emit(this.config())\"></cf-console-status>\n\n <div #consoleHost [id]=\"consoleHostElementId\" class=\"console-host\"\n [class.clickable]=\"consoleClient?.connectionStatus() == 'connected'\"\n [class.console-client-type-vnc]=\"consoleClientType() == 'vnc'\"\n [class.console-client-type-vmware]=\"consoleClientType() == 'vmware'\" (click)=\"clicked.emit(config())\">\n </div>\n</div>\n", styles: ["::ng-deep canvas{cursor:not-allowed!important;pointer-events:none!important;width:100%!important;height:100%!important}.console-tile-component{height:100%;width:100%;max-height:100%;max-width:100%}.console-host{max-width:100%;max-height:100%;width:100%;aspect-ratio:16/9;margin:0 auto;overflow:hidden}.console-host.clickable{cursor:pointer}.console-host.console-client-type-vmware{position:relative}.console-host .feedback-container{display:none!important}\n"] }]
1515
+ }], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], clicked: [{ type: i0.Output, args: ["clicked"] }], connectionStatus: [{ type: i0.Output, args: ["connectionStatus"] }], reconnectRequest: [{ type: i0.Output, args: ["reconnectRequest"] }], consoleHostElement: [{ type: i0.ViewChild, args: ["consoleHost", { isSignal: true }] }] } });
1516
+
1517
+ // ===BEGIN LICENSE===
1518
+ // Copyright 2025 Carnegie Mellon University. All rights reserved.
1519
+ // Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
1520
+ // ===END LICENSE===
1521
+
1522
+ // ===BEGIN LICENSE===
1523
+ // Copyright 2025 Carnegie Mellon University. All rights reserved.
1524
+ // Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
1525
+ // ===END LICENSE===
1526
+ class ClassOnHoverDirective {
1527
+ applyClasses = input.required(...(ngDevMode ? [{ debugName: "applyClasses" }] : /* istanbul ignore next */ []));
1528
+ directiveHost = inject(ElementRef);
1529
+ handleMouseEnter() {
1530
+ if (this.directiveHost?.nativeElement) {
1531
+ this.directiveHost.nativeElement.classList.add(this.applyClasses());
1532
+ }
1533
+ }
1534
+ handleMouseLeave() {
1535
+ if (this.directiveHost?.nativeElement) {
1536
+ this.directiveHost.nativeElement.classList.remove(this.applyClasses());
1537
+ }
1538
+ }
1539
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ClassOnHoverDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1540
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: ClassOnHoverDirective, isStandalone: true, selector: "[cfClassOnHover]", inputs: { applyClasses: { classPropertyName: "applyClasses", publicName: "applyClasses", isSignal: true, isRequired: true, transformFunction: null } }, host: { listeners: { "mouseenter": "handleMouseEnter()", "mouseleave": "handleMouseLeave()" } }, ngImport: i0 });
1541
+ }
1542
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ClassOnHoverDirective, decorators: [{
1543
+ type: Directive,
1544
+ args: [{ selector: '[cfClassOnHover]' }]
1545
+ }], propDecorators: { applyClasses: [{ type: i0.Input, args: [{ isSignal: true, alias: "applyClasses", required: true }] }], handleMouseEnter: [{
1546
+ type: HostListener,
1547
+ args: ["mouseenter"]
1548
+ }], handleMouseLeave: [{
1549
+ type: HostListener,
1550
+ args: ["mouseleave"]
1551
+ }] } });
1697
1552
 
1698
1553
  // ===BEGIN LICENSE===
1699
1554
  // Copyright 2025 Carnegie Mellon University. All rights reserved.
1700
1555
  // Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
1701
1556
  // ===END LICENSE===
1557
+ class ConsoleToolbarDefaultButtonComponent {
1558
+ clicked = output();
1559
+ disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
1560
+ label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
1561
+ isOngoing = input(false, ...(ngDevMode ? [{ debugName: "isOngoing" }] : /* istanbul ignore next */ []));
1562
+ picoCssService = inject(PicoCssService);
1563
+ hostElement = inject((ElementRef));
1564
+ async ngAfterViewInit() {
1565
+ const sheet = await this.picoCssService.loadStyleSheet();
1566
+ if (this.hostElement.nativeElement.shadowRoot) {
1567
+ this.hostElement.nativeElement.shadowRoot.adoptedStyleSheets = [sheet];
1568
+ }
1569
+ }
1570
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ConsoleToolbarDefaultButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1571
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ConsoleToolbarDefaultButtonComponent, isStandalone: true, selector: "cf-console-toolbar-default-button", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, isOngoing: { classPropertyName: "isOngoing", publicName: "isOngoing", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clicked: "clicked" }, ngImport: i0, template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n<div class=\"svg-button\" cfClassOnHover applyClasses=\"hovered\" [ariaDisabled]=\"disabled()\"\n [class.cursor-pointer]=\"!disabled()\" [class.disabled]=\"disabled()\" [class.ongoing]=\"isOngoing()\"\n (click)=\"!disabled() && clicked.emit()\">\n <div class=\"svg-container\">\n <ng-content></ng-content>\n </div>\n\n @if (label()) {\n <div class=\"button-label\">{{ label() }}</div>\n }\n</div>\n", styles: [":host{background-color:transparent;display:block}@keyframes glow-button-color{0%{color:var(--pico-muted-color);fill:var(--pico-muted-color);stroke:var(--pico-muted-color)}35%{color:#ee402e;fill:#ee402e;stroke:#ee402e}65%{color:#ee402e;fill:#ee402e;stroke:#ee402e}to{color:var(--pico-muted-color);fill:var(--pico-muted-color);stroke:var(--pico-muted-color)}}.svg-button{border:none;border-width:0!important;color:var(--pico-color);display:flex;font-weight:400;align-items:center;flex-direction:column;justify-content:center;margin:0}.svg-button:hover:not(.disabled){color:var(--pico-primary);fill:var(--pico-primary);stroke:var(--pico-primary);transition:all .3s ease}.svg-button.ongoing{animation:glow-button-color 2s infinite}.svg-button.disabled{color:var(--pico-muted-color)}.svg-container{height:var(--svg-icon-height);width:var(--svg-icon-width)}.button-label{font-size:.8rem;margin:0;text-align:center}.cursor-pointer{cursor:pointer}::ng-deep svg{height:56px;width:56px;padding:16px}::ng-deep svg,::ng-deep path,::ng-deep rect{fill:var(--pico-color);stroke:var(--pico-color)}::ng-deep svg.disabled,::ng-deep path.disabled,::ng-deep rect.disabled{fill:var(--pico-muted-color);stroke:var(--pico-muted-color)}::ng-deep svg:hover,::ng-deep path:hover,::ng-deep rect:hover{color:var(--pico-color);transition:fill .3s ease}::ng-deep .hovered:not(.disabled) svg,::ng-deep .hovered:not(.disabled) path,::ng-deep .hovered:not(.disabled) rect{fill:var(--pico-primary);stroke:var(--pico-primary);transition:all .3s ease}::ng-deep .ongoing:not(.disabled) svg,::ng-deep .ongoing:not(.disabled) path,::ng-deep .ongoing:not(.disabled) rect,::ng-deep .ongoing:not(.disabled) .svg-button{animation:glow-button-color 2s infinite}\n"], dependencies: [{ kind: "directive", type: ClassOnHoverDirective, selector: "[cfClassOnHover]", inputs: ["applyClasses"] }] });
1572
+ }
1573
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ConsoleToolbarDefaultButtonComponent, decorators: [{
1574
+ type: Component,
1575
+ args: [{ selector: 'cf-console-toolbar-default-button', imports: [ClassOnHoverDirective], template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n<div class=\"svg-button\" cfClassOnHover applyClasses=\"hovered\" [ariaDisabled]=\"disabled()\"\n [class.cursor-pointer]=\"!disabled()\" [class.disabled]=\"disabled()\" [class.ongoing]=\"isOngoing()\"\n (click)=\"!disabled() && clicked.emit()\">\n <div class=\"svg-container\">\n <ng-content></ng-content>\n </div>\n\n @if (label()) {\n <div class=\"button-label\">{{ label() }}</div>\n }\n</div>\n", styles: [":host{background-color:transparent;display:block}@keyframes glow-button-color{0%{color:var(--pico-muted-color);fill:var(--pico-muted-color);stroke:var(--pico-muted-color)}35%{color:#ee402e;fill:#ee402e;stroke:#ee402e}65%{color:#ee402e;fill:#ee402e;stroke:#ee402e}to{color:var(--pico-muted-color);fill:var(--pico-muted-color);stroke:var(--pico-muted-color)}}.svg-button{border:none;border-width:0!important;color:var(--pico-color);display:flex;font-weight:400;align-items:center;flex-direction:column;justify-content:center;margin:0}.svg-button:hover:not(.disabled){color:var(--pico-primary);fill:var(--pico-primary);stroke:var(--pico-primary);transition:all .3s ease}.svg-button.ongoing{animation:glow-button-color 2s infinite}.svg-button.disabled{color:var(--pico-muted-color)}.svg-container{height:var(--svg-icon-height);width:var(--svg-icon-width)}.button-label{font-size:.8rem;margin:0;text-align:center}.cursor-pointer{cursor:pointer}::ng-deep svg{height:56px;width:56px;padding:16px}::ng-deep svg,::ng-deep path,::ng-deep rect{fill:var(--pico-color);stroke:var(--pico-color)}::ng-deep svg.disabled,::ng-deep path.disabled,::ng-deep rect.disabled{fill:var(--pico-muted-color);stroke:var(--pico-muted-color)}::ng-deep svg:hover,::ng-deep path:hover,::ng-deep rect:hover{color:var(--pico-color);transition:fill .3s ease}::ng-deep .hovered:not(.disabled) svg,::ng-deep .hovered:not(.disabled) path,::ng-deep .hovered:not(.disabled) rect{fill:var(--pico-primary);stroke:var(--pico-primary);transition:all .3s ease}::ng-deep .ongoing:not(.disabled) svg,::ng-deep .ongoing:not(.disabled) path,::ng-deep .ongoing:not(.disabled) rect,::ng-deep .ongoing:not(.disabled) .svg-button{animation:glow-button-color 2s infinite}\n"] }]
1576
+ }], propDecorators: { clicked: [{ type: i0.Output, args: ["clicked"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], isOngoing: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOngoing", required: false }] }] } });
1577
+
1578
+ // ===BEGIN LICENSE===
1579
+ // Copyright 2025 Carnegie Mellon University. All rights reserved.
1580
+ // Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
1581
+ // ===END LICENSE===
1582
+ class ConsoleToolbarDefaultComponent {
1583
+ consoleContext = input.required(...(ngDevMode ? [{ debugName: "consoleContext" }] : /* istanbul ignore next */ []));
1584
+ // component state
1585
+ isClipboardDialogOpen = false;
1586
+ isKeyboardDialogOpen = false;
1587
+ isNetworkDialogOpen = false;
1588
+ isPowerDialogOpen = false;
1589
+ isSettingsDialogOpen = false;
1590
+ keyboardInputText = model("", ...(ngDevMode ? [{ debugName: "keyboardInputText" }] : /* istanbul ignore next */ []));
1591
+ // protected readonly selected = model<string>();
1592
+ // services and viewkids
1593
+ cfConfig = inject(ConsoleForgeConfig);
1594
+ clipboardService = inject(ClipboardService);
1595
+ clipboardTextInput = viewChild("clipboardText", ...(ngDevMode ? [{ debugName: "clipboardTextInput" }] : /* istanbul ignore next */ []));
1596
+ picoCssService = inject(PicoCssService);
1597
+ hostElement = inject((ElementRef));
1598
+ // trying this out. when the network configuration (which is passed into the library by the end dev)
1599
+ // changes, we need to update the model that holds the current network, so let's make a computed
1600
+ // signal that represents that change so we can be sure our effect only happens when we want it to
1601
+ // private readonly currentNetwork = (() => this.consoleContext()?.networks?.config()?.current || "");
1602
+ constructor() {
1603
+ // when the network config is changed, select the current network if exists
1604
+ // effect(() => {
1605
+ // this.selectedNetworkForChange.update(() => this.currentNetwork());
1606
+ // });
1607
+ }
1608
+ async ngAfterViewInit() {
1609
+ // apply pico to this component
1610
+ const sheet = await this.picoCssService.loadStyleSheet();
1611
+ if (this.hostElement.nativeElement.shadowRoot) {
1612
+ this.hostElement.nativeElement.shadowRoot.adoptedStyleSheets = [sheet];
1613
+ }
1614
+ }
1615
+ handleChangeToolbarPosition(position) {
1616
+ this.consoleContext().userSettings.patch({ toolbar: { dockTo: position } });
1617
+ }
1618
+ handleClipboardDialogOpenClose(isOpen) {
1619
+ this.isClipboardDialogOpen = isOpen;
1620
+ if (isOpen) {
1621
+ // Is there a better way to ensure .focus works other than timeouting it?
1622
+ setTimeout(() => this.clipboardTextInput()?.nativeElement?.focus(), 100);
1623
+ }
1624
+ }
1625
+ handleClipboardCopyLastText(text) {
1626
+ this.clipboardService.copyText(text, false);
1627
+ }
1628
+ handleNetworkChangeRequested(request) {
1629
+ if (!request.network) {
1630
+ this.consoleContext().networks.disconnectRequested({ nic: request.nic });
1631
+ }
1632
+ else {
1633
+ this.consoleContext().networks.connectionRequested(request);
1634
+ }
1635
+ this.isNetworkDialogOpen = false;
1636
+ }
1637
+ handleNetworkDisconnectAllRequested() {
1638
+ this.consoleContext().networks.disconnectRequested({});
1639
+ this.isNetworkDialogOpen = false;
1640
+ }
1641
+ handleNetworkDialogOpenClose(isOpen) {
1642
+ this.isNetworkDialogOpen = isOpen;
1643
+ }
1644
+ handleRecordToggle() {
1645
+ if (this.consoleContext().state.activeConsoleRecording()) {
1646
+ this.consoleContext().console.recordScreenStop();
1647
+ }
1648
+ else {
1649
+ this.consoleContext().console.recordScreenStart();
1650
+ }
1651
+ }
1652
+ async handleSendClipboardText(event, text) {
1653
+ event.preventDefault();
1654
+ if (text) {
1655
+ await this.consoleContext().clipboard.sendTextToConsoleClipboard(text);
1656
+ }
1657
+ this.isClipboardDialogOpen = false;
1658
+ }
1659
+ async handlSendKeyboardCtrlAltDel() {
1660
+ await this.consoleContext().console.sendCtrlAltDel();
1661
+ this.isKeyboardDialogOpen = false;
1662
+ }
1663
+ async handleSendKeyboardInput(event, text) {
1664
+ // prevent the form submit default
1665
+ event.preventDefault();
1666
+ if (text) {
1667
+ await this.consoleContext().console.sendKeyboardInput(text);
1668
+ }
1669
+ this.keyboardInputText.update(() => "");
1670
+ this.isKeyboardDialogOpen = false;
1671
+ }
1672
+ async handleSendPowerRequest(request) {
1673
+ await this.consoleContext().console.sendPowerRequest(request);
1674
+ this.isPowerDialogOpen = false;
1675
+ }
1676
+ handleSettingsDialogOpenClose(isOpen) {
1677
+ this.isSettingsDialogOpen = isOpen;
1678
+ }
1679
+ handleSettingsAllowLocalClipboardWrite(allow) {
1680
+ this.consoleContext().userSettings.patch({ console: { allowCopyToLocalClipboard: allow } });
1681
+ }
1682
+ handleSettingsAttemptRemoteSessionResize(attempt) {
1683
+ this.consoleContext().userSettings.patch({ console: { attemptRemoteSessionResize: attempt } });
1684
+ }
1685
+ handleSettingsScaleToContainerHostSize(scaleToCanvasHostSize) {
1686
+ this.consoleContext().userSettings.patch({ console: { scaleToCanvasHostSize } });
1687
+ }
1688
+ handleToolbarThemeChange(theme) {
1689
+ this.consoleContext().userSettings.patch({ toolbar: { preferTheme: theme } });
1690
+ }
1691
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ConsoleToolbarDefaultComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1692
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ConsoleToolbarDefaultComponent, isStandalone: true, selector: "cf-console-toolbar-default", inputs: { consoleContext: { classPropertyName: "consoleContext", publicName: "consoleContext", isSignal: true, isRequired: true, transformFunction: null }, keyboardInputText: { classPropertyName: "keyboardInputText", publicName: "keyboardInputText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { keyboardInputText: "keyboardInputTextChange" }, viewQueries: [{ propertyName: "clipboardTextInput", first: true, predicate: ["clipboardText"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n@if (consoleContext()) {\n<div class=\"toolbar-container\" cfApplyToolbarTheme\n [class.horizontal]=\"consoleContext().userSettings.settings().toolbar.dockTo == 'top' || consoleContext().userSettings.settings().toolbar.dockTo == 'bottom' \">\n <div class=\"button-container\">\n <cf-console-toolbar-default-button label=\"Settings\" (clicked)=\"handleSettingsDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M12.0002 8C9.79111 8 8.00024 9.79086 8.00024 12C8.00024 14.2091 9.79111 16 12.0002 16C14.2094 16 16.0002 14.2091 16.0002 12C16.0002 9.79086 14.2094 8 12.0002 8ZM10.0002 12C10.0002 10.8954 10.8957 10 12.0002 10C13.1048 10 14.0002 10.8954 14.0002 12C14.0002 13.1046 13.1048 14 12.0002 14C10.8957 14 10.0002 13.1046 10.0002 12Z\"\n fill=\"#000000\"></path>\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M11.2867 0.5C9.88583 0.5 8.6461 1.46745 8.37171 2.85605L8.29264 3.25622C8.10489 4.20638 7.06195 4.83059 6.04511 4.48813L5.64825 4.35447C4.32246 3.90796 2.83873 4.42968 2.11836 5.63933L1.40492 6.83735C0.67773 8.05846 0.954349 9.60487 2.03927 10.5142L2.35714 10.7806C3.12939 11.4279 3.12939 12.5721 2.35714 13.2194L2.03927 13.4858C0.954349 14.3951 0.67773 15.9415 1.40492 17.1626L2.11833 18.3606C2.83872 19.5703 4.3225 20.092 5.64831 19.6455L6.04506 19.5118C7.06191 19.1693 8.1049 19.7935 8.29264 20.7437L8.37172 21.1439C8.6461 22.5325 9.88584 23.5 11.2867 23.5H12.7136C14.1146 23.5 15.3543 22.5325 15.6287 21.1438L15.7077 20.7438C15.8954 19.7936 16.9384 19.1693 17.9553 19.5118L18.3521 19.6455C19.6779 20.092 21.1617 19.5703 21.8821 18.3606L22.5955 17.1627C23.3227 15.9416 23.046 14.3951 21.9611 13.4858L21.6432 13.2194C20.8709 12.5722 20.8709 11.4278 21.6432 10.7806L21.9611 10.5142C23.046 9.60489 23.3227 8.05845 22.5955 6.83732L21.8821 5.63932C21.1617 4.42968 19.678 3.90795 18.3522 4.35444L17.9552 4.48814C16.9384 4.83059 15.8954 4.20634 15.7077 3.25617L15.6287 2.85616C15.3543 1.46751 14.1146 0.5 12.7136 0.5H11.2867ZM10.3338 3.24375C10.4149 2.83334 10.7983 2.5 11.2867 2.5H12.7136C13.2021 2.5 13.5855 2.83336 13.6666 3.24378L13.7456 3.64379C14.1791 5.83811 16.4909 7.09167 18.5935 6.38353L18.9905 6.24984C19.4495 6.09527 19.9394 6.28595 20.1637 6.66264L20.8771 7.86064C21.0946 8.22587 21.0208 8.69271 20.6764 8.98135L20.3586 9.24773C18.6325 10.6943 18.6325 13.3057 20.3586 14.7523L20.6764 15.0186C21.0208 15.3073 21.0946 15.7741 20.8771 16.1394L20.1637 17.3373C19.9394 17.714 19.4495 17.9047 18.9905 17.7501L18.5936 17.6164C16.4909 16.9082 14.1791 18.1618 13.7456 20.3562L13.6666 20.7562C13.5855 21.1666 13.2021 21.5 12.7136 21.5H11.2867C10.7983 21.5 10.4149 21.1667 10.3338 20.7562L10.2547 20.356C9.82113 18.1617 7.50931 16.9082 5.40665 17.6165L5.0099 17.7501C4.55092 17.9047 4.06104 17.714 3.83671 17.3373L3.1233 16.1393C2.9058 15.7741 2.97959 15.3073 3.32398 15.0186L3.64185 14.7522C5.36782 13.3056 5.36781 10.6944 3.64185 9.24779L3.32398 8.98137C2.97959 8.69273 2.9058 8.2259 3.1233 7.86067L3.83674 6.66266C4.06106 6.28596 4.55093 6.09528 5.0099 6.24986L5.40676 6.38352C7.50938 7.09166 9.82112 5.83819 10.2547 3.64392L10.3338 3.24375Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if(consoleContext().state.isManualReconnectAvailable())\n {\n <cf-console-toolbar-default-button label=\"Reconnect\"\n (clicked)=\"consoleContext().console.sendReconnectRequest()\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C16.3556 22 20.0584 19.2159 21.4307 15.3332C21.6148 14.8125 21.3418 14.2412 20.8211 14.0572C20.3004 13.8731 19.7291 14.146 19.545 14.6668C18.4463 17.7753 15.4817 20 12 20C7.58172 20 4 16.4183 4 12C4 7.58172 7.58172 4 12 4C13.5516 4 14.8662 4.56117 16.1162 5.4406C16.9569 6.03212 17.7348 6.74106 18.5242 7.5H15.5C14.9477 7.5 14.5 7.94772 14.5 8.5C14.5 9.05228 14.9477 9.5 15.5 9.5H21C21.5523 9.5 22 9.05228 22 8.5V3C22 2.44772 21.5523 2 21 2C20.4477 2 20 2.44772 20 3V6.14371C19.1517 5.32583 18.2456 4.49337 17.267 3.80489C15.7949 2.76916 14.0847 2 12 2Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (!consoleContext().state.isViewOnly() && consoleContext().state.isConnected()) {\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button label=\"Keyboard\" (clicked)=\"isKeyboardDialogOpen = true\">\n <svg fill=\"#000000\" viewBox=\"0 0 1920 1920\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M1807.059 1637.706c0 31.059-25.299 56.47-56.47 56.47H169.411c-31.172 0-56.47-25.411-56.47-56.47v-903.53c0-31.058 25.298-56.47 56.47-56.47h1581.176c31.172 0 56.47 25.412 56.47 56.47v903.53Zm-56.47-1072.941h-729.262c14.908-86.965 65.958-113.506 133.384-147.163 89.336-44.611 200.583-100.291 200.583-304.602h-112.941c0 134.513-57.939 163.426-138.24 203.633-80.301 40.094-177.544 90.24-196.518 248.132H169.412C76.009 564.765 0 640.775 0 734.176v903.53c0 93.402 76.01 169.412 169.412 169.412h1581.176c93.403 0 169.412-76.01 169.412-169.412v-903.53c0-93.402-76.01-169.411-169.412-169.411Zm-564.707 677.647H734.118c-31.172 0-56.47 25.299-56.47 56.47v112.942c0 31.171 25.298 56.47 56.47 56.47h451.764c31.172 0 56.47-25.299 56.47-56.47v-112.942c0-31.171-25.298-56.47-56.47-56.47m338.824 0h-112.941c-31.172 0-56.47 25.299-56.47 56.47v112.942c0 31.171 25.298 56.47 56.47 56.47h112.94c31.173 0 56.471-25.299 56.471-56.47v-112.942c0-31.171-25.298-56.47-56.47-56.47m-1016.47 0H395.293c-31.172 0-56.47 25.299-56.47 56.47v112.942c0 31.171 25.298 56.47 56.47 56.47h112.941c31.172 0 56.47-25.299 56.47-56.47v-112.942c0-31.171-25.298-56.47-56.47-56.47m0-338.824h-112.94c-31.173 0-56.471 25.3-56.471 56.47V1073c0 31.172 25.298 56.47 56.47 56.47h112.941c31.172 0 56.47-25.298 56.47-56.47V960.059c0-31.172-25.298-56.47-56.47-56.47m225.883 225.882h112.94c31.173 0 56.471-25.3 56.471-56.471V960.059c0-31.172-25.298-56.47-56.47-56.47h-112.94c-31.172 0-56.47 25.298-56.47 56.47V1073c0 31.172 25.298 56.47 56.47 56.47m451.764-225.882h-112.94c-31.173 0-56.471 25.3-56.471 56.47V1073c0 31.172 25.298 56.47 56.47 56.47h112.941c31.172 0 56.47-25.298 56.47-56.47V960.059c0-31.172-25.298-56.47-56.47-56.47m338.824 0h-112.941c-31.172 0-56.47 25.298-56.47 56.47V1073c0 31.172 25.298 56.47 56.47 56.47h112.94c31.173 0 56.471-25.298 56.471-56.47V960.059c0-31.172-25.298-56.47-56.47-56.47\"\n fill-rule=\"evenodd\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if(!cfConfig.disabledFeatures.clipboard) {\n <cf-console-toolbar-default-button [disabled]=\"!consoleContext().state.isConnected()\" label=\"Clipboard\"\n (clicked)=\"handleClipboardDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" preserveAspectRatio=\"none\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M19.5 16.5L19.5 4.5L18.75 3.75H9L8.25 4.5L8.25 7.5L5.25 7.5L4.5 8.25V20.25L5.25 21H15L15.75 20.25V17.25H18.75L19.5 16.5ZM15.75 15.75L15.75 8.25L15 7.5L9.75 7.5V5.25L18 5.25V15.75H15.75ZM6 9L14.25 9L14.25 19.5L6 19.5L6 9Z\"\n fill=\"#080341\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (consoleContext().networks.config()?.networks?.length) {\n <cf-console-toolbar-default-button label=\"Networks ({{ consoleContext().networks.config()?.networks?.length }})\"\n (clicked)=\"handleNetworkDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M3 12H21M12 8V12M6.5 12V16M17.5 12V16M10.1 8H13.9C14.4601 8 14.7401 8 14.954 7.89101C15.1422 7.79513 15.2951 7.64215 15.391 7.45399C15.5 7.24008 15.5 6.96005 15.5 6.4V4.6C15.5 4.03995 15.5 3.75992 15.391 3.54601C15.2951 3.35785 15.1422 3.20487 14.954 3.10899C14.7401 3 14.4601 3 13.9 3H10.1C9.53995 3 9.25992 3 9.04601 3.10899C8.85785 3.20487 8.70487 3.35785 8.60899 3.54601C8.5 3.75992 8.5 4.03995 8.5 4.6V6.4C8.5 6.96005 8.5 7.24008 8.60899 7.45399C8.70487 7.64215 8.85785 7.79513 9.04601 7.89101C9.25992 8 9.53995 8 10.1 8ZM15.6 21H19.4C19.9601 21 20.2401 21 20.454 20.891C20.6422 20.7951 20.7951 20.6422 20.891 20.454C21 20.2401 21 19.9601 21 19.4V17.6C21 17.0399 21 16.7599 20.891 16.546C20.7951 16.3578 20.6422 16.2049 20.454 16.109C20.2401 16 19.9601 16 19.4 16H15.6C15.0399 16 14.7599 16 14.546 16.109C14.3578 16.2049 14.2049 16.3578 14.109 16.546C14 16.7599 14 17.0399 14 17.6V19.4C14 19.9601 14 20.2401 14.109 20.454C14.2049 20.6422 14.3578 20.7951 14.546 20.891C14.7599 21 15.0399 21 15.6 21ZM4.6 21H8.4C8.96005 21 9.24008 21 9.45399 20.891C9.64215 20.7951 9.79513 20.6422 9.89101 20.454C10 20.2401 10 19.9601 10 19.4V17.6C10 17.0399 10 16.7599 9.89101 16.546C9.79513 16.3578 9.64215 16.2049 9.45399 16.109C9.24008 16 8.96005 16 8.4 16H4.6C4.03995 16 3.75992 16 3.54601 16.109C3.35785 16.2049 3.20487 16.3578 3.10899 16.546C3 16.7599 3 17.0399 3 17.6V19.4C3 19.9601 3 20.2401 3.10899 20.454C3.20487 20.6422 3.35785 20.7951 3.54601 20.891C3.75992 21 4.03995 21 4.6 21Z\"\n stroke=\"#000000\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (consoleContext().console.supportedFeatures().powerManagement) {\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button label=\"Power\" (clicked)=\"isPowerDialogOpen = true\">\n <svg width=\"800px\" height=\"800px\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M13 3C13 2.44772 12.5523 2 12 2C11.4477 2 11 2.44772 11 3V13C11 13.5523 11.4477 14 12 14C12.5523 14 13 13.5523 13 13V3Z\"\n fill=\"none\" />\n <path\n d=\"M6.2798 6.70707C6.67031 6.31653 6.67028 5.68337 6.27973 5.29286C5.88919 4.90235 5.25603 4.90238 4.86552 5.29293C3.09635 7.06226 2 9.49298 2 12.1764C2 17.6204 6.49591 22 12 22C17.5041 22 22 17.6204 22 12.1764C22 9.49298 20.9036 7.06226 19.1345 5.29293C18.744 4.90238 18.1108 4.90235 17.7203 5.29286C17.3297 5.68337 17.3297 6.31653 17.7202 6.70707C19.1338 8.12083 20 10.0503 20 12.1764C20 16.4787 16.437 20 12 20C7.56296 20 4 16.4787 4 12.1764C4 10.0503 4.86618 8.12083 6.2798 6.70707Z\"\n fill=\"none\" />\n </svg>\n </cf-console-toolbar-default-button> }\n }\n\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button (clicked)=\"consoleContext().console.copyScreenshot()\"\n [disabled]=\"!consoleContext().state.isConnected()\" label=\"Screenshot\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M9.15023 3.01742C9.13605 3.03985 9.12278 3.0676 9.11298 3.09958C9.11044 3.10789 9.10778 3.11617 9.10502 3.12442L8.36963 5.31787C8.23301 5.72537 7.85129 6 7.4215 6H3C2.44772 6 2 6.44772 2 7V20C2 20.5523 2.44771 21 3 21H21C21.5523 21 22 20.5523 22 20V7C22 6.44771 21.5523 6 21 6H16.331C15.9011 6 15.5194 5.72528 15.3828 5.31769L14.6479 3.12423C14.6452 3.11605 14.6425 3.10783 14.64 3.09958C14.6302 3.0676 14.6169 3.03985 14.6027 3.01742C14.5986 3.01089 14.5946 3.00509 14.5908 3H9.16221C9.1584 3.00509 9.15437 3.01089 9.15023 3.01742ZM7.20525 2.49911C7.43535 1.76672 8.10563 1 9.06392 1H14.6891C15.6474 1 16.3177 1.76679 16.5478 2.49922L17.0506 4H21C22.6569 4 24 5.34315 24 7V20C24 21.6569 22.6569 23 21 23H3C1.34315 23 0 21.6569 0 20V7C0 5.34315 1.34315 4 3 4H6.70206L7.20525 2.49911ZM7 13C7 10.2386 9.23858 8 12 8C14.7614 8 17 10.2386 17 13C17 15.7614 14.7614 18 12 18C9.23858 18 7 15.7614 7 13ZM12 10C10.3431 10 9 11.3431 9 13C9 14.6569 10.3431 16 12 16C13.6569 16 15 14.6569 15 13C15 11.3431 13.6569 10 12 10Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if (!cfConfig.disabledFeatures.consoleScreenRecord) {\n <cf-console-toolbar-default-button (clicked)=\"handleRecordToggle()\"\n [disabled]=\"!consoleContext().state.isRecordingAvailable()\"\n [isOngoing]=\"!!consoleContext().state.activeConsoleRecording()\" label=\"Record\">\n @if (!consoleContext().state.activeConsoleRecording()) {\n <svg viewBox=\"0 0 20 20\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\" fill=\"#000000\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <g id=\"Dribbble-Light-Preview\" transform=\"translate(-100.000000, -3879.000000)\" fill=\"#000000\">\n <g id=\"icons\" transform=\"translate(56.000000, 160.000000)\">\n <path\n d=\"M56,3719 L56,3721 L62,3721 L62,3727 L64,3727 L64,3719 L56,3719 Z M58,3729.151 C58,3726.942 56.209,3725.151 54,3725.151 C51.791,3725.151 50,3726.942 50,3729.151 C50,3731.36 51.791,3733.151 54,3733.151 C56.209,3733.151 58,3731.36 58,3729.151 L58,3729.151 Z M62,3737 L56,3737 L56,3739 L64,3739 L64,3731 L62,3731 L62,3737 Z M46,3731 L44,3731 L44,3739 L52,3739 L52,3737 L46,3737 L46,3731 Z M46,3727 L44,3727 L44,3719 L52,3719 L52,3721 L46,3721 L46,3727 Z\"\n id=\"record-[#979]\"> </path>\n </g>\n </g>\n </g>\n </g>\n </svg>\n } @else {\n <svg viewBox=\"0 -0.5 21 21\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\" fill=\"#000000\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <g id=\"Dribbble-Light-Preview\" transform=\"translate(-59.000000, -440.000000)\" fill=\"#000000\">\n <g id=\"icons\" transform=\"translate(56.000000, 160.000000)\">\n <path\n d=\"M9.3,294 L17.7,294 L17.7,286 L9.3,286 L9.3,294 Z M15.6,280 L15.6,282 L21.9,282 L21.9,288 L24,288 L24,280 L15.6,280 Z M21.9,298 L15.6,298 L15.6,300 L24,300 L24,292 L21.9,292 L21.9,298 Z M5.1,292 L3,292 L3,300 L11.4,300 L11.4,298 L5.1,298 L5.1,292 Z M5.1,288 L3,288 L3,280 L11.4,280 L11.4,282 L5.1,282 L5.1,288 Z\"\n id=\"stop-[#1470]\"> </path>\n </g>\n </g>\n </g>\n </g>\n </svg>\n }\n </cf-console-toolbar-default-button>\n }\n\n <cf-console-toolbar-default-button (clicked)=\"consoleContext().console.toggleFullscreen()\" label=\"Fullscreen\">\n @if (consoleContext().state.isFullscreenAvailable()) {\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M4 2C2.89543 2 2 2.89543 2 4V8C2 8.55228 2.44772 9 3 9C3.55228 9 4 8.55228 4 8V4H8C8.55228 4 9 3.55228 9 3C9 2.44772 8.55228 2 8 2H4Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M20 2C21.1046 2 22 2.89543 22 4V8C22 8.55228 21.5523 9 21 9C20.4477 9 20 8.55228 20 8V4H16C15.4477 4 15 3.55228 15 3C15 2.44772 15.4477 2 16 2H20Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M20 22C21.1046 22 22 21.1046 22 20V16C22 15.4477 21.5523 15 21 15C20.4477 15 20 15.4477 20 16V20H16C15.4477 20 15 20.4477 15 21C15 21.5523 15.4477 22 16 22H20Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M2 20C2 21.1046 2.89543 22 4 22H8C8.55228 22 9 21.5523 9 21C9 20.4477 8.55228 20 8 20H4V16C4 15.4477 3.55228 15 3 15C2.44772 15 2 15.4477 2 16V20Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n } @else {\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M7 9C8.10457 9 9 8.10457 9 7V3C9 2.44772 8.55228 2 8 2C7.44772 2 7 2.44772 7 3V7H3C2.44772 7 2 7.44772 2 8C2 8.55228 2.44772 9 3 9H7Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M17 9C15.8954 9 15 8.10457 15 7V3C15 2.44772 15.4477 2 16 2C16.5523 2 17 2.44772 17 3V7H21C21.5523 7 22 7.44772 22 8C22 8.55228 21.5523 9 21 9H17Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M17 15C15.8954 15 15 15.8954 15 17V21C15 21.5523 15.4477 22 16 22C16.5523 22 17 21.5523 17 21V17H21C21.5523 17 22 16.5523 22 16C22 15.4477 21.5523 15 21 15H17Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M9 17C9 15.8954 8.10457 15 7 15H3C2.44772 15 2 15.4477 2 16C2 16.5523 2.44772 17 3 17H7V21C7 21.5523 7.44772 22 8 22C8.55228 22 9 21.5523 9 21V17Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n }\n </cf-console-toolbar-default-button>\n </div>\n\n <dialog [open]=\"isClipboardDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleClipboardDialogOpenClose(false)\"></button>\n <p>\n <strong>Clipboard</strong>\n </p>\n </header>\n\n @if (consoleContext().console.supportedFeatures().clipboardRemoteWrite) {\n <div class=\"dialog-section\">\n <h2>Send Text to Remote Clipboard</h2>\n <form (submit)=\"handleSendClipboardText($event, clipboardText.value)\">\n <fieldset role=\"group\">\n <input type=\"text\" class=\"clipboard-text\" aria-label=\"Clipboard text\"\n placeholder=\"Enter text to send to the remote clipboard\" #clipboardText autofocus>\n <button type=\"submit\"\n [disabled]=\"!clipboardText.value || !consoleContext().state.isConnected\">Send</button>\n </fieldset>\n </form>\n </div>\n }\n\n <div class=\"dialog-section\">\n <h2>Remote Clipboard Content</h2>\n <form (submit)=\"handleClipboardCopyLastText(consoleLastClipboardText.value)\">\n <fieldset role=\"group\">\n <input type=\"text\" id=\"textFromConsoleClipboard\" name=\"textFromConsoleClipboard\"\n class=\"clipboard-text\" aria-describedby=\"textFromConsoleClipboard-helper\"\n aria-label=\"Clipboard text\" disabled\n [value]=\"consoleContext().clipboard.consoleClipboardText()\"\n placeholder=\"Text on the remote will appear here\" #consoleLastClipboardText>\n <button type=\"submit\" [disabled]=\"!consoleLastClipboardText.value\">Copy</button>\n </fieldset>\n @if(consoleContext().userSettings.settings().console.allowCopyToLocalClipboard &&\n consoleContext().console.supportedFeatures().clipboardAutomaticLocalCopy)\n {\n <small id=\"textFromConsoleClipboard-helper\">\n Copied text on the remote machine will automatically copy to your local clipboard.\n Disable this in Settings.\n </small>\n }\n </form>\n </div>\n </article>\n </dialog>\n\n <dialog [open]=\"isKeyboardDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"isKeyboardDialogOpen = false\"></button>\n <p>\n <strong>Send Keystrokes</strong>\n </p>\n </header>\n\n <div class=\"dialog-section\">\n <h2>Send Keystrokes to Console</h2>\n <form (submit)=\"handleSendKeyboardInput($event, keyboardInputText())\">\n <fieldset role=\"group\">\n <input type=\"text\" id=\"keyboardInputText\" name=\"keyboardInputText\" class=\"keyboard-text\"\n aria-label=\"Keyboard text\" placeholder=\"Enter text to send as keyboard input to the console\"\n autofocus [(ngModel)]=\"keyboardInputText\">\n <button type=\"submit\"\n [disabled]=\"!keyboardInputText() || !consoleContext().state.isConnected\">Send</button>\n </fieldset>\n </form>\n </div>\n\n <div class=\"dialog-section\">\n <h2>Special Key Combinations</h2>\n\n <div class=\"dialog-button-group\">\n <button type=\"button\" aria-label=\"Send Ctrl+Alt+Delete\" (click)=\"handlSendKeyboardCtrlAltDel()\">\n Ctrl + Alt + Delete\n </button>\n </div>\n </div>\n </article>\n </dialog>\n\n <dialog [open]=\"isNetworkDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleNetworkDialogOpenClose(false)\"></button>\n <p>\n <strong>Networks</strong>\n </p>\n </header>\n\n <form>\n @for (nic of consoleContext().networks.config()?.nics; track nic)\n {\n <label for=\"nic-{{ nic }}-select\">{{ nic }}</label>\n <fieldset role=\"group\">\n <select #availableNetworksSelect name=\"nic-{{ nic }}-select\"\n aria-label=\"Select a network to connect to\">\n\n @if (!cfConfig.disabledFeatures.networkDisconnection)\n {\n <option [selected]=\"!consoleContext().networks.config()?.currentConnections?.[nic]\" value=\"\">\n [Disconnected]\n </option>\n }\n\n @for(network of consoleContext().networks.config()?.networks; track network) {\n <option [value]=\"network\"\n [selected]=\"consoleContext().networks.config()?.currentConnections?.[nic] === network\">\n {{ network }}\n </option>\n }\n </select>\n\n <button type=\"button\"\n (click)=\"handleNetworkChangeRequested({ network: availableNetworksSelect.value, nic: nic })\">\n {{ availableNetworksSelect.value ? \"Connect\" : \"Disconnect\" }}\n </button>\n </fieldset>\n }\n\n @if (!cfConfig.disabledFeatures.networkDisconnection)\n {\n <hr />\n <div class=\"dialog-button-group\">\n <button class=\"secondary\" type=\"button\" (click)=\"handleNetworkDisconnectAllRequested()\">\n Disconnect All Network Interfaces\n </button>\n </div>\n }\n </form>\n </article>\n </dialog>\n\n <dialog [open]=\"isPowerDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"isPowerDialogOpen = false\"></button>\n <p>\n <strong>Power</strong>\n </p>\n </header>\n\n <div class=\"dialog-button-group\">\n <button type=\"button\" (click)=\"handleSendPowerRequest('reboot')\">Request Reboot</button>\n <button type=\"button\" (click)=\"handleSendPowerRequest('shutdown')\">Request Shutdown</button>\n <hr />\n <button class=\"secondary\" type=\"button\" (click)=\"handleSendPowerRequest('rebootHard')\">\n Request Hard Reboot\n </button>\n </div>\n </article>\n </dialog>\n\n <dialog [open]=\"isSettingsDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleSettingsDialogOpenClose(false)\"></button>\n <p>\n <strong>Settings</strong>\n </p>\n </header>\n\n <div class=\"settings-form\">\n <div class=\"settings-behavior dialog-section\">\n <h4>Behavior</h4>\n <fieldset>\n <label>\n <input #inputAllowLocalClipboardWrite type=\"checkbox\" name=\"allowLocalClipboardWrite\"\n [checked]=\"consoleContext().userSettings.settings().console.allowCopyToLocalClipboard\"\n (change)=\"handleSettingsAllowLocalClipboardWrite(inputAllowLocalClipboardWrite.checked)\" />\n Allow the remote machine to copy text to my local clipboard\n </label>\n <label>\n <input #inputAttemptRemoteSessionResize type=\"checkbox\" name=\"attemptRemoteSessionResize\"\n [checked]=\"consoleContext().userSettings.settings().console.attemptRemoteSessionResize\"\n (change)=\"handleSettingsAttemptRemoteSessionResize(inputAttemptRemoteSessionResize.checked)\" />\n Attempt to resize the remote session to match local resolution\n </label>\n <label>\n <input #inputScaleToContainerSize type=\"checkbox\" name=\"scaleToContainerSize\"\n [checked]=\"consoleContext().userSettings.settings().console.scaleToCanvasHostSize\"\n (change)=\"handleSettingsScaleToContainerHostSize(inputScaleToContainerSize.checked)\" />\n Scale to maximum available size\n </label>\n </fieldset>\n </div>\n\n <div class=\"settings-toolbar-dock dialog-section\">\n <h4>Toolbar Position</h4>\n <div role=\"group\">\n <button (click)=\"handleChangeToolbarPosition('left')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'left'\">Left</button>\n <button (click)=\"handleChangeToolbarPosition('right')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'right'\">Right</button>\n <button (click)=\"handleChangeToolbarPosition('top')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'top'\">Top</button>\n <button (click)=\"handleChangeToolbarPosition('bottom')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'bottom'\">Bottom</button>\n </div>\n </div>\n\n <div class=\"settings-theme dialog-section\">\n <h4>Theme</h4>\n <div role=\"group\">\n <button (click)=\"handleToolbarThemeChange('light')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.preferTheme === 'light'\">Light</button>\n <button (click)=\"handleToolbarThemeChange('dark')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.preferTheme === 'dark'\">Dark</button>\n <button (click)=\"handleToolbarThemeChange(undefined)\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.preferTheme === undefined\">\n My Default\n </button>\n </div>\n </div>\n </div>\n </article>\n </dialog>\n</div>\n}\n", styles: [":host{display:block;height:100%;width:100%;max-width:100%}fieldset legend{font-weight:700}.toolbar-container{background-color:var(--pico-background-color);padding:4px;height:100%;display:flex;align-items:center;justify-content:center}.toolbar-container .button-container{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px}.toolbar-container .buttons-divider{border-top:1px solid var(--pico-color);margin:.25rem 0;width:100%}.toolbar-container.horizontal{width:100%}.toolbar-container.horizontal .button-container{flex-direction:row}.toolbar-container.horizontal .buttons-divider{align-self:stretch;border-left:1px solid var(--pico-color);height:auto;margin:0 1rem;width:1px}.toolbar-position-buttons{display:flex;gap:4px}.toolbar-position-buttons button{flex-grow:1}.settings-toolbar-dock{margin-top:1rem}dialog h2{font-size:1.1rem;font-weight:700}dialog small{font-size:.8rem}dialog .dialog-section:not(:last-of-type){margin-bottom:2rem}dialog .dialog-button-group button{display:block;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: ApplyToolbarThemeDirective, selector: "[cfApplyToolbarTheme]" }, { kind: "component", type: ConsoleToolbarDefaultButtonComponent, selector: "cf-console-toolbar-default-button", inputs: ["disabled", "label", "isOngoing"], outputs: ["clicked"] }], encapsulation: i0.ViewEncapsulation.ShadowDom });
1693
+ }
1694
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ConsoleToolbarDefaultComponent, decorators: [{
1695
+ type: Component,
1696
+ args: [{ selector: 'cf-console-toolbar-default', imports: [
1697
+ FormsModule,
1698
+ ApplyToolbarThemeDirective,
1699
+ ConsoleToolbarDefaultButtonComponent
1700
+ ], standalone: true, encapsulation: ViewEncapsulation.ShadowDom, template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n@if (consoleContext()) {\n<div class=\"toolbar-container\" cfApplyToolbarTheme\n [class.horizontal]=\"consoleContext().userSettings.settings().toolbar.dockTo == 'top' || consoleContext().userSettings.settings().toolbar.dockTo == 'bottom' \">\n <div class=\"button-container\">\n <cf-console-toolbar-default-button label=\"Settings\" (clicked)=\"handleSettingsDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M12.0002 8C9.79111 8 8.00024 9.79086 8.00024 12C8.00024 14.2091 9.79111 16 12.0002 16C14.2094 16 16.0002 14.2091 16.0002 12C16.0002 9.79086 14.2094 8 12.0002 8ZM10.0002 12C10.0002 10.8954 10.8957 10 12.0002 10C13.1048 10 14.0002 10.8954 14.0002 12C14.0002 13.1046 13.1048 14 12.0002 14C10.8957 14 10.0002 13.1046 10.0002 12Z\"\n fill=\"#000000\"></path>\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M11.2867 0.5C9.88583 0.5 8.6461 1.46745 8.37171 2.85605L8.29264 3.25622C8.10489 4.20638 7.06195 4.83059 6.04511 4.48813L5.64825 4.35447C4.32246 3.90796 2.83873 4.42968 2.11836 5.63933L1.40492 6.83735C0.67773 8.05846 0.954349 9.60487 2.03927 10.5142L2.35714 10.7806C3.12939 11.4279 3.12939 12.5721 2.35714 13.2194L2.03927 13.4858C0.954349 14.3951 0.67773 15.9415 1.40492 17.1626L2.11833 18.3606C2.83872 19.5703 4.3225 20.092 5.64831 19.6455L6.04506 19.5118C7.06191 19.1693 8.1049 19.7935 8.29264 20.7437L8.37172 21.1439C8.6461 22.5325 9.88584 23.5 11.2867 23.5H12.7136C14.1146 23.5 15.3543 22.5325 15.6287 21.1438L15.7077 20.7438C15.8954 19.7936 16.9384 19.1693 17.9553 19.5118L18.3521 19.6455C19.6779 20.092 21.1617 19.5703 21.8821 18.3606L22.5955 17.1627C23.3227 15.9416 23.046 14.3951 21.9611 13.4858L21.6432 13.2194C20.8709 12.5722 20.8709 11.4278 21.6432 10.7806L21.9611 10.5142C23.046 9.60489 23.3227 8.05845 22.5955 6.83732L21.8821 5.63932C21.1617 4.42968 19.678 3.90795 18.3522 4.35444L17.9552 4.48814C16.9384 4.83059 15.8954 4.20634 15.7077 3.25617L15.6287 2.85616C15.3543 1.46751 14.1146 0.5 12.7136 0.5H11.2867ZM10.3338 3.24375C10.4149 2.83334 10.7983 2.5 11.2867 2.5H12.7136C13.2021 2.5 13.5855 2.83336 13.6666 3.24378L13.7456 3.64379C14.1791 5.83811 16.4909 7.09167 18.5935 6.38353L18.9905 6.24984C19.4495 6.09527 19.9394 6.28595 20.1637 6.66264L20.8771 7.86064C21.0946 8.22587 21.0208 8.69271 20.6764 8.98135L20.3586 9.24773C18.6325 10.6943 18.6325 13.3057 20.3586 14.7523L20.6764 15.0186C21.0208 15.3073 21.0946 15.7741 20.8771 16.1394L20.1637 17.3373C19.9394 17.714 19.4495 17.9047 18.9905 17.7501L18.5936 17.6164C16.4909 16.9082 14.1791 18.1618 13.7456 20.3562L13.6666 20.7562C13.5855 21.1666 13.2021 21.5 12.7136 21.5H11.2867C10.7983 21.5 10.4149 21.1667 10.3338 20.7562L10.2547 20.356C9.82113 18.1617 7.50931 16.9082 5.40665 17.6165L5.0099 17.7501C4.55092 17.9047 4.06104 17.714 3.83671 17.3373L3.1233 16.1393C2.9058 15.7741 2.97959 15.3073 3.32398 15.0186L3.64185 14.7522C5.36782 13.3056 5.36781 10.6944 3.64185 9.24779L3.32398 8.98137C2.97959 8.69273 2.9058 8.2259 3.1233 7.86067L3.83674 6.66266C4.06106 6.28596 4.55093 6.09528 5.0099 6.24986L5.40676 6.38352C7.50938 7.09166 9.82112 5.83819 10.2547 3.64392L10.3338 3.24375Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if(consoleContext().state.isManualReconnectAvailable())\n {\n <cf-console-toolbar-default-button label=\"Reconnect\"\n (clicked)=\"consoleContext().console.sendReconnectRequest()\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C16.3556 22 20.0584 19.2159 21.4307 15.3332C21.6148 14.8125 21.3418 14.2412 20.8211 14.0572C20.3004 13.8731 19.7291 14.146 19.545 14.6668C18.4463 17.7753 15.4817 20 12 20C7.58172 20 4 16.4183 4 12C4 7.58172 7.58172 4 12 4C13.5516 4 14.8662 4.56117 16.1162 5.4406C16.9569 6.03212 17.7348 6.74106 18.5242 7.5H15.5C14.9477 7.5 14.5 7.94772 14.5 8.5C14.5 9.05228 14.9477 9.5 15.5 9.5H21C21.5523 9.5 22 9.05228 22 8.5V3C22 2.44772 21.5523 2 21 2C20.4477 2 20 2.44772 20 3V6.14371C19.1517 5.32583 18.2456 4.49337 17.267 3.80489C15.7949 2.76916 14.0847 2 12 2Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (!consoleContext().state.isViewOnly() && consoleContext().state.isConnected()) {\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button label=\"Keyboard\" (clicked)=\"isKeyboardDialogOpen = true\">\n <svg fill=\"#000000\" viewBox=\"0 0 1920 1920\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M1807.059 1637.706c0 31.059-25.299 56.47-56.47 56.47H169.411c-31.172 0-56.47-25.411-56.47-56.47v-903.53c0-31.058 25.298-56.47 56.47-56.47h1581.176c31.172 0 56.47 25.412 56.47 56.47v903.53Zm-56.47-1072.941h-729.262c14.908-86.965 65.958-113.506 133.384-147.163 89.336-44.611 200.583-100.291 200.583-304.602h-112.941c0 134.513-57.939 163.426-138.24 203.633-80.301 40.094-177.544 90.24-196.518 248.132H169.412C76.009 564.765 0 640.775 0 734.176v903.53c0 93.402 76.01 169.412 169.412 169.412h1581.176c93.403 0 169.412-76.01 169.412-169.412v-903.53c0-93.402-76.01-169.411-169.412-169.411Zm-564.707 677.647H734.118c-31.172 0-56.47 25.299-56.47 56.47v112.942c0 31.171 25.298 56.47 56.47 56.47h451.764c31.172 0 56.47-25.299 56.47-56.47v-112.942c0-31.171-25.298-56.47-56.47-56.47m338.824 0h-112.941c-31.172 0-56.47 25.299-56.47 56.47v112.942c0 31.171 25.298 56.47 56.47 56.47h112.94c31.173 0 56.471-25.299 56.471-56.47v-112.942c0-31.171-25.298-56.47-56.47-56.47m-1016.47 0H395.293c-31.172 0-56.47 25.299-56.47 56.47v112.942c0 31.171 25.298 56.47 56.47 56.47h112.941c31.172 0 56.47-25.299 56.47-56.47v-112.942c0-31.171-25.298-56.47-56.47-56.47m0-338.824h-112.94c-31.173 0-56.471 25.3-56.471 56.47V1073c0 31.172 25.298 56.47 56.47 56.47h112.941c31.172 0 56.47-25.298 56.47-56.47V960.059c0-31.172-25.298-56.47-56.47-56.47m225.883 225.882h112.94c31.173 0 56.471-25.3 56.471-56.471V960.059c0-31.172-25.298-56.47-56.47-56.47h-112.94c-31.172 0-56.47 25.298-56.47 56.47V1073c0 31.172 25.298 56.47 56.47 56.47m451.764-225.882h-112.94c-31.173 0-56.471 25.3-56.471 56.47V1073c0 31.172 25.298 56.47 56.47 56.47h112.941c31.172 0 56.47-25.298 56.47-56.47V960.059c0-31.172-25.298-56.47-56.47-56.47m338.824 0h-112.941c-31.172 0-56.47 25.298-56.47 56.47V1073c0 31.172 25.298 56.47 56.47 56.47h112.94c31.173 0 56.471-25.298 56.471-56.47V960.059c0-31.172-25.298-56.47-56.47-56.47\"\n fill-rule=\"evenodd\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if(!cfConfig.disabledFeatures.clipboard) {\n <cf-console-toolbar-default-button [disabled]=\"!consoleContext().state.isConnected()\" label=\"Clipboard\"\n (clicked)=\"handleClipboardDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" preserveAspectRatio=\"none\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M19.5 16.5L19.5 4.5L18.75 3.75H9L8.25 4.5L8.25 7.5L5.25 7.5L4.5 8.25V20.25L5.25 21H15L15.75 20.25V17.25H18.75L19.5 16.5ZM15.75 15.75L15.75 8.25L15 7.5L9.75 7.5V5.25L18 5.25V15.75H15.75ZM6 9L14.25 9L14.25 19.5L6 19.5L6 9Z\"\n fill=\"#080341\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (consoleContext().networks.config()?.networks?.length) {\n <cf-console-toolbar-default-button label=\"Networks ({{ consoleContext().networks.config()?.networks?.length }})\"\n (clicked)=\"handleNetworkDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M3 12H21M12 8V12M6.5 12V16M17.5 12V16M10.1 8H13.9C14.4601 8 14.7401 8 14.954 7.89101C15.1422 7.79513 15.2951 7.64215 15.391 7.45399C15.5 7.24008 15.5 6.96005 15.5 6.4V4.6C15.5 4.03995 15.5 3.75992 15.391 3.54601C15.2951 3.35785 15.1422 3.20487 14.954 3.10899C14.7401 3 14.4601 3 13.9 3H10.1C9.53995 3 9.25992 3 9.04601 3.10899C8.85785 3.20487 8.70487 3.35785 8.60899 3.54601C8.5 3.75992 8.5 4.03995 8.5 4.6V6.4C8.5 6.96005 8.5 7.24008 8.60899 7.45399C8.70487 7.64215 8.85785 7.79513 9.04601 7.89101C9.25992 8 9.53995 8 10.1 8ZM15.6 21H19.4C19.9601 21 20.2401 21 20.454 20.891C20.6422 20.7951 20.7951 20.6422 20.891 20.454C21 20.2401 21 19.9601 21 19.4V17.6C21 17.0399 21 16.7599 20.891 16.546C20.7951 16.3578 20.6422 16.2049 20.454 16.109C20.2401 16 19.9601 16 19.4 16H15.6C15.0399 16 14.7599 16 14.546 16.109C14.3578 16.2049 14.2049 16.3578 14.109 16.546C14 16.7599 14 17.0399 14 17.6V19.4C14 19.9601 14 20.2401 14.109 20.454C14.2049 20.6422 14.3578 20.7951 14.546 20.891C14.7599 21 15.0399 21 15.6 21ZM4.6 21H8.4C8.96005 21 9.24008 21 9.45399 20.891C9.64215 20.7951 9.79513 20.6422 9.89101 20.454C10 20.2401 10 19.9601 10 19.4V17.6C10 17.0399 10 16.7599 9.89101 16.546C9.79513 16.3578 9.64215 16.2049 9.45399 16.109C9.24008 16 8.96005 16 8.4 16H4.6C4.03995 16 3.75992 16 3.54601 16.109C3.35785 16.2049 3.20487 16.3578 3.10899 16.546C3 16.7599 3 17.0399 3 17.6V19.4C3 19.9601 3 20.2401 3.10899 20.454C3.20487 20.6422 3.35785 20.7951 3.54601 20.891C3.75992 21 4.03995 21 4.6 21Z\"\n stroke=\"#000000\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (consoleContext().console.supportedFeatures().powerManagement) {\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button label=\"Power\" (clicked)=\"isPowerDialogOpen = true\">\n <svg width=\"800px\" height=\"800px\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M13 3C13 2.44772 12.5523 2 12 2C11.4477 2 11 2.44772 11 3V13C11 13.5523 11.4477 14 12 14C12.5523 14 13 13.5523 13 13V3Z\"\n fill=\"none\" />\n <path\n d=\"M6.2798 6.70707C6.67031 6.31653 6.67028 5.68337 6.27973 5.29286C5.88919 4.90235 5.25603 4.90238 4.86552 5.29293C3.09635 7.06226 2 9.49298 2 12.1764C2 17.6204 6.49591 22 12 22C17.5041 22 22 17.6204 22 12.1764C22 9.49298 20.9036 7.06226 19.1345 5.29293C18.744 4.90238 18.1108 4.90235 17.7203 5.29286C17.3297 5.68337 17.3297 6.31653 17.7202 6.70707C19.1338 8.12083 20 10.0503 20 12.1764C20 16.4787 16.437 20 12 20C7.56296 20 4 16.4787 4 12.1764C4 10.0503 4.86618 8.12083 6.2798 6.70707Z\"\n fill=\"none\" />\n </svg>\n </cf-console-toolbar-default-button> }\n }\n\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button (clicked)=\"consoleContext().console.copyScreenshot()\"\n [disabled]=\"!consoleContext().state.isConnected()\" label=\"Screenshot\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M9.15023 3.01742C9.13605 3.03985 9.12278 3.0676 9.11298 3.09958C9.11044 3.10789 9.10778 3.11617 9.10502 3.12442L8.36963 5.31787C8.23301 5.72537 7.85129 6 7.4215 6H3C2.44772 6 2 6.44772 2 7V20C2 20.5523 2.44771 21 3 21H21C21.5523 21 22 20.5523 22 20V7C22 6.44771 21.5523 6 21 6H16.331C15.9011 6 15.5194 5.72528 15.3828 5.31769L14.6479 3.12423C14.6452 3.11605 14.6425 3.10783 14.64 3.09958C14.6302 3.0676 14.6169 3.03985 14.6027 3.01742C14.5986 3.01089 14.5946 3.00509 14.5908 3H9.16221C9.1584 3.00509 9.15437 3.01089 9.15023 3.01742ZM7.20525 2.49911C7.43535 1.76672 8.10563 1 9.06392 1H14.6891C15.6474 1 16.3177 1.76679 16.5478 2.49922L17.0506 4H21C22.6569 4 24 5.34315 24 7V20C24 21.6569 22.6569 23 21 23H3C1.34315 23 0 21.6569 0 20V7C0 5.34315 1.34315 4 3 4H6.70206L7.20525 2.49911ZM7 13C7 10.2386 9.23858 8 12 8C14.7614 8 17 10.2386 17 13C17 15.7614 14.7614 18 12 18C9.23858 18 7 15.7614 7 13ZM12 10C10.3431 10 9 11.3431 9 13C9 14.6569 10.3431 16 12 16C13.6569 16 15 14.6569 15 13C15 11.3431 13.6569 10 12 10Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if (!cfConfig.disabledFeatures.consoleScreenRecord) {\n <cf-console-toolbar-default-button (clicked)=\"handleRecordToggle()\"\n [disabled]=\"!consoleContext().state.isRecordingAvailable()\"\n [isOngoing]=\"!!consoleContext().state.activeConsoleRecording()\" label=\"Record\">\n @if (!consoleContext().state.activeConsoleRecording()) {\n <svg viewBox=\"0 0 20 20\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\" fill=\"#000000\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <g id=\"Dribbble-Light-Preview\" transform=\"translate(-100.000000, -3879.000000)\" fill=\"#000000\">\n <g id=\"icons\" transform=\"translate(56.000000, 160.000000)\">\n <path\n d=\"M56,3719 L56,3721 L62,3721 L62,3727 L64,3727 L64,3719 L56,3719 Z M58,3729.151 C58,3726.942 56.209,3725.151 54,3725.151 C51.791,3725.151 50,3726.942 50,3729.151 C50,3731.36 51.791,3733.151 54,3733.151 C56.209,3733.151 58,3731.36 58,3729.151 L58,3729.151 Z M62,3737 L56,3737 L56,3739 L64,3739 L64,3731 L62,3731 L62,3737 Z M46,3731 L44,3731 L44,3739 L52,3739 L52,3737 L46,3737 L46,3731 Z M46,3727 L44,3727 L44,3719 L52,3719 L52,3721 L46,3721 L46,3727 Z\"\n id=\"record-[#979]\"> </path>\n </g>\n </g>\n </g>\n </g>\n </svg>\n } @else {\n <svg viewBox=\"0 -0.5 21 21\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\" fill=\"#000000\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <g id=\"Dribbble-Light-Preview\" transform=\"translate(-59.000000, -440.000000)\" fill=\"#000000\">\n <g id=\"icons\" transform=\"translate(56.000000, 160.000000)\">\n <path\n d=\"M9.3,294 L17.7,294 L17.7,286 L9.3,286 L9.3,294 Z M15.6,280 L15.6,282 L21.9,282 L21.9,288 L24,288 L24,280 L15.6,280 Z M21.9,298 L15.6,298 L15.6,300 L24,300 L24,292 L21.9,292 L21.9,298 Z M5.1,292 L3,292 L3,300 L11.4,300 L11.4,298 L5.1,298 L5.1,292 Z M5.1,288 L3,288 L3,280 L11.4,280 L11.4,282 L5.1,282 L5.1,288 Z\"\n id=\"stop-[#1470]\"> </path>\n </g>\n </g>\n </g>\n </g>\n </svg>\n }\n </cf-console-toolbar-default-button>\n }\n\n <cf-console-toolbar-default-button (clicked)=\"consoleContext().console.toggleFullscreen()\" label=\"Fullscreen\">\n @if (consoleContext().state.isFullscreenAvailable()) {\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M4 2C2.89543 2 2 2.89543 2 4V8C2 8.55228 2.44772 9 3 9C3.55228 9 4 8.55228 4 8V4H8C8.55228 4 9 3.55228 9 3C9 2.44772 8.55228 2 8 2H4Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M20 2C21.1046 2 22 2.89543 22 4V8C22 8.55228 21.5523 9 21 9C20.4477 9 20 8.55228 20 8V4H16C15.4477 4 15 3.55228 15 3C15 2.44772 15.4477 2 16 2H20Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M20 22C21.1046 22 22 21.1046 22 20V16C22 15.4477 21.5523 15 21 15C20.4477 15 20 15.4477 20 16V20H16C15.4477 20 15 20.4477 15 21C15 21.5523 15.4477 22 16 22H20Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M2 20C2 21.1046 2.89543 22 4 22H8C8.55228 22 9 21.5523 9 21C9 20.4477 8.55228 20 8 20H4V16C4 15.4477 3.55228 15 3 15C2.44772 15 2 15.4477 2 16V20Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n } @else {\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M7 9C8.10457 9 9 8.10457 9 7V3C9 2.44772 8.55228 2 8 2C7.44772 2 7 2.44772 7 3V7H3C2.44772 7 2 7.44772 2 8C2 8.55228 2.44772 9 3 9H7Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M17 9C15.8954 9 15 8.10457 15 7V3C15 2.44772 15.4477 2 16 2C16.5523 2 17 2.44772 17 3V7H21C21.5523 7 22 7.44772 22 8C22 8.55228 21.5523 9 21 9H17Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M17 15C15.8954 15 15 15.8954 15 17V21C15 21.5523 15.4477 22 16 22C16.5523 22 17 21.5523 17 21V17H21C21.5523 17 22 16.5523 22 16C22 15.4477 21.5523 15 21 15H17Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M9 17C9 15.8954 8.10457 15 7 15H3C2.44772 15 2 15.4477 2 16C2 16.5523 2.44772 17 3 17H7V21C7 21.5523 7.44772 22 8 22C8.55228 22 9 21.5523 9 21V17Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n }\n </cf-console-toolbar-default-button>\n </div>\n\n <dialog [open]=\"isClipboardDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleClipboardDialogOpenClose(false)\"></button>\n <p>\n <strong>Clipboard</strong>\n </p>\n </header>\n\n @if (consoleContext().console.supportedFeatures().clipboardRemoteWrite) {\n <div class=\"dialog-section\">\n <h2>Send Text to Remote Clipboard</h2>\n <form (submit)=\"handleSendClipboardText($event, clipboardText.value)\">\n <fieldset role=\"group\">\n <input type=\"text\" class=\"clipboard-text\" aria-label=\"Clipboard text\"\n placeholder=\"Enter text to send to the remote clipboard\" #clipboardText autofocus>\n <button type=\"submit\"\n [disabled]=\"!clipboardText.value || !consoleContext().state.isConnected\">Send</button>\n </fieldset>\n </form>\n </div>\n }\n\n <div class=\"dialog-section\">\n <h2>Remote Clipboard Content</h2>\n <form (submit)=\"handleClipboardCopyLastText(consoleLastClipboardText.value)\">\n <fieldset role=\"group\">\n <input type=\"text\" id=\"textFromConsoleClipboard\" name=\"textFromConsoleClipboard\"\n class=\"clipboard-text\" aria-describedby=\"textFromConsoleClipboard-helper\"\n aria-label=\"Clipboard text\" disabled\n [value]=\"consoleContext().clipboard.consoleClipboardText()\"\n placeholder=\"Text on the remote will appear here\" #consoleLastClipboardText>\n <button type=\"submit\" [disabled]=\"!consoleLastClipboardText.value\">Copy</button>\n </fieldset>\n @if(consoleContext().userSettings.settings().console.allowCopyToLocalClipboard &&\n consoleContext().console.supportedFeatures().clipboardAutomaticLocalCopy)\n {\n <small id=\"textFromConsoleClipboard-helper\">\n Copied text on the remote machine will automatically copy to your local clipboard.\n Disable this in Settings.\n </small>\n }\n </form>\n </div>\n </article>\n </dialog>\n\n <dialog [open]=\"isKeyboardDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"isKeyboardDialogOpen = false\"></button>\n <p>\n <strong>Send Keystrokes</strong>\n </p>\n </header>\n\n <div class=\"dialog-section\">\n <h2>Send Keystrokes to Console</h2>\n <form (submit)=\"handleSendKeyboardInput($event, keyboardInputText())\">\n <fieldset role=\"group\">\n <input type=\"text\" id=\"keyboardInputText\" name=\"keyboardInputText\" class=\"keyboard-text\"\n aria-label=\"Keyboard text\" placeholder=\"Enter text to send as keyboard input to the console\"\n autofocus [(ngModel)]=\"keyboardInputText\">\n <button type=\"submit\"\n [disabled]=\"!keyboardInputText() || !consoleContext().state.isConnected\">Send</button>\n </fieldset>\n </form>\n </div>\n\n <div class=\"dialog-section\">\n <h2>Special Key Combinations</h2>\n\n <div class=\"dialog-button-group\">\n <button type=\"button\" aria-label=\"Send Ctrl+Alt+Delete\" (click)=\"handlSendKeyboardCtrlAltDel()\">\n Ctrl + Alt + Delete\n </button>\n </div>\n </div>\n </article>\n </dialog>\n\n <dialog [open]=\"isNetworkDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleNetworkDialogOpenClose(false)\"></button>\n <p>\n <strong>Networks</strong>\n </p>\n </header>\n\n <form>\n @for (nic of consoleContext().networks.config()?.nics; track nic)\n {\n <label for=\"nic-{{ nic }}-select\">{{ nic }}</label>\n <fieldset role=\"group\">\n <select #availableNetworksSelect name=\"nic-{{ nic }}-select\"\n aria-label=\"Select a network to connect to\">\n\n @if (!cfConfig.disabledFeatures.networkDisconnection)\n {\n <option [selected]=\"!consoleContext().networks.config()?.currentConnections?.[nic]\" value=\"\">\n [Disconnected]\n </option>\n }\n\n @for(network of consoleContext().networks.config()?.networks; track network) {\n <option [value]=\"network\"\n [selected]=\"consoleContext().networks.config()?.currentConnections?.[nic] === network\">\n {{ network }}\n </option>\n }\n </select>\n\n <button type=\"button\"\n (click)=\"handleNetworkChangeRequested({ network: availableNetworksSelect.value, nic: nic })\">\n {{ availableNetworksSelect.value ? \"Connect\" : \"Disconnect\" }}\n </button>\n </fieldset>\n }\n\n @if (!cfConfig.disabledFeatures.networkDisconnection)\n {\n <hr />\n <div class=\"dialog-button-group\">\n <button class=\"secondary\" type=\"button\" (click)=\"handleNetworkDisconnectAllRequested()\">\n Disconnect All Network Interfaces\n </button>\n </div>\n }\n </form>\n </article>\n </dialog>\n\n <dialog [open]=\"isPowerDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"isPowerDialogOpen = false\"></button>\n <p>\n <strong>Power</strong>\n </p>\n </header>\n\n <div class=\"dialog-button-group\">\n <button type=\"button\" (click)=\"handleSendPowerRequest('reboot')\">Request Reboot</button>\n <button type=\"button\" (click)=\"handleSendPowerRequest('shutdown')\">Request Shutdown</button>\n <hr />\n <button class=\"secondary\" type=\"button\" (click)=\"handleSendPowerRequest('rebootHard')\">\n Request Hard Reboot\n </button>\n </div>\n </article>\n </dialog>\n\n <dialog [open]=\"isSettingsDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleSettingsDialogOpenClose(false)\"></button>\n <p>\n <strong>Settings</strong>\n </p>\n </header>\n\n <div class=\"settings-form\">\n <div class=\"settings-behavior dialog-section\">\n <h4>Behavior</h4>\n <fieldset>\n <label>\n <input #inputAllowLocalClipboardWrite type=\"checkbox\" name=\"allowLocalClipboardWrite\"\n [checked]=\"consoleContext().userSettings.settings().console.allowCopyToLocalClipboard\"\n (change)=\"handleSettingsAllowLocalClipboardWrite(inputAllowLocalClipboardWrite.checked)\" />\n Allow the remote machine to copy text to my local clipboard\n </label>\n <label>\n <input #inputAttemptRemoteSessionResize type=\"checkbox\" name=\"attemptRemoteSessionResize\"\n [checked]=\"consoleContext().userSettings.settings().console.attemptRemoteSessionResize\"\n (change)=\"handleSettingsAttemptRemoteSessionResize(inputAttemptRemoteSessionResize.checked)\" />\n Attempt to resize the remote session to match local resolution\n </label>\n <label>\n <input #inputScaleToContainerSize type=\"checkbox\" name=\"scaleToContainerSize\"\n [checked]=\"consoleContext().userSettings.settings().console.scaleToCanvasHostSize\"\n (change)=\"handleSettingsScaleToContainerHostSize(inputScaleToContainerSize.checked)\" />\n Scale to maximum available size\n </label>\n </fieldset>\n </div>\n\n <div class=\"settings-toolbar-dock dialog-section\">\n <h4>Toolbar Position</h4>\n <div role=\"group\">\n <button (click)=\"handleChangeToolbarPosition('left')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'left'\">Left</button>\n <button (click)=\"handleChangeToolbarPosition('right')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'right'\">Right</button>\n <button (click)=\"handleChangeToolbarPosition('top')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'top'\">Top</button>\n <button (click)=\"handleChangeToolbarPosition('bottom')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'bottom'\">Bottom</button>\n </div>\n </div>\n\n <div class=\"settings-theme dialog-section\">\n <h4>Theme</h4>\n <div role=\"group\">\n <button (click)=\"handleToolbarThemeChange('light')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.preferTheme === 'light'\">Light</button>\n <button (click)=\"handleToolbarThemeChange('dark')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.preferTheme === 'dark'\">Dark</button>\n <button (click)=\"handleToolbarThemeChange(undefined)\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.preferTheme === undefined\">\n My Default\n </button>\n </div>\n </div>\n </div>\n </article>\n </dialog>\n</div>\n}\n", styles: [":host{display:block;height:100%;width:100%;max-width:100%}fieldset legend{font-weight:700}.toolbar-container{background-color:var(--pico-background-color);padding:4px;height:100%;display:flex;align-items:center;justify-content:center}.toolbar-container .button-container{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px}.toolbar-container .buttons-divider{border-top:1px solid var(--pico-color);margin:.25rem 0;width:100%}.toolbar-container.horizontal{width:100%}.toolbar-container.horizontal .button-container{flex-direction:row}.toolbar-container.horizontal .buttons-divider{align-self:stretch;border-left:1px solid var(--pico-color);height:auto;margin:0 1rem;width:1px}.toolbar-position-buttons{display:flex;gap:4px}.toolbar-position-buttons button{flex-grow:1}.settings-toolbar-dock{margin-top:1rem}dialog h2{font-size:1.1rem;font-weight:700}dialog small{font-size:.8rem}dialog .dialog-section:not(:last-of-type){margin-bottom:2rem}dialog .dialog-button-group button{display:block;width:100%}\n"] }]
1701
+ }], ctorParameters: () => [], propDecorators: { consoleContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "consoleContext", required: true }] }], keyboardInputText: [{ type: i0.Input, args: [{ isSignal: true, alias: "keyboardInputText", required: false }] }, { type: i0.Output, args: ["keyboardInputTextChange"] }], clipboardTextInput: [{ type: i0.ViewChild, args: ["clipboardText", { isSignal: true }] }] } });
1702
+
1703
+ // ===BEGIN LICENSE===
1704
+ // Copyright 2025 Carnegie Mellon University. All rights reserved.
1705
+ // Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
1706
+ // ===END LICENSE===
1707
+ const defaultCfConfig = {
1708
+ canvasRecording: {
1709
+ autoDownloadCompletedRecordings: true,
1710
+ chunkLength: 1000,
1711
+ frameRate: 25,
1712
+ maxDuration: 10000,
1713
+ mimeType: "video/webm"
1714
+ },
1715
+ consoleBackgroundStyle: "rgb(40, 40, 40)",
1716
+ disabledFeatures: {
1717
+ clipboard: false,
1718
+ consoleScreenRecord: false,
1719
+ manualConsoleReconnect: false,
1720
+ networkDisconnection: false,
1721
+ },
1722
+ logThreshold: LogLevel.WARNING,
1723
+ showBrowserNotificationsOnConsoleEvents: true,
1724
+ toolbar: {
1725
+ component: ConsoleToolbarDefaultComponent,
1726
+ disabled: false
1727
+ }
1728
+ };
1702
1729
 
1703
1730
  // ===BEGIN LICENSE===
1704
1731
  // Copyright 2025 Carnegie Mellon University. All rights reserved.