@aquera/nile-visualization 0.4.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-kpi-config.type.d.ts +5 -21
- 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 +2 -1
- package/dist/src/internal/types/primitive-chart-config.type.d.ts +2 -1
- 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-ai-panel/nile-ai-panel.css.js +8 -0
- package/dist/src/nile-ai-panel/nile-ai-panel.d.ts +2 -0
- package/dist/src/nile-ai-panel/nile-ai-panel.js +8 -0
- package/dist/src/nile-chart/index.d.ts +2 -2
- package/dist/src/nile-chart/nile-chart-config.d.ts +121 -29
- package/dist/src/nile-chart/nile-chart.css.js +32 -7
- package/dist/src/nile-chart/nile-chart.d.ts +23 -7
- package/dist/src/nile-chart/nile-chart.js +148 -49
- 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-kpi-chart/nile-kpi-chart.css.js +4 -4
- package/dist/src/nile-kpi-chart/nile-kpi-chart.d.ts +2 -0
- package/dist/src/nile-kpi-chart/nile-kpi-chart.js +6 -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
|
@@ -13,7 +13,7 @@ export const styles = css `
|
|
|
13
13
|
/* ── Unified Card Container ── */
|
|
14
14
|
|
|
15
15
|
.chart-card {
|
|
16
|
-
background: var(--nile-colors-white-base, var(--ng-colors-bg-
|
|
16
|
+
background: var(--nile-colors-white-base, var(--ng-colors-bg-primary));
|
|
17
17
|
border: var(--nile-border-width-1, var(--ng-stroke-width-1)) solid var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
|
|
18
18
|
border-radius: var(--nile-radius-radius-3xl, var(--ng-radius-xl));
|
|
19
19
|
box-shadow: var(--nile-box-shadow-3, var(--ng-shadow-sm));
|
|
@@ -33,7 +33,7 @@ export const styles = css `
|
|
|
33
33
|
position: relative;
|
|
34
34
|
z-index: 10;
|
|
35
35
|
padding: var(--nile-spacing-2xl, var(--ng-spacing-2xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl)) var(--nile-spacing-xl, var(--ng-spacing-xl));
|
|
36
|
-
background:
|
|
36
|
+
background: transparent;
|
|
37
37
|
border-bottom: var(--nile-border-width-1, var(--ng-stroke-width-1)) solid var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
|
|
38
38
|
border-radius: var(--nile-radius-radius-3xl, var(--ng-radius-xl)) var(--nile-radius-radius-3xl, var(--ng-radius-xl)) 0 0;
|
|
39
39
|
}
|
|
@@ -82,10 +82,35 @@ export const styles = css `
|
|
|
82
82
|
contain: layout style;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
/* ── Default slot (custom chart body only — not named slots) ── */
|
|
86
|
+
slot:not([name])::slotted(*) {
|
|
87
|
+
display: block;
|
|
86
88
|
width: 100%;
|
|
87
89
|
}
|
|
88
90
|
|
|
91
|
+
/* ── header / header-actions slots (one row; built-in AI + switcher on the right) ── */
|
|
92
|
+
slot[name='header']::slotted(*) {
|
|
93
|
+
display: block;
|
|
94
|
+
width: 100%;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
slot[name='header-actions']::slotted(*) {
|
|
98
|
+
display: inline-flex;
|
|
99
|
+
align-items: center;
|
|
100
|
+
gap: var(--nile-spacing-xs, var(--ng-spacing-xs));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/* ── footer slot ── */
|
|
104
|
+
slot[name='footer']::slotted(*) {
|
|
105
|
+
display: block;
|
|
106
|
+
margin: 0;
|
|
107
|
+
padding: var(--nile-spacing-xl, var(--ng-spacing-xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl));
|
|
108
|
+
border-top: var(--nile-border-width-1, var(--ng-stroke-width-1)) solid var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
|
|
109
|
+
font-family: var(--nile-font-family-serif, var(--ng-font-family-body));
|
|
110
|
+
font-size: var(--nile-type-scale-2, var(--ng-font-size-text-xs));
|
|
111
|
+
color: var(--nile-colors-neutral-700, var(--ng-colors-text-secondary-700));
|
|
112
|
+
}
|
|
113
|
+
|
|
89
114
|
nile-bar-chart,
|
|
90
115
|
nile-pie-chart,
|
|
91
116
|
nile-trendline-chart,
|
|
@@ -128,7 +153,7 @@ export const styles = css `
|
|
|
128
153
|
}
|
|
129
154
|
|
|
130
155
|
.chart-toggle:hover {
|
|
131
|
-
background: var(--nile-colors-
|
|
156
|
+
background: var(--nile-colors-white-base, var(--ng-colors-bg-primary));
|
|
132
157
|
box-shadow: var(--nile-box-shadow-3, var(--ng-shadow-sm));
|
|
133
158
|
}
|
|
134
159
|
|
|
@@ -188,7 +213,7 @@ export const styles = css `
|
|
|
188
213
|
}
|
|
189
214
|
|
|
190
215
|
.chart-menu-trigger:hover {
|
|
191
|
-
background:
|
|
216
|
+
background: transparent;
|
|
192
217
|
color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));
|
|
193
218
|
}
|
|
194
219
|
|
|
@@ -228,7 +253,7 @@ export const styles = css `
|
|
|
228
253
|
}
|
|
229
254
|
|
|
230
255
|
.chart-menu-item:hover {
|
|
231
|
-
background:
|
|
256
|
+
background: transparent;
|
|
232
257
|
}
|
|
233
258
|
|
|
234
259
|
.chart-menu-item.active {
|
|
@@ -259,7 +284,7 @@ export const styles = css `
|
|
|
259
284
|
}
|
|
260
285
|
|
|
261
286
|
.ai-trigger:hover {
|
|
262
|
-
background:
|
|
287
|
+
background: transparent;
|
|
263
288
|
color: var(--nile-colors-primary-600, var(--ng-colors-fg-brand-primary-600));
|
|
264
289
|
}
|
|
265
290
|
|
|
@@ -16,6 +16,7 @@ import '../nile-spline-chart/index.js';
|
|
|
16
16
|
import '../nile-radar-chart/index.js';
|
|
17
17
|
import '../nile-gauge-chart/index.js';
|
|
18
18
|
import '../nile-waterfall-chart/index.js';
|
|
19
|
+
import '../nile-map-chart/index.js';
|
|
19
20
|
import '../nile-cluster-chart/index.js';
|
|
20
21
|
import '../nile-stacked-chart/index.js';
|
|
21
22
|
import '../nile-histogram-chart/index.js';
|
|
@@ -46,6 +47,7 @@ import '../nile-euler-chart/index.js';
|
|
|
46
47
|
import '../nile-polygon-chart/index.js';
|
|
47
48
|
import '../nile-vector-chart/index.js';
|
|
48
49
|
import '../nile-xrange-chart/index.js';
|
|
50
|
+
import '../nile-kpi-chart/index.js';
|
|
49
51
|
import '../nile-ai-panel/index.js';
|
|
50
52
|
export declare class NileChart extends NileElement {
|
|
51
53
|
static styles: CSSResultGroup;
|
|
@@ -56,19 +58,27 @@ export declare class NileChart extends NileElement {
|
|
|
56
58
|
* Usage: `<nile-chart chart-type="pie" />` plus `config.chart` with series data only.
|
|
57
59
|
*/
|
|
58
60
|
chartTypeAttr: string;
|
|
59
|
-
/**
|
|
61
|
+
/** Summary/insight text — shown as the AI panel's opening message when the chat is opened. */
|
|
62
|
+
/**
|
|
63
|
+
* When set, fills `chart.type` if the config omits it (same values as `chart.type`, e.g. `stacked`, `pie`).
|
|
64
|
+
* Usage: `<nile-chart chart-type="pie" />` plus `config.chart` with series data only.
|
|
65
|
+
*/
|
|
66
|
+
/** Summary/insight text — shown as the AI panel's opening message when the chat is opened. */
|
|
60
67
|
summary: string;
|
|
61
|
-
/** Label for the toggle button (fallback when config is not set). */
|
|
62
|
-
toggleLabel: string;
|
|
63
|
-
/** Whether the insight overlay is visible. */
|
|
64
|
-
open: boolean;
|
|
65
68
|
private activeType;
|
|
66
69
|
private activeConfig;
|
|
67
70
|
private menuOpen;
|
|
68
71
|
private chatOpen;
|
|
72
|
+
/** True when elements are projected into the `header` slot (default title/subtitle hidden). */
|
|
73
|
+
private hasHeaderSlotContent;
|
|
74
|
+
/** True when elements are projected into `header-actions` (used to show the header row). */
|
|
75
|
+
private hasHeaderActionsSlot;
|
|
76
|
+
/** True when elements are projected into the `header` slot (default title/subtitle hidden). */
|
|
77
|
+
/** True when elements are projected into `header-actions` (used to show the header row). */
|
|
69
78
|
private aiPanel;
|
|
70
79
|
private get effectiveSummary();
|
|
71
|
-
|
|
80
|
+
/** AI panel shows when ai.enabled is true OR when a summary is provided. */
|
|
81
|
+
/** AI panel shows when ai.enabled is true OR when a summary is provided. */
|
|
72
82
|
private get aiEnabled();
|
|
73
83
|
private handleOutsideClick;
|
|
74
84
|
connectedCallback(): void;
|
|
@@ -78,7 +88,6 @@ export declare class NileChart extends NileElement {
|
|
|
78
88
|
private resolveConfig;
|
|
79
89
|
private resolvedConfig;
|
|
80
90
|
protected updated(changedProperties: PropertyValues): void;
|
|
81
|
-
private toggle;
|
|
82
91
|
private toggleMenu;
|
|
83
92
|
private toggleChat;
|
|
84
93
|
/** Push an AI response into the chat panel. Call this from your AI handler. */
|
|
@@ -87,6 +96,13 @@ export declare class NileChart extends NileElement {
|
|
|
87
96
|
private switchType;
|
|
88
97
|
private get headerTitle();
|
|
89
98
|
private get headerSubtitle();
|
|
99
|
+
private onHeaderSlotChange;
|
|
100
|
+
private onHeaderActionsSlotChange;
|
|
101
|
+
private syncHeaderSlots;
|
|
102
|
+
protected firstUpdated(changedProperties: PropertyValues): void;
|
|
103
|
+
/** Direct children with `slot=` — header row renders on first paint before slot assignment runs. */
|
|
104
|
+
private lightDomHasSlot;
|
|
105
|
+
private shouldShowHeader;
|
|
90
106
|
private renderTypeSwitcher;
|
|
91
107
|
private renderAiTrigger;
|
|
92
108
|
private renderHeader;
|
|
@@ -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';
|
|
@@ -49,6 +50,7 @@ import '../nile-euler-chart/index.js';
|
|
|
49
50
|
import '../nile-polygon-chart/index.js';
|
|
50
51
|
import '../nile-vector-chart/index.js';
|
|
51
52
|
import '../nile-xrange-chart/index.js';
|
|
53
|
+
import '../nile-kpi-chart/index.js';
|
|
52
54
|
import '../nile-ai-panel/index.js';
|
|
53
55
|
const CORE_CHART_LABELS = {
|
|
54
56
|
bar: 'Bar',
|
|
@@ -65,6 +67,7 @@ const CORE_CHART_LABELS = {
|
|
|
65
67
|
radar: 'Radar',
|
|
66
68
|
gauge: 'Gauge',
|
|
67
69
|
waterfall: 'Waterfall',
|
|
70
|
+
map: 'Map',
|
|
68
71
|
stacked: 'Stacked column',
|
|
69
72
|
cluster: 'Cluster',
|
|
70
73
|
histogram: 'Histogram',
|
|
@@ -84,6 +87,7 @@ const CORE_CHART_LABELS = {
|
|
|
84
87
|
xrange: 'X-range',
|
|
85
88
|
lollipop: 'Lollipop',
|
|
86
89
|
'line-column': 'Line + column',
|
|
90
|
+
kpi: 'KPI',
|
|
87
91
|
};
|
|
88
92
|
function chartTypeLabel(type) {
|
|
89
93
|
const hit = CORE_CHART_LABELS[type];
|
|
@@ -104,21 +108,26 @@ let NileChart = class NileChart extends NileElement {
|
|
|
104
108
|
* Usage: `<nile-chart chart-type="pie" />` plus `config.chart` with series data only.
|
|
105
109
|
*/
|
|
106
110
|
this.chartTypeAttr = '';
|
|
107
|
-
/**
|
|
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. */
|
|
108
117
|
this.summary = '';
|
|
109
|
-
/** Label for the toggle button (fallback when config is not set). */
|
|
110
|
-
this.toggleLabel = 'Summary';
|
|
111
|
-
/** Whether the insight overlay is visible. */
|
|
112
|
-
this.open = false;
|
|
113
118
|
this.activeType = null;
|
|
114
119
|
this.activeConfig = null;
|
|
115
120
|
this.menuOpen = false;
|
|
116
121
|
this.chatOpen = false;
|
|
122
|
+
/** True when elements are projected into the `header` slot (default title/subtitle hidden). */
|
|
123
|
+
this.hasHeaderSlotContent = false;
|
|
124
|
+
/** True when elements are projected into `header-actions` (used to show the header row). */
|
|
125
|
+
this.hasHeaderActionsSlot = false;
|
|
117
126
|
this.handleOutsideClick = (e) => {
|
|
118
127
|
if (!this.contains(e.target)) {
|
|
119
|
-
this.open = false;
|
|
120
128
|
this.menuOpen = false;
|
|
121
|
-
this.
|
|
129
|
+
this.chatOpen = false;
|
|
130
|
+
this.chatOpen = false;
|
|
122
131
|
}
|
|
123
132
|
};
|
|
124
133
|
this.resolvedConfig = null;
|
|
@@ -126,11 +135,11 @@ let NileChart = class NileChart extends NileElement {
|
|
|
126
135
|
get effectiveSummary() {
|
|
127
136
|
return this.resolvedConfig?.summary ?? this.summary;
|
|
128
137
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
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. */
|
|
132
140
|
get aiEnabled() {
|
|
133
|
-
return this.resolvedConfig?.ai?.enabled === true;
|
|
141
|
+
return this.resolvedConfig?.ai?.enabled === true || !!this.effectiveSummary;
|
|
142
|
+
return this.resolvedConfig?.ai?.enabled === true || !!this.effectiveSummary;
|
|
134
143
|
}
|
|
135
144
|
connectedCallback() {
|
|
136
145
|
super.connectedCallback();
|
|
@@ -169,13 +178,6 @@ let NileChart = class NileChart extends NileElement {
|
|
|
169
178
|
this.activeConfig = this.resolvedConfig;
|
|
170
179
|
}
|
|
171
180
|
}
|
|
172
|
-
toggle(e) {
|
|
173
|
-
e.stopPropagation();
|
|
174
|
-
this.open = !this.open;
|
|
175
|
-
if (this.open)
|
|
176
|
-
this.chatOpen = false;
|
|
177
|
-
this.emit('nile-chart-toggle', { open: this.open });
|
|
178
|
-
}
|
|
179
181
|
toggleMenu(e) {
|
|
180
182
|
e.stopPropagation();
|
|
181
183
|
this.menuOpen = !this.menuOpen;
|
|
@@ -183,8 +185,6 @@ let NileChart = class NileChart extends NileElement {
|
|
|
183
185
|
toggleChat(e) {
|
|
184
186
|
e.stopPropagation();
|
|
185
187
|
this.chatOpen = !this.chatOpen;
|
|
186
|
-
if (this.chatOpen)
|
|
187
|
-
this.open = false;
|
|
188
188
|
this.emit('nile-chart-ai-toggle', { open: this.chatOpen });
|
|
189
189
|
}
|
|
190
190
|
/** Push an AI response into the chat panel. Call this from your AI handler. */
|
|
@@ -220,6 +220,62 @@ let NileChart = class NileChart extends NileElement {
|
|
|
220
220
|
get headerSubtitle() {
|
|
221
221
|
return this.activeConfig?.chartSubtitle ?? this.resolvedConfig?.chartSubtitle ?? '';
|
|
222
222
|
}
|
|
223
|
+
onHeaderSlotChange(e) {
|
|
224
|
+
const slot = e.target;
|
|
225
|
+
this.hasHeaderSlotContent = slot.assignedElements({ flatten: true }).length > 0;
|
|
226
|
+
this.requestUpdate();
|
|
227
|
+
}
|
|
228
|
+
onHeaderActionsSlotChange(e) {
|
|
229
|
+
const slot = e.target;
|
|
230
|
+
this.hasHeaderActionsSlot = slot.assignedElements({ flatten: true }).length > 0;
|
|
231
|
+
this.requestUpdate();
|
|
232
|
+
}
|
|
233
|
+
syncHeaderSlots() {
|
|
234
|
+
const root = this.shadowRoot;
|
|
235
|
+
if (!root)
|
|
236
|
+
return;
|
|
237
|
+
const headerSlot = root.querySelector('slot[name="header"]');
|
|
238
|
+
const actionsSlot = root.querySelector('slot[name="header-actions"]');
|
|
239
|
+
let changed = false;
|
|
240
|
+
if (headerSlot) {
|
|
241
|
+
const next = headerSlot.assignedElements({ flatten: true }).length > 0;
|
|
242
|
+
if (next !== this.hasHeaderSlotContent) {
|
|
243
|
+
this.hasHeaderSlotContent = next;
|
|
244
|
+
changed = true;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
if (actionsSlot) {
|
|
248
|
+
const next = actionsSlot.assignedElements({ flatten: true }).length > 0;
|
|
249
|
+
if (next !== this.hasHeaderActionsSlot) {
|
|
250
|
+
this.hasHeaderActionsSlot = next;
|
|
251
|
+
changed = true;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
if (changed)
|
|
255
|
+
this.requestUpdate();
|
|
256
|
+
}
|
|
257
|
+
firstUpdated(changedProperties) {
|
|
258
|
+
super.firstUpdated(changedProperties);
|
|
259
|
+
this.syncHeaderSlots();
|
|
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
|
+
}
|
|
269
|
+
shouldShowHeader() {
|
|
270
|
+
const hasTitles = !!(this.headerTitle || this.headerSubtitle);
|
|
271
|
+
const hasBuiltinActions = this.aiEnabled || (this.resolvedConfig?.switchableTypes?.length ?? 0) > 0;
|
|
272
|
+
return (hasTitles ||
|
|
273
|
+
this.hasHeaderSlotContent ||
|
|
274
|
+
this.hasHeaderActionsSlot ||
|
|
275
|
+
this.lightDomHasSlot('header') ||
|
|
276
|
+
this.lightDomHasSlot('header-actions') ||
|
|
277
|
+
hasBuiltinActions);
|
|
278
|
+
}
|
|
223
279
|
renderTypeSwitcher() {
|
|
224
280
|
const types = this.resolvedConfig?.switchableTypes;
|
|
225
281
|
if (!types || types.length === 0)
|
|
@@ -268,19 +324,24 @@ let NileChart = class NileChart extends NileElement {
|
|
|
268
324
|
`;
|
|
269
325
|
}
|
|
270
326
|
renderHeader() {
|
|
327
|
+
if (!this.shouldShowHeader())
|
|
328
|
+
return nothing;
|
|
271
329
|
const title = this.headerTitle;
|
|
272
330
|
const subtitle = this.headerSubtitle;
|
|
273
|
-
const
|
|
274
|
-
const hasActions = hasTypeSwitcher || this.aiEnabled;
|
|
275
|
-
if (!title && !subtitle && !hasActions)
|
|
276
|
-
return nothing;
|
|
331
|
+
const showDefaultTitles = !this.hasHeaderSlotContent && !!(title || subtitle);
|
|
277
332
|
return html `
|
|
278
333
|
<div class="chart-header">
|
|
279
334
|
<div class="chart-header-titles">
|
|
280
|
-
|
|
281
|
-
${
|
|
335
|
+
<slot name="header" @slotchange=${this.onHeaderSlotChange}></slot>
|
|
336
|
+
${showDefaultTitles
|
|
337
|
+
? html `
|
|
338
|
+
${title ? html `<h3 class="chart-header-title">${title}</h3>` : nothing}
|
|
339
|
+
${subtitle ? html `<p class="chart-header-subtitle">${subtitle}</p>` : nothing}
|
|
340
|
+
`
|
|
341
|
+
: nothing}
|
|
282
342
|
</div>
|
|
283
343
|
<div class="chart-header-actions">
|
|
344
|
+
<slot name="header-actions" @slotchange=${this.onHeaderActionsSlotChange}></slot>
|
|
284
345
|
${this.renderAiTrigger()}
|
|
285
346
|
${this.renderTypeSwitcher()}
|
|
286
347
|
</div>
|
|
@@ -290,12 +351,19 @@ let NileChart = class NileChart extends NileElement {
|
|
|
290
351
|
renderAiPanel() {
|
|
291
352
|
if (!this.aiEnabled)
|
|
292
353
|
return nothing;
|
|
293
|
-
const aiConfig = this.resolvedConfig
|
|
354
|
+
const aiConfig = this.resolvedConfig?.ai;
|
|
355
|
+
const summary = this.effectiveSummary;
|
|
356
|
+
// Summary always takes priority. When summary is present it is the only
|
|
357
|
+
// opening message (shown in blue). welcomeMessage is only used when there
|
|
358
|
+
// is no summary at all.
|
|
359
|
+
const summaryMessage = summary;
|
|
360
|
+
const welcomeMessage = summary ? '' : (aiConfig?.welcomeMessage ?? '');
|
|
294
361
|
return html `
|
|
295
362
|
<div class="ai-panel-overlay" ?data-open=${this.chatOpen}>
|
|
296
363
|
<nile-ai-panel
|
|
297
|
-
.placeholder=${aiConfig
|
|
298
|
-
.welcomeMessage=${
|
|
364
|
+
.placeholder=${aiConfig?.placeholder ?? 'Ask about this chart...'}
|
|
365
|
+
.welcomeMessage=${welcomeMessage}
|
|
366
|
+
.summaryMessage=${summaryMessage}
|
|
299
367
|
@nile-ai-send=${this.handleAiSend}
|
|
300
368
|
></nile-ai-panel>
|
|
301
369
|
</div>
|
|
@@ -381,6 +449,7 @@ let NileChart = class NileChart extends NileElement {
|
|
|
381
449
|
.height=${config.height ?? '400px'}
|
|
382
450
|
.innerSize=${config.innerSize ?? '50%'}
|
|
383
451
|
.semiCircle=${config.semiCircle ?? false}
|
|
452
|
+
.semiCircle=${config.semiCircle ?? false}
|
|
384
453
|
.showDataLabels=${config.showDataLabels ?? true}
|
|
385
454
|
.showLegend=${config.showLegend ?? true}
|
|
386
455
|
.options=${mergedOptions}
|
|
@@ -441,6 +510,17 @@ let NileChart = class NileChart extends NileElement {
|
|
|
441
510
|
.options=${mergedOptions}
|
|
442
511
|
.loading=${config.loading ?? false}
|
|
443
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>`;
|
|
444
524
|
case 'stacked':
|
|
445
525
|
return html `<nile-stacked-chart
|
|
446
526
|
.data=${config.data}
|
|
@@ -768,6 +848,37 @@ let NileChart = class NileChart extends NileElement {
|
|
|
768
848
|
.options=${mergedOptions}
|
|
769
849
|
.loading=${config.loading ?? false}
|
|
770
850
|
></nile-xrange-chart>`;
|
|
851
|
+
case 'kpi': {
|
|
852
|
+
const k = config;
|
|
853
|
+
return html `<nile-kpi-chart
|
|
854
|
+
.config=${{
|
|
855
|
+
chart: {
|
|
856
|
+
type: 'kpi',
|
|
857
|
+
variant: k.variant,
|
|
858
|
+
label: k.label,
|
|
859
|
+
value: k.value,
|
|
860
|
+
prefix: k.prefix,
|
|
861
|
+
suffix: k.suffix,
|
|
862
|
+
trendValue: k.trendValue,
|
|
863
|
+
trendDirection: k.trendDirection,
|
|
864
|
+
trendLabel: k.trendLabel,
|
|
865
|
+
description: k.description,
|
|
866
|
+
sparkline: k.sparkline,
|
|
867
|
+
sparklineColor: k.sparklineColor,
|
|
868
|
+
gaugeValue: k.gaugeValue,
|
|
869
|
+
gaugeMin: k.gaugeMin,
|
|
870
|
+
gaugeMax: k.gaugeMax,
|
|
871
|
+
gaugeColor: k.gaugeColor,
|
|
872
|
+
loading: k.loading,
|
|
873
|
+
options: k.options,
|
|
874
|
+
height: k.height,
|
|
875
|
+
},
|
|
876
|
+
aq: {
|
|
877
|
+
chartSubtitle: k.chartSubtitle,
|
|
878
|
+
},
|
|
879
|
+
}}
|
|
880
|
+
></nile-kpi-chart>`;
|
|
881
|
+
}
|
|
771
882
|
default: {
|
|
772
883
|
const _exhaustive = config;
|
|
773
884
|
return _exhaustive;
|
|
@@ -781,23 +892,11 @@ let NileChart = class NileChart extends NileElement {
|
|
|
781
892
|
<div class="chart-wrapper">
|
|
782
893
|
<div class="chart-inner">
|
|
783
894
|
${this.activeConfig ? this.renderChartContent() : html `<slot></slot>`}
|
|
784
|
-
<button
|
|
785
|
-
class="chart-toggle"
|
|
786
|
-
aria-expanded="${this.open}"
|
|
787
|
-
@click="${this.toggle}"
|
|
788
|
-
>
|
|
789
|
-
${this.effectiveToggleLabel}
|
|
790
|
-
</button>
|
|
791
|
-
<div class="chart-overlay" ?data-open="${this.open}">
|
|
792
|
-
<div class="chart-content">
|
|
793
|
-
${this.resolvedConfig
|
|
794
|
-
? this.effectiveSummary
|
|
795
|
-
: html `<slot name="insight">${this.summary}</slot>`}
|
|
796
|
-
</div>
|
|
797
|
-
</div>
|
|
798
895
|
${this.renderAiPanel()}
|
|
799
896
|
</div>
|
|
800
897
|
</div>
|
|
898
|
+
<slot name="footer"></slot>
|
|
899
|
+
<slot name="footer"></slot>
|
|
801
900
|
</div>
|
|
802
901
|
`;
|
|
803
902
|
}
|
|
@@ -812,12 +911,6 @@ __decorate([
|
|
|
812
911
|
__decorate([
|
|
813
912
|
property({ type: String })
|
|
814
913
|
], NileChart.prototype, "summary", void 0);
|
|
815
|
-
__decorate([
|
|
816
|
-
property({ type: String, attribute: 'toggle-label' })
|
|
817
|
-
], NileChart.prototype, "toggleLabel", void 0);
|
|
818
|
-
__decorate([
|
|
819
|
-
state()
|
|
820
|
-
], NileChart.prototype, "open", void 0);
|
|
821
914
|
__decorate([
|
|
822
915
|
state()
|
|
823
916
|
], NileChart.prototype, "activeType", void 0);
|
|
@@ -830,6 +923,12 @@ __decorate([
|
|
|
830
923
|
__decorate([
|
|
831
924
|
state()
|
|
832
925
|
], NileChart.prototype, "chatOpen", void 0);
|
|
926
|
+
__decorate([
|
|
927
|
+
state()
|
|
928
|
+
], NileChart.prototype, "hasHeaderSlotContent", void 0);
|
|
929
|
+
__decorate([
|
|
930
|
+
state()
|
|
931
|
+
], NileChart.prototype, "hasHeaderActionsSlot", void 0);
|
|
833
932
|
__decorate([
|
|
834
933
|
query('nile-ai-panel')
|
|
835
934
|
], NileChart.prototype, "aiPanel", void 0);
|
|
@@ -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
|