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.
Files changed (74) hide show
  1. package/button/button.component.ts +132 -0
  2. package/button/button.module.ts +11 -0
  3. package/button/index.ts +2 -0
  4. package/core/types/convert-input.ts +2 -0
  5. package/core/types/index.ts +3 -0
  6. package/core/types/indexable.ts +3 -0
  7. package/core/types/ng-class.ts +11 -0
  8. package/core/util/convert.ts +63 -0
  9. package/core/util/index.ts +1 -0
  10. package/divider/divider.component.ts +13 -0
  11. package/divider/divider.module.ts +10 -0
  12. package/divider/index.ts +2 -0
  13. package/extended-input/extended-input.component.html +13 -0
  14. package/extended-input/extended-input.component.ts +77 -0
  15. package/extended-input/extended-input.module.ts +17 -0
  16. package/extended-input/index.ts +2 -0
  17. package/form/form-error.component.ts +20 -0
  18. package/form/form-item.component.ts +60 -0
  19. package/form/form.module.ts +17 -0
  20. package/form/index.ts +3 -0
  21. package/icon/icon.component.ts +45 -0
  22. package/icon/icons.ts +229 -0
  23. package/icon/index.ts +3 -0
  24. package/icon/walrus-icons-registry.service.ts +20 -0
  25. package/icon/walrus-icons.module.ts +8 -0
  26. package/index.ts +1 -0
  27. package/input/index.ts +2 -0
  28. package/input/input.directive.ts +65 -0
  29. package/input/input.module.ts +16 -0
  30. package/ng-package.json +11 -0
  31. package/package.json +27 -0
  32. package/password-input/index.ts +2 -0
  33. package/password-input/password-input.component.html +10 -0
  34. package/password-input/password-input.component.ts +56 -0
  35. package/password-input/password-input.module.ts +28 -0
  36. package/public-api.ts +10 -0
  37. package/skeleton/index.ts +2 -0
  38. package/skeleton/skeleton.component.ts +38 -0
  39. package/skeleton/skeleton.module.ts +11 -0
  40. package/spinner/index.ts +2 -0
  41. package/spinner/spinner.component.ts +11 -0
  42. package/spinner/spinner.module.ts +10 -0
  43. package/styles/components/_index.scss +15 -0
  44. package/styles/components/alert.scss +28 -0
  45. package/styles/components/button.scss +115 -0
  46. package/styles/components/card.scss +41 -0
  47. package/styles/components/divider.scss +19 -0
  48. package/styles/components/dropdown.scss +128 -0
  49. package/styles/components/extended-input.scss +64 -0
  50. package/styles/components/form.scss +85 -0
  51. package/styles/components/heading.scss +25 -0
  52. package/styles/components/icon.scss +32 -0
  53. package/styles/components/input.scss +43 -0
  54. package/styles/components/password-input.scss +31 -0
  55. package/styles/components/skeleton.scss +58 -0
  56. package/styles/components/spinner.scss +44 -0
  57. package/styles/components/tag.scss +70 -0
  58. package/styles/components/tooltip.scss +60 -0
  59. package/styles/functions.scss +184 -0
  60. package/styles/grid.scss +177 -0
  61. package/styles/index.scss +165 -0
  62. package/styles/mixins/_index.scss +22 -0
  63. package/styles/mixins/alert.scss +7 -0
  64. package/styles/mixins/button.scss +56 -0
  65. package/styles/mixins/reset-component.scss +13 -0
  66. package/styles/mixins/tag.scss +68 -0
  67. package/styles/reset.scss +104 -0
  68. package/styles/root.scss +31 -0
  69. package/styles/vars.scss +1075 -0
  70. package/tag/index.ts +2 -0
  71. package/tag/tag.component.ts +92 -0
  72. package/tag/tag.module.ts +11 -0
  73. package/tsconfig.lib.json +15 -0
  74. 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 {}
@@ -0,0 +1,2 @@
1
+ export * from './button.module';
2
+ export * from './button.component';
@@ -0,0 +1,2 @@
1
+ export type BooleanInput = boolean | string | undefined | null;
2
+ export type NumberInput = number | string | undefined | null;
@@ -0,0 +1,3 @@
1
+ export * from './convert-input';
2
+ export * from './indexable';
3
+ export * from './ng-class';
@@ -0,0 +1,3 @@
1
+ export interface IndexableObject {
2
+ [key: string]: any;
3
+ }
@@ -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 {}
@@ -0,0 +1,2 @@
1
+ export * from './divider.module';
2
+ export * from './divider.component';
@@ -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,2 @@
1
+ export * from './extended-input.module';
2
+ export * from './extended-input.component';
@@ -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,3 @@
1
+ export * from './form.module';
2
+ export * from './form-error.component';
3
+ export * from './form-item.component';
@@ -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
+ }