@visns-studio/visns-components 5.10.11 → 5.11.2

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 (55) hide show
  1. package/README.md +85 -0
  2. package/package.json +7 -7
  3. package/src/components/cms/DataGrid.jsx +8 -8
  4. package/src/components/cms/DropZone.jsx +1 -1
  5. package/src/components/cms/Form.jsx +1 -1
  6. package/src/components/cms/Gallery.jsx +1 -1
  7. package/src/components/cms/sorting/Item.jsx +1 -1
  8. package/src/components/crm/Autocomplete.jsx +3 -3
  9. package/src/components/crm/Breadcrumb.jsx +4 -4
  10. package/src/components/crm/BusinessCardOcr.jsx +681 -95
  11. package/src/components/crm/DataGrid.jsx +34 -32
  12. package/src/components/crm/Field.jsx +12 -12
  13. package/src/components/crm/Form.jsx +2 -2
  14. package/src/components/crm/Navigation.jsx +11 -11
  15. package/src/components/crm/Notification.jsx +2 -2
  16. package/src/components/crm/QuickAction.jsx +3 -3
  17. package/src/components/crm/SectionHeader.jsx +1 -1
  18. package/src/components/crm/SwitchAccount.jsx +4 -4
  19. package/src/components/crm/auth/ClientLogin.jsx +2 -2
  20. package/src/components/crm/auth/ClientOTPVerify.jsx +2 -2
  21. package/src/components/crm/auth/Login.jsx +3 -3
  22. package/src/components/crm/auth/Reset.jsx +2 -2
  23. package/src/components/crm/auth/TwoFactorAuth.jsx +2 -2
  24. package/src/components/crm/columns/ColumnRenderers.jsx +320 -259
  25. package/src/components/crm/controls/DataGridSearch.jsx +5 -5
  26. package/src/components/crm/generic/AlternativeActionModal.jsx +100 -0
  27. package/src/components/crm/generic/ContactSelectorModal.jsx +423 -0
  28. package/src/components/crm/generic/DatePickerDialog.jsx +302 -0
  29. package/src/components/crm/generic/DateRangeSelectorModal.jsx +181 -0
  30. package/src/components/crm/generic/GenericClientPortal.jsx +1 -1
  31. package/src/components/crm/generic/GenericDashboard.jsx +4 -4
  32. package/src/components/crm/generic/GenericDetail.jsx +6 -6
  33. package/src/components/crm/generic/GenericDynamic.jsx +3 -3
  34. package/src/components/crm/generic/GenericEditableTable.jsx +4 -4
  35. package/src/components/crm/generic/GenericFormBuilder.jsx +6 -6
  36. package/src/components/crm/generic/GenericGrid.jsx +2888 -0
  37. package/src/components/crm/generic/GenericIndex.jsx +5 -1255
  38. package/src/components/crm/generic/GenericReport.jsx +966 -646
  39. package/src/components/crm/generic/GenericReportForm.jsx +194 -0
  40. package/src/components/crm/generic/NotificationList.jsx +1 -1
  41. package/src/components/crm/generic/ReasonCollectorModal.jsx +194 -0
  42. package/src/components/crm/generic/SortableQuoteItems.jsx +3 -3
  43. package/src/components/crm/generic/shared/formatters.js +231 -0
  44. package/src/components/crm/generic/shared/gridUtils.js +194 -0
  45. package/src/components/crm/generic/styles/AlternativeActionModal.css +127 -0
  46. package/src/components/crm/generic/styles/ContactSelectorModal.css +367 -0
  47. package/src/components/crm/generic/styles/DatePickerDialog.css +84 -0
  48. package/src/components/crm/generic/styles/DateRangeSelectorModal.css +115 -0
  49. package/src/components/crm/generic/styles/GenericIndex.module.scss +382 -0
  50. package/src/components/crm/generic/styles/GenericReport.module.scss +96 -0
  51. package/src/components/crm/generic/styles/ReasonCollectorModal.css +217 -0
  52. package/src/components/crm/modals/GalleryModal.jsx +2 -2
  53. package/src/components/crm/sorting/Item.jsx +3 -3
  54. package/src/components/crm/styles/BusinessCardOcr.module.scss +197 -4
  55. package/src/index.js +4 -0
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Sort data based on column configuration
3
+ * @param {Array} data - Data array to sort
4
+ * @param {string} key - Column key to sort by
5
+ * @param {string} direction - Sort direction ('asc' or 'desc')
6
+ * @param {Array} gridHeaders - Grid headers configuration
7
+ * @returns {Array} Sorted data array
8
+ */
9
+ export const sortData = (data, key, direction, gridHeaders) => {
10
+ if (!key) return [...data];
11
+
12
+ return [...data].sort((a, b) => {
13
+ // Find the header config for this key to determine type
14
+ const headerConfig = gridHeaders.find((h) => h.key === key);
15
+ const type = headerConfig?.type || 'text';
16
+
17
+ // Get values, handling null/undefined
18
+ let aValue = a[key] === null || a[key] === undefined ? '' : a[key];
19
+ let bValue = b[key] === null || b[key] === undefined ? '' : b[key];
20
+
21
+ // Sort based on type
22
+ switch (type) {
23
+ case 'number':
24
+ case 'year':
25
+ aValue = parseFloat(aValue) || 0;
26
+ bValue = parseFloat(bValue) || 0;
27
+ break;
28
+ case 'date':
29
+ // Convert to timestamp for comparison
30
+ aValue = aValue ? new Date(aValue).getTime() : 0;
31
+ bValue = bValue ? new Date(bValue).getTime() : 0;
32
+ break;
33
+ default:
34
+ // For text, convert to lowercase strings
35
+ aValue = String(aValue).toLowerCase();
36
+ bValue = String(bValue).toLowerCase();
37
+ }
38
+
39
+ // Compare values
40
+ if (aValue < bValue) {
41
+ return direction === 'asc' ? -1 : 1;
42
+ }
43
+ if (aValue > bValue) {
44
+ return direction === 'asc' ? 1 : -1;
45
+ }
46
+ return 0;
47
+ });
48
+ };
49
+
50
+ /**
51
+ * Filter data based on filter values and configuration
52
+ * @param {Array} data - Data array to filter
53
+ * @param {Object} filterValues - Filter values object
54
+ * @param {Array} gridHeaders - Grid headers configuration
55
+ * @returns {Array} Filtered data array
56
+ */
57
+ export const filterData = (data, filterValues, gridHeaders) => {
58
+ // If no filter values are set, return the original data
59
+ if (Object.keys(filterValues).length === 0) {
60
+ return data;
61
+ }
62
+
63
+ // Filter the data based on the filter values
64
+ return data.filter((row) => {
65
+ // Check each filter
66
+ return Object.entries(filterValues).every(([key, value]) => {
67
+ // Skip empty filter values
68
+ if (!value) return true;
69
+
70
+ // Get the row value
71
+ const rowValue = row[key];
72
+ if (rowValue === null || rowValue === undefined) return false;
73
+
74
+ // Find the header config for this key
75
+ const headerConfig = gridHeaders.find((h) => h.key === key);
76
+ if (!headerConfig || !headerConfig.filter) return true;
77
+
78
+ const { type, operator } = headerConfig.filter;
79
+
80
+ // Apply filter based on type and operator
81
+ switch (type) {
82
+ case 'string':
83
+ const rowStr = String(rowValue).toLowerCase();
84
+ const filterStr = String(value).toLowerCase();
85
+
86
+ switch (operator) {
87
+ case 'equals':
88
+ return rowStr === filterStr;
89
+ case 'contains':
90
+ return rowStr.includes(filterStr);
91
+ case 'startsWith':
92
+ return rowStr.startsWith(filterStr);
93
+ case 'endsWith':
94
+ return rowStr.endsWith(filterStr);
95
+ default:
96
+ return rowStr.includes(filterStr);
97
+ }
98
+
99
+ case 'number':
100
+ const rowNum = parseFloat(rowValue);
101
+ const filterNum = parseFloat(value);
102
+
103
+ if (isNaN(rowNum) || isNaN(filterNum)) return false;
104
+
105
+ switch (operator) {
106
+ case 'equals':
107
+ return rowNum === filterNum;
108
+ case 'greaterThan':
109
+ return rowNum > filterNum;
110
+ case 'lessThan':
111
+ return rowNum < filterNum;
112
+ case 'greaterThanOrEqual':
113
+ return rowNum >= filterNum;
114
+ case 'lessThanOrEqual':
115
+ return rowNum <= filterNum;
116
+ default:
117
+ return rowNum === filterNum;
118
+ }
119
+
120
+ case 'date':
121
+ const rowDate = new Date(rowValue);
122
+ const filterDate = new Date(value);
123
+
124
+ if (isNaN(rowDate.getTime()) || isNaN(filterDate.getTime()))
125
+ return false;
126
+
127
+ switch (operator) {
128
+ case 'equals':
129
+ return (
130
+ rowDate.toDateString() ===
131
+ filterDate.toDateString()
132
+ );
133
+ case 'after':
134
+ return rowDate > filterDate;
135
+ case 'before':
136
+ return rowDate < filterDate;
137
+ default:
138
+ return (
139
+ rowDate.toDateString() ===
140
+ filterDate.toDateString()
141
+ );
142
+ }
143
+
144
+ default:
145
+ return true;
146
+ }
147
+ });
148
+ });
149
+ };
150
+
151
+ /**
152
+ * Transform headers from API response to grid headers format
153
+ * @param {Object} headerData - Header data from API response
154
+ * @returns {Array} Formatted grid headers array
155
+ */
156
+ export const transformApiHeaders = (headerData) => {
157
+ const headerEntries = Object.entries(headerData);
158
+ return headerEntries.map(([key, config]) => ({
159
+ key,
160
+ label: config.label || key,
161
+ sort: config.sort || key,
162
+ type: config.type || 'text',
163
+ filter: config.filter || null,
164
+ onClick: config.onClick || null,
165
+ }));
166
+ };
167
+
168
+ /**
169
+ * Initialize filter values from grid headers
170
+ * @param {Array} gridHeaders - Grid headers array
171
+ * @returns {Object} Initial filter values object
172
+ */
173
+ export const initializeFilterValues = (gridHeaders) => {
174
+ const initialFilterValues = {};
175
+ gridHeaders.forEach((header) => {
176
+ if (header.filter) {
177
+ initialFilterValues[header.key] = '';
178
+ }
179
+ });
180
+ return initialFilterValues;
181
+ };
182
+
183
+ /**
184
+ * Get sort indicator style based on current sort configuration
185
+ * @param {string} key - Column key
186
+ * @param {Object} sortConfig - Current sort configuration
187
+ * @returns {Object} Style object for sort indicator
188
+ */
189
+ export const getSortIndicatorStyle = (key, sortConfig) => {
190
+ if (sortConfig.key !== key) {
191
+ return { opacity: 0.3 }; // Dim the icon when not sorting by this column
192
+ }
193
+ return {}; // Full opacity when sorting by this column
194
+ };
@@ -0,0 +1,127 @@
1
+ /* Alternative Action Modal Styles */
2
+ .alternative-action-modal {
3
+ text-align: center;
4
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
5
+ }
6
+
7
+ .alternative-message {
8
+ margin-bottom: 24px;
9
+ color: #4a5568;
10
+ font-size: 16px;
11
+ line-height: 1.5;
12
+ }
13
+
14
+ .alternative-options {
15
+ display: flex;
16
+ flex-direction: column;
17
+ gap: 12px;
18
+ margin: 20px 0;
19
+ }
20
+
21
+ .alternative-action-option {
22
+ display: flex;
23
+ align-items: center;
24
+ padding: 16px 20px;
25
+ border: 2px solid #e2e8f0;
26
+ border-radius: 12px;
27
+ cursor: pointer;
28
+ transition: all 0.2s ease;
29
+ background-color: #ffffff;
30
+ text-align: left;
31
+ }
32
+
33
+ .alternative-action-option:hover {
34
+ border-color: #4299e1;
35
+ background-color: #f7fafc;
36
+ transform: translateY(-1px);
37
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
38
+ }
39
+
40
+ .alternative-action-option:active {
41
+ transform: translateY(0);
42
+ }
43
+
44
+ .alternative-icon {
45
+ font-size: 24px;
46
+ margin-right: 16px;
47
+ min-width: 32px;
48
+ text-align: center;
49
+ }
50
+
51
+ .alternative-content {
52
+ flex: 1;
53
+ }
54
+
55
+ .alternative-label {
56
+ font-weight: 600;
57
+ color: #2d3748;
58
+ font-size: 16px;
59
+ margin-bottom: 4px;
60
+ }
61
+
62
+ .alternative-description {
63
+ font-size: 14px;
64
+ color: #718096;
65
+ line-height: 1.4;
66
+ }
67
+
68
+ /* SweetAlert2 custom classes */
69
+ .alternative-swal-container {
70
+ z-index: 10000;
71
+ }
72
+
73
+ .alternative-swal-popup {
74
+ border-radius: 16px;
75
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
76
+ max-width: 480px;
77
+ }
78
+
79
+ .alternative-swal-content {
80
+ padding: 24px;
81
+ }
82
+
83
+ .alternative-swal-cancel {
84
+ background-color: #e2e8f0 !important;
85
+ color: #4a5568 !important;
86
+ border: none !important;
87
+ border-radius: 8px !important;
88
+ font-weight: 600 !important;
89
+ padding: 12px 24px !important;
90
+ font-size: 14px !important;
91
+ }
92
+
93
+ .alternative-swal-cancel:hover {
94
+ background-color: #cbd5e0 !important;
95
+ }
96
+
97
+ /* Responsive design */
98
+ @media (max-width: 640px) {
99
+ .alternative-action-option {
100
+ padding: 14px 16px;
101
+ }
102
+
103
+ .alternative-icon {
104
+ font-size: 20px;
105
+ margin-right: 12px;
106
+ min-width: 28px;
107
+ }
108
+
109
+ .alternative-label {
110
+ font-size: 15px;
111
+ }
112
+
113
+ .alternative-description {
114
+ font-size: 13px;
115
+ }
116
+
117
+ .alternative-options {
118
+ gap: 10px;
119
+ }
120
+ }
121
+
122
+ /* Focus styles for accessibility */
123
+ .alternative-action-option:focus {
124
+ outline: none;
125
+ border-color: #4299e1;
126
+ box-shadow: 0 0 0 3px rgba(66, 153, 225, 0.1);
127
+ }
@@ -0,0 +1,367 @@
1
+ /* Contact Selector Modal Styles */
2
+
3
+ .contact-selector-dialog {
4
+ max-width: 90vw !important;
5
+ width: 600px !important;
6
+ min-width: 400px !important;
7
+ }
8
+
9
+ .contact-selector-content {
10
+ max-width: 100% !important;
11
+ overflow: hidden !important;
12
+ }
13
+
14
+ .contact-selector-modal {
15
+ text-align: left;
16
+ font-family: inherit;
17
+ }
18
+
19
+ .contact-modal-header {
20
+ margin-bottom: 15px;
21
+ padding-bottom: 10px;
22
+ border-bottom: 1px solid #e5e7eb;
23
+ }
24
+
25
+ .contact-modal-message {
26
+ margin: 0 0 8px 0;
27
+ color: #374151;
28
+ font-size: 14px;
29
+ }
30
+
31
+ .field-info {
32
+ color: #6b7280;
33
+ font-size: 12px;
34
+ }
35
+
36
+ /* Existing contacts section */
37
+ .existing-contacts {
38
+ margin-bottom: 18px;
39
+ }
40
+
41
+ .existing-contacts h4 {
42
+ margin: 0 0 8px 0;
43
+ font-size: 13px;
44
+ font-weight: 600;
45
+ color: #374151;
46
+ }
47
+
48
+ .contacts-list {
49
+ max-height: 180px;
50
+ overflow-y: auto;
51
+ border: 1px solid #e5e7eb;
52
+ border-radius: 4px;
53
+ padding: 6px;
54
+ background-color: #f9fafb;
55
+ }
56
+
57
+ .contact-item {
58
+ display: flex;
59
+ justify-content: space-between;
60
+ align-items: flex-start;
61
+ padding: 8px;
62
+ margin-bottom: 6px;
63
+ background-color: #ffffff;
64
+ border: 1px solid #e5e7eb;
65
+ border-radius: 4px;
66
+ position: relative;
67
+ }
68
+
69
+ .contact-item:last-child {
70
+ margin-bottom: 0;
71
+ }
72
+
73
+ .contact-info {
74
+ flex: 1;
75
+ min-width: 0;
76
+ }
77
+
78
+ .contact-info strong {
79
+ color: #111827;
80
+ font-weight: 500;
81
+ display: block;
82
+ margin-bottom: 2px;
83
+ }
84
+
85
+ .contact-info small {
86
+ color: #6b7280;
87
+ font-size: 12px;
88
+ }
89
+
90
+ .contact-type {
91
+ display: inline-block;
92
+ background-color: #dbeafe;
93
+ color: #1e40af;
94
+ padding: 2px 6px;
95
+ border-radius: 10px;
96
+ font-size: 10px;
97
+ font-weight: 500;
98
+ margin-top: 4px;
99
+ }
100
+
101
+ .contact-item .contact-type {
102
+ position: absolute;
103
+ top: 8px;
104
+ right: 35px;
105
+ }
106
+
107
+ .remove-contact-btn {
108
+ background-color: #dc2626;
109
+ color: white;
110
+ border: none;
111
+ border-radius: 50%;
112
+ width: 24px;
113
+ height: 24px;
114
+ font-size: 14px;
115
+ font-weight: bold;
116
+ cursor: pointer;
117
+ display: flex;
118
+ align-items: center;
119
+ justify-content: center;
120
+ flex-shrink: 0;
121
+ transition: background-color 0.2s ease;
122
+ }
123
+
124
+ .remove-contact-btn:hover {
125
+ background-color: #b91c1c;
126
+ }
127
+
128
+ .no-contacts {
129
+ text-align: center;
130
+ color: #6b7280;
131
+ font-style: italic;
132
+ margin: 0;
133
+ padding: 20px;
134
+ }
135
+
136
+ /* Add contact section */
137
+ .add-contact-section {
138
+ border-top: 1px solid #e5e7eb;
139
+ padding-top: 15px;
140
+ }
141
+
142
+ .add-contact-section h4 {
143
+ margin: 0 0 10px 0;
144
+ font-size: 13px;
145
+ font-weight: 600;
146
+ color: #374151;
147
+ }
148
+
149
+ .existing-contact-selector {
150
+ margin-bottom: 15px;
151
+ padding: 12px;
152
+ background-color: #f9fafb;
153
+ border-radius: 6px;
154
+ border: 1px solid #e5e7eb;
155
+ }
156
+
157
+ .existing-contact-selector label {
158
+ display: block;
159
+ margin-bottom: 6px;
160
+ font-weight: 500;
161
+ color: #374151;
162
+ font-size: 12px;
163
+ }
164
+
165
+ .contact-select-row {
166
+ display: flex;
167
+ gap: 8px;
168
+ align-items: flex-end;
169
+ }
170
+
171
+ .existing-contact-selector select {
172
+ flex: 1;
173
+ margin: 0 !important;
174
+ padding: 6px 10px !important;
175
+ border: 1px solid #d1d5db !important;
176
+ border-radius: 4px !important;
177
+ font-size: 13px !important;
178
+ background-color: white !important;
179
+ height: 32px !important;
180
+ min-width: 0;
181
+ }
182
+
183
+ .add-contact-btn {
184
+ background-color: #4f46e5;
185
+ color: white;
186
+ border: none;
187
+ padding: 6px 12px;
188
+ border-radius: 4px;
189
+ font-size: 12px;
190
+ font-weight: 500;
191
+ cursor: pointer;
192
+ transition: background-color 0.2s ease;
193
+ height: 32px;
194
+ white-space: nowrap;
195
+ flex-shrink: 0;
196
+ }
197
+
198
+ .add-contact-btn:hover {
199
+ background-color: #4338ca;
200
+ }
201
+
202
+ .add-contact-btn:disabled {
203
+ background-color: #9ca3af;
204
+ cursor: not-allowed;
205
+ }
206
+
207
+ /* Manual contact section */
208
+ .manual-contact-section {
209
+ border-top: 1px solid #e5e7eb;
210
+ padding-top: 12px;
211
+ }
212
+
213
+ .manual-contact-toggle {
214
+ margin-bottom: 10px;
215
+ }
216
+
217
+ .toggle-manual-btn {
218
+ background-color: #6b7280;
219
+ color: white;
220
+ border: none;
221
+ padding: 8px 16px;
222
+ border-radius: 4px;
223
+ font-size: 12px;
224
+ cursor: pointer;
225
+ transition: background-color 0.2s ease;
226
+ }
227
+
228
+ .toggle-manual-btn:hover {
229
+ background-color: #4b5563;
230
+ }
231
+
232
+ .manual-contact-form {
233
+ padding: 12px;
234
+ background-color: #f9fafb;
235
+ border-radius: 6px;
236
+ border: 1px solid #e5e7eb;
237
+ }
238
+
239
+ .form-group {
240
+ margin-bottom: 10px;
241
+ }
242
+
243
+ .form-group:last-child {
244
+ margin-bottom: 0;
245
+ }
246
+
247
+ .form-field-row {
248
+ display: flex;
249
+ gap: 8px;
250
+ align-items: center;
251
+ }
252
+
253
+ .form-group label {
254
+ font-weight: 500;
255
+ color: #374151;
256
+ font-size: 12px;
257
+ white-space: nowrap;
258
+ min-width: 60px;
259
+ flex-shrink: 0;
260
+ }
261
+
262
+ .form-group input {
263
+ flex: 1;
264
+ margin: 0 !important;
265
+ padding: 6px 10px !important;
266
+ border: 1px solid #d1d5db !important;
267
+ border-radius: 4px !important;
268
+ font-size: 13px !important;
269
+ box-sizing: border-box !important;
270
+ height: 32px !important;
271
+ min-width: 0;
272
+ }
273
+
274
+ .form-group input:focus {
275
+ border-color: #4f46e5 !important;
276
+ outline: none !important;
277
+ box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1) !important;
278
+ }
279
+
280
+ .form-group input[style*="border-color: rgb(220, 38, 38)"] {
281
+ border-color: #dc2626 !important;
282
+ }
283
+
284
+ /* Contact limits */
285
+ .contact-limits {
286
+ margin-top: 15px;
287
+ text-align: center;
288
+ }
289
+
290
+ .contact-limits small {
291
+ color: #6b7280;
292
+ font-size: 11px;
293
+ }
294
+
295
+ /* Responsive design */
296
+ @media (max-width: 640px) {
297
+ .contact-selector-dialog {
298
+ width: 95vw !important;
299
+ max-width: 95vw !important;
300
+ min-width: 300px !important;
301
+ }
302
+
303
+ .contact-select-row {
304
+ flex-direction: column;
305
+ gap: 6px;
306
+ align-items: stretch;
307
+ }
308
+
309
+ .existing-contact-selector select {
310
+ margin-bottom: 6px !important;
311
+ }
312
+
313
+ .add-contact-btn {
314
+ width: 100%;
315
+ height: 36px;
316
+ }
317
+
318
+ .form-field-row {
319
+ flex-direction: column;
320
+ gap: 4px;
321
+ align-items: stretch;
322
+ }
323
+
324
+ .form-group label {
325
+ min-width: auto;
326
+ margin-bottom: 4px;
327
+ }
328
+
329
+ .form-group input {
330
+ height: 36px !important;
331
+ }
332
+
333
+ .contact-item {
334
+ flex-direction: column;
335
+ align-items: flex-start;
336
+ }
337
+
338
+ .contact-type {
339
+ position: static !important;
340
+ margin-top: 8px;
341
+ }
342
+
343
+ .remove-contact-btn {
344
+ position: absolute;
345
+ top: 8px;
346
+ right: 8px;
347
+ }
348
+ }
349
+
350
+ /* Integration with SweetAlert2 */
351
+ .contact-selector-dialog .swal2-html-container {
352
+ margin: 0 !important;
353
+ padding: 0 !important;
354
+ overflow: visible !important;
355
+ }
356
+
357
+ .contact-selector-dialog .swal2-actions {
358
+ margin-top: 20px !important;
359
+ }
360
+
361
+ .contact-selector-dialog .swal2-confirm {
362
+ background-color: var(--primary-color, #4f46e5) !important;
363
+ }
364
+
365
+ .contact-selector-dialog .swal2-cancel {
366
+ background-color: #6b7280 !important;
367
+ }