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.
- package/README.md +24 -0
- package/ng-package.json +10 -0
- package/package.json +34 -0
- package/src/lib/Verbena-input/error.service.ts +23 -0
- package/src/lib/Verbena-input/verbena-input.component.css +59 -0
- package/src/lib/Verbena-input/verbena-input.component.html +64 -0
- package/src/lib/Verbena-input/verbena-input.component.spec.ts +25 -0
- package/src/lib/Verbena-input/verbena-input.component.ts +162 -0
- package/src/lib/Verbena-input/verbena-input.module.ts +12 -0
- package/src/lib/components/TemplateDirective.directive.ts +10 -0
- package/src/lib/components/card/card.component.css +20 -0
- package/src/lib/components/card/card.component.html +23 -0
- package/src/lib/components/card/card.component.spec.ts +23 -0
- package/src/lib/components/card/card.component.ts +33 -0
- package/src/lib/components/card/card.module.ts +10 -0
- package/src/lib/components/card-data-view/card-data-view-footer/card-data-view-footer.component.css +3 -0
- package/src/lib/components/card-data-view/card-data-view-footer/card-data-view-footer.component.html +1 -0
- package/src/lib/components/card-data-view/card-data-view-footer/card-data-view-footer.component.spec.ts +23 -0
- package/src/lib/components/card-data-view/card-data-view-footer/card-data-view-footer.component.ts +10 -0
- package/src/lib/components/card-data-view/card-data-view-header/card-data-view-header.component.css +7 -0
- package/src/lib/components/card-data-view/card-data-view-header/card-data-view-header.component.html +1 -0
- package/src/lib/components/card-data-view/card-data-view-header/card-data-view-header.component.spec.ts +23 -0
- package/src/lib/components/card-data-view/card-data-view-header/card-data-view-header.component.ts +10 -0
- package/src/lib/components/card-data-view/card-data-view.component.css +39 -0
- package/src/lib/components/card-data-view/card-data-view.component.html +29 -0
- package/src/lib/components/card-data-view/card-data-view.component.spec.ts +23 -0
- package/src/lib/components/card-data-view/card-data-view.component.ts +66 -0
- package/src/lib/components/card-data-view/card-data-view.module.ts +20 -0
- package/src/lib/components/card-data-view/card-data.ts +7 -0
- package/src/lib/components/card-data-view/left-card-data/left-card-data.component.css +15 -0
- package/src/lib/components/card-data-view/left-card-data/left-card-data.component.html +4 -0
- package/src/lib/components/card-data-view/left-card-data/left-card-data.component.spec.ts +23 -0
- package/src/lib/components/card-data-view/left-card-data/left-card-data.component.ts +19 -0
- package/src/lib/components/card-data-view/left-card-data-view/left-card-data-view.component.css +0 -0
- package/src/lib/components/card-data-view/left-card-data-view/left-card-data-view.component.html +4 -0
- package/src/lib/components/card-data-view/left-card-data-view/left-card-data-view.component.spec.ts +23 -0
- package/src/lib/components/card-data-view/left-card-data-view/left-card-data-view.component.ts +12 -0
- package/src/lib/components/card-data-view/right-card-data-view/right-card-data-view.component.css +3 -0
- package/src/lib/components/card-data-view/right-card-data-view/right-card-data-view.component.html +1 -0
- package/src/lib/components/card-data-view/right-card-data-view/right-card-data-view.component.spec.ts +23 -0
- package/src/lib/components/card-data-view/right-card-data-view/right-card-data-view.component.ts +10 -0
- package/src/lib/components/chip/ChipChangeEvent.ts +4 -0
- package/src/lib/components/chip/chip.component.css +94 -0
- package/src/lib/components/chip/chip.component.html +49 -0
- package/src/lib/components/chip/chip.component.spec.ts +23 -0
- package/src/lib/components/chip/chip.component.ts +209 -0
- package/src/lib/components/chip/chip.module.ts +24 -0
- package/src/lib/components/chip/documentation.md +26 -0
- package/src/lib/components/data-export/data-export.component.css +0 -0
- package/src/lib/components/data-export/data-export.component.html +90 -0
- package/src/lib/components/data-export/data-export.component.spec.ts +23 -0
- package/src/lib/components/data-export/data-export.component.ts +158 -0
- package/src/lib/components/data-export/data-export.module.ts +13 -0
- package/src/lib/components/data-export/data-export.service.spec.ts +16 -0
- package/src/lib/components/data-export/data-export.service.ts +152 -0
- package/src/lib/components/data-export/data-export.types.ts +21 -0
- package/src/lib/components/data-table/column.directive.spec.ts +8 -0
- package/src/lib/components/data-table/column.directive.ts +19 -0
- package/src/lib/components/data-table/data-table.component.css +0 -0
- package/src/lib/components/data-table/data-table.component.html +55 -0
- package/src/lib/components/data-table/data-table.component.spec.ts +21 -0
- package/src/lib/components/data-table/data-table.component.ts +336 -0
- package/src/lib/components/data-table/data-table.module.ts +11 -0
- package/src/lib/components/data-table/data-table.types.ts +13 -0
- package/src/lib/components/data-table/style.types.ts +55 -0
- package/src/lib/components/data-view/data-view-click-outside.directive.ts +44 -0
- package/src/lib/components/data-view/data-view.component.css +74 -0
- package/src/lib/components/data-view/data-view.component.html +161 -0
- package/src/lib/components/data-view/data-view.component.spec.ts +23 -0
- package/src/lib/components/data-view/data-view.component.ts +136 -0
- package/src/lib/components/data-view/data-view.module.ts +16 -0
- package/src/lib/components/date-picker/date-picker.component.css +65 -0
- package/src/lib/components/date-picker/date-picker.component.html +60 -0
- package/src/lib/components/date-picker/date-picker.component.specs.ts +23 -0
- package/src/lib/components/date-picker/date-picker.component.ts +143 -0
- package/src/lib/components/date-picker/date-picker.module.ts +12 -0
- package/src/lib/components/drop-down/DropdownChangeEvent.ts +4 -0
- package/src/lib/components/drop-down/DropdownLoadEvent.ts +19 -0
- package/src/lib/components/drop-down/DropdownMenuItem.ts +42 -0
- package/src/lib/components/drop-down/documentation.md +69 -0
- package/src/lib/components/drop-down/drop-down-item/drop-down-item.component.css +123 -0
- package/src/lib/components/drop-down/drop-down-item/drop-down-item.component.html +133 -0
- package/src/lib/components/drop-down/drop-down-item/drop-down-item.component.spec.ts +23 -0
- package/src/lib/components/drop-down/drop-down-item/drop-down-item.component.ts +88 -0
- package/src/lib/components/drop-down/drop-down.component.css +317 -0
- package/src/lib/components/drop-down/drop-down.component.html +177 -0
- package/src/lib/components/drop-down/drop-down.component.spec.ts +23 -0
- package/src/lib/components/drop-down/drop-down.component.ts +757 -0
- package/src/lib/components/drop-down/drop-down.module.ts +24 -0
- package/src/lib/components/image/image.component.css +12 -0
- package/src/lib/components/image/image.component.html +18 -0
- package/src/lib/components/image/image.component.spec.ts +23 -0
- package/src/lib/components/image/image.component.ts +45 -0
- package/src/lib/components/image/image.module.ts +11 -0
- package/src/lib/components/notification/notification.component.css +3 -0
- package/src/lib/components/notification/notification.component.html +19 -0
- package/src/lib/components/notification/notification.component.spec.ts +23 -0
- package/src/lib/components/notification/notification.component.ts +77 -0
- package/src/lib/components/notification/notification.module.ts +14 -0
- package/src/lib/components/shared.module.ts +9 -0
- package/src/lib/components/sort-table/sort-table.component.css +67 -0
- package/src/lib/components/sort-table/sort-table.component.html +164 -0
- package/src/lib/components/sort-table/sort-table.component.spec.ts +23 -0
- package/src/lib/components/sort-table/sort-table.component.ts +204 -0
- package/src/lib/components/sort-table/sort-table.module.ts +11 -0
- package/src/lib/components/svg/svg.component.css +0 -0
- package/src/lib/components/svg/svg.component.html +1 -0
- package/src/lib/components/svg/svg.component.spec.ts +23 -0
- package/src/lib/components/svg/svg.component.ts +64 -0
- package/src/lib/components/svg/svg.module.ts +10 -0
- package/src/lib/components/table-filter/table-filter.component.css +93 -0
- package/src/lib/components/table-filter/table-filter.component.html +293 -0
- package/src/lib/components/table-filter/table-filter.component.spec.ts +23 -0
- package/src/lib/components/table-filter/table-filter.component.ts +221 -0
- package/src/lib/components/table-filter/table-filter.module.ts +25 -0
- package/src/lib/components/tooltip/tooltip.component.css +8 -0
- package/src/lib/components/tooltip/tooltip.component.html +13 -0
- package/src/lib/components/tooltip/tooltip.component.spec.ts +23 -0
- package/src/lib/components/tooltip/tooltip.component.ts +84 -0
- package/src/lib/components/tooltip/tooltip.module.ts +11 -0
- package/src/lib/components/verben-mail/verben-mail.component.config.ts +11 -0
- package/src/lib/components/verben-mail/verben-mail.component.css +71 -0
- package/src/lib/components/verben-mail/verben-mail.component.html +139 -0
- package/src/lib/components/verben-mail/verben-mail.component.ts +151 -0
- package/src/lib/components/verben-mail/verben-mail.module.ts +18 -0
- package/src/lib/components/visible-column/visible-column.component.css +83 -0
- package/src/lib/components/visible-column/visible-column.component.html +77 -0
- package/src/lib/components/visible-column/visible-column.component.spec.ts +23 -0
- package/src/lib/components/visible-column/visible-column.component.ts +106 -0
- package/src/lib/components/visible-column/visible-column.module.ts +11 -0
- package/src/lib/config.ts +37 -0
- package/src/lib/control-options/control-options.directive.ts +129 -0
- package/src/lib/control-options/control-options.module.ts +10 -0
- package/src/lib/convert-to-integer/convert-to-integer.directive.ts +28 -0
- package/src/lib/convert-to-integer/convert-to-integer.module.ts +10 -0
- package/src/lib/convert-to-integer/public-api.ts +1 -0
- package/src/lib/convert-to-number/convert-to-number.directive.ts +22 -0
- package/src/lib/convert-to-number/convert-to-number.module.ts +8 -0
- package/src/lib/convert-to-number/public-api.ts +1 -0
- package/src/lib/email-validator/email-validator.directive.ts +24 -0
- package/src/lib/email-validator/email-validator.module.ts +14 -0
- package/src/lib/models/column-filter.ts +5 -0
- package/src/lib/models/data-filter.ts +8 -0
- package/src/lib/models/mail-model.ts +8 -0
- package/src/lib/models/sort-filter.ts +0 -0
- package/src/lib/models/table-filter.ts +34 -0
- package/src/lib/number-range/number-range.directive.ts +35 -0
- package/src/lib/number-range/number-range.module.ts +11 -0
- package/src/lib/phone-number/phone-number.directive.ts +22 -0
- package/src/lib/phone-number/phone-number.module.ts +10 -0
- package/src/lib/phone-number/public-api.ts +1 -0
- package/src/lib/required-input/required-input.directive.ts +18 -0
- package/src/lib/required-input/required-input.module.ts +8 -0
- package/src/lib/theme-switcher/theme-switcher.directive.spec.ts +8 -0
- package/src/lib/theme-switcher/theme-switcher.directive.ts +70 -0
- package/src/lib/theme-switcher/theme-switcher.module.ts +8 -0
- package/src/lib/validate/error-message.service.ts +104 -0
- package/src/lib/validate/validate.directive.ts +110 -0
- package/src/lib/validate/validate.module.ts +17 -0
- package/src/lib/validate-input/validate-input.directive.ts +8 -0
- package/src/lib/validate-input/validate-input.module.ts +8 -0
- package/src/lib/verben-ng-ui.component.spec.ts +23 -0
- package/src/lib/verben-ng-ui.component.ts +16 -0
- package/src/lib/verben-ng-ui.service.spec.ts +16 -0
- package/src/lib/verben-ng-ui.service.ts +9 -0
- package/src/lib/verbena-badge/verbena-badge.component.css +16 -0
- package/src/lib/verbena-badge/verbena-badge.component.html +13 -0
- package/src/lib/verbena-badge/verbena-badge.component.spec.ts +25 -0
- package/src/lib/verbena-badge/verbena-badge.component.ts +18 -0
- package/src/lib/verbena-badge/verbena-badge.module.ts +10 -0
- package/src/lib/verbena-button/verbena-button.component.css +20 -0
- package/src/lib/verbena-button/verbena-button.component.html +25 -0
- package/src/lib/verbena-button/verbena-button.component.spec.ts +25 -0
- package/src/lib/verbena-button/verbena-button.component.ts +92 -0
- package/src/lib/verbena-button/verbena-button.module.ts +11 -0
- package/src/lib/verbena-switch/verbena-switch.component.css +45 -0
- package/src/lib/verbena-switch/verbena-switch.component.html +8 -0
- package/src/lib/verbena-switch/verbena-switch.component.spec.ts +25 -0
- package/src/lib/verbena-switch/verbena-switch.component.ts +31 -0
- package/src/lib/verbena-switch/verbena-switch.module.ts +10 -0
- package/src/lib/verbena-textarea/verbena-textarea.component.css +0 -0
- package/src/lib/verbena-textarea/verbena-textarea.component.html +19 -0
- package/src/lib/verbena-textarea/verbena-textarea.component.spec.ts +33 -0
- package/src/lib/verbena-textarea/verbena-textarea.component.ts +44 -0
- package/src/lib/verbena-textarea/verbena-textarea.module.ts +11 -0
- package/src/public-api.ts +122 -0
- package/src/styles.css +103 -0
- package/tsconfig.lib.json +15 -0
- package/tsconfig.lib.prod.json +11 -0
- 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.
|
package/ng-package.json
ADDED
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 {}
|
package/src/lib/components/card-data-view/card-data-view-footer/card-data-view-footer.component.html
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<ng-content></ng-content>
|
|
@@ -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
|
+
});
|
package/src/lib/components/card-data-view/card-data-view-footer/card-data-view-footer.component.ts
ADDED
|
@@ -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
|
+
}
|
package/src/lib/components/card-data-view/card-data-view-header/card-data-view-header.component.html
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<ng-content></ng-content>
|
|
@@ -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
|
+
});
|
package/src/lib/components/card-data-view/card-data-view-header/card-data-view-header.component.ts
ADDED
|
@@ -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
|
+
}
|