@@ -24,9 +24,12 @@ import {
24
24
COLOR_COMBINATION_CLASSES_REGEX ,
25
25
} from "@web/core/utils/colors" ;
26
26
import { ColorSelector } from "./color_selector" ;
27
+ import { backgroundImageCssToParts , backgroundImagePartsToCss } from "@html_editor/utils/image" ;
27
28
28
29
const RGBA_OPACITY = 0.6 ;
29
30
const HEX_OPACITY = "99" ;
31
+ const COLOR_COMBINATION_CLASSES = [ 1 , 2 , 3 , 4 , 5 ] . map ( ( i ) => `o_cc${ i } ` ) ;
32
+ const COLOR_COMBINATION_SELECTOR = COLOR_COMBINATION_CLASSES . map ( ( c ) => `.${ c } ` ) . join ( ", " ) ;
30
33
31
34
/**
32
35
* @typedef { Object } ColorShared
@@ -80,7 +83,7 @@ export class ColorPlugin extends Plugin {
80
83
* @param {string } color hexadecimal or bg-name/text-name class
81
84
* @param {'color'|'backgroundColor' } mode 'color' or 'backgroundColor'
82
85
*/
83
- apply_color_style : ( element , mode , color ) => {
86
+ apply_style : ( element , mode , color ) => {
84
87
element . style [ mode ] = color ;
85
88
return true ;
86
89
} ,
@@ -445,30 +448,84 @@ export class ColorPlugin extends Plugin {
445
448
* @param {'color'|'backgroundColor' } mode 'color' or 'backgroundColor'
446
449
*/
447
450
colorElement ( element , color , mode ) {
451
+ let parts = backgroundImageCssToParts ( element . style [ "background-image" ] ) ;
448
452
const oldClassName = element . getAttribute ( "class" ) || "" ;
453
+
454
+ if ( element . matches ( COLOR_COMBINATION_SELECTOR ) ) {
455
+ removePresetGradient ( element ) ;
456
+ }
457
+
458
+ if ( color . startsWith ( "o_cc" ) ) {
459
+ parts = backgroundImageCssToParts ( element . style [ "background-image" ] ) ;
460
+ element . classList . remove ( ...COLOR_COMBINATION_CLASSES ) ;
461
+ element . classList . add ( color ) ;
462
+ setBackgroundImageAndOverride ( element , element . style [ "background-image" ] ) ;
463
+ this . fixColorCombination ( element ) ;
464
+ return ;
465
+ }
466
+
467
+ if ( mode === "backgroundColor" ) {
468
+ if ( ! color ) {
469
+ element . classList . remove ( ...COLOR_COMBINATION_CLASSES ) ;
470
+ }
471
+ delete parts . gradient ;
472
+ const newBackgroundImage = backgroundImagePartsToCss ( parts ) ;
473
+ setBackgroundImageAndOverride ( element , newBackgroundImage ) ;
474
+ element . style [ "background-color" ] = "" ;
475
+ }
476
+
449
477
const newClassName = oldClassName
450
478
. replace ( mode === "color" ? TEXT_CLASSES_REGEX : BG_CLASSES_REGEX , "" )
451
479
. replace ( / \b t e x t - g r a d i e n t \b / g, "" ) // cannot be combined with setting a background
452
480
. replace ( / \s + / , " " ) ;
453
- oldClassName !== newClassName && element . setAttribute ( "class" , newClassName ) ;
454
- element . style [ "background-image" ] = "" ;
455
- if ( mode === "backgroundColor" ) {
456
- element . style [ "background" ] = "" ;
481
+ if ( oldClassName !== newClassName ) {
482
+ element . setAttribute ( "class" , newClassName ) ;
457
483
}
458
484
if ( color . startsWith ( "text" ) || color . startsWith ( "bg-" ) ) {
459
485
element . style [ mode ] = "" ;
460
486
element . classList . add ( color ) ;
461
487
} else if ( isColorGradient ( color ) ) {
462
488
element . style [ mode ] = "" ;
489
+ parts . gradient = color ;
463
490
if ( mode === "color" ) {
464
- element . style [ "background" ] = "" ;
465
- this . delegateTo ( "apply_color_style" , element , "background-image" , color ) ;
491
+ element . style [ "background-color" ] = "" ;
466
492
element . classList . add ( "text-gradient" ) ;
467
- } else {
468
- this . delegateTo ( "apply_color_style" , element , "background-image" , color ) ;
469
493
}
494
+ this . delegateTo (
495
+ "apply_style" ,
496
+ element ,
497
+ "background-image" ,
498
+ backgroundImagePartsToCss ( parts )
499
+ ) ;
470
500
} else {
471
- this . delegateTo ( "apply_color_style" , element , mode , color ) ;
501
+ this . delegateTo ( "apply_style" , element , mode , color ) ;
502
+ }
503
+ this . fixColorCombination ( element ) ;
504
+ }
505
+ /**
506
+ * There is a limitation with css. The defining a background image and a
507
+ * background gradient is done only by setting one style (background-image).
508
+ * If there is a class (in this case o_cc[1-5]) that defines a gradient, it
509
+ * will be overridden by the background-image property.
510
+ *
511
+ * This function will set the gradient of the o_cc in the background-image
512
+ * so that setting an image in the background-image property will not
513
+ * override the gradient.
514
+ */
515
+ fixColorCombination ( element ) {
516
+ const parts = backgroundImageCssToParts ( element . style [ "background-image" ] ) ;
517
+ const hasBackgroundColor =
518
+ element . style [ "background-color" ] ||
519
+ ! ! element . className . match ( / \b b g - / ) ||
520
+ parts . gradient ;
521
+
522
+ if ( ! hasBackgroundColor ) {
523
+ element . style [ "background-image" ] = "" ;
524
+ parts . gradient = backgroundImageCssToParts (
525
+ // Compute the style from o_cc class.
526
+ getComputedStyle ( element ) . backgroundImage
527
+ ) . gradient ;
528
+ element . style [ "background-image" ] = backgroundImagePartsToCss ( parts ) ;
472
529
}
473
530
}
474
531
@@ -485,3 +542,33 @@ export class ColorPlugin extends Plugin {
485
542
function getColorCombinationFromClass ( el ) {
486
543
return el . className . match ?. ( COLOR_COMBINATION_CLASSES_REGEX ) ?. [ 0 ] ;
487
544
}
545
+
546
+ /**
547
+ * Remove the gradient of the element only if it is the inheritance from the o_cc selector.
548
+ */
549
+ function removePresetGradient ( element ) {
550
+ const oldBackgroundImage = element . style [ "background-image" ] ;
551
+ const parts = backgroundImageCssToParts ( oldBackgroundImage ) ;
552
+ const currentGradient = parts . gradient ;
553
+ element . style . removeProperty ( "background-image" ) ;
554
+ const styleWithoutGradient = getComputedStyle ( element ) ;
555
+ const presetGradient = backgroundImageCssToParts ( styleWithoutGradient . backgroundImage ) . gradient ;
556
+ if ( presetGradient !== currentGradient ) {
557
+ const withGradient = backgroundImagePartsToCss ( parts ) ;
558
+ element . style [ "background-image" ] = withGradient === "none" ? "" : withGradient ;
559
+ } else {
560
+ delete parts . gradient ;
561
+ const withoutGradient = backgroundImagePartsToCss ( parts ) ;
562
+ element . style [ "background-image" ] = styleWithoutGradient === "none" ? "" : withoutGradient ;
563
+ }
564
+ }
565
+
566
+ function setBackgroundImageAndOverride ( el , backgroundImage ) {
567
+ const isNone = ! backgroundImage || backgroundImage === "none" ;
568
+ el . style . backgroundImage = isNone ? "" : backgroundImage ;
569
+ // If the current background image is empty but the inherited one isn't
570
+ // force the background image to override the inherited one.
571
+ if ( isNone && getComputedStyle ( el ) . backgroundImage !== "none" ) {
572
+ el . style . backgroundImage = "none" ;
573
+ }
574
+ }
0 commit comments