@aquera/nile-visualization 0.6.0 → 0.8.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 +2 -0
- package/dist/src/index.js +1 -0
- package/dist/src/internal/types/nile-chart-config-input.type.d.ts +6 -2
- package/dist/src/nile-chart/nile-chart-config-builder.js +2 -1
- package/dist/src/nile-chart/nile-chart.css.js +118 -6
- package/dist/src/nile-chart/nile-chart.d.ts +12 -0
- package/dist/src/nile-chart/nile-chart.js +42 -5
- package/dist/src/nile-executive-summary/index.d.ts +2 -0
- package/dist/src/nile-executive-summary/index.js +2 -0
- package/dist/src/nile-executive-summary/nile-executive-summary-config.d.ts +39 -0
- package/dist/src/nile-executive-summary/nile-executive-summary-config.js +8 -0
- package/dist/src/nile-executive-summary/nile-executive-summary.css.d.ts +9 -0
- package/dist/src/nile-executive-summary/nile-executive-summary.css.js +196 -0
- package/dist/src/nile-executive-summary/nile-executive-summary.d.ts +101 -0
- package/dist/src/nile-executive-summary/nile-executive-summary.js +308 -0
- package/dist/src/nile-kpi-chart/nile-kpi-chart.css.d.ts +5 -0
- package/dist/src/nile-kpi-chart/nile-kpi-chart.css.js +52 -11
- package/dist/src/nile-kpi-chart/nile-kpi-chart.d.ts +22 -4
- package/dist/src/nile-kpi-chart/nile-kpi-chart.js +204 -22
- package/package.json +3 -2
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Aquera Inc 2023
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the BSD-3-Clause license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import type { CSSResultGroup, TemplateResult } from 'lit';
|
|
8
|
+
import NileElement from '../internal/nile-element.js';
|
|
9
|
+
import type { NileExecutiveSummaryConfig } from './nile-executive-summary-config.js';
|
|
10
|
+
/**
|
|
11
|
+
* Nile Executive Summary component.
|
|
12
|
+
*
|
|
13
|
+
* @tag nile-executive-summary
|
|
14
|
+
*
|
|
15
|
+
* @summary A self-contained drawer component with a built-in trigger button.
|
|
16
|
+
* Place it anywhere — clicking the button slides in a right-side drawer that
|
|
17
|
+
* displays summary content (plain text or HTML) with a typewriter animation.
|
|
18
|
+
* Configured entirely via the `config` JS property.
|
|
19
|
+
*
|
|
20
|
+
* @event nile-show - Emitted when the drawer starts opening.
|
|
21
|
+
* @event nile-after-show - Emitted when the drawer is fully open and typing begins.
|
|
22
|
+
* @event nile-hide - Emitted when the drawer starts closing.
|
|
23
|
+
* @event nile-after-hide - Emitted when the drawer is fully closed.
|
|
24
|
+
* @event nile-typing-complete - Emitted when the typewriter animation finishes.
|
|
25
|
+
* @event nile-init - Emitted when the component connects to the DOM.
|
|
26
|
+
* @event nile-destroy - Emitted when the component disconnects from the DOM.
|
|
27
|
+
*
|
|
28
|
+
* @csspart base - Root wrapper (contains trigger + drawer).
|
|
29
|
+
* @csspart trigger - The built-in button that opens the drawer.
|
|
30
|
+
* @csspart overlay - The dim overlay behind the panel.
|
|
31
|
+
* @csspart panel - The drawer panel.
|
|
32
|
+
* @csspart header - The drawer header.
|
|
33
|
+
* @csspart title - The drawer title.
|
|
34
|
+
* @csspart close - The close button.
|
|
35
|
+
* @csspart body - The drawer body containing the typed summary.
|
|
36
|
+
*
|
|
37
|
+
* @cssproperty --executive-summary-size - Drawer width. Default: 480px.
|
|
38
|
+
* @cssproperty --executive-summary-header-spacing - Header padding. Default: 16px 20px.
|
|
39
|
+
* @cssproperty --executive-summary-body-spacing - Body padding. Default: 20px.
|
|
40
|
+
* @cssproperty --executive-summary-z-index - Z-index of the drawer. Default: 700.
|
|
41
|
+
* @cssproperty --executive-summary-overlay-color - Overlay background colour.
|
|
42
|
+
* @cssproperty --executive-summary-btn-bg - Trigger button background.
|
|
43
|
+
* @cssproperty --executive-summary-btn-color - Trigger button text colour.
|
|
44
|
+
* @cssproperty --executive-summary-btn-radius - Trigger button border-radius.
|
|
45
|
+
*/
|
|
46
|
+
export declare class NileExecutiveSummary extends NileElement {
|
|
47
|
+
static styles: CSSResultGroup;
|
|
48
|
+
private typingTimer;
|
|
49
|
+
private keyDownHandler;
|
|
50
|
+
private originalTrigger;
|
|
51
|
+
private scrollLockActive;
|
|
52
|
+
private backdrop;
|
|
53
|
+
private panel;
|
|
54
|
+
private overlay;
|
|
55
|
+
/**
|
|
56
|
+
* Full configuration. Assign via JavaScript — all fields are optional except `summary`.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```js
|
|
60
|
+
* el.config = {
|
|
61
|
+
* summary: '<p>Q1 revenue grew <strong>23%</strong>.</p>',
|
|
62
|
+
* buttonLabel: 'View Summary',
|
|
63
|
+
* drawerLabel: 'AI Executive Summary',
|
|
64
|
+
* typingSpeed: 20,
|
|
65
|
+
* };
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
config: NileExecutiveSummaryConfig | null;
|
|
69
|
+
/**
|
|
70
|
+
* Whether the drawer is currently open.
|
|
71
|
+
* Can be set programmatically; use `show()` / `hide()` for animated transitions.
|
|
72
|
+
*/
|
|
73
|
+
open: boolean;
|
|
74
|
+
/** @internal Characters revealed so far during typing. */
|
|
75
|
+
private displayedText;
|
|
76
|
+
/** @internal Whether typing is still in progress (drives cursor visibility). */
|
|
77
|
+
private isTyping;
|
|
78
|
+
connectedCallback(): void;
|
|
79
|
+
firstUpdated(): void;
|
|
80
|
+
disconnectedCallback(): void;
|
|
81
|
+
private addKeyListener;
|
|
82
|
+
private removeKeyListener;
|
|
83
|
+
private handleKeyDown;
|
|
84
|
+
private lockScroll;
|
|
85
|
+
private unlockScroll;
|
|
86
|
+
private animatePanel;
|
|
87
|
+
private animateOverlay;
|
|
88
|
+
private requestClose;
|
|
89
|
+
private startTyping;
|
|
90
|
+
private stopTyping;
|
|
91
|
+
/** Opens the drawer with animation. Resolves when the animation completes. */
|
|
92
|
+
show(): Promise<void>;
|
|
93
|
+
/** Closes the drawer with animation. Resolves when the animation completes. */
|
|
94
|
+
hide(): Promise<void>;
|
|
95
|
+
render(): TemplateResult;
|
|
96
|
+
}
|
|
97
|
+
declare global {
|
|
98
|
+
interface HTMLElementTagNameMap {
|
|
99
|
+
'nile-executive-summary': NileExecutiveSummary;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Aquera Inc 2023
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the BSD-3-Clause license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import { __decorate } from "tslib";
|
|
8
|
+
import { customElement, property, query, state } from 'lit/decorators.js';
|
|
9
|
+
import { classMap } from 'lit/directives/class-map.js';
|
|
10
|
+
import { html } from 'lit';
|
|
11
|
+
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
|
|
12
|
+
import NileElement from '../internal/nile-element.js';
|
|
13
|
+
import { styles } from './nile-executive-summary.css.js';
|
|
14
|
+
/**
|
|
15
|
+
* Nile Executive Summary component.
|
|
16
|
+
*
|
|
17
|
+
* @tag nile-executive-summary
|
|
18
|
+
*
|
|
19
|
+
* @summary A self-contained drawer component with a built-in trigger button.
|
|
20
|
+
* Place it anywhere — clicking the button slides in a right-side drawer that
|
|
21
|
+
* displays summary content (plain text or HTML) with a typewriter animation.
|
|
22
|
+
* Configured entirely via the `config` JS property.
|
|
23
|
+
*
|
|
24
|
+
* @event nile-show - Emitted when the drawer starts opening.
|
|
25
|
+
* @event nile-after-show - Emitted when the drawer is fully open and typing begins.
|
|
26
|
+
* @event nile-hide - Emitted when the drawer starts closing.
|
|
27
|
+
* @event nile-after-hide - Emitted when the drawer is fully closed.
|
|
28
|
+
* @event nile-typing-complete - Emitted when the typewriter animation finishes.
|
|
29
|
+
* @event nile-init - Emitted when the component connects to the DOM.
|
|
30
|
+
* @event nile-destroy - Emitted when the component disconnects from the DOM.
|
|
31
|
+
*
|
|
32
|
+
* @csspart base - Root wrapper (contains trigger + drawer).
|
|
33
|
+
* @csspart trigger - The built-in button that opens the drawer.
|
|
34
|
+
* @csspart overlay - The dim overlay behind the panel.
|
|
35
|
+
* @csspart panel - The drawer panel.
|
|
36
|
+
* @csspart header - The drawer header.
|
|
37
|
+
* @csspart title - The drawer title.
|
|
38
|
+
* @csspart close - The close button.
|
|
39
|
+
* @csspart body - The drawer body containing the typed summary.
|
|
40
|
+
*
|
|
41
|
+
* @cssproperty --executive-summary-size - Drawer width. Default: 480px.
|
|
42
|
+
* @cssproperty --executive-summary-header-spacing - Header padding. Default: 16px 20px.
|
|
43
|
+
* @cssproperty --executive-summary-body-spacing - Body padding. Default: 20px.
|
|
44
|
+
* @cssproperty --executive-summary-z-index - Z-index of the drawer. Default: 700.
|
|
45
|
+
* @cssproperty --executive-summary-overlay-color - Overlay background colour.
|
|
46
|
+
* @cssproperty --executive-summary-btn-bg - Trigger button background.
|
|
47
|
+
* @cssproperty --executive-summary-btn-color - Trigger button text colour.
|
|
48
|
+
* @cssproperty --executive-summary-btn-radius - Trigger button border-radius.
|
|
49
|
+
*/
|
|
50
|
+
let NileExecutiveSummary = class NileExecutiveSummary extends NileElement {
|
|
51
|
+
constructor() {
|
|
52
|
+
super(...arguments);
|
|
53
|
+
this.typingTimer = null;
|
|
54
|
+
this.originalTrigger = null;
|
|
55
|
+
this.scrollLockActive = false;
|
|
56
|
+
/**
|
|
57
|
+
* Full configuration. Assign via JavaScript — all fields are optional except `summary`.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```js
|
|
61
|
+
* el.config = {
|
|
62
|
+
* summary: '<p>Q1 revenue grew <strong>23%</strong>.</p>',
|
|
63
|
+
* buttonLabel: 'View Summary',
|
|
64
|
+
* drawerLabel: 'AI Executive Summary',
|
|
65
|
+
* typingSpeed: 20,
|
|
66
|
+
* };
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
this.config = null;
|
|
70
|
+
/**
|
|
71
|
+
* Whether the drawer is currently open.
|
|
72
|
+
* Can be set programmatically; use `show()` / `hide()` for animated transitions.
|
|
73
|
+
*/
|
|
74
|
+
this.open = false;
|
|
75
|
+
/** @internal Characters revealed so far during typing. */
|
|
76
|
+
this.displayedText = '';
|
|
77
|
+
/** @internal Whether typing is still in progress (drives cursor visibility). */
|
|
78
|
+
this.isTyping = false;
|
|
79
|
+
}
|
|
80
|
+
// ─── Lifecycle ─────────────────────────────────────────────────────────────
|
|
81
|
+
connectedCallback() {
|
|
82
|
+
super.connectedCallback();
|
|
83
|
+
this.keyDownHandler = this.handleKeyDown.bind(this);
|
|
84
|
+
this.emit('nile-init');
|
|
85
|
+
}
|
|
86
|
+
firstUpdated() {
|
|
87
|
+
this.backdrop.hidden = !this.open;
|
|
88
|
+
}
|
|
89
|
+
disconnectedCallback() {
|
|
90
|
+
super.disconnectedCallback();
|
|
91
|
+
this.stopTyping();
|
|
92
|
+
this.removeKeyListener();
|
|
93
|
+
this.unlockScroll();
|
|
94
|
+
this.emit('nile-destroy');
|
|
95
|
+
}
|
|
96
|
+
// ─── Keyboard / scroll ─────────────────────────────────────────────────────
|
|
97
|
+
addKeyListener() {
|
|
98
|
+
if (this.config?.closeOnEscape ?? true) {
|
|
99
|
+
document.addEventListener('keydown', this.keyDownHandler);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
removeKeyListener() {
|
|
103
|
+
document.removeEventListener('keydown', this.keyDownHandler);
|
|
104
|
+
}
|
|
105
|
+
handleKeyDown(e) {
|
|
106
|
+
if (this.open && e.key === 'Escape') {
|
|
107
|
+
e.stopPropagation();
|
|
108
|
+
this.requestClose('keyboard');
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
lockScroll() {
|
|
112
|
+
if (!this.scrollLockActive) {
|
|
113
|
+
document.body.style.overflow = 'hidden';
|
|
114
|
+
this.scrollLockActive = true;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
unlockScroll() {
|
|
118
|
+
if (this.scrollLockActive) {
|
|
119
|
+
document.body.style.overflow = '';
|
|
120
|
+
this.scrollLockActive = false;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// ─── Animation helpers ──────────────────────────────────────────────────────
|
|
124
|
+
async animatePanel(show) {
|
|
125
|
+
const from = show ? { opacity: '0', translate: '100%' } : { opacity: '1', translate: '0' };
|
|
126
|
+
const to = show ? { opacity: '1', translate: '0' } : { opacity: '0', translate: '100%' };
|
|
127
|
+
await this.panel.animate([from, to], { duration: 250, easing: 'ease', fill: 'forwards' }).finished;
|
|
128
|
+
}
|
|
129
|
+
async animateOverlay(show) {
|
|
130
|
+
const from = show ? { opacity: '0' } : { opacity: '1' };
|
|
131
|
+
const to = show ? { opacity: '1' } : { opacity: '0' };
|
|
132
|
+
await this.overlay.animate([from, to], { duration: 250, fill: 'forwards' }).finished;
|
|
133
|
+
}
|
|
134
|
+
// ─── Close request ──────────────────────────────────────────────────────────
|
|
135
|
+
requestClose(source) {
|
|
136
|
+
const preventOverlayClose = this.config?.preventOverlayClose ?? false;
|
|
137
|
+
if ((source === 'overlay' || source === 'keyboard') && preventOverlayClose)
|
|
138
|
+
return;
|
|
139
|
+
const ev = this.emit('nile-request-close', { cancelable: true, detail: { source } });
|
|
140
|
+
if (ev.defaultPrevented) {
|
|
141
|
+
// Deny-close jiggle
|
|
142
|
+
this.panel.animate([{ scale: '1' }, { scale: '1.01' }, { scale: '1' }], { duration: 250 });
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
this.hide();
|
|
146
|
+
}
|
|
147
|
+
// ─── Typing animation ───────────────────────────────────────────────────────
|
|
148
|
+
startTyping() {
|
|
149
|
+
this.stopTyping();
|
|
150
|
+
this.displayedText = '';
|
|
151
|
+
this.isTyping = true;
|
|
152
|
+
const text = this.config?.summary ?? '';
|
|
153
|
+
const speed = this.config?.typingSpeed ?? 30;
|
|
154
|
+
let index = 0;
|
|
155
|
+
const tick = () => {
|
|
156
|
+
if (index < text.length) {
|
|
157
|
+
this.displayedText += text[index++];
|
|
158
|
+
this.typingTimer = setTimeout(tick, speed);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
this.isTyping = false;
|
|
162
|
+
this.emit('nile-typing-complete');
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
tick();
|
|
166
|
+
}
|
|
167
|
+
stopTyping() {
|
|
168
|
+
if (this.typingTimer !== null) {
|
|
169
|
+
clearTimeout(this.typingTimer);
|
|
170
|
+
this.typingTimer = null;
|
|
171
|
+
}
|
|
172
|
+
this.isTyping = false;
|
|
173
|
+
}
|
|
174
|
+
// ─── Open / close ───────────────────────────────────────────────────────────
|
|
175
|
+
/** Opens the drawer with animation. Resolves when the animation completes. */
|
|
176
|
+
async show() {
|
|
177
|
+
if (this.open)
|
|
178
|
+
return;
|
|
179
|
+
this.open = true;
|
|
180
|
+
this.emit('nile-show');
|
|
181
|
+
this.addKeyListener();
|
|
182
|
+
this.lockScroll();
|
|
183
|
+
this.originalTrigger = document.activeElement;
|
|
184
|
+
this.backdrop.hidden = false;
|
|
185
|
+
await Promise.all([this.animatePanel(true), this.animateOverlay(true)]);
|
|
186
|
+
requestAnimationFrame(() => this.panel.focus({ preventScroll: true }));
|
|
187
|
+
this.emit('nile-after-show');
|
|
188
|
+
this.startTyping();
|
|
189
|
+
}
|
|
190
|
+
/** Closes the drawer with animation. Resolves when the animation completes. */
|
|
191
|
+
async hide() {
|
|
192
|
+
if (!this.open)
|
|
193
|
+
return;
|
|
194
|
+
this.open = false;
|
|
195
|
+
this.emit('nile-hide');
|
|
196
|
+
this.removeKeyListener();
|
|
197
|
+
this.stopTyping();
|
|
198
|
+
this.displayedText = '';
|
|
199
|
+
this.unlockScroll();
|
|
200
|
+
await Promise.all([this.animatePanel(false), this.animateOverlay(false)]);
|
|
201
|
+
this.backdrop.hidden = true;
|
|
202
|
+
// Reset animation fill state for next open
|
|
203
|
+
this.panel.getAnimations().forEach(a => a.cancel());
|
|
204
|
+
this.overlay.getAnimations().forEach(a => a.cancel());
|
|
205
|
+
// Restore focus to original trigger
|
|
206
|
+
const trigger = this.originalTrigger;
|
|
207
|
+
if (typeof trigger?.focus === 'function')
|
|
208
|
+
setTimeout(() => trigger.focus());
|
|
209
|
+
this.emit('nile-after-hide');
|
|
210
|
+
}
|
|
211
|
+
// ─── Render ─────────────────────────────────────────────────────────────────
|
|
212
|
+
render() {
|
|
213
|
+
const buttonLabel = this.config?.buttonLabel ?? 'Executive Summary';
|
|
214
|
+
const buttonVariant = this.config?.buttonVariant ?? 'primary';
|
|
215
|
+
const drawerLabel = this.config?.drawerLabel ?? 'Executive Summary';
|
|
216
|
+
return html `
|
|
217
|
+
<div part="base">
|
|
218
|
+
|
|
219
|
+
<!-- Built-in trigger — renders wherever the element is placed -->
|
|
220
|
+
<nile-button
|
|
221
|
+
part="trigger"
|
|
222
|
+
type="button"
|
|
223
|
+
variant=${buttonVariant}
|
|
224
|
+
aria-haspopup="dialog"
|
|
225
|
+
aria-expanded=${this.open ? 'true' : 'false'}
|
|
226
|
+
@click=${this.show}
|
|
227
|
+
>${buttonLabel}</nile-button>
|
|
228
|
+
|
|
229
|
+
<!-- Fixed backdrop: overlay + panel -->
|
|
230
|
+
<div class="es-backdrop">
|
|
231
|
+
|
|
232
|
+
<div
|
|
233
|
+
part="overlay"
|
|
234
|
+
class="es-overlay"
|
|
235
|
+
@click=${() => this.requestClose('overlay')}
|
|
236
|
+
tabindex="-1"
|
|
237
|
+
></div>
|
|
238
|
+
|
|
239
|
+
<div
|
|
240
|
+
part="panel"
|
|
241
|
+
class="es-panel"
|
|
242
|
+
role="dialog"
|
|
243
|
+
aria-modal="true"
|
|
244
|
+
aria-hidden=${this.open ? 'false' : 'true'}
|
|
245
|
+
aria-labelledby="es-title"
|
|
246
|
+
tabindex="0"
|
|
247
|
+
>
|
|
248
|
+
<header part="header" class="es-header">
|
|
249
|
+
<h2 part="title" class="es-title" id="es-title">${drawerLabel}</h2>
|
|
250
|
+
|
|
251
|
+
<button
|
|
252
|
+
part="close"
|
|
253
|
+
class="es-close"
|
|
254
|
+
type="button"
|
|
255
|
+
aria-label="Close"
|
|
256
|
+
@click=${() => this.requestClose('close-button')}
|
|
257
|
+
>
|
|
258
|
+
<!-- X icon (inline SVG — no icon lib dependency) -->
|
|
259
|
+
<svg viewBox="0 0 24 24" aria-hidden="true">
|
|
260
|
+
<line x1="18" y1="6" x2="6" y2="18"/>
|
|
261
|
+
<line x1="6" y1="6" x2="18" y2="18"/>
|
|
262
|
+
</svg>
|
|
263
|
+
</button>
|
|
264
|
+
</header>
|
|
265
|
+
|
|
266
|
+
<div part="body" class="es-body">
|
|
267
|
+
<div
|
|
268
|
+
class=${classMap({
|
|
269
|
+
'es-typed-text': true,
|
|
270
|
+
'es-typed-text--typing': this.isTyping,
|
|
271
|
+
})}
|
|
272
|
+
>${unsafeHTML(this.displayedText)}</div>
|
|
273
|
+
<slot></slot>
|
|
274
|
+
</div>
|
|
275
|
+
|
|
276
|
+
</div>
|
|
277
|
+
</div>
|
|
278
|
+
</div>
|
|
279
|
+
`;
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
NileExecutiveSummary.styles = styles;
|
|
283
|
+
__decorate([
|
|
284
|
+
query('.es-backdrop')
|
|
285
|
+
], NileExecutiveSummary.prototype, "backdrop", void 0);
|
|
286
|
+
__decorate([
|
|
287
|
+
query('.es-panel')
|
|
288
|
+
], NileExecutiveSummary.prototype, "panel", void 0);
|
|
289
|
+
__decorate([
|
|
290
|
+
query('.es-overlay')
|
|
291
|
+
], NileExecutiveSummary.prototype, "overlay", void 0);
|
|
292
|
+
__decorate([
|
|
293
|
+
property({ type: Object })
|
|
294
|
+
], NileExecutiveSummary.prototype, "config", void 0);
|
|
295
|
+
__decorate([
|
|
296
|
+
property({ type: Boolean, reflect: true })
|
|
297
|
+
], NileExecutiveSummary.prototype, "open", void 0);
|
|
298
|
+
__decorate([
|
|
299
|
+
state()
|
|
300
|
+
], NileExecutiveSummary.prototype, "displayedText", void 0);
|
|
301
|
+
__decorate([
|
|
302
|
+
state()
|
|
303
|
+
], NileExecutiveSummary.prototype, "isTyping", void 0);
|
|
304
|
+
NileExecutiveSummary = __decorate([
|
|
305
|
+
customElement('nile-executive-summary')
|
|
306
|
+
], NileExecutiveSummary);
|
|
307
|
+
export { NileExecutiveSummary };
|
|
308
|
+
//# sourceMappingURL=nile-executive-summary.js.map
|
|
@@ -1 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global tooltip styles — injected once into document.head so the tooltip
|
|
3
|
+
* element on document.body is styled independently of the shadow DOM.
|
|
4
|
+
*/
|
|
5
|
+
export declare const tooltipCss = "\n .nile-kpi-tooltip {\n position: fixed;\n display: none;\n transform: translate(-50%, calc(-100% - 10px));\n background: #1D2939;\n color: #fff;\n font-family: system-ui, sans-serif;\n font-size: 12px;\n font-weight: 500;\n line-height: 1.4;\n padding: 5px 10px;\n border-radius: 6px;\n pointer-events: none;\n white-space: nowrap;\n z-index: 2147483647;\n box-shadow: 0 4px 12px rgba(16, 24, 40, 0.22);\n }\n\n .nile-kpi-tooltip::after {\n content: '';\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border: 5px solid transparent;\n border-top-color:rgb(54, 74, 99);\n }\n";
|
|
1
6
|
export declare const styles: import("lit").CSSResult;
|
|
@@ -1,18 +1,53 @@
|
|
|
1
1
|
import { css } from 'lit';
|
|
2
|
+
/**
|
|
3
|
+
* Global tooltip styles — injected once into document.head so the tooltip
|
|
4
|
+
* element on document.body is styled independently of the shadow DOM.
|
|
5
|
+
*/
|
|
6
|
+
export const tooltipCss = `
|
|
7
|
+
.nile-kpi-tooltip {
|
|
8
|
+
position: fixed;
|
|
9
|
+
display: none;
|
|
10
|
+
transform: translate(-50%, calc(-100% - 10px));
|
|
11
|
+
background: #1D2939;
|
|
12
|
+
color: #fff;
|
|
13
|
+
font-family: system-ui, sans-serif;
|
|
14
|
+
font-size: 12px;
|
|
15
|
+
font-weight: 500;
|
|
16
|
+
line-height: 1.4;
|
|
17
|
+
padding: 5px 10px;
|
|
18
|
+
border-radius: 6px;
|
|
19
|
+
pointer-events: none;
|
|
20
|
+
white-space: nowrap;
|
|
21
|
+
z-index: 2147483647;
|
|
22
|
+
box-shadow: 0 4px 12px rgba(16, 24, 40, 0.22);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.nile-kpi-tooltip::after {
|
|
26
|
+
content: '';
|
|
27
|
+
position: absolute;
|
|
28
|
+
top: 100%;
|
|
29
|
+
left: 50%;
|
|
30
|
+
transform: translateX(-50%);
|
|
31
|
+
border: 5px solid transparent;
|
|
32
|
+
border-top-color:rgb(54, 74, 99);
|
|
33
|
+
}
|
|
34
|
+
`;
|
|
2
35
|
export const styles = css `
|
|
3
36
|
:host {
|
|
4
|
-
display:
|
|
37
|
+
display: flex;
|
|
38
|
+
flex-direction: column;
|
|
5
39
|
width: 100%;
|
|
6
40
|
position: relative;
|
|
41
|
+
box-sizing: border-box;
|
|
7
42
|
}
|
|
8
43
|
|
|
9
44
|
:host([hidden]) {
|
|
10
45
|
display: none;
|
|
11
46
|
}
|
|
12
47
|
|
|
13
|
-
/*
|
|
14
|
-
|
|
15
|
-
|
|
48
|
+
/* Card / gauge chrome on the host when used alone (inside nile-chart, embed-in-nile-chart skips this). */
|
|
49
|
+
:host([variant='card']:not([embed-in-nile-chart])),
|
|
50
|
+
:host([variant='gauge']:not([embed-in-nile-chart])) {
|
|
16
51
|
background: transparent;
|
|
17
52
|
border: var(--nile-border-width-1, var(--ng-stroke-width-1)) solid var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
|
|
18
53
|
border-radius: var(--nile-radius-radius-3xl, var(--ng-radius-xl));
|
|
@@ -20,13 +55,13 @@ export const styles = css `
|
|
|
20
55
|
transition: box-shadow var(--nile-transition-duration-default, var(--ng-transition-duration-default)) ease;
|
|
21
56
|
}
|
|
22
57
|
|
|
23
|
-
|
|
58
|
+
:host([variant='card']:not([embed-in-nile-chart]):hover),
|
|
59
|
+
:host([variant='gauge']:not([embed-in-nile-chart]):hover) {
|
|
24
60
|
box-shadow: var(--nile-box-shadow-7, var(--ng-shadow-md));
|
|
25
61
|
}
|
|
26
62
|
|
|
27
|
-
/* ── Base layout ── */
|
|
28
|
-
|
|
29
63
|
.kpi {
|
|
64
|
+
flex: 1 1 auto;
|
|
30
65
|
display: flex;
|
|
31
66
|
flex-direction: column;
|
|
32
67
|
gap: var(--nile-spacing-md, var(--ng-spacing-md));
|
|
@@ -52,10 +87,11 @@ export const styles = css `
|
|
|
52
87
|
.kpi-value {
|
|
53
88
|
margin: 0;
|
|
54
89
|
font-family: var(--nile-font-family-serif-colfax-medium, var(--ng-font-family-display));
|
|
55
|
-
font-size: 36px;
|
|
90
|
+
font-size: clamp(1.25rem, 2.5vw + 0.75rem, 36px);
|
|
56
91
|
font-weight: var(--nile-font-weight-semi-bold, var(--ng-font-weight-semibold));
|
|
57
92
|
color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));
|
|
58
93
|
line-height: 1.2;
|
|
94
|
+
cursor: default;
|
|
59
95
|
}
|
|
60
96
|
|
|
61
97
|
.kpi-prefix,
|
|
@@ -115,7 +151,8 @@ export const styles = css `
|
|
|
115
151
|
|
|
116
152
|
.kpi-sparkline {
|
|
117
153
|
width: 100%;
|
|
118
|
-
|
|
154
|
+
flex: 0 1 48px;
|
|
155
|
+
min-height: 22px;
|
|
119
156
|
margin-top: var(--nile-spacing-xs, var(--ng-spacing-xs));
|
|
120
157
|
}
|
|
121
158
|
|
|
@@ -127,8 +164,11 @@ export const styles = css `
|
|
|
127
164
|
}
|
|
128
165
|
|
|
129
166
|
.kpi-gauge-container {
|
|
130
|
-
width:
|
|
131
|
-
|
|
167
|
+
width: 100%;
|
|
168
|
+
max-width: 160px;
|
|
169
|
+
aspect-ratio: 1;
|
|
170
|
+
flex: 0 1 160px;
|
|
171
|
+
min-width: 72px;
|
|
132
172
|
margin: 0 auto;
|
|
133
173
|
}
|
|
134
174
|
|
|
@@ -153,6 +193,7 @@ export const styles = css `
|
|
|
153
193
|
/* ── Loading state ── */
|
|
154
194
|
|
|
155
195
|
.chart-loading {
|
|
196
|
+
flex: 1 1 auto;
|
|
156
197
|
display: flex;
|
|
157
198
|
align-items: center;
|
|
158
199
|
justify-content: center;
|
|
@@ -24,8 +24,8 @@ export interface ChartKpiSeparatedPayload {
|
|
|
24
24
|
gaugeColor?: string;
|
|
25
25
|
loading?: boolean;
|
|
26
26
|
options?: Highcharts.Options;
|
|
27
|
-
/**
|
|
28
|
-
height?: string;
|
|
27
|
+
/** Box size when a height is set (host min-height and height). */
|
|
28
|
+
height?: string | number;
|
|
29
29
|
}
|
|
30
30
|
/** Separated `{ chart, aq }` input for `<nile-kpi-chart>`. */
|
|
31
31
|
export interface NileKpiConfigInputType {
|
|
@@ -51,6 +51,8 @@ export declare class NileKpiChart extends NileElement {
|
|
|
51
51
|
private sparklineChart;
|
|
52
52
|
private gaugeChart;
|
|
53
53
|
private resizeObserver;
|
|
54
|
+
/** Tooltip element on document.body — outside shadow DOM, never clipped. */
|
|
55
|
+
private _tipEl;
|
|
54
56
|
private sparklineContainer;
|
|
55
57
|
private gaugeContainer;
|
|
56
58
|
/** Full configuration: `{ chart, aq }` (same convention as other Nile charts). */
|
|
@@ -89,13 +91,27 @@ export declare class NileKpiChart extends NileElement {
|
|
|
89
91
|
loading: boolean;
|
|
90
92
|
/** Highcharts options override for the sparkline or gauge. */
|
|
91
93
|
options: Highcharts.Options;
|
|
92
|
-
/**
|
|
94
|
+
/**
|
|
95
|
+
* Set by nile-chart: skip host border/shadow (variant card/gauge) so the parent chart-card is the only frame.
|
|
96
|
+
*/
|
|
97
|
+
embedInNileChart: boolean;
|
|
98
|
+
private _createTipEl;
|
|
99
|
+
private _showTip;
|
|
100
|
+
private _hideTip;
|
|
101
|
+
private formatCssLength;
|
|
102
|
+
private parseNumericValue;
|
|
103
|
+
private formatTooltipNumber;
|
|
104
|
+
private inferSparklineTooltipScale;
|
|
105
|
+
private getTooltipContent;
|
|
93
106
|
private applyConfig;
|
|
94
107
|
connectedCallback(): void;
|
|
95
108
|
disconnectedCallback(): void;
|
|
96
109
|
protected firstUpdated(): void;
|
|
97
110
|
protected updated(changedProperties: PropertyValues): void;
|
|
111
|
+
private syncSparklineChartSize;
|
|
98
112
|
private setupResizeObserver;
|
|
113
|
+
private _onSparklineMouseMove;
|
|
114
|
+
private _onSparklineMouseLeave;
|
|
99
115
|
private buildSparklineOptions;
|
|
100
116
|
private buildGaugeOptions;
|
|
101
117
|
private initSparkline;
|
|
@@ -103,8 +119,10 @@ export declare class NileKpiChart extends NileElement {
|
|
|
103
119
|
private destroySparkline;
|
|
104
120
|
private destroyGauge;
|
|
105
121
|
private destroyCharts;
|
|
122
|
+
private _onValueEnter;
|
|
123
|
+
private _onGaugeEnter;
|
|
124
|
+
private _onTipLeave;
|
|
106
125
|
private renderTrend;
|
|
107
|
-
private renderContent;
|
|
108
126
|
render(): TemplateResult;
|
|
109
127
|
}
|
|
110
128
|
declare global {
|