ngwr 0.0.1
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.
- package/button/button.component.ts +132 -0
- package/button/button.module.ts +11 -0
- package/button/index.ts +2 -0
- package/core/types/convert-input.ts +2 -0
- package/core/types/index.ts +3 -0
- package/core/types/indexable.ts +3 -0
- package/core/types/ng-class.ts +11 -0
- package/core/util/convert.ts +63 -0
- package/core/util/index.ts +1 -0
- package/divider/divider.component.ts +13 -0
- package/divider/divider.module.ts +10 -0
- package/divider/index.ts +2 -0
- package/extended-input/extended-input.component.html +13 -0
- package/extended-input/extended-input.component.ts +77 -0
- package/extended-input/extended-input.module.ts +17 -0
- package/extended-input/index.ts +2 -0
- package/form/form-error.component.ts +20 -0
- package/form/form-item.component.ts +60 -0
- package/form/form.module.ts +17 -0
- package/form/index.ts +3 -0
- package/icon/icon.component.ts +45 -0
- package/icon/icons.ts +229 -0
- package/icon/index.ts +3 -0
- package/icon/walrus-icons-registry.service.ts +20 -0
- package/icon/walrus-icons.module.ts +8 -0
- package/index.ts +1 -0
- package/input/index.ts +2 -0
- package/input/input.directive.ts +65 -0
- package/input/input.module.ts +16 -0
- package/ng-package.json +11 -0
- package/package.json +27 -0
- package/password-input/index.ts +2 -0
- package/password-input/password-input.component.html +10 -0
- package/password-input/password-input.component.ts +56 -0
- package/password-input/password-input.module.ts +28 -0
- package/public-api.ts +10 -0
- package/skeleton/index.ts +2 -0
- package/skeleton/skeleton.component.ts +38 -0
- package/skeleton/skeleton.module.ts +11 -0
- package/spinner/index.ts +2 -0
- package/spinner/spinner.component.ts +11 -0
- package/spinner/spinner.module.ts +10 -0
- package/styles/components/_index.scss +15 -0
- package/styles/components/alert.scss +28 -0
- package/styles/components/button.scss +115 -0
- package/styles/components/card.scss +41 -0
- package/styles/components/divider.scss +19 -0
- package/styles/components/dropdown.scss +128 -0
- package/styles/components/extended-input.scss +64 -0
- package/styles/components/form.scss +85 -0
- package/styles/components/heading.scss +25 -0
- package/styles/components/icon.scss +32 -0
- package/styles/components/input.scss +43 -0
- package/styles/components/password-input.scss +31 -0
- package/styles/components/skeleton.scss +58 -0
- package/styles/components/spinner.scss +44 -0
- package/styles/components/tag.scss +70 -0
- package/styles/components/tooltip.scss +60 -0
- package/styles/functions.scss +184 -0
- package/styles/grid.scss +177 -0
- package/styles/index.scss +165 -0
- package/styles/mixins/_index.scss +22 -0
- package/styles/mixins/alert.scss +7 -0
- package/styles/mixins/button.scss +56 -0
- package/styles/mixins/reset-component.scss +13 -0
- package/styles/mixins/tag.scss +68 -0
- package/styles/reset.scss +104 -0
- package/styles/root.scss +31 -0
- package/styles/vars.scss +1075 -0
- package/tag/index.ts +2 -0
- package/tag/tag.component.ts +92 -0
- package/tag/tag.module.ts +11 -0
- package/tsconfig.lib.json +15 -0
- package/tsconfig.lib.prod.json +10 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AfterViewInit,
|
|
3
|
+
ChangeDetectionStrategy,
|
|
4
|
+
ChangeDetectorRef,
|
|
5
|
+
Component,
|
|
6
|
+
ElementRef,
|
|
7
|
+
Input,
|
|
8
|
+
NgZone, OnChanges,
|
|
9
|
+
OnDestroy,
|
|
10
|
+
OnInit,
|
|
11
|
+
Renderer2, SimpleChanges,
|
|
12
|
+
ViewEncapsulation
|
|
13
|
+
} from '@angular/core';
|
|
14
|
+
import { fromEvent, Subject } from 'rxjs';
|
|
15
|
+
import { takeUntil } from 'rxjs/operators';
|
|
16
|
+
import { InputBoolean } from '../core/util';
|
|
17
|
+
|
|
18
|
+
export type WalrusButtonColor = 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'danger';
|
|
19
|
+
export type WalrusButtonSize = 'default' | 'small';
|
|
20
|
+
|
|
21
|
+
@Component({
|
|
22
|
+
selector: 'wr-btn, [wr-btn]',
|
|
23
|
+
exportAs: 'wrButton',
|
|
24
|
+
preserveWhitespaces: false,
|
|
25
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
26
|
+
encapsulation: ViewEncapsulation.None,
|
|
27
|
+
template: `<ng-content></ng-content><wr-spin *ngIf="loading"></wr-spin>`
|
|
28
|
+
})
|
|
29
|
+
export class WalrusButtonComponent implements OnInit, OnDestroy, AfterViewInit, OnChanges {
|
|
30
|
+
@Input() color: WalrusButtonColor = 'primary';
|
|
31
|
+
@Input() size: WalrusButtonSize = 'default';
|
|
32
|
+
|
|
33
|
+
@Input() @InputBoolean() disabled: boolean | string = false;
|
|
34
|
+
@Input() @InputBoolean() outlined: boolean | string = false;
|
|
35
|
+
@Input() @InputBoolean() rounded: boolean | string = false;
|
|
36
|
+
@Input() @InputBoolean() loading: boolean | string = false;
|
|
37
|
+
@Input() @InputBoolean() block: boolean | string = false;
|
|
38
|
+
|
|
39
|
+
private readonly baseClass: string = 'wr-btn';
|
|
40
|
+
private destroy$: Subject<void> = new Subject<void>();
|
|
41
|
+
|
|
42
|
+
constructor(
|
|
43
|
+
private readonly cdr: ChangeDetectorRef,
|
|
44
|
+
private readonly elRef: ElementRef,
|
|
45
|
+
private readonly ngZone: NgZone,
|
|
46
|
+
private readonly r2: Renderer2,
|
|
47
|
+
) {}
|
|
48
|
+
|
|
49
|
+
ngOnInit(): void {
|
|
50
|
+
this.setClasses();
|
|
51
|
+
|
|
52
|
+
this.ngZone.runOutsideAngular(() => {
|
|
53
|
+
/**
|
|
54
|
+
* Caretaker note: this event listener could've been added through `host.click` or `HostListener`.
|
|
55
|
+
* The compiler generates the `ɵɵlistener` instruction which wraps the actual listener internally into the
|
|
56
|
+
* function, which runs `markDirty()` before running the actual listener (the decorated class method).
|
|
57
|
+
* Since we're preventing the default behavior and stopping event propagation
|
|
58
|
+
* this doesn't require Angular to run the change detection.
|
|
59
|
+
*/
|
|
60
|
+
fromEvent<MouseEvent>(this.elRef.nativeElement, 'click')
|
|
61
|
+
.pipe(takeUntil(this.destroy$))
|
|
62
|
+
.subscribe(event => {
|
|
63
|
+
if (this.disabled && (event.target as HTMLElement)?.tagName === 'A') {
|
|
64
|
+
event.preventDefault();
|
|
65
|
+
event.stopImmediatePropagation();
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
ngAfterViewInit(): void {
|
|
72
|
+
this.insertSpan(this.elRef.nativeElement.childNodes, this.r2);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
ngOnDestroy(): void {
|
|
76
|
+
this.destroy$.next();
|
|
77
|
+
this.destroy$.complete();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
ngOnChanges(changes: SimpleChanges) {
|
|
81
|
+
if (!changes['disabled']?.currentValue) {
|
|
82
|
+
this.r2.removeClass(this.elRef.nativeElement, `${this.baseClass}--disabled`);
|
|
83
|
+
}
|
|
84
|
+
if (!changes['disabled']?.currentValue) {
|
|
85
|
+
this.r2.removeClass(this.elRef.nativeElement, `${this.baseClass}--loading`);
|
|
86
|
+
}
|
|
87
|
+
this.setClasses();
|
|
88
|
+
this.cdr.detectChanges();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
private insertSpan(nodes: NodeList, renderer: Renderer2): void {
|
|
92
|
+
nodes.forEach(node => {
|
|
93
|
+
if (node.nodeName === '#text') {
|
|
94
|
+
const span = renderer.createElement('span');
|
|
95
|
+
renderer.addClass(span, 'wr-btn__text');
|
|
96
|
+
const parent = renderer.parentNode(node);
|
|
97
|
+
renderer.insertBefore(parent, span, node);
|
|
98
|
+
renderer.appendChild(span, node);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
private setClasses() {
|
|
104
|
+
const el = this.elRef.nativeElement;
|
|
105
|
+
const add = (klass: string) => this.r2.addClass(el, `${this.baseClass}-${klass}`);
|
|
106
|
+
|
|
107
|
+
this.r2.addClass(el, this.baseClass);
|
|
108
|
+
add(this.color);
|
|
109
|
+
|
|
110
|
+
if (this.rounded) {
|
|
111
|
+
add(`-rounded`);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (this.loading) {
|
|
115
|
+
add(`-loading`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (this.block) {
|
|
119
|
+
add(`-block`);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
add(`-${this.size}`);
|
|
123
|
+
|
|
124
|
+
if (this.outlined) {
|
|
125
|
+
add(`-outlined`);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (this.disabled) {
|
|
129
|
+
add('-disabled');
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { CommonModule } from '@angular/common';
|
|
2
|
+
import { NgModule } from '@angular/core';
|
|
3
|
+
import { WalrusSpinnerModule } from '../spinner';
|
|
4
|
+
import { WalrusButtonComponent } from './button.component';
|
|
5
|
+
|
|
6
|
+
@NgModule({
|
|
7
|
+
imports: [CommonModule, WalrusSpinnerModule],
|
|
8
|
+
declarations: [WalrusButtonComponent],
|
|
9
|
+
exports: [WalrusButtonComponent],
|
|
10
|
+
})
|
|
11
|
+
export class WalrusButtonModule {}
|
package/button/index.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type NgClassType = string | string[] | Set<string> | NgClassInterface;
|
|
2
|
+
|
|
3
|
+
// use klass vs class
|
|
4
|
+
export interface NgClassInterface {
|
|
5
|
+
[klass: string]: any;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// use klass vs class
|
|
9
|
+
export interface NgStyleInterface {
|
|
10
|
+
[klass: string]: any;
|
|
11
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
|
2
|
+
|
|
3
|
+
export function toBoolean(value: boolean | string): boolean {
|
|
4
|
+
return coerceBooleanProperty(value);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function propDecoratorFactory<T, D>(
|
|
8
|
+
name: string,
|
|
9
|
+
fallback: (v: T) => D
|
|
10
|
+
): (target: any, propName: string) => void {
|
|
11
|
+
function propDecorator(
|
|
12
|
+
target: any,
|
|
13
|
+
propName: string,
|
|
14
|
+
originalDescriptor?: TypedPropertyDescriptor<any>
|
|
15
|
+
): any {
|
|
16
|
+
const privatePropName = `$$__walrusPropDecorator__${propName}`;
|
|
17
|
+
|
|
18
|
+
if (Object.prototype.hasOwnProperty.call(target, privatePropName)) {
|
|
19
|
+
console.warn(`The prop "${privatePropName}" is already exist, it will be overrided by ${name} decorator.`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
Object.defineProperty(target, privatePropName, {
|
|
23
|
+
configurable: true,
|
|
24
|
+
writable: true
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
get(): string {
|
|
29
|
+
return originalDescriptor && originalDescriptor.get
|
|
30
|
+
? originalDescriptor.get.bind(this)()
|
|
31
|
+
: this[privatePropName];
|
|
32
|
+
},
|
|
33
|
+
set(value: T): void {
|
|
34
|
+
if (originalDescriptor && originalDescriptor.set) {
|
|
35
|
+
originalDescriptor.set.bind(this)(fallback(value));
|
|
36
|
+
}
|
|
37
|
+
this[privatePropName] = fallback(value);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return propDecorator;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Input decorator that handle a prop to do get/set automatically with toBoolean
|
|
47
|
+
*
|
|
48
|
+
* Why not using @InputBoolean alone without @Input? AOT needs @Input to be visible
|
|
49
|
+
*
|
|
50
|
+
* @howToUse
|
|
51
|
+
* ```
|
|
52
|
+
* @Input() @InputBoolean() visible: boolean = false;
|
|
53
|
+
*
|
|
54
|
+
* // Act as below:
|
|
55
|
+
* // @Input()
|
|
56
|
+
* // get visible() { return this.__visible; }
|
|
57
|
+
* // set visible(value) { this.__visible = value; }
|
|
58
|
+
* // __visible = false;
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export function InputBoolean(): any {
|
|
62
|
+
return propDecoratorFactory('InputBoolean', toBoolean);
|
|
63
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './convert';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, HostBinding, ViewEncapsulation } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
@Component({
|
|
4
|
+
selector: 'wr-divider',
|
|
5
|
+
exportAs: 'wrDivider',
|
|
6
|
+
preserveWhitespaces: false,
|
|
7
|
+
template: '',
|
|
8
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
9
|
+
encapsulation: ViewEncapsulation.None
|
|
10
|
+
})
|
|
11
|
+
export class WalrusDividerComponent {
|
|
12
|
+
@HostBinding('class') classes = `wr-divider`;
|
|
13
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CommonModule } from '@angular/common';
|
|
2
|
+
import { NgModule } from '@angular/core';
|
|
3
|
+
import { WalrusDividerComponent } from './divider.component';
|
|
4
|
+
|
|
5
|
+
@NgModule({
|
|
6
|
+
imports: [CommonModule],
|
|
7
|
+
declarations: [WalrusDividerComponent],
|
|
8
|
+
exports: [WalrusDividerComponent]
|
|
9
|
+
})
|
|
10
|
+
export class WalrusDividerModule {}
|
package/divider/index.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<div class="wr-extended-input-prefix" *ngIf="prefix">
|
|
2
|
+
<span class="wr-extended-input-prefix__text" >{{ prefix }}</span>
|
|
3
|
+
</div>
|
|
4
|
+
<input
|
|
5
|
+
wr-input
|
|
6
|
+
[disabled]="disabled"
|
|
7
|
+
[value]="value"
|
|
8
|
+
(focusout)="onFocusOut()"
|
|
9
|
+
(input)="onInput($event)"
|
|
10
|
+
>
|
|
11
|
+
<div class="wr-extended-input-suffix" *ngIf="suffix">
|
|
12
|
+
<span class="wr-extended-input-suffix__text" >{{ suffix }}</span>
|
|
13
|
+
</div>
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Component,
|
|
3
|
+
ElementRef,
|
|
4
|
+
HostBinding,
|
|
5
|
+
Input,
|
|
6
|
+
OnInit,
|
|
7
|
+
Optional,
|
|
8
|
+
Renderer2,
|
|
9
|
+
Self,
|
|
10
|
+
ViewEncapsulation
|
|
11
|
+
} from '@angular/core';
|
|
12
|
+
import { ControlValueAccessor, NgControl } from '@angular/forms';
|
|
13
|
+
|
|
14
|
+
@Component({
|
|
15
|
+
selector: 'wr-extended-input',
|
|
16
|
+
templateUrl: './extended-input.component.html',
|
|
17
|
+
encapsulation: ViewEncapsulation.None
|
|
18
|
+
})
|
|
19
|
+
export class WalrusExtendedInputComponent implements ControlValueAccessor, OnInit {
|
|
20
|
+
@HostBinding('class') class = 'wr-extended-input';
|
|
21
|
+
@Input() suffix?: string;
|
|
22
|
+
@Input() prefix?: string;
|
|
23
|
+
|
|
24
|
+
public disabled: boolean = false;
|
|
25
|
+
public value: string | undefined = undefined;
|
|
26
|
+
public touched = false;
|
|
27
|
+
|
|
28
|
+
constructor(
|
|
29
|
+
@Optional() @Self() public ngControl: NgControl,
|
|
30
|
+
private readonly elRef: ElementRef,
|
|
31
|
+
private readonly r2: Renderer2
|
|
32
|
+
) {
|
|
33
|
+
if (ngControl !== null) {
|
|
34
|
+
ngControl.valueAccessor = this;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public ngOnInit(): void {
|
|
39
|
+
const el = this.elRef.nativeElement;
|
|
40
|
+
const add = (klass: string) => this.r2.addClass(el, `${this.class}-${klass}`);
|
|
41
|
+
|
|
42
|
+
if (this.suffix) {
|
|
43
|
+
add('-has-suffix')
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (this.prefix) {
|
|
47
|
+
add('-has-prefix')
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
onInput($event: any): void {
|
|
52
|
+
this.value = $event.currentTarget.value;
|
|
53
|
+
this.touched = true;
|
|
54
|
+
this.onChange(this.value);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
onChange = (value: any) => {};
|
|
58
|
+
|
|
59
|
+
onTouched = () => {};
|
|
60
|
+
|
|
61
|
+
onFocusOut(): void {
|
|
62
|
+
this.touched = true;
|
|
63
|
+
this.onTouched();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
registerOnChange(fn: any) {
|
|
67
|
+
this.onChange = fn;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
registerOnTouched(fn: any) {
|
|
71
|
+
this.onTouched = fn;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
writeValue(obj: any): void {
|
|
75
|
+
this.value = obj;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { PlatformModule } from '@angular/cdk/platform';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
import { NgModule } from '@angular/core';
|
|
4
|
+
|
|
5
|
+
import { WalrusInputModule } from '../input';
|
|
6
|
+
import { WalrusExtendedInputComponent } from './extended-input.component';
|
|
7
|
+
|
|
8
|
+
@NgModule({
|
|
9
|
+
imports: [
|
|
10
|
+
CommonModule,
|
|
11
|
+
PlatformModule,
|
|
12
|
+
WalrusInputModule,
|
|
13
|
+
],
|
|
14
|
+
declarations: [WalrusExtendedInputComponent],
|
|
15
|
+
exports: [WalrusExtendedInputComponent]
|
|
16
|
+
})
|
|
17
|
+
export class WalrusExtendedInputModule {}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, HostBinding, OnDestroy, ViewEncapsulation } from '@angular/core';
|
|
2
|
+
import { Subject } from 'rxjs';
|
|
3
|
+
|
|
4
|
+
@Component({
|
|
5
|
+
selector: 'wr-form-error',
|
|
6
|
+
exportAs: 'wrFormError',
|
|
7
|
+
preserveWhitespaces: false,
|
|
8
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
9
|
+
encapsulation: ViewEncapsulation.None,
|
|
10
|
+
template: `<ng-content></ng-content>`
|
|
11
|
+
})
|
|
12
|
+
export class WalrusFormErrorComponent implements OnDestroy {
|
|
13
|
+
@HostBinding() class = 'wr-form-error';
|
|
14
|
+
private destroy$ = new Subject();
|
|
15
|
+
|
|
16
|
+
ngOnDestroy(): void {
|
|
17
|
+
this.destroy$.next(null);
|
|
18
|
+
this.destroy$.complete();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ChangeDetectionStrategy,
|
|
3
|
+
ChangeDetectorRef,
|
|
4
|
+
Component,
|
|
5
|
+
ElementRef, Input, OnChanges,
|
|
6
|
+
OnDestroy, OnInit, Renderer2, SimpleChanges,
|
|
7
|
+
ViewEncapsulation
|
|
8
|
+
} from '@angular/core';
|
|
9
|
+
import { Subject } from 'rxjs';
|
|
10
|
+
import { InputBoolean } from '../core/util';
|
|
11
|
+
|
|
12
|
+
@Component({
|
|
13
|
+
selector: 'wr-form-item',
|
|
14
|
+
exportAs: 'wrFormItem',
|
|
15
|
+
preserveWhitespaces: false,
|
|
16
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
17
|
+
encapsulation: ViewEncapsulation.None,
|
|
18
|
+
template: `<ng-content></ng-content>`
|
|
19
|
+
})
|
|
20
|
+
export class WalrusFormItemComponent implements OnInit, OnDestroy, OnChanges {
|
|
21
|
+
@Input() @InputBoolean() hasError: boolean = false;
|
|
22
|
+
|
|
23
|
+
private readonly destroy$ = new Subject();
|
|
24
|
+
|
|
25
|
+
constructor(
|
|
26
|
+
private readonly cdr: ChangeDetectorRef,
|
|
27
|
+
private readonly el: ElementRef,
|
|
28
|
+
private readonly r2: Renderer2,
|
|
29
|
+
) {}
|
|
30
|
+
|
|
31
|
+
public ngOnInit(): void {
|
|
32
|
+
this.setClasses();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public ngOnDestroy(): void {
|
|
36
|
+
this.destroy$.next(null);
|
|
37
|
+
this.destroy$.complete();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public ngOnChanges(changes: SimpleChanges): void {
|
|
41
|
+
const baseClass = 'wr-form-item';
|
|
42
|
+
if (!changes['hasError']?.currentValue) {
|
|
43
|
+
this.r2.removeClass(this.el.nativeElement, `${baseClass}--has-error`);
|
|
44
|
+
}
|
|
45
|
+
this.setClasses();
|
|
46
|
+
this.cdr.detectChanges();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private setClasses(): void {
|
|
50
|
+
const baseClass = 'wr-form-item';
|
|
51
|
+
const el = this.el.nativeElement;
|
|
52
|
+
const add = (klass: string) => this.r2.addClass(el, `${baseClass}-${klass}`);
|
|
53
|
+
|
|
54
|
+
this.r2.addClass(el, baseClass);
|
|
55
|
+
|
|
56
|
+
if (this.hasError) {
|
|
57
|
+
add('-has-error');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { CommonModule } from '@angular/common';
|
|
2
|
+
import { NgModule } from '@angular/core';
|
|
3
|
+
import { WalrusFormItemComponent } from './form-item.component';
|
|
4
|
+
import { WalrusFormErrorComponent } from './form-error.component';
|
|
5
|
+
|
|
6
|
+
@NgModule({
|
|
7
|
+
imports: [CommonModule],
|
|
8
|
+
declarations: [
|
|
9
|
+
WalrusFormItemComponent,
|
|
10
|
+
WalrusFormErrorComponent
|
|
11
|
+
],
|
|
12
|
+
exports: [
|
|
13
|
+
WalrusFormItemComponent,
|
|
14
|
+
WalrusFormErrorComponent
|
|
15
|
+
]
|
|
16
|
+
})
|
|
17
|
+
export class WalrusFormModule {}
|
package/form/index.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ChangeDetectionStrategy,
|
|
3
|
+
Component,
|
|
4
|
+
ElementRef, HostBinding,
|
|
5
|
+
Inject,
|
|
6
|
+
Input,
|
|
7
|
+
Optional,
|
|
8
|
+
ViewEncapsulation
|
|
9
|
+
} from '@angular/core';
|
|
10
|
+
import { WalrusIconsRegistry } from './walrus-icons-registry.service';
|
|
11
|
+
import { DOCUMENT } from '@angular/common';
|
|
12
|
+
import { walrusIcon } from './icons';
|
|
13
|
+
|
|
14
|
+
@Component({
|
|
15
|
+
selector: 'wr-icon[name]',
|
|
16
|
+
template: '<ng-content></ng-content>',
|
|
17
|
+
encapsulation: ViewEncapsulation.None,
|
|
18
|
+
changeDetection: ChangeDetectionStrategy.OnPush
|
|
19
|
+
})
|
|
20
|
+
export class WalrusIconComponent {
|
|
21
|
+
@HostBinding('class') class = 'wr-icon';
|
|
22
|
+
private svgIcon: SVGElement | undefined;
|
|
23
|
+
|
|
24
|
+
@Input()
|
|
25
|
+
set name(iconName: walrusIcon) {
|
|
26
|
+
if (this.svgIcon) {
|
|
27
|
+
this.elRef.nativeElement.removeChild(this.svgIcon);
|
|
28
|
+
}
|
|
29
|
+
const svgData = this.r.getIcon(iconName) || '';
|
|
30
|
+
this.svgIcon = this.svgElementFromString(svgData);
|
|
31
|
+
this.elRef.nativeElement.appendChild(this.svgIcon);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
constructor(
|
|
35
|
+
private readonly elRef: ElementRef,
|
|
36
|
+
private readonly r: WalrusIconsRegistry,
|
|
37
|
+
@Optional() @Inject(DOCUMENT) private readonly doc: any
|
|
38
|
+
) {}
|
|
39
|
+
|
|
40
|
+
private svgElementFromString(svgContent: string): SVGElement {
|
|
41
|
+
const div = this.doc.createElement('div');
|
|
42
|
+
div.innerHTML = svgContent;
|
|
43
|
+
return div.querySelector('svg') || this.doc.createElementNS('http://www.w3.org/2000/svg', 'path');
|
|
44
|
+
}
|
|
45
|
+
}
|