@@ -4,6 +4,8 @@ import {$patchStyleText} from "@lexical/selection";
4
4
import { el } from "../../../utils/dom" ;
5
5
6
6
import removeIcon from "@icons/editor/color-clear.svg" ;
7
+ import selectIcon from "@icons/editor/color-select.svg" ;
8
+ import { uniqueIdSmall } from "../../../../services/util" ;
7
9
8
10
const colorChoices = [
9
11
'#000000' ,
@@ -34,6 +36,8 @@ const colorChoices = [
34
36
'#34495E' ,
35
37
] ;
36
38
39
+ const storageKey = 'bs-lexical-custom-colors' ;
40
+
37
41
export class EditorColorPicker extends EditorUiElement {
38
42
39
43
protected styleProperty : string ;
@@ -44,8 +48,10 @@ export class EditorColorPicker extends EditorUiElement {
44
48
}
45
49
46
50
buildDOM ( ) : HTMLElement {
51
+ const id = uniqueIdSmall ( ) ;
47
52
48
- const colorOptions = colorChoices . map ( choice => {
53
+ const allChoices = [ ...colorChoices , ...this . getCustomColorChoices ( ) ] ;
54
+ const colorOptions = allChoices . map ( choice => {
49
55
return el ( 'div' , {
50
56
class : 'editor-color-select-option' ,
51
57
style : `background-color: ${ choice } ` ,
@@ -62,6 +68,25 @@ export class EditorColorPicker extends EditorUiElement {
62
68
removeButton . innerHTML = removeIcon ;
63
69
colorOptions . push ( removeButton ) ;
64
70
71
+ const selectButton = el ( 'label' , {
72
+ class : 'editor-color-select-option' ,
73
+ for : `color-select-${ id } ` ,
74
+ 'data-color' : '' ,
75
+ title : 'Custom color' ,
76
+ } , [ ] ) ;
77
+ selectButton . innerHTML = selectIcon ;
78
+ colorOptions . push ( selectButton ) ;
79
+
80
+ const input = el ( 'input' , { type : 'color' , hidden : 'true' , id : `color-select-${ id } ` } ) as HTMLInputElement ;
81
+ colorOptions . push ( input ) ;
82
+ input . addEventListener ( 'change' , e => {
83
+ if ( input . value ) {
84
+ this . storeCustomColorChoice ( input . value ) ;
85
+ this . setColor ( input . value ) ;
86
+ this . rebuildDOM ( ) ;
87
+ }
88
+ } ) ;
89
+
65
90
const colorRows = [ ] ;
66
91
for ( let i = 0 ; i < colorOptions . length ; i += 5 ) {
67
92
const options = colorOptions . slice ( i , i + 5 ) ;
@@ -79,11 +104,33 @@ export class EditorColorPicker extends EditorUiElement {
79
104
return wrapper ;
80
105
}
81
106
107
+ storeCustomColorChoice ( color : string ) {
108
+ if ( colorChoices . includes ( color ) ) {
109
+ return ;
110
+ }
111
+
112
+ const customColors : string [ ] = this . getCustomColorChoices ( ) ;
113
+ if ( customColors . includes ( color ) ) {
114
+ return ;
115
+ }
116
+
117
+ customColors . push ( color ) ;
118
+ window . localStorage . setItem ( storageKey , JSON . stringify ( customColors ) ) ;
119
+ }
120
+
121
+ getCustomColorChoices ( ) : string [ ] {
122
+ return JSON . parse ( window . localStorage . getItem ( storageKey ) || '[]' ) ;
123
+ }
124
+
82
125
onClick ( event : MouseEvent ) {
83
126
const colorEl = ( event . target as HTMLElement ) . closest ( '[data-color]' ) as HTMLElement ;
84
127
if ( ! colorEl ) return ;
85
128
86
129
const color = colorEl . dataset . color as string ;
130
+ this . setColor ( color ) ;
131
+ }
132
+
133
+ setColor ( color : string ) {
87
134
this . getContext ( ) . editor . update ( ( ) => {
88
135
const selection = $getSelection ( ) ;
89
136
if ( selection ) {
0 commit comments