@spectric/ui 0.0.21 → 0.0.22
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/components/dialog/dialog.d.ts +1 -0
- package/dist/components/pagination/pagination.d.ts +1 -1
- package/dist/components/query_bar/QueryBar.d.ts +30 -10
- package/dist/components/query_bar/dateTimePopup.d.ts +2 -0
- package/dist/components/query_bar/geojsonPopup.d.ts +2 -0
- package/dist/components/query_bar/querylanguage/kuery/functions/geospatial.d.ts +19 -0
- package/dist/components/query_bar/querylanguage/outputTypes/toCQL.d.ts +2 -1
- package/dist/components/query_bar/querylanguage/outputTypes/toMongo.d.ts +6 -1
- package/dist/components/symbols.d.ts +6 -0
- package/dist/components/table/cell.d.ts +1 -1
- package/dist/components/table/table.d.ts +5 -1
- package/dist/custom-elements.json +5 -5
- package/dist/index.d.ts +4 -0
- package/dist/index.es.js +4382 -2795
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +349 -248
- package/dist/index.umd.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +6 -1
- package/src/components/dialog/dialog.css.ts +29 -29
- package/src/components/dialog/dialog.ts +3 -1
- package/src/components/input.ts +49 -39
- package/src/components/pagination/pagination.ts +167 -113
- package/src/components/query_bar/QueryBar.ts +438 -187
- package/src/components/query_bar/dateTimePopup.ts +54 -0
- package/src/components/query_bar/geojsonPopup.ts +44 -0
- package/src/components/query_bar/querylanguage/kuery/ast/_generated_/kuery.js +1836 -2745
- package/src/components/query_bar/querylanguage/kuery/ast/ast.ts +15 -13
- package/src/components/query_bar/querylanguage/kuery/ast/kuery.peg +92 -126
- package/src/components/query_bar/querylanguage/kuery/functions/geospatial.ts +25 -0
- package/src/components/query_bar/querylanguage/kuery/functions/index.ts +9 -7
- package/src/components/query_bar/querylanguage/outputTypes/toCQL.ts +56 -34
- package/src/components/query_bar/querylanguage/outputTypes/toMongo.ts +46 -34
- package/src/components/symbols.ts +6 -0
- package/src/components/table/__tests__/table.spec.ts +2 -2
- package/src/components/table/cell.ts +7 -3
- package/src/components/table/header.ts +3 -2
- package/src/components/table/table.css +4 -2
- package/src/components/table/table.ts +61 -5
- package/src/components/table/virtualBody.ts +8 -3
- package/src/components/tooltip/popover.ts +263 -225
- package/src/stories/Dialog.stories.ts +59 -0
- package/src/stories/QueryBar.stories.ts +46 -37
- package/src/stories/fixtures/data.ts +195 -36
- package/src/stories/table.stories.ts +70 -22
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
/* eslint-disable @kbn/eslint/require-license-header */
|
|
2
|
-
import { FieldTypes, KueryNode } from
|
|
3
|
-
import { wildcardSymbol } from
|
|
2
|
+
import { FieldTypes, KueryNode } from "../..";
|
|
3
|
+
import { wildcardSymbol } from "../kuery/node_types/wildcard";
|
|
4
|
+
import { wktToGeoJSON } from "@terraformer/wkt";
|
|
4
5
|
|
|
5
6
|
export const KQL_WILDCARD_SYMBOL = wildcardSymbol;
|
|
6
|
-
export const KQL_NODE_TYPE_WILDCARD =
|
|
7
|
-
export type FunctionName =
|
|
7
|
+
export const KQL_NODE_TYPE_WILDCARD = "wildcard";
|
|
8
|
+
export type FunctionName =
|
|
9
|
+
| "is"
|
|
10
|
+
| "and"
|
|
11
|
+
| "or"
|
|
12
|
+
| "not"
|
|
13
|
+
| "range"
|
|
14
|
+
| "exists"
|
|
15
|
+
| "nested";
|
|
8
16
|
const and = (node: KueryNode) => {
|
|
9
17
|
const children = node.arguments || [];
|
|
10
|
-
let query: any = {
|
|
18
|
+
let query: any = { $and: children.map((c: KueryNode) => toMongo(c)) };
|
|
11
19
|
|
|
12
20
|
return query;
|
|
13
21
|
};
|
|
@@ -17,62 +25,65 @@ const is = (node: KueryNode) => {
|
|
|
17
25
|
} = node;
|
|
18
26
|
|
|
19
27
|
let value = toMongo(valueArg);
|
|
20
|
-
const isExistsQuery =
|
|
28
|
+
const isExistsQuery =
|
|
29
|
+
valueArg.type === "wildcard" &&
|
|
30
|
+
(valueArg.value as any) === "@kuery-wildcard@";
|
|
21
31
|
if (isExistsQuery) {
|
|
22
|
-
return exists(node)
|
|
32
|
+
return exists(node);
|
|
23
33
|
}
|
|
24
|
-
let query: any = {}
|
|
25
|
-
query[toMongo(fieldNameArg)] = {
|
|
34
|
+
let query: any = {};
|
|
35
|
+
query[toMongo(fieldNameArg)] = { $eq: value };
|
|
26
36
|
return query;
|
|
27
37
|
};
|
|
28
38
|
|
|
29
39
|
const or = (node: KueryNode) => {
|
|
30
40
|
const children = node.arguments || [];
|
|
31
41
|
return {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
|
|
42
|
+
$or: children.map((child: KueryNode) => {
|
|
43
|
+
return toMongo(child);
|
|
44
|
+
}),
|
|
45
|
+
};
|
|
38
46
|
};
|
|
39
47
|
const not = (node: KueryNode) => {
|
|
40
48
|
const [fieldNameArg] = node.arguments;
|
|
41
49
|
let query: any = {};
|
|
42
|
-
query = {
|
|
50
|
+
query = { $ne: toMongo(fieldNameArg) };
|
|
43
51
|
return query;
|
|
44
52
|
};
|
|
45
53
|
|
|
46
54
|
const AST_TO_CQL = {
|
|
47
|
-
gt:
|
|
48
|
-
lt:
|
|
49
|
-
gte:
|
|
50
|
-
lte:
|
|
55
|
+
gt: "$gt",
|
|
56
|
+
lt: "$lt",
|
|
57
|
+
gte: "$gte",
|
|
58
|
+
lte: "$lte",
|
|
51
59
|
};
|
|
52
60
|
const range = (node: KueryNode) => {
|
|
53
61
|
const [fieldNameArg, operator] = node.arguments;
|
|
54
|
-
let valueArg = operator.value
|
|
62
|
+
let valueArg = operator.value;
|
|
55
63
|
// @ts-ignore
|
|
56
64
|
const opsign = AST_TO_CQL[operator.name];
|
|
57
65
|
let value = toMongo(valueArg);
|
|
58
66
|
|
|
59
|
-
let query: any = {}
|
|
60
|
-
query[fieldNameArg.value] = {}
|
|
61
|
-
query[fieldNameArg.value][opsign] = value
|
|
62
|
-
return query
|
|
63
|
-
|
|
64
|
-
|
|
67
|
+
let query: any = {};
|
|
68
|
+
query[fieldNameArg.value] = {};
|
|
69
|
+
query[fieldNameArg.value][opsign] = value;
|
|
70
|
+
return query;
|
|
65
71
|
};
|
|
66
72
|
const exists = (node: KueryNode) => {
|
|
67
73
|
const [fieldNameArg] = node.arguments;
|
|
68
|
-
return { [toMongo(fieldNameArg)]: { $ne: null } }
|
|
74
|
+
return { [toMongo(fieldNameArg)]: { $ne: null } };
|
|
69
75
|
};
|
|
70
76
|
|
|
71
77
|
const nested = (node: KueryNode) => {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
78
|
+
console.warn("TODO Implement nested search", node);
|
|
79
|
+
return "";
|
|
80
|
+
};
|
|
81
|
+
const geospatial = (node: KueryNode) => {
|
|
82
|
+
const [fieldName, operator, value] = node.arguments;
|
|
83
|
+
if (operator == "within") {
|
|
84
|
+
return { [fieldName.value]: { $geoWithin: wktToGeoJSON(value.value) } };
|
|
85
|
+
}
|
|
86
|
+
};
|
|
76
87
|
export const functions = {
|
|
77
88
|
is,
|
|
78
89
|
and,
|
|
@@ -80,7 +91,8 @@ export const functions = {
|
|
|
80
91
|
not,
|
|
81
92
|
range,
|
|
82
93
|
exists,
|
|
83
|
-
nested
|
|
94
|
+
nested,
|
|
95
|
+
geospatial,
|
|
84
96
|
};
|
|
85
97
|
const nodeTypes = {
|
|
86
98
|
function: (node: KueryNode) => {
|
|
@@ -92,7 +104,7 @@ const nodeTypes = {
|
|
|
92
104
|
},
|
|
93
105
|
wildcard: (node: KueryNode) => {
|
|
94
106
|
const { value } = node;
|
|
95
|
-
return `/${value.split(KQL_WILDCARD_SYMBOL).join(
|
|
107
|
+
return `/${value.split(KQL_WILDCARD_SYMBOL).join(".*")}/`;
|
|
96
108
|
},
|
|
97
109
|
};
|
|
98
110
|
|
|
@@ -28,7 +28,7 @@ test.beforeEach(async ({ page }) => {
|
|
|
28
28
|
test.describe("Spectric Table Tests", () => {
|
|
29
29
|
test("MultiSelect Table Select All/Deselect All ", async ({ page }) => {
|
|
30
30
|
await page.goto(
|
|
31
|
-
"http://localhost:6006/iframe.html?globals=&args=&id=spectric-ui-components-ui-table--
|
|
31
|
+
"http://localhost:6006/iframe.html?globals=&args=&id=spectric-ui-components-ui-table--multi-select&viewMode=story"
|
|
32
32
|
);
|
|
33
33
|
let tableLocator = page.locator("spectric-table");
|
|
34
34
|
tableLocator.waitFor();
|
|
@@ -149,7 +149,7 @@ test.describe("Spectric Table Tests", () => {
|
|
|
149
149
|
page,
|
|
150
150
|
}) => {
|
|
151
151
|
await page.goto(
|
|
152
|
-
"http://localhost:6006/iframe.html?globals=&args=&id=spectric-ui-components-ui-table--
|
|
152
|
+
"http://localhost:6006/iframe.html?globals=&args=&id=spectric-ui-components-ui-table--multi-select&viewMode=story"
|
|
153
153
|
);
|
|
154
154
|
let tableLocator = page.locator("spectric-table");
|
|
155
155
|
await tableLocator.waitFor();
|
|
@@ -79,7 +79,11 @@ export class TableCellElement<T> extends LitElement implements CellProps<T> {
|
|
|
79
79
|
column: this.column,
|
|
80
80
|
});
|
|
81
81
|
};
|
|
82
|
-
|
|
82
|
+
_displayOverflowTooltip = () => {
|
|
83
|
+
if (this.column.disableCellOverflowTooltip) {
|
|
84
|
+
this.overflow = null;
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
83
87
|
let div = this.querySelector("div.cell-contents");
|
|
84
88
|
let span = this.querySelector("span");
|
|
85
89
|
if (div && span) {
|
|
@@ -90,7 +94,7 @@ export class TableCellElement<T> extends LitElement implements CellProps<T> {
|
|
|
90
94
|
divBounds.width * divBounds.height
|
|
91
95
|
) {
|
|
92
96
|
console.log(
|
|
93
|
-
"We need to show a tooltip
|
|
97
|
+
"We need to show a tooltip with the content because we are overflowing"
|
|
94
98
|
);
|
|
95
99
|
this.overflow = this.getRenderedValue();
|
|
96
100
|
this.updateComplete.then(() => {
|
|
@@ -151,7 +155,7 @@ export class TableCellElement<T> extends LitElement implements CellProps<T> {
|
|
|
151
155
|
return html`
|
|
152
156
|
<td
|
|
153
157
|
style=${styleMap(this.styleRules)}
|
|
154
|
-
@mouseenter=${this.
|
|
158
|
+
@mouseenter=${this._displayOverflowTooltip}
|
|
155
159
|
>
|
|
156
160
|
${filterButtons}
|
|
157
161
|
<div class=${classes.join(" ")}>
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
TableSortDirection,
|
|
15
15
|
} from "./table";
|
|
16
16
|
import { DisposableElement } from "../../classes";
|
|
17
|
+
import { ARROW_DOWN, ARROW_UP } from "../symbols";
|
|
17
18
|
|
|
18
19
|
interface HeaderProps<T> {
|
|
19
20
|
columns: ColumnSettings<T>[];
|
|
@@ -125,9 +126,9 @@ export class TableHeaderElement<T>
|
|
|
125
126
|
: "";
|
|
126
127
|
let sortDirection =
|
|
127
128
|
column.sortDirection === TableSortDirection.ascending
|
|
128
|
-
?
|
|
129
|
+
? ARROW_UP
|
|
129
130
|
: column.sortDirection == TableSortDirection.descending
|
|
130
|
-
?
|
|
131
|
+
? ARROW_DOWN
|
|
131
132
|
: ``;
|
|
132
133
|
let sortClass = column.sortDirection || TableSortDirection.none;
|
|
133
134
|
let resizable = column.allowResize || column.allowResize === undefined;
|
|
@@ -20,14 +20,16 @@ spectric-table spectric-table-virtual-body tr:hover{
|
|
|
20
20
|
background-color: color-mix(in srgb, var(--spectric-primary, #1ea7fd), transparent 70%)
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
spectric-table tr {
|
|
23
|
+
spectric-table spectric-table-virtual-body tr {
|
|
24
24
|
height: var(--rowHeight);
|
|
25
25
|
}
|
|
26
26
|
spectric-table td{
|
|
27
|
-
height: var(--rowHeight);
|
|
28
27
|
padding:1px;
|
|
29
28
|
border: 1px solid transparent;
|
|
30
29
|
}
|
|
30
|
+
spectric-table spectric-table-virtual-body td{
|
|
31
|
+
height: var(--rowHeight);
|
|
32
|
+
}
|
|
31
33
|
|
|
32
34
|
spectric-table div[role="table"]{
|
|
33
35
|
display: table;
|
|
@@ -53,6 +53,7 @@ export type ColumnSettings<T> = {
|
|
|
53
53
|
sortable?: boolean;
|
|
54
54
|
sortDirection?: TableSortDirectionTypes;
|
|
55
55
|
filterable?: boolean;
|
|
56
|
+
disableCellOverflowTooltip?: boolean;
|
|
56
57
|
title?: DomRenderable | ((table: SpectricTableElement<T>) => DomRenderable);
|
|
57
58
|
/**
|
|
58
59
|
* Key to used for getting data from an object for a cell
|
|
@@ -237,7 +238,7 @@ export class SpectricTableElement<T = any>
|
|
|
237
238
|
protected createRenderRoot(): HTMLElement | DocumentFragment {
|
|
238
239
|
return this;
|
|
239
240
|
}
|
|
240
|
-
forceRefreshofSelectionColumn() {
|
|
241
|
+
private forceRefreshofSelectionColumn() {
|
|
241
242
|
// Because lit reuses dom elements for speed/effeciency it wont update unless the props are a different object.
|
|
242
243
|
// So we set the selection colum to a "new object" to force the rerender
|
|
243
244
|
let index = this.columns.findIndex(
|
|
@@ -251,6 +252,9 @@ export class SpectricTableElement<T = any>
|
|
|
251
252
|
this.selected = selected;
|
|
252
253
|
this.forceRefreshofSelectionColumn();
|
|
253
254
|
}
|
|
255
|
+
getSelected() {
|
|
256
|
+
return this.selected;
|
|
257
|
+
}
|
|
254
258
|
deselectAll() {
|
|
255
259
|
this.selected = [];
|
|
256
260
|
this.forceRefreshofSelectionColumn();
|
|
@@ -261,6 +265,53 @@ export class SpectricTableElement<T = any>
|
|
|
261
265
|
this.forceRefreshofSelectionColumn();
|
|
262
266
|
this.dispatchEvent(new CustomEvent("selected", { detail: this.selected }));
|
|
263
267
|
}
|
|
268
|
+
async scrollToRow(row: T | number) {
|
|
269
|
+
let index: number = -1;
|
|
270
|
+
if (Number.isInteger(row)) {
|
|
271
|
+
index = row as number;
|
|
272
|
+
} else {
|
|
273
|
+
index = this.data.findIndex((value) => value === row);
|
|
274
|
+
}
|
|
275
|
+
if (index !== -1) {
|
|
276
|
+
let body = this.querySelector("spectric-table-virtual-body");
|
|
277
|
+
let wrapper = this.querySelector(".table-wrapper")!;
|
|
278
|
+
let scrollPosition = index * this._getRowHeight();
|
|
279
|
+
wrapper.scrollTo({
|
|
280
|
+
top: scrollPosition,
|
|
281
|
+
behavior: "smooth",
|
|
282
|
+
});
|
|
283
|
+
//Wait for the smooth scroll to complete. Scroll to doesn't return a promise so we must manually check periodically
|
|
284
|
+
for (let wait = 0; wait < 100; wait++) {
|
|
285
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
286
|
+
if (wrapper.scrollTop == scrollPosition) {
|
|
287
|
+
console.log("Scroll complete");
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
if (body) {
|
|
292
|
+
//Highlight the row we scrolled to
|
|
293
|
+
requestAnimationFrame(() => {
|
|
294
|
+
let rows = [...body.querySelectorAll("tr")];
|
|
295
|
+
rows = rows.filter(
|
|
296
|
+
(row) => row.querySelector("spectric-table-cell")?.index === index
|
|
297
|
+
);
|
|
298
|
+
if (rows.length) {
|
|
299
|
+
rows[0].animate(
|
|
300
|
+
[{ backgroundColor: "red" }, { backgroundColor: "unset" }],
|
|
301
|
+
{ duration: 200, iterations: 5 }
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
_getRowHeight = () => {
|
|
309
|
+
let rowHeight = this.rowHeight - TD_BorderAndPadding;
|
|
310
|
+
if (rowHeight < this.fontSize + TD_BorderAndPadding) {
|
|
311
|
+
rowHeight = this.fontSize + TD_BorderAndPadding;
|
|
312
|
+
}
|
|
313
|
+
return rowHeight;
|
|
314
|
+
};
|
|
264
315
|
_handleSelectAllChange = (e: DomEvent<HTMLInputElement>) => {
|
|
265
316
|
e.stopPropagation();
|
|
266
317
|
if (e.target.checked) {
|
|
@@ -314,6 +365,14 @@ export class SpectricTableElement<T = any>
|
|
|
314
365
|
},
|
|
315
366
|
};
|
|
316
367
|
protected update(changedProperties: PropertyValues): void {
|
|
368
|
+
if (changedProperties.has("data")) {
|
|
369
|
+
this.selected = this.data.reduce((a, row) => {
|
|
370
|
+
if (this.selected.includes(row)) {
|
|
371
|
+
a.push(row);
|
|
372
|
+
}
|
|
373
|
+
return a;
|
|
374
|
+
}, [] as T[]);
|
|
375
|
+
}
|
|
317
376
|
if (changedProperties.has("columns")) {
|
|
318
377
|
if (this.select !== TableSelectOptions.none) {
|
|
319
378
|
if (!this.columns.find((col) => col[TABLE_CREATED_SELECTION_COLUMN])) {
|
|
@@ -333,10 +392,7 @@ export class SpectricTableElement<T = any>
|
|
|
333
392
|
}
|
|
334
393
|
protected render(): unknown {
|
|
335
394
|
let columns = this.columns.filter((column) => !column.hidden);
|
|
336
|
-
let rowHeight = this.
|
|
337
|
-
if (rowHeight < this.fontSize + TD_BorderAndPadding) {
|
|
338
|
-
rowHeight = this.fontSize + TD_BorderAndPadding;
|
|
339
|
-
}
|
|
395
|
+
let rowHeight = this._getRowHeight();
|
|
340
396
|
return html`
|
|
341
397
|
<div
|
|
342
398
|
class="table-wrapper"
|
|
@@ -43,14 +43,19 @@ export class TableVirtualBodyElement<T>
|
|
|
43
43
|
columnsMeasured: boolean = false;
|
|
44
44
|
constructor() {
|
|
45
45
|
super();
|
|
46
|
+
let lastScroll = 0;
|
|
46
47
|
this.addDisposableListener(
|
|
47
48
|
() => this.table.querySelector(".table-wrapper")!,
|
|
48
49
|
"scroll",
|
|
49
50
|
() => {
|
|
50
51
|
const scrollTop = this.table.querySelector(".table-wrapper")!.scrollTop;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
// Prevent changing the start index if the scroll hasn't changed more than at at least 1/4 a row
|
|
53
|
+
// I think I have bad math that is causing a new scroll event due to a couple pixel height difference after I create the spacers
|
|
54
|
+
if (Math.abs(lastScroll - scrollTop) <= this.rowHeight / 4) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
lastScroll = scrollTop;
|
|
58
|
+
this.startIndex = Math.floor(scrollTop / this.rowHeight);
|
|
54
59
|
}
|
|
55
60
|
);
|
|
56
61
|
}
|