@lmfaole/basics 0.3.0 → 0.4.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/README.md +182 -33
- package/basic-styling/components/basic-accordion.css +65 -0
- package/basic-styling/components/basic-alert.css +27 -0
- package/basic-styling/components/basic-dialog.css +41 -0
- package/basic-styling/components/basic-popover.css +54 -0
- package/basic-styling/components/basic-summary-table.css +76 -0
- package/basic-styling/components/basic-table.css +48 -0
- package/basic-styling/components/basic-tabs.css +45 -0
- package/basic-styling/components/basic-toast.css +102 -0
- package/basic-styling/components/basic-toc.css +30 -0
- package/basic-styling/components.css +9 -0
- package/basic-styling/global.css +61 -0
- package/basic-styling/index.css +2 -0
- package/basic-styling/tokens/base.css +19 -0
- package/basic-styling/tokens/palette.css +117 -0
- package/basic-styling/tokens/palette.tokens.json +1019 -0
- package/components/basic-accordion/index.d.ts +5 -5
- package/components/basic-accordion/index.js +169 -165
- package/components/basic-alert/index.d.ts +53 -0
- package/components/basic-alert/index.js +189 -0
- package/components/basic-alert/register.d.ts +1 -0
- package/components/basic-alert/register.js +3 -0
- package/components/basic-summary-table/index.js +188 -42
- package/components/basic-table/index.js +203 -145
- package/components/basic-toast/index.d.ts +65 -0
- package/components/basic-toast/index.js +429 -0
- package/components/basic-toast/register.d.ts +1 -0
- package/components/basic-toast/register.js +3 -0
- package/index.d.ts +2 -0
- package/index.js +2 -0
- package/package.json +22 -57
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
const ElementBase = globalThis.Element ?? class {};
|
|
2
|
+
const HTMLElementBase = globalThis.HTMLElement ?? class {};
|
|
3
|
+
const HTMLButtonElementBase = globalThis.HTMLButtonElement ?? class {};
|
|
4
|
+
|
|
5
|
+
export const ALERT_TAG_NAME = "basic-alert";
|
|
6
|
+
|
|
7
|
+
const DEFAULT_LABEL = "Alert";
|
|
8
|
+
const DEFAULT_LIVE = "assertive";
|
|
9
|
+
const TITLE_SELECTOR = "[data-alert-title]";
|
|
10
|
+
const CLOSE_SELECTOR = "[data-alert-close]";
|
|
11
|
+
const MANAGED_LABEL_ATTRIBUTE = "data-basic-alert-managed-label";
|
|
12
|
+
const MANAGED_LABELLEDBY_ATTRIBUTE = "data-basic-alert-managed-labelledby";
|
|
13
|
+
|
|
14
|
+
let nextAlertInstanceId = 1;
|
|
15
|
+
|
|
16
|
+
function collectOwnedElements(root, scope, selector) {
|
|
17
|
+
return Array.from(scope.querySelectorAll(selector)).filter(
|
|
18
|
+
(element) => element instanceof HTMLElementBase && element.closest(ALERT_TAG_NAME) === root,
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function normalizeAlertLabel(value) {
|
|
23
|
+
return value?.trim() || DEFAULT_LABEL;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function normalizeAlertLive(value) {
|
|
27
|
+
const normalized = value?.trim().toLowerCase();
|
|
28
|
+
return normalized === "polite" ? "polite" : DEFAULT_LIVE;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function getAlertRoleForLive(value) {
|
|
32
|
+
return normalizeAlertLive(value) === "polite" ? "status" : "alert";
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function normalizeAlertOpen(value, hidden = false) {
|
|
36
|
+
if (hidden) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (value == null) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const normalized = value.trim().toLowerCase();
|
|
45
|
+
return normalized === "" || normalized === "true" || normalized === "1";
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export class AlertElement extends HTMLElementBase {
|
|
49
|
+
static observedAttributes = ["data-label", "data-live", "data-open", "hidden"];
|
|
50
|
+
|
|
51
|
+
#instanceId = `${ALERT_TAG_NAME}-${nextAlertInstanceId++}`;
|
|
52
|
+
#title = null;
|
|
53
|
+
#closeButtons = [];
|
|
54
|
+
#eventsBound = false;
|
|
55
|
+
|
|
56
|
+
connectedCallback() {
|
|
57
|
+
if (!this.#eventsBound) {
|
|
58
|
+
this.addEventListener("click", this.#handleClick);
|
|
59
|
+
this.#eventsBound = true;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
this.#sync();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
disconnectedCallback() {
|
|
66
|
+
if (!this.#eventsBound) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
this.removeEventListener("click", this.#handleClick);
|
|
71
|
+
this.#eventsBound = false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
attributeChangedCallback() {
|
|
75
|
+
this.#sync();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
show() {
|
|
79
|
+
this.hidden = false;
|
|
80
|
+
this.toggleAttribute("data-open", true);
|
|
81
|
+
this.#sync();
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
hide() {
|
|
86
|
+
this.hidden = true;
|
|
87
|
+
this.toggleAttribute("data-open", false);
|
|
88
|
+
this.#sync();
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
#handleClick = (event) => {
|
|
93
|
+
if (!(event.target instanceof ElementBase)) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const closeButton = event.target.closest(CLOSE_SELECTOR);
|
|
98
|
+
|
|
99
|
+
if (
|
|
100
|
+
closeButton instanceof HTMLElementBase
|
|
101
|
+
&& closeButton.closest(ALERT_TAG_NAME) === this
|
|
102
|
+
) {
|
|
103
|
+
event.preventDefault();
|
|
104
|
+
this.hide();
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
#sync() {
|
|
109
|
+
const nextTitle = collectOwnedElements(this, this, TITLE_SELECTOR)[0] ?? null;
|
|
110
|
+
|
|
111
|
+
this.#title = nextTitle instanceof HTMLElementBase ? nextTitle : null;
|
|
112
|
+
this.#closeButtons = collectOwnedElements(this, this, CLOSE_SELECTOR);
|
|
113
|
+
this.#applyState();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
#applyState() {
|
|
117
|
+
for (const button of this.#closeButtons) {
|
|
118
|
+
if (button instanceof HTMLButtonElementBase && !button.hasAttribute("type")) {
|
|
119
|
+
button.type = "button";
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const open = normalizeAlertOpen(this.getAttribute("data-open"), this.hidden);
|
|
124
|
+
const baseId = this.id || this.#instanceId;
|
|
125
|
+
|
|
126
|
+
if (this.#title instanceof HTMLElementBase && !this.#title.id) {
|
|
127
|
+
this.#title.id = `${baseId}-title`;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
this.hidden = !open;
|
|
131
|
+
this.toggleAttribute("data-open", open);
|
|
132
|
+
this.setAttribute("role", getAlertRoleForLive(this.getAttribute("data-live")));
|
|
133
|
+
this.setAttribute("aria-live", normalizeAlertLive(this.getAttribute("data-live")));
|
|
134
|
+
this.setAttribute("aria-atomic", "true");
|
|
135
|
+
this.#syncAccessibleLabel();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
#syncAccessibleLabel() {
|
|
139
|
+
const nextLabel = normalizeAlertLabel(this.getAttribute("data-label"));
|
|
140
|
+
const hasManagedLabel = this.hasAttribute(MANAGED_LABEL_ATTRIBUTE);
|
|
141
|
+
const hasManagedLabelledBy = this.hasAttribute(MANAGED_LABELLEDBY_ATTRIBUTE);
|
|
142
|
+
|
|
143
|
+
if (hasManagedLabel && this.getAttribute("aria-label") !== nextLabel) {
|
|
144
|
+
this.removeAttribute("aria-label");
|
|
145
|
+
this.removeAttribute(MANAGED_LABEL_ATTRIBUTE);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (this.#title?.id) {
|
|
149
|
+
if (this.hasAttribute(MANAGED_LABEL_ATTRIBUTE)) {
|
|
150
|
+
this.removeAttribute("aria-label");
|
|
151
|
+
this.removeAttribute(MANAGED_LABEL_ATTRIBUTE);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (!this.hasAttribute("aria-labelledby") || hasManagedLabelledBy) {
|
|
155
|
+
this.setAttribute("aria-labelledby", this.#title.id);
|
|
156
|
+
this.setAttribute(MANAGED_LABELLEDBY_ATTRIBUTE, "");
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (hasManagedLabelledBy) {
|
|
163
|
+
this.removeAttribute("aria-labelledby");
|
|
164
|
+
this.removeAttribute(MANAGED_LABELLEDBY_ATTRIBUTE);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const hasOwnAriaLabel = this.hasAttribute("aria-label") && !this.hasAttribute(MANAGED_LABEL_ATTRIBUTE);
|
|
168
|
+
const hasOwnLabelledBy = this.hasAttribute("aria-labelledby");
|
|
169
|
+
|
|
170
|
+
if (hasOwnAriaLabel || hasOwnLabelledBy) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
this.setAttribute("aria-label", nextLabel);
|
|
175
|
+
this.setAttribute(MANAGED_LABEL_ATTRIBUTE, "");
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export function defineAlert(registry = globalThis.customElements) {
|
|
180
|
+
if (!registry?.get || !registry?.define) {
|
|
181
|
+
return AlertElement;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (!registry.get(ALERT_TAG_NAME)) {
|
|
185
|
+
registry.define(ALERT_TAG_NAME, AlertElement);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return AlertElement;
|
|
189
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -12,6 +12,11 @@ const DEFAULT_TOTAL_LABEL = "Totalt";
|
|
|
12
12
|
const GENERATED_SUMMARY_ROW_ATTRIBUTE = "data-basic-summary-table-generated-row";
|
|
13
13
|
const GENERATED_SUMMARY_CELL_ATTRIBUTE = "data-basic-summary-table-generated-cell";
|
|
14
14
|
const GENERATED_SUMMARY_LABEL_ATTRIBUTE = "data-basic-summary-table-generated-label";
|
|
15
|
+
const SUMMARY_OBSERVER_OPTIONS = {
|
|
16
|
+
subtree: true,
|
|
17
|
+
attributes: true,
|
|
18
|
+
attributeFilter: ["data-value"],
|
|
19
|
+
};
|
|
15
20
|
|
|
16
21
|
export function normalizeSummaryColumns(value) {
|
|
17
22
|
if (!value?.trim()) {
|
|
@@ -36,8 +41,30 @@ export function normalizeSummaryLocale(value) {
|
|
|
36
41
|
return value?.trim() || undefined;
|
|
37
42
|
}
|
|
38
43
|
|
|
44
|
+
function findSummaryNumberMatch(value) {
|
|
45
|
+
const text = String(value ?? "").trim();
|
|
46
|
+
|
|
47
|
+
if (!text) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const match = text.match(/(?:-\s*)?\d(?:[\d\s.,]*\d)?/);
|
|
52
|
+
|
|
53
|
+
if (!match || typeof match.index !== "number") {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
text,
|
|
59
|
+
numberText: match[0],
|
|
60
|
+
start: match.index,
|
|
61
|
+
end: match.index + match[0].length,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
39
65
|
function getDecimalSeparator(value) {
|
|
40
|
-
const
|
|
66
|
+
const numberMatch = findSummaryNumberMatch(value);
|
|
67
|
+
const text = numberMatch?.numberText.trim() ?? String(value ?? "").trim();
|
|
41
68
|
const lastComma = text.lastIndexOf(",");
|
|
42
69
|
const lastDot = text.lastIndexOf(".");
|
|
43
70
|
|
|
@@ -59,7 +86,8 @@ function getDecimalSeparator(value) {
|
|
|
59
86
|
}
|
|
60
87
|
|
|
61
88
|
function countFractionDigits(value) {
|
|
62
|
-
const
|
|
89
|
+
const numberMatch = findSummaryNumberMatch(value);
|
|
90
|
+
const text = numberMatch?.numberText.trim() ?? String(value ?? "").trim();
|
|
63
91
|
|
|
64
92
|
if (!text) {
|
|
65
93
|
return 0;
|
|
@@ -75,7 +103,8 @@ function countFractionDigits(value) {
|
|
|
75
103
|
}
|
|
76
104
|
|
|
77
105
|
export function parseSummaryNumber(value) {
|
|
78
|
-
const
|
|
106
|
+
const numberMatch = findSummaryNumberMatch(value);
|
|
107
|
+
const text = numberMatch?.numberText.trim() ?? String(value ?? "").trim();
|
|
79
108
|
|
|
80
109
|
if (!text) {
|
|
81
110
|
return null;
|
|
@@ -107,6 +136,28 @@ export function formatSummaryNumber(value, { locale, fractionDigits = 0 } = {})
|
|
|
107
136
|
}).format(value);
|
|
108
137
|
}
|
|
109
138
|
|
|
139
|
+
function getSummaryAffixes(value) {
|
|
140
|
+
const numberMatch = findSummaryNumberMatch(value);
|
|
141
|
+
|
|
142
|
+
if (!numberMatch) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
prefix: numberMatch.text.slice(0, numberMatch.start),
|
|
148
|
+
suffix: numberMatch.text.slice(numberMatch.end),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function formatSummaryValue(value, {
|
|
153
|
+
locale,
|
|
154
|
+
fractionDigits = 0,
|
|
155
|
+
prefix = "",
|
|
156
|
+
suffix = "",
|
|
157
|
+
} = {}) {
|
|
158
|
+
return `${prefix}${formatSummaryNumber(value, { locale, fractionDigits })}${suffix}`;
|
|
159
|
+
}
|
|
160
|
+
|
|
110
161
|
function findCellAtColumnIndex(row, targetColumnIndex) {
|
|
111
162
|
let columnIndex = 0;
|
|
112
163
|
|
|
@@ -134,6 +185,10 @@ function getLogicalColumnCount(table) {
|
|
|
134
185
|
let maxColumns = 0;
|
|
135
186
|
|
|
136
187
|
for (const row of Array.from(table.rows)) {
|
|
188
|
+
if (row.hasAttribute(GENERATED_SUMMARY_ROW_ATTRIBUTE)) {
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
|
|
137
192
|
let columnCount = 0;
|
|
138
193
|
|
|
139
194
|
for (const cell of Array.from(row.cells)) {
|
|
@@ -192,6 +247,10 @@ function calculateSummaryTotals(table, summaryColumns) {
|
|
|
192
247
|
totals.set(columnIndex, {
|
|
193
248
|
total: 0,
|
|
194
249
|
fractionDigits: 0,
|
|
250
|
+
prefix: "",
|
|
251
|
+
suffix: "",
|
|
252
|
+
affixInitialized: false,
|
|
253
|
+
affixConsistent: true,
|
|
195
254
|
});
|
|
196
255
|
}
|
|
197
256
|
|
|
@@ -213,6 +272,25 @@ function calculateSummaryTotals(table, summaryColumns) {
|
|
|
213
272
|
|
|
214
273
|
current.total += parsedValue;
|
|
215
274
|
current.fractionDigits = Math.max(current.fractionDigits, countFractionDigits(rawValue));
|
|
275
|
+
|
|
276
|
+
const affixes = getSummaryAffixes(cell?.textContent ?? "");
|
|
277
|
+
|
|
278
|
+
if (!affixes) {
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (!current.affixInitialized) {
|
|
283
|
+
current.prefix = affixes.prefix;
|
|
284
|
+
current.suffix = affixes.suffix;
|
|
285
|
+
current.affixInitialized = true;
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (current.prefix !== affixes.prefix || current.suffix !== affixes.suffix) {
|
|
290
|
+
current.affixConsistent = false;
|
|
291
|
+
current.prefix = "";
|
|
292
|
+
current.suffix = "";
|
|
293
|
+
}
|
|
216
294
|
}
|
|
217
295
|
}
|
|
218
296
|
|
|
@@ -238,6 +316,31 @@ function ensureGeneratedSummaryRow(table) {
|
|
|
238
316
|
return row;
|
|
239
317
|
}
|
|
240
318
|
|
|
319
|
+
function ensureSummaryRowCell(row, columnIndex, tagName) {
|
|
320
|
+
const expectedTagName = tagName.toUpperCase();
|
|
321
|
+
const existingCell = row.cells[columnIndex] ?? null;
|
|
322
|
+
|
|
323
|
+
if (existingCell?.tagName === expectedTagName) {
|
|
324
|
+
return existingCell;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const replacement = document.createElement(tagName);
|
|
328
|
+
|
|
329
|
+
if (existingCell) {
|
|
330
|
+
row.replaceChild(replacement, existingCell);
|
|
331
|
+
return replacement;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
row.append(replacement);
|
|
335
|
+
return replacement;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function syncSummaryCellText(cell, text) {
|
|
339
|
+
if (cell.textContent !== text) {
|
|
340
|
+
cell.textContent = text;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
241
344
|
function removeGeneratedSummaryRow(table) {
|
|
242
345
|
table.querySelector(`tr[${GENERATED_SUMMARY_ROW_ATTRIBUTE}]`)?.remove();
|
|
243
346
|
}
|
|
@@ -259,34 +362,58 @@ function syncSummaryFooter(table, {
|
|
|
259
362
|
const summaryColumnSet = new Set(summaryColumns.filter((column) => column < logicalColumnCount));
|
|
260
363
|
const row = ensureGeneratedSummaryRow(table);
|
|
261
364
|
|
|
262
|
-
row.replaceChildren();
|
|
263
|
-
|
|
264
365
|
for (let columnIndex = 0; columnIndex < logicalColumnCount; columnIndex += 1) {
|
|
265
366
|
if (columnIndex === effectiveLabelColumnIndex) {
|
|
266
|
-
const labelCell =
|
|
267
|
-
|
|
268
|
-
labelCell.
|
|
367
|
+
const labelCell = ensureSummaryRowCell(row, columnIndex, "th");
|
|
368
|
+
|
|
369
|
+
if (labelCell.getAttribute("scope") !== "row") {
|
|
370
|
+
labelCell.setAttribute("scope", "row");
|
|
371
|
+
}
|
|
372
|
+
|
|
269
373
|
labelCell.setAttribute(GENERATED_SUMMARY_LABEL_ATTRIBUTE, "");
|
|
270
|
-
|
|
374
|
+
labelCell.removeAttribute(GENERATED_SUMMARY_CELL_ATTRIBUTE);
|
|
375
|
+
labelCell.removeAttribute("data-summary-total");
|
|
376
|
+
labelCell.removeAttribute("data-summary-empty");
|
|
377
|
+
delete labelCell.dataset.value;
|
|
378
|
+
syncSummaryCellText(labelCell, totalLabel);
|
|
271
379
|
continue;
|
|
272
380
|
}
|
|
273
381
|
|
|
274
|
-
const valueCell =
|
|
382
|
+
const valueCell = ensureSummaryRowCell(row, columnIndex, "td");
|
|
275
383
|
valueCell.setAttribute(GENERATED_SUMMARY_CELL_ATTRIBUTE, "");
|
|
384
|
+
valueCell.removeAttribute(GENERATED_SUMMARY_LABEL_ATTRIBUTE);
|
|
385
|
+
valueCell.removeAttribute("scope");
|
|
276
386
|
|
|
277
387
|
if (summaryColumnSet.has(columnIndex)) {
|
|
278
|
-
const summary = totals.get(columnIndex) ?? {
|
|
279
|
-
|
|
388
|
+
const summary = totals.get(columnIndex) ?? {
|
|
389
|
+
total: 0,
|
|
390
|
+
fractionDigits: 0,
|
|
391
|
+
prefix: "",
|
|
392
|
+
suffix: "",
|
|
393
|
+
affixInitialized: false,
|
|
394
|
+
affixConsistent: true,
|
|
395
|
+
};
|
|
396
|
+
const formattedValue = formatSummaryValue(summary.total, {
|
|
280
397
|
locale,
|
|
281
398
|
fractionDigits: summary.fractionDigits,
|
|
399
|
+
prefix: summary.affixConsistent ? summary.prefix : "",
|
|
400
|
+
suffix: summary.affixConsistent ? summary.suffix : "",
|
|
282
401
|
});
|
|
402
|
+
|
|
403
|
+
syncSummaryCellText(valueCell, formattedValue);
|
|
283
404
|
valueCell.dataset.value = String(summary.total);
|
|
284
405
|
valueCell.dataset.summaryTotal = "";
|
|
406
|
+
valueCell.removeAttribute("data-summary-empty");
|
|
285
407
|
} else {
|
|
408
|
+
syncSummaryCellText(valueCell, "");
|
|
409
|
+
delete valueCell.dataset.value;
|
|
410
|
+
valueCell.removeAttribute("data-summary-total");
|
|
286
411
|
valueCell.dataset.summaryEmpty = "";
|
|
287
412
|
}
|
|
413
|
+
}
|
|
288
414
|
|
|
289
|
-
|
|
415
|
+
while (row.cells.length > logicalColumnCount) {
|
|
416
|
+
row.deleteCell(-1);
|
|
290
417
|
}
|
|
291
418
|
|
|
292
419
|
return true;
|
|
@@ -301,6 +428,7 @@ export class SummaryTableElement extends TableElement {
|
|
|
301
428
|
];
|
|
302
429
|
|
|
303
430
|
#summaryObserver = null;
|
|
431
|
+
#summaryObserving = false;
|
|
304
432
|
#scheduledFrame = 0;
|
|
305
433
|
|
|
306
434
|
connectedCallback() {
|
|
@@ -310,7 +438,7 @@ export class SummaryTableElement extends TableElement {
|
|
|
310
438
|
|
|
311
439
|
disconnectedCallback() {
|
|
312
440
|
super.disconnectedCallback();
|
|
313
|
-
this.#
|
|
441
|
+
this.#stopSummaryObserving();
|
|
314
442
|
this.#summaryObserver = null;
|
|
315
443
|
|
|
316
444
|
if (this.#scheduledFrame !== 0 && typeof window !== "undefined") {
|
|
@@ -320,33 +448,37 @@ export class SummaryTableElement extends TableElement {
|
|
|
320
448
|
}
|
|
321
449
|
|
|
322
450
|
refresh() {
|
|
323
|
-
|
|
451
|
+
this.#stopSummaryObserving();
|
|
324
452
|
|
|
325
|
-
|
|
453
|
+
try {
|
|
454
|
+
const table = getTable(this);
|
|
326
455
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
456
|
+
if (!(table instanceof HTMLTableElementBase)) {
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
330
459
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
460
|
+
const labelColumnIndex = normalizeTableRowHeaderColumn(
|
|
461
|
+
this.getAttribute("data-row-header-column"),
|
|
462
|
+
) - 1;
|
|
463
|
+
const summaryColumns = collectSummaryColumns(
|
|
464
|
+
table,
|
|
465
|
+
normalizeSummaryColumns(this.getAttribute("data-summary-columns")),
|
|
466
|
+
labelColumnIndex,
|
|
467
|
+
);
|
|
468
|
+
const totals = calculateSummaryTotals(table, summaryColumns);
|
|
469
|
+
|
|
470
|
+
syncSummaryFooter(table, {
|
|
471
|
+
labelColumnIndex,
|
|
472
|
+
locale: normalizeSummaryLocale(this.getAttribute("data-locale")),
|
|
473
|
+
summaryColumns,
|
|
474
|
+
totalLabel: normalizeSummaryTotalLabel(this.getAttribute("data-total-label")),
|
|
475
|
+
totals,
|
|
476
|
+
});
|
|
348
477
|
|
|
349
|
-
|
|
478
|
+
super.refresh();
|
|
479
|
+
} finally {
|
|
480
|
+
this.#startSummaryObserving();
|
|
481
|
+
}
|
|
350
482
|
}
|
|
351
483
|
|
|
352
484
|
#scheduleRefresh() {
|
|
@@ -369,11 +501,25 @@ export class SummaryTableElement extends TableElement {
|
|
|
369
501
|
this.#scheduleRefresh();
|
|
370
502
|
});
|
|
371
503
|
|
|
372
|
-
this.#
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
504
|
+
this.#startSummaryObserving();
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
#startSummaryObserving() {
|
|
508
|
+
if (!this.#summaryObserver || this.#summaryObserving) {
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
this.#summaryObserver.observe(this, SUMMARY_OBSERVER_OPTIONS);
|
|
513
|
+
this.#summaryObserving = true;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
#stopSummaryObserving() {
|
|
517
|
+
if (!this.#summaryObserver || !this.#summaryObserving) {
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
this.#summaryObserver.disconnect();
|
|
522
|
+
this.#summaryObserving = false;
|
|
377
523
|
}
|
|
378
524
|
}
|
|
379
525
|
|