diff --git a/projects/elonkit/src/theme.scss b/projects/elonkit/src/theme.scss
new file mode 100644
index 00000000..4cd2238c
--- /dev/null
+++ b/projects/elonkit/src/theme.scss
@@ -0,0 +1,123 @@
+@import './ui/alert/alert.component.theme';
+@import './ui/dropzone/dropzone.component.theme';
+@import './ui/inline-form-field/inline-form-field.component.theme';
+@import './ui/dropzone/dropzone.component.theme';
+@import './ui/avatar/avatar.component.theme';
+@import './ui//badge//badge.component.theme';
+
+$elonkit-default-theme: (
+ info:
+ mat-palette(
+ (
+ 50: #e9f4ff,
+ 100: #c8e3ff,
+ 200: #a3d1ff,
+ 300: #7ebfff,
+ 400: #63b1ff,
+ 500: #47a3ff,
+ 600: #409bff,
+ 700: #3791ff,
+ 800: #2f88ff,
+ 900: #2077ff,
+ A100: #fff,
+ A200: #fff,
+ A400: #cfe1ff,
+ A700: #b6d0ff,
+ contrast: (
+ 50: #000,
+ 100: #000,
+ 200: #000,
+ 300: #000,
+ 400: #000,
+ 500: #000,
+ 600: #000,
+ 700: #000,
+ 800: #fff,
+ 900: #fff,
+ A100: #000,
+ A200: #000,
+ A400: #000,
+ A700: #000
+ )
+ )
+ ),
+ success:
+ mat-palette(
+ (
+ 50: #e7f9f2,
+ 100: #c3efdf,
+ 200: #9be4ca,
+ 300: #73d9b5,
+ 400: #55d1a5,
+ 500: #37c995,
+ 600: #31c38d,
+ 700: #2abc82,
+ 800: #23b578,
+ 900: #16a967,
+ A100: #dcffee,
+ A200: #a9ffd6,
+ A400: #76ffbd,
+ A700: #5dffb1,
+ contrast: (
+ 50: #000,
+ 100: #000,
+ 200: #000,
+ 300: #000,
+ 400: #000,
+ 500: #000,
+ 600: #000,
+ 700: #000,
+ 800: #000,
+ 900: #fff,
+ A100: #000,
+ A200: #000,
+ A400: #000,
+ A700: #000
+ )
+ )
+ ),
+ danger:
+ mat-palette(
+ (
+ 50: #fdf2e5,
+ 100: #fadebe,
+ 200: #f7c992,
+ 300: #f3b366,
+ 400: #f1a246,
+ 500: #ee9225,
+ 600: #ec8a21,
+ 700: #e97f1b,
+ 800: #e77516,
+ 900: #e2630d,
+ A100: #fff,
+ A200: #ffe8da,
+ A400: #ffc7a7,
+ A700: #ffb78e,
+ contrast: (
+ 50: #000,
+ 100: #000,
+ 200: #000,
+ 300: #000,
+ 400: #000,
+ 500: #000,
+ 600: #000,
+ 700: #000,
+ 800: #000,
+ 900: #fff,
+ A100: #000,
+ A200: #000,
+ A400: #000,
+ A700: #000
+ )
+ )
+ )
+);
+
+@mixin elonkit-theme($theme, $elonkit-theme: $elonkit-default-theme) {
+ @include es-alert-theme($theme, $elonkit-theme);
+ @include es-dropzone-theme($theme, $elonkit-theme);
+ @include es-inline-form-field-theme($theme, $elonkit-theme);
+ @include es-paginator-theme($theme, $elonkit-theme);
+ @include es-avatar-theme($theme, $elonkit-theme);
+ @include es-badge-theme($theme, $elonkit-theme);
+}
diff --git a/projects/elonkit/src/theming/theming.scss b/projects/elonkit/src/theming/theming.scss
index 230d0de4..21c1bc5f 100644
--- a/projects/elonkit/src/theming/theming.scss
+++ b/projects/elonkit/src/theming/theming.scss
@@ -9,6 +9,7 @@
@import '../ui/paginator/paginator.component.theme';
@import '../ui/surface/surface.component.theme';
@import '../ui/tooltip/tooltip.component.theme';
+@import './ui/badge/badge.component.theme';
@function es-make-theme($es-theme) {
$result: $es-theme;
@@ -45,4 +46,5 @@
@include es-paginator-theme($theme, $es-theme);
@include es-surface-theme($theme, $es-theme);
@include es-tooltip-theme($theme, $es-theme);
+ @include es-badge-theme($theme, $es-theme);
}
diff --git a/projects/elonkit/src/ui/avatar/__stories__/avatar-story-no-image-typography/avatar-story-no-image-typography.source.ts b/projects/elonkit/src/ui/avatar/__stories__/avatar-story-no-image-typography/avatar-story-no-image-typography.source.ts
index 9801db98..29c688e1 100644
--- a/projects/elonkit/src/ui/avatar/__stories__/avatar-story-no-image-typography/avatar-story-no-image-typography.source.ts
+++ b/projects/elonkit/src/ui/avatar/__stories__/avatar-story-no-image-typography/avatar-story-no-image-typography.source.ts
@@ -3,6 +3,7 @@ export const AVATAR_STORY_NO_IMAGE_TYPOGRAPHY_SOURCE = {
НФ
`
};
diff --git a/projects/elonkit/src/ui/avatar/avatar-group.component.ts b/projects/elonkit/src/ui/avatar/avatar-group.component.ts
index 2a57814f..fab39c24 100644
--- a/projects/elonkit/src/ui/avatar/avatar-group.component.ts
+++ b/projects/elonkit/src/ui/avatar/avatar-group.component.ts
@@ -13,7 +13,7 @@ import {
} from '@angular/core';
import { ESAvatarComponent } from './avatar.component';
-import { takeUntil } from 'rxjs/operators';
+import { takeUntil, filter } from 'rxjs/operators';
import { Subject } from 'rxjs';
@Component({
@@ -42,7 +42,6 @@ export class ESAvatarGroupComponent implements OnInit, AfterContentInit, OnDestr
* @ignore
*/
public ngOnInit() {
- console.log(this.size);
this._elementRef.nativeElement.style.setProperty('--size', `${this.size + `px`}`);
}
@@ -51,11 +50,14 @@ export class ESAvatarGroupComponent implements OnInit, AfterContentInit, OnDestr
*/
public ngAfterContentInit() {
this.setAvatarsIndex(this.avatars);
- this.avatars.changes.pipe(takeUntil(this.destroyed$)).subscribe((avatars) => {
- if (avatars) {
+ this.avatars.changes
+ .pipe(
+ filter((avatars) => !!avatars),
+ takeUntil(this.destroyed$)
+ )
+ .subscribe((avatars) => {
this.setAvatarsIndex(avatars);
- }
- });
+ });
}
private setAvatarsIndex = (avatars): void => {
diff --git a/projects/elonkit/src/ui/avatar/avatar.component.ts b/projects/elonkit/src/ui/avatar/avatar.component.ts
index 5172428f..3d973791 100644
--- a/projects/elonkit/src/ui/avatar/avatar.component.ts
+++ b/projects/elonkit/src/ui/avatar/avatar.component.ts
@@ -46,10 +46,10 @@ export class ESAvatarComponent {
*/
@Input()
public get typography(): string {
- return this._typography;
+ return this._typography || 'es-subtitle-2';
}
public set typography(value: string) {
- this._typography = value || 'es-subtitle-2';
+ this._typography = value;
}
private _typography: string;
diff --git a/projects/elonkit/src/ui/avatar/ng-package.json b/projects/elonkit/src/ui/avatar/ng-package.json
new file mode 100644
index 00000000..789c95e4
--- /dev/null
+++ b/projects/elonkit/src/ui/avatar/ng-package.json
@@ -0,0 +1,5 @@
+{
+ "lib": {
+ "entryFile": "public-api.ts"
+ }
+}
diff --git a/projects/elonkit/src/ui/badge/__specs__/badge.spec.ts b/projects/elonkit/src/ui/badge/__specs__/badge.spec.ts
new file mode 100644
index 00000000..e64ddb94
--- /dev/null
+++ b/projects/elonkit/src/ui/badge/__specs__/badge.spec.ts
@@ -0,0 +1,56 @@
+import { Component } from '@angular/core';
+import { render } from '@testing-library/angular';
+
+import { ESBadgeModule } from '../badge.module';
+import { ESBadgeComponent } from '../badge.component';
+
+@Component({
+ template: ` Count `
+})
+class BadgeWrapperComponent {}
+
+describe('Badge', () => {
+ it('Should change badge size', async () => {
+ const component = await render(ESBadgeComponent, {
+ componentProperties: {
+ size: 40
+ },
+ imports: [ESBadgeModule],
+ excludeComponentDeclaration: true
+ });
+
+ expect(component.fixture.componentInstance.size).toBe(40);
+ });
+
+ it('Should change badge offsetVertical', async () => {
+ const component = await render(ESBadgeComponent, {
+ componentProperties: {
+ offsetVertical: 10
+ },
+ imports: [ESBadgeModule],
+ excludeComponentDeclaration: true
+ });
+
+ expect(component.fixture.componentInstance.offsetVertical).toBe(10);
+ });
+
+ it('Should change badge offsetHorizontal', async () => {
+ const component = await render(ESBadgeComponent, {
+ componentProperties: {
+ offsetHorizontal: 20
+ },
+ imports: [ESBadgeModule],
+ excludeComponentDeclaration: true
+ });
+
+ expect(component.fixture.componentInstance.offsetHorizontal).toBe(20);
+ });
+
+ it('Should accept count', async () => {
+ const component = await render(BadgeWrapperComponent, {
+ imports: [ESBadgeModule]
+ });
+
+ expect(component.getByText('Count')).toBeInTheDocument();
+ });
+});
diff --git a/projects/elonkit/src/ui/badge/__stories__/badge-story-basic/badge-story-basic.source.ts b/projects/elonkit/src/ui/badge/__stories__/badge-story-basic/badge-story-basic.source.ts
new file mode 100644
index 00000000..4ac178d2
--- /dev/null
+++ b/projects/elonkit/src/ui/badge/__stories__/badge-story-basic/badge-story-basic.source.ts
@@ -0,0 +1,24 @@
+export const BADGE_STORY_BASIC_SOURCE = {
+ html: `
+
+
+
+
+
+
+ `
+};
diff --git a/projects/elonkit/src/ui/badge/__stories__/badge-story-basic/index.ts b/projects/elonkit/src/ui/badge/__stories__/badge-story-basic/index.ts
new file mode 100644
index 00000000..b1f2714c
--- /dev/null
+++ b/projects/elonkit/src/ui/badge/__stories__/badge-story-basic/index.ts
@@ -0,0 +1 @@
+export { BADGE_STORY_BASIC_SOURCE } from './badge-story-basic.source';
diff --git a/projects/elonkit/src/ui/badge/__stories__/badge-story-count/badge-story-count.source.ts b/projects/elonkit/src/ui/badge/__stories__/badge-story-count/badge-story-count.source.ts
new file mode 100644
index 00000000..6a0cebab
--- /dev/null
+++ b/projects/elonkit/src/ui/badge/__stories__/badge-story-count/badge-story-count.source.ts
@@ -0,0 +1,26 @@
+export const BADGE_STORY_COUNT_SOURCE = {
+ html: `
+
+
+
+
+
+
+
+
+ `
+};
diff --git a/projects/elonkit/src/ui/badge/__stories__/badge-story-count/index.ts b/projects/elonkit/src/ui/badge/__stories__/badge-story-count/index.ts
new file mode 100644
index 00000000..512a540b
--- /dev/null
+++ b/projects/elonkit/src/ui/badge/__stories__/badge-story-count/index.ts
@@ -0,0 +1 @@
+export { BADGE_STORY_COUNT_SOURCE } from './badge-story-count.source';
diff --git a/projects/elonkit/src/ui/badge/__stories__/badge-story-custom/badge-story-custom.source.ts b/projects/elonkit/src/ui/badge/__stories__/badge-story-custom/badge-story-custom.source.ts
new file mode 100644
index 00000000..1cc7f958
--- /dev/null
+++ b/projects/elonkit/src/ui/badge/__stories__/badge-story-custom/badge-story-custom.source.ts
@@ -0,0 +1,22 @@
+export const BADGE_STORY_CUSTOM_SOURCE = {
+ html: `
+
+
+
+
+
+
+ `
+};
diff --git a/projects/elonkit/src/ui/badge/__stories__/badge-story-custom/index.ts b/projects/elonkit/src/ui/badge/__stories__/badge-story-custom/index.ts
new file mode 100644
index 00000000..11c8e8aa
--- /dev/null
+++ b/projects/elonkit/src/ui/badge/__stories__/badge-story-custom/index.ts
@@ -0,0 +1 @@
+export { BADGE_STORY_CUSTOM_SOURCE } from './badge-story-custom.source';
diff --git a/projects/elonkit/src/ui/badge/__stories__/badge-story-icon/badge-story-icon.source.ts b/projects/elonkit/src/ui/badge/__stories__/badge-story-icon/badge-story-icon.source.ts
new file mode 100644
index 00000000..d86f89f0
--- /dev/null
+++ b/projects/elonkit/src/ui/badge/__stories__/badge-story-icon/badge-story-icon.source.ts
@@ -0,0 +1,22 @@
+export const BADGE_STORY_ICON_SOURCE = {
+ html: `
+
+ favorite
+
+
+
+ favorite
+
+
+ `
+};
diff --git a/projects/elonkit/src/ui/badge/__stories__/badge-story-icon/index.ts b/projects/elonkit/src/ui/badge/__stories__/badge-story-icon/index.ts
new file mode 100644
index 00000000..997c9432
--- /dev/null
+++ b/projects/elonkit/src/ui/badge/__stories__/badge-story-icon/index.ts
@@ -0,0 +1 @@
+export { BADGE_STORY_ICON_SOURCE } from './badge-story-icon.source';
diff --git a/projects/elonkit/src/ui/badge/__stories__/badge.stories.mdx b/projects/elonkit/src/ui/badge/__stories__/badge.stories.mdx
new file mode 100644
index 00000000..fa74bda0
--- /dev/null
+++ b/projects/elonkit/src/ui/badge/__stories__/badge.stories.mdx
@@ -0,0 +1,319 @@
+import { Meta, Story, ArgsTable } from '@storybook/addon-docs/blocks';
+import { Canvas } from '~storybook/components';
+import { action } from '@storybook/addon-actions';
+
+import { MatIconModule } from '@angular/material/icon';
+import { MatButtonModule } from '@angular/material/button';
+
+import { ESBadgeComponent, ESBadgeModule } from '..';
+
+import { ESAvatarModule } from '@elonsoft/elonkit/ui/avatar';
+
+import { BADGE_STORY_BASIC_SOURCE } from './badge-story-basic';
+import { BADGE_STORY_ICON_SOURCE } from './badge-story-icon';
+import { BADGE_STORY_COUNT_SOURCE } from './badge-story-count';
+import { BADGE_STORY_CUSTOM_SOURCE } from './badge-story-custom';
+
+
+
+# Badge
+
+Generates a badge component to the different positions of its children. Pass children component
+with attribute es-role="child"
+
+## Demos
+
+####
+
+####
+
+### Basic badge
+
+Basic badge with no image using color input as background color and borderSize input as border size:
+
+####
+
+
+
+####
+
+####
+
+### Icon badge
+
+Badge with icon. Pass icon via ng-content with attribute es-role="icon":
+
+####
+
+
+
+####
+
+####
+
+### Count badge
+
+Badge with count. Pass count via ng-content with attribute es-role="count":
+
+####
+
+
+
+####
+
+### Custom badge
+
+Badge with custom position. If position input is undefined use offsetHorizontal/offsetVertical inputs
+to set horizontal and vertical offset of child element mask; to change badge positions use
+positions input as object of positions:
+
+
+
+####
+
+####
+
+## API
+
+
+
+## Interfaces
+
+ESBadgeDefaultOptions defines default badge size
+
+```ts
+export interface ESBadgeDefaultOptions {
+ size?: number;
+ position?: ESBadgePosition;
+ borderSize?: number;
+}
+```
+
+ESBadgePosition defines badge position type
+
+```ts
+export enum ESBadgePosition {
+ AboveBefore = 'above before',
+ AboveAfter = 'above after',
+ BelowBefore = 'below before',
+ BelowAfter = 'below after'
+}
+```
+
+ESBadgePositionStyles defines types for object of custom positions
+
+```ts
+export interface ESBadgePositionStyles {
+ 'top.px'?: number;
+ 'right.px'?: number;
+ 'bottom.px'?: number;
+ 'left.px'?: number;
+}
+```
+
+Injection token that can be used to configure the default options for all components within an app.
+
+```ts
+import { ES_BADGE_DEFAULT_OPTIONS } from '@elonsoft/elonkit/ui/badge';
+
+@NgModule({
+ providers: [
+ {
+ provide: ES_BADGE_DEFAULT_OPTIONS,
+ useValue: {
+ size: 14
+ }
+ }
+ ]
+})
+```
diff --git a/projects/elonkit/src/ui/badge/badge.component.html b/projects/elonkit/src/ui/badge/badge.component.html
new file mode 100644
index 00000000..e545fc25
--- /dev/null
+++ b/projects/elonkit/src/ui/badge/badge.component.html
@@ -0,0 +1,13 @@
+
diff --git a/projects/elonkit/src/ui/badge/badge.component.scss b/projects/elonkit/src/ui/badge/badge.component.scss
new file mode 100644
index 00000000..6a4253dc
--- /dev/null
+++ b/projects/elonkit/src/ui/badge/badge.component.scss
@@ -0,0 +1,34 @@
+$div-width: 40;
+$badge-size: 16;
+
+.es-badge {
+ position: relative;
+ width: fit-content;
+
+ > :nth-child(2) {
+ display: block;
+ mask: radial-gradient(
+ circle at calc(var(--childElement) - var(--offsetHorizontal) - var(--borderSize))
+ calc(var(--childElement) - var(--offsetVertical) - var(--borderSize)),
+ transparent var(--transparent),
+ #fff 0
+ );
+ }
+
+ &__content {
+ align-items: center;
+ border-radius: 50%;
+ box-sizing: border-box;
+ display: flex;
+ justify-content: center;
+ position: absolute;
+ z-index: 1000;
+
+ [es-role='icon'] {
+ border-radius: 50%;
+ font-size: 16px;
+ height: fit-content;
+ width: fit-content;
+ }
+ }
+}
diff --git a/projects/elonkit/src/ui/badge/badge.component.theme.scss b/projects/elonkit/src/ui/badge/badge.component.theme.scss
new file mode 100644
index 00000000..519bd988
--- /dev/null
+++ b/projects/elonkit/src/ui/badge/badge.component.theme.scss
@@ -0,0 +1,21 @@
+@mixin es-badge-theme($theme, $elonkit-theme) {
+ $cl-mono-b: map-get($elonkit-theme, mono-b);
+ $attention: map-get($elonkit-theme, attention);
+
+ /* stylelint-disable-next-line */
+ .es-badge__content {
+ background-color: mat-color($attention, 500);
+
+ [es-role='icon'] {
+ background-color: mat-color($cl-mono-b, 500);
+ }
+
+ [es-role='child'] {
+ color: mat-color($cl-mono-b, 500);
+ }
+
+ [es-role='count'] {
+ color: mat-color($cl-mono-b, 500);
+ }
+ }
+}
diff --git a/projects/elonkit/src/ui/badge/badge.component.ts b/projects/elonkit/src/ui/badge/badge.component.ts
new file mode 100644
index 00000000..89a0e94a
--- /dev/null
+++ b/projects/elonkit/src/ui/badge/badge.component.ts
@@ -0,0 +1,224 @@
+import {
+ Component,
+ ChangeDetectionStrategy,
+ ChangeDetectorRef,
+ ViewEncapsulation,
+ Input,
+ InjectionToken,
+ Optional,
+ Inject,
+ ElementRef,
+ ViewChild
+} from '@angular/core';
+
+import { coerceNumberProperty } from '@angular/cdk/coercion';
+import { ESBadgeDefaultOptions, ESBadgePosition, ESBadgePositionStyles } from './badge.types';
+
+export const ES_BADGE_DEFAULT_OPTIONS = new InjectionToken(
+ 'ES_BADGE_DEFAULT_OPTIONS'
+);
+
+@Component({
+ selector: 'es-badge',
+ templateUrl: './badge.component.html',
+ styleUrls: ['./badge.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ encapsulation: ViewEncapsulation.None
+})
+export class ESBadgeComponent {
+ /**
+ * Defines badge size in pixels.
+ */
+ @Input()
+ public get size(): number {
+ return this._size;
+ }
+ public set size(value: number) {
+ this._size = coerceNumberProperty(value, 14);
+ }
+ private _size: number;
+
+ /**
+ * Defines badge position.
+ */
+ @Input()
+ public get position(): ESBadgePosition {
+ return this._position;
+ }
+ public set position(value: ESBadgePosition) {
+ this._position = value;
+ if (this._position) {
+ this.setPositions();
+ }
+ }
+ private _position: ESBadgePosition;
+
+ /**
+ * Defines badge border width in pixels.
+ */
+ @Input()
+ public get borderSize(): number {
+ return this._borderSize;
+ }
+ public set borderSize(value: number) {
+ this._borderSize = coerceNumberProperty(value, 2);
+ }
+ private _borderSize: number;
+
+ /**
+ * Defines badge background color.
+ */
+ @Input() public color: string;
+
+ /**
+ * Defines badge custom positions.
+ */
+ @Input()
+ public get positions(): ESBadgePositionStyles {
+ return this._positions;
+ }
+ public set positions(value: ESBadgePositionStyles) {
+ this._positions = value;
+ this.setPositions();
+ }
+ private _positions: ESBadgePositionStyles;
+
+ private badgePosition = ESBadgePosition;
+
+ /**
+ * Defines badge vertical offset.
+ */
+ @Input()
+ public get offsetVertical(): number {
+ return this._offsetVertical;
+ }
+ public set offsetVertical(value: number) {
+ this._offsetVertical = coerceNumberProperty(value);
+ setTimeout(() => {
+ this._elementRef.nativeElement.style.setProperty(
+ '--offsetVertical',
+ `${this._offsetVertical + `px`}`
+ );
+ this.setStyles();
+ });
+ }
+ private _offsetVertical: number;
+
+ /**
+ * Defines badge horizontal offset.
+ */
+ @Input()
+ public get offsetHorizontal(): number {
+ return this._offsetHorizontal;
+ }
+ public set offsetHorizontal(value: number) {
+ this._offsetHorizontal = coerceNumberProperty(value);
+ setTimeout(() => {
+ this._elementRef.nativeElement.style.setProperty(
+ '--offsetHorizontal',
+ `${this._offsetHorizontal + `px`}`
+ );
+ this.setStyles();
+ });
+ }
+ private _offsetHorizontal: number;
+
+ /**
+ * Child element, passing to ng-content.
+ */
+ @ViewChild('childElement')
+ public childElement: ElementRef;
+
+ /**
+ * @ignore
+ */
+ constructor(
+ /**
+ * @internal
+ */
+ public changeDetector: ChangeDetectorRef,
+ /**
+ * @internal
+ */
+ @Optional()
+ @Inject('ES_BADGE_DEFAULT_OPTIONS')
+ private defaultOptions: ESBadgeDefaultOptions,
+ private _elementRef: ElementRef
+ ) {
+ this.size = this.defaultOptions?.size;
+ this.position = this.defaultOptions?.position;
+ this.offsetVertical = this.defaultOptions?.offsetVertical;
+ this.offsetHorizontal = this.defaultOptions?.offsetHorizontal;
+ this.borderSize = this.defaultOptions?.borderSize;
+ }
+
+ private setPositions() {
+ setTimeout(() => {
+ const childElement = this.childElement.nativeElement.offsetWidth;
+ const transparent = this.size / 2 + this.borderSize;
+ let offsetVertical = childElement - transparent;
+ let offsetHorizontal = this.borderSize * 2;
+
+ switch (this.position) {
+ case this.badgePosition.AboveAfter: {
+ this.positions = { 'top.px': 0, 'right.px': -1 };
+ break;
+ }
+ case this.badgePosition.AboveBefore: {
+ this.positions = { 'top.px': 0, 'left.px': 0 };
+ offsetHorizontal = offsetVertical;
+ break;
+ }
+ case this.badgePosition.BelowAfter: {
+ this.positions = { 'bottom.px': -1, 'right.px': -1 };
+ offsetVertical = this.borderSize * 2;
+ offsetHorizontal = this.borderSize * 2;
+ break;
+ }
+ case this.badgePosition.BelowBefore: {
+ this.positions = { 'left.px': 0, 'bottom.px': -1 };
+ offsetVertical = this.borderSize * 2;
+ offsetHorizontal = childElement - transparent;
+ break;
+ }
+ }
+ this.setOffsets(offsetVertical, offsetHorizontal);
+ });
+ }
+
+ /**
+ * @internal
+ * @ignore
+ */
+ public stylesObject() {
+ return {
+ 'height.px': this.size,
+ 'width.px': this.size,
+ 'background-color.px': this.color,
+ ...this.positions
+ };
+ }
+
+ private setOffsets(offsetVertical, offsetHorizontal): void {
+ this._elementRef.nativeElement.style.setProperty(
+ '--offsetVertical',
+ `${offsetVertical + `px`}`
+ );
+ this._elementRef.nativeElement.style.setProperty(
+ '--offsetHorizontal',
+ `${offsetHorizontal + `px`}`
+ );
+ this.changeDetector.markForCheck();
+ }
+
+ private setStyles() {
+ const childElement = this.childElement.nativeElement.offsetWidth;
+ this._elementRef.nativeElement.style.setProperty('--borderSize', `${this.borderSize + `px`}`);
+ this._elementRef.nativeElement.style.setProperty(
+ '--transparent',
+ `${this.size / 2 + this.borderSize + 1 + `px`}`
+ );
+ this._elementRef.nativeElement.style.setProperty('--childElement', `${childElement + `px`}`);
+ this.changeDetector.markForCheck();
+ }
+}
diff --git a/projects/elonkit/src/ui/badge/badge.module.ts b/projects/elonkit/src/ui/badge/badge.module.ts
new file mode 100644
index 00000000..12cb257a
--- /dev/null
+++ b/projects/elonkit/src/ui/badge/badge.module.ts
@@ -0,0 +1,11 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { ESBadgeComponent } from './badge.component';
+
+@NgModule({
+ declarations: [ESBadgeComponent],
+ imports: [CommonModule],
+ exports: [ESBadgeComponent]
+})
+export class ESBadgeModule {}
diff --git a/projects/elonkit/src/ui/badge/badge.types.ts b/projects/elonkit/src/ui/badge/badge.types.ts
new file mode 100644
index 00000000..4272fd98
--- /dev/null
+++ b/projects/elonkit/src/ui/badge/badge.types.ts
@@ -0,0 +1,21 @@
+export interface ESBadgeDefaultOptions {
+ size?: number;
+ position?: ESBadgePosition;
+ borderSize?: number;
+ offsetVertical?: number;
+ offsetHorizontal?: number;
+}
+
+export enum ESBadgePosition {
+ AboveBefore = 'above before',
+ AboveAfter = 'above after',
+ BelowBefore = 'below before',
+ BelowAfter = 'below after'
+}
+
+export interface ESBadgePositionStyles {
+ 'top.px'?: number;
+ 'right.px'?: number;
+ 'bottom.px'?: number;
+ 'left.px'?: number;
+}
diff --git a/projects/elonkit/src/ui/badge/index.ts b/projects/elonkit/src/ui/badge/index.ts
new file mode 100644
index 00000000..7e1a213e
--- /dev/null
+++ b/projects/elonkit/src/ui/badge/index.ts
@@ -0,0 +1 @@
+export * from './public-api';
diff --git a/projects/elonkit/src/ui/badge/public-api.ts b/projects/elonkit/src/ui/badge/public-api.ts
new file mode 100644
index 00000000..6f61c70e
--- /dev/null
+++ b/projects/elonkit/src/ui/badge/public-api.ts
@@ -0,0 +1,3 @@
+export { ESBadgeModule } from './badge.module';
+export { ESBadgeComponent } from './badge.component';
+export { ESBadgeDefaultOptions } from './badge.types';
diff --git a/projects/elonkit/storybook/assets/icons/avatar/star.svg b/projects/elonkit/storybook/assets/icons/avatar/star.svg
new file mode 100644
index 00000000..bc7ef0d6
--- /dev/null
+++ b/projects/elonkit/storybook/assets/icons/avatar/star.svg
@@ -0,0 +1 @@
+
\ No newline at end of file