@franzzemen/brokenstock-shell 0.2.0 → 0.2.2
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.
|
@@ -107,14 +107,9 @@ class AuthenticationService {
|
|
|
107
107
|
get auth() {
|
|
108
108
|
return this.#auth;
|
|
109
109
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
/** Check if the current user has any of the specified roles. */
|
|
115
|
-
hasAnyRole(roleNames) {
|
|
116
|
-
return this.authenticated() && roleNames.some(r => this.userSession()?.roles.includes(r) === true);
|
|
117
|
-
}
|
|
110
|
+
// Legacy hasRole/hasAnyRole removed (legacy-authz-teardown): sessions carry no
|
|
111
|
+
// roles, and every gate migrated to hasFeature (commerce) with the BE enforcing
|
|
112
|
+
// the security axis.
|
|
118
113
|
/**
|
|
119
114
|
* Is this BOOLEAN feature granted and on? e.g. `hasFeature('real-time')`.
|
|
120
115
|
*
|
|
@@ -1851,6 +1846,48 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
1851
1846
|
args: [{ providedIn: 'root' }]
|
|
1852
1847
|
}] });
|
|
1853
1848
|
|
|
1849
|
+
const STORAGE_KEY = 'shell.commandTerminalVisible';
|
|
1850
|
+
/**
|
|
1851
|
+
* Controls visibility of the command terminal at the bottom of the shell.
|
|
1852
|
+
*
|
|
1853
|
+
* State is a single signal, persisted to localStorage so the user's choice
|
|
1854
|
+
* survives reloads. The side-menu toggles it; the shell layout reads it to
|
|
1855
|
+
* collapse the terminal (and its resize handle) rows.
|
|
1856
|
+
*/
|
|
1857
|
+
class TerminalVisibilityService {
|
|
1858
|
+
constructor() {
|
|
1859
|
+
this.visible = signal(this.#readInitial(), /* @ts-ignore */
|
|
1860
|
+
...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
1861
|
+
effect(() => {
|
|
1862
|
+
const isVisible = this.visible();
|
|
1863
|
+
try {
|
|
1864
|
+
localStorage.setItem(STORAGE_KEY, isVisible ? '1' : '0');
|
|
1865
|
+
}
|
|
1866
|
+
catch {
|
|
1867
|
+
// localStorage unavailable (private mode / SSR) — non-fatal.
|
|
1868
|
+
}
|
|
1869
|
+
});
|
|
1870
|
+
}
|
|
1871
|
+
toggle() {
|
|
1872
|
+
this.visible.update(v => !v);
|
|
1873
|
+
}
|
|
1874
|
+
#readInitial() {
|
|
1875
|
+
try {
|
|
1876
|
+
const raw = localStorage.getItem(STORAGE_KEY);
|
|
1877
|
+
return raw === null ? true : raw === '1';
|
|
1878
|
+
}
|
|
1879
|
+
catch {
|
|
1880
|
+
return true;
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TerminalVisibilityService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1884
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TerminalVisibilityService, providedIn: 'root' }); }
|
|
1885
|
+
}
|
|
1886
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TerminalVisibilityService, decorators: [{
|
|
1887
|
+
type: Injectable,
|
|
1888
|
+
args: [{ providedIn: 'root' }]
|
|
1889
|
+
}], ctorParameters: () => [] });
|
|
1890
|
+
|
|
1854
1891
|
class KeyboardShortcutService {
|
|
1855
1892
|
#groups;
|
|
1856
1893
|
#activeGroupId;
|
|
@@ -2282,7 +2319,9 @@ class SideMenu {
|
|
|
2282
2319
|
this.#focusService = inject(TerminalFocusService);
|
|
2283
2320
|
this.#commandService = inject(CommandService);
|
|
2284
2321
|
this.#shortcutService = inject(KeyboardShortcutService);
|
|
2322
|
+
this.#terminalVisibility = inject(TerminalVisibilityService);
|
|
2285
2323
|
this.hasShortcuts = this.#shortcutService.activeShortcuts;
|
|
2324
|
+
this.terminalVisible = this.#terminalVisibility.visible;
|
|
2286
2325
|
this.#allMenuItems = inject(SHELL_MENU_ITEMS, { optional: true }) ?? [];
|
|
2287
2326
|
this.menuItems = computed(() => this.#allMenuItems.filter(item => !item.visible || item.visible()), /* @ts-ignore */
|
|
2288
2327
|
...(ngDevMode ? [{ debugName: "menuItems" }] : /* istanbul ignore next */ []));
|
|
@@ -2290,6 +2329,7 @@ class SideMenu {
|
|
|
2290
2329
|
#focusService;
|
|
2291
2330
|
#commandService;
|
|
2292
2331
|
#shortcutService;
|
|
2332
|
+
#terminalVisibility;
|
|
2293
2333
|
#allMenuItems;
|
|
2294
2334
|
onMenuClick(item) {
|
|
2295
2335
|
if (item.command) {
|
|
@@ -2300,12 +2340,15 @@ class SideMenu {
|
|
|
2300
2340
|
toggleHelp() {
|
|
2301
2341
|
this.#shortcutService.toggleHelp();
|
|
2302
2342
|
}
|
|
2343
|
+
toggleTerminal() {
|
|
2344
|
+
this.#terminalVisibility.toggle();
|
|
2345
|
+
}
|
|
2303
2346
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: SideMenu, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2304
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: SideMenu, isStandalone: true, selector: "shell-side-menu", ngImport: i0, template: "<nav class=\"side-menu\">\n @for (item of menuItems(); track item.route) {\n <a\n class=\"menu-item\"\n [routerLink]=\"item.route\"\n routerLinkActive=\"active\"\n [matTooltip]=\"item.label\"\n matTooltipPosition=\"right\"\n (click)=\"onMenuClick(item)\"\n >\n <mat-icon>{{ item.icon }}</mat-icon>\n </a>\n }\n <div class=\"menu-spacer\"></div>\n @if (hasShortcuts()) {\n <button\n class=\"help-button\"\n matTooltip=\"Keyboard shortcuts\"\n matTooltipPosition=\"right\"\n (click)=\"toggleHelp()\"\n >\n <span class=\"help-modifier\">Alt+</span><span class=\"help-key\">?</span>\n </button>\n }\n</nav>\n", styles: [".side-menu{display:flex;flex-direction:column;align-items:center;padding-top:8px;gap:4px;height:100%;background-color:var(--color-surface);border-right:1px solid var(--color-surface-border)}.menu-item{display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:8px;color:var(--color-secondary-info);text-decoration:none;transition:background-color .15s,color .15s}.menu-item:hover{background-color:var(--color-surface-light);color:var(--color-interactive)}.menu-item.active,.menu-item.active:hover{background-color:var(--color-interactive, #00e5ff);color:var(--color-surface-dark, #0d1117)}.menu-spacer{flex:1}.help-button{margin-bottom:8px;padding:4px 6px;border:1px solid var(--color-surface-border);border-radius:6px;background:none;font-size:.7rem;font-family:Roboto Mono,monospace;cursor:pointer;color:var(--color-interactive);transition:background-color .15s}.help-button:hover{background-color:var(--color-surface-light)}.help-modifier{opacity:.6}.help-key{font-weight:700}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
|
|
2347
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: SideMenu, isStandalone: true, selector: "shell-side-menu", ngImport: i0, template: "<nav class=\"side-menu\">\n @for (item of menuItems(); track item.route) {\n <a\n class=\"menu-item\"\n [routerLink]=\"item.route\"\n routerLinkActive=\"active\"\n [matTooltip]=\"item.label\"\n matTooltipPosition=\"right\"\n (click)=\"onMenuClick(item)\"\n >\n <mat-icon>{{ item.icon }}</mat-icon>\n </a>\n }\n <div class=\"menu-spacer\"></div>\n <button\n class=\"menu-item terminal-toggle\"\n type=\"button\"\n [class.active]=\"terminalVisible()\"\n [matTooltip]=\"terminalVisible() ? 'Hide command console' : 'Show command console'\"\n matTooltipPosition=\"right\"\n [attr.aria-pressed]=\"terminalVisible()\"\n (click)=\"toggleTerminal()\"\n >\n <mat-icon>terminal</mat-icon>\n </button>\n @if (hasShortcuts()) {\n <button\n class=\"help-button\"\n matTooltip=\"Keyboard shortcuts\"\n matTooltipPosition=\"right\"\n (click)=\"toggleHelp()\"\n >\n <span class=\"help-modifier\">Alt+</span><span class=\"help-key\">?</span>\n </button>\n }\n</nav>\n", styles: [".side-menu{display:flex;flex-direction:column;align-items:center;padding-top:8px;gap:4px;height:100%;background-color:var(--color-surface);border-right:1px solid var(--color-surface-border)}.menu-item{display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:8px;color:var(--color-secondary-info);text-decoration:none;transition:background-color .15s,color .15s}.menu-item:hover{background-color:var(--color-surface-light);color:var(--color-interactive)}.menu-item.active,.menu-item.active:hover{background-color:var(--color-interactive, #00e5ff);color:var(--color-surface-dark, #0d1117)}.menu-spacer{flex:1}.menu-item.terminal-toggle{border:none;background:none;padding:0;cursor:pointer;margin-bottom:4px}.help-button{margin-bottom:8px;padding:4px 6px;border:1px solid var(--color-surface-border);border-radius:6px;background:none;font-size:.7rem;font-family:Roboto Mono,monospace;cursor:pointer;color:var(--color-interactive);transition:background-color .15s}.help-button:hover{background-color:var(--color-surface-light)}.help-modifier{opacity:.6}.help-key{font-weight:700}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
|
|
2305
2348
|
}
|
|
2306
2349
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: SideMenu, decorators: [{
|
|
2307
2350
|
type: Component,
|
|
2308
|
-
args: [{ selector: 'shell-side-menu', imports: [RouterLink, RouterLinkActive, MatIconModule, MatTooltipModule], changeDetection: ChangeDetectionStrategy.Eager, template: "<nav class=\"side-menu\">\n @for (item of menuItems(); track item.route) {\n <a\n class=\"menu-item\"\n [routerLink]=\"item.route\"\n routerLinkActive=\"active\"\n [matTooltip]=\"item.label\"\n matTooltipPosition=\"right\"\n (click)=\"onMenuClick(item)\"\n >\n <mat-icon>{{ item.icon }}</mat-icon>\n </a>\n }\n <div class=\"menu-spacer\"></div>\n @if (hasShortcuts()) {\n <button\n class=\"help-button\"\n matTooltip=\"Keyboard shortcuts\"\n matTooltipPosition=\"right\"\n (click)=\"toggleHelp()\"\n >\n <span class=\"help-modifier\">Alt+</span><span class=\"help-key\">?</span>\n </button>\n }\n</nav>\n", styles: [".side-menu{display:flex;flex-direction:column;align-items:center;padding-top:8px;gap:4px;height:100%;background-color:var(--color-surface);border-right:1px solid var(--color-surface-border)}.menu-item{display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:8px;color:var(--color-secondary-info);text-decoration:none;transition:background-color .15s,color .15s}.menu-item:hover{background-color:var(--color-surface-light);color:var(--color-interactive)}.menu-item.active,.menu-item.active:hover{background-color:var(--color-interactive, #00e5ff);color:var(--color-surface-dark, #0d1117)}.menu-spacer{flex:1}.help-button{margin-bottom:8px;padding:4px 6px;border:1px solid var(--color-surface-border);border-radius:6px;background:none;font-size:.7rem;font-family:Roboto Mono,monospace;cursor:pointer;color:var(--color-interactive);transition:background-color .15s}.help-button:hover{background-color:var(--color-surface-light)}.help-modifier{opacity:.6}.help-key{font-weight:700}\n"] }]
|
|
2351
|
+
args: [{ selector: 'shell-side-menu', imports: [RouterLink, RouterLinkActive, MatIconModule, MatTooltipModule], changeDetection: ChangeDetectionStrategy.Eager, template: "<nav class=\"side-menu\">\n @for (item of menuItems(); track item.route) {\n <a\n class=\"menu-item\"\n [routerLink]=\"item.route\"\n routerLinkActive=\"active\"\n [matTooltip]=\"item.label\"\n matTooltipPosition=\"right\"\n (click)=\"onMenuClick(item)\"\n >\n <mat-icon>{{ item.icon }}</mat-icon>\n </a>\n }\n <div class=\"menu-spacer\"></div>\n <button\n class=\"menu-item terminal-toggle\"\n type=\"button\"\n [class.active]=\"terminalVisible()\"\n [matTooltip]=\"terminalVisible() ? 'Hide command console' : 'Show command console'\"\n matTooltipPosition=\"right\"\n [attr.aria-pressed]=\"terminalVisible()\"\n (click)=\"toggleTerminal()\"\n >\n <mat-icon>terminal</mat-icon>\n </button>\n @if (hasShortcuts()) {\n <button\n class=\"help-button\"\n matTooltip=\"Keyboard shortcuts\"\n matTooltipPosition=\"right\"\n (click)=\"toggleHelp()\"\n >\n <span class=\"help-modifier\">Alt+</span><span class=\"help-key\">?</span>\n </button>\n }\n</nav>\n", styles: [".side-menu{display:flex;flex-direction:column;align-items:center;padding-top:8px;gap:4px;height:100%;background-color:var(--color-surface);border-right:1px solid var(--color-surface-border)}.menu-item{display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:8px;color:var(--color-secondary-info);text-decoration:none;transition:background-color .15s,color .15s}.menu-item:hover{background-color:var(--color-surface-light);color:var(--color-interactive)}.menu-item.active,.menu-item.active:hover{background-color:var(--color-interactive, #00e5ff);color:var(--color-surface-dark, #0d1117)}.menu-spacer{flex:1}.menu-item.terminal-toggle{border:none;background:none;padding:0;cursor:pointer;margin-bottom:4px}.help-button{margin-bottom:8px;padding:4px 6px;border:1px solid var(--color-surface-border);border-radius:6px;background:none;font-size:.7rem;font-family:Roboto Mono,monospace;cursor:pointer;color:var(--color-interactive);transition:background-color .15s}.help-button:hover{background-color:var(--color-surface-light)}.help-modifier{opacity:.6}.help-key{font-weight:700}\n"] }]
|
|
2309
2352
|
}] });
|
|
2310
2353
|
|
|
2311
2354
|
class MainContent {
|
|
@@ -2445,9 +2488,11 @@ class Shell {
|
|
|
2445
2488
|
this.#thinkingService = inject(ThinkingService);
|
|
2446
2489
|
this.#commandService = inject(CommandService);
|
|
2447
2490
|
this.#authService = inject(AuthenticationService);
|
|
2491
|
+
this.#terminalVisibility = inject(TerminalVisibilityService);
|
|
2448
2492
|
this.isThinking = this.#thinkingService.isThinking;
|
|
2449
2493
|
this.isAuthenticated = this.#authService.authenticated;
|
|
2450
2494
|
this.helpOverlay = this.#commandService.helpOverlay;
|
|
2495
|
+
this.terminalVisible = this.#terminalVisibility.visible;
|
|
2451
2496
|
this.terminalHeight = signal(`${DEFAULT_TERMINAL_HEIGHT}px`, /* @ts-ignore */
|
|
2452
2497
|
...(ngDevMode ? [{ debugName: "terminalHeight" }] : /* istanbul ignore next */ []));
|
|
2453
2498
|
this.isDragging = signal(false, /* @ts-ignore */
|
|
@@ -2469,6 +2514,7 @@ class Shell {
|
|
|
2469
2514
|
#thinkingService;
|
|
2470
2515
|
#commandService;
|
|
2471
2516
|
#authService;
|
|
2517
|
+
#terminalVisibility;
|
|
2472
2518
|
dismissHelp() {
|
|
2473
2519
|
this.#commandService.dismissHelp();
|
|
2474
2520
|
}
|
|
@@ -2485,11 +2531,11 @@ class Shell {
|
|
|
2485
2531
|
document.addEventListener('mouseup', this.#onMouseUp);
|
|
2486
2532
|
}
|
|
2487
2533
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: Shell, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2488
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: Shell, isStandalone: true, selector: "shell-root", ngImport: i0, template: "<div class=\"shell\" [style.--terminal-height]=\"terminalHeight()\" [class.is-dragging]=\"isDragging()\">\n <shell-status-bar class=\"shell-status\" [class.disabled-zone]=\"isThinking()\">\n <ng-content />\n </shell-status-bar>\n @if (isAuthenticated()) {\n <shell-side-menu class=\"shell-menu\" [class.disabled-zone]=\"isThinking()\" />\n }\n <shell-main-content class=\"shell-main\" [class.full-width]=\"!isAuthenticated()\" />\n <div class=\"shell-resize\" [class.dragging]=\"isDragging()\" (mousedown)=\"onResizeStart($event)\"></div>\n
|
|
2534
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: Shell, isStandalone: true, selector: "shell-root", ngImport: i0, template: "<div class=\"shell\" [style.--terminal-height]=\"terminalHeight()\" [class.is-dragging]=\"isDragging()\" [class.terminal-hidden]=\"!terminalVisible()\">\n <shell-status-bar class=\"shell-status\" [class.disabled-zone]=\"isThinking()\">\n <ng-content />\n </shell-status-bar>\n @if (isAuthenticated()) {\n <shell-side-menu class=\"shell-menu\" [class.disabled-zone]=\"isThinking()\" />\n }\n <shell-main-content class=\"shell-main\" [class.full-width]=\"!isAuthenticated()\" />\n @if (terminalVisible()) {\n <div class=\"shell-resize\" [class.dragging]=\"isDragging()\" (mousedown)=\"onResizeStart($event)\"></div>\n <shell-command-terminal class=\"shell-terminal\" [class.disabled-zone]=\"isThinking()\" />\n }\n <faq-modal />\n\n @if (helpOverlay(); as helpText) {\n <div class=\"help-backdrop\" (click)=\"dismissHelp()\">\n <div class=\"help-panel\" (click)=\"$event.stopPropagation()\" role=\"dialog\" aria-label=\"Command help\">\n <div class=\"help-panel-header\">\n <span class=\"help-panel-title\">Help</span>\n <button class=\"help-panel-close\" type=\"button\" (click)=\"dismissHelp()\" aria-label=\"Close help\">\u2715</button>\n </div>\n <div class=\"help-panel-content\">{{ helpText }}</div>\n <div class=\"help-panel-footer\">\n <span>Tip: for most commands you can swap the first and second words \u2014 e.g. \"disable user\" works the same as \"user disable\"</span>\n <span class=\"help-panel-footer-dismiss\">Press Escape, click outside, or start typing to close</span>\n </div>\n </div>\n </div>\n }\n</div>\n", styles: [".shell{position:relative;display:grid;grid-template-areas:\"status status\" \"menu main\" \"resize resize\" \"terminal terminal\";grid-template-columns:56px 1fr;grid-template-rows:48px 1fr 4px var(--terminal-height, 160px);height:100vh;width:100vw;overflow:hidden;background-color:var(--color-surface-dark)}.shell.terminal-hidden{grid-template-rows:48px 1fr 0 0}.shell-status{grid-area:status}.shell-menu{grid-area:menu}.shell-main{grid-area:main;overflow:hidden}.shell-main.full-width{grid-column:1 / -1}.shell-resize{grid-area:resize;cursor:row-resize;background-color:var(--color-surface-border);transition:background-color .15s ease}.shell-resize:hover,.shell-resize.dragging{background-color:var(--color-interactive)}.shell-terminal{grid-area:terminal}.shell.is-dragging{user-select:none;-webkit-user-select:none}.disabled-zone{pointer-events:none;opacity:.4;transition:opacity .2s ease}.help-backdrop{position:absolute;inset:0;z-index:100;background-color:#000000a6;display:flex;align-items:center;justify-content:center}.help-panel{background-color:var(--color-surface, #161b22);border:2px solid var(--color-interactive, #00e5ff);border-radius:4px;width:70%;max-width:820px;max-height:75vh;display:flex;flex-direction:column;font-family:Roboto Mono,Courier New,monospace;font-size:.85rem}.help-panel-header{display:flex;justify-content:space-between;align-items:center;padding:8px 16px;background-color:var(--color-surface-light, #21262d);border-bottom:1px solid var(--color-interactive, #00e5ff);border-radius:2px 2px 0 0;flex-shrink:0}.help-panel-title{color:var(--color-interactive, #00e5ff);font-weight:700;letter-spacing:.05em;text-transform:uppercase;font-size:.75rem}.help-panel-close{background:none;border:1px solid var(--color-surface-border, #30363d);color:var(--color-secondary-info, #9e9e9e);cursor:pointer;padding:2px 8px;font-size:.9rem;line-height:1.4;border-radius:3px;transition:color .15s ease,border-color .15s ease}.help-panel-close:hover{color:var(--color-text-primary, #ffffff);border-color:var(--color-interactive, #00e5ff)}.help-panel-content{flex:1;overflow-y:auto;padding:16px 20px;color:var(--color-text-primary, #ffffff);white-space:pre-wrap;line-height:1.7}.help-panel-footer{padding:6px 16px;background-color:var(--color-surface-light, #21262d);border-top:1px solid var(--color-surface-border, #30363d);border-radius:0 0 2px 2px;color:var(--color-secondary-info, #9e9e9e);font-size:.75rem;flex-shrink:0;display:flex;flex-direction:column;gap:2px}.help-panel-footer-dismiss{opacity:.6}\n"], dependencies: [{ kind: "component", type: StatusBar, selector: "shell-status-bar" }, { kind: "component", type: SideMenu, selector: "shell-side-menu" }, { kind: "component", type: MainContent, selector: "shell-main-content" }, { kind: "component", type: CommandTerminal, selector: "shell-command-terminal" }, { kind: "component", type: FaqModal, selector: "faq-modal" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
|
|
2489
2535
|
}
|
|
2490
2536
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: Shell, decorators: [{
|
|
2491
2537
|
type: Component,
|
|
2492
|
-
args: [{ selector: 'shell-root', imports: [StatusBar, SideMenu, MainContent, CommandTerminal, FaqModal], changeDetection: ChangeDetectionStrategy.Eager, template: "<div class=\"shell\" [style.--terminal-height]=\"terminalHeight()\" [class.is-dragging]=\"isDragging()\">\n <shell-status-bar class=\"shell-status\" [class.disabled-zone]=\"isThinking()\">\n <ng-content />\n </shell-status-bar>\n @if (isAuthenticated()) {\n <shell-side-menu class=\"shell-menu\" [class.disabled-zone]=\"isThinking()\" />\n }\n <shell-main-content class=\"shell-main\" [class.full-width]=\"!isAuthenticated()\" />\n <div class=\"shell-resize\" [class.dragging]=\"isDragging()\" (mousedown)=\"onResizeStart($event)\"></div>\n
|
|
2538
|
+
args: [{ selector: 'shell-root', imports: [StatusBar, SideMenu, MainContent, CommandTerminal, FaqModal], changeDetection: ChangeDetectionStrategy.Eager, template: "<div class=\"shell\" [style.--terminal-height]=\"terminalHeight()\" [class.is-dragging]=\"isDragging()\" [class.terminal-hidden]=\"!terminalVisible()\">\n <shell-status-bar class=\"shell-status\" [class.disabled-zone]=\"isThinking()\">\n <ng-content />\n </shell-status-bar>\n @if (isAuthenticated()) {\n <shell-side-menu class=\"shell-menu\" [class.disabled-zone]=\"isThinking()\" />\n }\n <shell-main-content class=\"shell-main\" [class.full-width]=\"!isAuthenticated()\" />\n @if (terminalVisible()) {\n <div class=\"shell-resize\" [class.dragging]=\"isDragging()\" (mousedown)=\"onResizeStart($event)\"></div>\n <shell-command-terminal class=\"shell-terminal\" [class.disabled-zone]=\"isThinking()\" />\n }\n <faq-modal />\n\n @if (helpOverlay(); as helpText) {\n <div class=\"help-backdrop\" (click)=\"dismissHelp()\">\n <div class=\"help-panel\" (click)=\"$event.stopPropagation()\" role=\"dialog\" aria-label=\"Command help\">\n <div class=\"help-panel-header\">\n <span class=\"help-panel-title\">Help</span>\n <button class=\"help-panel-close\" type=\"button\" (click)=\"dismissHelp()\" aria-label=\"Close help\">\u2715</button>\n </div>\n <div class=\"help-panel-content\">{{ helpText }}</div>\n <div class=\"help-panel-footer\">\n <span>Tip: for most commands you can swap the first and second words \u2014 e.g. \"disable user\" works the same as \"user disable\"</span>\n <span class=\"help-panel-footer-dismiss\">Press Escape, click outside, or start typing to close</span>\n </div>\n </div>\n </div>\n }\n</div>\n", styles: [".shell{position:relative;display:grid;grid-template-areas:\"status status\" \"menu main\" \"resize resize\" \"terminal terminal\";grid-template-columns:56px 1fr;grid-template-rows:48px 1fr 4px var(--terminal-height, 160px);height:100vh;width:100vw;overflow:hidden;background-color:var(--color-surface-dark)}.shell.terminal-hidden{grid-template-rows:48px 1fr 0 0}.shell-status{grid-area:status}.shell-menu{grid-area:menu}.shell-main{grid-area:main;overflow:hidden}.shell-main.full-width{grid-column:1 / -1}.shell-resize{grid-area:resize;cursor:row-resize;background-color:var(--color-surface-border);transition:background-color .15s ease}.shell-resize:hover,.shell-resize.dragging{background-color:var(--color-interactive)}.shell-terminal{grid-area:terminal}.shell.is-dragging{user-select:none;-webkit-user-select:none}.disabled-zone{pointer-events:none;opacity:.4;transition:opacity .2s ease}.help-backdrop{position:absolute;inset:0;z-index:100;background-color:#000000a6;display:flex;align-items:center;justify-content:center}.help-panel{background-color:var(--color-surface, #161b22);border:2px solid var(--color-interactive, #00e5ff);border-radius:4px;width:70%;max-width:820px;max-height:75vh;display:flex;flex-direction:column;font-family:Roboto Mono,Courier New,monospace;font-size:.85rem}.help-panel-header{display:flex;justify-content:space-between;align-items:center;padding:8px 16px;background-color:var(--color-surface-light, #21262d);border-bottom:1px solid var(--color-interactive, #00e5ff);border-radius:2px 2px 0 0;flex-shrink:0}.help-panel-title{color:var(--color-interactive, #00e5ff);font-weight:700;letter-spacing:.05em;text-transform:uppercase;font-size:.75rem}.help-panel-close{background:none;border:1px solid var(--color-surface-border, #30363d);color:var(--color-secondary-info, #9e9e9e);cursor:pointer;padding:2px 8px;font-size:.9rem;line-height:1.4;border-radius:3px;transition:color .15s ease,border-color .15s ease}.help-panel-close:hover{color:var(--color-text-primary, #ffffff);border-color:var(--color-interactive, #00e5ff)}.help-panel-content{flex:1;overflow-y:auto;padding:16px 20px;color:var(--color-text-primary, #ffffff);white-space:pre-wrap;line-height:1.7}.help-panel-footer{padding:6px 16px;background-color:var(--color-surface-light, #21262d);border-top:1px solid var(--color-surface-border, #30363d);border-radius:0 0 2px 2px;color:var(--color-secondary-info, #9e9e9e);font-size:.75rem;flex-shrink:0;display:flex;flex-direction:column;gap:2px}.help-panel-footer-dismiss{opacity:.6}\n"] }]
|
|
2493
2539
|
}] });
|
|
2494
2540
|
|
|
2495
2541
|
class Login {
|
|
@@ -2652,5 +2698,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
2652
2698
|
* Generated bundle index. Do not edit.
|
|
2653
2699
|
*/
|
|
2654
2700
|
|
|
2655
|
-
export { AuthenticationService, CLEAR_USAGE, CommandRegistryService, CommandService, CommandTerminal, ConfirmDialog, FAQ_CONTENT_LOADER, FAQ_DEV_EDITOR, FAQ_DEV_MODE, FAQ_DEV_WORKSPACE_ROOT, FAQ_PUBLIC_PUBLISHER, FAQ_PUBLIC_SITE_BASE_URL, FaqAuthoringPanel, FaqHistoryService, FaqMarkdownRendererService, FaqModal, FaqService, HELP_USAGE, HttpFaqContentLoader, KeyboardShortcutService, Login, MainContent, PublicFaqIndex, PublicFaqPage, PublicFaqToc, RegexValidatorDirective, SHELL_APP_NAME, SHELL_AUTH_URLS, SHELL_COMMANDS, SHELL_MENU_ITEMS, SHELL_POST_LOGIN_ROUTE, Shell, SideMenu, StatusBar, TerminalFocusService, ThemeService, ThinkingService, audienceAllowed, authGuard, authInterceptor, buildFallbackChain, guestGuard, provideShellConfig, tokenize };
|
|
2701
|
+
export { AuthenticationService, CLEAR_USAGE, CommandRegistryService, CommandService, CommandTerminal, ConfirmDialog, FAQ_CONTENT_LOADER, FAQ_DEV_EDITOR, FAQ_DEV_MODE, FAQ_DEV_WORKSPACE_ROOT, FAQ_PUBLIC_PUBLISHER, FAQ_PUBLIC_SITE_BASE_URL, FaqAuthoringPanel, FaqHistoryService, FaqMarkdownRendererService, FaqModal, FaqService, HELP_USAGE, HttpFaqContentLoader, KeyboardShortcutService, Login, MainContent, PublicFaqIndex, PublicFaqPage, PublicFaqToc, RegexValidatorDirective, SHELL_APP_NAME, SHELL_AUTH_URLS, SHELL_COMMANDS, SHELL_MENU_ITEMS, SHELL_POST_LOGIN_ROUTE, Shell, SideMenu, StatusBar, TerminalFocusService, TerminalVisibilityService, ThemeService, ThinkingService, audienceAllowed, authGuard, authInterceptor, buildFallbackChain, guestGuard, provideShellConfig, tokenize };
|
|
2656
2702
|
//# sourceMappingURL=franzzemen-brokenstock-shell.mjs.map
|