diff --git a/package-lock.json b/package-lock.json index 36523df..b9cdc22 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,8 @@ "@angular/platform-browser": "^14.1.0", "@angular/platform-browser-dynamic": "^14.1.0", "@angular/router": "^14.1.0", + "@ng-icons/core": "^22.4.0", + "@ng-icons/tabler-icons": "^22.4.0", "fast-average-color": "^9.1.1", "moment": "^2.29.4", "rxjs": "~7.5.0", @@ -2632,6 +2634,26 @@ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" }, + "node_modules/@ng-icons/core": { + "version": "22.4.0", + "resolved": "https://registry.npmjs.org/@ng-icons/core/-/core-22.4.0.tgz", + "integrity": "sha512-sOACYxjGuJ7TQEARD7XhLF0mZGTTkEF8o2yNl3J+KXTPz+A5CptkT/57S+UNdXXeKuw9c6xlYpxUWu3tISkp/Q==", + "dependencies": { + "tslib": "^2.2.0" + }, + "peerDependencies": { + "@angular/common": ">=14.0.0", + "@angular/core": ">=14.0.0" + } + }, + "node_modules/@ng-icons/tabler-icons": { + "version": "22.4.0", + "resolved": "https://registry.npmjs.org/@ng-icons/tabler-icons/-/tabler-icons-22.4.0.tgz", + "integrity": "sha512-aF9MLx//95Yp3smWNGRUaHtYecO37TtubukNArTdxShKX3+wThdPb5rvIeIq9KoOEq2iJn2iWXHq+XRdPILKrw==", + "dependencies": { + "tslib": "^2.2.0" + } + }, "node_modules/@ngtools/webpack": { "version": "14.2.6", "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-14.2.6.tgz", @@ -13458,6 +13480,22 @@ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" }, + "@ng-icons/core": { + "version": "22.4.0", + "resolved": "https://registry.npmjs.org/@ng-icons/core/-/core-22.4.0.tgz", + "integrity": "sha512-sOACYxjGuJ7TQEARD7XhLF0mZGTTkEF8o2yNl3J+KXTPz+A5CptkT/57S+UNdXXeKuw9c6xlYpxUWu3tISkp/Q==", + "requires": { + "tslib": "^2.2.0" + } + }, + "@ng-icons/tabler-icons": { + "version": "22.4.0", + "resolved": "https://registry.npmjs.org/@ng-icons/tabler-icons/-/tabler-icons-22.4.0.tgz", + "integrity": "sha512-aF9MLx//95Yp3smWNGRUaHtYecO37TtubukNArTdxShKX3+wThdPb5rvIeIq9KoOEq2iJn2iWXHq+XRdPILKrw==", + "requires": { + "tslib": "^2.2.0" + } + }, "@ngtools/webpack": { "version": "14.2.6", "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-14.2.6.tgz", diff --git a/package.json b/package.json index c13fe9e..d72a07f 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,8 @@ "@angular/platform-browser": "^14.1.0", "@angular/platform-browser-dynamic": "^14.1.0", "@angular/router": "^14.1.0", + "@ng-icons/core": "^22.4.0", + "@ng-icons/tabler-icons": "^22.4.0", "fast-average-color": "^9.1.1", "moment": "^2.29.4", "rxjs": "~7.5.0", diff --git a/projects/ui/src/lib/button/button.component.scss b/projects/ui/src/lib/button/button.component.scss index 222f06b..281756b 100644 --- a/projects/ui/src/lib/button/button.component.scss +++ b/projects/ui/src/lib/button/button.component.scss @@ -9,7 +9,10 @@ border-radius: var(--sk-br-m); border: none; cursor: pointer; + font-size: 1rem; font-weight: 500; + outline: none; + appearance: none; &:hover { opacity: 0.9; diff --git a/projects/ui/src/lib/button/button.interface.ts b/projects/ui/src/lib/button/button.interface.ts new file mode 100644 index 0000000..5cbe392 --- /dev/null +++ b/projects/ui/src/lib/button/button.interface.ts @@ -0,0 +1,6 @@ +export type ButtonAppearance = + | 'default' + | 'primary' + | 'secondary' + | 'outline' + | 'flat'; diff --git a/projects/ui/src/lib/directives/directives.module.ts b/projects/ui/src/lib/directives/directives.module.ts new file mode 100644 index 0000000..32b6e30 --- /dev/null +++ b/projects/ui/src/lib/directives/directives.module.ts @@ -0,0 +1,18 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { KeyboardDirective } from './keyboard.directive'; + + + +@NgModule({ + declarations: [ + KeyboardDirective + ], + imports: [ + CommonModule + ], + exports: [ + KeyboardDirective + ] +}) +export class DirectivesModule { } diff --git a/projects/ui/src/lib/directives/keyboard.directive.spec.ts b/projects/ui/src/lib/directives/keyboard.directive.spec.ts new file mode 100644 index 0000000..d6eabf0 --- /dev/null +++ b/projects/ui/src/lib/directives/keyboard.directive.spec.ts @@ -0,0 +1,8 @@ +import { KeyboardDirective } from './keyboard.directive'; + +describe('KeyboardDirective', () => { + it('should create an instance', () => { + const directive = new KeyboardDirective(); + expect(directive).toBeTruthy(); + }); +}); diff --git a/projects/ui/src/lib/directives/keyboard.directive.ts b/projects/ui/src/lib/directives/keyboard.directive.ts new file mode 100644 index 0000000..3719c57 --- /dev/null +++ b/projects/ui/src/lib/directives/keyboard.directive.ts @@ -0,0 +1,18 @@ +import { Directive, EventEmitter, HostListener, Output } from '@angular/core'; + +@Directive({ + selector: '[skirdaKeyboard]', +}) +export class KeyboardDirective { + @Output() escape: EventEmitter = new EventEmitter(); + + constructor() {} + + @HostListener('window:keydown.Escape', ['$event']) keyboardHandler( + event: KeyboardEvent + ) { + event.preventDefault(); + event.stopPropagation(); + this.escape.emit(event); + } +} diff --git a/projects/ui/src/lib/game/game.component.html b/projects/ui/src/lib/game/game.component.html index be8c381..60fcf43 100644 --- a/projects/ui/src/lib/game/game.component.html +++ b/projects/ui/src/lib/game/game.component.html @@ -6,5 +6,5 @@ description - + diff --git a/projects/ui/src/lib/icon/icon.component.html b/projects/ui/src/lib/icon/icon.component.html index 9b7d932..2566434 100644 --- a/projects/ui/src/lib/icon/icon.component.html +++ b/projects/ui/src/lib/icon/icon.component.html @@ -1 +1 @@ -
+ diff --git a/projects/ui/src/lib/icon/icon.component.scss b/projects/ui/src/lib/icon/icon.component.scss index 1ae7b77..e6dead2 100644 --- a/projects/ui/src/lib/icon/icon.component.scss +++ b/projects/ui/src/lib/icon/icon.component.scss @@ -1,6 +1,4 @@ -@import './skirda/skirda.css'; - -:host::ng-deep { +:host { display: flex; align-items: center; justify-content: center; diff --git a/projects/ui/src/lib/icon/icon.component.ts b/projects/ui/src/lib/icon/icon.component.ts index cd6ba4e..a2535c5 100644 --- a/projects/ui/src/lib/icon/icon.component.ts +++ b/projects/ui/src/lib/icon/icon.component.ts @@ -1,5 +1,6 @@ import { Component, Input, OnInit } from '@angular/core'; import { environment } from 'src/environments/environment'; +import { icons } from './icons'; const BASE_SIZE = 24; const BASE_STROKE_WIDTH = 1.5; @@ -9,17 +10,17 @@ const BASE_STROKE_WIDTH = 1.5; templateUrl: './icon.component.html', styleUrls: ['./icon.component.scss'], }) -export class IconComponent implements OnInit { +export class IconComponent { @Input() name!: string; @Input() size: number | string = 24; @Input() sizeUnit: string = 'px'; @Input() color: string = '#fff'; - constructor() {} - - ngOnInit(): void {} - get sizeWithUnit() { return this.size + this.sizeUnit; } + + get iconName() { + return icons.get(this.name) ?? 'tablerIcons'; + } } diff --git a/projects/ui/src/lib/icon/icon.module.ts b/projects/ui/src/lib/icon/icon.module.ts index 79ab8cf..1192ce8 100644 --- a/projects/ui/src/lib/icon/icon.module.ts +++ b/projects/ui/src/lib/icon/icon.module.ts @@ -1,10 +1,34 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { IconComponent } from './icon.component'; +import { NgIconsModule } from '@ng-icons/core'; +import { + tablerIcons, + tablerSearch, + tablerLayoutSidebar, + tablerServerBolt, + tablerDeviceGamepad2, + tablerUsers, + tablerDownload, + tablerPlayerPlay, + tablerX, +} from '@ng-icons/tabler-icons'; + +const icons = { + tablerIcons, + tablerSearch, + tablerLayoutSidebar, + tablerServerBolt, + tablerDeviceGamepad2, + tablerUsers, + tablerDownload, + tablerPlayerPlay, + tablerX, +}; @NgModule({ declarations: [IconComponent], - imports: [CommonModule], + imports: [CommonModule, NgIconsModule.withIcons(icons)], exports: [IconComponent], }) export class IconModule {} diff --git a/projects/ui/src/lib/icon/icons.ts b/projects/ui/src/lib/icon/icons.ts new file mode 100644 index 0000000..b910a7d --- /dev/null +++ b/projects/ui/src/lib/icon/icons.ts @@ -0,0 +1,12 @@ +const icons: Map = new Map(); + +icons.set('search', 'tablerSearch'); +icons.set('menu-panel', 'tablerLayoutSidebar'); +icons.set('server', 'tablerServerBolt'); +icons.set('library', 'tablerDeviceGamepad2'); +icons.set('friends', 'tablerUsers'); +icons.set('download', 'tablerDownload'); +icons.set('play', 'tablerPlayerPlay'); +icons.set('close', 'tablerX'); + +export { icons }; diff --git a/projects/ui/src/lib/icon/skirda/skirda.css b/projects/ui/src/lib/icon/skirda/skirda.css deleted file mode 100644 index 1b37a70..0000000 --- a/projects/ui/src/lib/icon/skirda/skirda.css +++ /dev/null @@ -1,42 +0,0 @@ -@font-face { - font-family: 'skirda'; - src: url('./skirda.eot?27107141'); - src: url('./skirda.eot?27107141#iefix') format('embedded-opentype'), - url('./skirda.woff2?27107141') format('woff2'), - url('./skirda.woff?27107141') format('woff'), - url('./skirda.ttf?27107141') format('truetype'), - url('./skirda.svg?27107141#skirda') format('svg'); - font-weight: normal; - font-style: normal; -} -/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */ -/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */ - -@media screen and (-webkit-min-device-pixel-ratio:0) { - @font-face { - font-family: 'skirda'; - src: url('./skirda.svg?27107141#skirda') format('svg'); - } -} - -[class^="skirda-"]:before, [class*=" skirda-"]:before { - font-family: "skirda"; - display: inline-block; - text-decoration: inherit; - text-align: center; - font-variant: normal; - text-transform: none; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -.skirda-discord:before { content: '\e800'; } /* '' */ -.skirda-friends:before { content: '\e801'; } /* '' */ -.skirda-menu-panel:before { content: '\e802'; } /* '' */ -.skirda-play:before { content: '\e803'; } /* '' */ -.skirda-search:before { content: '\e804'; } /* '' */ -.skirda-server:before { content: '\e805'; } /* '' */ -.skirda-sign-out:before { content: '\e806'; } /* '' */ -.skirda-favorite:before { content: '\e807'; } /* '' */ -.skirda-library:before { content: '\e808'; } /* '' */ -.skirda-download:before { content: '\e809'; } /* '' */ diff --git a/projects/ui/src/lib/icon/skirda/skirda.eot b/projects/ui/src/lib/icon/skirda/skirda.eot deleted file mode 100644 index 3f81b6b..0000000 Binary files a/projects/ui/src/lib/icon/skirda/skirda.eot and /dev/null differ diff --git a/projects/ui/src/lib/icon/skirda/skirda.svg b/projects/ui/src/lib/icon/skirda/skirda.svg deleted file mode 100644 index e732458..0000000 --- a/projects/ui/src/lib/icon/skirda/skirda.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - -Copyright (C) 2022 by original authors @ fontello.com - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/projects/ui/src/lib/icon/skirda/skirda.ttf b/projects/ui/src/lib/icon/skirda/skirda.ttf deleted file mode 100644 index 4e11751..0000000 Binary files a/projects/ui/src/lib/icon/skirda/skirda.ttf and /dev/null differ diff --git a/projects/ui/src/lib/icon/skirda/skirda.woff b/projects/ui/src/lib/icon/skirda/skirda.woff deleted file mode 100644 index be8bac3..0000000 Binary files a/projects/ui/src/lib/icon/skirda/skirda.woff and /dev/null differ diff --git a/projects/ui/src/lib/icon/skirda/skirda.woff2 b/projects/ui/src/lib/icon/skirda/skirda.woff2 deleted file mode 100644 index d78d1e3..0000000 Binary files a/projects/ui/src/lib/icon/skirda/skirda.woff2 and /dev/null differ diff --git a/projects/ui/src/lib/popup/popup.class.ts b/projects/ui/src/lib/popup/popup.class.ts new file mode 100644 index 0000000..9cffd25 --- /dev/null +++ b/projects/ui/src/lib/popup/popup.class.ts @@ -0,0 +1,183 @@ +import { ButtonAppearance } from '../button/button.interface'; + +export type PopupAppearance = 'default' | 'attention'; +export type PopupTheme = 'dark' | 'light'; + +export interface PopupHeader { + title: string; + closable?: boolean; +} + +export interface StrictPopupHeader extends PopupHeader { + title: string; + closable: boolean; +} + +export interface PopupAction { + title: string; + event: string; + appearance?: ButtonAppearance; +} + +export interface StrictPopupAction extends PopupAction { + title: string; + event: string; + appearance: ButtonAppearance; +} + +export interface PopupOverlay { + closable?: boolean; + background?: string; +} + +export interface StrictPopupOverlay extends PopupOverlay { + closable: boolean; + background: string; +} + +export interface PopupConfig { + header?: PopupHeader | StrictPopupHeader; + actions?: PopupAction[] | StrictPopupAction[]; + overlay?: PopupOverlay | StrictPopupOverlay; + body?: string; + appearance?: PopupAppearance; + theme?: PopupTheme; +} + +export interface StrictPopupConfig extends PopupConfig { + header: StrictPopupHeader; + actions: StrictPopupAction[]; + overlay: StrictPopupOverlay; + body?: string; + appearance: PopupAppearance; + theme: PopupTheme; +} + +export class PopupConfiguration implements StrictPopupConfig { + private _header: StrictPopupHeader; + private _actions: StrictPopupAction[]; + private _overlay: StrictPopupOverlay; + private _body?: string; + private _appearance: PopupAppearance; + private _theme: PopupTheme; + + constructor(config?: PopupConfig) { + this._header = this.getHeaderConfig(config); + this._actions = this.getActionsConfig(config); + this._overlay = this.getOverlayConfig(config); + this._body = this.getBodyConfig(config); + this._appearance = this.getAppearanceConfig(config); + this._theme = this.getThemeConfig(config); + } + + /** + * If the config object has a header object with a title property, return that, otherwise return + * 'Window'. + * @param {PopupConfig} [config] - PopupConfig - This is the configuration object that is passed to the + * popup. + * @returns An object with the properties title and closable. + */ + private getHeaderConfig(config?: PopupConfig) { + return { + title: config?.header?.title ?? 'Window', + closable: config?.header?.closable ?? true, + }; + } + + /** + * It checks if the config has actions and if it does it is pushing the actions into the actions + * array. If the config doesn't have actions it is pushing the default actions into the actions array + * @param {PopupConfig} [config] - PopupConfig - This is the config object that is passed to the + * popup. + * @returns An array of PopupAction objects. + */ + private getActionsConfig(config?: PopupConfig): StrictPopupAction[] { + let actions: StrictPopupAction[] = []; + + /* Checking if the config has actions and if it does it is pushing the actions into the actions array. */ + if (config && config.actions) { + for (const action of config.actions) { + actions.push({ + title: action.title, + event: action.event, + appearance: action.appearance ?? 'default', + }); + } + + return actions; + } + + /* Pushing the default actions into the actions array. */ + actions.push({ + title: 'Cancel', + event: 'cancel', + appearance: 'flat', + }); + actions.push({ + title: 'Submit', + event: 'submit', + appearance: 'primary', + }); + + return actions; + } + + private getOverlayConfig(config?: PopupConfig) { + return { + closable: config?.overlay?.closable ?? 'true', + background: config?.overlay?.background ?? 'var(--sk-overlay)', + }; + } + + /** + * If the config object has an appearance property, return it, otherwise return 'default'. + * @param {PopupConfig} [config] - PopupConfig - This is the configuration object that is passed to the + * popup. + * @returns The appearance of the popup. + */ + private getAppearanceConfig(config?: PopupConfig) { + return (config?.appearance ?? 'default'); + } + + /** + * If the config object has a body property, return that, otherwise return 'Content'. + * @param {PopupConfig} [config] - PopupConfig - This is the configuration object that we will pass to + * the popup. + * @returns The body of the popup. + */ + private getBodyConfig(config?: PopupConfig) { + return config?.body ?? 'Content'; + } + + private getThemeConfig(config?: PopupConfig) { + return config?.theme ?? 'dark'; + } + + get header() { + return this._header; + } + + get actions() { + return this._actions; + } + + get overlay() { + return this._overlay; + } + + get body() { + return this._body; + } + + get appearance() { + return this._appearance; + } + + get theme() { + return this._theme; + } + + set body(value: string | undefined) { + this._body = value; + } +} diff --git a/projects/ui/src/lib/popup/popup.component.html b/projects/ui/src/lib/popup/popup.component.html index 8399381..38b82e6 100644 --- a/projects/ui/src/lib/popup/popup.component.html +++ b/projects/ui/src/lib/popup/popup.component.html @@ -1,20 +1,22 @@ -