@carefirst/library 1.3.8 → 1.3.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. package/.eslintrc.json +31 -0
  2. package/ng-package.json +8 -0
  3. package/package.json +11 -14
  4. package/public/styles/colors.scss +2 -2
  5. package/public/styles/font.scss +2 -2
  6. package/src/lib/components/alert/alert.component.html +0 -0
  7. package/src/lib/components/alert/alert.component.scss +63 -0
  8. package/src/lib/components/alert/alert.component.spec.ts +23 -0
  9. package/src/lib/components/alert/alert.component.ts +73 -0
  10. package/src/lib/components/badge/badge.component.html +5 -0
  11. package/src/lib/components/badge/badge.component.scss +96 -0
  12. package/src/lib/components/badge/badge.component.spec.ts +23 -0
  13. package/src/lib/components/badge/badge.component.ts +61 -0
  14. package/src/lib/components/button/button.component.html +20 -0
  15. package/src/lib/components/button/button.component.scss +153 -0
  16. package/src/lib/components/button/button.component.spec.ts +21 -0
  17. package/src/lib/components/button/button.component.ts +94 -0
  18. package/src/lib/components/calendar/calendar.component.html +9 -0
  19. package/src/lib/components/calendar/calendar.component.scss +34 -0
  20. package/src/lib/components/calendar/calendar.component.spec.ts +23 -0
  21. package/src/lib/components/calendar/calendar.component.ts +53 -0
  22. package/src/lib/components/chat-bubble/chat-bubble.component.html +9 -0
  23. package/src/lib/components/chat-bubble/chat-bubble.component.scss +31 -0
  24. package/src/lib/components/chat-bubble/chat-bubble.component.spec.ts +23 -0
  25. package/src/lib/components/chat-bubble/chat-bubble.component.ts +43 -0
  26. package/src/lib/components/form-input/form-input.component.html +37 -0
  27. package/src/lib/components/form-input/form-input.component.scss +23 -0
  28. package/src/lib/components/form-input/form-input.component.spec.ts +23 -0
  29. package/src/lib/components/form-input/form-input.component.ts +95 -0
  30. package/src/lib/components/form-input-select/form-input-select.component.html +27 -0
  31. package/src/lib/components/form-input-select/form-input-select.component.scss +40 -0
  32. package/src/lib/components/form-input-select/form-input-select.component.spec.ts +23 -0
  33. package/src/lib/components/form-input-select/form-input-select.component.ts +61 -0
  34. package/src/lib/components/form-input-text-area/form-input-text-area.component.html +29 -0
  35. package/src/lib/components/form-input-text-area/form-input-text-area.component.scss +19 -0
  36. package/src/lib/components/form-input-text-area/form-input-text-area.component.spec.ts +23 -0
  37. package/src/lib/components/form-input-text-area/form-input-text-area.component.ts +76 -0
  38. package/src/lib/components/form-validation/form-validation.component.html +8 -0
  39. package/src/lib/components/form-validation/form-validation.component.scss +8 -0
  40. package/src/lib/components/form-validation/form-validation.component.spec.ts +23 -0
  41. package/src/lib/components/form-validation/form-validation.component.ts +34 -0
  42. package/src/lib/components/icon/icon.component.html +529 -0
  43. package/src/lib/components/icon/icon.component.scss +61 -0
  44. package/src/lib/components/icon/icon.component.spec.ts +21 -0
  45. package/src/lib/components/icon/icon.component.ts +40 -0
  46. package/src/lib/components/logo/logo.component.html +10 -0
  47. package/src/lib/components/logo/logo.component.scss +5 -0
  48. package/src/lib/components/logo/logo.component.spec.ts +23 -0
  49. package/src/lib/components/logo/logo.component.ts +21 -0
  50. package/src/lib/components/notification/notification.component.html +39 -0
  51. package/src/lib/components/notification/notification.component.scss +20 -0
  52. package/src/lib/components/notification/notification.component.spec.ts +21 -0
  53. package/src/lib/components/notification/notification.component.ts +23 -0
  54. package/src/lib/components/page/page.component.html +5 -0
  55. package/src/lib/components/page/page.component.scss +35 -0
  56. package/src/lib/components/page/page.component.spec.ts +21 -0
  57. package/src/lib/components/page/page.component.ts +42 -0
  58. package/src/lib/components/spacer/spacer.component.html +4 -0
  59. package/src/lib/components/spacer/spacer.component.scss +27 -0
  60. package/src/lib/components/spacer/spacer.component.spec.ts +21 -0
  61. package/src/lib/components/spacer/spacer.component.ts +43 -0
  62. package/src/lib/components/spinner/spinner.component.html +1 -0
  63. package/src/lib/components/spinner/spinner.component.scss +14 -0
  64. package/src/lib/components/spinner/spinner.component.spec.ts +23 -0
  65. package/src/lib/components/spinner/spinner.component.ts +33 -0
  66. package/src/lib/directives/button-loader.directive.spec.ts +8 -0
  67. package/src/lib/directives/button-loader.directive.ts +77 -0
  68. package/src/lib/interfaces/alert.interface.ts +20 -0
  69. package/src/lib/interfaces/icon.interface.ts +62 -0
  70. package/src/lib/interfaces/input.interface.ts +8 -0
  71. package/src/lib/interfaces/notification.interface.ts +15 -0
  72. package/src/lib/interfaces/spacer.interface.ts +6 -0
  73. package/src/lib/library.module.ts +66 -0
  74. package/src/lib/utils/attribute.util.ts +66 -0
  75. package/src/lib/utils/form-validators-utility.ts +186 -0
  76. package/{public-api.d.ts → src/public-api.ts} +21 -0
  77. package/tsconfig.lib.json +12 -0
  78. package/tsconfig.lib.prod.json +10 -0
  79. package/tsconfig.spec.json +14 -0
  80. package/esm2022/carefirst-library.mjs +0 -2
  81. package/esm2022/lib/components/alert/alert.component.mjs +0 -56
  82. package/esm2022/lib/components/button/button.component.mjs +0 -87
  83. package/esm2022/lib/components/calendar/calendar.component.mjs +0 -39
  84. package/esm2022/lib/components/form-input/form-input.component.mjs +0 -87
  85. package/esm2022/lib/components/form-input-select/form-input-select.component.mjs +0 -46
  86. package/esm2022/lib/components/form-input-text-area/form-input-text-area.component.mjs +0 -61
  87. package/esm2022/lib/components/form-validation/form-validation.component.mjs +0 -20
  88. package/esm2022/lib/components/icon/icon.component.mjs +0 -29
  89. package/esm2022/lib/components/logo/logo.component.mjs +0 -18
  90. package/esm2022/lib/components/notification/notification.component.mjs +0 -22
  91. package/esm2022/lib/components/page/page.component.mjs +0 -31
  92. package/esm2022/lib/components/spacer/spacer.component.mjs +0 -30
  93. package/esm2022/lib/directives/button-loader.directive.mjs +0 -41
  94. package/esm2022/lib/interfaces/alert.interface.mjs +0 -2
  95. package/esm2022/lib/interfaces/icon.interface.mjs +0 -52
  96. package/esm2022/lib/interfaces/input.interface.mjs +0 -2
  97. package/esm2022/lib/interfaces/notification.interface.mjs +0 -2
  98. package/esm2022/lib/interfaces/spacer.interface.mjs +0 -2
  99. package/esm2022/lib/library.module.mjs +0 -85
  100. package/esm2022/lib/utils/attribute.util.mjs +0 -34
  101. package/esm2022/lib/utils/form-validators-utility.mjs +0 -113
  102. package/esm2022/public-api.mjs +0 -21
  103. package/fesm2022/carefirst-library.mjs +0 -799
  104. package/fesm2022/carefirst-library.mjs.map +0 -1
  105. package/index.d.ts +0 -2
  106. package/lib/components/alert/alert.component.d.ts +0 -14
  107. package/lib/components/button/button.component.d.ts +0 -30
  108. package/lib/components/calendar/calendar.component.d.ts +0 -15
  109. package/lib/components/form-input/form-input.component.d.ts +0 -37
  110. package/lib/components/form-input-select/form-input-select.component.d.ts +0 -21
  111. package/lib/components/form-input-text-area/form-input-text-area.component.d.ts +0 -27
  112. package/lib/components/form-validation/form-validation.component.d.ts +0 -9
  113. package/lib/components/icon/icon.component.d.ts +0 -13
  114. package/lib/components/logo/logo.component.d.ts +0 -7
  115. package/lib/components/notification/notification.component.d.ts +0 -9
  116. package/lib/components/page/page.component.d.ts +0 -13
  117. package/lib/components/spacer/spacer.component.d.ts +0 -14
  118. package/lib/directives/button-loader.directive.d.ts +0 -12
  119. package/lib/interfaces/alert.interface.d.ts +0 -11
  120. package/lib/interfaces/icon.interface.d.ts +0 -4
  121. package/lib/interfaces/input.interface.d.ts +0 -4
  122. package/lib/interfaces/notification.interface.d.ts +0 -11
  123. package/lib/interfaces/spacer.interface.d.ts +0 -3
  124. package/lib/library.module.d.ts +0 -22
  125. package/lib/utils/attribute.util.d.ts +0 -4
  126. package/lib/utils/form-validators-utility.d.ts +0 -8
@@ -0,0 +1,94 @@
1
+ /**
2
+ * CareFirst Library - Button
3
+ *
4
+ * @file button.component
5
+ * @description Contains all the logic for generating a CareFirst Button
6
+ * @author Jacques Coetzee
7
+ * @since 2023 - 11 - 07
8
+ * @usage <cf-btn type="'primary' | 'secondary' | 'tertiary'" fontSize="'small' | 'large'" %customColor="var() | hex"% %disabled% %alert% %action% %snug%>TEXT</cf-btn>
9
+ */
10
+
11
+ import { Component, Input, type SimpleChanges, type OnChanges, HostBinding } from '@angular/core';
12
+ import { checkTruthAttribute, validateStringValue } from '../../utils/attribute.util';
13
+ import { iconsC, type IconsT } from '../../interfaces/icon.interface';
14
+
15
+ @Component({
16
+ selector: 'cf-btn',
17
+ templateUrl: './button.component.html',
18
+ styleUrls: ['./button.component.scss'],
19
+ })
20
+ export class ButtonComponent implements OnChanges {
21
+ @Input() type: 'primary' | 'secondary' | 'tertiary' = 'primary';
22
+ @Input() disabled?: boolean | string | undefined;
23
+ @Input() alert?: boolean | string | undefined;
24
+ @Input() action?: boolean | string | undefined;
25
+ @Input() snug?: boolean | string | undefined;
26
+ @Input() fontSize?: 'small' | 'large';
27
+ @Input() iconStart?: IconsT | undefined;
28
+ @Input() iconEnd?: IconsT | undefined;
29
+ @Input() loading?: boolean | string | undefined;
30
+ @Input() customColor?: string | undefined;
31
+
32
+ @HostBinding('style.pointer-events') get parentEvents(): string {
33
+ if (this.disabled) {
34
+ return 'none';
35
+ }
36
+ return 'auto';
37
+ }
38
+
39
+ //--- Local variables
40
+ inputType: typeof this.type = 'primary';
41
+ inputFontSize: typeof this.fontSize | undefined = undefined;
42
+ inputDisabled = false;
43
+ inputAlert = false;
44
+ inputAction = false;
45
+ inputSnug = false;
46
+ inputIconStart: typeof this.iconStart | undefined = undefined;
47
+ inputIconEnd: typeof this.iconEnd | undefined = undefined;
48
+ inputLoading = false;
49
+ inputCustomColor = '';
50
+
51
+ /**----------------------------------------------------------------
52
+ * @name ngOnChanges
53
+ * @description Update various values on input changes
54
+ * @returns {void}
55
+ */
56
+ ngOnChanges(changes: SimpleChanges): void {
57
+ //--- Type
58
+ this.inputType =
59
+ validateStringValue<'primary' | 'secondary' | 'tertiary'>(changes, 'type', ['primary', 'secondary', 'tertiary'], this.inputType) || 'primary';
60
+ //--- Font Size
61
+ this.inputFontSize = validateStringValue<'small' | 'large'>(changes, 'fontSize', ['small', 'large'], this.inputFontSize);
62
+ //--- Disabled
63
+ this.inputDisabled = checkTruthAttribute(changes, 'disabled', this.inputDisabled);
64
+ //--- Alert
65
+ this.inputAlert = checkTruthAttribute(changes, 'alert', this.inputAlert);
66
+ //--- Action
67
+ this.inputAction = checkTruthAttribute(changes, 'action', this.inputAction);
68
+ //--- Snug
69
+ this.inputSnug = checkTruthAttribute(changes, 'snug', this.inputSnug);
70
+ //--- Icon Start
71
+ this.inputIconStart = validateStringValue<IconsT>(changes, 'iconStart', iconsC.slice(), this.inputIconStart);
72
+ //--- Icon Start
73
+ this.inputIconEnd = validateStringValue<IconsT>(changes, 'iconEnd', iconsC.slice(), this.inputIconEnd);
74
+ //--- Loading
75
+ this.inputLoading = checkTruthAttribute(changes, 'loading', this.inputLoading);
76
+ //--- Custom color
77
+ if (changes['customColor']?.currentValue) this.inputCustomColor = this.checkCustomColor(changes['customColor'].currentValue);
78
+ }
79
+
80
+ /**----------------------------------------------------------------
81
+ * @name checkCustomColor
82
+ * @description Check if the custom color is valid
83
+ * @param {string} color
84
+ * @returns {string}
85
+ */
86
+ checkCustomColor(color: string): string {
87
+ //--- Check for a css variable
88
+ if (color.startsWith('var')) return color;
89
+ //--- Check hex
90
+ if (color.startsWith('#') && (color.length === 4 || color.length === 7) && color.split('').every((char) => char.match(/[#0-9a-fA-F]+/)))
91
+ return color;
92
+ return '';
93
+ }
94
+ }
@@ -0,0 +1,9 @@
1
+ <ion-datetime
2
+ [class]="inputColor"
3
+ mode="ios"
4
+ firstDayOfWeek="1"
5
+ [min]="min"
6
+ [max]="max"
7
+ [presentation]="inputTime ? 'date-time' : 'date'"
8
+ (ionChange)="setValue($event.detail.value)">
9
+ </ion-datetime>
@@ -0,0 +1,34 @@
1
+ ion-datetime {
2
+ --background: var(--cf-app-background-light);
3
+ color: var(--cf-app-text-color-default);
4
+ }
5
+
6
+ ion-datetime::part(calendar-day) {
7
+ font-size: 1.6rem;
8
+ }
9
+
10
+ ion-datetime::part(month-year-button) {
11
+ font-size: 1.8rem;
12
+ font-weight: 900;
13
+ color: var(--cf-app-text-color-default);
14
+ }
15
+
16
+ ion-datetime.accent::part(today) {
17
+ border: 1px solid var(--cf-app-color-accent);
18
+ color: var(--cf-app-color-accent);
19
+ }
20
+
21
+ ion-datetime.accent::part(active) {
22
+ background-color: var(--cf-app-color-accent);
23
+ color: var(--cf-app-text-color-light);
24
+ }
25
+
26
+ ion-datetime.success::part(today) {
27
+ border: 1px solid var(--cf-app-color-primary);
28
+ color: var(--cf-app-text-color-default);
29
+ }
30
+
31
+ ion-datetime.success::part(active) {
32
+ background-color: var(--cf-app-system-color-success);
33
+ color: var(--cf-app-text-color-light);
34
+ }
@@ -0,0 +1,23 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { CalendarComponent } from './calendar.component';
4
+
5
+ describe('CalendarComponent', () => {
6
+ let component: CalendarComponent;
7
+ let fixture: ComponentFixture<CalendarComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [CalendarComponent]
12
+ })
13
+ .compileComponents();
14
+
15
+ fixture = TestBed.createComponent(CalendarComponent);
16
+ component = fixture.componentInstance;
17
+ fixture.detectChanges();
18
+ });
19
+
20
+ it('should create', () => {
21
+ expect(component).toBeTruthy();
22
+ });
23
+ });
@@ -0,0 +1,53 @@
1
+ /**
2
+ * CareFirst Library Calendar
3
+ *
4
+ * @file calendar.component
5
+ * @description Contains all the logic for generating a CareFirst Calendar
6
+ * @author Arno Jansen van Vuuren
7
+ * @since 2023 - 12 - 01
8
+ * @usage <cf-calendar %displayTime% %color%="success | accent" %min% %max%></cf-calendar>
9
+ */
10
+
11
+ import { Component, EventEmitter, Input, Output, type OnChanges, type SimpleChanges } from '@angular/core';
12
+ import dayjs from 'dayjs';
13
+ //--- Utils
14
+ import { checkTruthAttribute, validateStringValue } from '../../utils/attribute.util';
15
+
16
+ @Component({
17
+ selector: 'cf-calendar',
18
+ templateUrl: './calendar.component.html',
19
+ styleUrl: './calendar.component.scss',
20
+ })
21
+ export class CalendarComponent implements OnChanges {
22
+ @Input() displayTime?: boolean | string | undefined;
23
+ @Input() color?: 'success' | 'accent';
24
+ @Input() min?: string | undefined = undefined;
25
+ @Input() max?: string | undefined = undefined;
26
+ @Output() value = new EventEmitter<string>();
27
+
28
+ //--- Local variables
29
+ inputTime = false;
30
+ inputColor: typeof this.color = 'accent';
31
+
32
+ /**----------------------------------------------------------------
33
+ * @name ngOnChanges
34
+ * @description Update various values on component input changes
35
+ * @returns {void}
36
+ */
37
+ ngOnChanges(changes: SimpleChanges): void {
38
+ //--- Display Time
39
+ this.inputTime = checkTruthAttribute(changes, 'displayTime', this.inputTime);
40
+ //--- Color
41
+ this.inputColor = validateStringValue<'success' | 'accent'>(changes, 'color', ['success', 'accent'], this.inputColor) || 'accent';
42
+ }
43
+
44
+ /**----------------------------------------------------------------
45
+ * @name setValue
46
+ * @description Emit the selected date value
47
+ * @param {string | string[] | null | undefined} value
48
+ * @returns {void}
49
+ */
50
+ setValue(value: string | string[] | null | undefined): void {
51
+ if (typeof value === 'string') this.value.emit(dayjs(value).format('YYYY-MM-DD' + (this.inputTime ? ' HH:mm' : '')));
52
+ }
53
+ }
@@ -0,0 +1,9 @@
1
+ <div id="container" [ngClass]="inputType">
2
+ <div id="message">
3
+ <p class="body-extra-small">{{ inputDate }}</p>
4
+ <cf-spacer default="4"></cf-spacer>
5
+ <div id="bubble">
6
+ <p class="body-extra-small">{{ inputMessage }}</p>
7
+ </div>
8
+ </div>
9
+ </div>
@@ -0,0 +1,31 @@
1
+ #container {
2
+ display: flex;
3
+
4
+ #message {
5
+ p {
6
+ color: var(--cf-app-text-color-default);
7
+ }
8
+ #bubble {
9
+ background: var(--message-background-color);
10
+ border-radius: var(--border-radius);
11
+ padding: 12px 16px;
12
+ p {
13
+ color: var(--cf-app-text-color-light);
14
+ }
15
+ }
16
+ }
17
+ }
18
+
19
+ #container.outgoing {
20
+ justify-content: end;
21
+ text-align: end;
22
+ --border-radius: 16px 4px 16px 16px;
23
+ --message-background-color: var(--cf-app-color-primary);
24
+ }
25
+
26
+ #container.incoming {
27
+ justify-content: start;
28
+ text-align: start;
29
+ --border-radius: 4px 16px 16px 16px;
30
+ --message-background-color: var(--cf-app-color-secondary);
31
+ }
@@ -0,0 +1,23 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { ChatBubbleComponent } from './chat-bubble.component';
4
+
5
+ describe('ChatBubbleComponent', () => {
6
+ let component: ChatBubbleComponent;
7
+ let fixture: ComponentFixture<ChatBubbleComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [ChatBubbleComponent]
12
+ })
13
+ .compileComponents();
14
+
15
+ fixture = TestBed.createComponent(ChatBubbleComponent);
16
+ component = fixture.componentInstance;
17
+ fixture.detectChanges();
18
+ });
19
+
20
+ it('should create', () => {
21
+ expect(component).toBeTruthy();
22
+ });
23
+ });
@@ -0,0 +1,43 @@
1
+ /**
2
+ * CareFirst Chat Bubble
3
+ *
4
+ * @file chat-bubble.component
5
+ * @description Contains all the logic for generating a CareFirst Chat Bubble
6
+ * @author Jacques Coetzee
7
+ * @since 2024 - 02 - 22
8
+ * @usage <cf-chat-bubble type="outgoing | incoming" date="string" message="string"></cf-chat-bubble>
9
+ */
10
+
11
+ import { Component, Input, type OnChanges, type SimpleChanges } from '@angular/core';
12
+ //--- Utils
13
+ import { validateStringValue } from '../../utils/attribute.util';
14
+
15
+ @Component({
16
+ selector: 'cf-chat-bubble',
17
+ templateUrl: './chat-bubble.component.html',
18
+ styleUrl: './chat-bubble.component.scss',
19
+ })
20
+ export class ChatBubbleComponent implements OnChanges {
21
+ @Input() type: 'outgoing' | 'incoming' = 'outgoing';
22
+ @Input() date: string = '';
23
+ @Input() message: string = '';
24
+
25
+ //--- Local variables
26
+ inputType: typeof this.type = 'incoming';
27
+ inputDate: typeof this.date = '';
28
+ inputMessage: typeof this.message = '';
29
+
30
+ /**----------------------------------------------------------------
31
+ * @name ngOnChanges
32
+ * @description Update various values on input changes
33
+ * @returns {void}
34
+ */
35
+ ngOnChanges(changes: SimpleChanges): void {
36
+ //--- Type
37
+ this.inputType = validateStringValue<typeof this.type>(changes, 'type', ['incoming', 'outgoing'], this.inputType) || 'outgoing';
38
+ //--- Date
39
+ this.inputDate = changes['date']?.currentValue || '';
40
+ //--- Message
41
+ this.inputMessage = changes['message']?.currentValue || '';
42
+ }
43
+ }
@@ -0,0 +1,37 @@
1
+ <!-- ngModel -->
2
+ <ion-input
3
+ *ngIf="!control"
4
+ [ngClass]="{ 'text-center': inputTextCenter, 'grey-background': inputGreyBackground }"
5
+ [label]="label"
6
+ [labelPlacement]="inputLabelPlacement"
7
+ [placeholder]="placeholder"
8
+ fill="outline"
9
+ [clearInput]="!inputClear"
10
+ [autocapitalize]="autoCapitalize"
11
+ mode="md"
12
+ [inputmode]="localInputMode"
13
+ [min]="min"
14
+ [max]="max"
15
+ [maxlength]="maxLength || null"
16
+ [type]="type"
17
+ (ionInput)="valueChange.emit($event.detail.value ?? undefined)"
18
+ [value]="value"></ion-input>
19
+ <!-- Form Control -->
20
+ <ion-input
21
+ *ngIf="control"
22
+ [ngClass]="{ 'text-center': inputTextCenter, 'grey-background': inputGreyBackground }"
23
+ [label]="label"
24
+ [labelPlacement]="inputLabelPlacement"
25
+ [placeholder]="placeholder"
26
+ fill="outline"
27
+ [clearInput]="!inputClear"
28
+ [autocapitalize]="autoCapitalize"
29
+ mode="md"
30
+ [inputmode]="localInputMode"
31
+ [formControl]="control"
32
+ [min]="min"
33
+ [max]="max"
34
+ [maxlength]="maxLength || null"
35
+ [type]="type"
36
+ (ionInput)="valueChange.emit($event.detail.value ?? undefined)"></ion-input>
37
+ <cf-form-validation *ngIf="control" [control]="control"></cf-form-validation>
@@ -0,0 +1,23 @@
1
+ /*===============================================
2
+ ================== Form Items ===================
3
+ ===============================================*/
4
+ ion-input {
5
+ font-family: 'Roboto', sans-serif;
6
+ font-weight: 400;
7
+ font-style: normal;
8
+ font-size: 1.6rem;
9
+ color: var(--cf-app-text-color-default);
10
+ text-align: start;
11
+ --border-radius: 8px !important; //--- important overrides the fill option
12
+ --highlight-color-focused: var(--cf-app-color-primary);
13
+ --highlight-color-invalid: var(--cf-app-system-color-error);
14
+ --highlight-color-valid: var(--cf-app-color-primary);
15
+ }
16
+
17
+ ion-input.text-center {
18
+ text-align: center;
19
+ }
20
+
21
+ ion-input.grey-background {
22
+ --background: var(--cf-app-system-color-outline);
23
+ }
@@ -0,0 +1,23 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { FormInputComponent } from './form-input.component';
4
+
5
+ describe('FormInputComponent', () => {
6
+ let component: FormInputComponent;
7
+ let fixture: ComponentFixture<FormInputComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [FormInputComponent]
12
+ })
13
+ .compileComponents();
14
+
15
+ fixture = TestBed.createComponent(FormInputComponent);
16
+ component = fixture.componentInstance;
17
+ fixture.detectChanges();
18
+ });
19
+
20
+ it('should create', () => {
21
+ expect(component).toBeTruthy();
22
+ });
23
+ });
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Carefirst Library Form Input
3
+ *
4
+ * @file form-input.component
5
+ * @description Contains all the logic for generating a CareFirst Form Input Field
6
+ * @author Arno Jansen van Vuuren
7
+ * @since 2023 - 12 - 14
8
+ * @usage <cf-form-input label="Label Name" %labelPlacement% %inputMode% %noClearButton% %textCenter% %min% %max% %autoCapitalize% %type% %[(value)]="twoWayComs"% %(valueChange)="currentValueEvent"% %[control]%="formName.controls.controlName"></cf-form-input>
9
+ * disable input by disabling the form control
10
+ */
11
+
12
+ import { Component, Input, Output, type OnChanges, type SimpleChanges, EventEmitter } from '@angular/core';
13
+ import { FormControl } from '@angular/forms';
14
+ //--- Utils
15
+ import { checkTruthAttribute, validateStringValue } from '../../utils/attribute.util';
16
+
17
+ /**==============================================
18
+ * @interface inputsC
19
+ * @description Define available input values
20
+ */
21
+ const inputsC = {
22
+ labelPlacement: ['fixed', 'floating', 'stacked', 'start', 'end'],
23
+ inputMode: ['text', 'email', 'numeric', 'tel', 'decimal', 'url', 'search'],
24
+ autoCapitalize: ['off', 'none', 'on', 'sentences', 'words', 'characters'],
25
+ type: ['date', 'datetime-local', 'email', 'month', 'number', 'password', 'search', 'tel', 'text', 'time', 'url', 'week'],
26
+ } as const;
27
+
28
+ @Component({
29
+ selector: 'cf-form-input',
30
+ templateUrl: './form-input.component.html',
31
+ styleUrl: './form-input.component.scss',
32
+ })
33
+ export class FormInputComponent implements OnChanges {
34
+ @Input() label!: string;
35
+ @Input() min: number | string = 'none';
36
+ @Input() max: number | string = 'none';
37
+ @Input() labelPlacement?: (typeof inputsC.labelPlacement)[number];
38
+ @Input() placeholder?: string | undefined;
39
+ @Input() inputmode?: (typeof inputsC.inputMode)[number];
40
+ @Input() autoCapitalize?: (typeof inputsC.autoCapitalize)[number];
41
+ @Input() type?: (typeof inputsC.type)[number];
42
+ @Input() noClearButton?: boolean | string | undefined;
43
+ @Input() control?: FormControl | null;
44
+ @Input() textCenter?: boolean | string | undefined;
45
+ @Input() maxLength?: number | string;
46
+ @Input() greyBackground?: boolean | string | undefined;
47
+
48
+ //--- ngModel
49
+ @Input() value: string | undefined;
50
+ @Output() valueChange = new EventEmitter<typeof this.value>();
51
+
52
+ //--- Local variables
53
+ inputLabelPlacement: typeof this.labelPlacement;
54
+ localInputMode: typeof this.inputmode;
55
+ inputClear = false;
56
+ inputTextCenter = false;
57
+ inputType: typeof this.type;
58
+ inputAutoCapitalize: typeof this.autoCapitalize;
59
+ inputGreyBackground = false;
60
+
61
+ /**----------------------------------------------------------------
62
+ * @name ngOnChanges
63
+ * @description Detect changes to input values
64
+ * @param {SimpleChanges} changes
65
+ */
66
+ ngOnChanges(changes: SimpleChanges): void {
67
+ //--- Label Placement
68
+ this.inputLabelPlacement =
69
+ validateStringValue<(typeof inputsC.labelPlacement)[number]>(
70
+ changes,
71
+ 'labelPlacement',
72
+ inputsC.labelPlacement.slice(),
73
+ this.inputLabelPlacement
74
+ ) || 'floating';
75
+ //--- Input Type (keyboard)
76
+ this.localInputMode =
77
+ validateStringValue<(typeof inputsC.inputMode)[number]>(changes, 'inputmode', inputsC.inputMode.slice(), this.localInputMode) || 'text';
78
+ //--- Clear Button
79
+ this.inputClear = checkTruthAttribute(changes, 'noClearButton', this.inputClear);
80
+ //--- Text Center
81
+ this.inputTextCenter = checkTruthAttribute(changes, 'textCenter', this.inputTextCenter);
82
+ //--- Type
83
+ this.inputType = validateStringValue<(typeof inputsC.type)[number]>(changes, 'type', inputsC.type.slice(), this.inputType) || 'text';
84
+ //--- Auto Capitalize
85
+ this.inputAutoCapitalize =
86
+ validateStringValue<(typeof inputsC.autoCapitalize)[number]>(
87
+ changes,
88
+ 'autoCapitalize',
89
+ inputsC.autoCapitalize.slice(),
90
+ this.inputAutoCapitalize
91
+ ) || 'none';
92
+ //--- Grey Background
93
+ this.inputGreyBackground = checkTruthAttribute(changes, 'greyBackground', this.inputGreyBackground);
94
+ }
95
+ }
@@ -0,0 +1,27 @@
1
+ <!-- ngModel -->
2
+ <ion-select
3
+ *ngIf="!control"
4
+ [label]="label"
5
+ [labelPlacement]="inputLabelPlacement"
6
+ [placeholder]="placeholder"
7
+ fill="outline"
8
+ mode="md"
9
+ interface="popover"
10
+ (ionChange)="valueChange.emit($event.detail.value ?? undefined)"
11
+ [value]="value">
12
+ <ion-select-option *ngFor="let option of options" [value]="option.value">{{ option.displayName }}</ion-select-option>
13
+ </ion-select>
14
+ <!-- Form Control -->
15
+ <ion-select
16
+ *ngIf="control"
17
+ [label]="label"
18
+ [labelPlacement]="inputLabelPlacement"
19
+ [placeholder]="placeholder"
20
+ fill="outline"
21
+ mode="md"
22
+ interface="popover"
23
+ [formControl]="control"
24
+ (ionChange)="valueChange.emit($event.detail.value ?? undefined)">
25
+ <ion-select-option *ngFor="let option of options" [value]="option.value">{{ option.displayName }}</ion-select-option>
26
+ </ion-select>
27
+ <cf-form-validation *ngIf="control" [control]="control"></cf-form-validation>
@@ -0,0 +1,40 @@
1
+ /*===============================================
2
+ ================== Form Items ===================
3
+ ===============================================*/
4
+ ion-select {
5
+ font-family: 'Roboto', sans-serif;
6
+ font-weight: 400;
7
+ font-style: normal;
8
+ font-size: 1.6rem;
9
+ color: var(--cf-app-text-color-default);
10
+ text-align: start;
11
+ --border-radius: 8px !important; //--- important overrides the fill option
12
+ --highlight-color-focused: var(--cf-app-color-primary);
13
+ --highlight-color-invalid: var(--cf-app-system-color-error);
14
+ --highlight-color-valid: var(--cf-app-color-primary);
15
+ }
16
+
17
+ /*===============================================
18
+ ================ Select Popovers ================
19
+ ===============================================*/
20
+ ::ng-deep ion-select-popover ion-list[class*='popover'] {
21
+ background: var(--cf-app-background-light);
22
+ ion-item[class*='popover'] {
23
+ ion-radio {
24
+ font-family: 'Roboto', sans-serif;
25
+ font-weight: 400;
26
+ font-style: normal;
27
+ font-size: 1.6rem;
28
+ color: var(--cf-app-text-color-default);
29
+ text-align: start;
30
+ }
31
+
32
+ --background: transparent;
33
+ --border-radius: 8px;
34
+ --background-focused: var(--cf-app-color-accent);
35
+ --background-focused-opacity: 0.5;
36
+ --background-hover: var(--cf-app-color-primary);
37
+ --background-hover-opacity: 0.1;
38
+ padding: 4px;
39
+ }
40
+ }
@@ -0,0 +1,23 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { FormInputSelectComponent } from './form-input-select.component';
4
+
5
+ describe('FormInputSelectComponent', () => {
6
+ let component: FormInputSelectComponent;
7
+ let fixture: ComponentFixture<FormInputSelectComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [FormInputSelectComponent]
12
+ })
13
+ .compileComponents();
14
+
15
+ fixture = TestBed.createComponent(FormInputSelectComponent);
16
+ component = fixture.componentInstance;
17
+ fixture.detectChanges();
18
+ });
19
+
20
+ it('should create', () => {
21
+ expect(component).toBeTruthy();
22
+ });
23
+ });
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Carefirst Library Form Input Select
3
+ *
4
+ * @file form-input-select.component
5
+ * @description Contains all the logic for generating a CareFirst Select
6
+ * @author Arno Jansen van Vuuren
7
+ * @since 2023 - 12 - 14
8
+ * @usage <cf-form-input-select label="Label Name" [options]="[{ displayName: string; value: string | number | boolean | null | undefined }]" %labelPlacement% %(valueChange)="currentValue"% %[(value)]="twoWayComs"% %[control]%="formName.controls.controlName"></cf-form-input-select>
9
+ * disable input by disabling the form control
10
+ */
11
+
12
+ import { Component, EventEmitter, Input, Output, type OnChanges, type SimpleChanges } from '@angular/core';
13
+ import { FormControl } from '@angular/forms';
14
+ //--- Utils
15
+ import { validateStringValue } from '../../utils/attribute.util';
16
+ //--- Interfaces
17
+ import type { FormInputSelectOptionsI } from '../../interfaces/input.interface';
18
+
19
+ /**==============================================
20
+ * @interface inputSelectC
21
+ * @description Define available input select values
22
+ */
23
+ const inputSelectC = {
24
+ labelPlacement: ['fixed', 'floating', 'stacked', 'start', 'end'],
25
+ } as const;
26
+
27
+ @Component({
28
+ selector: 'cf-form-input-select',
29
+ templateUrl: './form-input-select.component.html',
30
+ styleUrl: './form-input-select.component.scss',
31
+ })
32
+ export class FormInputSelectComponent<T> implements OnChanges {
33
+ @Input() label!: string;
34
+ @Input() options!: FormInputSelectOptionsI<T>[];
35
+ @Input() labelPlacement?: (typeof inputSelectC.labelPlacement)[number];
36
+ @Input() placeholder?: string | undefined;
37
+ @Input() control?: FormControl | null;
38
+
39
+ //--- ngModel
40
+ @Input() value: FormInputSelectOptionsI<T>['value'] | undefined;
41
+ @Output() valueChange = new EventEmitter<typeof this.value>();
42
+
43
+ //--- Local variables
44
+ inputLabelPlacement: typeof this.labelPlacement;
45
+
46
+ /**----------------------------------------------------------------
47
+ * @name ngOnChanges
48
+ * @description Detect changes to input values
49
+ * @param {SimpleChanges} changes
50
+ */
51
+ ngOnChanges(changes: SimpleChanges): void {
52
+ //--- Label Placement
53
+ this.inputLabelPlacement =
54
+ validateStringValue<(typeof inputSelectC.labelPlacement)[number]>(
55
+ changes,
56
+ 'labelPlacement',
57
+ inputSelectC.labelPlacement.slice(),
58
+ this.inputLabelPlacement
59
+ ) || 'floating';
60
+ }
61
+ }