Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
giswqs
GitHub Repository: giswqs/geemap
Path: blob/master/js/legend.ts
2313 views
1
import type { RenderProps } from "@anywidget/types";
2
3
import { css, html, nothing } from "lit";
4
import { property } from "lit/decorators.js";
5
import { styleMap } from "lit/directives/style-map.js";
6
7
import { legacyStyles } from "./ipywidgets_styles";
8
import { LitWidget } from "./lit_widget";
9
import { materialStyles } from "./styles";
10
11
import "./container";
12
13
function zip<T>(a: T[], b: T[]) {
14
const maxLength = Math.min(a.length, b.length);
15
return a.slice(0, maxLength).map((el, i) => [el, b[i]]);
16
}
17
18
export interface LegendData {
19
[key: string]: [color: string];
20
}
21
22
export interface LegendModel {
23
title: string;
24
legend_keys: string[];
25
legend_colors: string[];
26
add_header: boolean;
27
show_close_button: boolean;
28
}
29
30
export class Legend extends LitWidget<LegendModel, Legend> {
31
static get componentName(): string {
32
return `legend-widget`;
33
}
34
35
static override styles = [
36
legacyStyles,
37
materialStyles,
38
css`
39
.legend {
40
max-height: 200px;
41
max-width: 300px;
42
overflow: auto;
43
padding: 4px;
44
}
45
46
widget-container .legend {
47
padding: 0px !important;
48
}
49
50
.legend .legend-title {
51
font-size: 90%;
52
font-weight: bold;
53
margin-bottom: 2px;
54
margin-left: 2px;
55
margin-top: 0;
56
text-align: left;
57
}
58
59
.legend ul {
60
float: left;
61
list-style: none;
62
margin-bottom: 5px;
63
margin: 0;
64
padding: 0;
65
}
66
67
.legend li {
68
font-size: 80%;
69
line-height: 18px;
70
margin-bottom: 2px;
71
margin-left: 1px;
72
}
73
74
.legend .legend-labels li span {
75
border: 1px solid #999;
76
display: block;
77
float: left;
78
height: 16px;
79
margin-left: 2px;
80
margin-right: 5px;
81
width: 30px;
82
}`
83
];
84
85
@property({ type: String }) override title = "";
86
@property({ type: Array }) legendKeys: string[] = [];
87
@property({ type: Array }) legendColors: string[] = [];
88
@property({ type: Boolean }) addHeader: boolean = true;
89
@property({ type: Boolean }) showCloseButton: boolean = true;
90
91
modelNameToViewName(): Map<keyof LegendModel, keyof Legend | null> {
92
return new Map([
93
["title", "title"],
94
["legend_keys", "legendKeys"],
95
["legend_colors", "legendColors"],
96
["add_header", "addHeader"],
97
["show_close_button", "showCloseButton"],
98
]);
99
}
100
101
override render() {
102
return this.addHeader ? html`
103
<widget-container
104
.title="${this.title}"
105
.hideCloseButton="${!this.showCloseButton}"
106
@close-clicked="${this.onCloseButtonClicked}">
107
${this.renderLegend("")}
108
</widget-container>` : this.renderLegend(this.title);
109
}
110
111
private onCloseButtonClicked(_: Event) {
112
this.model?.send({ "type": "click", "id": "close" });
113
}
114
115
private renderLegend(title: string) {
116
const legend = zip<string>(this.legendKeys, this.legendColors)
117
.map(([key, color]) =>
118
html`<li>
119
<span style="${styleMap({ background: color })}">
120
</span>${key}
121
</li>`
122
);
123
return html`<div class="legend">
124
${title ? html`<h4 class="legend-title">${title}</h4>` : nothing}
125
<ul class="legend-labels">
126
${legend}
127
</ul>
128
</div>`;
129
}
130
}
131
132
// Without this check, there's a component registry issue when developing locally.
133
if (!customElements.get(Legend.componentName)) {
134
customElements.define(Legend.componentName, Legend);
135
}
136
137
async function render({ model, el }: RenderProps<LegendModel>) {
138
const manager = document.createElement(
139
Legend.componentName
140
) as Legend;
141
manager.model = model;
142
el.appendChild(manager);
143
}
144
145
export default { render };
146
147