Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
giswqs
GitHub Repository: giswqs/geemap
Path: blob/master/js/palette_editor.ts
2313 views
1
import { css, html, LitElement, PropertyValues } from "lit";
2
import { property, query } from "lit/decorators.js";
3
4
import { ColorPicker } from "./color_picker";
5
import { legacyStyles } from "./ipywidgets_styles";
6
import { flexStyles, materialStyles } from "./styles";
7
import { SelectOption, renderSelect } from "./utils";
8
9
import "./color_picker";
10
11
export class PaletteEditor extends LitElement {
12
static get componentName() {
13
return `palette-editor`;
14
}
15
16
static override styles = [
17
flexStyles,
18
legacyStyles,
19
materialStyles,
20
css`
21
.horizontal-flex > .legacy-button {
22
flex-shrink: 0;
23
height: 28px;
24
width: 28px;
25
}
26
`,
27
];
28
29
@property({ type: Array }) classesOptions: Array<SelectOption> = [
30
{ label: "Any", value: "any" },
31
...Array.from({ length: 7 }, (_, i) => ({
32
label: `${i + 3}`,
33
value: `${i + 3}`,
34
})),
35
];
36
@property({ type: String }) classes: string = "any";
37
@property({ type: Array }) colormaps: Array<string> = [];
38
@property({ type: String }) colormap: string = "Custom";
39
@property({ type: String }) palette: string = "";
40
41
@query('color-picker') colorPicker!: ColorPicker;
42
43
paletteTokens: Array<string> = [];
44
45
override render() {
46
return html`
47
<div class="vertical-flex">
48
<div class="horizontal-flex">
49
<span class="legacy-text">Colormap:</span>
50
${renderSelect(
51
this.colormaps,
52
this.colormap,
53
this.onColormapChanged
54
)}
55
<span class="legacy-text">Classes:</span>
56
${renderSelect(
57
this.classesOptions,
58
this.classes,
59
this.onClassesChanged
60
)}
61
</div>
62
<div class="horizontal-flex">
63
<span class="legacy-text">Palette:</span>
64
<input
65
type="text"
66
class="legacy-text-input"
67
id="palette"
68
name="palette"
69
.value="${this.palette}"
70
?disabled="${this.colormap !== "Custom"}"
71
@change="${this.onPaletteChanged}"
72
/>
73
</div>
74
<slot></slot>
75
<div class="horizontal-flex">
76
<span class="legacy-text">Add/remove color:</span>
77
<color-picker></color-picker>
78
<button
79
class="legacy-button"
80
@click="${this.onAddButtonClicked}"
81
>
82
<span class="material-symbols-outlined">add</span>
83
</button>
84
<button
85
class="legacy-button"
86
@click="${this.onSubtractButtonClicked}"
87
>
88
<span class="material-symbols-outlined">remove</span>
89
</button>
90
<button
91
class="legacy-button"
92
@click="${this.onClearButtonClicked}"
93
>
94
<span class="material-symbols-outlined">ink_eraser</span>
95
</button>
96
</div>
97
</div>
98
`;
99
}
100
101
override updated(changedProperties: PropertyValues<PaletteEditor>): void {
102
super.updated(changedProperties);
103
if (changedProperties.has("palette")) {
104
if (this.palette === "") {
105
this.paletteTokens = [];
106
} else {
107
this.paletteTokens = this.palette.split(",").map(color => color.trim());
108
}
109
}
110
}
111
112
private sendOnPaletteChangedEvent(): void {
113
this.dispatchEvent(
114
new CustomEvent("calculate-palette", {
115
detail: {
116
colormap: this.colormap,
117
classes: this.classes,
118
palette: this.palette,
119
},
120
bubbles: true,
121
composed: true,
122
})
123
);
124
}
125
126
private onClassesChanged(event: Event): void {
127
const target = event.target as HTMLInputElement;
128
this.classes = target.value;
129
this.sendOnPaletteChangedEvent();
130
}
131
132
private onColormapChanged(event: Event): void {
133
const target = event.target as HTMLInputElement;
134
this.colormap = target.value;
135
this.sendOnPaletteChangedEvent();
136
}
137
138
private onPaletteChanged(event: Event): void {
139
const target = event.target as HTMLInputElement;
140
this.palette = target.value;
141
this.sendOnPaletteChangedEvent();
142
}
143
144
private onAddButtonClicked(_event: Event): void {
145
this.colormap = "Custom";
146
this.classes = "any";
147
148
const tokens = [...this.paletteTokens];
149
tokens.push(this.colorPicker.value);
150
this.palette = tokens.join(", ");
151
152
this.sendOnPaletteChangedEvent();
153
}
154
155
private onSubtractButtonClicked(_event: Event): void {
156
this.colormap = "Custom";
157
this.classes = "any";
158
159
const tokens = [...this.paletteTokens];
160
tokens.pop();
161
this.palette = tokens.join(", ");
162
163
this.sendOnPaletteChangedEvent();
164
}
165
166
private onClearButtonClicked(_event: Event): void {
167
this.colormap = "Custom";
168
this.classes = "any";
169
this.palette = "";
170
171
this.sendOnPaletteChangedEvent();
172
}
173
}
174
175
// Without this check, there's a component registry issue when developing locally.
176
if (!customElements.get(PaletteEditor.componentName)) {
177
customElements.define(PaletteEditor.componentName, PaletteEditor);
178
}
179