@oicl/openbridge-webcomponents-full-bundle 2.0.0-next.149 → 2.0.0-next.150

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.
Files changed (26) hide show
  1. package/bundle/openbridge-webcomponents.bundle.js +4443 -3841
  2. package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
  3. package/custom-elements.json +381 -2
  4. package/dist/components/alert-list-details-experimental/alert-list-details-experimental.css.js +94 -0
  5. package/dist/components/alert-list-details-experimental/alert-list-details-experimental.css.js.map +1 -0
  6. package/dist/components/alert-list-details-experimental/alert-list-details-experimental.d.ts +72 -0
  7. package/dist/components/alert-list-details-experimental/alert-list-details-experimental.d.ts.map +1 -0
  8. package/dist/components/alert-list-details-experimental/alert-list-details-experimental.js +396 -0
  9. package/dist/components/alert-list-details-experimental/alert-list-details-experimental.js.map +1 -0
  10. package/dist/components/table/table.css.js +43 -0
  11. package/dist/components/table/table.css.js.map +1 -1
  12. package/dist/components/table/table.d.ts +31 -1
  13. package/dist/components/table/table.d.ts.map +1 -1
  14. package/dist/components/table/table.js +124 -11
  15. package/dist/components/table/table.js.map +1 -1
  16. package/dist/types.d.ts +2 -0
  17. package/dist/types.d.ts.map +1 -1
  18. package/dist/types.js.map +1 -1
  19. package/package.json +1 -1
  20. package/src/components/alert-list-details-experimental/alert-list-details-experimental.css +70 -0
  21. package/src/components/alert-list-details-experimental/alert-list-details-experimental.stories.ts +510 -0
  22. package/src/components/alert-list-details-experimental/alert-list-details-experimental.ts +457 -0
  23. package/src/components/table/table.css +42 -0
  24. package/src/components/table/table.stories.ts +279 -0
  25. package/src/components/table/table.ts +177 -13
  26. package/src/types.ts +6 -4
@@ -0,0 +1,72 @@
1
+ import { LitElement } from 'lit';
2
+ import { Alert } from '../../types.js';
3
+ import '../icon-button/icon-button.js';
4
+ import '../button/button.js';
5
+ import '../../icons/icon-silence-iec.js';
6
+ import '../../icons/icon-alerts.js';
7
+ import '../../icons/icon-alerts-shelf.js';
8
+ import '../../icons/icon-alerts-active.js';
9
+ import '../../icons/icon-alarm-rectified-iec.js';
10
+ import '../../icons/icon-unacknowledged.js';
11
+ import '../../icons/icon-alarm-noack-iec.js';
12
+ import '../../icons/icon-warning-noack-iec.js';
13
+ import '../alert-icon/alert-icon.js';
14
+ import '../scrollbar/scrollbar.js';
15
+ export declare enum AlertListMode {
16
+ UNACKED = "unacked",
17
+ ALL = "all",
18
+ SHELVED = "shelved",
19
+ BLOCKED = "blocked",
20
+ RECTIFIED = "rectified"
21
+ }
22
+ export type ObcAckClickEvent = CustomEvent<{
23
+ alert: Alert;
24
+ }>;
25
+ export type ObcRowClickEvent = CustomEvent<{
26
+ alert: Alert;
27
+ }>;
28
+ export declare function getAlertListModeData(selectedMode: AlertListMode): {
29
+ name: AlertListMode;
30
+ title: string;
31
+ emptyTitle: string;
32
+ emptyIcon: import('lit-html').TemplateResult<1>;
33
+ filter: (alert: Alert) => boolean;
34
+ };
35
+ export declare function canAckFilter(filter: (alert: Alert) => boolean): (alert: Alert) => boolean;
36
+ /**
37
+ * @availableWhen timeFormatter showTime==true
38
+ * @property defaultExpanded - Whether groups start expanded. Set false to open the list collapsed.
39
+ * @fires {ObcAckClickEvent} ack-click - Fired when the user clicks the "ACK" button.
40
+ * @fires {ObcRowClickEvent} row-click - Fired when the user clicks a row.
41
+ * @experimental
42
+ */
43
+ export declare class ObcAlertListDetailsExperimental extends LitElement {
44
+ selectedMode: AlertListMode;
45
+ alerts: Alert[];
46
+ showTime: boolean;
47
+ timeFormatter: (time: Date) => string;
48
+ small: boolean;
49
+ /** Whether groups start expanded. Set false to open the list collapsed. */
50
+ defaultExpanded: boolean;
51
+ private alertList;
52
+ private expansionOverrides;
53
+ private alertByRowId;
54
+ getVisibleAlerts(): Alert[];
55
+ private onRowClick;
56
+ private onCellButtonClick;
57
+ private onExpandToggle;
58
+ private isExpanded;
59
+ private get columns();
60
+ private get metadata();
61
+ private get filteredAlerts();
62
+ private buildVisibleRows;
63
+ private buildRowCells;
64
+ render(): import('lit-html').TemplateResult<1>;
65
+ static styles: import('lit').CSSResult;
66
+ }
67
+ declare global {
68
+ interface HTMLElementTagNameMap {
69
+ 'obc-alert-list-details-experimental': ObcAlertListDetailsExperimental;
70
+ }
71
+ }
72
+ //# sourceMappingURL=alert-list-details-experimental.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alert-list-details-experimental.d.ts","sourceRoot":"","sources":["../../../src/components/alert-list-details-experimental/alert-list-details-experimental.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAkB,MAAM,KAAK,CAAC;AAKhD,OAAO,+BAA+B,CAAC;AACvC,OAAO,qBAAqB,CAAC;AAC7B,OAAO,iCAAiC,CAAC;AACzC,OAAO,4BAA4B,CAAC;AACpC,OAAO,kCAAkC,CAAC;AAC1C,OAAO,mCAAmC,CAAC;AAC3C,OAAO,yCAAyC,CAAC;AACjD,OAAO,oCAAoC,CAAC;AAC5C,OAAO,qCAAqC,CAAC;AAC7C,OAAO,uCAAuC,CAAC;AAC/C,OAAO,6BAA6B,CAAC;AACrC,OAAO,EACL,KAAK,EAMN,MAAM,gBAAgB,CAAC;AAgBxB,OAAO,2BAA2B,CAAC;AAEnC,oBAAY,aAAa;IACvB,OAAO,YAAY;IACnB,GAAG,QAAQ;IACX,OAAO,YAAY;IACnB,OAAO,YAAY;IACnB,SAAS,cAAc;CACxB;AAED,MAAM,MAAM,gBAAgB,GAAG,WAAW,CAAC;IACzC,KAAK,EAAE,KAAK,CAAC;CACd,CAAC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,WAAW,CAAC;IACzC,KAAK,EAAE,KAAK,CAAC;CACd,CAAC,CAAC;AAEH,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,aAAa;;;;;oBAO1C,KAAK;EAuC1B;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,IACpD,OAAO,KAAK,aAKrB;AAED;;;;;;GAMG;AACH,qBACa,+BAAgC,SAAQ,UAAU;IACnC,YAAY,EAAE,aAAa,CAAqB;IACjD,MAAM,EAAE,KAAK,EAAE,CAAM;IACnB,QAAQ,EAAE,OAAO,CAAS;IACvB,aAAa,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAEV;IAC9B,KAAK,EAAE,OAAO,CAAS;IACL,eAAe,EAAE,OAAO,CAAQ;IAG7E,OAAO,CAAC,SAAS,CAAY;IAEpB,OAAO,CAAC,kBAAkB,CAA8B;IAEjE,OAAO,CAAC,YAAY,CAA4B;IAEzC,gBAAgB,IAAI,KAAK,EAAE;IAelC,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,UAAU;IAIlB,OAAO,KAAK,OAAO,GAkFlB;IAED,OAAO,KAAK,QAAQ,GAEnB;IAED,OAAO,KAAK,cAAc,GAEzB;IAED,OAAO,CAAC,gBAAgB;IAiFxB,OAAO,CAAC,aAAa;IAkEZ,MAAM;IA0Bf,OAAgB,MAAM,0BAA2B;CAClD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,qCAAqC,EAAE,+BAA+B,CAAC;KACxE;CACF"}
@@ -0,0 +1,396 @@
1
+ import { unsafeCSS, LitElement, html } from "lit";
2
+ import { customElement } from "../../decorator.js";
3
+ import compentStyle from "./alert-list-details-experimental.css.js";
4
+ import { msg } from "@lit/localize";
5
+ import { property, query, state } from "lit/decorators.js";
6
+ import "../icon-button/icon-button.js";
7
+ import "../button/button.js";
8
+ import "../../icons/icon-silence-iec.js";
9
+ import "../../icons/icon-alerts.js";
10
+ import "../../icons/icon-alerts-shelf.js";
11
+ import "../../icons/icon-alerts-active.js";
12
+ import "../../icons/icon-alarm-rectified-iec.js";
13
+ import "../../icons/icon-unacknowledged.js";
14
+ import "../../icons/icon-alarm-noack-iec.js";
15
+ import "../../icons/icon-warning-noack-iec.js";
16
+ import "../alert-icon/alert-icon.js";
17
+ import { isAcknowledged, isActive, comparePriorityAlerts, isShelved, isBlocked } from "../../types.js";
18
+ import { requiresAcknowledgement, usesAlarmNoAckIcon, excludedFromUnackedFilter } from "../../alert-severity.js";
19
+ import { ObcTableCellType } from "../table/table.js";
20
+ import "../scrollbar/scrollbar.js";
21
+ var __defProp = Object.defineProperty;
22
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
23
+ var __decorateClass = (decorators, target, key, kind) => {
24
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
25
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
26
+ if (decorator = decorators[i])
27
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
28
+ if (kind && result) __defProp(target, key, result);
29
+ return result;
30
+ };
31
+ var AlertListMode = /* @__PURE__ */ ((AlertListMode2) => {
32
+ AlertListMode2["UNACKED"] = "unacked";
33
+ AlertListMode2["ALL"] = "all";
34
+ AlertListMode2["SHELVED"] = "shelved";
35
+ AlertListMode2["BLOCKED"] = "blocked";
36
+ AlertListMode2["RECTIFIED"] = "rectified";
37
+ return AlertListMode2;
38
+ })(AlertListMode || {});
39
+ function getAlertListModeData(selectedMode) {
40
+ if (selectedMode === "all")
41
+ return {
42
+ name: "all",
43
+ title: msg("All"),
44
+ emptyTitle: msg("No active alerts"),
45
+ emptyIcon: html`<obi-alerts></obi-alerts>`,
46
+ filter: (alert) => !isShelved(alert) && isActive(alert)
47
+ };
48
+ else if (selectedMode === "unacked")
49
+ return {
50
+ name: "unacked",
51
+ title: msg("Unacked"),
52
+ emptyTitle: msg("No unacknowledged alerts"),
53
+ emptyIcon: html`<obi-unacknowledged></obi-unacknowledged>`,
54
+ filter: (alert) => !isAcknowledged(alert) && isActive(alert) && !excludedFromUnackedFilter(alert.type) && !isShelved(alert)
55
+ };
56
+ else if (selectedMode === "shelved")
57
+ return {
58
+ name: "shelved",
59
+ title: msg("Shelved"),
60
+ emptyTitle: msg("No shelved alerts"),
61
+ emptyIcon: html`<obi-alerts-shelf></obi-alerts-shelf>`,
62
+ filter: (alert) => isShelved(alert)
63
+ };
64
+ else if (selectedMode === "blocked")
65
+ return {
66
+ name: "blocked",
67
+ title: msg("Blocked"),
68
+ emptyTitle: msg("No blocked alerts"),
69
+ emptyIcon: html`<obi-alerts-active></obi-alerts-active>`,
70
+ filter: (alert) => isBlocked(alert)
71
+ };
72
+ else if (selectedMode === "rectified")
73
+ return {
74
+ name: "rectified",
75
+ title: msg("Rectified"),
76
+ emptyTitle: msg("No rectified alerts"),
77
+ emptyIcon: html`<obi-alarm-rectified-iec></obi-alarm-rectified-iec>`,
78
+ filter: (alert) => !isActive(alert)
79
+ };
80
+ else throw new Error("Invalid selected mode");
81
+ }
82
+ function canAckFilter(filter) {
83
+ return (alert) => !isAcknowledged(alert) && !alert.noAck && !excludedFromUnackedFilter(alert.type) && filter(alert);
84
+ }
85
+ let ObcAlertListDetailsExperimental = class extends LitElement {
86
+ constructor() {
87
+ super(...arguments);
88
+ this.selectedMode = "all";
89
+ this.alerts = [];
90
+ this.showTime = false;
91
+ this.timeFormatter = (time) => time.toLocaleTimeString(void 0, { hour12: false });
92
+ this.small = false;
93
+ this.defaultExpanded = true;
94
+ this.expansionOverrides = /* @__PURE__ */ new Map();
95
+ this.alertByRowId = /* @__PURE__ */ new Map();
96
+ }
97
+ getVisibleAlerts() {
98
+ const seen = /* @__PURE__ */ new Set();
99
+ return this.alertList.getAllVisibleRows().map((rowId) => this.alertByRowId.get(rowId)).filter((alert) => alert !== void 0).filter((alert) => {
100
+ if (seen.has(alert.id)) {
101
+ return false;
102
+ }
103
+ seen.add(alert.id);
104
+ return true;
105
+ });
106
+ }
107
+ onRowClick(e) {
108
+ const row = this.alertByRowId.get(e.detail.row.id);
109
+ if (row) {
110
+ this.dispatchEvent(
111
+ new CustomEvent("row-click", { detail: { alert: row } })
112
+ );
113
+ }
114
+ }
115
+ onCellButtonClick(e) {
116
+ const row = this.alertByRowId.get(e.detail.rowId);
117
+ if (row) {
118
+ this.dispatchEvent(
119
+ new CustomEvent("ack-click", {
120
+ detail: { alert: row },
121
+ bubbles: false
122
+ })
123
+ );
124
+ }
125
+ }
126
+ onExpandToggle(e) {
127
+ const overrides = new Map(this.expansionOverrides);
128
+ overrides.set(e.detail.rowId, e.detail.expanded);
129
+ this.expansionOverrides = overrides;
130
+ }
131
+ isExpanded(rowId) {
132
+ return this.expansionOverrides.get(rowId) ?? this.defaultExpanded;
133
+ }
134
+ get columns() {
135
+ if (this.small) {
136
+ const columns = [
137
+ {
138
+ label: "Status",
139
+ key: "status",
140
+ sortDirection: "desc",
141
+ sortable: true,
142
+ compareFunction: (_a, _b, aRow, bRow) => {
143
+ const aAlert = this.alertByRowId.get(aRow.id);
144
+ const bAlert = this.alertByRowId.get(bRow.id);
145
+ if (aAlert && bAlert) {
146
+ return comparePriorityAlerts(aAlert, bAlert);
147
+ }
148
+ return 0;
149
+ }
150
+ }
151
+ ];
152
+ if (this.showTime) {
153
+ columns.push({
154
+ label: "Activated",
155
+ key: "time"
156
+ });
157
+ }
158
+ columns.push({
159
+ label: "ACK-status",
160
+ key: "action"
161
+ });
162
+ return columns;
163
+ } else {
164
+ const columns = [
165
+ {
166
+ label: "Status",
167
+ key: "status",
168
+ sortDirection: "desc",
169
+ sortable: true,
170
+ compareFunction: (_a, _b, aRow, bRow) => {
171
+ const aAlert = this.alertByRowId.get(aRow.id);
172
+ const bAlert = this.alertByRowId.get(bRow.id);
173
+ if (aAlert && bAlert) {
174
+ return comparePriorityAlerts(aAlert, bAlert);
175
+ }
176
+ return 0;
177
+ }
178
+ },
179
+ {
180
+ label: "ACK-status",
181
+ key: "action",
182
+ dividerRight: true
183
+ }
184
+ ];
185
+ if (this.showTime) {
186
+ columns.push({
187
+ label: "Activated",
188
+ key: "time",
189
+ sortable: true,
190
+ compareFunction: (_a, _b, aRow, bRow) => {
191
+ const aAlert = this.alertByRowId.get(aRow.id);
192
+ const bAlert = this.alertByRowId.get(bRow.id);
193
+ if (aAlert && bAlert) {
194
+ const aTime = new Date(aAlert.time);
195
+ const bTime = new Date(bAlert.time);
196
+ return aTime.getTime() - bTime.getTime();
197
+ }
198
+ return 0;
199
+ }
200
+ });
201
+ }
202
+ columns.push({
203
+ label: "Tag ID",
204
+ key: "tagId",
205
+ sortable: true,
206
+ compareFunction: (a, b) => {
207
+ const aText = a?.type === ObcTableCellType.Regular ? String(a.text ?? "") : "";
208
+ const bText = b?.type === ObcTableCellType.Regular ? String(b.text ?? "") : "";
209
+ return aText.localeCompare(bText);
210
+ }
211
+ });
212
+ return columns;
213
+ }
214
+ }
215
+ get metadata() {
216
+ return getAlertListModeData(this.selectedMode);
217
+ }
218
+ get filteredAlerts() {
219
+ return this.alerts.filter(this.metadata.filter);
220
+ }
221
+ buildVisibleRows() {
222
+ const alerts = this.filteredAlerts;
223
+ const alertIds = new Set(alerts.map((alert) => alert.id));
224
+ const membersByGroupId = /* @__PURE__ */ new Map();
225
+ const roots = [];
226
+ for (const alert of alerts) {
227
+ const groupIds = (alert.memberOf ?? []).filter(
228
+ (groupId) => groupId !== alert.id && alertIds.has(groupId)
229
+ );
230
+ if (groupIds.length === 0) {
231
+ roots.push(alert);
232
+ continue;
233
+ }
234
+ for (const groupId of groupIds) {
235
+ const members = membersByGroupId.get(groupId) ?? [];
236
+ members.push(alert);
237
+ membersByGroupId.set(groupId, members);
238
+ }
239
+ }
240
+ const reachable = /* @__PURE__ */ new Set();
241
+ const markReachable = (alert) => {
242
+ if (reachable.has(alert.id)) {
243
+ return;
244
+ }
245
+ reachable.add(alert.id);
246
+ for (const member of membersByGroupId.get(alert.id) ?? []) {
247
+ markReachable(member);
248
+ }
249
+ };
250
+ roots.forEach(markReachable);
251
+ for (const alert of alerts) {
252
+ if (!reachable.has(alert.id)) {
253
+ roots.push(alert);
254
+ markReachable(alert);
255
+ }
256
+ }
257
+ const rows = [];
258
+ this.alertByRowId = /* @__PURE__ */ new Map();
259
+ const visit = (alert, level, parentRowId, ancestors) => {
260
+ const segment = encodeURIComponent(alert.id);
261
+ const rowId = parentRowId === void 0 ? segment : `${parentRowId}/${segment}`;
262
+ const members = membersByGroupId.get(alert.id) ?? [];
263
+ const expandableMembers = members.filter(
264
+ (member) => !ancestors.has(member.id)
265
+ );
266
+ const expanded = this.isExpanded(rowId);
267
+ this.alertByRowId.set(rowId, alert);
268
+ rows.push({
269
+ ...this.buildRowCells(alert),
270
+ id: rowId,
271
+ parentId: parentRowId,
272
+ level,
273
+ expandable: expandableMembers.length > 0,
274
+ expanded
275
+ });
276
+ if (!expanded) {
277
+ return;
278
+ }
279
+ const nextAncestors = new Set(ancestors).add(alert.id);
280
+ for (const member of expandableMembers) {
281
+ visit(member, level + 1, rowId, nextAncestors);
282
+ }
283
+ };
284
+ for (const alert of roots) {
285
+ visit(alert, 0, void 0, /* @__PURE__ */ new Set());
286
+ }
287
+ return rows;
288
+ }
289
+ buildRowCells(alert) {
290
+ let action = {
291
+ type: ObcTableCellType.Regular
292
+ };
293
+ if (!isAcknowledged(alert) && isActive(alert) && requiresAcknowledgement(alert.type)) {
294
+ if (alert.noAck) {
295
+ const icon = usesAlarmNoAckIcon(alert.type) ? html`<obi-alarm-noack-iec usecsscolor></obi-alarm-noack-iec>` : html`<obi-warning-noack-iec usecsscolor></obi-warning-noack-iec>`;
296
+ action = {
297
+ type: ObcTableCellType.Regular,
298
+ largeIcon: true,
299
+ icon,
300
+ align: "center"
301
+ };
302
+ } else {
303
+ action = {
304
+ type: ObcTableCellType.Button,
305
+ text: msg("ACK")
306
+ };
307
+ }
308
+ }
309
+ const status = {
310
+ type: ObcTableCellType.Regular,
311
+ largeIcon: true,
312
+ text: alert.text,
313
+ title: alert.source,
314
+ noWrap: true,
315
+ icon: html`<obc-alert-icon
316
+ .type=${alert.type}
317
+ .acknowledged=${isAcknowledged(alert)}
318
+ .active=${isActive(alert)}
319
+ ></obc-alert-icon>`
320
+ };
321
+ const time = this.showTime ? {
322
+ type: ObcTableCellType.Regular,
323
+ text: this.timeFormatter(alert.time),
324
+ align: "center",
325
+ neutral: true
326
+ } : void 0;
327
+ const tagId = this.small ? void 0 : {
328
+ type: ObcTableCellType.Regular,
329
+ text: "#" + alert.id,
330
+ align: "right"
331
+ };
332
+ return {
333
+ status,
334
+ time,
335
+ action,
336
+ tagId
337
+ };
338
+ }
339
+ render() {
340
+ const selectedList = this.metadata;
341
+ const data = this.buildVisibleRows();
342
+ return html`
343
+ <div class="wrapper ${this.small ? "small" : ""}">
344
+ ${data.length > 0 ? html` <obc-table
345
+ class="alert-list"
346
+ .data=${data}
347
+ .columns=${this.columns}
348
+ .striped=${true}
349
+ .showHeader=${!this.small}
350
+ @row-click=${this.onRowClick}
351
+ @cell-button-click=${this.onCellButtonClick}
352
+ @expand-toggle=${this.onExpandToggle}
353
+ ></obc-table>
354
+ <div class="spacer"></div>` : html` <div class="empty-list">
355
+ <div class="icon">${selectedList.emptyIcon}</div>
356
+ <div class="empty-title">${selectedList.emptyTitle}</div>
357
+ </div>`}
358
+ </div>
359
+ `;
360
+ }
361
+ };
362
+ ObcAlertListDetailsExperimental.styles = unsafeCSS(compentStyle);
363
+ __decorateClass([
364
+ property({ type: String })
365
+ ], ObcAlertListDetailsExperimental.prototype, "selectedMode", 2);
366
+ __decorateClass([
367
+ property({ type: Array })
368
+ ], ObcAlertListDetailsExperimental.prototype, "alerts", 2);
369
+ __decorateClass([
370
+ property({ type: Boolean })
371
+ ], ObcAlertListDetailsExperimental.prototype, "showTime", 2);
372
+ __decorateClass([
373
+ property({ attribute: false })
374
+ ], ObcAlertListDetailsExperimental.prototype, "timeFormatter", 2);
375
+ __decorateClass([
376
+ property({ type: Boolean })
377
+ ], ObcAlertListDetailsExperimental.prototype, "small", 2);
378
+ __decorateClass([
379
+ property({ type: Boolean, attribute: false })
380
+ ], ObcAlertListDetailsExperimental.prototype, "defaultExpanded", 2);
381
+ __decorateClass([
382
+ query("obc-table")
383
+ ], ObcAlertListDetailsExperimental.prototype, "alertList", 2);
384
+ __decorateClass([
385
+ state()
386
+ ], ObcAlertListDetailsExperimental.prototype, "expansionOverrides", 2);
387
+ ObcAlertListDetailsExperimental = __decorateClass([
388
+ customElement("obc-alert-list-details-experimental")
389
+ ], ObcAlertListDetailsExperimental);
390
+ export {
391
+ AlertListMode,
392
+ ObcAlertListDetailsExperimental,
393
+ canAckFilter,
394
+ getAlertListModeData
395
+ };
396
+ //# sourceMappingURL=alert-list-details-experimental.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alert-list-details-experimental.js","sources":["../../../src/components/alert-list-details-experimental/alert-list-details-experimental.ts"],"sourcesContent":["import {LitElement, html, unsafeCSS} from 'lit';\nimport {customElement} from '../../decorator.js';\nimport compentStyle from './alert-list-details-experimental.css?inline';\nimport {msg} from '@lit/localize';\nimport {property, query, state} from 'lit/decorators.js';\nimport '../icon-button/icon-button.js';\nimport '../button/button.js';\nimport '../../icons/icon-silence-iec.js';\nimport '../../icons/icon-alerts.js';\nimport '../../icons/icon-alerts-shelf.js';\nimport '../../icons/icon-alerts-active.js';\nimport '../../icons/icon-alarm-rectified-iec.js';\nimport '../../icons/icon-unacknowledged.js';\nimport '../../icons/icon-alarm-noack-iec.js';\nimport '../../icons/icon-warning-noack-iec.js';\nimport '../alert-icon/alert-icon.js';\nimport {\n Alert,\n comparePriorityAlerts,\n isActive,\n isAcknowledged,\n isBlocked,\n isShelved,\n} from '../../types.js';\nimport {\n excludedFromUnackedFilter,\n requiresAcknowledgement,\n usesAlarmNoAckIcon,\n} from '../../alert-severity.js';\nimport {\n ObcTable,\n ObcTableCellClickEvent,\n ObcTableCellData,\n ObcTableCellType,\n ObcTableExpandToggleEvent,\n ObcTableRowClickEvent,\n ObcTableRow,\n ObcTableColumn,\n} from '../table/table.js';\nimport '../scrollbar/scrollbar.js';\n\nexport enum AlertListMode {\n UNACKED = 'unacked',\n ALL = 'all',\n SHELVED = 'shelved',\n BLOCKED = 'blocked',\n RECTIFIED = 'rectified',\n}\n\nexport type ObcAckClickEvent = CustomEvent<{\n alert: Alert;\n}>;\n\nexport type ObcRowClickEvent = CustomEvent<{\n alert: Alert;\n}>;\n\nexport function getAlertListModeData(selectedMode: AlertListMode) {\n if (selectedMode === AlertListMode.ALL)\n return {\n name: AlertListMode.ALL,\n title: msg('All'),\n emptyTitle: msg('No active alerts'),\n emptyIcon: html`<obi-alerts></obi-alerts>`,\n filter: (alert: Alert) => !isShelved(alert) && isActive(alert),\n };\n else if (selectedMode === AlertListMode.UNACKED)\n return {\n name: AlertListMode.UNACKED,\n title: msg('Unacked'),\n emptyTitle: msg('No unacknowledged alerts'),\n emptyIcon: html`<obi-unacknowledged></obi-unacknowledged>`,\n filter: (alert: Alert) =>\n !isAcknowledged(alert) &&\n isActive(alert) &&\n !excludedFromUnackedFilter(alert.type) &&\n !isShelved(alert),\n };\n else if (selectedMode === AlertListMode.SHELVED)\n return {\n name: AlertListMode.SHELVED,\n title: msg('Shelved'),\n emptyTitle: msg('No shelved alerts'),\n emptyIcon: html`<obi-alerts-shelf></obi-alerts-shelf>`,\n filter: (alert: Alert) => isShelved(alert),\n };\n else if (selectedMode === AlertListMode.BLOCKED)\n return {\n name: AlertListMode.BLOCKED,\n title: msg('Blocked'),\n emptyTitle: msg('No blocked alerts'),\n emptyIcon: html`<obi-alerts-active></obi-alerts-active>`,\n filter: (alert: Alert) => isBlocked(alert),\n };\n else if (selectedMode === AlertListMode.RECTIFIED)\n return {\n name: AlertListMode.RECTIFIED,\n title: msg('Rectified'),\n emptyTitle: msg('No rectified alerts'),\n emptyIcon: html`<obi-alarm-rectified-iec></obi-alarm-rectified-iec>`,\n filter: (alert: Alert) => !isActive(alert),\n };\n else throw new Error('Invalid selected mode');\n}\n\nexport function canAckFilter(filter: (alert: Alert) => boolean) {\n return (alert: Alert) =>\n !isAcknowledged(alert) &&\n !alert.noAck &&\n !excludedFromUnackedFilter(alert.type) &&\n filter(alert);\n}\n\n/**\n * @availableWhen timeFormatter showTime==true\n * @property defaultExpanded - Whether groups start expanded. Set false to open the list collapsed.\n * @fires {ObcAckClickEvent} ack-click - Fired when the user clicks the \"ACK\" button.\n * @fires {ObcRowClickEvent} row-click - Fired when the user clicks a row.\n * @experimental\n */\n@customElement('obc-alert-list-details-experimental')\nexport class ObcAlertListDetailsExperimental extends LitElement {\n @property({type: String}) selectedMode: AlertListMode = AlertListMode.ALL;\n @property({type: Array}) alerts: Alert[] = [];\n @property({type: Boolean}) showTime: boolean = false;\n @property({attribute: false}) timeFormatter: (time: Date) => string = (\n time: Date\n ) => time.toLocaleTimeString(undefined, {hour12: false});\n @property({type: Boolean}) small: boolean = false;\n @property({type: Boolean, attribute: false}) defaultExpanded: boolean = true;\n\n @query('obc-table')\n private alertList!: ObcTable;\n\n @state() private expansionOverrides = new Map<string, boolean>();\n\n private alertByRowId = new Map<string, Alert>();\n\n public getVisibleAlerts(): Alert[] {\n const seen = new Set<string>();\n return this.alertList\n .getAllVisibleRows()\n .map((rowId) => this.alertByRowId.get(rowId))\n .filter((alert): alert is Alert => alert !== undefined)\n .filter((alert) => {\n if (seen.has(alert.id)) {\n return false;\n }\n seen.add(alert.id);\n return true;\n });\n }\n\n private onRowClick(e: ObcTableRowClickEvent) {\n const row = this.alertByRowId.get(e.detail.row.id);\n if (row) {\n this.dispatchEvent(\n new CustomEvent('row-click', {detail: {alert: row}}) as ObcRowClickEvent\n );\n }\n }\n\n private onCellButtonClick(e: ObcTableCellClickEvent) {\n const row = this.alertByRowId.get(e.detail.rowId);\n if (row) {\n this.dispatchEvent(\n new CustomEvent('ack-click', {\n detail: {alert: row},\n bubbles: false,\n }) as ObcAckClickEvent\n );\n }\n }\n\n private onExpandToggle(e: ObcTableExpandToggleEvent) {\n const overrides = new Map(this.expansionOverrides);\n overrides.set(e.detail.rowId, e.detail.expanded);\n this.expansionOverrides = overrides;\n }\n\n private isExpanded(rowId: string) {\n return this.expansionOverrides.get(rowId) ?? this.defaultExpanded;\n }\n\n private get columns() {\n if (this.small) {\n const columns: ObcTableColumn<ObcTableCellData, ObcTableRow>[] = [\n {\n label: 'Status',\n key: 'status',\n sortDirection: 'desc',\n sortable: true,\n compareFunction: (_a, _b, aRow, bRow) => {\n const aAlert = this.alertByRowId.get(aRow.id);\n const bAlert = this.alertByRowId.get(bRow.id);\n if (aAlert && bAlert) {\n return comparePriorityAlerts(aAlert, bAlert);\n }\n return 0;\n },\n },\n ];\n if (this.showTime) {\n columns.push({\n label: 'Activated',\n key: 'time',\n });\n }\n columns.push({\n label: 'ACK-status',\n key: 'action',\n });\n return columns;\n } else {\n const columns: ObcTableColumn<ObcTableCellData, ObcTableRow>[] = [\n {\n label: 'Status',\n key: 'status',\n sortDirection: 'desc',\n sortable: true,\n compareFunction: (_a, _b, aRow, bRow) => {\n const aAlert = this.alertByRowId.get(aRow.id);\n const bAlert = this.alertByRowId.get(bRow.id);\n if (aAlert && bAlert) {\n return comparePriorityAlerts(aAlert, bAlert);\n }\n return 0;\n },\n },\n {\n label: 'ACK-status',\n key: 'action',\n dividerRight: true,\n },\n ];\n if (this.showTime) {\n columns.push({\n label: 'Activated',\n key: 'time',\n sortable: true,\n compareFunction: (_a, _b, aRow, bRow) => {\n const aAlert = this.alertByRowId.get(aRow.id);\n const bAlert = this.alertByRowId.get(bRow.id);\n if (aAlert && bAlert) {\n const aTime = new Date(aAlert.time);\n const bTime = new Date(bAlert.time);\n return aTime.getTime() - bTime.getTime();\n }\n return 0;\n },\n });\n }\n columns.push({\n label: 'Tag ID',\n key: 'tagId',\n sortable: true,\n compareFunction: (a, b) => {\n const aText =\n a?.type === ObcTableCellType.Regular ? String(a.text ?? '') : '';\n const bText =\n b?.type === ObcTableCellType.Regular ? String(b.text ?? '') : '';\n return aText.localeCompare(bText);\n },\n });\n return columns;\n }\n }\n\n private get metadata() {\n return getAlertListModeData(this.selectedMode);\n }\n\n private get filteredAlerts() {\n return this.alerts.filter(this.metadata.filter);\n }\n\n private buildVisibleRows(): ObcTableRow[] {\n const alerts = this.filteredAlerts;\n const alertIds = new Set(alerts.map((alert) => alert.id));\n const membersByGroupId = new Map<string, Alert[]>();\n const roots: Alert[] = [];\n for (const alert of alerts) {\n const groupIds = (alert.memberOf ?? []).filter(\n (groupId) => groupId !== alert.id && alertIds.has(groupId)\n );\n if (groupIds.length === 0) {\n roots.push(alert);\n continue;\n }\n for (const groupId of groupIds) {\n const members = membersByGroupId.get(groupId) ?? [];\n members.push(alert);\n membersByGroupId.set(groupId, members);\n }\n }\n\n const reachable = new Set<string>();\n const markReachable = (alert: Alert) => {\n if (reachable.has(alert.id)) {\n return;\n }\n reachable.add(alert.id);\n for (const member of membersByGroupId.get(alert.id) ?? []) {\n markReachable(member);\n }\n };\n roots.forEach(markReachable);\n for (const alert of alerts) {\n if (!reachable.has(alert.id)) {\n roots.push(alert);\n markReachable(alert);\n }\n }\n\n const rows: ObcTableRow[] = [];\n this.alertByRowId = new Map();\n const visit = (\n alert: Alert,\n level: number,\n parentRowId: string | undefined,\n ancestors: Set<string>\n ) => {\n const segment = encodeURIComponent(alert.id);\n const rowId =\n parentRowId === undefined ? segment : `${parentRowId}/${segment}`;\n const members = membersByGroupId.get(alert.id) ?? [];\n // A member can name a group that is also its own descendant.\n const expandableMembers = members.filter(\n (member) => !ancestors.has(member.id)\n );\n const expanded = this.isExpanded(rowId);\n\n this.alertByRowId.set(rowId, alert);\n rows.push({\n ...this.buildRowCells(alert),\n id: rowId,\n parentId: parentRowId,\n level,\n expandable: expandableMembers.length > 0,\n expanded,\n });\n\n if (!expanded) {\n return;\n }\n const nextAncestors = new Set(ancestors).add(alert.id);\n for (const member of expandableMembers) {\n visit(member, level + 1, rowId, nextAncestors);\n }\n };\n\n for (const alert of roots) {\n visit(alert, 0, undefined, new Set());\n }\n return rows;\n }\n\n private buildRowCells(\n alert: Alert\n ): Record<string, ObcTableCellData | undefined> {\n let action: ObcTableCellData = {\n type: ObcTableCellType.Regular,\n };\n if (\n !isAcknowledged(alert) &&\n isActive(alert) &&\n requiresAcknowledgement(alert.type)\n ) {\n if (alert.noAck) {\n const icon = usesAlarmNoAckIcon(alert.type)\n ? html`<obi-alarm-noack-iec usecsscolor></obi-alarm-noack-iec>`\n : html`<obi-warning-noack-iec usecsscolor></obi-warning-noack-iec>`;\n action = {\n type: ObcTableCellType.Regular,\n largeIcon: true,\n icon,\n align: 'center',\n };\n } else {\n action = {\n type: ObcTableCellType.Button,\n text: msg('ACK'),\n };\n }\n }\n\n const status: ObcTableCellData = {\n type: ObcTableCellType.Regular,\n largeIcon: true,\n text: alert.text,\n title: alert.source,\n noWrap: true,\n icon: html`<obc-alert-icon\n .type=${alert.type}\n .acknowledged=${isAcknowledged(alert)}\n .active=${isActive(alert)}\n ></obc-alert-icon>`,\n };\n\n const time: ObcTableCellData | undefined = this.showTime\n ? {\n type: ObcTableCellType.Regular,\n text: this.timeFormatter(alert.time),\n align: 'center',\n neutral: true,\n }\n : undefined;\n\n const tagId: ObcTableCellData | undefined = this.small\n ? undefined\n : {\n type: ObcTableCellType.Regular,\n text: '#' + alert.id,\n align: 'right',\n };\n return {\n status,\n time,\n action,\n tagId,\n };\n }\n\n override render() {\n const selectedList = this.metadata;\n const data = this.buildVisibleRows();\n\n return html`\n <div class=\"wrapper ${this.small ? 'small' : ''}\">\n ${data.length > 0\n ? html` <obc-table\n class=\"alert-list\"\n .data=${data}\n .columns=${this.columns}\n .striped=${true}\n .showHeader=${!this.small}\n @row-click=${this.onRowClick}\n @cell-button-click=${this.onCellButtonClick}\n @expand-toggle=${this.onExpandToggle}\n ></obc-table>\n <div class=\"spacer\"></div>`\n : html` <div class=\"empty-list\">\n <div class=\"icon\">${selectedList.emptyIcon}</div>\n <div class=\"empty-title\">${selectedList.emptyTitle}</div>\n </div>`}\n </div>\n `;\n }\n\n static override styles = unsafeCSS(compentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-alert-list-details-experimental': ObcAlertListDetailsExperimental;\n }\n}\n"],"names":["AlertListMode"],"mappings":"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"}
@@ -424,6 +424,49 @@ const compentStyle = css`* {
424
424
  flex-shrink: 0;
425
425
  }
426
426
 
427
+ /* ---- Hierarchy ---- */
428
+
429
+ /*
430
+ * Indent gutter for a hierarchical row. One step per level plus one for
431
+ * the chevron itself, so a leaf and a group at the same level align.
432
+ */
433
+
434
+ :is(:is(.grid-container .grid-row) .grid-cell) .row-expander {
435
+ --row-indent-step: var(
436
+ --menu-navigation-components-table-item-icon-size
437
+ );
438
+ /* Depth of this row; the row's inline style overrides it. */
439
+ --row-level: 0;
440
+ display: flex;
441
+ align-items: center;
442
+ justify-content: flex-end;
443
+ flex-shrink: 0;
444
+ align-self: stretch;
445
+ width: calc((var(--row-level) + 1) * var(--row-indent-step));
446
+ }
447
+
448
+ :is(:is(.grid-container .grid-row) .grid-cell) .row-expander .chevron {
449
+ display: flex;
450
+ align-items: center;
451
+ justify-content: center;
452
+ /* Pointer target floor, and the gutter is only one step wide. */
453
+ min-width: var(--row-indent-step);
454
+ min-height: var(--row-indent-step);
455
+ align-self: stretch;
456
+ color: var(--on-flat-neutral-color);
457
+ transition: transform 100ms ease-in-out;
458
+ }
459
+
460
+ :is(:is(.grid-container .grid-row) .grid-cell) .row-expander .chevron.expanded {
461
+ transform: rotate(90deg);
462
+ }
463
+
464
+ @media (prefers-reduced-motion: reduce) {
465
+ :is(:is(.grid-container .grid-row) .grid-cell) .row-expander .chevron {
466
+ transition: none;
467
+ }
468
+ }
469
+
427
470
  .large-icon:is(:is(.grid-container .grid-row) .grid-cell) .icon {
428
471
  min-width: var(--menu-navigation-components-table-item-icon-size-large);
429
472
  min-height: var(
@@ -1 +1 @@
1
- {"version":3,"file":"table.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"table.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -5,6 +5,7 @@ import { TagColor } from '../tag/tag.js';
5
5
  import { ExternalScaleSide, FillMode, FrameStyle, InstrumentState, Priority, ScaleType } from '../../building-blocks/bar-horizontal/bar-horizontal.js';
6
6
  import '../table-header-item/table-header-item.js';
7
7
  import '../button/button.js';
8
+ import '../../icons/icon-chevron-right-google.js';
8
9
  import '../../building-blocks/bar-horizontal/bar-horizontal.js';
9
10
  export declare enum ObcTableCellType {
10
11
  Regular = "regular",
@@ -95,7 +96,11 @@ export type ObcTableCellData = ObcTableCellDataRegular | ObcTableCellDataButton
95
96
  export interface ObcTableRow {
96
97
  selected?: boolean;
97
98
  id: string;
98
- [key: string]: ObcTableCellData | boolean | undefined | string;
99
+ parentId?: string;
100
+ level?: number;
101
+ expandable?: boolean;
102
+ expanded?: boolean;
103
+ [key: string]: ObcTableCellData | boolean | undefined | string | number;
99
104
  }
100
105
  export interface ObcTableColumnUnsortable<T extends ObcTableCellData, S extends ObcTableRow> {
101
106
  label: string;
@@ -134,6 +139,10 @@ export type ObcTableSelectionChangeEvent = CustomEvent<{
134
139
  export type ObcTableRowClickEvent = CustomEvent<{
135
140
  row: ObcTableRow;
136
141
  }>;
142
+ export type ObcTableExpandToggleEvent = CustomEvent<{
143
+ rowId: string;
144
+ expanded: boolean;
145
+ }>;
137
146
  /**
138
147
  * `<obc-table>` renders tabular data with configurable columns and cell types.
139
148
  *
@@ -146,11 +155,17 @@ export type ObcTableRowClickEvent = CustomEvent<{
146
155
  * - Cell rendering variants: `checkbox`, `tag`, `horizontal-bar`, and `button` cell types.
147
156
  * - Visual variants: `rowDivider`, `striped`, `narrowHeader`, and `showHeader`.
148
157
  * - Sorting support for sortable columns via column definitions.
158
+ * - Hierarchical rows via `parentId`, `level`, `expandable` and `expanded`.
149
159
  *
150
160
  * Usage Guidelines
151
161
  * - Controlled selection: pass `selectedRowIds` and update it on `selection-change`.
152
162
  * - Uncontrolled selection: pass `defaultSelectedRowIds` and listen to `selection-change`.
153
163
  * - Use `selectAllAriaLabel` to customize the header checkbox accessibility label.
164
+ * - Hierarchy is controlled, and flat: pass only the rows that are currently
165
+ * visible, each with the `parentId` of its parent row, and drop a collapsed
166
+ * group's descendants from `data` on `expand-toggle`. The table draws the
167
+ * indent and the chevron, keeps each sibling set sorted within its parent,
168
+ * and owns no expansion state of its own.
154
169
  *
155
170
  * Slots/Content
156
171
  * - This component does not expose public slots. Provide content via `data` and `columns`.
@@ -161,6 +176,15 @@ export type ObcTableRowClickEvent = CustomEvent<{
161
176
  * - `cell-checkbox-change` fires when a checkbox cell changes.
162
177
  * - `cell-tag-click` fires when a tag inside a cell is clicked.
163
178
  * - `selection-change` fires when row selection changes (source: `row` or `header`).
179
+ * - `expand-toggle` fires when a group row's chevron or expand key is used.
180
+ *
181
+ * Accessibility
182
+ * A table with hierarchical rows renders as a
183
+ * [treegrid](https://www.w3.org/WAI/ARIA/apg/patterns/treegrid/): rows carry
184
+ * `aria-level`, and group rows `aria-expanded`. Right expands a collapsed
185
+ * group, Left collapses an expanded one or moves to the parent row. Cell-level
186
+ * arrow navigation, which the full pattern also specifies, is out of scope —
187
+ * arrow keys move between rows, matching the flat table.
164
188
  *
165
189
  * Best Practices
166
190
  * - Keep column `key` values stable across renders to avoid selection or sorting resets.
@@ -187,6 +211,7 @@ export type ObcTableRowClickEvent = CustomEvent<{
187
211
  * @fires {ObcTableCellCheckboxChangeEvent} cell-checkbox-change - Fired when a cell checkbox is changed.
188
212
  * @fires {ObcTableCellTagClickEvent} cell-tag-click - Fired when a tag inside a cell is clicked.
189
213
  * @fires {ObcTableSelectionChangeEvent} selection-change - Fired when row selection changes.
214
+ * @fires {ObcTableExpandToggleEvent} expand-toggle - Fired when a group row is expanded or collapsed.
190
215
  * @beta
191
216
  */
192
217
  export declare class ObcTable extends LitElement {
@@ -204,14 +229,19 @@ export declare class ObcTable extends LitElement {
204
229
  private _sortDirection;
205
230
  private _selectedRowIds;
206
231
  private _previousPositions;
232
+ private get hasHierarchy();
233
+ private sortWithinSiblings;
207
234
  get sortedData(): ObcTableRow[];
208
235
  private _handleSortClick;
209
236
  private _handleRowClick;
237
+ private _handleExpandToggle;
238
+ private _renderRowExpander;
210
239
  private _focusFirstRow;
211
240
  private _focusLeftHeaderItem;
212
241
  private _focusHeaderByIndex;
213
242
  private _handleHeaderKeyDown;
214
243
  private _handleRowKeyDown;
244
+ private _handleRowExpandKey;
215
245
  private _getAllPositions;
216
246
  private _animateRowChanges;
217
247
  private _hasRenderedRows;