1
1
mirror of https://github.com/Eugeny/tabby.git synced 2024-12-23 10:32:29 +03:00
This commit is contained in:
Eugene Pankov 2017-06-01 22:23:36 +02:00
parent c0f7cd9a7a
commit 73722c0b2f
31 changed files with 2946 additions and 589 deletions

View File

@ -18,16 +18,21 @@ if (process.env.DEV) {
nodeModule.globalPaths.unshift(path.dirname(require('electron').remote.app.getAppPath()))
}
nodeModule.globalPaths.unshift(path.join(
const builtinPluginsPath = path.join(
path.dirname(require('electron').remote.app.getPath('exe')),
(process.platform === 'darwin') ? '../Resources' : 'resources',
'builtin-plugins/node_modules',
))
nodeModule.globalPaths.unshift(path.join(
)
const userPluginsPath = path.join(
require('electron').remote.app.getPath('appData'),
'terminus',
'plugins',
))
)
Object.assign(window, { builtinPluginsPath, userPluginsPath })
nodeModule.globalPaths.unshift(builtinPluginsPath)
nodeModule.globalPaths.unshift(userPluginsPath)
if (process.env.TERMINUS_PLUGINS) {
process.env.TERMINUS_PLUGINS.split(':').map(x => nodeModule.globalPaths.unshift(normalizePath(x)))
@ -35,15 +40,20 @@ if (process.env.TERMINUS_PLUGINS) {
export declare type ProgressCallback = (current, total) => void
interface IPluginEntry {
export interface IPluginInfo {
name: string
path: string
info: any
description: string
packageName: string
isBuiltin: boolean
version: string
homepage?: string
path?: string
info?: any
}
export async function findPlugins (): Promise<IPluginEntry[]> {
export async function findPlugins (): Promise<IPluginInfo[]> {
let paths = nodeModule.globalPaths
let foundPlugins: IPluginEntry[] = []
let foundPlugins: IPluginInfo[] = []
for (let pluginDir of paths) {
pluginDir = normalizePath(pluginDir)
@ -63,10 +73,16 @@ export async function findPlugins (): Promise<IPluginEntry[]> {
}
try {
let info = await fs.readJson(infoPath)
console.log(pluginDir, builtinPluginsPath)
foundPlugins.push({
name: pluginName,
name: pluginName.substring('terminus-'.length),
packageName: pluginName,
isBuiltin: pluginDir === builtinPluginsPath,
version: info.version,
description: info.description,
path: pluginPath,
info: await fs.readJson(infoPath),
info,
})
} catch (error) {
console.error('Cannot load package info for', pluginName)
@ -74,10 +90,11 @@ export async function findPlugins (): Promise<IPluginEntry[]> {
}
}
(window as any).installedPlugins = foundPlugins
return foundPlugins
}
export async function loadPlugins (foundPlugins: IPluginEntry[], progress: ProgressCallback): Promise<any[]> {
export async function loadPlugins (foundPlugins: IPluginInfo[], progress: ProgressCallback): Promise<any[]> {
let plugins: any[] = []
progress(0, 1)
let index = 0

View File

@ -8,9 +8,7 @@ exports.builtinPlugins = [
'terminus-core',
'terminus-settings',
'terminus-terminal',
'terminus-clickable-links',
'terminus-community-color-schemes',
'terminus-theme-hype',
]
exports.version = appInfo.version
exports.electronVersion = pkgInfo.devDependencies.electron

View File

@ -1,2 +0,0 @@
dist
node_modules

View File

@ -1,27 +0,0 @@
{
"name": "terminus-clickable-links",
"version": "0.0.1",
"description": "Makes URLs and file paths clickable in Terminus",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"scripts": {
"build": "webpack --progress --color",
"watch": "webpack --progress --color --watch"
},
"files": ["dist"],
"author": "Eugene Pankov",
"license": "MIT",
"devDependencies": {
"awesome-typescript-loader": "^3.1.2",
"typescript": "^2.2.2",
"webpack": "^2.3.3"
},
"peerDependencies": {
"@angular/core": "^4.0.1",
"terminus-core": "*",
"terminus-terminal": "*"
},
"dependencies": {
"untildify": "^3.0.2"
}
}

View File

@ -1,6 +0,0 @@
export abstract class LinkHandler {
regex: string
convert (uri: string): string { return uri }
verify (_uri: string): boolean { return true }
abstract handle (uri: string): void
}

View File

@ -1,95 +0,0 @@
import { Observable } from 'rxjs'
import { Inject, Injectable } from '@angular/core'
import { TerminalDecorator, TerminalTabComponent } from 'terminus-terminal'
import { LinkHandler } from './api'
@Injectable()
export class LinkHighlighterDecorator extends TerminalDecorator {
constructor (@Inject(LinkHandler) private handlers: LinkHandler[]) {
super()
}
attach (terminal: TerminalTabComponent): void {
return
terminal.contentUpdated$
.throttle(() => Observable.from([500]))
.subscribe(() => {
//this.insertLinks(terminal.hterm.screen_)
})
}
insertLinks (screen) {
if ('#text' === screen.cursorNode_.nodeName) {
// replace text node to element
const cursorNode = document.createElement('span')
cursorNode.textContent = screen.cursorNode_.textContent
screen.cursorRowNode_.replaceChild(cursorNode, screen.cursorNode_)
screen.cursorNode_ = cursorNode
}
const traverse = (parentNode: Node) => {
Array.from(parentNode.childNodes).forEach((node) => {
if (node.nodeName === '#text') {
parentNode.replaceChild(this.urlizeNode(node), node)
} else if (node.nodeName !== 'A') {
traverse(node)
}
})
}
screen.rowsArray.forEach((x) => traverse(x))
}
urlizeNode (node) {
let matches = []
this.handlers.forEach((handler) => {
let regex = new RegExp(handler.regex, 'gi')
while (true) {
let match = regex.exec(node.textContent)
if (!match) {
break
}
let uri = handler.convert(match[0])
if (!handler.verify(uri)) {
continue
}
matches.push({
start: regex.lastIndex - match[0].length,
end: regex.lastIndex,
text: match[0],
uri,
handler
})
}
})
if (matches.length === 0) {
return node
}
matches.sort((a, b) => a.start < b.start ? -1 : 1)
let span = document.createElement('span')
let position = 0
matches.forEach((match) => {
if (match.start < position) {
return
}
if (match.start > position) {
span.appendChild(document.createTextNode(node.textContent.slice(position, match.start)))
}
let a = document.createElement('a')
a.textContent = match.text
a.addEventListener('click', () => {
match.handler.handle(match.uri)
})
span.appendChild(a)
position = match.end
})
span.appendChild(document.createTextNode(node.textContent.slice(position)))
return span
}
}

View File

@ -1,40 +0,0 @@
import * as fs from 'fs'
const untildify = require('untildify')
import { Injectable } from '@angular/core'
import { ElectronService } from 'terminus-core'
import { LinkHandler } from './api'
@Injectable()
export class URLHandler extends LinkHandler {
regex = 'http(s)?://[^\\s;\'"]+[^,;\\s]'
constructor (private electron: ElectronService) {
super()
}
handle (uri: string) {
this.electron.shell.openExternal(uri)
}
}
@Injectable()
export class FileHandler extends LinkHandler {
regex = '[~/][^\\s,;\'"]+'
constructor (private electron: ElectronService) {
super()
}
convert (uri: string): string {
return untildify(uri)
}
verify (uri: string) {
return fs.existsSync(uri)
}
handle (uri: string) {
this.electron.shell.openExternal('file://' + uri)
}
}

View File

@ -1,22 +0,0 @@
/*
This plugin is based on Hyperterm Hyperlinks:
https://github.com/zeit/hyperlinks/blob/master/index.js
*/
import { NgModule } from '@angular/core'
import { TerminalDecorator } from 'terminus-terminal'
import { LinkHandler } from './api'
import { FileHandler, URLHandler } from './handlers'
import { LinkHighlighterDecorator } from './decorator'
@NgModule({
providers: [
{ provide: LinkHandler, useClass: FileHandler, multi: true },
{ provide: LinkHandler, useClass: URLHandler, multi: true },
{ provide: TerminalDecorator, useClass: LinkHighlighterDecorator, multi: true },
],
})
export default class LinkHighlighterModule { }
export * from './api'

View File

@ -1,42 +0,0 @@
const path = require('path')
module.exports = {
target: 'node',
entry: 'src/index.ts',
devtool: 'source-map',
context: __dirname,
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index.js',
pathinfo: true,
libraryTarget: 'umd',
devtoolModuleFilenameTemplate: 'webpack-terminus-clickable-links:///[resource-path]',
},
resolve: {
modules: ['.', 'src', 'node_modules', '../app/node_modules'].map(x => path.join(__dirname, x)),
extensions: ['.ts', '.js'],
},
module: {
loaders: [
{
test: /\.ts$/,
loader: 'awesome-typescript-loader',
query: {
configFileName: path.resolve(__dirname, 'tsconfig.json'),
paths: {
"terminus-*": [path.resolve(__dirname, '../terminus-*')],
"*": [path.resolve(__dirname, '../app/node_modules/*')],
}
}
},
]
},
externals: [
'fs',
'untildify',
/^rxjs/,
/^@angular/,
/^@ng-bootstrap/,
/^terminus-/,
]
}

View File

@ -17,7 +17,6 @@
"@types/js-yaml": "^3.5.29",
"@types/node": "^7.0.12",
"@types/webpack-env": "^1.13.0",
"angular2-toaster": "3.0.1",
"awesome-typescript-loader": "^3.1.2",
"bootstrap": "4.0.0-alpha.6",
"core-js": "^2.4.1",

View File

@ -65,5 +65,4 @@ title-bar(
[scrollable]='tab.scrollable',
)
toaster-container([toasterconfig]="toasterconfig")
ng-template(ngbModalContainer)

View File

@ -1,6 +1,5 @@
import { Component, Inject, Input } from '@angular/core'
import { trigger, style, animate, transition, state } from '@angular/animations'
import { ToasterConfig } from 'angular2-toaster'
import { ElectronService } from '../services/electron.service'
import { HostAppService, Platform } from '../services/hostApp.service'
@ -41,7 +40,6 @@ import { AppService, IToolbarButton, ToolbarButtonProvider } from '../api'
]
})
export class AppRootComponent {
toasterConfig: ToasterConfig
Platform = Platform
@Input() ready = false
@Input() leftToolbarButtons: IToolbarButton[]
@ -64,12 +62,6 @@ export class AppRootComponent {
this.logger = log.create('main')
this.logger.info('v', electron.app.getVersion())
this.toasterConfig = new ToasterConfig({
mouseoverTimerStop: true,
preventDuplicates: true,
timeout: 4000,
})
this.leftToolbarButtons = this.getToolbarButtons(false)
this.rightToolbarButtons = this.getToolbarButtons(true)

View File

@ -2,7 +2,6 @@ import { NgModule, ModuleWithProviders } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
import { FormsModule } from '@angular/forms'
import { ToasterModule } from 'angular2-toaster'
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar'
@ -55,7 +54,6 @@ const PROVIDERS = [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
ToasterModule,
NgbModule,
PerfectScrollbarModule.forRoot({
suppressScrollX: true,

View File

@ -50,7 +50,7 @@ $input-bg-focus: $input-bg;
//$input-border-focus: lighten($brand-primary, 25%);
//$input-box-shadow-focus: $input-box-shadow, rgba($input-border-focus, .6);
$input-color-focus: $input-color;
$input-group-addon-bg: $input-bg;
$input-group-addon-bg: $body-bg2;
$input-group-addon-border-color: $input-border-color;
$modal-content-bg: $body-bg;
@ -69,7 +69,8 @@ $dropdown-link-hover-bg: $body-bg3;
$dropdown-link-disabled-color: #333;
$dropdown-header-color: #333;
$list-group-color: $body-color;
$list-group-bg: $body-bg2;
@import '~bootstrap/scss/bootstrap.scss';

2649
terminus-plugin-manager/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,46 @@
{
"name": "terminus-plugin-manager",
"version": "0.0.1",
"description": "Terminus' plugin manager",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"scripts": {
"build": "webpack --progress --color --display-modules",
"watch": "webpack --progress --color --watch"
},
"files": [
"dist"
],
"author": "Eugene Pankov",
"license": "MIT",
"devDependencies": {
"@types/mz": "0.0.31",
"@types/node": "7.0.12",
"@types/npm": "^2.0.28",
"@types/semver": "^5.3.31",
"@types/webpack-env": "1.13.0",
"awesome-typescript-loader": "3.1.2",
"css-loader": "^0.28.0",
"pug": "^2.0.0-beta11",
"pug-loader": "^2.3.0",
"raw-loader": "^0.5.1",
"sass-loader": "^6.0.3",
"semver": "^5.3.0",
"to-string-loader": "^1.1.5",
"typescript": "^2.2.2",
"webpack": "2.3.3"
},
"peerDependencies": {
"@angular/common": "4.0.1",
"@angular/core": "4.0.1",
"@angular/forms": "4.0.1",
"@angular/platform-browser": "4.0.1",
"@ng-bootstrap/ng-bootstrap": "1.0.0-alpha.22",
"terminus-core": "*",
"terminus-settings": "*",
"rxjs": "5.3.0"
},
"dependencies": {
"axios": "^0.16.1"
}
}

View File

@ -0,0 +1,46 @@
h3 Installed
.list-group
ng-container(*ngFor='let plugin of pluginManager.installedPlugins')
.list-group-item.flex-column.align-items-start(*ngIf='knownUpgrades[plugin.name]')
.d-flex.w-100
h6.mr-auto.mb-0 {{plugin.name}}
p.mb-0.mr-3 {{plugin.version}}
button.btn.btn-outline-primary((click)='upgradePlugin(plugin)')
i.fa.fa-arrow-up
span Upgrade ({{knownUpgrades[plugin.name].version}})
small.mb-0 {{plugin.description}}
ng-container(*ngFor='let plugin of pluginManager.installedPlugins')
.list-group-item.flex-column.align-items-start(*ngIf='!knownUpgrades[plugin.name]')
.d-flex.w-100
h6.mr-auto.mb-0 {{plugin.name}}
p.mb-0.mr-3 {{plugin.version}}
button.btn.btn-outline-danger((click)='uninstallPlugin(plugin)', *ngIf='!plugin.isBuiltin')
i.fa.fa-trash-o
small.mb-0 {{plugin.description}}
h3.mt-4 Available
.input-group.mb-4
.input-group-addon
i.fa.fa-fw.fa-circle-o-notch.fa-spin(*ngIf='!availablePluginsReady')
i.fa.fa-fw.fa-search(*ngIf='availablePluginsReady')
input.form-control(
type='text',
'[(ngModel)]'='_1',
(ngModelChange)='availablePluginsQuery$.next(_1)',
placeholder='Search plugins'
)
.list-group(*ngIf='availablePlugins$')
ng-container(*ngFor='let plugin of (availablePlugins$|async)')
.list-group-item.flex-column.align-items-start(*ngIf='!isAlreadyInstalled(plugin)')
.d-flex.w-100
h6.mr-auto.mb-0 {{plugin.name}}
p.mb-0.mr-3 {{plugin.version}}
button.btn.btn-outline-primary((click)='installPlugin(plugin)')
i.fa.fa-download
span Install
small.mb-0 {{plugin.description}}

View File

@ -0,0 +1,8 @@
.appearance-preview {
padding: 10px 20px;
margin: 0 0 10px;
overflow: hidden;
span {
white-space: pre;
}
}

View File

@ -0,0 +1,55 @@
import { BehaviorSubject, Observable } from 'rxjs'
import * as fs from 'fs-promise'
import * as path from 'path'
import * as semver from 'semver'
import { exec } from 'mz/child_process'
import { Component, Inject, ChangeDetectionStrategy } from '@angular/core'
import { IPluginInfo, PluginManagerService } from '../services/pluginManager.service'
@Component({
template: require('./pluginsSettingsTab.component.pug'),
styles: [require('./pluginsSettingsTab.component.scss')],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class PluginsSettingsTabComponent {
availablePlugins$: Observable<IPluginInfo[]>
availablePluginsQuery$ = new BehaviorSubject<string>('')
availablePluginsReady = false
knownUpgrades: {[id: string]: IPluginInfo} = {}
busy: boolean
constructor (
public pluginManager: PluginManagerService
) {
}
ngOnInit () {
this.availablePlugins$ = this.availablePluginsQuery$
.debounceTime(200)
.distinctUntilChanged()
.flatMap(query => {
this.availablePluginsReady = false
return this.pluginManager.listAvailable(query).do(() => {
this.availablePluginsReady = true
})
})
this.availablePlugins$.first().subscribe(available => {
for (let plugin of this.pluginManager.installedPlugins) {
this.knownUpgrades[plugin.name] = available.find(x => x.name === plugin.name && semver.gt(x.version, plugin.version))
}
})
}
isAlreadyInstalled (plugin: IPluginInfo): boolean {
return this.pluginManager.installedPlugins.some(x => x.name === plugin.name)
}
async installPlugin (plugin: IPluginInfo): Promise<void> {
this.busy = true
}
async upgradePlugin (plugin: IPluginInfo): Promise<void> {
return this.installPlugin(this.knownUpgrades[plugin.name])
}
}

View File

@ -0,0 +1,31 @@
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { FormsModule } from '@angular/forms'
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
import { SettingsTabProvider } from 'terminus-settings'
import { PluginsSettingsTabComponent } from './components/pluginsSettingsTab.component'
import { PluginManagerService } from './services/pluginManager.service'
import { PluginsSettingsTabProvider } from './settings'
@NgModule({
imports: [
BrowserModule,
FormsModule,
NgbModule,
],
providers: [
{ provide: SettingsTabProvider, useClass: PluginsSettingsTabProvider, multi: true },
PluginManagerService,
],
entryComponents: [
PluginsSettingsTabComponent,
],
declarations: [
PluginsSettingsTabComponent,
],
})
export default class PluginManagerModule { }
export { PluginManagerService }

View File

@ -0,0 +1,49 @@
import * as fs from 'fs-promise'
import { Observable } from 'rxjs'
import { Injectable } from '@angular/core'
import { Logger, LogService } from 'terminus-core'
import axios from 'axios'
const NAME_PREFIX = 'terminus-'
export interface IPluginInfo {
name: string
description: string
packageName: string
isBuiltin: boolean
version: string
homepage?: string
path?: string
}
@Injectable()
export class PluginManagerService {
logger: Logger
builtinPluginsPath: string = (window as any).builtinPluginsPath
userPluginsPath: string = (window as any).userPluginsPath
installedPlugins: IPluginInfo[] = (window as any).installedPlugins
constructor (
log: LogService,
) {
this.logger = log.create('pluginManager')
}
listAvailable (query?: string): Observable<IPluginInfo[]> {
return Observable
.fromPromise(
axios.get(`https://www.npmjs.com/-/search?text=${NAME_PREFIX}+${encodeURIComponent(query || '')}&from=0&size=1000`)
)
.map(response => response.data.objects.map(item => ({
name: item.package.name.substring(NAME_PREFIX.length),
packageName: item.package.name,
description: item.package.description,
version: item.package.version,
homepage: item.package.links.homepage,
})))
.map(plugins => plugins.filter(x => x.packageName.startsWith(NAME_PREFIX)))
}
async installPlugin (plugin: IPluginInfo) {
}
}

View File

@ -0,0 +1,13 @@
import { Injectable } from '@angular/core'
import { SettingsTabProvider, ComponentType } from 'terminus-settings'
import { PluginsSettingsTabComponent } from './components/pluginsSettingsTab.component'
@Injectable()
export class PluginsSettingsTabProvider extends SettingsTabProvider {
title = 'Plugins'
getComponentType (): ComponentType {
return PluginsSettingsTabComponent
}
}

View File

@ -10,6 +10,7 @@ module.exports = {
filename: 'index.js',
pathinfo: true,
libraryTarget: 'umd',
devtoolModuleFilenameTemplate: 'webpack-terminus-plugin-manager:///[resource-path]',
},
resolve: {
modules: ['.', 'src', 'node_modules', '../app/node_modules'].map(x => path.join(__dirname, x)),
@ -20,7 +21,7 @@ module.exports = {
{
test: /\.ts$/,
loader: 'awesome-typescript-loader',
options: {
query: {
configFileName: path.resolve(__dirname, 'tsconfig.json'),
paths: {
"terminus-*": [path.resolve(__dirname, '../terminus-*')],
@ -28,10 +29,19 @@ module.exports = {
}
}
},
{ test: /\.pug$/, use: ['apply-loader', 'pug-loader'] },
{ test: /\.scss$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] },
]
},
externals: [
'fs',
'fs-promise',
'font-manager',
'path',
'node-pty',
'mz/child_process',
'winreg',
/^rxjs/,
/^@angular/,
/^@ng-bootstrap/,
/^terminus-/,

View File

@ -74,8 +74,10 @@ export class TerminalTabComponent extends BaseTabComponent {
ngOnInit () {
this.focused$.subscribe(() => {
this.hterm.scrollPort_.focus()
this.hterm.scrollPort_.resize()
setTimeout(() => {
this.hterm.scrollPort_.resize()
this.hterm.scrollPort_.focus()
}, 100)
})
this.hterm = new hterm.hterm.Terminal()
@ -88,6 +90,7 @@ export class TerminalTabComponent extends BaseTabComponent {
this.hterm.onTerminalReady = () => {
this.htermVisible = true
this.hterm.installKeyboard()
this.hterm.scrollPort_.setCtrlVPaste(true)
this.io = this.hterm.io.push()
this.attachIOHandlers(this.io)
}

View File

@ -1,29 +0,0 @@
{
"name": "terminus-theme-hype",
"version": "0.0.1",
"description": "Hyper inspired theme for Terminus",
"main": "dist/index.js",
"scripts": {
"build": "webpack --progress --color",
"watch": "webpack --progress --color --watch"
},
"files": ["dist"],
"author": "Eugene Pankov",
"license": "MIT",
"peerDependencies": {
"@angular/core": "4.0.1",
"terminus-core": "*"
},
"devDependencies": {
"@types/webpack-env": "1.13.0",
"node-sass": "^4.5.0",
"bootstrap": "4.0.0-alpha.6",
"sass-loader": "^6.0.3",
"css-loader": "0.26.1",
"typescript": "~2.1.0",
"to-string-loader": "^1.1.5",
"awesome-typescript-loader": "3.1.2",
"raw-loader": "0.5.1",
"webpack": "2.3.3"
}
}

View File

@ -1,16 +0,0 @@
import { NgModule, Injectable } from '@angular/core'
import { Theme } from 'terminus-core'
@Injectable()
class HypeTheme extends Theme {
name = 'Hype'
css = require('./theme.scss')
terminalBackground = '#010101'
}
@NgModule({
providers: [
{ provide: Theme, useClass: HypeTheme, multi: true },
],
})
export default class HypeThemeModule { }

View File

@ -1,258 +0,0 @@
$window-border: #313131;
$body-bg: #010101;
$body-bg2: #010101;
$body-bg3: #111;
$tab-border-radius: 3px;
$button-hover-bg: rgba(255, 255, 255, .05);
$button-active-bg: rgba(255, 255, 255, .1);
$white: #fff !default;
$black: #000 !default;
$red: #d9534f !default;
$orange: #f0ad4e !default;
$yellow: #ffd500 !default;
$green: #5cb85c !default;
$blue: #0275d8 !default;
$teal: #5bc0de !default;
$pink: #ff5b77 !default;
$purple: #613d7c !default;
$body-color: #aaa;
$font-family-sans-serif: "Source Sans Pro";
$font-size-base: 14rem / 16;
$btn-secondary-color: #ccc;
$btn-secondary-bg: #222;
$btn-secondary-border: #444;
//$btn-warning-bg: rgba($orange, .5);
$nav-tabs-border-color: $body-bg2;
$nav-tabs-border-width: 1px;
$nav-tabs-border-radius: 0;
$nav-tabs-link-hover-border-color: $body-bg2;
$nav-tabs-active-link-hover-color: $white;
$nav-tabs-active-link-hover-bg: $blue;
$nav-tabs-active-link-hover-border-color: darken($blue, 30%);
$input-bg: #111;
$input-bg-disabled: #333;
$input-color: $body-color;
//$input-border-color: rgba($black,.15);
//$input-box-shadow: inset 0 1px 1px rgba($black,.075);
$input-border-radius: 0;
$input-bg-focus: $input-bg;
//$input-border-focus: lighten($brand-primary, 25%);
//$input-box-shadow-focus: $input-box-shadow, rgba($input-border-focus, .6);
$input-color-focus: $input-color;
$modal-content-bg: $body-bg;
$modal-content-border-color: $body-bg2;
$modal-header-border-color: $body-bg2;
$modal-footer-border-color: $body-bg2;
$popover-bg: $body-bg2;
@import '~bootstrap/scss/bootstrap.scss';
.nav-tabs {
background: $btn-secondary-bg;
.nav-link {
transition: 0.25s all;
border-bottom-color: $nav-tabs-border-color;
}
}
ngb-tabset .tab-content {
padding-top: 20px;
}
[ngbradiogroup] > label.active {
background: $blue;
}
title-bar {
background: $body-bg2;
button {
&:hover { background: $button-hover-bg !important; }
&:active { background: $button-active-bg !important; }
}
}
app-root {
background: $body-bg;
border: 1px solid $window-border;
&> .content {
.tab-bar {
.btn-tab-bar {
background: transparent;
&:hover { background: $button-hover-bg !important; }
&:active { background: $button-active-bg !important; }
}
&>.tabs {
tab-header {
background: $body-bg;
.index {
color: #555;
}
.name {
text-align: center;
}
button {
color: $body-color;
border: none;
transition: 0.25s all;
}
}
}
}
&.tabs-on-top .tab-bar {
margin-top: -1px;
border-bottom: 1px solid $window-border;
tab-header {
margin-bottom: -1px;
border: 1px solid transparent;
border-bottom: 1px solid $window-border;
border-top-left-radius: $tab-border-radius;
border-top-right-radius: $tab-border-radius;
&.active {
border: 1px solid $window-border;
border-bottom: 1px solid transparent;
}
&.has-activity:not(.active) {
border-top: 1px solid $green;
}
}
}
&:not(.tabs-on-top) .tab-bar {
margin-bottom: -1px;
border-top: 1px solid $window-border;
tab-header {
margin-top: -1px;
border: 1px solid transparent;
border-top: 1px solid $window-border;
border-bottom-left-radius: $tab-border-radius;
border-bottom-right-radius: $tab-border-radius;
&.active {
border: 1px solid $window-border;
border-top: 1px solid transparent;
}
&.has-activity:not(.active) {
border-bottom: 1px solid $green;
}
}
}
}
}
tab-body {
background: $body-bg;
}
settings-tab > ngb-tabset {
border-right: 1px solid $body-bg2;
& > .nav {
background: $body-bg3;
& > .nav-item > .nav-link {
border-left: none;
border-right: none;
border-top: 1px solid transparent;
border-bottom: 1px solid transparent;
padding: 10px 50px 10px 20px;
font-size: 14px;
&.active {
border-top-color: $nav-tabs-active-link-hover-border-color;
border-bottom-color: $nav-tabs-active-link-hover-border-color;
}
}
}
}
multi-hotkey-input {
.item {
background: $body-bg3;
border: 1px solid $blue;
border-radius: 3px;
margin-right: 5px;
.body {
padding: 3px 0 2px;
.stroke {
padding: 0 6px;
border-right: 1px solid $body-bg;
}
}
.remove {
padding: 3px 8px 2px;
}
}
.add {
color: #777;
padding: 4px 10px 0;
}
.add, .item .body, .item .remove {
&:hover { background: darken($body-bg3, 5%); }
&:active { background: darken($body-bg3, 15%); }
}
}
hotkey-input-modal {
.input {
background: $input-bg;
padding: 10px;
font-size: 24px;
line-height: 27px;
height: 55px;
.stroke {
background: $body-bg3;
border: 1px solid $blue;
border-radius: 3px;
margin-right: 10px;
padding: 3px 10px;
}
}
.timeout {
background: $input-bg;
div {
background: $blue;
}
}
}
.form-group label {
margin-bottom: 2px;
}

View File

@ -1,18 +0,0 @@
{
"compilerOptions": {
"baseUrl": "src",
"module": "commonjs",
"target": "es2016",
"declaration": false,
"noImplicitAny": false,
"removeComments": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"lib": [
"dom",
"es2015",
"es7"
]
},
"exclude": ["node_modules", "dist"]
}

View File

@ -3,8 +3,6 @@ module.exports = [
require('./terminus-core/webpack.config.js'),
require('./terminus-settings/webpack.config.js'),
require('./terminus-terminal/webpack.config.js'),
require('./terminus-clickable-links/webpack.config.js'),
require('./terminus-community-color-schemes/webpack.config.js'),
//require('./terminus-plugin-manager/webpack.config.js'),
require('./terminus-theme-hype/webpack.config.js'),
require('./terminus-plugin-manager/webpack.config.js'),
]