avatar base
This commit is contained in:
parent
a3775ed3ac
commit
500a56e429
1
projects/ui/src/lib/avatar/avatar.component.html
Normal file
1
projects/ui/src/lib/avatar/avatar.component.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
{{shortUsername}}
|
24
projects/ui/src/lib/avatar/avatar.component.scss
Normal file
24
projects/ui/src/lib/avatar/avatar.component.scss
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
23
projects/ui/src/lib/avatar/avatar.component.spec.ts
Normal file
23
projects/ui/src/lib/avatar/avatar.component.spec.ts
Normal 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();
|
||||||
|
});
|
||||||
|
});
|
33
projects/ui/src/lib/avatar/avatar.component.ts
Normal file
33
projects/ui/src/lib/avatar/avatar.component.ts
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
1
projects/ui/src/lib/avatar/avatar.interface.ts
Normal file
1
projects/ui/src/lib/avatar/avatar.interface.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export type AvatarSize = 'default' | 'small' | 'medium' | 'large';
|
18
projects/ui/src/lib/avatar/avatar.module.ts
Normal file
18
projects/ui/src/lib/avatar/avatar.module.ts
Normal 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 { }
|
@ -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">
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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 {}
|
||||||
|
21
projects/ui/src/lib/utils/string-hash-to-hsl.ts
Normal file
21
projects/ui/src/lib/utils/string-hash-to-hsl.ts
Normal 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}%)`;
|
||||||
|
}
|
@ -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';
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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}`);
|
||||||
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user