@aquera/nile-visualization 2.9.8 → 2.9.10
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/nile-chart/nile-chart-config.d.ts +1 -0
- package/dist/src/nile-chart/nile-chart-skeleton.d.ts +2 -0
- package/dist/src/nile-chart/nile-chart-skeleton.js +184 -0
- package/dist/src/nile-chart/nile-chart.css.js +421 -36
- package/dist/src/nile-chart/nile-chart.d.ts +3 -0
- package/dist/src/nile-chart/nile-chart.js +33 -17
- package/dist/src/nile-filter-chart/nile-filter-chart.css.js +196 -124
- package/dist/src/nile-filter-chart/nile-filter-chart.d.ts +20 -3
- package/dist/src/nile-filter-chart/nile-filter-chart.js +97 -25
- package/dist/src/nile-filter-chart/utils/prompt.js +211 -61
- package/dist/src/nile-filter-chart/utils/types.d.ts +60 -27
- package/package.json +1 -1
|
@@ -8,6 +8,13 @@ export declare class NileFilterChart extends NileElement implements FilterChartH
|
|
|
8
8
|
/** When set, the host (e.g. nile-chart) is already rendering the control's label/description
|
|
9
9
|
* in its own header — skip the in-body copies to avoid duplication. */
|
|
10
10
|
hideControlHeaders: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Visual appearance. `'minimal'` collapses control padding to 6px for
|
|
13
|
+
* compact layouts; default (`'default'` or omitted) keeps the standard
|
|
14
|
+
* 16px / 20px. Set via the reflected `appearance` attribute, the
|
|
15
|
+
* `.appearance` property, or `config.chart.appearance`.
|
|
16
|
+
*/
|
|
17
|
+
appearance: 'default' | 'minimal';
|
|
11
18
|
selectedValues: Map<string, unknown>;
|
|
12
19
|
private collapsedGroups;
|
|
13
20
|
/** Currently displayed (animated) placeholder text per prompt-variant control id. */
|
|
@@ -21,8 +28,17 @@ export declare class NileFilterChart extends NileElement implements FilterChartH
|
|
|
21
28
|
/** Id of the prompt control whose input currently has focus (drives the
|
|
22
29
|
* nile-dropdown panel open state). null when no prompt is focused. */
|
|
23
30
|
promptFocusedId: string | null;
|
|
24
|
-
/**
|
|
31
|
+
/** Pixel width of each prompt control's bordered field — kept in sync with
|
|
32
|
+
* the rendered `.fc-prompt__field` via a ResizeObserver attached in
|
|
33
|
+
* prompt.ts. Consumed by the suggestion tooltip so its popup matches the
|
|
34
|
+
* input box width and wraps long content onto multiple lines. */
|
|
35
|
+
promptFieldWidth: Map<string, number>;
|
|
36
|
+
/** Active rtypewiter timers per prompt control id (so we can stop them). */
|
|
25
37
|
private _promptTimers;
|
|
38
|
+
/** Per-control typewriter tick fn — retained so the animation can be resumed
|
|
39
|
+
* from its preserved closure state (phrase index, char index, deleting flag)
|
|
40
|
+
* after a pause-at-rest-point. */
|
|
41
|
+
private _promptTickFns;
|
|
26
42
|
/** Compiled filtrex predicates per prompt control id (strict-mode successes). */
|
|
27
43
|
private _promptEvaluators;
|
|
28
44
|
/** Parsed AST per prompt control id (strict-mode successes). */
|
|
@@ -60,6 +76,7 @@ export declare class NileFilterChart extends NileElement implements FilterChartH
|
|
|
60
76
|
submitPrompt(ctrl: NormalizedFilterControl): void;
|
|
61
77
|
setPromptActiveIndex(id: string, idx: number): void;
|
|
62
78
|
setPromptFocused(id: string, focused: boolean): void;
|
|
79
|
+
setPromptFieldWidth(id: string, width: number): void;
|
|
63
80
|
private _validateOrClear;
|
|
64
81
|
private _clearPromptValidation;
|
|
65
82
|
private _syncPromptAnimations;
|
|
@@ -80,8 +97,8 @@ export declare class NileFilterChart extends NileElement implements FilterChartH
|
|
|
80
97
|
private _renderControl;
|
|
81
98
|
/**
|
|
82
99
|
* If any prompt control in `controls` has its toggle enabled and is currently
|
|
83
|
-
* in
|
|
84
|
-
* shows everything,
|
|
100
|
+
* in Expression mode, collapse the visible set down to just that prompt —
|
|
101
|
+
* Prompt mode shows everything, Expression mode shows only the expression input.
|
|
85
102
|
*/
|
|
86
103
|
private _filterByPromptMode;
|
|
87
104
|
private _renderGroup;
|
|
@@ -24,6 +24,13 @@ let NileFilterChart = NileFilterChart_1 = class NileFilterChart extends NileElem
|
|
|
24
24
|
/** When set, the host (e.g. nile-chart) is already rendering the control's label/description
|
|
25
25
|
* in its own header — skip the in-body copies to avoid duplication. */
|
|
26
26
|
this.hideControlHeaders = false;
|
|
27
|
+
/**
|
|
28
|
+
* Visual appearance. `'minimal'` collapses control padding to 6px for
|
|
29
|
+
* compact layouts; default (`'default'` or omitted) keeps the standard
|
|
30
|
+
* 16px / 20px. Set via the reflected `appearance` attribute, the
|
|
31
|
+
* `.appearance` property, or `config.chart.appearance`.
|
|
32
|
+
*/
|
|
33
|
+
this.appearance = 'default';
|
|
27
34
|
this.selectedValues = new Map();
|
|
28
35
|
this.collapsedGroups = new Set();
|
|
29
36
|
/** Currently displayed (animated) placeholder text per prompt-variant control id. */
|
|
@@ -37,8 +44,17 @@ let NileFilterChart = NileFilterChart_1 = class NileFilterChart extends NileElem
|
|
|
37
44
|
/** Id of the prompt control whose input currently has focus (drives the
|
|
38
45
|
* nile-dropdown panel open state). null when no prompt is focused. */
|
|
39
46
|
this.promptFocusedId = null;
|
|
40
|
-
/**
|
|
47
|
+
/** Pixel width of each prompt control's bordered field — kept in sync with
|
|
48
|
+
* the rendered `.fc-prompt__field` via a ResizeObserver attached in
|
|
49
|
+
* prompt.ts. Consumed by the suggestion tooltip so its popup matches the
|
|
50
|
+
* input box width and wraps long content onto multiple lines. */
|
|
51
|
+
this.promptFieldWidth = new Map();
|
|
52
|
+
/** Active rtypewiter timers per prompt control id (so we can stop them). */
|
|
41
53
|
this._promptTimers = new Map();
|
|
54
|
+
/** Per-control typewriter tick fn — retained so the animation can be resumed
|
|
55
|
+
* from its preserved closure state (phrase index, char index, deleting flag)
|
|
56
|
+
* after a pause-at-rest-point. */
|
|
57
|
+
this._promptTickFns = new Map();
|
|
42
58
|
/** Compiled filtrex predicates per prompt control id (strict-mode successes). */
|
|
43
59
|
this._promptEvaluators = new Map();
|
|
44
60
|
/** Parsed AST per prompt control id (strict-mode successes). */
|
|
@@ -71,6 +87,9 @@ let NileFilterChart = NileFilterChart_1 = class NileFilterChart extends NileElem
|
|
|
71
87
|
this._normalizeIds();
|
|
72
88
|
this._initValues();
|
|
73
89
|
this._syncPromptAnimations();
|
|
90
|
+
const cfgAppearance = this.config?.chart?.appearance;
|
|
91
|
+
if (cfgAppearance === 'minimal' || cfgAppearance === 'default')
|
|
92
|
+
this.appearance = cfgAppearance;
|
|
74
93
|
}
|
|
75
94
|
// Keep portaled suggestion panels in sync with the latest panel content.
|
|
76
95
|
// nile-dropdown clones the panel once at open-time and never re-clones,
|
|
@@ -125,6 +144,10 @@ let NileFilterChart = NileFilterChart_1 = class NileFilterChart extends NileElem
|
|
|
125
144
|
clearTimeout(pending);
|
|
126
145
|
this._promptDebounce.delete(ctrl.id);
|
|
127
146
|
}
|
|
147
|
+
if (this._promptTimers.has(ctrl.id)) {
|
|
148
|
+
this._stopPromptAnimation(ctrl.id);
|
|
149
|
+
this._startPromptAnimation(ctrl);
|
|
150
|
+
}
|
|
128
151
|
const value = String(this.selectedValues.get(ctrl.id) ?? '');
|
|
129
152
|
this._validateOrClear(ctrl, value, { explicit: true });
|
|
130
153
|
}
|
|
@@ -147,13 +170,42 @@ let NileFilterChart = NileFilterChart_1 = class NileFilterChart extends NileElem
|
|
|
147
170
|
setPromptFocused(id, focused) {
|
|
148
171
|
if (focused) {
|
|
149
172
|
this.promptFocusedId = id;
|
|
173
|
+
const t = this._promptTimers.get(id);
|
|
174
|
+
if (t) {
|
|
175
|
+
clearTimeout(t);
|
|
176
|
+
this._promptTimers.delete(id);
|
|
177
|
+
}
|
|
178
|
+
if (this.promptPlaceholder.get(id) !== '') {
|
|
179
|
+
this.promptPlaceholder = new Map(this.promptPlaceholder).set(id, '');
|
|
180
|
+
}
|
|
150
181
|
}
|
|
151
182
|
else if (this.promptFocusedId === id) {
|
|
152
183
|
this.promptFocusedId = null;
|
|
184
|
+
// Resume from the preserved closure state. Guard against re-entry: if
|
|
185
|
+
// a timer somehow exists (shouldn't, but defensive), don't double-tick.
|
|
186
|
+
const tickFn = this._promptTickFns.get(id);
|
|
187
|
+
if (tickFn && !this._promptTimers.has(id)) {
|
|
188
|
+
tickFn();
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
setPromptFieldWidth(id, width) {
|
|
193
|
+
const rounded = Math.round(width);
|
|
194
|
+
if (this.promptFieldWidth.get(id) === rounded)
|
|
195
|
+
return;
|
|
196
|
+
this.promptFieldWidth = new Map(this.promptFieldWidth).set(id, rounded);
|
|
197
|
+
// Tippy popups are portaled to document.body so component-scoped styles
|
|
198
|
+
// can't reach them, and nile-lite-tooltip's `maxWidth` only takes effect
|
|
199
|
+
// at attach time (its updated() hook doesn't re-attach for maxWidth
|
|
200
|
+
// changes). Mirror the live width onto a document-level CSS variable
|
|
201
|
+
// the global .tippy-box rule reads — wrapping then always reflects
|
|
202
|
+
// the current input width.
|
|
203
|
+
if (typeof document !== 'undefined') {
|
|
204
|
+
document.documentElement.style.setProperty('--fc-prompt-tooltip-max-width', `${rounded}px`);
|
|
153
205
|
}
|
|
154
206
|
}
|
|
155
207
|
_validateOrClear(ctrl, value, opts = {}) {
|
|
156
|
-
const isNql = this.promptModes.get(ctrl.id) === '
|
|
208
|
+
const isNql = this.promptModes.get(ctrl.id) === 'expression';
|
|
157
209
|
if (value.trim() === '') {
|
|
158
210
|
this._clearPromptValidation(ctrl.id);
|
|
159
211
|
this._emitChange();
|
|
@@ -187,7 +239,6 @@ let NileFilterChart = NileFilterChart_1 = class NileFilterChart extends NileElem
|
|
|
187
239
|
// expressions); NQL surfaces them so the user sees what's wrong.
|
|
188
240
|
const errs = new Map(this.promptErrors);
|
|
189
241
|
if (isNql) {
|
|
190
|
-
console.error(`[nile-filter-chart] "${ctrl.id}" parse error:`, error.message);
|
|
191
242
|
errs.set(ctrl.id, error.message);
|
|
192
243
|
}
|
|
193
244
|
else {
|
|
@@ -213,7 +264,7 @@ let NileFilterChart = NileFilterChart_1 = class NileFilterChart extends NileElem
|
|
|
213
264
|
_syncPromptAnimations() {
|
|
214
265
|
const wanted = new Set();
|
|
215
266
|
for (const ctrl of this._flatControls()) {
|
|
216
|
-
if (ctrl.variant === 'prompt') {
|
|
267
|
+
if (ctrl.variant === 'prompt' || ctrl.variant === 'hybrid' || ctrl.variant === 'expression') {
|
|
217
268
|
wanted.add(ctrl.id);
|
|
218
269
|
if (!this._promptTimers.has(ctrl.id))
|
|
219
270
|
this._startPromptAnimation(ctrl);
|
|
@@ -226,9 +277,18 @@ let NileFilterChart = NileFilterChart_1 = class NileFilterChart extends NileElem
|
|
|
226
277
|
}
|
|
227
278
|
}
|
|
228
279
|
_startPromptAnimation(ctrl) {
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
280
|
+
const getPhrases = () => {
|
|
281
|
+
const mode = this.promptModes.get(ctrl.id);
|
|
282
|
+
if (ctrl.variant === 'hybrid' || ctrl.variant === 'expression') {
|
|
283
|
+
if (mode === 'expression' && ctrl.expressionPlaceholders?.length)
|
|
284
|
+
return ctrl.expressionPlaceholders;
|
|
285
|
+
if (mode === 'prompt' && ctrl.promptPlaceholders?.length)
|
|
286
|
+
return ctrl.promptPlaceholders;
|
|
287
|
+
}
|
|
288
|
+
return ctrl.placeholders && ctrl.placeholders.length
|
|
289
|
+
? ctrl.placeholders
|
|
290
|
+
: ['Ask anything…'];
|
|
291
|
+
};
|
|
232
292
|
const typeSpeed = ctrl.typeSpeedMs ?? 60;
|
|
233
293
|
const pauseAfterType = ctrl.pauseBeforeDeleteMs ?? 1400;
|
|
234
294
|
const pauseBetween = ctrl.pauseBetweenMs ?? 400;
|
|
@@ -236,6 +296,9 @@ let NileFilterChart = NileFilterChart_1 = class NileFilterChart extends NileElem
|
|
|
236
296
|
let charIdx = 0;
|
|
237
297
|
let deleting = false;
|
|
238
298
|
const tick = () => {
|
|
299
|
+
const phrases = getPhrases();
|
|
300
|
+
if (phraseIdx >= phrases.length)
|
|
301
|
+
phraseIdx = 0;
|
|
239
302
|
const phrase = phrases[phraseIdx];
|
|
240
303
|
let nextDelay;
|
|
241
304
|
if (!deleting) {
|
|
@@ -265,15 +328,18 @@ let NileFilterChart = NileFilterChart_1 = class NileFilterChart extends NileElem
|
|
|
265
328
|
}
|
|
266
329
|
this._promptTimers.set(ctrl.id, setTimeout(tick, nextDelay));
|
|
267
330
|
};
|
|
268
|
-
|
|
331
|
+
this._promptTickFns.set(ctrl.id, tick);
|
|
269
332
|
this.promptPlaceholder = new Map(this.promptPlaceholder).set(ctrl.id, '');
|
|
270
|
-
this.
|
|
333
|
+
if (this.promptFocusedId !== ctrl.id) {
|
|
334
|
+
this._promptTimers.set(ctrl.id, setTimeout(tick, 100));
|
|
335
|
+
}
|
|
271
336
|
}
|
|
272
337
|
_stopPromptAnimation(id) {
|
|
273
338
|
const t = this._promptTimers.get(id);
|
|
274
339
|
if (t)
|
|
275
340
|
clearTimeout(t);
|
|
276
341
|
this._promptTimers.delete(id);
|
|
342
|
+
this._promptTickFns.delete(id);
|
|
277
343
|
const next = new Map(this.promptPlaceholder);
|
|
278
344
|
next.delete(id);
|
|
279
345
|
this.promptPlaceholder = next;
|
|
@@ -357,8 +423,8 @@ let NileFilterChart = NileFilterChart_1 = class NileFilterChart extends NileElem
|
|
|
357
423
|
|| ctrl.variant === 'expression'
|
|
358
424
|
|| ctrl.variant === 'hybrid') {
|
|
359
425
|
const initialMode = ctrl.variant === 'expression'
|
|
360
|
-
? '
|
|
361
|
-
: (ctrl.queryLanguage?.mode ?? 'strict') === 'strict' ? '
|
|
426
|
+
? 'expression'
|
|
427
|
+
: (ctrl.queryLanguage?.mode ?? 'strict') === 'strict' ? 'expression' : 'prompt';
|
|
362
428
|
modes.set(ctrl.id, initialMode);
|
|
363
429
|
}
|
|
364
430
|
if (ctrl.value !== undefined) {
|
|
@@ -403,12 +469,12 @@ let NileFilterChart = NileFilterChart_1 = class NileFilterChart extends NileElem
|
|
|
403
469
|
this.selectedValues.forEach((val, id) => {
|
|
404
470
|
// Prompt controls in NQL mode with a successful parse emit the
|
|
405
471
|
// structured `{ source, ast }` payload so downstream consumers get
|
|
406
|
-
// both the typed text and the parsed shape.
|
|
472
|
+
// both the typed text and the parsed shape. Prompt mode (and Expression
|
|
407
473
|
// pre-validation / parse-failure) emit the raw string — the same
|
|
408
474
|
// shape every other variant uses.
|
|
409
475
|
const mode = this.promptModes.get(id);
|
|
410
476
|
const ast = this._promptAsts.get(id);
|
|
411
|
-
if (mode === '
|
|
477
|
+
if (mode === 'expression' && ast && typeof val === 'string' && val.trim() !== '') {
|
|
412
478
|
filters[id] = { source: val, ast };
|
|
413
479
|
}
|
|
414
480
|
else {
|
|
@@ -422,13 +488,13 @@ let NileFilterChart = NileFilterChart_1 = class NileFilterChart extends NileElem
|
|
|
422
488
|
detail.errors = errors;
|
|
423
489
|
}
|
|
424
490
|
if (this._promptEvaluators.size > 0) {
|
|
425
|
-
// Only surface evaluators for controls whose active mode is
|
|
426
|
-
// In
|
|
427
|
-
//
|
|
428
|
-
//
|
|
491
|
+
// Only surface evaluators for controls whose active mode is Expression.
|
|
492
|
+
// In Prompt mode the consumer expects a plain-string payload — leaking
|
|
493
|
+
// the cached evaluator from the last Expression pass would lie about
|
|
494
|
+
// what the user has selected.
|
|
429
495
|
const evaluators = {};
|
|
430
496
|
this._promptEvaluators.forEach((fn, id) => {
|
|
431
|
-
if (this.promptModes.get(id) === '
|
|
497
|
+
if (this.promptModes.get(id) === 'expression')
|
|
432
498
|
evaluators[id] = fn;
|
|
433
499
|
});
|
|
434
500
|
if (Object.keys(evaluators).length > 0)
|
|
@@ -488,8 +554,8 @@ let NileFilterChart = NileFilterChart_1 = class NileFilterChart extends NileElem
|
|
|
488
554
|
enabled: true,
|
|
489
555
|
mode: ctrl.queryLanguage?.mode ?? 'strict',
|
|
490
556
|
toggle: {
|
|
491
|
-
|
|
492
|
-
|
|
557
|
+
prompt: { label: ctrl.queryLanguage?.toggle?.prompt?.label ?? 'Prompt' },
|
|
558
|
+
expression: { label: ctrl.queryLanguage?.toggle?.expression?.label ?? 'Expression' },
|
|
493
559
|
},
|
|
494
560
|
},
|
|
495
561
|
});
|
|
@@ -506,15 +572,15 @@ let NileFilterChart = NileFilterChart_1 = class NileFilterChart extends NileElem
|
|
|
506
572
|
}
|
|
507
573
|
/**
|
|
508
574
|
* If any prompt control in `controls` has its toggle enabled and is currently
|
|
509
|
-
* in
|
|
510
|
-
* shows everything,
|
|
575
|
+
* in Expression mode, collapse the visible set down to just that prompt —
|
|
576
|
+
* Prompt mode shows everything, Expression mode shows only the expression input.
|
|
511
577
|
*/
|
|
512
578
|
_filterByPromptMode(controls) {
|
|
513
|
-
const
|
|
579
|
+
const expressionPrompt = controls.find(c => ((c.variant === 'prompt' && c.queryLanguage?.enabled)
|
|
514
580
|
|| c.variant === 'hybrid'
|
|
515
581
|
|| c.variant === 'expression')
|
|
516
|
-
&& this.promptModes.get(c.id) === '
|
|
517
|
-
return
|
|
582
|
+
&& this.promptModes.get(c.id) === 'expression');
|
|
583
|
+
return expressionPrompt ? [expressionPrompt] : controls;
|
|
518
584
|
}
|
|
519
585
|
_renderGroup(group) {
|
|
520
586
|
const collapsed = this.collapsedGroups.has(group.label);
|
|
@@ -573,6 +639,9 @@ __decorate([
|
|
|
573
639
|
__decorate([
|
|
574
640
|
property({ type: Boolean, attribute: 'hide-control-headers', reflect: true })
|
|
575
641
|
], NileFilterChart.prototype, "hideControlHeaders", void 0);
|
|
642
|
+
__decorate([
|
|
643
|
+
property({ type: String, reflect: true })
|
|
644
|
+
], NileFilterChart.prototype, "appearance", void 0);
|
|
576
645
|
__decorate([
|
|
577
646
|
state()
|
|
578
647
|
], NileFilterChart.prototype, "selectedValues", void 0);
|
|
@@ -594,6 +663,9 @@ __decorate([
|
|
|
594
663
|
__decorate([
|
|
595
664
|
state()
|
|
596
665
|
], NileFilterChart.prototype, "promptFocusedId", void 0);
|
|
666
|
+
__decorate([
|
|
667
|
+
state()
|
|
668
|
+
], NileFilterChart.prototype, "promptFieldWidth", void 0);
|
|
597
669
|
NileFilterChart = NileFilterChart_1 = __decorate([
|
|
598
670
|
customElement('nile-filter-chart')
|
|
599
671
|
], NileFilterChart);
|