verben-ng-ui 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 (190) hide show
  1. package/README.md +24 -0
  2. package/ng-package.json +10 -0
  3. package/package.json +34 -0
  4. package/src/lib/Verbena-input/error.service.ts +23 -0
  5. package/src/lib/Verbena-input/verbena-input.component.css +59 -0
  6. package/src/lib/Verbena-input/verbena-input.component.html +64 -0
  7. package/src/lib/Verbena-input/verbena-input.component.spec.ts +25 -0
  8. package/src/lib/Verbena-input/verbena-input.component.ts +162 -0
  9. package/src/lib/Verbena-input/verbena-input.module.ts +12 -0
  10. package/src/lib/components/TemplateDirective.directive.ts +10 -0
  11. package/src/lib/components/card/card.component.css +20 -0
  12. package/src/lib/components/card/card.component.html +23 -0
  13. package/src/lib/components/card/card.component.spec.ts +23 -0
  14. package/src/lib/components/card/card.component.ts +33 -0
  15. package/src/lib/components/card/card.module.ts +10 -0
  16. package/src/lib/components/card-data-view/card-data-view-footer/card-data-view-footer.component.css +3 -0
  17. package/src/lib/components/card-data-view/card-data-view-footer/card-data-view-footer.component.html +1 -0
  18. package/src/lib/components/card-data-view/card-data-view-footer/card-data-view-footer.component.spec.ts +23 -0
  19. package/src/lib/components/card-data-view/card-data-view-footer/card-data-view-footer.component.ts +10 -0
  20. package/src/lib/components/card-data-view/card-data-view-header/card-data-view-header.component.css +7 -0
  21. package/src/lib/components/card-data-view/card-data-view-header/card-data-view-header.component.html +1 -0
  22. package/src/lib/components/card-data-view/card-data-view-header/card-data-view-header.component.spec.ts +23 -0
  23. package/src/lib/components/card-data-view/card-data-view-header/card-data-view-header.component.ts +10 -0
  24. package/src/lib/components/card-data-view/card-data-view.component.css +39 -0
  25. package/src/lib/components/card-data-view/card-data-view.component.html +29 -0
  26. package/src/lib/components/card-data-view/card-data-view.component.spec.ts +23 -0
  27. package/src/lib/components/card-data-view/card-data-view.component.ts +66 -0
  28. package/src/lib/components/card-data-view/card-data-view.module.ts +20 -0
  29. package/src/lib/components/card-data-view/card-data.ts +7 -0
  30. package/src/lib/components/card-data-view/left-card-data/left-card-data.component.css +15 -0
  31. package/src/lib/components/card-data-view/left-card-data/left-card-data.component.html +4 -0
  32. package/src/lib/components/card-data-view/left-card-data/left-card-data.component.spec.ts +23 -0
  33. package/src/lib/components/card-data-view/left-card-data/left-card-data.component.ts +19 -0
  34. package/src/lib/components/card-data-view/left-card-data-view/left-card-data-view.component.css +0 -0
  35. package/src/lib/components/card-data-view/left-card-data-view/left-card-data-view.component.html +4 -0
  36. package/src/lib/components/card-data-view/left-card-data-view/left-card-data-view.component.spec.ts +23 -0
  37. package/src/lib/components/card-data-view/left-card-data-view/left-card-data-view.component.ts +12 -0
  38. package/src/lib/components/card-data-view/right-card-data-view/right-card-data-view.component.css +3 -0
  39. package/src/lib/components/card-data-view/right-card-data-view/right-card-data-view.component.html +1 -0
  40. package/src/lib/components/card-data-view/right-card-data-view/right-card-data-view.component.spec.ts +23 -0
  41. package/src/lib/components/card-data-view/right-card-data-view/right-card-data-view.component.ts +10 -0
  42. package/src/lib/components/chip/ChipChangeEvent.ts +4 -0
  43. package/src/lib/components/chip/chip.component.css +94 -0
  44. package/src/lib/components/chip/chip.component.html +49 -0
  45. package/src/lib/components/chip/chip.component.spec.ts +23 -0
  46. package/src/lib/components/chip/chip.component.ts +209 -0
  47. package/src/lib/components/chip/chip.module.ts +24 -0
  48. package/src/lib/components/chip/documentation.md +26 -0
  49. package/src/lib/components/data-export/data-export.component.css +0 -0
  50. package/src/lib/components/data-export/data-export.component.html +90 -0
  51. package/src/lib/components/data-export/data-export.component.spec.ts +23 -0
  52. package/src/lib/components/data-export/data-export.component.ts +158 -0
  53. package/src/lib/components/data-export/data-export.module.ts +13 -0
  54. package/src/lib/components/data-export/data-export.service.spec.ts +16 -0
  55. package/src/lib/components/data-export/data-export.service.ts +152 -0
  56. package/src/lib/components/data-export/data-export.types.ts +21 -0
  57. package/src/lib/components/data-table/column.directive.spec.ts +8 -0
  58. package/src/lib/components/data-table/column.directive.ts +19 -0
  59. package/src/lib/components/data-table/data-table.component.css +0 -0
  60. package/src/lib/components/data-table/data-table.component.html +55 -0
  61. package/src/lib/components/data-table/data-table.component.spec.ts +21 -0
  62. package/src/lib/components/data-table/data-table.component.ts +336 -0
  63. package/src/lib/components/data-table/data-table.module.ts +11 -0
  64. package/src/lib/components/data-table/data-table.types.ts +13 -0
  65. package/src/lib/components/data-table/style.types.ts +55 -0
  66. package/src/lib/components/data-view/data-view-click-outside.directive.ts +44 -0
  67. package/src/lib/components/data-view/data-view.component.css +74 -0
  68. package/src/lib/components/data-view/data-view.component.html +161 -0
  69. package/src/lib/components/data-view/data-view.component.spec.ts +23 -0
  70. package/src/lib/components/data-view/data-view.component.ts +136 -0
  71. package/src/lib/components/data-view/data-view.module.ts +16 -0
  72. package/src/lib/components/date-picker/date-picker.component.css +65 -0
  73. package/src/lib/components/date-picker/date-picker.component.html +60 -0
  74. package/src/lib/components/date-picker/date-picker.component.specs.ts +23 -0
  75. package/src/lib/components/date-picker/date-picker.component.ts +143 -0
  76. package/src/lib/components/date-picker/date-picker.module.ts +12 -0
  77. package/src/lib/components/drop-down/DropdownChangeEvent.ts +4 -0
  78. package/src/lib/components/drop-down/DropdownLoadEvent.ts +19 -0
  79. package/src/lib/components/drop-down/DropdownMenuItem.ts +42 -0
  80. package/src/lib/components/drop-down/documentation.md +69 -0
  81. package/src/lib/components/drop-down/drop-down-item/drop-down-item.component.css +123 -0
  82. package/src/lib/components/drop-down/drop-down-item/drop-down-item.component.html +133 -0
  83. package/src/lib/components/drop-down/drop-down-item/drop-down-item.component.spec.ts +23 -0
  84. package/src/lib/components/drop-down/drop-down-item/drop-down-item.component.ts +88 -0
  85. package/src/lib/components/drop-down/drop-down.component.css +317 -0
  86. package/src/lib/components/drop-down/drop-down.component.html +177 -0
  87. package/src/lib/components/drop-down/drop-down.component.spec.ts +23 -0
  88. package/src/lib/components/drop-down/drop-down.component.ts +757 -0
  89. package/src/lib/components/drop-down/drop-down.module.ts +24 -0
  90. package/src/lib/components/image/image.component.css +12 -0
  91. package/src/lib/components/image/image.component.html +18 -0
  92. package/src/lib/components/image/image.component.spec.ts +23 -0
  93. package/src/lib/components/image/image.component.ts +45 -0
  94. package/src/lib/components/image/image.module.ts +11 -0
  95. package/src/lib/components/notification/notification.component.css +3 -0
  96. package/src/lib/components/notification/notification.component.html +19 -0
  97. package/src/lib/components/notification/notification.component.spec.ts +23 -0
  98. package/src/lib/components/notification/notification.component.ts +77 -0
  99. package/src/lib/components/notification/notification.module.ts +14 -0
  100. package/src/lib/components/shared.module.ts +9 -0
  101. package/src/lib/components/sort-table/sort-table.component.css +67 -0
  102. package/src/lib/components/sort-table/sort-table.component.html +164 -0
  103. package/src/lib/components/sort-table/sort-table.component.spec.ts +23 -0
  104. package/src/lib/components/sort-table/sort-table.component.ts +204 -0
  105. package/src/lib/components/sort-table/sort-table.module.ts +11 -0
  106. package/src/lib/components/svg/svg.component.css +0 -0
  107. package/src/lib/components/svg/svg.component.html +1 -0
  108. package/src/lib/components/svg/svg.component.spec.ts +23 -0
  109. package/src/lib/components/svg/svg.component.ts +64 -0
  110. package/src/lib/components/svg/svg.module.ts +10 -0
  111. package/src/lib/components/table-filter/table-filter.component.css +93 -0
  112. package/src/lib/components/table-filter/table-filter.component.html +293 -0
  113. package/src/lib/components/table-filter/table-filter.component.spec.ts +23 -0
  114. package/src/lib/components/table-filter/table-filter.component.ts +221 -0
  115. package/src/lib/components/table-filter/table-filter.module.ts +25 -0
  116. package/src/lib/components/tooltip/tooltip.component.css +8 -0
  117. package/src/lib/components/tooltip/tooltip.component.html +13 -0
  118. package/src/lib/components/tooltip/tooltip.component.spec.ts +23 -0
  119. package/src/lib/components/tooltip/tooltip.component.ts +84 -0
  120. package/src/lib/components/tooltip/tooltip.module.ts +11 -0
  121. package/src/lib/components/verben-mail/verben-mail.component.config.ts +11 -0
  122. package/src/lib/components/verben-mail/verben-mail.component.css +71 -0
  123. package/src/lib/components/verben-mail/verben-mail.component.html +139 -0
  124. package/src/lib/components/verben-mail/verben-mail.component.ts +151 -0
  125. package/src/lib/components/verben-mail/verben-mail.module.ts +18 -0
  126. package/src/lib/components/visible-column/visible-column.component.css +83 -0
  127. package/src/lib/components/visible-column/visible-column.component.html +77 -0
  128. package/src/lib/components/visible-column/visible-column.component.spec.ts +23 -0
  129. package/src/lib/components/visible-column/visible-column.component.ts +106 -0
  130. package/src/lib/components/visible-column/visible-column.module.ts +11 -0
  131. package/src/lib/config.ts +37 -0
  132. package/src/lib/control-options/control-options.directive.ts +129 -0
  133. package/src/lib/control-options/control-options.module.ts +10 -0
  134. package/src/lib/convert-to-integer/convert-to-integer.directive.ts +28 -0
  135. package/src/lib/convert-to-integer/convert-to-integer.module.ts +10 -0
  136. package/src/lib/convert-to-integer/public-api.ts +1 -0
  137. package/src/lib/convert-to-number/convert-to-number.directive.ts +22 -0
  138. package/src/lib/convert-to-number/convert-to-number.module.ts +8 -0
  139. package/src/lib/convert-to-number/public-api.ts +1 -0
  140. package/src/lib/email-validator/email-validator.directive.ts +24 -0
  141. package/src/lib/email-validator/email-validator.module.ts +14 -0
  142. package/src/lib/models/column-filter.ts +5 -0
  143. package/src/lib/models/data-filter.ts +8 -0
  144. package/src/lib/models/mail-model.ts +8 -0
  145. package/src/lib/models/sort-filter.ts +0 -0
  146. package/src/lib/models/table-filter.ts +34 -0
  147. package/src/lib/number-range/number-range.directive.ts +35 -0
  148. package/src/lib/number-range/number-range.module.ts +11 -0
  149. package/src/lib/phone-number/phone-number.directive.ts +22 -0
  150. package/src/lib/phone-number/phone-number.module.ts +10 -0
  151. package/src/lib/phone-number/public-api.ts +1 -0
  152. package/src/lib/required-input/required-input.directive.ts +18 -0
  153. package/src/lib/required-input/required-input.module.ts +8 -0
  154. package/src/lib/theme-switcher/theme-switcher.directive.spec.ts +8 -0
  155. package/src/lib/theme-switcher/theme-switcher.directive.ts +70 -0
  156. package/src/lib/theme-switcher/theme-switcher.module.ts +8 -0
  157. package/src/lib/validate/error-message.service.ts +104 -0
  158. package/src/lib/validate/validate.directive.ts +110 -0
  159. package/src/lib/validate/validate.module.ts +17 -0
  160. package/src/lib/validate-input/validate-input.directive.ts +8 -0
  161. package/src/lib/validate-input/validate-input.module.ts +8 -0
  162. package/src/lib/verben-ng-ui.component.spec.ts +23 -0
  163. package/src/lib/verben-ng-ui.component.ts +16 -0
  164. package/src/lib/verben-ng-ui.service.spec.ts +16 -0
  165. package/src/lib/verben-ng-ui.service.ts +9 -0
  166. package/src/lib/verbena-badge/verbena-badge.component.css +16 -0
  167. package/src/lib/verbena-badge/verbena-badge.component.html +13 -0
  168. package/src/lib/verbena-badge/verbena-badge.component.spec.ts +25 -0
  169. package/src/lib/verbena-badge/verbena-badge.component.ts +18 -0
  170. package/src/lib/verbena-badge/verbena-badge.module.ts +10 -0
  171. package/src/lib/verbena-button/verbena-button.component.css +20 -0
  172. package/src/lib/verbena-button/verbena-button.component.html +25 -0
  173. package/src/lib/verbena-button/verbena-button.component.spec.ts +25 -0
  174. package/src/lib/verbena-button/verbena-button.component.ts +92 -0
  175. package/src/lib/verbena-button/verbena-button.module.ts +11 -0
  176. package/src/lib/verbena-switch/verbena-switch.component.css +45 -0
  177. package/src/lib/verbena-switch/verbena-switch.component.html +8 -0
  178. package/src/lib/verbena-switch/verbena-switch.component.spec.ts +25 -0
  179. package/src/lib/verbena-switch/verbena-switch.component.ts +31 -0
  180. package/src/lib/verbena-switch/verbena-switch.module.ts +10 -0
  181. package/src/lib/verbena-textarea/verbena-textarea.component.css +0 -0
  182. package/src/lib/verbena-textarea/verbena-textarea.component.html +19 -0
  183. package/src/lib/verbena-textarea/verbena-textarea.component.spec.ts +33 -0
  184. package/src/lib/verbena-textarea/verbena-textarea.component.ts +44 -0
  185. package/src/lib/verbena-textarea/verbena-textarea.module.ts +11 -0
  186. package/src/public-api.ts +122 -0
  187. package/src/styles.css +103 -0
  188. package/tsconfig.lib.json +15 -0
  189. package/tsconfig.lib.prod.json +11 -0
  190. package/tsconfig.spec.json +15 -0
package/README.md ADDED
@@ -0,0 +1,24 @@
1
+ # VerbenNgUi
2
+
3
+ This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 18.2.0.
4
+
5
+ ## Code scaffolding
6
+
7
+ Run `ng generate component component-name --project verben-ng-ui` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project verben-ng-ui`.
8
+ > Note: Don't forget to add `--project verben-ng-ui` or else it will be added to the default project in your `angular.json` file.
9
+
10
+ ## Build
11
+
12
+ Run `ng build verben-ng-ui` to build the project. The build artifacts will be stored in the `dist/` directory.
13
+
14
+ ## Publishing
15
+
16
+ After building your library with `ng build verben-ng-ui`, go to the dist folder `cd dist/verben-ng-ui` and run `npm publish`.
17
+
18
+ ## Running unit tests
19
+
20
+ Run `ng test verben-ng-ui` to execute the unit tests via [Karma](https://karma-runner.github.io).
21
+
22
+ ## Further help
23
+
24
+ To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
@@ -0,0 +1,10 @@
1
+ {
2
+ "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3
+ "dest": "../../dist/verben-ng-ui",
4
+ "lib": {
5
+ "entryFile": "src/public-api.ts"
6
+ },
7
+ "allowedNonPeerDependencies": [
8
+ "lodash"
9
+ ]
10
+ }
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "verben-ng-ui",
3
+ "version": "0.0.1",
4
+ "author": "Verbena Logic",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/verbena-engineering/verben-ng-ui-app"
8
+ },
9
+ "bugs": {
10
+ "url": "https://github.com/verbena-engineering/verben-ng-ui-app/issues"
11
+ },
12
+ "homepage": "",
13
+ "keywords": [
14
+ "angular",
15
+ "javascript",
16
+ "typescript"
17
+ ],
18
+ "scripts": {
19
+ "build-watch": "ng build --watch"
20
+ },
21
+ "peerDependencies": {
22
+ "@angular/common": "^14.0.0 || ^18.0.0",
23
+ "@angular/core": "^14.0.0 || ^18.0.0"
24
+ },
25
+ "dependencies": {
26
+ "lodash": "^4.17.21",
27
+ "tslib": "^2.3.0"
28
+ },
29
+ "sideEffects": false,
30
+ "devDependencies": {
31
+ "@types/lodash": "^4.17.10",
32
+ "autoprefixer": "^10.4.20"
33
+ }
34
+ }
@@ -0,0 +1,23 @@
1
+ import { Injectable } from '@angular/core';
2
+
3
+ @Injectable({
4
+ providedIn: 'root'
5
+ })
6
+ export class ErrorService {
7
+ getErrorMessage(type: string, label: string, minMaxValue?: number): string {
8
+ switch (type) {
9
+ case 'required':
10
+ return `${label} is required.`;
11
+ case 'invalidNumber':
12
+ return `${label} must be a valid number.`;
13
+ case 'invalidInteger':
14
+ return `${label} must be an integer.`;
15
+ case 'minLength':
16
+ return `${label} must be at least ${minMaxValue} characters long.`;
17
+ case 'maxLength':
18
+ return `${label} cannot exceed ${minMaxValue} characters.`;
19
+ default:
20
+ return 'Invalid input.';
21
+ }
22
+ }
23
+ }
@@ -0,0 +1,59 @@
1
+ .input-container {
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: 5px;
5
+ position: relative; /* Needed for positioning elements */
6
+ }
7
+
8
+ .input-field {
9
+ width: 100%;
10
+ padding: 6px;
11
+ }
12
+
13
+ .error-message {
14
+ font-size: 12px;
15
+ margin: 0;
16
+ }
17
+
18
+ .error-top {
19
+ position: absolute;
20
+ top: 0;
21
+ left: 50%;
22
+ }
23
+
24
+ .error-bottom {
25
+ position: relative;
26
+ margin-top: 5px;
27
+ }
28
+
29
+ .error-left {
30
+ position: absolute;
31
+ left: -10px;
32
+ }
33
+
34
+ .error-right {
35
+ position: absolute;
36
+ right: -10px;
37
+ top: 0px;
38
+ }
39
+
40
+ .input-wrapper {
41
+ position: relative;
42
+ }
43
+
44
+ .input-field {
45
+ width: 100%;
46
+ padding: 8px;
47
+ }
48
+
49
+ .error-dot {
50
+ position: absolute;
51
+ top: 0%;
52
+ right: -10px;
53
+ transform: translateY(-50%);
54
+ width: 8px;
55
+ height: 8px;
56
+ border-radius: 50%;
57
+ cursor: pointer;
58
+ }
59
+
@@ -0,0 +1,64 @@
1
+ <div class="input-container"
2
+ [ngStyle]="{
3
+ 'display': 'flex',
4
+ 'flex-direction': 'column',
5
+
6
+ }"
7
+ >
8
+ <div
9
+ [ngStyle]="{
10
+ 'display': 'flex',
11
+ 'justify-content': labelPosition,
12
+ 'color': labelColor,
13
+ 'padding': '0'
14
+ }"
15
+ class="input-field"
16
+ >
17
+ <label [for]="label">{{ label }}</label>
18
+ </div>
19
+
20
+ <div class="input-wrapper">
21
+ <input
22
+ [id]="label"
23
+ [attr.type]="type"
24
+ [attr.placeholder]="placeHolder"
25
+ [required]="required"
26
+ [attr.minlength]="minLength?.toString()"
27
+ [attr.maxlength]="maxLength?.toString()"
28
+ (input)="onInput($event)"
29
+ [(ngModel)]="value"
30
+ [ngStyle]="{
31
+ 'background-color': bgColor,
32
+ 'border': showBorder ? (errorMessage ? '1px solid ' + errorBorderColor : border) : 'none',
33
+ 'border-radius': borderRadius,
34
+ 'color': textColor
35
+ }"
36
+ class="input-field"
37
+ />
38
+
39
+ <!-- Conditional red dot for error when showErrorMessage is false -->
40
+ <verben-tooltip *ngIf="errorMessage && !showErrorMessage"
41
+ [tooltipContent]="tooltipTemplate"
42
+ customClass="error-tooltip">
43
+ <div class="error-dot"
44
+ [ngStyle]="{ 'background-color': errorBorderColor }">
45
+ </div>
46
+ </verben-tooltip>
47
+
48
+ <!-- Tooltip template for error message -->
49
+ <ng-template #tooltipTemplate>
50
+ {{ errorMessage }}
51
+ </ng-template>
52
+
53
+ <!-- Conditional error message display -->
54
+ <span *ngIf="errorMessage && showErrorMessage"
55
+ [ngStyle]="{ 'color': errorMessageColor }"
56
+ [ngClass]="{'error-message': true,
57
+ 'error-top': errorPosition === 'top',
58
+ 'error-bottom': errorPosition === 'bottom',
59
+ 'error-left': errorPosition === 'left',
60
+ 'error-right': errorPosition === 'right'}">
61
+ {{ errorMessage }}
62
+ </span>
63
+ </div>
64
+ </div>
@@ -0,0 +1,25 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { VerbenaInputComponent } from './verbena-input.component';
3
+ import { FormsModule } from '@angular/forms';
4
+
5
+ describe('VerbenaInputComponent', () => {
6
+ let component: VerbenaInputComponent;
7
+ let fixture: ComponentFixture<VerbenaInputComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ declarations: [VerbenaInputComponent],
12
+ imports: [FormsModule]
13
+ }).compileComponents();
14
+ });
15
+
16
+ beforeEach(() => {
17
+ fixture = TestBed.createComponent(VerbenaInputComponent);
18
+ component = fixture.componentInstance;
19
+ fixture.detectChanges();
20
+ });
21
+
22
+ it('should create', () => {
23
+ expect(component).toBeTruthy();
24
+ });
25
+ });
@@ -0,0 +1,162 @@
1
+ import { Component, Input, Output, EventEmitter, OnInit, forwardRef } from '@angular/core';
2
+ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
3
+
4
+ @Component({
5
+ selector: 'verbena-input',
6
+ templateUrl: './verbena-input.component.html',
7
+ styleUrls: ['./verbena-input.component.css'],
8
+ providers: [
9
+ {
10
+ provide: NG_VALUE_ACCESSOR,
11
+ useExisting: forwardRef(() => VerbenaInputComponent),
12
+ multi: true
13
+ }
14
+ ]
15
+ })
16
+ export class VerbenaInputComponent implements ControlValueAccessor, OnInit {
17
+ @Input() label: string = '';
18
+ @Input() placeHolder: string = '';
19
+ @Input() required: boolean = false;
20
+ @Input() minLength?: number;
21
+ @Input() maxLength?: number;
22
+ @Input() type: 'text' | 'integer' | 'number' | 'decimal' | 'email' | 'date' = 'text';
23
+ @Input() bgColor: string = '#f9f9f9';
24
+ @Input() border: string = '1px solid #ccc';
25
+ @Input() borderRadius: string = '5px';
26
+ @Input() textColor: string = '#333';
27
+ @Input() value: string = '';
28
+ @Input() labelPosition: string = 'start';
29
+ @Input() labelColor: string = 'black';
30
+ @Input() disable: boolean = false;
31
+ @Input() min?: number;
32
+ @Input() max?: number;
33
+
34
+ @Input() showBorder: boolean = true;
35
+ @Input() showErrorMessage: boolean = true;
36
+ @Input() errorMessageColor: string = 'red';
37
+ @Input() errorBorderColor: string = 'red';
38
+ @Input() errorPosition: 'left' | 'right' | 'top' | 'bottom' = 'bottom';
39
+
40
+ @Input() capitalization: 'none' | 'uppercase' | 'lowercase' | 'sentencecase' | 'pascalcase' | 'camelcase' = 'none';
41
+
42
+ // New property for custom error messages
43
+ @Input() customErrorMessages: {
44
+ required?: string;
45
+ minLength?: string;
46
+ maxLength?: string;
47
+ minValue?: string;
48
+ maxValue?: string;
49
+ integer?: string;
50
+ number?: string;
51
+ decimal?: string;
52
+ email?: string;
53
+ } = {};
54
+
55
+ @Output() valueChange = new EventEmitter<string>();
56
+
57
+ errorMessage: string | undefined;
58
+ inputId: string = '';
59
+
60
+ onChange: any = () => {};
61
+ onTouch: any = () => {};
62
+
63
+ ngOnInit() {
64
+ this.inputId = `verbena-input-${Math.random().toString(36).substr(2, 9)}`;
65
+ }
66
+
67
+ onInput(event: Event) {
68
+ const target = event.target as HTMLInputElement;
69
+ this.value = target.value.trim();
70
+ this.value = this.applyCapitalization(this.value, this.capitalization);
71
+ this.validate();
72
+ const sanitizedValue = this.sanitizeValue(this.value);
73
+ this.onChange(sanitizedValue);
74
+ this.valueChange.emit(sanitizedValue);
75
+ }
76
+
77
+ applyCapitalization(value: string, format: string): string {
78
+ switch (format) {
79
+ case 'uppercase': return value.toUpperCase();
80
+ case 'lowercase': return value.toLowerCase();
81
+ case 'sentencecase': return value.charAt(0).toUpperCase() + value.slice(1).toLowerCase();
82
+ case 'pascalcase': return value.replace(/\w+/g, (w) => w[0].toUpperCase() + w.slice(1).toLowerCase());
83
+ case 'camelcase': return value.replace(/(?:^\w|[A-Z]|\b\w|\s+)/g, (match, index) =>
84
+ index === 0 ? match.toLowerCase() : match.toUpperCase()).replace(/\s+/g, '');
85
+ default: return value;
86
+ }
87
+ }
88
+
89
+ sanitizeValue(value: string): string {
90
+ if (['number', 'decimal', 'integer'].includes(this.type)) {
91
+ return value.replace(/,/g, '');
92
+ }
93
+ return value;
94
+ }
95
+
96
+ validate() {
97
+ this.errorMessage = '';
98
+
99
+ if (this.required && !this.value) {
100
+ this.errorMessage = this.customErrorMessages.required || 'This field is required.';
101
+ return;
102
+ }
103
+
104
+ if (this.minLength && this.value.length < this.minLength) {
105
+ this.errorMessage = this.customErrorMessages.minLength || `Minimum length is ${this.minLength}.`;
106
+ return;
107
+ }
108
+
109
+ if (this.maxLength && this.value.length > this.maxLength) {
110
+ this.errorMessage = this.customErrorMessages.maxLength || `Maximum length is ${this.maxLength}.`;
111
+ return;
112
+ }
113
+
114
+ const sanitizedValue = this.sanitizeValue(this.value);
115
+ const numericValue = parseFloat(sanitizedValue);
116
+
117
+ if (['integer', 'number', 'decimal'].includes(this.type)) {
118
+ if (this.min !== undefined && numericValue < this.min) {
119
+ this.errorMessage = this.customErrorMessages.minValue || `Minimum value is ${this.min}.`;
120
+ return;
121
+ } else if (this.max !== undefined && numericValue > this.max) {
122
+ this.errorMessage = this.customErrorMessages.maxValue || `Maximum value is ${this.max}.`;
123
+ return;
124
+ }
125
+ }
126
+
127
+ if (this.type === 'integer' && !/^\d+$/.test(this.value)) {
128
+ this.errorMessage = this.customErrorMessages.integer || 'Please enter a valid integer.';
129
+ return;
130
+ }
131
+
132
+ if (this.type === 'number' && !/^\d+(\.\d+)?$/.test(this.value)) {
133
+ this.errorMessage = this.customErrorMessages.number || 'Please enter a valid number.';
134
+ return;
135
+ }
136
+
137
+ if (this.type === 'decimal' && !/^\d+(\.\d+)?$/.test(this.value)) {
138
+ this.errorMessage = this.customErrorMessages.decimal || 'Please enter a valid decimal.';
139
+ return;
140
+ }
141
+
142
+ if (this.type === 'email' && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(this.value)) {
143
+ this.errorMessage = this.customErrorMessages.email || 'Please enter a valid email address.';
144
+ }
145
+ }
146
+
147
+ writeValue(value: any): void {
148
+ this.value = value ? this.applyCapitalization(value.trim(), this.capitalization) : '';
149
+ }
150
+
151
+ registerOnChange(fn: any): void {
152
+ this.onChange = fn;
153
+ }
154
+
155
+ registerOnTouched(fn: any): void {
156
+ this.onTouch = fn;
157
+ }
158
+
159
+ setDisabledState(isDisabled: boolean): void {
160
+ this.disable = isDisabled;
161
+ }
162
+ }
@@ -0,0 +1,12 @@
1
+ import { NgModule } from '@angular/core';
2
+ import { FormsModule } from '@angular/forms';
3
+ import { CommonModule } from '@angular/common';
4
+ import { TooltipModule } from '../components/tooltip/tooltip.module';
5
+ import { VerbenaInputComponent } from './verbena-input.component';
6
+
7
+ @NgModule({
8
+ declarations: [VerbenaInputComponent],
9
+ imports: [CommonModule, FormsModule, TooltipModule],
10
+ exports: [VerbenaInputComponent],
11
+ })
12
+ export class VerbenaInputModule {}
@@ -0,0 +1,10 @@
1
+ import { Directive, Input, TemplateRef } from '@angular/core';
2
+
3
+ @Directive({
4
+ selector: '[vTemplate]',
5
+ })
6
+ export class TemplateDirective {
7
+ @Input() vTemplate!: string; // The name of the template
8
+
9
+ constructor(public template: TemplateRef<any>) {}
10
+ }
@@ -0,0 +1,20 @@
1
+ .card {
2
+ border: 1px solid #ddd;
3
+ border-radius: 4px;
4
+ overflow: hidden;
5
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
6
+ }
7
+ .card-header {
8
+ background-color: #f8f9fa;
9
+ padding: 10px 15px;
10
+ border-bottom: 1px solid #ddd;
11
+ }
12
+ .card-body {
13
+ padding: 15px;
14
+ }
15
+ .card-footer {
16
+ background-color: #f8f9fa;
17
+ padding: 10px 15px;
18
+ border-top: 1px solid #ddd;
19
+ }
20
+
@@ -0,0 +1,23 @@
1
+ <div class="card"
2
+ [style.background-color]="bgColor"
3
+ [style.margin]="mg"
4
+ [style.border]="border"
5
+ [style.border-radius]="borderRadius"
6
+ [style.color]="textColor"
7
+ [style.width]="width"
8
+ [style.height]="height"
9
+ [ngClass]="disabled?'disable':''"
10
+ [style.aspect-ratio]="aspectRatio"
11
+ [style.padding]="pd"
12
+ >
13
+ <div class="card-header" *ngIf="hasHeader">
14
+ <ng-content select="[card-header]"></ng-content>
15
+ </div>
16
+ <div class="card-body" *ngIf="hasBody">
17
+ <ng-content select="[card-body]"></ng-content>
18
+ </div>
19
+ <div class="card-footer" *ngIf="hasFooter">
20
+ <ng-content select="[card-footer]"></ng-content>
21
+ </div>
22
+ </div>
23
+
@@ -0,0 +1,23 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { CardComponent } from './card.component';
4
+
5
+ describe('CardComponent', () => {
6
+ let component: CardComponent;
7
+ let fixture: ComponentFixture<CardComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [CardComponent]
12
+ })
13
+ .compileComponents();
14
+
15
+ fixture = TestBed.createComponent(CardComponent);
16
+ component = fixture.componentInstance;
17
+ fixture.detectChanges();
18
+ });
19
+
20
+ it('should create', () => {
21
+ expect(component).toBeTruthy();
22
+ });
23
+ });
@@ -0,0 +1,33 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { Component, ContentChild, ElementRef, AfterContentInit, Input } from '@angular/core';
3
+
4
+ @Component({
5
+ selector: 'verben-card',
6
+ templateUrl: './card.component.html',
7
+ styleUrls: ['./card.component.css']
8
+ })
9
+
10
+ export class CardComponent implements AfterContentInit {
11
+ hasHeader = false;
12
+ hasFooter = false;
13
+ hasBody = false;
14
+ @Input() pd = '10px';
15
+ @Input() mg = '0px';
16
+ @Input() height?:string ;
17
+ @Input() width?:string ;
18
+ @Input() textColor?:string ;
19
+ @Input() bgColor?:string ;
20
+ @Input() border?:string ;
21
+ @Input() borderRadius?:string ;
22
+ @Input() disabled:boolean=false ;
23
+ @Input() aspectRatio?:number ;
24
+ @ContentChild('card-header', { static: false }) cardHeader: ElementRef | undefined;
25
+ @ContentChild('card-body', { static: false }) cardBody: ElementRef | undefined;
26
+ @ContentChild('card-footer', { static: false }) cardFooter: ElementRef | undefined;
27
+
28
+ ngAfterContentInit() {
29
+ this.hasHeader = !this.cardHeader;
30
+ this.hasBody = !this.cardBody;
31
+ this.hasFooter = !this.cardFooter;
32
+ }
33
+ }
@@ -0,0 +1,10 @@
1
+ import { NgModule } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { CardComponent } from './card.component';
4
+
5
+ @NgModule({
6
+ declarations:[CardComponent],
7
+ imports: [ CommonModule],
8
+ exports: [CardComponent]
9
+ })
10
+ export class CardModule {}
@@ -0,0 +1,23 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { CardDataViewFooterComponent } from './card-data-view-footer.component';
4
+
5
+ describe('CardDataViewFooterComponent', () => {
6
+ let component: CardDataViewFooterComponent;
7
+ let fixture: ComponentFixture<CardDataViewFooterComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [CardDataViewFooterComponent]
12
+ })
13
+ .compileComponents();
14
+
15
+ fixture = TestBed.createComponent(CardDataViewFooterComponent);
16
+ component = fixture.componentInstance;
17
+ fixture.detectChanges();
18
+ });
19
+
20
+ it('should create', () => {
21
+ expect(component).toBeTruthy();
22
+ });
23
+ });
@@ -0,0 +1,10 @@
1
+ import { Component } from '@angular/core';
2
+
3
+ @Component({
4
+ selector: 'verben-card-data-view-footer',
5
+ templateUrl: './card-data-view-footer.component.html',
6
+ styleUrl: './card-data-view-footer.component.css'
7
+ })
8
+ export class CardDataViewFooterComponent {
9
+
10
+ }
@@ -0,0 +1,7 @@
1
+ :host{
2
+ padding: 15px;
3
+ position: absolute;
4
+ top: 0;
5
+ width: 100%;
6
+
7
+ }
@@ -0,0 +1,23 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { CardDataViewHeaderComponent } from './card-data-view-header.component';
4
+
5
+ describe('CardDataViewHeaderComponent', () => {
6
+ let component: CardDataViewHeaderComponent;
7
+ let fixture: ComponentFixture<CardDataViewHeaderComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [CardDataViewHeaderComponent]
12
+ })
13
+ .compileComponents();
14
+
15
+ fixture = TestBed.createComponent(CardDataViewHeaderComponent);
16
+ component = fixture.componentInstance;
17
+ fixture.detectChanges();
18
+ });
19
+
20
+ it('should create', () => {
21
+ expect(component).toBeTruthy();
22
+ });
23
+ });
@@ -0,0 +1,10 @@
1
+ import { Component } from '@angular/core';
2
+
3
+ @Component({
4
+ selector: 'verben-card-data-view-header',
5
+ templateUrl: './card-data-view-header.component.html',
6
+ styleUrl: './card-data-view-header.component.css'
7
+ })
8
+ export class CardDataViewHeaderComponent {
9
+
10
+ }
@@ -0,0 +1,39 @@
1
+ .container
2
+ {
3
+ gap: 10px;
4
+ min-height: 100vh;
5
+ }
6
+ :host{
7
+ border-radius: 12px;
8
+ }
9
+ .master-detail-container
10
+ {
11
+ display: grid;
12
+ grid-template-columns: 30% 70%;
13
+ gap:15px;
14
+ justify-content: center;
15
+ margin-top: 20px;
16
+ }
17
+ .master-only-container
18
+ {
19
+ display: grid;
20
+ grid-template-columns: 100%;
21
+ justify-content: center;
22
+ margin-top: 20px;
23
+
24
+ }
25
+
26
+ .paginator-text
27
+ {
28
+ margin-left: auto;
29
+ margin-right: auto;
30
+ }
31
+ .cursor-pointer
32
+ {
33
+ cursor: pointer;
34
+ }
35
+ .toRight
36
+ {
37
+ float:right;
38
+ margin: 5px 10px 0px 0px;
39
+ }