Skip to content

Commit c78f7ec

Browse files
Added feature to add custom colors to the canvas color menu
1 parent f6b4ecb commit c78f7ec

File tree

4 files changed

+105
-2
lines changed

4 files changed

+105
-2
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ All custom events are prefixed with `advanced-canvas:` and can be listened to us
280280
- Payload: `Canvas`, `BBox`
281281
- `advanced-canvas:popup-menu-created`
282282
- Fired when the a node popup menu gets created (Not firing multiple times if it gets moved between nodes of the same type)
283-
- Payload: `Canvas`, `Node`
283+
- Payload: `Canvas`
284284
- `advanced-canvas:node-interaction`
285285
- Fired when a node gets hovered over
286286
- Payload: `Canvas`, `Node`

src/@types/Canvas.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export interface Canvas {
6161
readonly: boolean
6262
setReadonly(readonly: boolean): void
6363

64-
selection: Set<CanvasNode|CanvasEdge>
64+
selection: Set<CanvasElement>
6565
getSelectionData(): SelectionData
6666
deselectAll(): void
6767

@@ -163,6 +163,7 @@ export interface CanvasElement {
163163
initialized: boolean
164164

165165
initialize(): void
166+
setColor(color: string): void
166167
}
167168

168169
export type CanvasNodeType = 'text' | 'group' | 'file' | 'link'
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
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+
}

src/main.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import EdgesStyleCanvasExtension from './canvas-extensions/edges-style-canvas-ex
1717
import EdgeDataTaggerCanvasExtension from './canvas-extensions/edge-data-tagger-canvas-extension'
1818
import DebugHelper from './utils/debug-helper'
1919
import DefaultNodeSizeCanvasExtension from './canvas-extensions/default-node-size-canvas-extension'
20+
import ColorPaletteCanvasExtension from './canvas-extensions/color-palette-canvas-extension'
2021

2122
const CANVAS_EXTENSIONS: any[] = [
2223
NodeDataTaggerCanvasExtension,
@@ -27,6 +28,7 @@ const CANVAS_EXTENSIONS: any[] = [
2728
ReadonlyCanvasExtension,
2829
GroupCanvasExtension,
2930
EncapsulateCanvasExtension,
31+
ColorPaletteCanvasExtension,
3032
StickersCanvasExtension,
3133
ShapesCanvasExtension,
3234
EdgesStyleCanvasExtension,

0 commit comments

Comments
 (0)