1+ import { Canvas } from "src/@types/Canvas"
2+ import { CanvasEvent } from "src/events/events"
3+ import AdvancedCanvasPlugin from "src/main"
4+
5+ const DEFAULT_COLORS_COUNT = 6
6+ const CUSTOM_COLORS_MOD_STYLES_ID = 'mod-custom-colors'
7+
8+ export default class ColorPaletteCanvasExtension {
9+ plugin : AdvancedCanvasPlugin
10+ observer : MutationObserver | null = null
11+
12+ constructor ( plugin : AdvancedCanvasPlugin ) {
13+ this . plugin = plugin
14+
15+ this . plugin . registerEvent ( this . plugin . app . workspace . on (
16+ 'css-change' ,
17+ ( ) => this . updateCustomColorModStyleClasses ( )
18+ ) )
19+
20+ this . plugin . registerEvent ( this . plugin . app . workspace . on (
21+ CanvasEvent . PopupMenuCreated ,
22+ ( canvas : Canvas ) => this . patchColorSelection ( canvas )
23+ ) )
24+
25+ this . plugin . register ( ( ) => this . observer ?. disconnect ( ) )
26+ }
27+
28+ private patchColorSelection ( canvas : Canvas ) {
29+ if ( this . observer ) this . observer . disconnect ( )
30+
31+ this . observer = new MutationObserver ( mutations => {
32+ const colorMenuOpened = mutations . some ( mutation =>
33+ Object . values ( mutation . addedNodes ) . some ( ( node : Node ) =>
34+ node instanceof HTMLElement && node . classList . contains ( 'canvas-submenu' ) && Object . values ( node . childNodes ) . some ( ( node : Node ) =>
35+ node instanceof HTMLElement && node . classList . contains ( 'canvas-color-picker-item' )
36+ )
37+ )
38+ )
39+ if ( ! colorMenuOpened ) return
40+
41+ const submenu = canvas . menu . menuEl . querySelector ( '.canvas-submenu' )
42+ if ( ! submenu ) return
43+
44+ this . updateCustomColorModStyleClasses ( )
45+
46+ for ( const colorId of this . getCustomColors ( ) ) {
47+ const customColorMenuItem = this . createColorMenuItem ( canvas , colorId )
48+ submenu . insertBefore ( customColorMenuItem , submenu . lastChild )
49+ }
50+ } )
51+
52+ this . observer . observe ( canvas . menu . menuEl , { childList : true } )
53+ }
54+
55+ private createColorMenuItem ( canvas : Canvas , colorId : string ) {
56+ const menuItem = document . createElement ( 'div' )
57+ menuItem . classList . add ( 'canvas-color-picker-item' )
58+ menuItem . classList . add ( `mod-canvas-color-${ colorId } ` )
59+
60+ menuItem . addEventListener ( 'click' , ( ) => {
61+ for ( const item of canvas . selection ) {
62+ item . setColor ( colorId )
63+ }
64+
65+ canvas . requestSave ( )
66+ } )
67+
68+ return menuItem
69+ }
70+
71+ private updateCustomColorModStyleClasses ( ) {
72+ document . getElementById ( CUSTOM_COLORS_MOD_STYLES_ID ) ?. remove ( )
73+
74+ const customColorModStyle = document . createElement ( 'style' )
75+ customColorModStyle . id = CUSTOM_COLORS_MOD_STYLES_ID
76+ document . body . appendChild ( customColorModStyle )
77+
78+ for ( const colorId of this . getCustomColors ( ) ) {
79+ // Add mod-canvas-color-<colorId> style to the css
80+ customColorModStyle . innerHTML += `
81+ .mod-canvas-color-${ colorId } {
82+ --canvas-color: var(--canvas-color-${ colorId } );
83+ }
84+ `
85+ }
86+ }
87+
88+ private getCustomColors ( ) : string [ ] {
89+ const colors : string [ ] = [ ]
90+
91+ while ( true ) {
92+ const colorId = ( DEFAULT_COLORS_COUNT + colors . length + 1 ) . toString ( )
93+ if ( ! getComputedStyle ( document . body ) . getPropertyValue ( `--canvas-color-${ colorId } ` ) ) break
94+
95+ colors . push ( colorId )
96+ }
97+
98+ return colors
99+ }
100+ }
0 commit comments