diff --git a/projects/elonkit/src/assets/elonkit/es-table-actions/close.svg b/projects/elonkit/src/assets/elonkit/es-table-actions/close.svg new file mode 100644 index 00000000..73097b0b --- /dev/null +++ b/projects/elonkit/src/assets/elonkit/es-table-actions/close.svg @@ -0,0 +1,3 @@ + + + diff --git a/projects/elonkit/src/public-api.ts b/projects/elonkit/src/public-api.ts index 6a001935..ddd120f4 100644 --- a/projects/elonkit/src/public-api.ts +++ b/projects/elonkit/src/public-api.ts @@ -11,6 +11,7 @@ export * from './ui/inline-form-field'; export * from './ui/paginator'; export * from './ui/timepicker'; export * from './ui/tooltip'; +export * from './ui/table-actions'; export * from './ui/icons'; export * from './ui/locale'; diff --git a/projects/elonkit/src/theming/theming.scss b/projects/elonkit/src/theming/theming.scss index 230d0de4..23f8119c 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/table-actions/table-actions.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-table-actions-theme($theme, $es-theme); } diff --git a/projects/elonkit/src/ui/icons/icons.service.ts b/projects/elonkit/src/ui/icons/icons.service.ts index d51c54bd..3cf03fc3 100644 --- a/projects/elonkit/src/ui/icons/icons.service.ts +++ b/projects/elonkit/src/ui/icons/icons.service.ts @@ -29,7 +29,8 @@ export const ES_SVG_ICONS = { 'play', 'speed', 'un-mute' - ] as const + ] as const, + 'es-table-actions': ['close'] as const }; @Injectable() diff --git a/projects/elonkit/src/ui/locale/locales/en.ts b/projects/elonkit/src/ui/locale/locales/en.ts index 6828736b..92e12f82 100644 --- a/projects/elonkit/src/ui/locale/locales/en.ts +++ b/projects/elonkit/src/ui/locale/locales/en.ts @@ -38,5 +38,8 @@ export const en = { avatar: { labelAvatar: 'Avatar', labelStatus: 'Status' + }, + tableActions: { + title: 'Selected' } }; diff --git a/projects/elonkit/src/ui/locale/locales/ru.ts b/projects/elonkit/src/ui/locale/locales/ru.ts index d6613ed8..f4c8faa5 100644 --- a/projects/elonkit/src/ui/locale/locales/ru.ts +++ b/projects/elonkit/src/ui/locale/locales/ru.ts @@ -38,5 +38,8 @@ export const ru = { avatar: { labelAvatar: 'Аватар', labelStatus: 'Статус' + }, + tableActions: { + title: 'Выбрано' } }; diff --git a/projects/elonkit/src/ui/table-actions/__specs__/table-actions.spec.ts b/projects/elonkit/src/ui/table-actions/__specs__/table-actions.spec.ts new file mode 100644 index 00000000..8dabe58b --- /dev/null +++ b/projects/elonkit/src/ui/table-actions/__specs__/table-actions.spec.ts @@ -0,0 +1,31 @@ +import { render } from '@testing-library/angular'; +import { ESLocaleService, en, ru } from '../../locale'; +import { ESTableActionsComponent, ESTableActionsModule } from '../'; + +describe('Table Actions', () => { + it('Should change locale', async () => { + const localeService = new ESLocaleService(); + localeService.register('ru', ru); + localeService.use('ru'); + + const component = await render(ESTableActionsComponent, { + imports: [ESTableActionsModule], + providers: [{ provide: ESLocaleService, useValue: localeService }], + excludeComponentDeclaration: true + }); + + expect(component.getByText(ru.tableActions.title)).toBeInTheDocument(); + }); + + it('Should accept total input', async () => { + const component = await render(ESTableActionsComponent, { + imports: [ESTableActionsModule], + componentProperties: { + total: 15 + }, + excludeComponentDeclaration: true + }); + + expect(component.getAllByText('Selected 15')).not.toBeNull(); + }); +}); diff --git a/projects/elonkit/src/ui/table-actions/__stories__/table-actions-story-basic/index.ts b/projects/elonkit/src/ui/table-actions/__stories__/table-actions-story-basic/index.ts new file mode 100644 index 00000000..50edd9f6 --- /dev/null +++ b/projects/elonkit/src/ui/table-actions/__stories__/table-actions-story-basic/index.ts @@ -0,0 +1,3 @@ +export { TABLE_ACTIONS_SOURCE } from './table-actions-story-basic.source'; +export { TableActionsStoryBasicComponent } from './table-actions-story-basic.component'; +export { TableActionsStoryBasicModule } from './table-actions-story-basic.module'; diff --git a/projects/elonkit/src/ui/table-actions/__stories__/table-actions-story-basic/table-actions-story-basic.component.html b/projects/elonkit/src/ui/table-actions/__stories__/table-actions-story-basic/table-actions-story-basic.component.html new file mode 100644 index 00000000..4ec83a87 --- /dev/null +++ b/projects/elonkit/src/ui/table-actions/__stories__/table-actions-story-basic/table-actions-story-basic.component.html @@ -0,0 +1,39 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
No. {{element.position}} Name {{element.name}} Weight {{element.weight}} Symbol {{element.symbol}}
+ + + + +
+ diff --git a/projects/elonkit/src/ui/table-actions/__stories__/table-actions-story-basic/table-actions-story-basic.component.scss b/projects/elonkit/src/ui/table-actions/__stories__/table-actions-story-basic/table-actions-story-basic.component.scss new file mode 100644 index 00000000..6d671976 --- /dev/null +++ b/projects/elonkit/src/ui/table-actions/__stories__/table-actions-story-basic/table-actions-story-basic.component.scss @@ -0,0 +1,16 @@ +.table-actions { + padding: 30px; + width: 80%; + + .mat-elevation-z8 { + box-shadow: none; + } + + &__story-table { + width: 100%; + } + + &__button { + opacity: 0.6; + } +} diff --git a/projects/elonkit/src/ui/table-actions/__stories__/table-actions-story-basic/table-actions-story-basic.component.ts b/projects/elonkit/src/ui/table-actions/__stories__/table-actions-story-basic/table-actions-story-basic.component.ts new file mode 100644 index 00000000..d18f20ab --- /dev/null +++ b/projects/elonkit/src/ui/table-actions/__stories__/table-actions-story-basic/table-actions-story-basic.component.ts @@ -0,0 +1,35 @@ +import { Component, ChangeDetectionStrategy, Input } from '@angular/core'; + +export interface PeriodicElement { + name: string; + position: number; + weight: number; + symbol: string; +} + +const ELEMENT_DATA: PeriodicElement[] = [ + { position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H' }, + { position: 2, name: 'Helium', weight: 4.0026, symbol: 'He' }, + { position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li' }, + { position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be' }, + { position: 5, name: 'Boron', weight: 10.811, symbol: 'B' }, + { position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C' }, + { position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N' }, + { position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O' }, + { position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F' }, + { position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne' } +]; + +@Component({ + selector: 'es-table-actions-basic', + templateUrl: './table-actions-story-basic.component.html', + styleUrls: ['./table-actions-story-basic.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TableActionsStoryBasicComponent { + public displayedColumns: string[] = ['position', 'name', 'weight', 'symbol']; + public dataSource = ELEMENT_DATA; + public total = 10; + + public onAction(): void {} +} diff --git a/projects/elonkit/src/ui/table-actions/__stories__/table-actions-story-basic/table-actions-story-basic.module.ts b/projects/elonkit/src/ui/table-actions/__stories__/table-actions-story-basic/table-actions-story-basic.module.ts new file mode 100644 index 00000000..388c8681 --- /dev/null +++ b/projects/elonkit/src/ui/table-actions/__stories__/table-actions-story-basic/table-actions-story-basic.module.ts @@ -0,0 +1,14 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { MatTableModule } from '@angular/material/table'; +import { MatIconModule } from '@angular/material/icon'; +import { MatButtonModule } from '@angular/material/button'; +import { TableActionsStoryBasicComponent } from './table-actions-story-basic.component'; +import { ESTableActionsModule } from '../../'; + +@NgModule({ + declarations: [TableActionsStoryBasicComponent], + imports: [CommonModule, ESTableActionsModule, MatTableModule, MatIconModule, MatButtonModule], + exports: [TableActionsStoryBasicComponent] +}) +export class TableActionsStoryBasicModule {} diff --git a/projects/elonkit/src/ui/table-actions/__stories__/table-actions-story-basic/table-actions-story-basic.source.ts b/projects/elonkit/src/ui/table-actions/__stories__/table-actions-story-basic/table-actions-story-basic.source.ts new file mode 100644 index 00000000..6427f04b --- /dev/null +++ b/projects/elonkit/src/ui/table-actions/__stories__/table-actions-story-basic/table-actions-story-basic.source.ts @@ -0,0 +1,78 @@ +export const TABLE_ACTIONS_SOURCE = { + ts: ` + import { Component, ChangeDetectionStrategy, Input } from '@angular/core'; + + export interface PeriodicElement { + name: string; + position: number; + weight: number; + symbol: string; + } + + const ELEMENT_DATA: PeriodicElement[] = [ + { position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H' }, + { position: 2, name: 'Helium', weight: 4.0026, symbol: 'He' }, + { position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li' }, + { position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be' }, + { position: 5, name: 'Boron', weight: 10.811, symbol: 'B' }, + { position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C' }, + { position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N' }, + { position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O' }, + { position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F' }, + { position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne' } + ]; + + @Component({ + selector: 'es-table-actions-basic', + templateUrl: './table-actions-story-basic.component.html', + styleUrls: ['./table-actions-story-basic.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush + }) + + export class TableActionsStoryBasicComponent { + public displayedColumns: string[] = ['position', 'name', 'weight', 'symbol']; + public dataSource = ELEMENT_DATA; + public total = 10; + + public onAction():void {} + } + `, + html: ` + + + + + + + + + + + + + + + + + + + + + + + + + + + +
No. {{element.position}} Name {{element.name}} Weight {{element.weight}} Symbol {{element.symbol}}
+ + + + + ` +}; diff --git a/projects/elonkit/src/ui/table-actions/__stories__/table-actions.stories.mdx b/projects/elonkit/src/ui/table-actions/__stories__/table-actions.stories.mdx new file mode 100644 index 00000000..8e6ce983 --- /dev/null +++ b/projects/elonkit/src/ui/table-actions/__stories__/table-actions.stories.mdx @@ -0,0 +1,50 @@ +import { Meta, Story, ArgsTable } from '@storybook/addon-docs/blocks'; +import { Canvas } from '~storybook/components'; + +import { action } from '@storybook/addon-actions'; +import { CoreModule } from '~storybook/core.module'; +import { ESTableActionsComponent } from '..'; + +import { + TableActionsStoryBasicComponent, + TableActionsStoryBasicModule, + TABLE_ACTIONS_SOURCE +} from './table-actions-story-basic'; + + + +# Table actions + +Table actions component. Show tables selected elements and provide actions on them. +All actions buttons, besides close button, could be passing via ng-content. + +## Demos + + + + {((args) => ({ + component: TableActionsStoryBasicComponent, + moduleMetadata: { + imports: [TableActionsStoryBasicModule, CoreModule] + }, + props: { + ...args, + onAction: action('onAction') + } + })).bind({})} + + + +## API + + diff --git a/projects/elonkit/src/ui/table-actions/index.ts b/projects/elonkit/src/ui/table-actions/index.ts new file mode 100644 index 00000000..7e1a213e --- /dev/null +++ b/projects/elonkit/src/ui/table-actions/index.ts @@ -0,0 +1 @@ +export * from './public-api'; diff --git a/projects/elonkit/src/ui/table-actions/public-api.ts b/projects/elonkit/src/ui/table-actions/public-api.ts new file mode 100644 index 00000000..15f02407 --- /dev/null +++ b/projects/elonkit/src/ui/table-actions/public-api.ts @@ -0,0 +1,2 @@ +export * from './table-actions.module'; +export * from './table-actions.component'; diff --git a/projects/elonkit/src/ui/table-actions/table-actions.component.html b/projects/elonkit/src/ui/table-actions/table-actions.component.html new file mode 100644 index 00000000..fc38f48f --- /dev/null +++ b/projects/elonkit/src/ui/table-actions/table-actions.component.html @@ -0,0 +1,14 @@ +
+
+ + {{(locale$ | async).tableActions.title}} {{total}} + +
+ +
+ +
+
+
diff --git a/projects/elonkit/src/ui/table-actions/table-actions.component.scss b/projects/elonkit/src/ui/table-actions/table-actions.component.scss new file mode 100644 index 00000000..76dabfd0 --- /dev/null +++ b/projects/elonkit/src/ui/table-actions/table-actions.component.scss @@ -0,0 +1,32 @@ +.es-table-actions { + box-sizing: border-box; + + &__content { + align-items: center; + box-sizing: border-box; + display: flex; + justify-content: space-between; + padding: 8px 16px; + width: 100%; + + span { + font-size: 16px; + } + } + + &__total { + padding-left: 8px; + } + + &__actions { + align-items: center; + display: flex; + } + + &__separator { + height: 40px; + margin-left: 8px; + margin-right: 8px; + width: 1px; + } +} diff --git a/projects/elonkit/src/ui/table-actions/table-actions.component.ts b/projects/elonkit/src/ui/table-actions/table-actions.component.ts new file mode 100644 index 00000000..64700c82 --- /dev/null +++ b/projects/elonkit/src/ui/table-actions/table-actions.component.ts @@ -0,0 +1,60 @@ +import { + Component, + ChangeDetectionStrategy, + ViewEncapsulation, + Input, + Output, + EventEmitter +} from '@angular/core'; + +import { ESLocaleService, ESLocale } from '../locale'; + +import { Observable } from 'rxjs'; + +@Component({ + selector: 'es-table-actions', + templateUrl: './table-actions.component.html', + styleUrls: ['./table-actions.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + encapsulation: ViewEncapsulation.None +}) +export class ESTableActionsComponent { + private _total; + + /** + * Total number of selected rows. + */ + @Input() public total: number; + + /** + * Event emitted when user clicks close button. + */ + @Output() public closed = new EventEmitter(); + + /** + * Emit closed button click + */ + /** + * @internal + * @ignore + */ + public onCloseClick(): void { + this.closed.emit(); + } + + /** + * @internal + * @ignore + */ + public locale$: Observable; + + constructor( + /** + * @internal + * @ignore + */ + public localeService: ESLocaleService + ) { + this.locale$ = this.localeService.locale(); + } +} diff --git a/projects/elonkit/src/ui/table-actions/table-actions.module.ts b/projects/elonkit/src/ui/table-actions/table-actions.module.ts new file mode 100644 index 00000000..ffcd54af --- /dev/null +++ b/projects/elonkit/src/ui/table-actions/table-actions.module.ts @@ -0,0 +1,14 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; + +import { MatButtonModule } from '@angular/material/button'; +import { MatIconModule } from '@angular/material/icon'; +import { ESTableActionsComponent } from './table-actions.component'; +import { HttpClientModule } from '@angular/common/http'; + +@NgModule({ + imports: [CommonModule, MatButtonModule, MatIconModule, HttpClientModule], + exports: [ESTableActionsComponent], + declarations: [ESTableActionsComponent] +}) +export class ESTableActionsModule {} diff --git a/projects/elonkit/src/ui/table-actions/table-actions.theme.scss b/projects/elonkit/src/ui/table-actions/table-actions.theme.scss new file mode 100644 index 00000000..6f0abd56 --- /dev/null +++ b/projects/elonkit/src/ui/table-actions/table-actions.theme.scss @@ -0,0 +1,16 @@ +@mixin es-table-actions-theme($theme, $elonkit-theme) { + $accent: map-get($theme, accent); + $mono-a: map-get($elonkit-theme, mono-a); + + .es-table-actions { + background-color: mat-color($accent, A100); + + &__total { + color: mat-color($mono-a, 500); + } + + &__separator { + background-color: mat-color($mono-a, A100); + } + } +}