@mosa-ng/material 17.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/.eslintrc.json +31 -0
  2. package/README.md +24 -0
  3. package/ng-package.json +10 -0
  4. package/package.json +12 -0
  5. package/src/lib/components/alert-widget/alert-widget.module.ts +17 -0
  6. package/src/lib/components/alert-widget/alert.widget.html +7 -0
  7. package/src/lib/components/alert-widget/alert.widget.scss +50 -0
  8. package/src/lib/components/alert-widget/alert.widget.ts +61 -0
  9. package/src/lib/components/base/base.module.ts +14 -0
  10. package/src/lib/components/base/cell-editor.base.component.ts +79 -0
  11. package/src/lib/components/cell-editor/cell-editor.component.html +6 -0
  12. package/src/lib/components/cell-editor/cell-editor.component.scss +53 -0
  13. package/src/lib/components/cell-editor/cell-editor.component.ts +115 -0
  14. package/src/lib/components/cell-editor/cell-editor.module.ts +15 -0
  15. package/src/lib/components/confirm-dialog/confirm-dialog.module.ts +19 -0
  16. package/src/lib/components/confirm-dialog/confirm.dialog.html +15 -0
  17. package/src/lib/components/confirm-dialog/confirm.dialog.scss +3 -0
  18. package/src/lib/components/confirm-dialog/confirm.dialog.ts +60 -0
  19. package/src/lib/components/loading-button/loading-button.component.html +42 -0
  20. package/src/lib/components/loading-button/loading-button.component.scss +40 -0
  21. package/src/lib/components/loading-button/loading-button.component.ts +42 -0
  22. package/src/lib/components/loading-button/loading-button.module.ts +21 -0
  23. package/src/lib/components/logger/README.md +83 -0
  24. package/src/lib/components/logger/logger.component.html +32 -0
  25. package/src/lib/components/logger/logger.component.scss +120 -0
  26. package/src/lib/components/logger/logger.component.ts +116 -0
  27. package/src/lib/components/logger/logger.module.ts +23 -0
  28. package/src/lib/components/skeleton-loader/base.skeleton-loader.ts +14 -0
  29. package/src/lib/components/skeleton-loader/list-skeleton-loader/list-skeleton-loader.module.ts +17 -0
  30. package/src/lib/components/skeleton-loader/list-skeleton-loader/list.skeleton-loader.html +5 -0
  31. package/src/lib/components/skeleton-loader/list-skeleton-loader/list.skeleton-loader.scss +0 -0
  32. package/src/lib/components/skeleton-loader/list-skeleton-loader/list.skeleton-loader.ts +26 -0
  33. package/src/lib/components/skeleton-loader/skeleton/skeleton.component.html +0 -0
  34. package/src/lib/components/skeleton-loader/skeleton/skeleton.component.scss +15 -0
  35. package/src/lib/components/skeleton-loader/skeleton/skeleton.component.ts +64 -0
  36. package/src/lib/components/skeleton-loader/skeleton-loader.module.ts +17 -0
  37. package/src/lib/components/skeleton-loader/table-skeleton-loader/table-skeleton-loader.module.ts +19 -0
  38. package/src/lib/components/skeleton-loader/table-skeleton-loader/table.skeleton-loader.html +12 -0
  39. package/src/lib/components/skeleton-loader/table-skeleton-loader/table.skeleton-loader.scss +3 -0
  40. package/src/lib/components/skeleton-loader/table-skeleton-loader/table.skeleton-loader.ts +44 -0
  41. package/src/lib/components/update-dialog/mat-update-dialog/mat-update.dialog.html +17 -0
  42. package/src/lib/components/update-dialog/mat-update-dialog/mat-update.dialog.scss +3 -0
  43. package/src/lib/components/update-dialog/mat-update-dialog/mat-update.dialog.ts +28 -0
  44. package/src/lib/components/update-dialog/update-dialog.module.ts +22 -0
  45. package/src/lib/components/update-dialog/update.dialog.ts +124 -0
  46. package/src/lib/directives/cell-editor/cell-editor.directive.module.ts +15 -0
  47. package/src/lib/directives/cell-editor/cell-editor.directive.ts +163 -0
  48. package/src/lib/directives/click-outside/click-outside.directive.module.ts +15 -0
  49. package/src/lib/directives/click-outside/click-outside.directive.ts +48 -0
  50. package/src/lib/models/confirm-dialog.model.ts +33 -0
  51. package/src/lib/models/skeleton.model.ts +19 -0
  52. package/src/lib/models/states/cell-editor-base-state.model.ts +3 -0
  53. package/src/lib/models/states/logger-state.model.ts +5 -0
  54. package/src/lib/models/table-item.model.ts +6 -0
  55. package/src/lib/models/update-config.model.ts +20 -0
  56. package/src/lib/mosa-material.module.ts +26 -0
  57. package/src/lib/services/cell-editor.service.ts +46 -0
  58. package/src/lib/services/facades/logger.facade.ts +37 -0
  59. package/src/lib/services/logger.service.ts +49 -0
  60. package/src/lib/styles/_vars.scss +71 -0
  61. package/src/public-api.ts +1 -0
  62. package/tsconfig.lib.json +14 -0
  63. package/tsconfig.lib.prod.json +10 -0
  64. package/tsconfig.spec.json +14 -0
@@ -0,0 +1,40 @@
1
+ :host {
2
+ pointer-events: none;
3
+ }
4
+
5
+ button:not(:disabled) {
6
+ pointer-events: all;
7
+ }
8
+
9
+ .icon-spinner {
10
+ position: absolute;
11
+ top: 0;
12
+ left: 0;
13
+ }
14
+
15
+ .spinner {
16
+ .spinner-inner {
17
+ display: flex;
18
+ align-items: center;
19
+
20
+ mat-spinner {
21
+ position: absolute;
22
+ }
23
+
24
+ .label.loading {
25
+ margin-left: 30px;
26
+ }
27
+ }
28
+ }
29
+
30
+ .progress-bar {
31
+ overflow: hidden;
32
+ position: relative;
33
+
34
+ mat-progress-bar {
35
+ position: absolute;
36
+ bottom: 0;
37
+ left: 0;
38
+ width: 100%;
39
+ }
40
+ }
@@ -0,0 +1,42 @@
1
+ import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
2
+ import { ThemePalette } from '@angular/material/core';
3
+
4
+ @Component({
5
+ selector: 'mosa-loading-button',
6
+ templateUrl: './loading-button.component.html',
7
+ styleUrls: [ './loading-button.component.scss' ],
8
+ changeDetection: ChangeDetectionStrategy.OnPush,
9
+ })
10
+ export class LoadingButtonComponent {
11
+
12
+ @Input()
13
+ public mode: 'spinner' | 'progress-bar' = 'spinner';
14
+
15
+ @Input()
16
+ public loading: boolean;
17
+
18
+ @Input()
19
+ public disabled: boolean;
20
+
21
+ @Input()
22
+ public color: ThemePalette = 'primary';
23
+
24
+ @Input()
25
+ public buttonType: 'default' | 'raised' | 'stroked' | 'flat' | 'icon';
26
+
27
+ @Input()
28
+ public icon: string;
29
+
30
+ @Output()
31
+ // eslint-disable-next-line @angular-eslint/no-output-native
32
+ public click: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>();
33
+
34
+ constructor() {
35
+ }
36
+
37
+ public onClick(e: MouseEvent): void {
38
+ e.stopPropagation();
39
+ this.click.emit(e);
40
+ }
41
+
42
+ }
@@ -0,0 +1,21 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { NgModule } from '@angular/core';
3
+ import { MatButtonModule } from '@angular/material/button';
4
+ import { MatIconModule } from '@angular/material/icon';
5
+ import { MatProgressBarModule } from '@angular/material/progress-bar';
6
+ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
7
+ import { LoadingButtonComponent } from './loading-button.component';
8
+
9
+ @NgModule({
10
+ declarations: [ LoadingButtonComponent ],
11
+ imports: [
12
+ CommonModule,
13
+ MatProgressSpinnerModule,
14
+ MatProgressBarModule,
15
+ MatButtonModule,
16
+ MatIconModule,
17
+ ],
18
+ exports: [ LoadingButtonComponent ],
19
+ })
20
+ export class LoadingButtonModule {
21
+ }
@@ -0,0 +1,83 @@
1
+ # Logger
2
+
3
+ The mosa logger is a tool to display messages / infos to a user. It can also be used to catch http request errors and
4
+ directly display the error message to the user
5
+
6
+ ## Example usage
7
+
8
+ ### HTML
9
+
10
+ `````html
11
+ <mosa-logger></mosa-logger>
12
+ `````
13
+
14
+ ### TypeScript
15
+
16
+ ````typescript
17
+ export class AppComponent implements OnInit {
18
+
19
+ @ViewChild(LoggerComponent)
20
+ public set logger(logger: LoggerComponent) {
21
+ this.myLoggerService.logger(logger, this.defaultLoggerConfig);
22
+ }
23
+
24
+ constructor(
25
+ private myCoreLoggerService: CoreLoggerService,
26
+ private myLoggerService: LoggerService,
27
+ ) {
28
+ }
29
+
30
+ public ngOnInit(): void {
31
+ // Subscribe to ui logs
32
+ this.defaultLoggerConfig = {
33
+ debug: !environment.production,
34
+ closeOnClick: false,
35
+ showDismiss: true,
36
+ };
37
+ this.myCoreLoggerService.subUiLogs()
38
+ .subscribe((data: ILogEvent): void => {
39
+ if (data) {
40
+ this.myLoggerService.show({
41
+ title: data.title,
42
+ msg: data.msg,
43
+ ...data.config,
44
+ ...this.defaultLoggerConfig as ILoggerConfig,
45
+ }, data.type);
46
+ }
47
+ });
48
+ }
49
+ }
50
+ ````
51
+
52
+ ## Logger features
53
+
54
+ For model definition see [ILoggerConfig](../../../../../core/src/lib/models/logger/logger-config.model.ts)
55
+
56
+ ````typescript
57
+ // Subscribe to each log emitted in the code, or from http requests
58
+ this.myLoggerService.subUiLogs()
59
+
60
+ // Get error message from an object
61
+ this.myLoggerService.getErrorMsg(err);
62
+
63
+ // Get error title from an object
64
+ this.myLoggerService.getErrorTitle(err);
65
+
66
+ // Log an error
67
+ this.myLoggerService.logError({ msg: message });
68
+
69
+ // Log a success message
70
+ this.myLoggerService.logSuccess({ msg: message });
71
+
72
+ // Log a warning message
73
+ this.myLoggerService.logWarning({ msg: message });
74
+
75
+ // Log an info message
76
+ this.myLoggerService.logInfo({ msg: message });
77
+
78
+ // Any kind of log
79
+ this.myLoggerService.log({ msg: message });
80
+
81
+ // Any kind of log
82
+ this.myLoggerService.show({ msg: message }, 'default');
83
+ ````
@@ -0,0 +1,32 @@
1
+ <ng-container *ngIf="loggerState$ | async as state">
2
+ <div #loggerElement
3
+ *ngFor="let log of state.logs"
4
+ [@slide]="log.state"
5
+ [class.none]="!log.state"
6
+ [class]="log.config.className"
7
+ (click)="onClickLog(log)"
8
+ [class.touch]="log.config.closeOnClick"
9
+ class="logger-element">
10
+
11
+ <div class="content">
12
+ <mat-icon class="icon">{{ log.icon }}</mat-icon>
13
+ <div>
14
+ <div *ngIf="log.title" class="title">{{ log.title | translate }}</div>
15
+ <div *ngIf="log.message" [innerHTML]="log.message | translate" class="message"></div>
16
+ </div>
17
+ </div>
18
+
19
+ <div *ngIf="log.config.action || log.config.showDismiss" class="actions">
20
+ <button (click)="slideOut(log.id)" *ngIf="log.config.showDismiss" class="dismiss" mat-button>
21
+ {{ 'mosa.commons.buttons.dismiss' | translate | uppercase }}
22
+ </button>
23
+ <button (click)="$event.stopPropagation(); callAction(log)"
24
+ *ngIf="log.config.action && log.config.action.label && log.config.action.callback"
25
+ class="action-btn" mat-button>
26
+ {{ log.config.action.label | translate | uppercase }}
27
+ </button>
28
+ </div>
29
+
30
+ </div>
31
+ </ng-container>
32
+
@@ -0,0 +1,120 @@
1
+ @import "../../styles/vars";
2
+
3
+ :host {
4
+ @include size(100%, 100%);
5
+ @include move(0, 0);
6
+ @include flex(true, false);
7
+ position: fixed;
8
+ z-index: 10000;
9
+ align-items: flex-end;
10
+ pointer-events: none;
11
+ }
12
+
13
+ .logger-element {
14
+ padding: 10px 15px;
15
+ margin: 10px 10px 0;
16
+ width: 350px;
17
+ background: $white;
18
+ border-radius: 4px;
19
+ box-shadow: 3px 3px 10px rgba($black, .3);
20
+ border-left: 5px solid;
21
+ pointer-events: all;
22
+ max-height: 400px;
23
+
24
+ &.touch {
25
+ cursor: pointer;
26
+ }
27
+
28
+ .content {
29
+ display: flex;
30
+ width: 100%;
31
+
32
+ .icon {
33
+ flex-shrink: 0;
34
+ margin-right: 10px;
35
+ }
36
+
37
+ .title {
38
+ font-weight: 500;
39
+ color: #222222;
40
+ }
41
+
42
+ .message {
43
+ @include maxLines();
44
+ flex: 1 auto;
45
+ font-size: 15px;
46
+ margin-top: 3px;
47
+ color: #222222;
48
+ }
49
+ }
50
+
51
+ .actions {
52
+ display: flex;
53
+ justify-content: flex-end;
54
+ margin-top: 10px;
55
+ }
56
+
57
+ .dismiss {
58
+ color: #222222;
59
+ }
60
+
61
+ button:not(:first-child) {
62
+ margin-left: 10px;
63
+ }
64
+
65
+ &.snackbar-error {
66
+ border-color: $danger;
67
+ color: $danger;
68
+
69
+ button.action-btn {
70
+ background-color: darken($danger, 15%);
71
+ color: $white;
72
+ }
73
+ }
74
+
75
+ &.snackbar-success {
76
+ border-color: $success;
77
+ color: $success;
78
+
79
+ button.action-btn {
80
+ background-color: darken($success, 15%);
81
+ color: $white;
82
+ }
83
+ }
84
+
85
+ &.snackbar-warning {
86
+ border-color: $warning;
87
+ color: $warning;
88
+
89
+ button.action-btn {
90
+ background-color: darken($warning, 10%);
91
+ color: $white;
92
+ }
93
+ }
94
+
95
+ &.snackbar-info {
96
+ border-color: $info;
97
+ color: $info;
98
+
99
+ button.action-btn {
100
+ background-color: darken($info, 15%);
101
+ color: $white;
102
+ }
103
+ }
104
+
105
+ &.snackbar-default {
106
+ border-color: #222222;
107
+ color: #222222;
108
+
109
+ button.action-btn {
110
+ background-color: #222222;
111
+ color: $white;
112
+ }
113
+ }
114
+ }
115
+
116
+ @media screen and (max-width: 480px) {
117
+ .logger-element {
118
+ width: 100%;
119
+ }
120
+ }
@@ -0,0 +1,116 @@
1
+ import { animate, state, style, transition, trigger } from '@angular/animations';
2
+ import { ChangeDetectionStrategy, Component, OnInit, QueryList, ViewChildren } from '@angular/core';
3
+ import { ILog, ILoggerConfig } from '@mosa-ng/core';
4
+ import { Observable } from 'rxjs';
5
+ import { ILoggerState } from '../../models/states/logger-state.model';
6
+ import { LoggerFacade } from '../../services/facades/logger.facade';
7
+ import { BaseComponent } from '../base/base.component';
8
+
9
+ @Component({
10
+ selector: 'mosa-logger',
11
+ templateUrl: './logger.component.html',
12
+ styleUrls: [ './logger.component.scss' ],
13
+ animations: [
14
+ trigger('slide', [
15
+ state('enter', style({ transform: 'translateX(0)' })),
16
+ transition(':leave', [
17
+ animate(200, style({ transform: 'translateX(120%)' })),
18
+ ]),
19
+ transition(':enter', [
20
+ style({ transform: 'translateX(120%)' }),
21
+ animate(200, style({ transform: 'translateX(0)' })),
22
+ ]),
23
+ ]),
24
+ ],
25
+ changeDetection: ChangeDetectionStrategy.OnPush,
26
+ })
27
+ export class LoggerComponent extends BaseComponent implements OnInit {
28
+
29
+ @ViewChildren('loggerElement')
30
+ public elements: QueryList<HTMLElement>;
31
+
32
+ public loggerState$: Observable<ILoggerState>;
33
+
34
+ /**
35
+ * Default constructor
36
+ * @param myLoggerFacade
37
+ */
38
+ constructor(
39
+ private readonly myLoggerFacade: LoggerFacade,
40
+ ) {
41
+ super();
42
+ }
43
+
44
+ public override ngOnInit(): void {
45
+ super.ngOnInit();
46
+ this.loggerState$ = this.myLoggerFacade.subState();
47
+ }
48
+
49
+ public onClickLog(log: ILog): void {
50
+ if (log.config.closeOnClick) {
51
+ this.slideOut(log.id);
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Shows the snackbar
57
+ * @param title
58
+ * @param message
59
+ * @param type
60
+ * @param config
61
+ */
62
+ public slideIn(title: string, message: string, type: string, config: ILoggerConfig): number {
63
+ const logs: ILog[] = [ ...this.myLoggerFacade.snapshot.logs ];
64
+ const i = logs.length;
65
+ let icon: string;
66
+
67
+ switch (type) {
68
+ case 'error':
69
+ icon = 'error';
70
+ break;
71
+ case 'warning':
72
+ icon = 'warning';
73
+ break;
74
+ case 'info':
75
+ icon = 'info';
76
+ break;
77
+ case 'success':
78
+ icon = 'done';
79
+ break;
80
+ case 'default':
81
+ icon = 'notifications';
82
+ break;
83
+ }
84
+
85
+ logs.push({ id: i, title, message, config, state: 'enter', icon });
86
+ this.myLoggerFacade.updateLogs(logs);
87
+ return i;
88
+ }
89
+
90
+ /**
91
+ * Hides the log
92
+ * @param id
93
+ */
94
+ public slideOut(id: number): void {
95
+ let logs: ILog[] = [ ...this.myLoggerFacade.snapshot.logs ];
96
+ if (logs.length > 0) {
97
+ const item = logs.find((e: ILog): boolean => e.id === id);
98
+ if (item) {
99
+ item.state = 'leave';
100
+ this.myLoggerFacade.updateLogs(logs);
101
+ setTimeout((): void => {
102
+ logs = [ ...this.myLoggerFacade.snapshot.logs ];
103
+ const index = logs.findIndex((log: ILog): boolean => log.id === item.id);
104
+ logs.splice(index, 1);
105
+ this.myLoggerFacade.updateLogs(logs);
106
+ }, 200);
107
+ }
108
+ }
109
+ }
110
+
111
+ public callAction(log: ILog): void {
112
+ log.config.action.callback.call(this);
113
+ this.slideOut(log.id);
114
+ }
115
+
116
+ }
@@ -0,0 +1,23 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { NgModule } from '@angular/core';
3
+ import { MatButtonModule } from '@angular/material/button';
4
+ import { MatIconModule } from '@angular/material/icon';
5
+ import { TranslateModule } from '@ngx-translate/core';
6
+ import { LoggerComponent } from './logger.component';
7
+
8
+ @NgModule({
9
+ declarations: [
10
+ LoggerComponent,
11
+ ],
12
+ imports: [
13
+ CommonModule,
14
+ MatIconModule,
15
+ MatButtonModule,
16
+ TranslateModule,
17
+ ],
18
+ exports: [
19
+ LoggerComponent,
20
+ ],
21
+ })
22
+ export class LoggerModule {
23
+ }
@@ -0,0 +1,14 @@
1
+ import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
2
+
3
+ @Component({
4
+ selector: 'mosa-skeleton-loader',
5
+ template: '',
6
+ changeDetection: ChangeDetectionStrategy.OnPush,
7
+ })
8
+ // eslint-disable-next-line @angular-eslint/component-class-suffix
9
+ export class BaseSkeletonLoader {
10
+
11
+ @Input()
12
+ public itemCount: number;
13
+
14
+ }
@@ -0,0 +1,17 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { NgModule } from '@angular/core';
3
+ import { MatListModule } from '@angular/material/list';
4
+ import { SkeletonLoaderModule } from '../skeleton-loader.module';
5
+ import { ListSkeletonLoader } from './list.skeleton-loader';
6
+
7
+ @NgModule({
8
+ declarations: [ ListSkeletonLoader ],
9
+ imports: [
10
+ CommonModule,
11
+ MatListModule,
12
+ SkeletonLoaderModule,
13
+ ],
14
+ exports: [ ListSkeletonLoader ],
15
+ })
16
+ export class ListSkeletonLoaderModule {
17
+ }
@@ -0,0 +1,5 @@
1
+ <mat-list>
2
+ <mat-list-item *ngFor="let item of items">
3
+ <ng-container *ngTemplateOutlet="content, context: { $implicit: item }"></ng-container>
4
+ </mat-list-item>
5
+ </mat-list>
@@ -0,0 +1,26 @@
1
+ import { ChangeDetectionStrategy, Component, Input, OnInit, TemplateRef } from '@angular/core';
2
+ import { BaseSkeletonLoader } from '../base.skeleton-loader';
3
+
4
+ @Component({
5
+ selector: 'mosa-list-skeleton-loader',
6
+ templateUrl: './list.skeleton-loader.html',
7
+ styleUrls: [ './list.skeleton-loader.scss' ],
8
+ changeDetection: ChangeDetectionStrategy.OnPush,
9
+ })
10
+ // eslint-disable-next-line @angular-eslint/component-class-suffix
11
+ export class ListSkeletonLoader extends BaseSkeletonLoader implements OnInit {
12
+
13
+ @Input()
14
+ public content: TemplateRef<unknown>;
15
+
16
+ public items: number[] = [];
17
+
18
+ constructor() {
19
+ super();
20
+ }
21
+
22
+ public ngOnInit(): void {
23
+ this.items = Array(this.itemCount).fill(this.itemCount).map((x: number, i: number): number => i);
24
+ }
25
+
26
+ }
@@ -0,0 +1,15 @@
1
+ :host {
2
+ display: flex;
3
+ background: #d4d4d4;
4
+ flex-shrink: 0;
5
+ animation: loading .25s infinite linear alternate-reverse;
6
+ }
7
+
8
+ @keyframes loading {
9
+ from {
10
+ opacity: 1;
11
+ }
12
+ to {
13
+ opacity: .5;
14
+ }
15
+ }
@@ -0,0 +1,64 @@
1
+ import { ChangeDetectionStrategy, Component, ElementRef, Input, OnInit } from '@angular/core';
2
+ import { Skeleton } from '../../../models/skeleton.model';
3
+
4
+ @Component({
5
+ selector: 'mosa-skeleton',
6
+ templateUrl: './skeleton.component.html',
7
+ styleUrls: [ './skeleton.component.scss' ],
8
+ changeDetection: ChangeDetectionStrategy.OnPush,
9
+ })
10
+ export class SkeletonComponent implements OnInit {
11
+
12
+ @Input()
13
+ public skeleton: Skeleton;
14
+
15
+ @Input()
16
+ public width: number | string;
17
+
18
+ @Input()
19
+ public height: number | string;
20
+
21
+ @Input()
22
+ public randomizeOffset: number;
23
+
24
+ @Input()
25
+ public borderRadius: number | string;
26
+
27
+ private readonly element: HTMLElement;
28
+
29
+ constructor(
30
+ private readonly myElementRef: ElementRef,
31
+ ) {
32
+ this.element = this.myElementRef.nativeElement;
33
+ }
34
+
35
+ public ngOnInit(): void {
36
+ if (!this.skeleton) {
37
+ this.skeleton = new Skeleton({
38
+ width: this.width,
39
+ height: this.height,
40
+ borderRadius: this.borderRadius,
41
+ randomizeOffset: this.randomizeOffset,
42
+ });
43
+ }
44
+ this.element.style.width = this.actualWidth;
45
+ this.element.style.height = SkeletonComponent.value(this.skeleton.height);
46
+ this.element.style.borderRadius = SkeletonComponent.value(this.skeleton.borderRadius);
47
+ }
48
+
49
+ private get actualWidth(): string {
50
+ if (this.skeleton.randomizeOffset > 0 && typeof this.skeleton.width === 'number') {
51
+ return `${ this.skeleton.width - Math.floor(Math.random() * this.skeleton.randomizeOffset) }px`;
52
+ }
53
+
54
+ return SkeletonComponent.value(this.skeleton.width);
55
+ }
56
+
57
+ private static value(val: number | string): string {
58
+ if (typeof val === 'number') {
59
+ return `${ val }px`;
60
+ }
61
+ return val;
62
+ }
63
+
64
+ }
@@ -0,0 +1,17 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { NgModule } from '@angular/core';
3
+ import { BaseSkeletonLoader } from './base.skeleton-loader';
4
+ import { SkeletonComponent } from './skeleton/skeleton.component';
5
+
6
+ @NgModule({
7
+ declarations: [ BaseSkeletonLoader, SkeletonComponent ],
8
+ imports: [
9
+ CommonModule,
10
+ ],
11
+ exports: [
12
+ BaseSkeletonLoader,
13
+ SkeletonComponent,
14
+ ],
15
+ })
16
+ export class SkeletonLoaderModule {
17
+ }
@@ -0,0 +1,19 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { NgModule } from '@angular/core';
3
+ import { MatTableModule } from '@angular/material/table';
4
+ import { SkeletonLoaderModule } from '../skeleton-loader.module';
5
+ import { TableSkeletonLoader } from './table.skeleton-loader';
6
+
7
+ @NgModule({
8
+ declarations: [ TableSkeletonLoader ],
9
+ imports: [
10
+ CommonModule,
11
+ MatTableModule,
12
+ SkeletonLoaderModule,
13
+ ],
14
+ exports: [
15
+ TableSkeletonLoader,
16
+ ],
17
+ })
18
+ export class TableSkeletonLoaderModule {
19
+ }
@@ -0,0 +1,12 @@
1
+ <table [dataSource]="items" mat-table>
2
+ <ng-container *ngFor="let column of columns; let i = index;" [matColumnDef]="'column-' + i">
3
+ <th *matHeaderCellDef mat-header-cell>
4
+ <mosa-skeleton [skeleton]="column[0]"></mosa-skeleton>
5
+ </th>
6
+ <td *matCellDef="let row" mat-cell>
7
+ <mosa-skeleton [skeleton]="column[1]"></mosa-skeleton>
8
+ </td>
9
+ </ng-container>
10
+ <tr *matHeaderRowDef="displayedColumns;sticky:true" mat-header-row></tr>
11
+ <tr *matRowDef="let row; columns: displayedColumns;" class="row-hover" mat-row></tr>
12
+ </table>