forked from basecamp/lexxy
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhighlight.js
More file actions
105 lines (82 loc) · 3.45 KB
/
Copy pathhighlight.js
File metadata and controls
105 lines (82 loc) · 3.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import { $getSelection, $isRangeSelection } from "lexical"
import { $getSelectionStyleValueForProperty } from "@lexical/selection"
import { ToolbarDropdown } from "../toolbar_dropdown"
import { registerEventListener } from "../../helpers/listener_helper"
import { createElement } from "../../helpers/html_helper"
const APPLY_HIGHLIGHT_SELECTOR = "button.lexxy-highlight-button"
const REMOVE_HIGHLIGHT_SELECTOR = "[data-command='removeHighlight']"
// Use Symbol instead of null since $getSelectionStyleValueForProperty
// responds differently for backward selections if null is the default
// see https://github.com/facebook/lexical/issues/8013
const NO_STYLE = Symbol("no_style")
export class HighlightDropdown extends ToolbarDropdown {
editorReady() {
if (!this.editorElement.supportsHighlight) return
this.#setUpButtons()
this.#registerButtonHandlers()
}
onOpen() {
this.editor.getEditorState().read(() => {
this.#updateColorButtonStates($getSelection())
})
}
#registerButtonHandlers() {
this.#colorButtons.forEach(button => {
this.track(registerEventListener(button, "click", this.#handleColorButtonClick))
})
}
#setUpButtons() {
this.#buttonContainer.innerHTML = ""
const colorGroups = this.editorElement.config.get("highlight.buttons")
if (!colorGroups) return
this.#populateButtonGroup("color", colorGroups.color)
this.#populateButtonGroup("background-color", colorGroups["background-color"])
const maxNumberOfColors = Math.max(colorGroups.color.length, colorGroups["background-color"].length)
this.panel.style.setProperty("--max-colors", maxNumberOfColors)
}
#populateButtonGroup(attribute, values) {
values.forEach((value, index) => {
this.#buttonContainer.appendChild(this.#createButton(attribute, value, index))
})
}
#createButton(attribute, value, index) {
return createElement("button", {
type: "button",
dataset: { value, style: attribute },
style: `${attribute}: ${value}`,
class: "lexxy-editor__toolbar-button lexxy-highlight-button",
name: `${attribute}-${index}`,
role: "menuitem"
})
}
#handleColorButtonClick = (event) => {
event.preventDefault()
const button = event.target.closest(APPLY_HIGHLIGHT_SELECTOR)
if (!button) return
const { style, value } = button.dataset
this.editor.dispatchCommand("toggleHighlight", { [style]: value })
this.close()
}
#updateColorButtonStates(selection) {
if (!$isRangeSelection(selection)) { return }
// Use non-"" default, so "" indicates mixed highlighting
const textColor = $getSelectionStyleValueForProperty(selection, "color", NO_STYLE)
const backgroundColor = $getSelectionStyleValueForProperty(selection, "background-color", NO_STYLE)
this.#colorButtons.forEach(button => {
const matchesSelection = button.dataset.value === textColor || button.dataset.value === backgroundColor
const next = matchesSelection.toString()
if (button.getAttribute("aria-pressed") !== next) {
button.setAttribute("aria-pressed", next)
}
})
const hasHighlight = textColor !== NO_STYLE || backgroundColor !== NO_STYLE
this.panel.querySelector(REMOVE_HIGHLIGHT_SELECTOR).disabled = !hasHighlight
}
get #buttonContainer() {
return this.panel.querySelector(".lexxy-highlight-colors")
}
get #colorButtons() {
return Array.from(this.panel.querySelectorAll(APPLY_HIGHLIGHT_SELECTOR))
}
}
export default HighlightDropdown