@chat21/chat21-web-widget 5.1.8-ar → 5.1.9-ar

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,9 @@
6
6
  ### **Copyrigth**:
7
7
  *Tiledesk SRL*
8
8
 
9
+ # 5.1.9-ar
10
+ - **bug-fixed**: set default widget size
11
+
9
12
  # 5.1.8-ar
10
13
  - **changed**: update emoji detection logic in conversation-footer and utils
11
14
  - **bug-fixed**: 'DOMAIN_NOT_ALLOWED' in textarea footer component
@@ -23,6 +26,9 @@
23
26
  # 5.1.7-rc6
24
27
  - **added**: Added MAX_ATTACHMENT_ERROR error message when uploading a file larger than 10 MB
25
28
 
29
+ # this branch
30
+ - **bug-fixed**: set the color of the buttons with visibility control to the font color (setButtonColors function)
31
+
26
32
  # 5.1.7-rc5
27
33
  - **bug-fixed**: bug fixed BUTTON STYLES
28
34
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@chat21/chat21-web-widget",
3
3
  "author": "Tiledesk SRL",
4
- "version": "5.1.8-ar",
4
+ "version": "5.1.9-ar",
5
5
  "license": "MIT",
6
6
  "homepage": "https://www.tiledesk.com",
7
7
  "repository": {
@@ -401,9 +401,11 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
401
401
  this.triggerLoadParamsEvent(); // first trigger
402
402
  //this.setAvailableAgentsStatus();
403
403
 
404
-
405
404
  /** NETWORK STATUS */
406
- this.listenToNetworkStatus()
405
+ this.listenToNetworkStatus();
406
+
407
+ /** SET WIDGET SIZE */
408
+ this.onWidgetSizeChange(this.g.size);
407
409
 
408
410
  }
409
411
 
@@ -727,7 +729,7 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
727
729
  // visualizzo l'iframe!!!
728
730
  this.triggerOnViewInit();
729
731
  this.g.setParentBodyStyleMobile(this.g.isOpen, this.g.isMobile);
730
- this.g.setElementStyle(this.g.isOpen)
732
+ this.g.setElementStyle(this.g.isOpen);
731
733
  // this.triggerOnAuthStateChanged(true)
732
734
  // mostro il widget
733
735
  // setTimeout(() => {
@@ -1,4 +1,5 @@
1
1
  import { Component, ElementRef, EventEmitter, Input, OnInit, Output, SimpleChanges } from '@angular/core';
2
+ import { getColorBck } from 'src/chat21-core/utils/utils-user';
2
3
 
3
4
  @Component({
4
5
  selector: 'chat-action-button-attachment',
@@ -26,9 +27,10 @@ export class ActionButtonComponent implements OnInit {
26
27
  //decomment if element should have same color of themeColor and fregroundColor
27
28
  if(this.fontSize) this.elementRef.nativeElement.querySelector('.action').style.setProperty('--buttonFontSize', this.fontSize);
28
29
  if(this.backgroundColor) this.elementRef.nativeElement.querySelector('.action').style.setProperty('--buttonBackgroundColor', this.backgroundColor);
29
- if(this.textColor) this.elementRef.nativeElement.querySelector('.action').style.setProperty('--textColor', this.textColor);
30
+ if(this.textColor) this.elementRef.nativeElement.querySelector('.action').style.setProperty('--buttonTextColor', this.textColor);
30
31
  if(this.hoverBackgroundColor) this.elementRef.nativeElement.querySelector('.action').style.setProperty('--hoverBackgroundColor', this.hoverBackgroundColor);
31
32
  if(this.hoverTextColor) this.elementRef.nativeElement.querySelector('.action').style.setProperty('--hoverTextColor', this.hoverTextColor);
33
+
32
34
  }
33
35
 
34
36
  onMouseOver(event){
@@ -10,7 +10,7 @@ import { TemplateBindingParseResult } from '@angular/compiler';
10
10
  import { AppStorageService } from '../../chat21-core/providers/abstract/app-storage.service';
11
11
  import { LoggerService } from '../../chat21-core/providers/abstract/logger.service';
12
12
  import { LoggerInstance } from '../../chat21-core/providers/logger/loggerInstance';
13
- import { invertColor, isAllowedUrlInText, isJsonArray } from '../../chat21-core/utils/utils';
13
+ import { ensureAccessibleTextColor, invertColor, isAllowedUrlInText, isJsonArray, normalizeColorToHex } from '../../chat21-core/utils/utils';
14
14
  import { AppConfigService } from './app-config.service';
15
15
 
16
16
 
@@ -322,10 +322,14 @@ export class GlobalSettingsService {
322
322
  if (response !== null) {
323
323
  this.setVariablesFromService(this.globals, response);
324
324
  }
325
+ /** set button colors */
326
+ this.setButtonColors();
327
+
325
328
  this.setVariableFromStorage(this.globals);
326
329
  this.setVariablesFromSettings(this.globals);
327
330
  this.setVariablesFromAttributeHtml(this.globals, this.el);
328
331
  this.setVariablesFromUrlParameters(this.globals);
332
+
329
333
  this.setDepartmentFromExternal();
330
334
  /** set color with gradient from theme's colors */
331
335
  this.globals.setColorWithGradient();
@@ -333,11 +337,19 @@ export class GlobalSettingsService {
333
337
  this.setCssIframe();
334
338
  /** set main style */
335
339
  this.setStyle();
336
-
337
- this.logger.debug('[GLOBAL-SET] ***** END SET PARAMETERS *****');
338
340
  this.obsSettingsService.next(true);
339
341
  }
340
342
 
343
+ private setButtonColors() {
344
+ this.logger.debug('[GLOBAL-SET] ***** END SET PARAMETERS *****', this.globals);
345
+ const bubbleSentBackground = this.globals?.bubbleSentBackground;
346
+ const buttonBackgroundColor = this.globals?.buttonBackgroundColor;
347
+
348
+ this.globals.buttonTextColor = ensureAccessibleTextColor(buttonBackgroundColor, bubbleSentBackground);
349
+ this.globals.buttonHoverTextColor = ensureAccessibleTextColor(bubbleSentBackground, buttonBackgroundColor);
350
+
351
+ }
352
+
341
353
  /**
342
354
  *
343
355
  */
@@ -1936,7 +1948,7 @@ export class GlobalSettingsService {
1936
1948
  if (this.globals.departmentID) {
1937
1949
  this.globals.departments.forEach(department => {
1938
1950
  if (department._id === this.globals.departmentID) {
1939
- this.logger.debug('[GLOBAL-SET] setDepartmentFromExternal > EXTERNAL DEPARTMENT ::::' + department._id);
1951
+ console.log('[GLOBAL-SET] setDepartmentFromExternal > EXTERNAL DEPARTMENT ::::' + department._id);
1940
1952
  this.globals.setParameter('departmentDefault', department);
1941
1953
  this.setDepartment(department);
1942
1954
  isValidID = true;
@@ -1964,7 +1976,7 @@ export class GlobalSettingsService {
1964
1976
  * save attributes in this.appStorageService
1965
1977
  */
1966
1978
  setDepartment(department) {
1967
- this.logger.debug('[GLOBAL-SET] setDepartment: ', JSON.stringify(department));
1979
+ this.logger.log('[GLOBAL-SET] setDepartment: ', JSON.stringify(department));
1968
1980
  this.globals.setParameter('departmentSelected', department);
1969
1981
  // let attributes = this.globals.attributes;
1970
1982
  let attributes: any = JSON.parse(this.appStorageService.getItem('attributes'));
@@ -389,6 +389,115 @@ export function convertColorToRGBA(color, opacity) {
389
389
  return result;
390
390
  }
391
391
 
392
+ export function normalizeColorToHex(input?: string): string | null {
393
+ if (!input) {
394
+ return null;
395
+ }
396
+ let color = input.trim();
397
+ if (color.toLowerCase().includes('gradient')) {
398
+ const match = color.match(/(#[0-9a-fA-F]{3,8}|rgba?\([^)]*\))/);
399
+ if (!match) {
400
+ return null;
401
+ }
402
+ color = match[0];
403
+ }
404
+ if (color.startsWith('#')) {
405
+ const hex = color.slice(1);
406
+ if (hex.length === 3) {
407
+ return (
408
+ '#' +
409
+ hex
410
+ .split('')
411
+ .map((char) => char + char)
412
+ .join('')
413
+ .toLowerCase()
414
+ );
415
+ }
416
+ if (hex.length === 4) {
417
+ return (
418
+ '#' +
419
+ hex
420
+ .slice(0, 3)
421
+ .split('')
422
+ .map((char) => char + char)
423
+ .join('')
424
+ .toLowerCase()
425
+ );
426
+ }
427
+ if (hex.length === 6 || hex.length === 8) {
428
+ return '#' + hex.slice(0, 6).toLowerCase();
429
+ }
430
+ return null;
431
+ }
432
+ const rgbaMatch = color.match(/rgba?\s*\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)(?:\s*,\s*([\d.]+))?\s*\)/i);
433
+ if (rgbaMatch) {
434
+ const [, r, g, b] = rgbaMatch;
435
+ const toHex = (value: number) => {
436
+ const clamped = Math.max(0, Math.min(255, Math.round(value)));
437
+ return clamped.toString(16).padStart(2, '0');
438
+ };
439
+ return `#${toHex(parseFloat(r))}${toHex(parseFloat(g))}${toHex(parseFloat(b))}`;
440
+ }
441
+ return null;
442
+ }
443
+
444
+ export function ensureAccessibleTextColor(backgroundColor?: string, fontColor?: string, minContrast = 4.5): string | null {
445
+ const bgHex = normalizeColorToHex(backgroundColor);
446
+ if (!bgHex) {
447
+ return normalizeColorToHex(fontColor);
448
+ }
449
+
450
+ const fontHex = normalizeColorToHex(fontColor);
451
+ if (fontHex && getContrastRatio(bgHex, fontHex) >= minContrast) {
452
+ return fontHex;
453
+ }
454
+
455
+ const blackContrast = getContrastRatio(bgHex, '#000000');
456
+ const whiteContrast = getContrastRatio(bgHex, '#ffffff');
457
+ return blackContrast >= whiteContrast ? '#000000' : '#ffffff';
458
+ }
459
+
460
+ function getContrastRatio(backgroundHex: string, foregroundHex: string): number {
461
+ const bg = hexToRgb(backgroundHex);
462
+ const fg = hexToRgb(foregroundHex);
463
+ if (!bg || !fg) {
464
+ return 1;
465
+ }
466
+ const l1 = relativeLuminance(bg);
467
+ const l2 = relativeLuminance(fg);
468
+ const lighter = Math.max(l1, l2);
469
+ const darker = Math.min(l1, l2);
470
+ return (lighter + 0.05) / (darker + 0.05);
471
+ }
472
+
473
+ function relativeLuminance({ r, g, b }: { r: number; g: number; b: number }): number {
474
+ const srgb = [r, g, b].map((value) => {
475
+ const channel = value / 255;
476
+ return channel <= 0.03928 ? channel / 12.92 : Math.pow((channel + 0.055) / 1.055, 2.4);
477
+ });
478
+ return 0.2126 * srgb[0] + 0.7152 * srgb[1] + 0.0722 * srgb[2];
479
+ }
480
+
481
+ function hexToRgb(hex: string): { r: number; g: number; b: number } | null {
482
+ let value = hex.replace('#', '');
483
+ if (value.length === 3) {
484
+ value = value
485
+ .split('')
486
+ .map((char) => char + char)
487
+ .join('');
488
+ }
489
+ if (value.length !== 6) {
490
+ return null;
491
+ }
492
+ const r = parseInt(value.slice(0, 2), 16);
493
+ const g = parseInt(value.slice(2, 4), 16);
494
+ const b = parseInt(value.slice(4, 6), 16);
495
+ if ([r, g, b].some((channel) => Number.isNaN(channel))) {
496
+ return null;
497
+ }
498
+ return { r, g, b };
499
+ }
500
+
392
501
 
393
502
  // export function setLanguage(windowContext, translatorService) {
394
503
  // if (translatorService.getBrowserLanguage(windowContext)) {