avatar base

This commit is contained in:
wagonsoftware 2022-11-02 23:31:50 +03:00
parent a3775ed3ac
commit 500a56e429
16 changed files with 149 additions and 7 deletions

View File

@ -0,0 +1 @@
{{shortUsername}}

View File

@ -0,0 +1,24 @@
:host {
display: block;
aspect-ratio: 1/1;
text-transform: uppercase;
color: #000;
display: flex;
justify-content: center;
align-items: center;
width: var(--local-size, 50px);
font-size: var(--local-size);
&[data-size="default"] {
--local-size: 50px;
}
&[data-size="small"] {
--local-size: 50px;
}
&[data-size="medium"] {
--local-size: 50px;
}
&[data-size="large"] {
--local-size: 50px;
}
}

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AvatarComponent } from './avatar.component';
describe('AvatarComponent', () => {
let component: AvatarComponent;
let fixture: ComponentFixture<AvatarComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ AvatarComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(AvatarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,33 @@
import { Component, HostBinding, Input, OnInit } from '@angular/core';
import { stringHashToHsl } from '../utils/string-hash-to-hsl';
import { AvatarSize } from './avatar.interface';
@Component({
selector: 'skirda-avatar',
templateUrl: './avatar.component.html',
styleUrls: ['./avatar.component.scss'],
})
export class AvatarComponent implements OnInit {
@Input() username: string = 'username';
@Input() size: AvatarSize = 'default';
constructor() {}
ngOnInit(): void {}
@HostBinding('style.background-color')
get color() {
return stringHashToHsl(this.username);
}
@HostBinding('data-size')
get avatarSize() {
return `${this.size}px`;
}
get shortUsername() {
let array = this.username.split(' ');
if (array.length >= 2) return array[0].charAt(0) + array[1].charAt(0);
else return this.username.charAt(0);
}
}

View File

@ -0,0 +1 @@
export type AvatarSize = 'default' | 'small' | 'medium' | 'large';

View File

@ -0,0 +1,18 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AvatarComponent } from './avatar.component';
@NgModule({
declarations: [
AvatarComponent
],
imports: [
CommonModule
],
exports: [
AvatarComponent
]
})
export class AvatarModule { }

View File

@ -1,4 +1,4 @@
<div class="popup-overlay" (click)="closeViaClick($event)" [attr.style]="'--local-overlay:' + config.overlay.background" [ngClass]="{'shown': loaded, 'hiding': hiding}" skirdaKeyboard (escape)="closeViaEscape($event)"> <div class="popup-overlay" [style.left]="offsetLeft + 'px'" (click)="closeViaClick($event)" [attr.style]="'--local-overlay:' + config.overlay.background" [ngClass]="{'shown': loaded, 'hiding': hiding}" skirdaKeyboard (escape)="closeViaEscape($event)">
<div class="popup-window-wrapper" [attr.data-appearance]="config.appearance" [attr.data-theme]="config.theme"> <div class="popup-window-wrapper" [attr.data-appearance]="config.appearance" [attr.data-theme]="config.theme">
<div class="popup-window"> <div class="popup-window">
<div class="popup-head"> <div class="popup-head">

View File

@ -1,5 +1,10 @@
:host::ng-deep { :host::ng-deep {
position: absolute; position: absolute;
width: 100vw;
height: 100vh;
// background-color: red;
top: 0;
left: 0px;
@keyframes show { @keyframes show {
from { from {
@ -43,10 +48,10 @@
.popup-overlay { .popup-overlay {
display: block; display: block;
position: fixed; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: 100%; width: 100vw;
height: 100vh; height: 100vh;
background-color: var(--local-overlay, var(--sk-overlay)); background-color: var(--local-overlay, var(--sk-overlay));
display: flex; display: flex;

View File

@ -1,6 +1,7 @@
import { import {
AfterViewInit, AfterViewInit,
Component, Component,
ElementRef,
EventEmitter, EventEmitter,
Input, Input,
OnInit, OnInit,
@ -21,16 +22,21 @@ export class PopupComponent implements OnInit, AfterViewInit {
loaded: boolean = false; loaded: boolean = false;
hiding: boolean = false; hiding: boolean = false;
contentQueue?: TemplateRef<any>; contentQueue?: TemplateRef<any>;
offsetLeft: number = 0;
@Output() event: EventEmitter<string> = new EventEmitter(); @Output() event: EventEmitter<string> = new EventEmitter();
@ViewChild(PopupDirective) private popupContent!: PopupDirective; @ViewChild(PopupDirective) private popupContent!: PopupDirective;
constructor() {} constructor(private element: ElementRef<HTMLElement>) {}
ngOnInit(): void {} ngOnInit(): void {}
ngAfterViewInit(): void { ngAfterViewInit(): void {
setTimeout(() => {
this.offsetLeft =
-this.element.nativeElement.getBoundingClientRect().left;
}, 0);
if (this.contentQueue) { if (this.contentQueue) {
this.load(this.contentQueue); this.load(this.contentQueue);
this.contentQueue = undefined; this.contentQueue = undefined;

View File

@ -10,8 +10,9 @@ import { ButtonModule } from './button/button.module';
import { TagModule } from './tag/tag.module'; import { TagModule } from './tag/tag.module';
import { PipesModule } from './pipes/pipes.module'; import { PipesModule } from './pipes/pipes.module';
import { GameModule } from './game/game.module'; import { GameModule } from './game/game.module';
import { PopupModule } from '../public-api';
import { DirectivesModule } from './directives/directives.module'; import { DirectivesModule } from './directives/directives.module';
import { PopupModule } from './popup/popup.module';
import { AvatarModule } from './avatar/avatar.module';
@NgModule({ @NgModule({
declarations: [], declarations: [],
@ -29,6 +30,7 @@ import { DirectivesModule } from './directives/directives.module';
GameModule, GameModule,
PopupModule, PopupModule,
DirectivesModule, DirectivesModule,
AvatarModule,
], ],
exports: [ exports: [
IconModule, IconModule,
@ -44,6 +46,7 @@ import { DirectivesModule } from './directives/directives.module';
GameModule, GameModule,
PopupModule, PopupModule,
DirectivesModule, DirectivesModule,
AvatarModule,
], ],
}) })
export class UiModule {} export class UiModule {}

View File

@ -0,0 +1,21 @@
/**
* Converts a string to an HSL color
* @param value string to convert
* @return HSL color string
*/
export function stringHashToHsl(value: string): string {
if (value === ``) return ``;
let hash = 0;
for (let i = 0; i < value.length; i++) {
hash = value.charCodeAt(i) + ((hash << 5) - hash);
hash = hash & hash;
}
const hue = hash % 360;
const saturation = 60 + (hash % 5);
const lightness = 80 + (hash % 5);
return `hsl(${hue},${saturation}%,${lightness}%)`;
}

View File

@ -14,3 +14,4 @@ export * from './lib/tag/tag.module';
export * from './lib/pipes/pipes.module'; export * from './lib/pipes/pipes.module';
export * from './lib/game/game.module'; export * from './lib/game/game.module';
export * from './lib/popup/popup.module'; export * from './lib/popup/popup.module';
export * from './lib/avatar/avatar.module';

View File

@ -36,6 +36,7 @@
transition: 0.1s ease; transition: 0.1s ease;
border-radius: var(--sk-br-m); border-radius: var(--sk-br-m);
cursor: pointer; cursor: pointer;
flex-shrink: 0;
&:hover { &:hover {
background-color: rgba(255, 255, 255, 0.05); background-color: rgba(255, 255, 255, 0.05);

View File

@ -26,6 +26,6 @@
background-color: rgba(0,0,0,0.15); background-color: rgba(0,0,0,0.15);
display: flex; display: flex;
backdrop-filter: blur(2rem); backdrop-filter: blur(2rem);
overflow-y: auto; // overflow-y: auto;
} }
} }

View File

@ -56,7 +56,7 @@ export class GamePageComponent implements OnInit, OnDestroy {
// background: 'rgba(255, 255, 255, 1)', // background: 'rgba(255, 255, 255, 1)',
}, },
body: 'Humblebrag chillwave sriracha, ramps polaroid distillery edison bulb palo santo etsy sus pabst knausgaard typewriter dreamcatcher.', body: 'Humblebrag chillwave sriracha, ramps polaroid distillery edison bulb palo santo etsy sus pabst knausgaard typewriter dreamcatcher.',
theme: 'light', theme: 'dark',
}) })
.subscribe((event) => { .subscribe((event) => {
console.log(`event: ${event}`); console.log(`event: ${event}`);

View File

@ -29,3 +29,8 @@
<p>Church-key listicle whatever hoodie hexagon pour-over ascot paleo tacos, organic aesthetic tbh meggings raclette.</p> <p>Church-key listicle whatever hoodie hexagon pour-over ascot paleo tacos, organic aesthetic tbh meggings raclette.</p>
</ng-template> </ng-template>
<skirda-button (click)="openPopup(popupContent)">Call popup</skirda-button> <skirda-button (click)="openPopup(popupContent)">Call popup</skirda-button>
<hr>
<h3>Avatar</h3>
<skirda-avatar></skirda-avatar>