@@ -9,22 +9,22 @@ import { FontPresetsService } from '../../services/font-presets.service';
99 template : `
1010 <div class="flex-1 overflow-hidden flex flex-col rounded-lg" [ngStyle]="windowStyles()">
1111 @if (!hideDecorations()) {
12- <div class="flex items-center px-3 py-2 select-none border-b"
13- [style.background]="titleBarBg()"
14- [style.border-color]="borderColor()">
12+ <div class="flex items-center px-3 py-2 select-none border-b" [style.background]="titleBarBg()" [style.border-color]="borderColor()">
1513 <div class="flex items-center gap-1.5">
1614 <div class="w-3 h-3 rounded-full" style="background: #ff5f56;"></div>
1715 <div class="w-3 h-3 rounded-full" style="background: #ffbd2e;"></div>
1816 <div class="w-3 h-3 rounded-full" style="background: #27c93f;"></div>
1917 </div>
20- <span class="flex-1 text-center text-xs select-none opacity-50"
21- [style.font-family]="terminalFont()"
22- [style.color]="colors().foreground">bash</span>
18+ <span class="flex-1 text-center text-xs select-none opacity-50" [style.font-family]="terminalFont()" [style.color]="colors().foreground">bash</span>
2319 </div>
2420 }
2521
2622 @if (tabBarVisible() && tabBarEdge() === 'top') {
27- <ng-container *ngTemplateOutlet="tabBar"></ng-container>
23+ <div class="flex bg-opacity-90" [style.background]="tabBarBg()">
24+ @for (tab of tabs; track tab.name; let i = $index) {
25+ <div class="px-4 py-1.5 text-xs" [ngStyle]="tabStyles(i === 0)">{{ tab.name }}</div>
26+ }
27+ </div>
2828 }
2929
3030 <div class="flex-1 overflow-hidden relative p-3" [ngStyle]="terminalStyles()">
@@ -52,88 +52,32 @@ import { FontPresetsService } from '../../services/font-presets.service';
5252 <span [style.color]="c('color4')">arch</span>
5353 <span [style.color]="c('foreground')" class="opacity-60">:~$ </span>
5454 <span [style.color]="c('foreground')">cat </span>
55- <span class="url-text" [style.color]="urlColor()" [style.text-decoration]="urlUnderline()" >https://sw.kovidgoyal.net/kitty/</span>
55+ <span class="url-text" [style.color]="urlColor()">https://sw.kovidgoyal.net/kitty/</span>
5656 </div>
5757 <div class="whitespace-nowrap mt-2">
5858 <span [style.color]="c('color2')">user</span>
5959 <span [style.color]="c('foreground')" class="opacity-60">@</span>
6060 <span [style.color]="c('color4')">arch</span>
6161 <span [style.color]="c('foreground')" class="opacity-60">:~$ </span>
6262 @if (cursorShape() === 'block') {
63- <span class="inline-block w-2 h-4 align-text-bottom"
64- [class.animate-blink]="cursorBlinking()"
65- [style.background]="cursorColor()"
66- [style.color]="cursorTextColor()"> </span>
63+ <span class="inline-block w-2 h-4 align-text-bottom" [class.animate-blink]="cursorBlinking()" [style.background]="cursorColor()"> </span>
6764 } @else if (cursorShape() === 'beam') {
68- <span class="inline-block w-0.5 h-4 align-text-bottom border-l-2"
69- [class.animate-blink]="cursorBlinking()"
70- [style.border-color]="cursorColor()"></span>
65+ <span class="inline-block w-0.5 h-4 align-text-bottom border-l-2" [class.animate-blink]="cursorBlinking()" [style.border-color]="cursorColor()"></span>
7166 } @else {
72- <span class="inline-block w-2 h-4 align-text-bottom border-b-2"
73- [class.animate-blink]="cursorBlinking()"
74- [style.border-color]="cursorColor()"> </span>
67+ <span class="inline-block w-2 h-4 align-text-bottom border-b-2" [class.animate-blink]="cursorBlinking()" [style.border-color]="cursorColor()"> </span>
7568 }
7669 </div>
7770 </div>
7871 </div>
7972
8073 @if (tabBarVisible() && tabBarEdge() === 'bottom') {
81- <ng-container *ngTemplateOutlet="tabBar"></ng-container>
74+ <div class="flex bg-opacity-90" [style.background]="tabBarBg()">
75+ @for (tab of tabs; track tab.name; let i = $index) {
76+ <div class="px-4 py-1.5 text-xs" [ngStyle]="tabStyles(i === 0)">{{ tab.name }}</div>
77+ }
78+ </div>
8279 }
8380 </div>
84-
85- <ng-template #tabBar>
86- <div class="flex items-stretch overflow-hidden select-none" [ngStyle]="tabBarContainerStyles()">
87- @switch (tabBarStyle()) {
88- @case ('fade') {
89- @for (tab of tabs; track tab.name; let i = $index; let first = $first) {
90- @if (!first) { <div class="w-px" [style.background]="tabBarBg()"></div> }
91- <div class="px-3 py-1.5 text-xs whitespace-nowrap flex items-center" [ngStyle]="fadeTabStyles(i === 0, i)">{{ tab.name }}</div>
92- }
93- <div class="flex-1" [style.background]="tabBarBg()"></div>
94- }
95- @case ('separator') {
96- @for (tab of tabs; track tab.name; let i = $index; let first = $first) {
97- @if (!first) {
98- <div class="px-1 py-1.5 text-xs flex items-center opacity-50" [style.color]="inactiveTabColor()">{{ tabSeparator() }}</div>
99- }
100- <div class="px-3 py-1.5 text-xs whitespace-nowrap flex items-center" [ngStyle]="simpleTabStyles(i === 0)">{{ tab.name }}</div>
101- }
102- <div class="flex-1" [style.background]="tabBarBg()"></div>
103- }
104- @case ('slant') {
105- @for (tab of tabs; track tab.name; let i = $index) {
106- <div class="px-3 py-1.5 text-xs whitespace-nowrap flex items-center relative" [ngStyle]="slantTabStyles(i === 0)">
107- <span class="relative z-10">{{ tab.name }}</span>
108- </div>
109- }
110- <div class="flex-1" [style.background]="tabBarBg()"></div>
111- }
112- @case ('powerline') {
113- @for (tab of tabs; track tab.name; let i = $index) {
114- <div class="flex items-center">
115- <div class="px-3 py-1.5 text-xs whitespace-nowrap flex items-center" [ngStyle]="simpleTabStyles(i === 0)">
116- {{ tab.name }}
117- </div>
118- @if (i < tabs.length - 1) {
119- <svg width="14" height="24" viewBox="0 0 14 24" preserveAspectRatio="none" class="flex-shrink-0">
120- <path d="M0,0 L14,12 L0,24 Z" [attr.fill]="tabBgColor(i === 0)"/>
121- <path d="M0,0 L14,12 L0,24 L14,24 L14,0 Z" [attr.fill]="tabBgColor(false)"/>
122- </svg>
123- }
124- </div>
125- }
126- <div class="flex-1" [style.background]="tabBarBg()"></div>
127- }
128- @default {
129- @for (tab of tabs; track tab.name; let i = $index) {
130- <div class="px-3 py-1.5 text-xs whitespace-nowrap flex items-center" [ngStyle]="simpleTabStyles(i === 0)">{{ tab.name }}</div>
131- }
132- <div class="flex-1" [style.background]="tabBarBg()"></div>
133- }
134- }
135- </div>
136- </ng-template>
13781 ` ,
13882 styles : [ `
13983 .url-text { text-decoration: underline; cursor: pointer; }
@@ -162,7 +106,6 @@ export class TerminalWindowComponent {
162106 mouseCfg = computed ( ( ) => this . store . configState ( ) . mouse ) ;
163107
164108 c ( key : string ) : string { return ( this . colors ( ) as unknown as Record < string , string > ) [ key ] || '#888888' ; }
165-
166109 terminalFont = computed ( ( ) => { const f = this . fonts ( ) . font_family ; return `"${ f } ", "JetBrains Mono", monospace` ; } ) ;
167110
168111 windowStyles = computed ( ( ) => {
@@ -174,7 +117,6 @@ export class TerminalWindowComponent {
174117 titleBarBg = computed ( ( ) => this . darken ( this . colors ( ) . background , 10 ) ) ;
175118 borderColor = computed ( ( ) => this . darken ( this . colors ( ) . background , 20 ) ) ;
176119 tabBarBg = computed ( ( ) => { const cfg = this . tabBarCfg ( ) ; return ( cfg . tab_bar_background && cfg . tab_bar_background !== 'none' ) ? cfg . tab_bar_background : this . darken ( this . colors ( ) . background , 8 ) ; } ) ;
177-
178120 hideDecorations = computed ( ( ) => this . windowCfg ( ) . hide_window_decorations ) ;
179121
180122 terminalStyles = computed ( ( ) => {
@@ -188,47 +130,18 @@ export class TerminalWindowComponent {
188130
189131 tabBarVisible = computed ( ( ) => { const cfg = this . tabBarCfg ( ) ; const minTabs = cfg . tab_bar_min_tabs ?? 2 ; return cfg . tab_bar_style !== 'hidden' && 3 >= minTabs ; } ) ;
190132 tabBarEdge = computed ( ( ) => this . tabBarCfg ( ) . tab_bar_edge ) ;
191- tabBarStyle = computed ( ( ) => this . tabBarCfg ( ) . tab_bar_style ) ;
192- tabSeparator = computed ( ( ) => this . tabBarCfg ( ) . tab_separator || ' ┇' ) ;
193-
194- tabBarContainerStyles = computed ( ( ) => ( { background : this . tabBarBg ( ) , borderTop : this . tabBarEdge ( ) === 'bottom' ? `1px solid ${ this . borderColor ( ) } ` : 'none' , borderBottom : this . tabBarEdge ( ) === 'top' ? `1px solid ${ this . borderColor ( ) } ` : 'none' } ) ) ;
195- inactiveTabColor = computed ( ( ) => this . tabBarCfg ( ) . inactive_tab_foreground ) ;
196-
197- simpleTabStyles ( isActive : boolean ) : Record < string , string > {
198- const cfg = this . tabBarCfg ( ) ;
199- return isActive ? { background : cfg . active_tab_background , color : cfg . active_tab_foreground , fontWeight : '600' } : { background : cfg . inactive_tab_background , color : cfg . inactive_tab_foreground } ;
200- }
201-
202- fadeTabStyles ( isActive : boolean , index : number ) : Record < string , string > {
203- const cfg = this . tabBarCfg ( ) ;
204- const fade = cfg . tab_fade || [ 0.25 , 0.5 , 0.75 , 1 ] ;
205- const fadeVal = isActive ? 1 : ( fade [ Math . min ( index , fade . length - 1 ) ] ?? 1 ) ;
206- return isActive ? { background : cfg . active_tab_background , color : cfg . active_tab_foreground , fontWeight : '600' } : { background : cfg . inactive_tab_background , color : cfg . inactive_tab_foreground , opacity : String ( fadeVal ) } ;
207- }
208-
209- slantTabStyles ( isActive : boolean ) : Record < string , string > {
210- const cfg = this . tabBarCfg ( ) ;
211- return isActive ? { background : cfg . active_tab_background , color : cfg . active_tab_foreground , fontWeight : '600' } : { background : cfg . inactive_tab_background , color : cfg . inactive_tab_foreground } ;
212- }
213133
214- powerlineTabStyles ( isActive : boolean ) : Record < string , string > {
134+ tabStyles ( isActive : boolean ) : Record < string , string > {
215135 const cfg = this . tabBarCfg ( ) ;
216- const bg = isActive ? cfg . active_tab_background : cfg . inactive_tab_background ;
217- return { background : bg , color : isActive ? cfg . active_tab_foreground : cfg . inactive_tab_foreground , fontWeight : isActive ? '600' : '400' , '--tab-bg' : bg } as Record < string , string > ;
218- }
219-
220- tabBgColor ( isActive : boolean ) : string {
221- const cfg = this . tabBarCfg ( ) ;
222- return isActive ? cfg . active_tab_background : cfg . inactive_tab_background ;
136+ return isActive
137+ ? { background : cfg . active_tab_background , color : cfg . active_tab_foreground , fontWeight : '600' }
138+ : { background : cfg . inactive_tab_background , color : cfg . inactive_tab_foreground } ;
223139 }
224140
225141 cursorShape = computed ( ( ) => this . cursorCfg ( ) . cursor_shape ) ;
226142 cursorColor = computed ( ( ) => { const c = this . cursorCfg ( ) . cursor ; return c === 'none' || ! c ?. startsWith ( '#' ) ? this . colors ( ) . foreground : c ; } ) ;
227- cursorTextColor = computed ( ( ) => { const c = this . cursorCfg ( ) . cursor_text_color ; return c === 'background' ? this . colors ( ) . background : ( c ?. startsWith ( '#' ) ? c : this . colors ( ) . background ) ; } ) ;
228143 cursorBlinking = computed ( ( ) => this . cursorCfg ( ) . cursor_blink_interval !== 0 ) ;
229-
230144 urlColor = computed ( ( ) => this . mouseCfg ( ) . url_color || this . colors ( ) . color4 || '#0087bd' ) ;
231- urlUnderline = computed ( ( ) => { const style = this . mouseCfg ( ) . url_style ; if ( style === 'none' ) return 'none' ; if ( style === 'double' ) return 'underline double' ; if ( style === 'curly' ) return 'underline wavy' ; if ( style === 'dashed' ) return 'underline dashed' ; if ( style === 'dotted' ) return 'underline dotted' ; return 'underline' ; } ) ;
232145
233146 private parseBorderWidth ( val : string ) : string { if ( ! val || val === '0' || val === '0pt' || val === '0px' ) return '0px' ; if ( val . endsWith ( 'pt' ) ) { const n = Number . parseFloat ( val ) ; return `${ Math . max ( 0 , Math . round ( n * 1.333 ) ) } px` ; } return val . endsWith ( 'px' ) ? val : '1px' ; }
234147 private darken ( hex : string , amount : number ) : string { if ( ! hex ?. startsWith ( '#' ) ) return '#333' ; const c = hex . slice ( 1 ) ; if ( c . length !== 6 ) return hex ; const r = Math . max ( 0 , Math . min ( 255 , Number . parseInt ( c . slice ( 0 , 2 ) , 16 ) - amount ) ) ; const g = Math . max ( 0 , Math . min ( 255 , Number . parseInt ( c . slice ( 2 , 4 ) , 16 ) - amount ) ) ; const b = Math . max ( 0 , Math . min ( 255 , Number . parseInt ( c . slice ( 4 , 6 ) , 16 ) - amount ) ) ; return `#${ r . toString ( 16 ) . padStart ( 2 , '0' ) } ${ g . toString ( 16 ) . padStart ( 2 , '0' ) } ${ b . toString ( 16 ) . padStart ( 2 , '0' ) } ` ; }
0 commit comments