@aquera/nile-visualization 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/index.d.ts +8 -2
- package/dist/src/index.js +3 -0
- package/dist/src/internal/dashboard-adapters.d.ts +13 -0
- package/dist/src/internal/dashboard-adapters.js +123 -0
- package/dist/src/internal/highcharts-provider.js +27 -0
- package/dist/src/internal/types/chart-config.type.d.ts +2 -1
- package/dist/src/internal/types/chart-map-config.type.d.ts +29 -0
- package/dist/src/internal/types/chart-map-config.type.js +2 -0
- package/dist/src/internal/types/dashboard-config.type.d.ts +8 -0
- package/dist/src/internal/types/dashboard-config.type.js +2 -0
- package/dist/src/internal/types/index.d.ts +1 -0
- package/dist/src/internal/types/widget-config.type.d.ts +23 -0
- package/dist/src/internal/types/widget-config.type.js +2 -0
- package/dist/src/internal/types/widget-layout.type.d.ts +11 -0
- package/dist/src/internal/types/widget-layout.type.js +2 -0
- package/dist/src/nile-chart/index.d.ts +2 -2
- package/dist/src/nile-chart/nile-chart-config.d.ts +119 -30
- package/dist/src/nile-chart/nile-chart.d.ts +11 -0
- package/dist/src/nile-chart/nile-chart.js +33 -0
- package/dist/src/nile-dashboard-viewer/index.d.ts +2 -0
- package/dist/src/nile-dashboard-viewer/index.js +2 -0
- package/dist/src/nile-dashboard-viewer/nile-dashboard-viewer.css.d.ts +1 -0
- package/dist/src/nile-dashboard-viewer/nile-dashboard-viewer.css.js +29 -0
- package/dist/src/nile-dashboard-viewer/nile-dashboard-viewer.d.ts +43 -0
- package/dist/src/nile-dashboard-viewer/nile-dashboard-viewer.js +84 -0
- package/dist/src/nile-map-chart/index.d.ts +2 -0
- package/dist/src/nile-map-chart/index.js +2 -0
- package/dist/src/nile-map-chart/nile-map-chart.css.d.ts +1 -0
- package/dist/src/nile-map-chart/nile-map-chart.css.js +28 -0
- package/dist/src/nile-map-chart/nile-map-chart.d.ts +74 -0
- package/dist/src/nile-map-chart/nile-map-chart.js +263 -0
- package/dist/src/nile-widget-viewer/index.d.ts +3 -0
- package/dist/src/nile-widget-viewer/index.js +2 -0
- package/dist/src/nile-widget-viewer/nile-widget-viewer.css.d.ts +1 -0
- package/dist/src/nile-widget-viewer/nile-widget-viewer.css.js +20 -0
- package/dist/src/nile-widget-viewer/nile-widget-viewer.d.ts +33 -0
- package/dist/src/nile-widget-viewer/nile-widget-viewer.js +50 -0
- package/package.json +4 -2
|
@@ -19,6 +19,7 @@ import '../nile-spline-chart/index.js';
|
|
|
19
19
|
import '../nile-radar-chart/index.js';
|
|
20
20
|
import '../nile-gauge-chart/index.js';
|
|
21
21
|
import '../nile-waterfall-chart/index.js';
|
|
22
|
+
import '../nile-map-chart/index.js';
|
|
22
23
|
import '../nile-cluster-chart/index.js';
|
|
23
24
|
import '../nile-stacked-chart/index.js';
|
|
24
25
|
import '../nile-histogram-chart/index.js';
|
|
@@ -66,6 +67,7 @@ const CORE_CHART_LABELS = {
|
|
|
66
67
|
radar: 'Radar',
|
|
67
68
|
gauge: 'Gauge',
|
|
68
69
|
waterfall: 'Waterfall',
|
|
70
|
+
map: 'Map',
|
|
69
71
|
stacked: 'Stacked column',
|
|
70
72
|
cluster: 'Cluster',
|
|
71
73
|
histogram: 'Histogram',
|
|
@@ -107,6 +109,11 @@ let NileChart = class NileChart extends NileElement {
|
|
|
107
109
|
*/
|
|
108
110
|
this.chartTypeAttr = '';
|
|
109
111
|
/** Summary/insight text — shown as the AI panel's opening message when the chat is opened. */
|
|
112
|
+
/**
|
|
113
|
+
* When set, fills `chart.type` if the config omits it (same values as `chart.type`, e.g. `stacked`, `pie`).
|
|
114
|
+
* Usage: `<nile-chart chart-type="pie" />` plus `config.chart` with series data only.
|
|
115
|
+
*/
|
|
116
|
+
/** Summary/insight text — shown as the AI panel's opening message when the chat is opened. */
|
|
110
117
|
this.summary = '';
|
|
111
118
|
this.activeType = null;
|
|
112
119
|
this.activeConfig = null;
|
|
@@ -120,6 +127,7 @@ let NileChart = class NileChart extends NileElement {
|
|
|
120
127
|
if (!this.contains(e.target)) {
|
|
121
128
|
this.menuOpen = false;
|
|
122
129
|
this.chatOpen = false;
|
|
130
|
+
this.chatOpen = false;
|
|
123
131
|
}
|
|
124
132
|
};
|
|
125
133
|
this.resolvedConfig = null;
|
|
@@ -128,8 +136,10 @@ let NileChart = class NileChart extends NileElement {
|
|
|
128
136
|
return this.resolvedConfig?.summary ?? this.summary;
|
|
129
137
|
}
|
|
130
138
|
/** AI panel shows when ai.enabled is true OR when a summary is provided. */
|
|
139
|
+
/** AI panel shows when ai.enabled is true OR when a summary is provided. */
|
|
131
140
|
get aiEnabled() {
|
|
132
141
|
return this.resolvedConfig?.ai?.enabled === true || !!this.effectiveSummary;
|
|
142
|
+
return this.resolvedConfig?.ai?.enabled === true || !!this.effectiveSummary;
|
|
133
143
|
}
|
|
134
144
|
connectedCallback() {
|
|
135
145
|
super.connectedCallback();
|
|
@@ -248,12 +258,22 @@ let NileChart = class NileChart extends NileElement {
|
|
|
248
258
|
super.firstUpdated(changedProperties);
|
|
249
259
|
this.syncHeaderSlots();
|
|
250
260
|
}
|
|
261
|
+
/** Direct children with `slot=` — header row renders on first paint before slot assignment runs. */
|
|
262
|
+
lightDomHasSlot(name) {
|
|
263
|
+
for (let i = 0; i < this.children.length; i++) {
|
|
264
|
+
if (this.children[i].getAttribute('slot') === name)
|
|
265
|
+
return true;
|
|
266
|
+
}
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
251
269
|
shouldShowHeader() {
|
|
252
270
|
const hasTitles = !!(this.headerTitle || this.headerSubtitle);
|
|
253
271
|
const hasBuiltinActions = this.aiEnabled || (this.resolvedConfig?.switchableTypes?.length ?? 0) > 0;
|
|
254
272
|
return (hasTitles ||
|
|
255
273
|
this.hasHeaderSlotContent ||
|
|
256
274
|
this.hasHeaderActionsSlot ||
|
|
275
|
+
this.lightDomHasSlot('header') ||
|
|
276
|
+
this.lightDomHasSlot('header-actions') ||
|
|
257
277
|
hasBuiltinActions);
|
|
258
278
|
}
|
|
259
279
|
renderTypeSwitcher() {
|
|
@@ -429,6 +449,7 @@ let NileChart = class NileChart extends NileElement {
|
|
|
429
449
|
.height=${config.height ?? '400px'}
|
|
430
450
|
.innerSize=${config.innerSize ?? '50%'}
|
|
431
451
|
.semiCircle=${config.semiCircle ?? false}
|
|
452
|
+
.semiCircle=${config.semiCircle ?? false}
|
|
432
453
|
.showDataLabels=${config.showDataLabels ?? true}
|
|
433
454
|
.showLegend=${config.showLegend ?? true}
|
|
434
455
|
.options=${mergedOptions}
|
|
@@ -489,6 +510,17 @@ let NileChart = class NileChart extends NileElement {
|
|
|
489
510
|
.options=${mergedOptions}
|
|
490
511
|
.loading=${config.loading ?? false}
|
|
491
512
|
></nile-waterfall-chart>`;
|
|
513
|
+
case 'map':
|
|
514
|
+
return html `<nile-map-chart
|
|
515
|
+
.data=${config.data}
|
|
516
|
+
.mapData=${config.mapData ?? null}
|
|
517
|
+
.joinBy=${config.joinBy ?? ['hc-key', 'hc-key']}
|
|
518
|
+
.seriesType=${config.seriesType ?? 'map'}
|
|
519
|
+
.zoom=${config.zoom ?? true}
|
|
520
|
+
.height=${config.height ?? '500px'}
|
|
521
|
+
.options=${mergedOptions}
|
|
522
|
+
.loading=${config.loading ?? false}
|
|
523
|
+
></nile-map-chart>`;
|
|
492
524
|
case 'stacked':
|
|
493
525
|
return html `<nile-stacked-chart
|
|
494
526
|
.data=${config.data}
|
|
@@ -864,6 +896,7 @@ let NileChart = class NileChart extends NileElement {
|
|
|
864
896
|
</div>
|
|
865
897
|
</div>
|
|
866
898
|
<slot name="footer"></slot>
|
|
899
|
+
<slot name="footer"></slot>
|
|
867
900
|
</div>
|
|
868
901
|
`;
|
|
869
902
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const styles: import("lit").CSSResult;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
export const styles = css `
|
|
3
|
+
:host {
|
|
4
|
+
display: block;
|
|
5
|
+
width: 100%;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
:host([hidden]) {
|
|
9
|
+
display: none;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.dashboard-grid {
|
|
13
|
+
display: grid;
|
|
14
|
+
width: 100%;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.dashboard-cell {
|
|
18
|
+
overflow: hidden;
|
|
19
|
+
min-height: 0;
|
|
20
|
+
min-width: 0;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
nile-widget-viewer {
|
|
24
|
+
display: block;
|
|
25
|
+
width: 100%;
|
|
26
|
+
height: 100%;
|
|
27
|
+
}
|
|
28
|
+
`;
|
|
29
|
+
//# sourceMappingURL=nile-dashboard-viewer.css.js.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { nothing } from 'lit';
|
|
2
|
+
import type { CSSResultGroup, TemplateResult } from 'lit';
|
|
3
|
+
import NileElement from '../internal/nile-element.js';
|
|
4
|
+
import type { NileDashboardConfig } from '../internal/types/dashboard-config.type.js';
|
|
5
|
+
import '../nile-widget-viewer/index.js';
|
|
6
|
+
/**
|
|
7
|
+
* Renders a full dashboard grid of widgets. Each widget is positioned using CSS Grid
|
|
8
|
+
* with the `layout: { x, y, w, h }` values from its config.
|
|
9
|
+
*
|
|
10
|
+
* - `x` / `w` → `grid-column: (x+1) / span w`
|
|
11
|
+
* - `y` / `h` → `grid-row: (y+1) / span h`
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```html
|
|
15
|
+
* <nile-dashboard-viewer columns="12" cell-height="80" gap="8"></nile-dashboard-viewer>
|
|
16
|
+
* ```
|
|
17
|
+
* ```js
|
|
18
|
+
* el.config = {
|
|
19
|
+
* name: 'My Dashboard',
|
|
20
|
+
* widgets: [
|
|
21
|
+
* { type: 'chart', layout: { x: 0, y: 0, w: 6, h: 4 }, nileConfig: { chart: { type: 'pie', data: [...] } } },
|
|
22
|
+
* { type: 'kpi', layout: { x: 0, y: 4, w: 3, h: 2 }, nileConfig: { chart: { type: 'kpi', label: 'Revenue', value: '$1.2M' } } },
|
|
23
|
+
* ]
|
|
24
|
+
* };
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare class NileDashboardViewer extends NileElement {
|
|
28
|
+
static styles: CSSResultGroup;
|
|
29
|
+
/** Dashboard configuration containing all widget configs. */
|
|
30
|
+
config: NileDashboardConfig | null;
|
|
31
|
+
/** Total number of grid columns. Default: 12. */
|
|
32
|
+
columns: number;
|
|
33
|
+
/** Height of a single grid row in pixels. Default: 80. */
|
|
34
|
+
cellHeight: number;
|
|
35
|
+
/** Gap between grid cells in pixels. Default: 8. */
|
|
36
|
+
gap: number;
|
|
37
|
+
render(): TemplateResult | typeof nothing;
|
|
38
|
+
}
|
|
39
|
+
declare global {
|
|
40
|
+
interface HTMLElementTagNameMap {
|
|
41
|
+
'nile-dashboard-viewer': NileDashboardViewer;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { customElement, property } from 'lit/decorators.js';
|
|
3
|
+
import { html, nothing } from 'lit';
|
|
4
|
+
import NileElement from '../internal/nile-element.js';
|
|
5
|
+
import { styles } from './nile-dashboard-viewer.css.js';
|
|
6
|
+
import '../nile-widget-viewer/index.js';
|
|
7
|
+
/**
|
|
8
|
+
* Renders a full dashboard grid of widgets. Each widget is positioned using CSS Grid
|
|
9
|
+
* with the `layout: { x, y, w, h }` values from its config.
|
|
10
|
+
*
|
|
11
|
+
* - `x` / `w` → `grid-column: (x+1) / span w`
|
|
12
|
+
* - `y` / `h` → `grid-row: (y+1) / span h`
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```html
|
|
16
|
+
* <nile-dashboard-viewer columns="12" cell-height="80" gap="8"></nile-dashboard-viewer>
|
|
17
|
+
* ```
|
|
18
|
+
* ```js
|
|
19
|
+
* el.config = {
|
|
20
|
+
* name: 'My Dashboard',
|
|
21
|
+
* widgets: [
|
|
22
|
+
* { type: 'chart', layout: { x: 0, y: 0, w: 6, h: 4 }, nileConfig: { chart: { type: 'pie', data: [...] } } },
|
|
23
|
+
* { type: 'kpi', layout: { x: 0, y: 4, w: 3, h: 2 }, nileConfig: { chart: { type: 'kpi', label: 'Revenue', value: '$1.2M' } } },
|
|
24
|
+
* ]
|
|
25
|
+
* };
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
let NileDashboardViewer = class NileDashboardViewer extends NileElement {
|
|
29
|
+
constructor() {
|
|
30
|
+
super(...arguments);
|
|
31
|
+
/** Dashboard configuration containing all widget configs. */
|
|
32
|
+
this.config = null;
|
|
33
|
+
/** Total number of grid columns. Default: 12. */
|
|
34
|
+
this.columns = 12;
|
|
35
|
+
/** Height of a single grid row in pixels. Default: 80. */
|
|
36
|
+
this.cellHeight = 80;
|
|
37
|
+
/** Gap between grid cells in pixels. Default: 8. */
|
|
38
|
+
this.gap = 8;
|
|
39
|
+
}
|
|
40
|
+
render() {
|
|
41
|
+
if (!this.config?.widgets?.length)
|
|
42
|
+
return nothing;
|
|
43
|
+
return html `
|
|
44
|
+
<div
|
|
45
|
+
class="dashboard-grid"
|
|
46
|
+
style="
|
|
47
|
+
grid-template-columns: repeat(${this.columns}, 1fr);
|
|
48
|
+
grid-auto-rows: ${this.cellHeight}px;
|
|
49
|
+
gap: ${this.gap}px;
|
|
50
|
+
"
|
|
51
|
+
>
|
|
52
|
+
${this.config.widgets.map((widget) => html `
|
|
53
|
+
<div
|
|
54
|
+
class="dashboard-cell"
|
|
55
|
+
style="
|
|
56
|
+
grid-column: ${widget.layout.x + 1} / span ${widget.layout.w};
|
|
57
|
+
grid-row: ${widget.layout.y + 1} / span ${widget.layout.h};
|
|
58
|
+
"
|
|
59
|
+
>
|
|
60
|
+
<nile-widget-viewer .config=${widget}></nile-widget-viewer>
|
|
61
|
+
</div>
|
|
62
|
+
`)}
|
|
63
|
+
</div>
|
|
64
|
+
`;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
NileDashboardViewer.styles = styles;
|
|
68
|
+
__decorate([
|
|
69
|
+
property({ type: Object })
|
|
70
|
+
], NileDashboardViewer.prototype, "config", void 0);
|
|
71
|
+
__decorate([
|
|
72
|
+
property({ type: Number })
|
|
73
|
+
], NileDashboardViewer.prototype, "columns", void 0);
|
|
74
|
+
__decorate([
|
|
75
|
+
property({ type: Number, attribute: 'cell-height' })
|
|
76
|
+
], NileDashboardViewer.prototype, "cellHeight", void 0);
|
|
77
|
+
__decorate([
|
|
78
|
+
property({ type: Number })
|
|
79
|
+
], NileDashboardViewer.prototype, "gap", void 0);
|
|
80
|
+
NileDashboardViewer = __decorate([
|
|
81
|
+
customElement('nile-dashboard-viewer')
|
|
82
|
+
], NileDashboardViewer);
|
|
83
|
+
export { NileDashboardViewer };
|
|
84
|
+
//# sourceMappingURL=nile-dashboard-viewer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const styles: import("lit").CSSResult;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
export const styles = css `
|
|
3
|
+
:host {
|
|
4
|
+
display: block;
|
|
5
|
+
width: 100%;
|
|
6
|
+
position: relative;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
:host([hidden]) {
|
|
10
|
+
display: none;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.chart-container {
|
|
14
|
+
width: 100%;
|
|
15
|
+
min-height: var(--nile-height-200px, var(--ng-height-200px));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.chart-loading {
|
|
19
|
+
display: flex;
|
|
20
|
+
align-items: center;
|
|
21
|
+
justify-content: center;
|
|
22
|
+
min-height: inherit;
|
|
23
|
+
color: var(--nile-colors-neutral-700, var(--ng-colors-text-secondary-700));
|
|
24
|
+
font-family: var(--nile-font-family-serif, var(--ng-font-family-body));
|
|
25
|
+
font-size: var(--nile-type-scale-3, var(--ng-font-size-text-sm));
|
|
26
|
+
}
|
|
27
|
+
`;
|
|
28
|
+
//# sourceMappingURL=nile-map-chart.css.js.map
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { CSSResultGroup, PropertyValues, TemplateResult } from 'lit';
|
|
2
|
+
import type Highcharts from 'highcharts';
|
|
3
|
+
import NileElement from '../internal/nile-element.js';
|
|
4
|
+
import type { NileChartConfigInputType } from '../internal/types/index.js';
|
|
5
|
+
export interface MapChartDataPoint {
|
|
6
|
+
/** Highcharts map key matching the map topology (e.g. 'us-ca'). */
|
|
7
|
+
'hc-key'?: string;
|
|
8
|
+
value: number;
|
|
9
|
+
name?: string;
|
|
10
|
+
color?: string;
|
|
11
|
+
[key: string]: unknown;
|
|
12
|
+
}
|
|
13
|
+
export declare class NileMapChart extends NileElement {
|
|
14
|
+
static styles: CSSResultGroup;
|
|
15
|
+
private _hc;
|
|
16
|
+
private chart;
|
|
17
|
+
private resizeObserver;
|
|
18
|
+
private chartContainer;
|
|
19
|
+
/** Full chart configuration. Accepts separated { chart, aq } input. */
|
|
20
|
+
config: NileChartConfigInputType | null;
|
|
21
|
+
/** The chart title displayed above the chart. */
|
|
22
|
+
chartTitle: string;
|
|
23
|
+
/** The subtitle displayed below the title. */
|
|
24
|
+
chartSubtitle: string;
|
|
25
|
+
/**
|
|
26
|
+
* Array of data points. Each point should have a value and a key matching the
|
|
27
|
+
* map topology (e.g. `{ 'hc-key': 'us-ca', value: 42 }`).
|
|
28
|
+
*/
|
|
29
|
+
data: MapChartDataPoint[];
|
|
30
|
+
/**
|
|
31
|
+
* GeoJSON or Highcharts topology object describing the map shapes.
|
|
32
|
+
* Obtain from https://code.highcharts.com/mapdata/ or supply your own.
|
|
33
|
+
*/
|
|
34
|
+
mapData: object | null;
|
|
35
|
+
/**
|
|
36
|
+
* How to join `data` with `mapData`. Defaults to `['hc-key', 'hc-key']`.
|
|
37
|
+
* Pass a single string to match by that property name on both sides,
|
|
38
|
+
* or a two-element array `[mapKey, dataKey]` for different key names.
|
|
39
|
+
*/
|
|
40
|
+
joinBy: string | string[];
|
|
41
|
+
/** Deep-merge override object for full Highcharts options. */
|
|
42
|
+
options: Highcharts.Options;
|
|
43
|
+
/** Whether to show a loading indicator instead of the chart. */
|
|
44
|
+
loading: boolean;
|
|
45
|
+
/** CSS height for the chart container. */
|
|
46
|
+
height: string;
|
|
47
|
+
/** Enable mouse-wheel zoom, double-click zoom, and +/− zoom buttons. Default: true. */
|
|
48
|
+
zoom: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Type of the primary map series.
|
|
51
|
+
* - `'map'` (default) — choropleth/filled regions
|
|
52
|
+
* - `'mapline'` — line/route overlay
|
|
53
|
+
* - `'mappoint'` — scatter points on map
|
|
54
|
+
* - `'mapbubble'` — sized bubbles on map
|
|
55
|
+
* For multi-series or `tiledwebmap`, pass `options.series` directly (it replaces the default series).
|
|
56
|
+
*/
|
|
57
|
+
seriesType: 'map' | 'mapline' | 'mappoint' | 'mapbubble' | 'tiledwebmap';
|
|
58
|
+
/** Apply { chart, aq } config to individual properties. */
|
|
59
|
+
private applyConfig;
|
|
60
|
+
connectedCallback(): void;
|
|
61
|
+
disconnectedCallback(): void;
|
|
62
|
+
protected firstUpdated(): void;
|
|
63
|
+
protected updated(changedProperties: PropertyValues): void;
|
|
64
|
+
private setupResizeObserver;
|
|
65
|
+
private buildOptions;
|
|
66
|
+
private initChart;
|
|
67
|
+
private destroyChart;
|
|
68
|
+
render(): TemplateResult;
|
|
69
|
+
}
|
|
70
|
+
declare global {
|
|
71
|
+
interface HTMLElementTagNameMap {
|
|
72
|
+
'nile-map-chart': NileMapChart;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { customElement, property, query } from 'lit/decorators.js';
|
|
3
|
+
import { html } from 'lit';
|
|
4
|
+
import NileElement from '../internal/nile-element.js';
|
|
5
|
+
import { getHighcharts } from '../internal/highcharts-provider.js';
|
|
6
|
+
import { deepMerge } from '../internal/utils.js';
|
|
7
|
+
import { styles } from './nile-map-chart.css.js';
|
|
8
|
+
let NileMapChart = class NileMapChart extends NileElement {
|
|
9
|
+
constructor() {
|
|
10
|
+
super(...arguments);
|
|
11
|
+
this._hc = null;
|
|
12
|
+
this.chart = null;
|
|
13
|
+
this.resizeObserver = null;
|
|
14
|
+
/** Full chart configuration. Accepts separated { chart, aq } input. */
|
|
15
|
+
this.config = null;
|
|
16
|
+
/** The chart title displayed above the chart. */
|
|
17
|
+
this.chartTitle = '';
|
|
18
|
+
/** The subtitle displayed below the title. */
|
|
19
|
+
this.chartSubtitle = '';
|
|
20
|
+
/**
|
|
21
|
+
* Array of data points. Each point should have a value and a key matching the
|
|
22
|
+
* map topology (e.g. `{ 'hc-key': 'us-ca', value: 42 }`).
|
|
23
|
+
*/
|
|
24
|
+
this.data = [];
|
|
25
|
+
/**
|
|
26
|
+
* GeoJSON or Highcharts topology object describing the map shapes.
|
|
27
|
+
* Obtain from https://code.highcharts.com/mapdata/ or supply your own.
|
|
28
|
+
*/
|
|
29
|
+
this.mapData = null;
|
|
30
|
+
/**
|
|
31
|
+
* How to join `data` with `mapData`. Defaults to `['hc-key', 'hc-key']`.
|
|
32
|
+
* Pass a single string to match by that property name on both sides,
|
|
33
|
+
* or a two-element array `[mapKey, dataKey]` for different key names.
|
|
34
|
+
*/
|
|
35
|
+
this.joinBy = ['hc-key', 'hc-key'];
|
|
36
|
+
/** Deep-merge override object for full Highcharts options. */
|
|
37
|
+
this.options = {};
|
|
38
|
+
/** Whether to show a loading indicator instead of the chart. */
|
|
39
|
+
this.loading = false;
|
|
40
|
+
/** CSS height for the chart container. */
|
|
41
|
+
this.height = '500px';
|
|
42
|
+
/** Enable mouse-wheel zoom, double-click zoom, and +/− zoom buttons. Default: true. */
|
|
43
|
+
this.zoom = true;
|
|
44
|
+
/**
|
|
45
|
+
* Type of the primary map series.
|
|
46
|
+
* - `'map'` (default) — choropleth/filled regions
|
|
47
|
+
* - `'mapline'` — line/route overlay
|
|
48
|
+
* - `'mappoint'` — scatter points on map
|
|
49
|
+
* - `'mapbubble'` — sized bubbles on map
|
|
50
|
+
* For multi-series or `tiledwebmap`, pass `options.series` directly (it replaces the default series).
|
|
51
|
+
*/
|
|
52
|
+
this.seriesType = 'map';
|
|
53
|
+
}
|
|
54
|
+
/** Apply { chart, aq } config to individual properties. */
|
|
55
|
+
applyConfig(cfg) {
|
|
56
|
+
const { chart: c, aq } = cfg;
|
|
57
|
+
if (c) {
|
|
58
|
+
const map = c;
|
|
59
|
+
if (map.data)
|
|
60
|
+
this.data = map.data;
|
|
61
|
+
if (map.mapData)
|
|
62
|
+
this.mapData = map.mapData;
|
|
63
|
+
if (map.joinBy !== undefined)
|
|
64
|
+
this.joinBy = map.joinBy;
|
|
65
|
+
if (map.seriesType)
|
|
66
|
+
this.seriesType = map.seriesType;
|
|
67
|
+
if (map.height)
|
|
68
|
+
this.height = map.height;
|
|
69
|
+
if (map.loading !== undefined)
|
|
70
|
+
this.loading = map.loading;
|
|
71
|
+
if (map.zoom !== undefined)
|
|
72
|
+
this.zoom = map.zoom;
|
|
73
|
+
if (map.options)
|
|
74
|
+
this.options = map.options;
|
|
75
|
+
}
|
|
76
|
+
if (aq) {
|
|
77
|
+
if (aq.chartTitle)
|
|
78
|
+
this.chartTitle = aq.chartTitle;
|
|
79
|
+
if (aq.chartSubtitle)
|
|
80
|
+
this.chartSubtitle = aq.chartSubtitle;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
connectedCallback() {
|
|
84
|
+
super.connectedCallback();
|
|
85
|
+
if (this.config)
|
|
86
|
+
this.applyConfig(this.config);
|
|
87
|
+
}
|
|
88
|
+
disconnectedCallback() {
|
|
89
|
+
super.disconnectedCallback();
|
|
90
|
+
this.destroyChart();
|
|
91
|
+
this.resizeObserver?.disconnect();
|
|
92
|
+
this.resizeObserver = null;
|
|
93
|
+
}
|
|
94
|
+
firstUpdated() {
|
|
95
|
+
// If config was set synchronously before the first render (common when the
|
|
96
|
+
// consumer assigns `.config = {...}` immediately after the element is in the
|
|
97
|
+
// DOM), connectedCallback will have missed it. Apply it here so buildOptions()
|
|
98
|
+
// has the full options—including series type, mapView, and projection—before
|
|
99
|
+
// Highcharts is ever initialised.
|
|
100
|
+
if (this.config)
|
|
101
|
+
this.applyConfig(this.config);
|
|
102
|
+
this.initChart();
|
|
103
|
+
this.setupResizeObserver();
|
|
104
|
+
}
|
|
105
|
+
updated(changedProperties) {
|
|
106
|
+
if (changedProperties.has('config') && this.config) {
|
|
107
|
+
this.applyConfig(this.config);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const chartProps = [
|
|
111
|
+
'data',
|
|
112
|
+
'mapData',
|
|
113
|
+
'joinBy',
|
|
114
|
+
'chartTitle',
|
|
115
|
+
'chartSubtitle',
|
|
116
|
+
'options',
|
|
117
|
+
'height',
|
|
118
|
+
'loading',
|
|
119
|
+
'zoom',
|
|
120
|
+
'seriesType',
|
|
121
|
+
];
|
|
122
|
+
const needsUpdate = chartProps.some(p => changedProperties.has(p));
|
|
123
|
+
if (!needsUpdate)
|
|
124
|
+
return;
|
|
125
|
+
if (this.loading) {
|
|
126
|
+
this.destroyChart();
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (this.chart) {
|
|
130
|
+
this.chart.update(this.buildOptions(), true, true);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
this.initChart();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
setupResizeObserver() {
|
|
137
|
+
if (!this.chartContainer)
|
|
138
|
+
return;
|
|
139
|
+
this.resizeObserver = new ResizeObserver(() => {
|
|
140
|
+
this.chart?.reflow();
|
|
141
|
+
});
|
|
142
|
+
this.resizeObserver.observe(this.chartContainer);
|
|
143
|
+
}
|
|
144
|
+
buildOptions() {
|
|
145
|
+
const self = this;
|
|
146
|
+
const defaults = {
|
|
147
|
+
chart: {
|
|
148
|
+
height: this.height,
|
|
149
|
+
},
|
|
150
|
+
title: {
|
|
151
|
+
text: this.chartTitle || undefined,
|
|
152
|
+
},
|
|
153
|
+
subtitle: {
|
|
154
|
+
text: this.chartSubtitle || undefined,
|
|
155
|
+
},
|
|
156
|
+
colorAxis: {
|
|
157
|
+
min: 0,
|
|
158
|
+
},
|
|
159
|
+
legend: {
|
|
160
|
+
enabled: true,
|
|
161
|
+
},
|
|
162
|
+
mapNavigation: {
|
|
163
|
+
enabled: this.zoom,
|
|
164
|
+
enableMouseWheelZoom: this.zoom,
|
|
165
|
+
enableDoubleClickZoom: this.zoom,
|
|
166
|
+
enableDoubleClickZoomTo: false,
|
|
167
|
+
buttonOptions: {
|
|
168
|
+
alignTo: 'spacingBox',
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
series: this.seriesType !== 'tiledwebmap' ? [
|
|
172
|
+
{
|
|
173
|
+
type: this.seriesType,
|
|
174
|
+
data: this.data,
|
|
175
|
+
mapData: this.mapData ?? undefined,
|
|
176
|
+
joinBy: this.joinBy,
|
|
177
|
+
cursor: 'pointer',
|
|
178
|
+
point: {
|
|
179
|
+
events: {
|
|
180
|
+
click() {
|
|
181
|
+
self.emit('nile-chart-click', {
|
|
182
|
+
point: this,
|
|
183
|
+
name: this.name,
|
|
184
|
+
value: this.value,
|
|
185
|
+
key: this['hc-key'],
|
|
186
|
+
});
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
] : [],
|
|
192
|
+
credits: {
|
|
193
|
+
enabled: false,
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
return deepMerge(defaults, this.options);
|
|
197
|
+
}
|
|
198
|
+
async initChart() {
|
|
199
|
+
if (this.loading || !this.chartContainer)
|
|
200
|
+
return;
|
|
201
|
+
if (!this._hc)
|
|
202
|
+
this._hc = await getHighcharts();
|
|
203
|
+
// Highcharts Maps module adds mapChart(); fall back to chart() if unavailable.
|
|
204
|
+
const hcAny = this._hc;
|
|
205
|
+
const factory = typeof hcAny.mapChart === 'function' ? hcAny.mapChart : hcAny.chart;
|
|
206
|
+
this.chart = factory(this.chartContainer, this.buildOptions());
|
|
207
|
+
this.emit('nile-chart-ready', { chart: this.chart });
|
|
208
|
+
}
|
|
209
|
+
destroyChart() {
|
|
210
|
+
if (this.chart) {
|
|
211
|
+
this.chart.destroy();
|
|
212
|
+
this.chart = null;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
render() {
|
|
216
|
+
if (this.loading) {
|
|
217
|
+
return html `<div class="chart-loading" style="height:${this.height}">Loading...</div>`;
|
|
218
|
+
}
|
|
219
|
+
return html `<div class="chart-container"></div>`;
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
NileMapChart.styles = styles;
|
|
223
|
+
__decorate([
|
|
224
|
+
query('.chart-container')
|
|
225
|
+
], NileMapChart.prototype, "chartContainer", void 0);
|
|
226
|
+
__decorate([
|
|
227
|
+
property({ type: Object })
|
|
228
|
+
], NileMapChart.prototype, "config", void 0);
|
|
229
|
+
__decorate([
|
|
230
|
+
property({ type: String, attribute: 'chart-title' })
|
|
231
|
+
], NileMapChart.prototype, "chartTitle", void 0);
|
|
232
|
+
__decorate([
|
|
233
|
+
property({ type: String, attribute: 'chart-subtitle' })
|
|
234
|
+
], NileMapChart.prototype, "chartSubtitle", void 0);
|
|
235
|
+
__decorate([
|
|
236
|
+
property({ type: Array })
|
|
237
|
+
], NileMapChart.prototype, "data", void 0);
|
|
238
|
+
__decorate([
|
|
239
|
+
property({ type: Object })
|
|
240
|
+
], NileMapChart.prototype, "mapData", void 0);
|
|
241
|
+
__decorate([
|
|
242
|
+
property({ type: Array })
|
|
243
|
+
], NileMapChart.prototype, "joinBy", void 0);
|
|
244
|
+
__decorate([
|
|
245
|
+
property({ type: Object })
|
|
246
|
+
], NileMapChart.prototype, "options", void 0);
|
|
247
|
+
__decorate([
|
|
248
|
+
property({ type: Boolean, reflect: true })
|
|
249
|
+
], NileMapChart.prototype, "loading", void 0);
|
|
250
|
+
__decorate([
|
|
251
|
+
property({ type: String })
|
|
252
|
+
], NileMapChart.prototype, "height", void 0);
|
|
253
|
+
__decorate([
|
|
254
|
+
property({ type: Boolean })
|
|
255
|
+
], NileMapChart.prototype, "zoom", void 0);
|
|
256
|
+
__decorate([
|
|
257
|
+
property({ type: String })
|
|
258
|
+
], NileMapChart.prototype, "seriesType", void 0);
|
|
259
|
+
NileMapChart = __decorate([
|
|
260
|
+
customElement('nile-map-chart')
|
|
261
|
+
], NileMapChart);
|
|
262
|
+
export { NileMapChart };
|
|
263
|
+
//# sourceMappingURL=nile-map-chart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const styles: import("lit").CSSResult;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
export const styles = css `
|
|
3
|
+
:host {
|
|
4
|
+
display: block;
|
|
5
|
+
width: 100%;
|
|
6
|
+
height: 100%;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
:host([hidden]) {
|
|
10
|
+
display: none;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
nile-chart,
|
|
14
|
+
nile-kpi-chart {
|
|
15
|
+
display: block;
|
|
16
|
+
width: 100%;
|
|
17
|
+
height: 100%;
|
|
18
|
+
}
|
|
19
|
+
`;
|
|
20
|
+
//# sourceMappingURL=nile-widget-viewer.css.js.map
|