@mj-biz-apps/common-ng 5.4.0

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 (82) hide show
  1. package/README.md +276 -0
  2. package/dist/lib/components/address-editor/address-editor.component.d.ts +249 -0
  3. package/dist/lib/components/address-editor/address-editor.component.d.ts.map +1 -0
  4. package/dist/lib/components/address-editor/address-editor.component.js +981 -0
  5. package/dist/lib/components/address-editor/address-editor.component.js.map +1 -0
  6. package/dist/lib/components/contact-method-list/contact-method-list.component.d.ts +256 -0
  7. package/dist/lib/components/contact-method-list/contact-method-list.component.d.ts.map +1 -0
  8. package/dist/lib/components/contact-method-list/contact-method-list.component.js +788 -0
  9. package/dist/lib/components/contact-method-list/contact-method-list.component.js.map +1 -0
  10. package/dist/lib/components/org-hierarchy-tree/org-hierarchy-tree.component.d.ts +119 -0
  11. package/dist/lib/components/org-hierarchy-tree/org-hierarchy-tree.component.d.ts.map +1 -0
  12. package/dist/lib/components/org-hierarchy-tree/org-hierarchy-tree.component.js +295 -0
  13. package/dist/lib/components/org-hierarchy-tree/org-hierarchy-tree.component.js.map +1 -0
  14. package/dist/lib/components/relationship-list/relationship-list.component.d.ts +392 -0
  15. package/dist/lib/components/relationship-list/relationship-list.component.d.ts.map +1 -0
  16. package/dist/lib/components/relationship-list/relationship-list.component.js +1171 -0
  17. package/dist/lib/components/relationship-list/relationship-list.component.js.map +1 -0
  18. package/dist/lib/custom/Organization/organization-form.component.d.ts +24 -0
  19. package/dist/lib/custom/Organization/organization-form.component.d.ts.map +1 -0
  20. package/dist/lib/custom/Organization/organization-form.component.js +244 -0
  21. package/dist/lib/custom/Organization/organization-form.component.js.map +1 -0
  22. package/dist/lib/custom/Person/person-form.component.d.ts +24 -0
  23. package/dist/lib/custom/Person/person-form.component.d.ts.map +1 -0
  24. package/dist/lib/custom/Person/person-form.component.js +231 -0
  25. package/dist/lib/custom/Person/person-form.component.js.map +1 -0
  26. package/dist/lib/custom/custom-forms.module.d.ts +17 -0
  27. package/dist/lib/custom/custom-forms.module.d.ts.map +1 -0
  28. package/dist/lib/custom/custom-forms.module.js +64 -0
  29. package/dist/lib/custom/custom-forms.module.js.map +1 -0
  30. package/dist/lib/generated/Entities/mjBizAppsCommonAddress/mjbizappscommonaddress.form.component.d.ts +10 -0
  31. package/dist/lib/generated/Entities/mjBizAppsCommonAddress/mjbizappscommonaddress.form.component.d.ts.map +1 -0
  32. package/dist/lib/generated/Entities/mjBizAppsCommonAddress/mjbizappscommonaddress.form.component.js +94 -0
  33. package/dist/lib/generated/Entities/mjBizAppsCommonAddress/mjbizappscommonaddress.form.component.js.map +1 -0
  34. package/dist/lib/generated/Entities/mjBizAppsCommonAddressLink/mjbizappscommonaddresslink.form.component.d.ts +10 -0
  35. package/dist/lib/generated/Entities/mjBizAppsCommonAddressLink/mjbizappscommonaddresslink.form.component.d.ts.map +1 -0
  36. package/dist/lib/generated/Entities/mjBizAppsCommonAddressLink/mjbizappscommonaddresslink.form.component.js +70 -0
  37. package/dist/lib/generated/Entities/mjBizAppsCommonAddressLink/mjbizappscommonaddresslink.form.component.js.map +1 -0
  38. package/dist/lib/generated/Entities/mjBizAppsCommonAddressType/mjbizappscommonaddresstype.form.component.d.ts +10 -0
  39. package/dist/lib/generated/Entities/mjBizAppsCommonAddressType/mjbizappscommonaddresstype.form.component.d.ts.map +1 -0
  40. package/dist/lib/generated/Entities/mjBizAppsCommonAddressType/mjbizappscommonaddresstype.form.component.js +86 -0
  41. package/dist/lib/generated/Entities/mjBizAppsCommonAddressType/mjbizappscommonaddresstype.form.component.js.map +1 -0
  42. package/dist/lib/generated/Entities/mjBizAppsCommonContactMethod/mjbizappscommoncontactmethod.form.component.d.ts +10 -0
  43. package/dist/lib/generated/Entities/mjBizAppsCommonContactMethod/mjbizappscommoncontactmethod.form.component.d.ts.map +1 -0
  44. package/dist/lib/generated/Entities/mjBizAppsCommonContactMethod/mjbizappscommoncontactmethod.form.component.js +70 -0
  45. package/dist/lib/generated/Entities/mjBizAppsCommonContactMethod/mjbizappscommoncontactmethod.form.component.js.map +1 -0
  46. package/dist/lib/generated/Entities/mjBizAppsCommonContactType/mjbizappscommoncontacttype.form.component.d.ts +10 -0
  47. package/dist/lib/generated/Entities/mjBizAppsCommonContactType/mjbizappscommoncontacttype.form.component.d.ts.map +1 -0
  48. package/dist/lib/generated/Entities/mjBizAppsCommonContactType/mjbizappscommoncontacttype.form.component.js +86 -0
  49. package/dist/lib/generated/Entities/mjBizAppsCommonContactType/mjbizappscommoncontacttype.form.component.js.map +1 -0
  50. package/dist/lib/generated/Entities/mjBizAppsCommonOrganization/mjbizappscommonorganization.form.component.d.ts +10 -0
  51. package/dist/lib/generated/Entities/mjBizAppsCommonOrganization/mjbizappscommonorganization.form.component.d.ts.map +1 -0
  52. package/dist/lib/generated/Entities/mjBizAppsCommonOrganization/mjbizappscommonorganization.form.component.js +190 -0
  53. package/dist/lib/generated/Entities/mjBizAppsCommonOrganization/mjbizappscommonorganization.form.component.js.map +1 -0
  54. package/dist/lib/generated/Entities/mjBizAppsCommonOrganizationType/mjbizappscommonorganizationtype.form.component.d.ts +10 -0
  55. package/dist/lib/generated/Entities/mjBizAppsCommonOrganizationType/mjbizappscommonorganizationtype.form.component.d.ts.map +1 -0
  56. package/dist/lib/generated/Entities/mjBizAppsCommonOrganizationType/mjbizappscommonorganizationtype.form.component.js +80 -0
  57. package/dist/lib/generated/Entities/mjBizAppsCommonOrganizationType/mjbizappscommonorganizationtype.form.component.js.map +1 -0
  58. package/dist/lib/generated/Entities/mjBizAppsCommonPerson/mjbizappscommonperson.form.component.d.ts +10 -0
  59. package/dist/lib/generated/Entities/mjBizAppsCommonPerson/mjbizappscommonperson.form.component.d.ts.map +1 -0
  60. package/dist/lib/generated/Entities/mjBizAppsCommonPerson/mjbizappscommonperson.form.component.js +184 -0
  61. package/dist/lib/generated/Entities/mjBizAppsCommonPerson/mjbizappscommonperson.form.component.js.map +1 -0
  62. package/dist/lib/generated/Entities/mjBizAppsCommonRelationship/mjbizappscommonrelationship.form.component.d.ts +10 -0
  63. package/dist/lib/generated/Entities/mjBizAppsCommonRelationship/mjbizappscommonrelationship.form.component.d.ts.map +1 -0
  64. package/dist/lib/generated/Entities/mjBizAppsCommonRelationship/mjbizappscommonrelationship.form.component.js +78 -0
  65. package/dist/lib/generated/Entities/mjBizAppsCommonRelationship/mjbizappscommonrelationship.form.component.js.map +1 -0
  66. package/dist/lib/generated/Entities/mjBizAppsCommonRelationshipType/mjbizappscommonrelationshiptype.form.component.d.ts +10 -0
  67. package/dist/lib/generated/Entities/mjBizAppsCommonRelationshipType/mjbizappscommonrelationshiptype.form.component.d.ts.map +1 -0
  68. package/dist/lib/generated/Entities/mjBizAppsCommonRelationshipType/mjbizappscommonrelationshiptype.form.component.js +90 -0
  69. package/dist/lib/generated/Entities/mjBizAppsCommonRelationshipType/mjbizappscommonrelationshiptype.form.component.js.map +1 -0
  70. package/dist/lib/generated/class-registrations-manifest.d.ts +22 -0
  71. package/dist/lib/generated/class-registrations-manifest.d.ts.map +1 -0
  72. package/dist/lib/generated/class-registrations-manifest.js +39 -0
  73. package/dist/lib/generated/class-registrations-manifest.js.map +1 -0
  74. package/dist/lib/generated/generated-forms.module.d.ts +28 -0
  75. package/dist/lib/generated/generated-forms.module.d.ts.map +1 -0
  76. package/dist/lib/generated/generated-forms.module.js +94 -0
  77. package/dist/lib/generated/generated-forms.module.js.map +1 -0
  78. package/dist/public-api.d.ts +23 -0
  79. package/dist/public-api.d.ts.map +1 -0
  80. package/dist/public-api.js +30 -0
  81. package/dist/public-api.js.map +1 -0
  82. package/package.json +46 -0
@@ -0,0 +1,788 @@
1
+ import { Component, Input, Output, EventEmitter, inject, ChangeDetectorRef } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { FormsModule } from '@angular/forms';
4
+ import { Metadata, RunView } from '@memberjunction/core';
5
+ import * as i0 from "@angular/core";
6
+ import * as i1 from "@angular/common";
7
+ import * as i2 from "@angular/forms";
8
+ const _forTrack0 = ($index, $item) => $item.ID;
9
+ function ContactMethodListComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) {
10
+ i0.ɵɵelementStart(0, "span", 3);
11
+ i0.ɵɵtext(1);
12
+ i0.ɵɵelementEnd();
13
+ } if (rf & 2) {
14
+ const ctx_r0 = i0.ɵɵnextContext();
15
+ i0.ɵɵadvance();
16
+ i0.ɵɵtextInterpolate1("(", ctx_r0.ContactMethods.length, ")");
17
+ } }
18
+ function ContactMethodListComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) {
19
+ i0.ɵɵelementStart(0, "div", 4)(1, "div", 5);
20
+ i0.ɵɵelement(2, "i", 6);
21
+ i0.ɵɵtext(3, " Loading contacts... ");
22
+ i0.ɵɵelementEnd()();
23
+ } }
24
+ function ContactMethodListComponent_Conditional_6_Conditional_1_Template(rf, ctx) { if (rf & 1) {
25
+ i0.ɵɵelementStart(0, "div", 7);
26
+ i0.ɵɵelement(1, "i", 2);
27
+ i0.ɵɵtext(2, " No contact methods yet ");
28
+ i0.ɵɵelementEnd();
29
+ } }
30
+ function ContactMethodListComponent_Conditional_6_For_3_Conditional_0_For_7_Template(rf, ctx) { if (rf & 1) {
31
+ i0.ɵɵelementStart(0, "option", 15);
32
+ i0.ɵɵtext(1);
33
+ i0.ɵɵelementEnd();
34
+ } if (rf & 2) {
35
+ const t_r3 = ctx.$implicit;
36
+ i0.ɵɵproperty("value", t_r3.ID);
37
+ i0.ɵɵadvance();
38
+ i0.ɵɵtextInterpolate(t_r3.Name);
39
+ } }
40
+ function ContactMethodListComponent_Conditional_6_For_3_Conditional_0_Conditional_22_Template(rf, ctx) { if (rf & 1) {
41
+ i0.ɵɵelement(0, "i", 25);
42
+ } }
43
+ function ContactMethodListComponent_Conditional_6_For_3_Conditional_0_Template(rf, ctx) { if (rf & 1) {
44
+ const _r2 = i0.ɵɵgetCurrentView();
45
+ i0.ɵɵelementStart(0, "div", 10)(1, "div", 12)(2, "div", 13)(3, "label");
46
+ i0.ɵɵtext(4, "Type");
47
+ i0.ɵɵelementEnd();
48
+ i0.ɵɵelementStart(5, "select", 14);
49
+ i0.ɵɵtwoWayListener("ngModelChange", function ContactMethodListComponent_Conditional_6_For_3_Conditional_0_Template_select_ngModelChange_5_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r0.EditForm.TypeID, $event) || (ctx_r0.EditForm.TypeID = $event); return i0.ɵɵresetView($event); });
50
+ i0.ɵɵrepeaterCreate(6, ContactMethodListComponent_Conditional_6_For_3_Conditional_0_For_7_Template, 2, 2, "option", 15, _forTrack0);
51
+ i0.ɵɵelementEnd()();
52
+ i0.ɵɵelementStart(8, "div", 16)(9, "label");
53
+ i0.ɵɵtext(10, "Value");
54
+ i0.ɵɵelementEnd();
55
+ i0.ɵɵelementStart(11, "input", 17);
56
+ i0.ɵɵtwoWayListener("ngModelChange", function ContactMethodListComponent_Conditional_6_For_3_Conditional_0_Template_input_ngModelChange_11_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r0.EditForm.Value, $event) || (ctx_r0.EditForm.Value = $event); return i0.ɵɵresetView($event); });
57
+ i0.ɵɵelementEnd()();
58
+ i0.ɵɵelementStart(12, "div", 18)(13, "label");
59
+ i0.ɵɵtext(14, "Label");
60
+ i0.ɵɵelementEnd();
61
+ i0.ɵɵelementStart(15, "input", 19);
62
+ i0.ɵɵtwoWayListener("ngModelChange", function ContactMethodListComponent_Conditional_6_For_3_Conditional_0_Template_input_ngModelChange_15_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r0.EditForm.Label, $event) || (ctx_r0.EditForm.Label = $event); return i0.ɵɵresetView($event); });
63
+ i0.ɵɵelementEnd()();
64
+ i0.ɵɵelementStart(16, "div", 20)(17, "input", 21);
65
+ i0.ɵɵtwoWayListener("ngModelChange", function ContactMethodListComponent_Conditional_6_For_3_Conditional_0_Template_input_ngModelChange_17_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r0.EditForm.IsPrimary, $event) || (ctx_r0.EditForm.IsPrimary = $event); return i0.ɵɵresetView($event); });
66
+ i0.ɵɵelementEnd();
67
+ i0.ɵɵelementStart(18, "label", 22);
68
+ i0.ɵɵtext(19, "Primary");
69
+ i0.ɵɵelementEnd()();
70
+ i0.ɵɵelementStart(20, "div", 23)(21, "button", 24);
71
+ i0.ɵɵlistener("click", function ContactMethodListComponent_Conditional_6_For_3_Conditional_0_Template_button_click_21_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.onSaveEdit()); });
72
+ i0.ɵɵconditionalCreate(22, ContactMethodListComponent_Conditional_6_For_3_Conditional_0_Conditional_22_Template, 1, 0, "i", 25);
73
+ i0.ɵɵtext(23, " Save ");
74
+ i0.ɵɵelementEnd();
75
+ i0.ɵɵelementStart(24, "button", 26);
76
+ i0.ɵɵlistener("click", function ContactMethodListComponent_Conditional_6_For_3_Conditional_0_Template_button_click_24_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.onCancelEdit()); });
77
+ i0.ɵɵtext(25, "Cancel");
78
+ i0.ɵɵelementEnd()()()();
79
+ } if (rf & 2) {
80
+ const cm_r4 = i0.ɵɵnextContext().$implicit;
81
+ const ctx_r0 = i0.ɵɵnextContext(2);
82
+ i0.ɵɵadvance(5);
83
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.EditForm.TypeID);
84
+ i0.ɵɵadvance();
85
+ i0.ɵɵrepeater(ctx_r0.ContactTypes);
86
+ i0.ɵɵadvance(5);
87
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.EditForm.Value);
88
+ i0.ɵɵproperty("placeholder", ctx_r0.getPlaceholder(ctx_r0.EditForm.TypeID));
89
+ i0.ɵɵadvance(4);
90
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.EditForm.Label);
91
+ i0.ɵɵadvance(2);
92
+ i0.ɵɵproperty("id", "primary-edit-" + cm_r4.ID);
93
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.EditForm.IsPrimary);
94
+ i0.ɵɵadvance();
95
+ i0.ɵɵproperty("for", "primary-edit-" + cm_r4.ID);
96
+ i0.ɵɵadvance(3);
97
+ i0.ɵɵproperty("disabled", ctx_r0.Saving);
98
+ i0.ɵɵadvance();
99
+ i0.ɵɵconditional(ctx_r0.Saving ? 22 : -1);
100
+ } }
101
+ function ContactMethodListComponent_Conditional_6_For_3_Conditional_1_Conditional_9_Template(rf, ctx) { if (rf & 1) {
102
+ i0.ɵɵelementStart(0, "span", 33);
103
+ i0.ɵɵelement(1, "i", 38);
104
+ i0.ɵɵelementEnd();
105
+ } }
106
+ function ContactMethodListComponent_Conditional_6_For_3_Conditional_1_Conditional_11_Template(rf, ctx) { if (rf & 1) {
107
+ const _r6 = i0.ɵɵgetCurrentView();
108
+ i0.ɵɵelementStart(0, "button", 39);
109
+ i0.ɵɵlistener("click", function ContactMethodListComponent_Conditional_6_For_3_Conditional_1_Conditional_11_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r6); const cm_r4 = i0.ɵɵnextContext(2).$implicit; const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onSetPrimary(cm_r4)); });
110
+ i0.ɵɵelement(1, "i", 40);
111
+ i0.ɵɵelementEnd();
112
+ } }
113
+ function ContactMethodListComponent_Conditional_6_For_3_Conditional_1_Conditional_12_Template(rf, ctx) { if (rf & 1) {
114
+ const _r7 = i0.ɵɵgetCurrentView();
115
+ i0.ɵɵelementStart(0, "button", 41);
116
+ i0.ɵɵlistener("click", function ContactMethodListComponent_Conditional_6_For_3_Conditional_1_Conditional_12_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r7); const cm_r4 = i0.ɵɵnextContext(2).$implicit; const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onOpenLink(cm_r4.Value)); });
117
+ i0.ɵɵelement(1, "i", 42);
118
+ i0.ɵɵelementEnd();
119
+ } }
120
+ function ContactMethodListComponent_Conditional_6_For_3_Conditional_1_Conditional_13_Template(rf, ctx) { if (rf & 1) {
121
+ const _r8 = i0.ɵɵgetCurrentView();
122
+ i0.ɵɵelementStart(0, "button", 43);
123
+ i0.ɵɵlistener("click", function ContactMethodListComponent_Conditional_6_For_3_Conditional_1_Conditional_13_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r8); const cm_r4 = i0.ɵɵnextContext(2).$implicit; const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onCopyValue(cm_r4.Value)); });
124
+ i0.ɵɵelement(1, "i", 44);
125
+ i0.ɵɵelementEnd();
126
+ } }
127
+ function ContactMethodListComponent_Conditional_6_For_3_Conditional_1_Conditional_14_Template(rf, ctx) { if (rf & 1) {
128
+ const _r9 = i0.ɵɵgetCurrentView();
129
+ i0.ɵɵelementStart(0, "button", 45);
130
+ i0.ɵɵlistener("click", function ContactMethodListComponent_Conditional_6_For_3_Conditional_1_Conditional_14_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r9); const cm_r4 = i0.ɵɵnextContext(2).$implicit; const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onEdit(cm_r4)); });
131
+ i0.ɵɵelement(1, "i", 46);
132
+ i0.ɵɵelementEnd();
133
+ i0.ɵɵelementStart(2, "button", 47);
134
+ i0.ɵɵlistener("click", function ContactMethodListComponent_Conditional_6_For_3_Conditional_1_Conditional_14_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r9); const cm_r4 = i0.ɵɵnextContext(2).$implicit; const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onDelete(cm_r4)); });
135
+ i0.ɵɵelement(3, "i", 48);
136
+ i0.ɵɵelementEnd();
137
+ } }
138
+ function ContactMethodListComponent_Conditional_6_For_3_Conditional_1_Template(rf, ctx) { if (rf & 1) {
139
+ const _r5 = i0.ɵɵgetCurrentView();
140
+ i0.ɵɵelementStart(0, "div", 27)(1, "div", 28);
141
+ i0.ɵɵelement(2, "i");
142
+ i0.ɵɵelementEnd();
143
+ i0.ɵɵelementStart(3, "div", 29)(4, "div", 30);
144
+ i0.ɵɵlistener("click", function ContactMethodListComponent_Conditional_6_For_3_Conditional_1_Template_div_click_4_listener() { i0.ɵɵrestoreView(_r5); const cm_r4 = i0.ɵɵnextContext().$implicit; const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onCopyValue(cm_r4.Value)); });
145
+ i0.ɵɵtext(5);
146
+ i0.ɵɵelementEnd();
147
+ i0.ɵɵelementStart(6, "div", 31);
148
+ i0.ɵɵtext(7);
149
+ i0.ɵɵelementEnd()();
150
+ i0.ɵɵelementStart(8, "div", 32);
151
+ i0.ɵɵconditionalCreate(9, ContactMethodListComponent_Conditional_6_For_3_Conditional_1_Conditional_9_Template, 2, 0, "span", 33);
152
+ i0.ɵɵelementEnd();
153
+ i0.ɵɵelementStart(10, "div", 34);
154
+ i0.ɵɵconditionalCreate(11, ContactMethodListComponent_Conditional_6_For_3_Conditional_1_Conditional_11_Template, 2, 0, "button", 35);
155
+ i0.ɵɵconditionalCreate(12, ContactMethodListComponent_Conditional_6_For_3_Conditional_1_Conditional_12_Template, 2, 0, "button", 36)(13, ContactMethodListComponent_Conditional_6_For_3_Conditional_1_Conditional_13_Template, 2, 0, "button", 37);
156
+ i0.ɵɵconditionalCreate(14, ContactMethodListComponent_Conditional_6_For_3_Conditional_1_Conditional_14_Template, 4, 0);
157
+ i0.ɵɵelementEnd()();
158
+ } if (rf & 2) {
159
+ const cm_r4 = i0.ɵɵnextContext().$implicit;
160
+ const ctx_r0 = i0.ɵɵnextContext(2);
161
+ i0.ɵɵclassProp("primary", cm_r4.IsPrimary);
162
+ i0.ɵɵadvance();
163
+ i0.ɵɵproperty("ngClass", ctx_r0.getIconColorClass(cm_r4.ContactTypeID));
164
+ i0.ɵɵadvance();
165
+ i0.ɵɵclassMap(ctx_r0.getContactTypeIcon(cm_r4.ContactTypeID));
166
+ i0.ɵɵadvance(3);
167
+ i0.ɵɵtextInterpolate(cm_r4.Value);
168
+ i0.ɵɵadvance(2);
169
+ i0.ɵɵtextInterpolate(ctx_r0.getContactMeta(cm_r4));
170
+ i0.ɵɵadvance(2);
171
+ i0.ɵɵconditional(cm_r4.IsPrimary ? 9 : -1);
172
+ i0.ɵɵadvance(2);
173
+ i0.ɵɵconditional(ctx_r0.EditMode && !cm_r4.IsPrimary ? 11 : -1);
174
+ i0.ɵɵadvance();
175
+ i0.ɵɵconditional(ctx_r0.isLinkType(cm_r4.ContactTypeID) ? 12 : 13);
176
+ i0.ɵɵadvance(2);
177
+ i0.ɵɵconditional(ctx_r0.EditMode ? 14 : -1);
178
+ } }
179
+ function ContactMethodListComponent_Conditional_6_For_3_Template(rf, ctx) { if (rf & 1) {
180
+ i0.ɵɵconditionalCreate(0, ContactMethodListComponent_Conditional_6_For_3_Conditional_0_Template, 26, 9, "div", 10)(1, ContactMethodListComponent_Conditional_6_For_3_Conditional_1_Template, 15, 11, "div", 11);
181
+ } if (rf & 2) {
182
+ const cm_r4 = ctx.$implicit;
183
+ const ctx_r0 = i0.ɵɵnextContext(2);
184
+ i0.ɵɵconditional(ctx_r0.EditingId === cm_r4.ID ? 0 : 1);
185
+ } }
186
+ function ContactMethodListComponent_Conditional_6_Conditional_4_For_6_Template(rf, ctx) { if (rf & 1) {
187
+ i0.ɵɵelementStart(0, "option", 15);
188
+ i0.ɵɵtext(1);
189
+ i0.ɵɵelementEnd();
190
+ } if (rf & 2) {
191
+ const t_r11 = ctx.$implicit;
192
+ i0.ɵɵproperty("value", t_r11.ID);
193
+ i0.ɵɵadvance();
194
+ i0.ɵɵtextInterpolate(t_r11.Name);
195
+ } }
196
+ function ContactMethodListComponent_Conditional_6_Conditional_4_Conditional_21_Template(rf, ctx) { if (rf & 1) {
197
+ i0.ɵɵelement(0, "i", 25);
198
+ } }
199
+ function ContactMethodListComponent_Conditional_6_Conditional_4_Template(rf, ctx) { if (rf & 1) {
200
+ const _r10 = i0.ɵɵgetCurrentView();
201
+ i0.ɵɵelementStart(0, "div", 8)(1, "div", 13)(2, "label");
202
+ i0.ɵɵtext(3, "Type");
203
+ i0.ɵɵelementEnd();
204
+ i0.ɵɵelementStart(4, "select", 14);
205
+ i0.ɵɵtwoWayListener("ngModelChange", function ContactMethodListComponent_Conditional_6_Conditional_4_Template_select_ngModelChange_4_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r0 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r0.AddForm.TypeID, $event) || (ctx_r0.AddForm.TypeID = $event); return i0.ɵɵresetView($event); });
206
+ i0.ɵɵrepeaterCreate(5, ContactMethodListComponent_Conditional_6_Conditional_4_For_6_Template, 2, 2, "option", 15, _forTrack0);
207
+ i0.ɵɵelementEnd()();
208
+ i0.ɵɵelementStart(7, "div", 16)(8, "label");
209
+ i0.ɵɵtext(9, "Value");
210
+ i0.ɵɵelementEnd();
211
+ i0.ɵɵelementStart(10, "input", 17);
212
+ i0.ɵɵtwoWayListener("ngModelChange", function ContactMethodListComponent_Conditional_6_Conditional_4_Template_input_ngModelChange_10_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r0 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r0.AddForm.Value, $event) || (ctx_r0.AddForm.Value = $event); return i0.ɵɵresetView($event); });
213
+ i0.ɵɵelementEnd()();
214
+ i0.ɵɵelementStart(11, "div", 18)(12, "label");
215
+ i0.ɵɵtext(13, "Label");
216
+ i0.ɵɵelementEnd();
217
+ i0.ɵɵelementStart(14, "input", 49);
218
+ i0.ɵɵtwoWayListener("ngModelChange", function ContactMethodListComponent_Conditional_6_Conditional_4_Template_input_ngModelChange_14_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r0 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r0.AddForm.Label, $event) || (ctx_r0.AddForm.Label = $event); return i0.ɵɵresetView($event); });
219
+ i0.ɵɵelementEnd()();
220
+ i0.ɵɵelementStart(15, "div", 20)(16, "input", 50);
221
+ i0.ɵɵtwoWayListener("ngModelChange", function ContactMethodListComponent_Conditional_6_Conditional_4_Template_input_ngModelChange_16_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r0 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r0.AddForm.IsPrimary, $event) || (ctx_r0.AddForm.IsPrimary = $event); return i0.ɵɵresetView($event); });
222
+ i0.ɵɵelementEnd();
223
+ i0.ɵɵelementStart(17, "label", 51);
224
+ i0.ɵɵtext(18, "Primary");
225
+ i0.ɵɵelementEnd()();
226
+ i0.ɵɵelementStart(19, "div", 23)(20, "button", 24);
227
+ i0.ɵɵlistener("click", function ContactMethodListComponent_Conditional_6_Conditional_4_Template_button_click_20_listener() { i0.ɵɵrestoreView(_r10); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onSaveAdd()); });
228
+ i0.ɵɵconditionalCreate(21, ContactMethodListComponent_Conditional_6_Conditional_4_Conditional_21_Template, 1, 0, "i", 25);
229
+ i0.ɵɵtext(22, " Add ");
230
+ i0.ɵɵelementEnd();
231
+ i0.ɵɵelementStart(23, "button", 26);
232
+ i0.ɵɵlistener("click", function ContactMethodListComponent_Conditional_6_Conditional_4_Template_button_click_23_listener() { i0.ɵɵrestoreView(_r10); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onCancelAdd()); });
233
+ i0.ɵɵtext(24, "Cancel");
234
+ i0.ɵɵelementEnd()()();
235
+ } if (rf & 2) {
236
+ const ctx_r0 = i0.ɵɵnextContext(2);
237
+ i0.ɵɵadvance(4);
238
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.AddForm.TypeID);
239
+ i0.ɵɵadvance();
240
+ i0.ɵɵrepeater(ctx_r0.ContactTypes);
241
+ i0.ɵɵadvance(5);
242
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.AddForm.Value);
243
+ i0.ɵɵproperty("placeholder", ctx_r0.getPlaceholder(ctx_r0.AddForm.TypeID));
244
+ i0.ɵɵadvance(4);
245
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.AddForm.Label);
246
+ i0.ɵɵadvance(2);
247
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.AddForm.IsPrimary);
248
+ i0.ɵɵadvance(4);
249
+ i0.ɵɵproperty("disabled", ctx_r0.Saving);
250
+ i0.ɵɵadvance();
251
+ i0.ɵɵconditional(ctx_r0.Saving ? 21 : -1);
252
+ } }
253
+ function ContactMethodListComponent_Conditional_6_Conditional_5_Template(rf, ctx) { if (rf & 1) {
254
+ const _r12 = i0.ɵɵgetCurrentView();
255
+ i0.ɵɵelementStart(0, "div", 9)(1, "button", 52);
256
+ i0.ɵɵlistener("click", function ContactMethodListComponent_Conditional_6_Conditional_5_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r12); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onShowAdd()); });
257
+ i0.ɵɵelement(2, "i", 53);
258
+ i0.ɵɵtext(3, " Add Contact ");
259
+ i0.ɵɵelementEnd()();
260
+ } }
261
+ function ContactMethodListComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) {
262
+ i0.ɵɵelementStart(0, "div", 4);
263
+ i0.ɵɵconditionalCreate(1, ContactMethodListComponent_Conditional_6_Conditional_1_Template, 3, 0, "div", 7);
264
+ i0.ɵɵrepeaterCreate(2, ContactMethodListComponent_Conditional_6_For_3_Template, 2, 1, null, null, _forTrack0);
265
+ i0.ɵɵconditionalCreate(4, ContactMethodListComponent_Conditional_6_Conditional_4_Template, 25, 7, "div", 8);
266
+ i0.ɵɵconditionalCreate(5, ContactMethodListComponent_Conditional_6_Conditional_5_Template, 4, 0, "div", 9);
267
+ i0.ɵɵelementEnd();
268
+ } if (rf & 2) {
269
+ const ctx_r0 = i0.ɵɵnextContext();
270
+ i0.ɵɵadvance();
271
+ i0.ɵɵconditional(ctx_r0.ContactMethods.length === 0 && !ctx_r0.ShowAddForm ? 1 : -1);
272
+ i0.ɵɵadvance();
273
+ i0.ɵɵrepeater(ctx_r0.ContactMethods);
274
+ i0.ɵɵadvance(2);
275
+ i0.ɵɵconditional(ctx_r0.ShowAddForm ? 4 : -1);
276
+ i0.ɵɵadvance();
277
+ i0.ɵɵconditional(!ctx_r0.ShowAddForm && ctx_r0.EditingId === null && ctx_r0.EditMode ? 5 : -1);
278
+ } }
279
+ /**
280
+ * Displays and manages contact methods (email, phone, social, etc.) for a
281
+ * Person or Organization record.
282
+ *
283
+ * Contact methods are loaded from the `MJ.BizApps.Common: Contact Methods`
284
+ * entity, filtered by either {@link PersonID} or {@link OrganizationID}.
285
+ * The component provides inline add, edit, delete, set-primary, copy-to-clipboard,
286
+ * and open-link functionality.
287
+ *
288
+ * Primary management is scoped per contact type -- setting a contact as primary
289
+ * only demotes other primaries of the **same** type.
290
+ *
291
+ * @example
292
+ * ```html
293
+ * <!-- For a Person -->
294
+ * <bizapps-contact-method-list
295
+ * [PersonID]="person.ID">
296
+ * </bizapps-contact-method-list>
297
+ *
298
+ * <!-- For an Organization -->
299
+ * <bizapps-contact-method-list
300
+ * [OrganizationID]="org.ID">
301
+ * </bizapps-contact-method-list>
302
+ * ```
303
+ */
304
+ export class ContactMethodListComponent {
305
+ cdr = inject(ChangeDetectorRef);
306
+ /**
307
+ * Controls whether add, edit, delete, and set-primary actions are available.
308
+ * When `false`, the component renders in read-only display mode.
309
+ * Copy and open-link actions remain available regardless of this setting.
310
+ */
311
+ EditMode = false;
312
+ /** Emitted after any mutation (save, delete, set-primary) so the parent can refresh derived data. */
313
+ DataChanged = new EventEmitter();
314
+ _personID = null;
315
+ _organizationID = null;
316
+ /**
317
+ * The Person record ID whose contact methods should be displayed.
318
+ *
319
+ * Mutually exclusive with {@link OrganizationID}. Setting this triggers
320
+ * a data reload unless the value has not changed.
321
+ *
322
+ * @example `'A1B2C3D4-E5F6-7890-ABCD-EF1234567890'`
323
+ */
324
+ set PersonID(value) {
325
+ const prev = this._personID;
326
+ this._personID = value;
327
+ if (value && value !== prev) {
328
+ this.loadData();
329
+ }
330
+ }
331
+ get PersonID() { return this._personID; }
332
+ /**
333
+ * The Organization record ID whose contact methods should be displayed.
334
+ *
335
+ * Mutually exclusive with {@link PersonID}. Setting this triggers
336
+ * a data reload unless the value has not changed.
337
+ *
338
+ * @example `'B2C3D4E5-F6A7-8901-BCDE-F12345678901'`
339
+ */
340
+ set OrganizationID(value) {
341
+ const prev = this._organizationID;
342
+ this._organizationID = value;
343
+ if (value && value !== prev) {
344
+ this.loadData();
345
+ }
346
+ }
347
+ get OrganizationID() { return this._organizationID; }
348
+ /**
349
+ * The loaded contact method entities for the current Person or Organization,
350
+ * sorted with primaries first, then by contact type display rank.
351
+ */
352
+ ContactMethods = [];
353
+ /**
354
+ * All active contact types available for selection in type dropdowns.
355
+ * Loaded from `MJ.BizApps.Common: Contact Types`, sorted by `DisplayRank ASC`.
356
+ */
357
+ ContactTypes = [];
358
+ /**
359
+ * The ID of the contact method currently being edited, or `null` when
360
+ * not in edit mode.
361
+ */
362
+ EditingId = null;
363
+ /**
364
+ * Controls visibility of the inline add form. When `true`, the add form
365
+ * is displayed at the bottom of the contact list.
366
+ */
367
+ ShowAddForm = false;
368
+ /**
369
+ * Indicates whether the component is performing the initial data load.
370
+ * The template shows a loading spinner while this is `true`.
371
+ */
372
+ Loading = false;
373
+ /**
374
+ * Indicates whether a save, delete, or set-primary operation is in progress.
375
+ * Used to disable action buttons and show spinner feedback while `true`.
376
+ */
377
+ Saving = false;
378
+ /**
379
+ * The form model bound to the inline edit panel via two-way binding.
380
+ * Populated from the existing contact method record when editing begins.
381
+ */
382
+ EditForm = this.createEmptyForm();
383
+ /**
384
+ * The form model bound to the inline add panel via two-way binding.
385
+ * Reset to defaults each time the add form is opened.
386
+ */
387
+ AddForm = this.createEmptyForm();
388
+ /** Maps lowercase contact type names to CSS icon-color classes. */
389
+ iconColorMap = {
390
+ 'email': 'icon-email',
391
+ 'mobile phone': 'icon-mobile',
392
+ 'work phone': 'icon-phone',
393
+ 'home phone': 'icon-phone',
394
+ 'phone': 'icon-phone',
395
+ 'linkedin': 'icon-linkedin',
396
+ 'twitter': 'icon-twitter',
397
+ 'twitter / x': 'icon-twitter',
398
+ 'website': 'icon-web',
399
+ 'fax': 'icon-fax'
400
+ };
401
+ /** Contact type names (lowercase) that represent clickable URLs rather than copyable values. */
402
+ linkTypeNames = new Set(['linkedin', 'twitter', 'twitter / x', 'website']);
403
+ /** Creates a blank {@link ContactFormData} with empty defaults. */
404
+ createEmptyForm() {
405
+ return { TypeID: '', Value: '', Label: '', IsPrimary: false };
406
+ }
407
+ /**
408
+ * Loads contact methods and contact types from the server.
409
+ * Resets editing state before loading.
410
+ */
411
+ async loadData() {
412
+ this.Loading = true;
413
+ this.EditingId = null;
414
+ this.ShowAddForm = false;
415
+ this.cdr.detectChanges();
416
+ try {
417
+ const rv = new RunView();
418
+ // Build filter
419
+ let filter = '';
420
+ if (this._personID) {
421
+ filter = `PersonID='${this._personID}'`;
422
+ }
423
+ else if (this._organizationID) {
424
+ filter = `OrganizationID='${this._organizationID}'`;
425
+ }
426
+ else {
427
+ return;
428
+ }
429
+ const [methodsResult, typesResult] = await rv.RunViews([
430
+ {
431
+ EntityName: 'MJ.BizApps.Common: Contact Methods',
432
+ ExtraFilter: filter,
433
+ ResultType: 'entity_object'
434
+ },
435
+ {
436
+ EntityName: 'MJ.BizApps.Common: Contact Types',
437
+ ExtraFilter: 'IsActive=1',
438
+ OrderBy: 'DisplayRank ASC',
439
+ ResultType: 'entity_object'
440
+ }
441
+ ]);
442
+ this.ContactMethods = methodsResult.Success
443
+ ? methodsResult.Results
444
+ : [];
445
+ this.ContactTypes = typesResult.Success
446
+ ? typesResult.Results
447
+ : [];
448
+ // Sort: primary first, then by type rank
449
+ this.ContactMethods.sort((a, b) => {
450
+ if (a.IsPrimary && !b.IsPrimary)
451
+ return -1;
452
+ if (!a.IsPrimary && b.IsPrimary)
453
+ return 1;
454
+ return this.getTypeRank(a.ContactTypeID) - this.getTypeRank(b.ContactTypeID);
455
+ });
456
+ // Set default type for add form
457
+ if (this.ContactTypes.length > 0) {
458
+ this.AddForm.TypeID = this.ContactTypes[0].ID;
459
+ }
460
+ }
461
+ catch (err) {
462
+ console.error('ContactMethodList: Error loading data', err);
463
+ }
464
+ finally {
465
+ this.Loading = false;
466
+ this.cdr.detectChanges();
467
+ }
468
+ }
469
+ /** Returns the DisplayRank for a contact type, defaulting to 999 if not found. */
470
+ getTypeRank(typeID) {
471
+ const ct = this.ContactTypes.find(t => t.ID === typeID);
472
+ return ct?.DisplayRank ?? 999;
473
+ }
474
+ /**
475
+ * Resolves the Font Awesome icon class for a given contact type.
476
+ *
477
+ * Falls back to `'fa-solid fa-circle-info'` when the type is not found
478
+ * or has no icon configured.
479
+ *
480
+ * @param typeID - The ContactType record ID to look up
481
+ * @returns The CSS class string for the icon (e.g., `'fa-solid fa-envelope'`)
482
+ */
483
+ getContactTypeIcon(typeID) {
484
+ const ct = this.ContactTypes.find(t => t.ID === typeID);
485
+ return ct?.IconClass || 'fa-solid fa-circle-info';
486
+ }
487
+ /**
488
+ * Returns a CSS class name that applies a theme color to the contact
489
+ * type icon based on the type name.
490
+ *
491
+ * Falls back to `'icon-default'` for unrecognized type names.
492
+ *
493
+ * @param typeID - The ContactType record ID to look up
494
+ * @returns A CSS class string such as `'icon-email'` or `'icon-linkedin'`
495
+ */
496
+ getIconColorClass(typeID) {
497
+ const ct = this.ContactTypes.find(t => t.ID === typeID);
498
+ if (!ct)
499
+ return 'icon-default';
500
+ const key = ct.Name.toLowerCase();
501
+ return this.iconColorMap[key] || 'icon-default';
502
+ }
503
+ /**
504
+ * Builds a display-friendly metadata string for a contact method row,
505
+ * combining the optional label and the contact type name.
506
+ *
507
+ * @param cm - The contact method entity to format
508
+ * @returns A string such as `'Work · Email'` or just `'Email'`
509
+ */
510
+ getContactMeta(cm) {
511
+ const parts = [];
512
+ if (cm.Label)
513
+ parts.push(cm.Label);
514
+ if (cm.ContactType)
515
+ parts.push(cm.ContactType);
516
+ return parts.join(' · ') || cm.ContactType;
517
+ }
518
+ /**
519
+ * Returns a context-appropriate placeholder string for the value input
520
+ * field based on the selected contact type.
521
+ *
522
+ * @param typeID - The ContactType record ID to look up
523
+ * @returns A placeholder string such as `'Enter email address...'`
524
+ */
525
+ getPlaceholder(typeID) {
526
+ const ct = this.ContactTypes.find(t => t.ID === typeID);
527
+ if (!ct)
528
+ return 'Enter value...';
529
+ const name = ct.Name.toLowerCase();
530
+ if (name.includes('email'))
531
+ return 'Enter email address...';
532
+ if (name.includes('phone') || name.includes('mobile'))
533
+ return 'Enter phone number...';
534
+ if (name.includes('linkedin') || name.includes('twitter') || name.includes('website'))
535
+ return 'Enter URL...';
536
+ return 'Enter value...';
537
+ }
538
+ /**
539
+ * Determines whether a contact type represents a URL that should be
540
+ * opened in a new browser tab rather than copied to the clipboard.
541
+ *
542
+ * @param typeID - The ContactType record ID to check
543
+ * @returns `true` for LinkedIn, Twitter/X, and Website types; `false` otherwise
544
+ */
545
+ isLinkType(typeID) {
546
+ const ct = this.ContactTypes.find(t => t.ID === typeID);
547
+ if (!ct)
548
+ return false;
549
+ return this.linkTypeNames.has(ct.Name.toLowerCase());
550
+ }
551
+ /**
552
+ * Copies the given string value to the system clipboard.
553
+ *
554
+ * Silently ignores clipboard write failures (e.g., when the Clipboard
555
+ * API is not available).
556
+ *
557
+ * @param value - The text to copy to the clipboard
558
+ */
559
+ onCopyValue(value) {
560
+ navigator.clipboard.writeText(value).catch(() => {
561
+ // Fallback: silently fail
562
+ });
563
+ }
564
+ /**
565
+ * Opens the given URL in a new browser tab.
566
+ *
567
+ * Automatically prepends `'https://'` when the value does not already
568
+ * include a protocol prefix.
569
+ *
570
+ * @param value - The URL string to open
571
+ */
572
+ onOpenLink(value) {
573
+ let url = value;
574
+ if (!url.startsWith('http://') && !url.startsWith('https://')) {
575
+ url = 'https://' + url;
576
+ }
577
+ window.open(url, '_blank');
578
+ }
579
+ /**
580
+ * Opens the inline add form for creating a new contact method.
581
+ *
582
+ * Resets the add form to defaults and pre-selects the first available
583
+ * contact type.
584
+ */
585
+ onShowAdd() {
586
+ this.AddForm = this.createEmptyForm();
587
+ if (this.ContactTypes.length > 0) {
588
+ this.AddForm.TypeID = this.ContactTypes[0].ID;
589
+ }
590
+ this.ShowAddForm = true;
591
+ this.cdr.detectChanges();
592
+ }
593
+ /**
594
+ * Closes the inline add form without saving.
595
+ */
596
+ onCancelAdd() {
597
+ this.ShowAddForm = false;
598
+ this.cdr.detectChanges();
599
+ }
600
+ /**
601
+ * Persists the new contact method from the add form.
602
+ *
603
+ * When the "Primary" flag is set, other primaries of the same contact
604
+ * type are demoted first. The contact list is reloaded after saving.
605
+ */
606
+ async onSaveAdd() {
607
+ if (!this.AddForm.Value)
608
+ return;
609
+ this.Saving = true;
610
+ this.cdr.detectChanges();
611
+ try {
612
+ const md = new Metadata();
613
+ const cm = await md.GetEntityObject('MJ.BizApps.Common: Contact Methods');
614
+ cm.NewRecord();
615
+ cm.ContactTypeID = this.AddForm.TypeID;
616
+ cm.Value = this.AddForm.Value;
617
+ cm.Label = this.AddForm.Label || null;
618
+ cm.IsPrimary = this.AddForm.IsPrimary;
619
+ if (this._personID) {
620
+ cm.PersonID = this._personID;
621
+ }
622
+ else if (this._organizationID) {
623
+ cm.OrganizationID = this._organizationID;
624
+ }
625
+ // If setting primary, clear other primaries of same type
626
+ if (this.AddForm.IsPrimary) {
627
+ await this.clearPrimariesForType(this.AddForm.TypeID);
628
+ }
629
+ await cm.Save();
630
+ await this.loadData();
631
+ this.DataChanged.emit();
632
+ }
633
+ catch (err) {
634
+ console.error('ContactMethodList: Error adding contact', err);
635
+ }
636
+ finally {
637
+ this.Saving = false;
638
+ this.cdr.detectChanges();
639
+ }
640
+ }
641
+ /**
642
+ * Opens the inline edit form for an existing contact method, populating
643
+ * the form fields from the current entity data.
644
+ *
645
+ * Closes the add form if it is currently open.
646
+ *
647
+ * @param cm - The contact method entity to edit
648
+ */
649
+ onEdit(cm) {
650
+ this.EditForm = {
651
+ TypeID: cm.ContactTypeID,
652
+ Value: cm.Value,
653
+ Label: cm.Label || '',
654
+ IsPrimary: cm.IsPrimary
655
+ };
656
+ this.EditingId = cm.ID;
657
+ this.ShowAddForm = false;
658
+ this.cdr.detectChanges();
659
+ }
660
+ /**
661
+ * Cancels the current edit operation and returns to display mode.
662
+ */
663
+ onCancelEdit() {
664
+ this.EditingId = null;
665
+ this.cdr.detectChanges();
666
+ }
667
+ /**
668
+ * Persists the edited contact method from the edit form.
669
+ *
670
+ * When the "Primary" flag is newly set, other primaries of the same
671
+ * contact type are demoted first. The contact list is reloaded after saving.
672
+ */
673
+ async onSaveEdit() {
674
+ if (!this.EditForm.Value || !this.EditingId)
675
+ return;
676
+ this.Saving = true;
677
+ this.cdr.detectChanges();
678
+ try {
679
+ const cm = this.ContactMethods.find(c => c.ID === this.EditingId);
680
+ if (!cm)
681
+ return;
682
+ // If setting primary, clear other primaries of same type
683
+ if (this.EditForm.IsPrimary && !cm.IsPrimary) {
684
+ await this.clearPrimariesForType(this.EditForm.TypeID);
685
+ }
686
+ cm.ContactTypeID = this.EditForm.TypeID;
687
+ cm.Value = this.EditForm.Value;
688
+ cm.Label = this.EditForm.Label || null;
689
+ cm.IsPrimary = this.EditForm.IsPrimary;
690
+ await cm.Save();
691
+ await this.loadData();
692
+ this.DataChanged.emit();
693
+ }
694
+ catch (err) {
695
+ console.error('ContactMethodList: Error saving contact', err);
696
+ }
697
+ finally {
698
+ this.Saving = false;
699
+ this.cdr.detectChanges();
700
+ }
701
+ }
702
+ /**
703
+ * Promotes the given contact method to primary for its contact type,
704
+ * demoting all other primaries of the same type.
705
+ *
706
+ * After the update, the contact list is reloaded.
707
+ *
708
+ * @param cm - The contact method entity to promote
709
+ */
710
+ async onSetPrimary(cm) {
711
+ this.Saving = true;
712
+ this.cdr.detectChanges();
713
+ try {
714
+ // Clear other primaries of same type
715
+ await this.clearPrimariesForType(cm.ContactTypeID);
716
+ cm.IsPrimary = true;
717
+ await cm.Save();
718
+ await this.loadData();
719
+ this.DataChanged.emit();
720
+ }
721
+ catch (err) {
722
+ console.error('ContactMethodList: Error setting primary', err);
723
+ }
724
+ finally {
725
+ this.Saving = false;
726
+ this.cdr.detectChanges();
727
+ }
728
+ }
729
+ /**
730
+ * Permanently deletes the given contact method record.
731
+ *
732
+ * After deletion, the contact list is reloaded.
733
+ *
734
+ * @param cm - The contact method entity to delete
735
+ */
736
+ async onDelete(cm) {
737
+ this.Saving = true;
738
+ this.cdr.detectChanges();
739
+ try {
740
+ await cm.Delete();
741
+ await this.loadData();
742
+ this.DataChanged.emit();
743
+ }
744
+ catch (err) {
745
+ console.error('ContactMethodList: Error deleting contact', err);
746
+ }
747
+ finally {
748
+ this.Saving = false;
749
+ this.cdr.detectChanges();
750
+ }
751
+ }
752
+ /** Removes the primary flag from all contact methods of the given type. */
753
+ async clearPrimariesForType(typeID) {
754
+ const sameType = this.ContactMethods.filter(c => c.ContactTypeID === typeID && c.IsPrimary);
755
+ for (const c of sameType) {
756
+ c.IsPrimary = false;
757
+ await c.Save();
758
+ }
759
+ }
760
+ static ɵfac = function ContactMethodListComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ContactMethodListComponent)(); };
761
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ContactMethodListComponent, selectors: [["bizapps-contact-method-list"]], inputs: { EditMode: "EditMode", PersonID: "PersonID", OrganizationID: "OrganizationID" }, outputs: { DataChanged: "DataChanged" }, decls: 7, vars: 2, consts: [[1, "section-header"], [1, "section-label"], [1, "fa-solid", "fa-address-card"], [1, "count"], [1, "cm-flat-list"], [1, "loading-row"], [1, "fa-solid", "fa-spinner"], [1, "empty-state"], [1, "cm-flat-add-form"], [1, "cm-flat-footer"], [1, "cm-flat-edit-row"], [1, "cm-flat-row", 3, "primary"], [1, "form-row"], [1, "form-field", "type-field"], [3, "ngModelChange", "ngModel"], [3, "value"], [1, "form-field", "flex-1"], ["type", "text", 3, "ngModelChange", "ngModel", "placeholder"], [1, "form-field", "label-field"], ["type", "text", "placeholder", "e.g., Work", 3, "ngModelChange", "ngModel"], [1, "checkbox-field"], ["type", "checkbox", 3, "ngModelChange", "id", "ngModel"], [3, "for"], [1, "form-actions"], [1, "btn", "btn-primary", "btn-sm", 3, "click", "disabled"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "btn", "btn-cancel", "btn-sm", 3, "click"], [1, "cm-flat-row"], [1, "cm-flat-icon", 3, "ngClass"], [1, "cm-flat-content"], [1, "cm-flat-value", 3, "click"], [1, "cm-flat-meta"], [1, "cm-flat-badges"], [1, "badge", "badge-primary"], [1, "cm-flat-actions"], ["title", "Set Primary", 1, "btn-ghost"], ["title", "Open", 1, "btn-ghost"], ["title", "Copy", 1, "btn-ghost"], [1, "fa-solid", "fa-star"], ["title", "Set Primary", 1, "btn-ghost", 3, "click"], [1, "fa-regular", "fa-star"], ["title", "Open", 1, "btn-ghost", 3, "click"], [1, "fa-solid", "fa-external-link"], ["title", "Copy", 1, "btn-ghost", 3, "click"], [1, "fa-solid", "fa-copy"], ["title", "Edit", 1, "btn-ghost", 3, "click"], [1, "fa-solid", "fa-pen"], ["title", "Remove", 1, "btn-ghost", "danger", 3, "click"], [1, "fa-solid", "fa-trash"], ["type", "text", "placeholder", "e.g., Direct Line", 3, "ngModelChange", "ngModel"], ["type", "checkbox", "id", "primary-add", 3, "ngModelChange", "ngModel"], ["for", "primary-add"], [1, "btn", "btn-outline", "full-width", 3, "click"], [1, "fa-solid", "fa-plus"]], template: function ContactMethodListComponent_Template(rf, ctx) { if (rf & 1) {
762
+ i0.ɵɵelementStart(0, "div", 0)(1, "span", 1);
763
+ i0.ɵɵelement(2, "i", 2);
764
+ i0.ɵɵtext(3, " Contact Methods ");
765
+ i0.ɵɵconditionalCreate(4, ContactMethodListComponent_Conditional_4_Template, 2, 1, "span", 3);
766
+ i0.ɵɵelementEnd()();
767
+ i0.ɵɵconditionalCreate(5, ContactMethodListComponent_Conditional_5_Template, 4, 0, "div", 4)(6, ContactMethodListComponent_Conditional_6_Template, 6, 3, "div", 4);
768
+ } if (rf & 2) {
769
+ i0.ɵɵadvance(4);
770
+ i0.ɵɵconditional(!ctx.Loading && ctx.ContactMethods.length > 0 ? 4 : -1);
771
+ i0.ɵɵadvance();
772
+ i0.ɵɵconditional(ctx.Loading ? 5 : 6);
773
+ } }, dependencies: [CommonModule, i1.NgClass, FormsModule, i2.NgSelectOption, i2.ɵNgSelectMultipleOption, i2.DefaultValueAccessor, i2.CheckboxControlValueAccessor, i2.SelectControlValueAccessor, i2.NgControlStatus, i2.NgModel], styles: ["\n\n\n\n\n\n[_nghost-%COMP%] {\n display: block;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;\n color: #333;\n}\n\n.section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 16px;\n}\n\n.section-label[_ngcontent-%COMP%] {\n font-size: 15px;\n font-weight: 600;\n color: #333;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.section-label[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #1976d2;\n}\n\n.count[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #888;\n font-weight: 400;\n}\n\n\n\n.cm-flat-list[_ngcontent-%COMP%] {\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n overflow: hidden;\n}\n\n\n\n.cm-flat-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 10px 16px;\n border-bottom: 1px solid #f0f0f0;\n gap: 12px;\n transition: background 0.1s;\n}\n\n.cm-flat-row[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n.cm-flat-row[_ngcontent-%COMP%]:hover {\n background: #fafafa;\n}\n\n.cm-flat-row.primary[_ngcontent-%COMP%] {\n background: #f1f8e9;\n}\n\n\n\n.cm-flat-icon[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n font-size: 15px;\n flex-shrink: 0;\n}\n\n.cm-flat-icon.icon-email[_ngcontent-%COMP%] {\n background: #e3f2fd;\n color: #1565c0;\n}\n\n.cm-flat-icon.icon-phone[_ngcontent-%COMP%] {\n background: #e8f5e9;\n color: #2e7d32;\n}\n\n.cm-flat-icon.icon-mobile[_ngcontent-%COMP%] {\n background: #e8f5e9;\n color: #2e7d32;\n}\n\n.cm-flat-icon.icon-linkedin[_ngcontent-%COMP%] {\n background: #e3f2fd;\n color: #0077b5;\n}\n\n.cm-flat-icon.icon-twitter[_ngcontent-%COMP%] {\n background: #e8e8e8;\n color: #333;\n}\n\n.cm-flat-icon.icon-web[_ngcontent-%COMP%] {\n background: #fff3e0;\n color: #e65100;\n}\n\n.cm-flat-icon.icon-fax[_ngcontent-%COMP%] {\n background: #f3e5f5;\n color: #7b1fa2;\n}\n\n.cm-flat-icon.icon-default[_ngcontent-%COMP%] {\n background: #f5f5f5;\n color: #666;\n}\n\n\n\n.cm-flat-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.cm-flat-value[_ngcontent-%COMP%] {\n font-size: 14px;\n color: #333;\n cursor: pointer;\n}\n\n.cm-flat-value[_ngcontent-%COMP%]:hover {\n color: #1976d2;\n}\n\n.cm-flat-meta[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #888;\n margin-top: 1px;\n}\n\n\n\n.cm-flat-badges[_ngcontent-%COMP%] {\n display: flex;\n gap: 6px;\n flex-shrink: 0;\n}\n\n.badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.badge-primary[_ngcontent-%COMP%] {\n background: #e8f5e9;\n color: #2e7d32;\n}\n\n\n\n.cm-flat-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 2px;\n flex-shrink: 0;\n opacity: 0;\n transition: opacity 0.15s;\n}\n\n.cm-flat-row[_ngcontent-%COMP%]:hover .cm-flat-actions[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n\n\n.btn-ghost[_ngcontent-%COMP%] {\n background: transparent;\n color: #999;\n padding: 6px 8px;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n font-size: 13px;\n transition: all 0.15s ease;\n}\n\n.btn-ghost[_ngcontent-%COMP%]:hover {\n color: #333;\n background: #f5f5f5;\n}\n\n.btn-ghost.danger[_ngcontent-%COMP%]:hover {\n color: #c62828;\n background: #ffebee;\n}\n\n\n\n.cm-flat-add-form[_ngcontent-%COMP%] {\n padding: 14px 16px;\n background: #f8f9ff;\n border-top: 2px solid #1976d2;\n display: flex;\n gap: 10px;\n align-items: flex-end;\n flex-wrap: wrap;\n}\n\n\n\n.cm-flat-edit-row[_ngcontent-%COMP%] {\n padding: 14px 16px;\n background: #f8f9ff;\n border-bottom: 2px solid #1976d2;\n}\n\n.cm-flat-edit-row[_ngcontent-%COMP%] .form-row[_ngcontent-%COMP%] {\n display: flex;\n gap: 10px;\n align-items: flex-end;\n}\n\n\n\n.btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: none;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.btn-primary[_ngcontent-%COMP%] {\n background: #1976d2;\n color: white;\n}\n\n.btn-primary[_ngcontent-%COMP%]:hover {\n background: #1565c0;\n}\n\n.btn-cancel[_ngcontent-%COMP%] {\n background: #f5f5f5;\n color: #666;\n border: 1px solid #e0e0e0;\n}\n\n.btn-cancel[_ngcontent-%COMP%]:hover {\n background: #eeeeee;\n}\n\n.btn-sm[_ngcontent-%COMP%] {\n padding: 7px 14px;\n}\n\n\n\n.form-field[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n}\n\n.form-field.flex-1[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.form-field[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: block;\n font-size: 12px;\n font-weight: 600;\n color: #666;\n margin-bottom: 4px;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.form-field[_ngcontent-%COMP%] input[_ngcontent-%COMP%], \n.form-field[_ngcontent-%COMP%] select[_ngcontent-%COMP%] {\n width: 100%;\n padding: 8px 12px;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n font-size: 14px;\n font-family: inherit;\n background: white;\n}\n\n.form-field[_ngcontent-%COMP%] input[_ngcontent-%COMP%]:focus, \n.form-field[_ngcontent-%COMP%] select[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: #1976d2;\n box-shadow: 0 0 0 3px rgba(25, 118, 210, 0.1);\n}\n\n.form-field.type-field[_ngcontent-%COMP%] {\n max-width: 160px;\n}\n\n.form-field.label-field[_ngcontent-%COMP%] {\n max-width: 140px;\n}\n\n.checkbox-field[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding-top: 20px;\n}\n\n.checkbox-field[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n}\n\n.checkbox-field[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 13px;\n color: #555;\n cursor: pointer;\n}\n\n.form-actions[_ngcontent-%COMP%] {\n padding-top: 18px;\n display: flex;\n gap: 6px;\n}\n\n\n\n.copy-toast[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n background: #333;\n color: white;\n border-radius: 4px;\n font-size: 11px;\n margin-left: 8px;\n animation: _ngcontent-%COMP%_fadeInOut 1.5s ease-in-out;\n}\n\n@keyframes _ngcontent-%COMP%_fadeInOut {\n 0% { opacity: 0; }\n 15% { opacity: 1; }\n 70% { opacity: 1; }\n 100% { opacity: 0; }\n}\n\n\n\n.empty-state[_ngcontent-%COMP%] {\n text-align: center;\n padding: 32px 16px;\n color: #888;\n font-size: 14px;\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 24px;\n color: #ccc;\n margin-bottom: 8px;\n display: block;\n}\n\n\n\n.loading-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n color: #888;\n font-size: 13px;\n gap: 8px;\n}\n\n.loading-row[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_spin 1s linear infinite;\n}\n\n@keyframes _ngcontent-%COMP%_spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\n\n\n.cm-flat-footer[_ngcontent-%COMP%] {\n padding: 12px 16px;\n border-top: 1px solid #e0e0e0;\n background: #fafafa;\n}\n\n.btn-outline[_ngcontent-%COMP%] {\n background: transparent;\n border: 1px dashed #ccc;\n color: #666;\n}\n\n.btn-outline[_ngcontent-%COMP%]:hover {\n border-color: #1976d2;\n color: #1976d2;\n background: #f5f9ff;\n}\n\n.btn-outline.full-width[_ngcontent-%COMP%] {\n width: 100%;\n justify-content: center;\n}"] });
774
+ }
775
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ContactMethodListComponent, [{
776
+ type: Component,
777
+ args: [{ standalone: true, imports: [CommonModule, FormsModule], selector: 'bizapps-contact-method-list', template: "<!-- ContactMethodList - Flat List with Icons Design (Option B) -->\n\n<div class=\"section-header\">\n <span class=\"section-label\">\n <i class=\"fa-solid fa-address-card\"></i>\n Contact Methods\n @if (!Loading && ContactMethods.length > 0) {\n <span class=\"count\">({{ ContactMethods.length }})</span>\n }\n </span>\n</div>\n\n@if (Loading) {\n <div class=\"cm-flat-list\">\n <div class=\"loading-row\">\n <i class=\"fa-solid fa-spinner\"></i> Loading contacts...\n </div>\n </div>\n} @else {\n <div class=\"cm-flat-list\">\n @if (ContactMethods.length === 0 && !ShowAddForm) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-address-card\"></i>\n No contact methods yet\n </div>\n }\n\n @for (cm of ContactMethods; track cm.ID) {\n <!-- Edit mode for this row -->\n @if (EditingId === cm.ID) {\n <div class=\"cm-flat-edit-row\">\n <div class=\"form-row\">\n <div class=\"form-field type-field\">\n <label>Type</label>\n <select [(ngModel)]=\"EditForm.TypeID\">\n @for (t of ContactTypes; track t.ID) {\n <option [value]=\"t.ID\">{{ t.Name }}</option>\n }\n </select>\n </div>\n <div class=\"form-field flex-1\">\n <label>Value</label>\n <input type=\"text\" [(ngModel)]=\"EditForm.Value\" [placeholder]=\"getPlaceholder(EditForm.TypeID)\">\n </div>\n <div class=\"form-field label-field\">\n <label>Label</label>\n <input type=\"text\" [(ngModel)]=\"EditForm.Label\" placeholder=\"e.g., Work\">\n </div>\n <div class=\"checkbox-field\">\n <input type=\"checkbox\" [id]=\"'primary-edit-' + cm.ID\" [(ngModel)]=\"EditForm.IsPrimary\">\n <label [for]=\"'primary-edit-' + cm.ID\">Primary</label>\n </div>\n <div class=\"form-actions\">\n <button class=\"btn btn-primary btn-sm\" (click)=\"onSaveEdit()\" [disabled]=\"Saving\">\n @if (Saving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n }\n Save\n </button>\n <button class=\"btn btn-cancel btn-sm\" (click)=\"onCancelEdit()\">Cancel</button>\n </div>\n </div>\n </div>\n } @else {\n <!-- Display row -->\n <div class=\"cm-flat-row\" [class.primary]=\"cm.IsPrimary\">\n <div class=\"cm-flat-icon\" [ngClass]=\"getIconColorClass(cm.ContactTypeID)\">\n <i [class]=\"getContactTypeIcon(cm.ContactTypeID)\"></i>\n </div>\n <div class=\"cm-flat-content\">\n <div class=\"cm-flat-value\" (click)=\"onCopyValue(cm.Value)\">{{ cm.Value }}</div>\n <div class=\"cm-flat-meta\">{{ getContactMeta(cm) }}</div>\n </div>\n <div class=\"cm-flat-badges\">\n @if (cm.IsPrimary) {\n <span class=\"badge badge-primary\"><i class=\"fa-solid fa-star\"></i></span>\n }\n </div>\n <div class=\"cm-flat-actions\">\n @if (EditMode && !cm.IsPrimary) {\n <button class=\"btn-ghost\" title=\"Set Primary\" (click)=\"onSetPrimary(cm)\">\n <i class=\"fa-regular fa-star\"></i>\n </button>\n }\n @if (isLinkType(cm.ContactTypeID)) {\n <button class=\"btn-ghost\" title=\"Open\" (click)=\"onOpenLink(cm.Value)\">\n <i class=\"fa-solid fa-external-link\"></i>\n </button>\n } @else {\n <button class=\"btn-ghost\" title=\"Copy\" (click)=\"onCopyValue(cm.Value)\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n }\n @if (EditMode) {\n <button class=\"btn-ghost\" title=\"Edit\" (click)=\"onEdit(cm)\">\n <i class=\"fa-solid fa-pen\"></i>\n </button>\n <button class=\"btn-ghost danger\" title=\"Remove\" (click)=\"onDelete(cm)\">\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n }\n </div>\n </div>\n }\n }\n\n <!-- Add form -->\n @if (ShowAddForm) {\n <div class=\"cm-flat-add-form\">\n <div class=\"form-field type-field\">\n <label>Type</label>\n <select [(ngModel)]=\"AddForm.TypeID\">\n @for (t of ContactTypes; track t.ID) {\n <option [value]=\"t.ID\">{{ t.Name }}</option>\n }\n </select>\n </div>\n <div class=\"form-field flex-1\">\n <label>Value</label>\n <input type=\"text\" [(ngModel)]=\"AddForm.Value\" [placeholder]=\"getPlaceholder(AddForm.TypeID)\">\n </div>\n <div class=\"form-field label-field\">\n <label>Label</label>\n <input type=\"text\" [(ngModel)]=\"AddForm.Label\" placeholder=\"e.g., Direct Line\">\n </div>\n <div class=\"checkbox-field\">\n <input type=\"checkbox\" id=\"primary-add\" [(ngModel)]=\"AddForm.IsPrimary\">\n <label for=\"primary-add\">Primary</label>\n </div>\n <div class=\"form-actions\">\n <button class=\"btn btn-primary btn-sm\" (click)=\"onSaveAdd()\" [disabled]=\"Saving\">\n @if (Saving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n }\n Add\n </button>\n <button class=\"btn btn-cancel btn-sm\" (click)=\"onCancelAdd()\">Cancel</button>\n </div>\n </div>\n }\n\n <!-- Add button footer -->\n @if (!ShowAddForm && EditingId === null && EditMode) {\n <div class=\"cm-flat-footer\">\n <button class=\"btn btn-outline full-width\" (click)=\"onShowAdd()\">\n <i class=\"fa-solid fa-plus\"></i>\n Add Contact\n </button>\n </div>\n }\n </div>\n}\n", styles: ["/* ============================================\n ContactMethodList - Flat List with Icons Design\n Pixel-perfect match to Option B mockup\n ============================================ */\n\n:host {\n display: block;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;\n color: #333;\n}\n\n.section-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 16px;\n}\n\n.section-label {\n font-size: 15px;\n font-weight: 600;\n color: #333;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.section-label i {\n color: #1976d2;\n}\n\n.count {\n font-size: 12px;\n color: #888;\n font-weight: 400;\n}\n\n/* Flat list container */\n.cm-flat-list {\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n overflow: hidden;\n}\n\n/* Row */\n.cm-flat-row {\n display: flex;\n align-items: center;\n padding: 10px 16px;\n border-bottom: 1px solid #f0f0f0;\n gap: 12px;\n transition: background 0.1s;\n}\n\n.cm-flat-row:last-child {\n border-bottom: none;\n}\n\n.cm-flat-row:hover {\n background: #fafafa;\n}\n\n.cm-flat-row.primary {\n background: #f1f8e9;\n}\n\n/* Icon */\n.cm-flat-icon {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n font-size: 15px;\n flex-shrink: 0;\n}\n\n.cm-flat-icon.icon-email {\n background: #e3f2fd;\n color: #1565c0;\n}\n\n.cm-flat-icon.icon-phone {\n background: #e8f5e9;\n color: #2e7d32;\n}\n\n.cm-flat-icon.icon-mobile {\n background: #e8f5e9;\n color: #2e7d32;\n}\n\n.cm-flat-icon.icon-linkedin {\n background: #e3f2fd;\n color: #0077b5;\n}\n\n.cm-flat-icon.icon-twitter {\n background: #e8e8e8;\n color: #333;\n}\n\n.cm-flat-icon.icon-web {\n background: #fff3e0;\n color: #e65100;\n}\n\n.cm-flat-icon.icon-fax {\n background: #f3e5f5;\n color: #7b1fa2;\n}\n\n.cm-flat-icon.icon-default {\n background: #f5f5f5;\n color: #666;\n}\n\n/* Content */\n.cm-flat-content {\n flex: 1;\n min-width: 0;\n}\n\n.cm-flat-value {\n font-size: 14px;\n color: #333;\n cursor: pointer;\n}\n\n.cm-flat-value:hover {\n color: #1976d2;\n}\n\n.cm-flat-meta {\n font-size: 12px;\n color: #888;\n margin-top: 1px;\n}\n\n/* Badges */\n.cm-flat-badges {\n display: flex;\n gap: 6px;\n flex-shrink: 0;\n}\n\n.badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.badge-primary {\n background: #e8f5e9;\n color: #2e7d32;\n}\n\n/* Actions */\n.cm-flat-actions {\n display: flex;\n gap: 2px;\n flex-shrink: 0;\n opacity: 0;\n transition: opacity 0.15s;\n}\n\n.cm-flat-row:hover .cm-flat-actions {\n opacity: 1;\n}\n\n/* Ghost buttons */\n.btn-ghost {\n background: transparent;\n color: #999;\n padding: 6px 8px;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n font-size: 13px;\n transition: all 0.15s ease;\n}\n\n.btn-ghost:hover {\n color: #333;\n background: #f5f5f5;\n}\n\n.btn-ghost.danger:hover {\n color: #c62828;\n background: #ffebee;\n}\n\n/* Add form */\n.cm-flat-add-form {\n padding: 14px 16px;\n background: #f8f9ff;\n border-top: 2px solid #1976d2;\n display: flex;\n gap: 10px;\n align-items: flex-end;\n flex-wrap: wrap;\n}\n\n/* Edit inline row */\n.cm-flat-edit-row {\n padding: 14px 16px;\n background: #f8f9ff;\n border-bottom: 2px solid #1976d2;\n}\n\n.cm-flat-edit-row .form-row {\n display: flex;\n gap: 10px;\n align-items: flex-end;\n}\n\n/* Buttons */\n.btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: none;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.btn-primary {\n background: #1976d2;\n color: white;\n}\n\n.btn-primary:hover {\n background: #1565c0;\n}\n\n.btn-cancel {\n background: #f5f5f5;\n color: #666;\n border: 1px solid #e0e0e0;\n}\n\n.btn-cancel:hover {\n background: #eeeeee;\n}\n\n.btn-sm {\n padding: 7px 14px;\n}\n\n/* Form fields */\n.form-field {\n display: flex;\n flex-direction: column;\n}\n\n.form-field.flex-1 {\n flex: 1;\n}\n\n.form-field label {\n display: block;\n font-size: 12px;\n font-weight: 600;\n color: #666;\n margin-bottom: 4px;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.form-field input,\n.form-field select {\n width: 100%;\n padding: 8px 12px;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n font-size: 14px;\n font-family: inherit;\n background: white;\n}\n\n.form-field input:focus,\n.form-field select:focus {\n outline: none;\n border-color: #1976d2;\n box-shadow: 0 0 0 3px rgba(25, 118, 210, 0.1);\n}\n\n.form-field.type-field {\n max-width: 160px;\n}\n\n.form-field.label-field {\n max-width: 140px;\n}\n\n.checkbox-field {\n display: flex;\n align-items: center;\n gap: 8px;\n padding-top: 20px;\n}\n\n.checkbox-field input[type=\"checkbox\"] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n}\n\n.checkbox-field label {\n font-size: 13px;\n color: #555;\n cursor: pointer;\n}\n\n.form-actions {\n padding-top: 18px;\n display: flex;\n gap: 6px;\n}\n\n/* Copy toast */\n.copy-toast {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n background: #333;\n color: white;\n border-radius: 4px;\n font-size: 11px;\n margin-left: 8px;\n animation: fadeInOut 1.5s ease-in-out;\n}\n\n@keyframes fadeInOut {\n 0% { opacity: 0; }\n 15% { opacity: 1; }\n 70% { opacity: 1; }\n 100% { opacity: 0; }\n}\n\n/* Empty state */\n.empty-state {\n text-align: center;\n padding: 32px 16px;\n color: #888;\n font-size: 14px;\n}\n\n.empty-state i {\n font-size: 24px;\n color: #ccc;\n margin-bottom: 8px;\n display: block;\n}\n\n/* Loading */\n.loading-row {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n color: #888;\n font-size: 13px;\n gap: 8px;\n}\n\n.loading-row i {\n animation: spin 1s linear infinite;\n}\n\n@keyframes spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\n/* Footer add button area */\n.cm-flat-footer {\n padding: 12px 16px;\n border-top: 1px solid #e0e0e0;\n background: #fafafa;\n}\n\n.btn-outline {\n background: transparent;\n border: 1px dashed #ccc;\n color: #666;\n}\n\n.btn-outline:hover {\n border-color: #1976d2;\n color: #1976d2;\n background: #f5f9ff;\n}\n\n.btn-outline.full-width {\n width: 100%;\n justify-content: center;\n}\n"] }]
778
+ }], null, { EditMode: [{
779
+ type: Input
780
+ }], DataChanged: [{
781
+ type: Output
782
+ }], PersonID: [{
783
+ type: Input
784
+ }], OrganizationID: [{
785
+ type: Input
786
+ }] }); })();
787
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ContactMethodListComponent, { className: "ContactMethodListComponent", filePath: "lib/components/contact-method-list/contact-method-list.component.ts", lineNumber: 65 }); })();
788
+ //# sourceMappingURL=contact-method-list.component.js.map