@rhc-shared-components/packages-table 0.1.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 +1533 -0
- package/dist/check-317f30b2.js +4 -0
- package/dist/check-ee7cdde5.js +5 -0
- package/dist/components/ExcludedPackagesTable.d.ts +6 -0
- package/dist/components/FilterInput.d.ts +6 -0
- package/dist/components/FilterableTable.d.ts +19 -0
- package/dist/components/Select.d.ts +9 -0
- package/dist/components/ToggleGroup.d.ts +10 -0
- package/dist/components/VulnerabilitiesTable.d.ts +6 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +4930 -0
- package/dist/index.modern.js +4460 -0
- package/dist/index.test.d.ts +1 -0
- package/dist/inline-edit-320c12ad.js +5 -0
- package/dist/inline-edit-b186d03c.js +4 -0
- package/dist/table-817f1921.js +5 -0
- package/dist/table-ffd0513c.js +4 -0
- package/dist/table-grid-5d7f8359.js +4 -0
- package/dist/table-grid-6f46705c.js +5 -0
- package/dist/table-scrollable-01103545.js +4 -0
- package/dist/table-scrollable-423d12ef.js +5 -0
- package/dist/table-tree-view-ee6ac38a.js +4 -0
- package/dist/table-tree-view-eec85588.js +5 -0
- package/package.json +84 -0
|
@@ -0,0 +1,4460 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import React__default, { useState, useEffect, useCallback, cloneElement } from 'react';
|
|
3
|
+
import { setTabIndex, useOUIAProps, handleArrows, Tooltip as Tooltip$1, Button, Popover, Checkbox, Toolbar, ToolbarContent, ToolbarItem, Pagination, Bullseye, EmptyState, EmptyStateIcon, Title, TextInput, Select, SelectOption, ToggleGroup as ToggleGroup$1, ToggleGroupItem } from '@patternfly/react-core';
|
|
4
|
+
import { sortBy, uniqueId } from 'lodash';
|
|
5
|
+
import { Tooltip } from '@patternfly/react-core/dist/esm/components/Tooltip/Tooltip';
|
|
6
|
+
import { Button as Button$1 } from '@patternfly/react-core/dist/esm/components/Button/Button';
|
|
7
|
+
import mergeWith from 'lodash/mergeWith';
|
|
8
|
+
import { Dropdown } from '@patternfly/react-core/dist/esm/components/Dropdown';
|
|
9
|
+
import { KebabToggle } from '@patternfly/react-core/dist/esm/components/Dropdown/KebabToggle';
|
|
10
|
+
import { DropdownItem } from '@patternfly/react-core/dist/esm/components/Dropdown/DropdownItem';
|
|
11
|
+
import { DropdownSeparator } from '@patternfly/react-core/dist/esm/components/Dropdown/DropdownSeparator';
|
|
12
|
+
import { DropdownPosition, DropdownDirection } from '@patternfly/react-core/dist/esm/components/Dropdown/dropdownConstants';
|
|
13
|
+
import { format } from 'date-fns';
|
|
14
|
+
|
|
15
|
+
var css_248z = ".packages-table pfe-tab-panel {\n --pfe-tabs__panel--PaddingTop: 1.5rem;\n --pfe-tabs__panel--PaddingLeft: 0; }\n\n.vulnerabilities-table pfe-icon {\n font-size: 1rem;\n padding-right: 0.5rem; }\n .vulnerabilities-table pfe-icon.color-critical {\n --pfe-icon--Color: #a30000; }\n .vulnerabilities-table pfe-icon.color-important {\n --pfe-icon--Color: #ec7a08; }\n .vulnerabilities-table pfe-icon.color-moderate {\n --pfe-icon--Color: #f5c12e; }\n .vulnerabilities-table pfe-icon.color-low {\n --pfe-icon--Color: #777; }\n\n.vulnerabilities-table__affected-packages-cell {\n text-overflow: ellipsis;\n overflow: hidden;\n white-space: nowrap; }\n\n.vulnerabilities-table__impact-cell {\n display: flex;\n align-items: center;\n flex-wrap: nowrap; }\n\n.filterable-table {\n padding-bottom: var(--pf-global--spacer--lg); }\n .filterable-table__bottom-pagination[class] {\n margin-top: 1rem; }\n .filterable-table .pf-c-toolbar {\n padding-top: 0; }\n .filterable-table .pf-c-toolbar__content {\n --pf-c-toolbar__content--PaddingRight: 0;\n --pf-c-toolbar__content--PaddingLeft: 0; }\n .filterable-table .pf-c-input-group {\n min-width: 20rem; }\n .filterable-table .pf-c-input-group__text {\n --pf-c-input-group__text--PaddingRight: 0; }\n .filterable-table .pf-c-pagination.pf-m-bottom {\n --pf-c-pagination--m-bottom--md--PaddingRight: 0; }\n\n.filter-input {\n width: 18rem;\n margin: 1rem 0 1rem 0; }\n .filter-input pfe-icon {\n --pfe-icon--Color: #777;\n font-size: 1rem;\n position: absolute;\n margin-top: 9px; }\n .filter-input pfe-icon.clear-icon {\n margin-left: -50px;\n cursor: pointer; }\n .filter-input pfe-icon.search-icon {\n margin-left: -30px; }\n";
|
|
16
|
+
|
|
17
|
+
function _extends() {
|
|
18
|
+
_extends = Object.assign || function (target) {
|
|
19
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
20
|
+
var source = arguments[i];
|
|
21
|
+
|
|
22
|
+
for (var key in source) {
|
|
23
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
24
|
+
target[key] = source[key];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return target;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
return _extends.apply(this, arguments);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let logger = () => null;
|
|
36
|
+
/**
|
|
37
|
+
* Reveal web components when loading is complete by removing the unresolved attribute
|
|
38
|
+
* from the body tag; log the event.
|
|
39
|
+
* @throws debugging log indicating the reveal event
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
function reveal() {
|
|
44
|
+
logger(`[reveal] elements ready, revealing the body`);
|
|
45
|
+
window.document.body.removeAttribute("unresolved");
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Auto-reveal functionality prevents a flash of unstyled content before components
|
|
49
|
+
* have finished loading.
|
|
50
|
+
* @param {function} logFunction
|
|
51
|
+
* @see https://github.com/github/webcomponentsjs#webcomponents-loaderjs
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
function autoReveal(logFunction) {
|
|
56
|
+
logger = logFunction; // If Web Components are already ready, run the handler right away. If they
|
|
57
|
+
// are not yet ready, wait.
|
|
58
|
+
//
|
|
59
|
+
// see https://github.com/github/webcomponentsjs#webcomponents-loaderjs for
|
|
60
|
+
// info about web component readiness events
|
|
61
|
+
|
|
62
|
+
const polyfillPresent = window.WebComponents;
|
|
63
|
+
const polyfillReady = polyfillPresent && window.WebComponents.ready;
|
|
64
|
+
|
|
65
|
+
if (!polyfillPresent || polyfillReady) {
|
|
66
|
+
handleWebComponentsReady();
|
|
67
|
+
} else {
|
|
68
|
+
window.addEventListener("WebComponentsReady", handleWebComponentsReady);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Reveal web components when loading is complete and log event.
|
|
73
|
+
* @throws debugging log indicating the web components are ready
|
|
74
|
+
*/
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
function handleWebComponentsReady() {
|
|
78
|
+
logger("[reveal] web components ready");
|
|
79
|
+
reveal();
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Verify that a property definition's `type` field contains one of the allowed
|
|
83
|
+
* types. If the definition type resolves to falsy, assumes String type.
|
|
84
|
+
* @param {constructor} definition
|
|
85
|
+
* @default String
|
|
86
|
+
* @return {Boolean} True if the definition type is one of String, Number, or Boolean
|
|
87
|
+
*/
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
function isAllowedType(definition) {
|
|
91
|
+
return [String, Number, Boolean].includes(definition.type || String);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Verify that a property definition's `default` value is of the correct type.
|
|
95
|
+
*
|
|
96
|
+
* A `default` value is valid if it's of the same type as the `type`
|
|
97
|
+
* definition. Or, if there is no `type` definition, then it must be a String
|
|
98
|
+
* (the default value for `type`).
|
|
99
|
+
* @param {type} definition
|
|
100
|
+
* @return {Boolean} True if the default value matches the type of the definition object.
|
|
101
|
+
*/
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
function isValidDefaultType(definition) {
|
|
105
|
+
return definition.hasOwnProperty("default") && definition.default.constructor === definition.type;
|
|
106
|
+
} // @POLYFILL Array.includes
|
|
107
|
+
|
|
108
|
+
/** @see https://tc39.github.io/ecma262/#sec-array.prototype.includes */
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
if (!Array.prototype.includes) {
|
|
112
|
+
Object.defineProperty(Array.prototype, "includes", {
|
|
113
|
+
value: function (valueToFind, fromIndex) {
|
|
114
|
+
if (this == null) {
|
|
115
|
+
throw new TypeError('"this" is null or not defined');
|
|
116
|
+
} // 1. Let O be ? ToObject(this value).
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
var o = Object(this); // 2. Let len be ? ToLength(? Get(O, "length")).
|
|
120
|
+
|
|
121
|
+
var len = o.length >>> 0; // 3. If len is 0, return false.
|
|
122
|
+
|
|
123
|
+
if (len === 0) {
|
|
124
|
+
return false;
|
|
125
|
+
} // 4. Let n be ? ToInteger(fromIndex).
|
|
126
|
+
// (If fromIndex is undefined, this step produces the value 0.)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
var n = fromIndex | 0; // 5. If n ≥ 0, then
|
|
130
|
+
// a. Let k be n.
|
|
131
|
+
// 6. Else n < 0,
|
|
132
|
+
// a. Let k be len + n.
|
|
133
|
+
// b. If k < 0, let k be 0.
|
|
134
|
+
|
|
135
|
+
var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
|
|
136
|
+
|
|
137
|
+
function sameValueZero(x, y) {
|
|
138
|
+
return x === y || typeof x === "number" && typeof y === "number" && isNaN(x) && isNaN(y);
|
|
139
|
+
} // 7. Repeat, while k < len
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
while (k < len) {
|
|
143
|
+
// a. Let elementK be the result of ? Get(O, ! ToString(k)).
|
|
144
|
+
// b. If SameValueZero(valueToFind, elementK) is true, return true.
|
|
145
|
+
if (sameValueZero(o[k], valueToFind)) {
|
|
146
|
+
return true;
|
|
147
|
+
} // c. Increase k by 1.
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
k++;
|
|
151
|
+
} // 8. Return false
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
} // @POLYFILL Object.entries
|
|
158
|
+
|
|
159
|
+
/** @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries */
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
if (!Object.entries) {
|
|
163
|
+
Object.entries = function (obj) {
|
|
164
|
+
var ownProps = Object.keys(obj),
|
|
165
|
+
i = ownProps.length,
|
|
166
|
+
resArray = new Array(i); // preallocate the Array
|
|
167
|
+
|
|
168
|
+
while (i--) resArray[i] = [ownProps[i], obj[ownProps[i]]];
|
|
169
|
+
|
|
170
|
+
return resArray;
|
|
171
|
+
};
|
|
172
|
+
} // @POLYFILL String.startsWith
|
|
173
|
+
|
|
174
|
+
/** @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith#polyfill */
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
if (!String.prototype.startsWith) {
|
|
178
|
+
Object.defineProperty(String.prototype, "startsWith", {
|
|
179
|
+
value: function (search, rawPos) {
|
|
180
|
+
var pos = rawPos > 0 ? rawPos | 0 : 0;
|
|
181
|
+
return this.substring(pos, pos + search.length) === search;
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
} // @POLYFILL Element.closest
|
|
185
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
if (!Element.prototype.closest) {
|
|
189
|
+
Element.prototype.closest = function (s) {
|
|
190
|
+
var el = this;
|
|
191
|
+
|
|
192
|
+
do {
|
|
193
|
+
if (el.matches(s)) return el;
|
|
194
|
+
el = el.parentElement || el.parentNode;
|
|
195
|
+
} while (el !== null && el.nodeType === 1);
|
|
196
|
+
|
|
197
|
+
return null;
|
|
198
|
+
};
|
|
199
|
+
} // @POLYFILL Element.matches
|
|
200
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Element/matches
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
if (!Element.prototype.matches) {
|
|
204
|
+
Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
|
|
205
|
+
} // @POLYFILL Array.prototype.find
|
|
206
|
+
// https://tc39.github.io/ecma262/#sec-array.prototype.find
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
if (!Array.prototype.find) {
|
|
210
|
+
Object.defineProperty(Array.prototype, "find", {
|
|
211
|
+
value: function (predicate) {
|
|
212
|
+
// 1. Let O be ? ToObject(this value).
|
|
213
|
+
if (this == null) {
|
|
214
|
+
throw new TypeError('"this" is null or not defined');
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
var o = Object(this); // 2. Let len be ? ToLength(? Get(O, "length")).
|
|
218
|
+
|
|
219
|
+
var len = o.length >>> 0; // 3. If IsCallable(predicate) is false, throw a TypeError exception.
|
|
220
|
+
|
|
221
|
+
if (typeof predicate !== "function") {
|
|
222
|
+
throw new TypeError("predicate must be a function");
|
|
223
|
+
} // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
var thisArg = arguments[1]; // 5. Let k be 0.
|
|
227
|
+
|
|
228
|
+
var k = 0; // 6. Repeat, while k < len
|
|
229
|
+
|
|
230
|
+
while (k < len) {
|
|
231
|
+
// a. Let Pk be ! ToString(k).
|
|
232
|
+
// b. Let kValue be ? Get(O, Pk).
|
|
233
|
+
// c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
|
|
234
|
+
// d. If testResult is true, return kValue.
|
|
235
|
+
var kValue = o[k];
|
|
236
|
+
|
|
237
|
+
if (predicate.call(thisArg, kValue, k, o)) {
|
|
238
|
+
return kValue;
|
|
239
|
+
} // e. Increase k by 1.
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
k++;
|
|
243
|
+
} // 7. Return undefined.
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
return undefined;
|
|
247
|
+
},
|
|
248
|
+
configurable: true,
|
|
249
|
+
writable: true
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
/*!
|
|
253
|
+
* PatternFly Elements: PFElement 1.12.3
|
|
254
|
+
* @license
|
|
255
|
+
* Copyright 2021 Red Hat, Inc.
|
|
256
|
+
*
|
|
257
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
258
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
259
|
+
* in the Software without restriction, including without limitation the rights
|
|
260
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
261
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
262
|
+
* furnished to do so, subject to the following conditions:
|
|
263
|
+
*
|
|
264
|
+
* The above copyright notice and this permission notice shall be included in
|
|
265
|
+
* all copies or substantial portions of the Software.
|
|
266
|
+
*
|
|
267
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
268
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
269
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
270
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
271
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
272
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
273
|
+
* SOFTWARE.
|
|
274
|
+
*
|
|
275
|
+
*/
|
|
276
|
+
// /**
|
|
277
|
+
// * Global prefix used for all components in the project.
|
|
278
|
+
// * @constant {String}
|
|
279
|
+
// * */
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
const prefix = "pfe";
|
|
283
|
+
/**
|
|
284
|
+
* @class PFElement
|
|
285
|
+
* @extends HTMLElement
|
|
286
|
+
* @version 1.12.3
|
|
287
|
+
* @classdesc Serves as the baseline for all PatternFly Element components.
|
|
288
|
+
*/
|
|
289
|
+
|
|
290
|
+
class PFElement extends HTMLElement {
|
|
291
|
+
/**
|
|
292
|
+
* A boolean value that indicates if the logging should be printed to the console; used for debugging.
|
|
293
|
+
* For use in a JS file or script tag; can also be added in the constructor of a component during development.
|
|
294
|
+
* @example PFElement.debugLog(true);
|
|
295
|
+
* @tags debug
|
|
296
|
+
*/
|
|
297
|
+
static debugLog(preference = null) {
|
|
298
|
+
if (preference !== null) {
|
|
299
|
+
// wrap localStorage references in a try/catch; merely referencing it can
|
|
300
|
+
// throw errors in some locked down environments
|
|
301
|
+
try {
|
|
302
|
+
localStorage.pfeLog = !!preference;
|
|
303
|
+
} catch (e) {
|
|
304
|
+
// if localStorage fails, fall back to PFElement._debugLog
|
|
305
|
+
PFElement._debugLog = !!preference;
|
|
306
|
+
return PFElement._debugLog;
|
|
307
|
+
}
|
|
308
|
+
} // @TODO the reference to _debugLog is for backwards compatibiilty and will be removed in 2.0
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
return localStorage.pfeLog === "true" || PFElement._debugLog;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* A boolean value that indicates if the performance should be tracked.
|
|
315
|
+
* For use in a JS file or script tag; can also be added in the constructor of a component during development.
|
|
316
|
+
* @example PFElement._trackPerformance = true;
|
|
317
|
+
*/
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
static trackPerformance(preference = null) {
|
|
321
|
+
if (preference !== null) {
|
|
322
|
+
PFElement._trackPerformance = !!preference;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
return PFElement._trackPerformance;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* A object that contains configuration set outside of pfe.
|
|
329
|
+
*
|
|
330
|
+
* @example const config = PFElement.config;
|
|
331
|
+
*/
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
static get config() {
|
|
335
|
+
// @TODO: Add config validation in the future.
|
|
336
|
+
return window.PfeConfig || {};
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* A logging wrapper which checks the debugLog boolean and prints to the console if true.
|
|
340
|
+
*
|
|
341
|
+
* @example PFElement.log("Hello");
|
|
342
|
+
*/
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
static log(...msgs) {
|
|
346
|
+
if (PFElement.debugLog()) {
|
|
347
|
+
console.log(...msgs);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Local logging that outputs the tag name as a prefix automatically
|
|
352
|
+
*
|
|
353
|
+
* @example this.log("Hello");
|
|
354
|
+
*/
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
log(...msgs) {
|
|
358
|
+
PFElement.log(`[${this.tag}${this.id ? `#${this.id}` : ""}]`, ...msgs);
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* A console warning wrapper which formats your output with useful debugging information.
|
|
362
|
+
*
|
|
363
|
+
* @example PFElement.warn("Hello");
|
|
364
|
+
*/
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
static warn(...msgs) {
|
|
368
|
+
console.warn(...msgs);
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Local warning wrapper that outputs the tag name as a prefix automatically.
|
|
372
|
+
* For use inside a component's function.
|
|
373
|
+
* @example this.warn("Hello");
|
|
374
|
+
*/
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
warn(...msgs) {
|
|
378
|
+
PFElement.warn(`[${this.tag}${this.id ? `#${this.id}` : ``}]`, ...msgs);
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* A console error wrapper which formats your output with useful debugging information.
|
|
382
|
+
* For use inside a component's function.
|
|
383
|
+
* @example PFElement.error("Hello");
|
|
384
|
+
*/
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
static error(...msgs) {
|
|
388
|
+
throw new Error([...msgs].join(" "));
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Local error wrapper that outputs the tag name as a prefix automatically.
|
|
392
|
+
* For use inside a component's function.
|
|
393
|
+
* @example this.error("Hello");
|
|
394
|
+
*/
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
error(...msgs) {
|
|
398
|
+
PFElement.error(`[${this.tag}${this.id ? `#${this.id}` : ``}]`, ...msgs);
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* A global definition of component types (a general way of defining the purpose of a
|
|
402
|
+
* component and how it is put together).
|
|
403
|
+
*/
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
static get PfeTypes() {
|
|
407
|
+
return {
|
|
408
|
+
Container: "container",
|
|
409
|
+
Content: "content",
|
|
410
|
+
Combo: "combo"
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* The current version of a component; set by the compiler using the package.json data.
|
|
415
|
+
*/
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
static get version() {
|
|
419
|
+
return "1.12.3";
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* A local alias to the static version.
|
|
423
|
+
* For use in the console to validate version being loaded.
|
|
424
|
+
* @example PfeAccordion.version
|
|
425
|
+
*/
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
get version() {
|
|
429
|
+
return this._pfeClass.version;
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Global property definitions: properties managed by the base class that apply to all components.
|
|
433
|
+
*/
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
static get properties() {
|
|
437
|
+
return {
|
|
438
|
+
pfelement: {
|
|
439
|
+
title: "Upgraded flag",
|
|
440
|
+
type: Boolean,
|
|
441
|
+
default: true,
|
|
442
|
+
observer: "_upgradeObserver"
|
|
443
|
+
},
|
|
444
|
+
on: {
|
|
445
|
+
title: "Context",
|
|
446
|
+
description: "Describes the visual context (backgrounds).",
|
|
447
|
+
type: String,
|
|
448
|
+
values: ["light", "dark", "saturated"],
|
|
449
|
+
default: el => el.contextVariable,
|
|
450
|
+
observer: "_onObserver"
|
|
451
|
+
},
|
|
452
|
+
context: {
|
|
453
|
+
title: "Context hook",
|
|
454
|
+
description: "Lets you override the system-set context.",
|
|
455
|
+
type: String,
|
|
456
|
+
values: ["light", "dark", "saturated"],
|
|
457
|
+
observer: "_contextObserver"
|
|
458
|
+
},
|
|
459
|
+
// @TODO: Deprecated with 1.0
|
|
460
|
+
oldTheme: {
|
|
461
|
+
type: String,
|
|
462
|
+
values: ["light", "dark", "saturated"],
|
|
463
|
+
alias: "context",
|
|
464
|
+
attr: "pfe-theme"
|
|
465
|
+
},
|
|
466
|
+
_style: {
|
|
467
|
+
title: "Custom styles",
|
|
468
|
+
type: String,
|
|
469
|
+
attr: "style",
|
|
470
|
+
observer: "_inlineStyleObserver"
|
|
471
|
+
},
|
|
472
|
+
type: {
|
|
473
|
+
title: "Component type",
|
|
474
|
+
type: String,
|
|
475
|
+
values: ["container", "content", "combo"]
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
static get observedAttributes() {
|
|
481
|
+
const properties = this.allProperties;
|
|
482
|
+
|
|
483
|
+
if (properties) {
|
|
484
|
+
const oa = Object.keys(properties).filter(prop => properties[prop].observer || properties[prop].cascade || properties[prop].alias).map(p => this._convertPropNameToAttrName(p));
|
|
485
|
+
return [...oa];
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* A quick way to fetch a random ID value.
|
|
490
|
+
* _Note:_ All values are prefixes with `pfe` automatically to ensure an ID-safe value is returned.
|
|
491
|
+
*
|
|
492
|
+
* @example this.id = this.randomID;
|
|
493
|
+
*/
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
get randomId() {
|
|
497
|
+
return `${prefix}-` + Math.random().toString(36).substr(2, 9);
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Set the --context variable with the provided value in this component.
|
|
501
|
+
*/
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
set contextVariable(value) {
|
|
505
|
+
this.cssVariable("context", value);
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Get the current value of the --context variable in this component.
|
|
509
|
+
* @return {string} [dark|light|saturated]
|
|
510
|
+
*/
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
get contextVariable() {
|
|
514
|
+
/* @DEPRECATED --theme in 1.0, to be removed in 2.0 */
|
|
515
|
+
return this.cssVariable("context") || this.cssVariable("theme");
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Returns a boolean statement of whether or not this component contains any light DOM.
|
|
519
|
+
* @returns {boolean}
|
|
520
|
+
* @example if(this.hasLightDOM()) this._init();
|
|
521
|
+
*/
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
hasLightDOM() {
|
|
525
|
+
return this.children.length || this.textContent.trim().length;
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Returns a boolean statement of whether or not that slot exists in the light DOM.
|
|
529
|
+
*
|
|
530
|
+
* @param {String|Array} name The slot name.
|
|
531
|
+
* @example this.hasSlot("header");
|
|
532
|
+
*/
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
hasSlot(name) {
|
|
536
|
+
if (!name) {
|
|
537
|
+
this.warn(`Please provide at least one slot name for which to search.`);
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
if (typeof name === "string") {
|
|
542
|
+
return [...this.children].filter(child => child.hasAttribute("slot") && child.getAttribute("slot") === name).length > 0;
|
|
543
|
+
} else if (Array.isArray(name)) {
|
|
544
|
+
return name.reduce(n => [...this.children].filter(child => child.hasAttribute("slot") && child.getAttribute("slot") === n).length > 0);
|
|
545
|
+
} else {
|
|
546
|
+
this.warn(`Expected hasSlot argument to be a string or an array, but it was given: ${typeof name}.`);
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Given a slot name, returns elements assigned to the slot as an arry.
|
|
552
|
+
* If no value is provided (i.e., `this.getSlot()`), it returns all children not assigned to a slot (without a slot attribute).
|
|
553
|
+
*
|
|
554
|
+
* @example: `this.getSlot("header")`
|
|
555
|
+
*/
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
getSlot(name = "unassigned") {
|
|
559
|
+
if (name !== "unassigned") {
|
|
560
|
+
return [...this.children].filter(child => child.hasAttribute("slot") && child.getAttribute("slot") === name);
|
|
561
|
+
} else {
|
|
562
|
+
return [...this.children].filter(child => !child.hasAttribute("slot"));
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
cssVariable(name, value, element = this) {
|
|
567
|
+
name = name.substr(0, 2) !== "--" ? "--" + name : name;
|
|
568
|
+
|
|
569
|
+
if (value) {
|
|
570
|
+
element.style.setProperty(name, value);
|
|
571
|
+
return value;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
return window.getComputedStyle(element).getPropertyValue(name).trim() || null;
|
|
575
|
+
}
|
|
576
|
+
/**
|
|
577
|
+
* This alerts nested components to a change in the context
|
|
578
|
+
*/
|
|
579
|
+
|
|
580
|
+
|
|
581
|
+
contextUpdate() {
|
|
582
|
+
// Loop over light DOM elements, find direct descendants that are components
|
|
583
|
+
const lightEls = [...this.querySelectorAll("*")].filter(item => item.tagName.toLowerCase().slice(0, 4) === `${prefix}-`) // Closest will return itself or it's ancestor matching that selector
|
|
584
|
+
.filter(item => {
|
|
585
|
+
// If there is no parent element, return null
|
|
586
|
+
if (!item.parentElement) return; // Otherwise, find the closest component that's this one
|
|
587
|
+
else return item.parentElement.closest(`[${this._pfeClass._getCache("prop2attr").pfelement}]`) === this;
|
|
588
|
+
}); // Loop over shadow elements, find direct descendants that are components
|
|
589
|
+
|
|
590
|
+
let shadowEls = [...this.shadowRoot.querySelectorAll("*")].filter(item => item.tagName.toLowerCase().slice(0, 4) === `${prefix}-`) // Closest will return itself or it's ancestor matching that selector
|
|
591
|
+
.filter(item => {
|
|
592
|
+
// If there is a parent element and we can find another web component in the ancestor tree
|
|
593
|
+
if (item.parentElement && item.parentElement.closest(`[${this._pfeClass._getCache("prop2attr").pfelement}]`)) {
|
|
594
|
+
return item.parentElement.closest(`[${this._pfeClass._getCache("prop2attr").pfelement}]`) === this;
|
|
595
|
+
} // Otherwise, check if the host matches this context
|
|
596
|
+
|
|
597
|
+
|
|
598
|
+
if (item.getRootNode().host === this) return true; // If neither state is true, return false
|
|
599
|
+
|
|
600
|
+
return false;
|
|
601
|
+
});
|
|
602
|
+
const nestedEls = lightEls.concat(shadowEls); // If nested elements don't exist, return without processing
|
|
603
|
+
|
|
604
|
+
if (nestedEls.length === 0) return; // Loop over the nested elements and reset their context
|
|
605
|
+
|
|
606
|
+
nestedEls.map(child => {
|
|
607
|
+
if (child.resetContext) {
|
|
608
|
+
this.log(`Update context of ${child.tagName.toLowerCase()}`); // Ask the component to recheck it's context in case it changed
|
|
609
|
+
|
|
610
|
+
child.resetContext(this.on);
|
|
611
|
+
}
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
resetContext(fallback) {
|
|
616
|
+
if (this.isIE11) return; // Priority order for context values to be pulled from:
|
|
617
|
+
//--> 1. context (OLD: pfe-theme)
|
|
618
|
+
//--> 2. --context (OLD: --theme)
|
|
619
|
+
|
|
620
|
+
let value = this.context || this.contextVariable || fallback; // Validate that the current context (this.on) and the new context (value) are the same OR
|
|
621
|
+
// no context is set and there isn't a new context being set
|
|
622
|
+
|
|
623
|
+
if (this.on === value || !this.on && !value) return;
|
|
624
|
+
this.log(`Resetting context from ${this.on} to ${value || "null"}`);
|
|
625
|
+
this.on = value;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
constructor(pfeClass, {
|
|
629
|
+
type = null,
|
|
630
|
+
delayRender = false
|
|
631
|
+
} = {}) {
|
|
632
|
+
super();
|
|
633
|
+
this._pfeClass = pfeClass;
|
|
634
|
+
this.tag = pfeClass.tag;
|
|
635
|
+
this._parseObserver = this._parseObserver.bind(this);
|
|
636
|
+
this.isIE11 = /MSIE|Trident|Edge\//.test(window.navigator.userAgent); // Initialize the array of jump links pointers
|
|
637
|
+
// Expects items in the array to be NodeItems
|
|
638
|
+
|
|
639
|
+
if (!this._pfeClass.instances || !(this._pfeClass.instances.length >= 0)) this._pfeClass.instances = []; // Set up the mark ID based on existing ID on component if it exists
|
|
640
|
+
|
|
641
|
+
if (!this.id) {
|
|
642
|
+
this._markId = this.randomId.replace("pfe", this.tag);
|
|
643
|
+
} else if (this.id.startsWith("pfe-") && !this.id.startsWith(this.tag)) {
|
|
644
|
+
this._markId = this.id.replace("pfe", this.tag);
|
|
645
|
+
} else {
|
|
646
|
+
this._markId = `${this.tag}-${this.id}`;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
this._markCount = 0; // TODO: Deprecated for 1.0 release
|
|
650
|
+
|
|
651
|
+
this.schemaProps = pfeClass.schemaProperties; // TODO: Migrate this out of schema for 1.0
|
|
652
|
+
|
|
653
|
+
this.slots = pfeClass.slots;
|
|
654
|
+
this.template = document.createElement("template"); // Set the default value to the passed in type
|
|
655
|
+
|
|
656
|
+
if (type && this._pfeClass.allProperties.type) this._pfeClass.allProperties.type.default = type; // Initalize the properties and attributes from the property getter
|
|
657
|
+
|
|
658
|
+
this._initializeProperties();
|
|
659
|
+
|
|
660
|
+
this.attachShadow({
|
|
661
|
+
mode: "open"
|
|
662
|
+
}); // Tracks if the component has been initially rendered. Useful if for debouncing
|
|
663
|
+
// template updates.
|
|
664
|
+
|
|
665
|
+
this._rendered = false;
|
|
666
|
+
if (!delayRender) this.render();
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* Standard connected callback; fires when the component is added to the DOM.
|
|
670
|
+
*/
|
|
671
|
+
|
|
672
|
+
|
|
673
|
+
connectedCallback() {
|
|
674
|
+
this._initializeAttributeDefaults();
|
|
675
|
+
|
|
676
|
+
if (window.ShadyCSS) window.ShadyCSS.styleElement(this); // Register this instance with the pointer for the scoped class and the global context
|
|
677
|
+
|
|
678
|
+
this._pfeClass.instances.push(this);
|
|
679
|
+
|
|
680
|
+
PFElement.allInstances.push(this); // If the slot definition exists, set up an observer
|
|
681
|
+
|
|
682
|
+
if (typeof this.slots === "object") {
|
|
683
|
+
this._slotsObserver = new MutationObserver(() => this._initializeSlots(this.tag, this.slots));
|
|
684
|
+
|
|
685
|
+
this._initializeSlots(this.tag, this.slots);
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Standard disconnected callback; fires when a componet is removed from the DOM.
|
|
690
|
+
* Add your removeEventListeners here.
|
|
691
|
+
*/
|
|
692
|
+
|
|
693
|
+
|
|
694
|
+
disconnectedCallback() {
|
|
695
|
+
if (this._cascadeObserver) this._cascadeObserver.disconnect();
|
|
696
|
+
if (this._slotsObserver) this._slotsObserver.disconnect(); // Remove this instance from the pointer
|
|
697
|
+
|
|
698
|
+
const classIdx = this._pfeClass.instances.find(item => item !== this);
|
|
699
|
+
|
|
700
|
+
delete this._pfeClass.instances[classIdx];
|
|
701
|
+
const globalIdx = PFElement.allInstances.find(item => item !== this);
|
|
702
|
+
delete PFElement.allInstances[globalIdx];
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Attribute changed callback fires when attributes are updated.
|
|
706
|
+
* This combines the global and the component-specific logic.
|
|
707
|
+
*/
|
|
708
|
+
|
|
709
|
+
|
|
710
|
+
attributeChangedCallback(attr, oldVal, newVal) {
|
|
711
|
+
if (!this._pfeClass.allProperties) return;
|
|
712
|
+
|
|
713
|
+
let propName = this._pfeClass._attr2prop(attr);
|
|
714
|
+
|
|
715
|
+
const propDef = this._pfeClass.allProperties[propName]; // If the attribute that changed derives from a property definition
|
|
716
|
+
|
|
717
|
+
if (propDef) {
|
|
718
|
+
// If the property/attribute pair has an alias, copy the new value to the alias target
|
|
719
|
+
if (propDef.alias) {
|
|
720
|
+
const aliasedPropDef = this._pfeClass.allProperties[propDef.alias];
|
|
721
|
+
|
|
722
|
+
const aliasedAttr = this._pfeClass._prop2attr(propDef.alias);
|
|
723
|
+
|
|
724
|
+
const aliasedAttrVal = this.getAttribute(aliasedAttr);
|
|
725
|
+
|
|
726
|
+
if (aliasedAttrVal !== newVal) {
|
|
727
|
+
this[propDef.alias] = this._castPropertyValue(aliasedPropDef, newVal);
|
|
728
|
+
}
|
|
729
|
+
} // If the property/attribute pair has an observer, fire it
|
|
730
|
+
// Observers receive the oldValue and the newValue from the attribute changed callback
|
|
731
|
+
|
|
732
|
+
|
|
733
|
+
if (propDef.observer) {
|
|
734
|
+
this[propDef.observer](this._castPropertyValue(propDef, oldVal), this._castPropertyValue(propDef, newVal));
|
|
735
|
+
} // If the property/attribute pair has a cascade target, copy the attribute to the matching elements
|
|
736
|
+
// Note: this handles the cascading of new/updated attributes
|
|
737
|
+
|
|
738
|
+
|
|
739
|
+
if (propDef.cascade) {
|
|
740
|
+
this._cascadeAttribute(attr, this._pfeClass._convertSelectorsToArray(propDef.cascade));
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
/**
|
|
745
|
+
* Standard render function.
|
|
746
|
+
*/
|
|
747
|
+
|
|
748
|
+
|
|
749
|
+
render() {
|
|
750
|
+
this.shadowRoot.innerHTML = "";
|
|
751
|
+
this.template.innerHTML = this.html;
|
|
752
|
+
|
|
753
|
+
if (window.ShadyCSS) {
|
|
754
|
+
window.ShadyCSS.prepareTemplate(this.template, this.tag);
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
this.shadowRoot.appendChild(this.template.content.cloneNode(true));
|
|
758
|
+
this.log(`render`); // Cascade properties to the rendered template
|
|
759
|
+
|
|
760
|
+
this.cascadeProperties(); // Update the display context
|
|
761
|
+
|
|
762
|
+
this.contextUpdate();
|
|
763
|
+
|
|
764
|
+
if (PFElement.trackPerformance()) {
|
|
765
|
+
try {
|
|
766
|
+
performance.mark(`${this._markId}-rendered`);
|
|
767
|
+
|
|
768
|
+
if (this._markCount < 1) {
|
|
769
|
+
this._markCount = this._markCount + 1; // Navigation start, i.e., the browser first sees that the user has navigated to the page
|
|
770
|
+
|
|
771
|
+
performance.measure(`${this._markId}-from-navigation-to-first-render`, undefined, `${this._markId}-rendered`); // Render is run before connection unless delayRender is used
|
|
772
|
+
|
|
773
|
+
performance.measure(`${this._markId}-from-defined-to-first-render`, `${this._markId}-defined`, `${this._markId}-rendered`);
|
|
774
|
+
}
|
|
775
|
+
} catch (err) {
|
|
776
|
+
this.log(`Performance marks are not supported by this browser.`);
|
|
777
|
+
}
|
|
778
|
+
} // If the slot definition exists, set up an observer
|
|
779
|
+
|
|
780
|
+
|
|
781
|
+
if (typeof this.slots === "object" && this._slotsObserver) {
|
|
782
|
+
this._slotsObserver.observe(this, {
|
|
783
|
+
childList: true
|
|
784
|
+
});
|
|
785
|
+
} // If an observer was defined, set it to begin observing here
|
|
786
|
+
|
|
787
|
+
|
|
788
|
+
if (this._cascadeObserver) {
|
|
789
|
+
this._cascadeObserver.observe(this, {
|
|
790
|
+
attributes: true,
|
|
791
|
+
childList: true,
|
|
792
|
+
subtree: true
|
|
793
|
+
});
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
this._rendered = true;
|
|
797
|
+
}
|
|
798
|
+
/**
|
|
799
|
+
* A wrapper around an event dispatch to standardize formatting.
|
|
800
|
+
*/
|
|
801
|
+
|
|
802
|
+
|
|
803
|
+
emitEvent(name, {
|
|
804
|
+
bubbles = true,
|
|
805
|
+
cancelable = false,
|
|
806
|
+
composed = true,
|
|
807
|
+
detail = {}
|
|
808
|
+
} = {}) {
|
|
809
|
+
if (detail) this.log(`Custom event: ${name}`, detail);else this.log(`Custom event: ${name}`);
|
|
810
|
+
this.dispatchEvent(new CustomEvent(name, {
|
|
811
|
+
bubbles,
|
|
812
|
+
cancelable,
|
|
813
|
+
composed,
|
|
814
|
+
detail
|
|
815
|
+
}));
|
|
816
|
+
}
|
|
817
|
+
/**
|
|
818
|
+
* Handles the cascading of properties to nested components when new elements are added
|
|
819
|
+
* Attribute updates/additions are handled by the attribute callback
|
|
820
|
+
*/
|
|
821
|
+
|
|
822
|
+
|
|
823
|
+
cascadeProperties(nodeList) {
|
|
824
|
+
const cascade = this._pfeClass._getCache("cascadingProperties");
|
|
825
|
+
|
|
826
|
+
if (cascade) {
|
|
827
|
+
if (this._cascadeObserver) this._cascadeObserver.disconnect();
|
|
828
|
+
let selectors = Object.keys(cascade); // Find out if anything in the nodeList matches any of the observed selectors for cacading properties
|
|
829
|
+
|
|
830
|
+
if (selectors) {
|
|
831
|
+
if (nodeList) {
|
|
832
|
+
[...nodeList].forEach(nodeItem => {
|
|
833
|
+
selectors.forEach(selector => {
|
|
834
|
+
// if this node has a match function (i.e., it's an HTMLElement, not
|
|
835
|
+
// a text node), see if it matches the selector, otherwise drop it (like it's hot).
|
|
836
|
+
if (nodeItem.matches && nodeItem.matches(selector)) {
|
|
837
|
+
let attrNames = cascade[selector]; // each selector can match multiple properties/attributes, so
|
|
838
|
+
// copy each of them
|
|
839
|
+
|
|
840
|
+
attrNames.forEach(attrName => this._copyAttribute(attrName, nodeItem));
|
|
841
|
+
}
|
|
842
|
+
});
|
|
843
|
+
});
|
|
844
|
+
} else {
|
|
845
|
+
// If a match was found, cascade each attribute to the element
|
|
846
|
+
const components = selectors.filter(item => item.slice(0, prefix.length + 1) === `${prefix}-`).map(name => customElements.whenDefined(name));
|
|
847
|
+
if (components) Promise.all(components).then(() => {
|
|
848
|
+
this._cascadeAttributes(selectors, cascade);
|
|
849
|
+
});else this._cascadeAttributes(selectors, cascade);
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
if (this._rendered && this._cascadeObserver) this._cascadeObserver.observe(this, {
|
|
854
|
+
attributes: true,
|
|
855
|
+
childList: true,
|
|
856
|
+
subtree: true
|
|
857
|
+
});
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
/* --- Observers for global properties --- */
|
|
861
|
+
|
|
862
|
+
/**
|
|
863
|
+
* This responds to changes in the pfelement attribute; indicates if the component upgraded
|
|
864
|
+
* @TODO maybe we should use just the attribute instead of the class?
|
|
865
|
+
* https://github.com/angular/angular/issues/15399#issuecomment-318785677
|
|
866
|
+
*/
|
|
867
|
+
|
|
868
|
+
|
|
869
|
+
_upgradeObserver() {
|
|
870
|
+
this.classList.add("PFElement");
|
|
871
|
+
}
|
|
872
|
+
/**
|
|
873
|
+
* This responds to changes in the context attribute; manual override tool
|
|
874
|
+
*/
|
|
875
|
+
|
|
876
|
+
|
|
877
|
+
_contextObserver(oldValue, newValue) {
|
|
878
|
+
if (newValue && (oldValue && oldValue !== newValue || !oldValue)) {
|
|
879
|
+
this.log(`Running the context observer`);
|
|
880
|
+
this.on = newValue;
|
|
881
|
+
this.cssVariable("context", newValue);
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
/**
|
|
885
|
+
* This responds to changes in the context; source of truth for components
|
|
886
|
+
*/
|
|
887
|
+
|
|
888
|
+
|
|
889
|
+
_onObserver(oldValue, newValue) {
|
|
890
|
+
if (oldValue && oldValue !== newValue || newValue && !oldValue) {
|
|
891
|
+
this.log(`Context update`); // Fire an event for child components
|
|
892
|
+
|
|
893
|
+
this.contextUpdate();
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
/**
|
|
897
|
+
* This responds to inline style changes and greps for context or theme updates.
|
|
898
|
+
* @TODO: --theme will be deprecated in 2.0
|
|
899
|
+
*/
|
|
900
|
+
|
|
901
|
+
|
|
902
|
+
_inlineStyleObserver(oldValue, newValue) {
|
|
903
|
+
if (oldValue === newValue) return; // If there are no inline styles, a context might have been deleted, so call resetContext
|
|
904
|
+
|
|
905
|
+
if (!newValue) this.resetContext();else {
|
|
906
|
+
this.log(`Style observer activated on ${this.tag}`, `${newValue || "null"}`); // Grep for context/theme
|
|
907
|
+
|
|
908
|
+
const regex = /--[\w|-]*(?:context|theme):\s*(?:\"*(light|dark|saturated)\"*)/gi;
|
|
909
|
+
let match = regex.exec(newValue); // If no match is returned, exit the observer
|
|
910
|
+
|
|
911
|
+
if (!match) return;
|
|
912
|
+
const newContext = match[1]; // If the new context value differs from the on value, update
|
|
913
|
+
|
|
914
|
+
if (newContext !== this.on && !this.context) this.on = newContext;
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
/**
|
|
918
|
+
* This is connected with a mutation observer that watches for updates to the light DOM
|
|
919
|
+
* and pushes down the cascading values
|
|
920
|
+
*/
|
|
921
|
+
|
|
922
|
+
|
|
923
|
+
_parseObserver(mutationsList) {
|
|
924
|
+
// Iterate over the mutation list, look for cascade updates
|
|
925
|
+
for (let mutation of mutationsList) {
|
|
926
|
+
// If a new node is added, attempt to cascade attributes to it
|
|
927
|
+
if (mutation.type === "childList" && mutation.addedNodes.length) {
|
|
928
|
+
const nonTextNodes = [...mutation.addedNodes].filter(n => n.nodeType !== HTMLElement.TEXT_NODE);
|
|
929
|
+
this.cascadeProperties(nonTextNodes);
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
/* --- End observers --- */
|
|
934
|
+
|
|
935
|
+
/**
|
|
936
|
+
* Validate that the property meets the requirements for type and naming.
|
|
937
|
+
*/
|
|
938
|
+
|
|
939
|
+
|
|
940
|
+
static _validateProperties() {
|
|
941
|
+
for (let propName in this.allProperties) {
|
|
942
|
+
const propDef = this.allProperties[propName]; // Verify that properties conform to the allowed data types
|
|
943
|
+
|
|
944
|
+
if (!isAllowedType(propDef)) {
|
|
945
|
+
this.error(`Property "${propName}" on ${this.name} must have type String, Number, or Boolean.`);
|
|
946
|
+
} // Verify the property name conforms to our naming rules
|
|
947
|
+
|
|
948
|
+
|
|
949
|
+
if (!/^[a-z_]/.test(propName)) {
|
|
950
|
+
this.error(`Property ${this.name}.${propName} defined, but prop names must begin with a lower-case letter or an underscore`);
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
const isFunction = typeof propDef.default === "function"; // If the default value is not the same type as defined by the property
|
|
954
|
+
// and it's not a function (we can't validate the output of the function
|
|
955
|
+
// on the class level), throw a warning
|
|
956
|
+
|
|
957
|
+
if (propDef.default && !isValidDefaultType(propDef) && !isFunction) this.error(`[${this.name}] The default value \`${propDef.default}\` does not match the assigned type ${propDef.type.name} for the \'${propName}\' property`);
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
/**
|
|
961
|
+
* Convert provided property value to the correct type as defined in the properties method.
|
|
962
|
+
*/
|
|
963
|
+
|
|
964
|
+
|
|
965
|
+
_castPropertyValue(propDef, attrValue) {
|
|
966
|
+
switch (propDef.type) {
|
|
967
|
+
case Number:
|
|
968
|
+
// map various attribute string values to their respective
|
|
969
|
+
// desired property values
|
|
970
|
+
return {
|
|
971
|
+
[attrValue]: Number(attrValue),
|
|
972
|
+
null: null,
|
|
973
|
+
NaN: NaN,
|
|
974
|
+
undefined: undefined
|
|
975
|
+
}[attrValue];
|
|
976
|
+
|
|
977
|
+
case Boolean:
|
|
978
|
+
return attrValue !== null;
|
|
979
|
+
|
|
980
|
+
case String:
|
|
981
|
+
return {
|
|
982
|
+
[attrValue]: attrValue,
|
|
983
|
+
undefined: undefined
|
|
984
|
+
}[attrValue];
|
|
985
|
+
|
|
986
|
+
default:
|
|
987
|
+
return attrValue;
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
991
|
+
* Map provided value to the attribute name on the component.
|
|
992
|
+
*/
|
|
993
|
+
|
|
994
|
+
|
|
995
|
+
_assignValueToAttribute(obj, attr, value) {
|
|
996
|
+
// If the default is false and the property is boolean, we don't need to do anything
|
|
997
|
+
const isBooleanFalse = obj.type === Boolean && !value;
|
|
998
|
+
const isNull = value === null;
|
|
999
|
+
const isUndefined = typeof value === "undefined"; // If the attribute is not defined, set the default value
|
|
1000
|
+
|
|
1001
|
+
if (isBooleanFalse || isNull || isUndefined) {
|
|
1002
|
+
this.removeAttribute(attr);
|
|
1003
|
+
} else {
|
|
1004
|
+
// Boolean values get an empty string: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#boolean-attributes
|
|
1005
|
+
if (obj.type === Boolean && typeof value === "boolean") {
|
|
1006
|
+
this.setAttribute(attr, "");
|
|
1007
|
+
} else {
|
|
1008
|
+
// Validate against the provided values
|
|
1009
|
+
if (obj.values) {
|
|
1010
|
+
this._validateAttributeValue(obj, attr, value);
|
|
1011
|
+
} // Still accept the value provided even if it's not valid
|
|
1012
|
+
|
|
1013
|
+
|
|
1014
|
+
this.setAttribute(attr, value);
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
/**
|
|
1019
|
+
* Maps the defined slots into an object that is easier to query
|
|
1020
|
+
*/
|
|
1021
|
+
|
|
1022
|
+
|
|
1023
|
+
_initializeSlots(tag, slots) {
|
|
1024
|
+
this.log("Validate slots...");
|
|
1025
|
+
if (this._slotsObserver) this._slotsObserver.disconnect(); // Loop over the properties provided by the schema
|
|
1026
|
+
|
|
1027
|
+
Object.keys(slots).forEach(slot => {
|
|
1028
|
+
let slotObj = slots[slot]; // Only attach the information if the data provided is a schema object
|
|
1029
|
+
|
|
1030
|
+
if (typeof slotObj === "object") {
|
|
1031
|
+
let slotExists = false;
|
|
1032
|
+
let result = []; // If it's a named slot, look for that slot definition
|
|
1033
|
+
|
|
1034
|
+
if (slotObj.namedSlot) {
|
|
1035
|
+
// Check prefixed slots
|
|
1036
|
+
result = this.getSlot(`${tag}--${slot}`);
|
|
1037
|
+
|
|
1038
|
+
if (result.length > 0) {
|
|
1039
|
+
slotObj.nodes = result;
|
|
1040
|
+
slotExists = true;
|
|
1041
|
+
} // Check for unprefixed slots
|
|
1042
|
+
|
|
1043
|
+
|
|
1044
|
+
result = this.getSlot(`${slot}`);
|
|
1045
|
+
|
|
1046
|
+
if (result.length > 0) {
|
|
1047
|
+
slotObj.nodes = result;
|
|
1048
|
+
slotExists = true;
|
|
1049
|
+
} // If it's the default slot, look for direct children not assigned to a slot
|
|
1050
|
+
|
|
1051
|
+
} else {
|
|
1052
|
+
result = [...this.children].filter(child => !child.hasAttribute("slot"));
|
|
1053
|
+
|
|
1054
|
+
if (result.length > 0) {
|
|
1055
|
+
slotObj.nodes = result;
|
|
1056
|
+
slotExists = true;
|
|
1057
|
+
}
|
|
1058
|
+
} // If the slot exists, attach an attribute to the parent to indicate that
|
|
1059
|
+
|
|
1060
|
+
|
|
1061
|
+
if (slotExists) {
|
|
1062
|
+
this.setAttribute(`has_${slot}`, "");
|
|
1063
|
+
} else {
|
|
1064
|
+
this.removeAttribute(`has_${slot}`);
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
});
|
|
1068
|
+
this.log("Slots validated.");
|
|
1069
|
+
if (this._slotsObserver) this._slotsObserver.observe(this, {
|
|
1070
|
+
childList: true
|
|
1071
|
+
});
|
|
1072
|
+
}
|
|
1073
|
+
/**
|
|
1074
|
+
* Sets up the property definitions based on the properties method.
|
|
1075
|
+
*/
|
|
1076
|
+
|
|
1077
|
+
|
|
1078
|
+
_initializeProperties() {
|
|
1079
|
+
const properties = this._pfeClass.allProperties;
|
|
1080
|
+
let hasCascade = false;
|
|
1081
|
+
if (Object.keys(properties).length > 0) this.log(`Initialize properties`);
|
|
1082
|
+
|
|
1083
|
+
for (let propName in properties) {
|
|
1084
|
+
const propDef = properties[propName]; // Check if the property exists, throw a warning if it does.
|
|
1085
|
+
// HTMLElements have a LOT of properties; it wouldn't be hard
|
|
1086
|
+
// to overwrite one accidentally.
|
|
1087
|
+
|
|
1088
|
+
if (typeof this[propName] !== "undefined") {
|
|
1089
|
+
this.log(`Property "${propName}" on ${this.constructor.name} cannot be defined because the property name is reserved`);
|
|
1090
|
+
} else {
|
|
1091
|
+
const attrName = this._pfeClass._prop2attr(propName);
|
|
1092
|
+
|
|
1093
|
+
if (propDef.cascade) hasCascade = true;
|
|
1094
|
+
Object.defineProperty(this, propName, {
|
|
1095
|
+
get: () => {
|
|
1096
|
+
const attrValue = this.getAttribute(attrName);
|
|
1097
|
+
return this._castPropertyValue(propDef, attrValue);
|
|
1098
|
+
},
|
|
1099
|
+
set: rawNewVal => {
|
|
1100
|
+
// Assign the value to the attribute
|
|
1101
|
+
this._assignValueToAttribute(propDef, attrName, rawNewVal);
|
|
1102
|
+
|
|
1103
|
+
return rawNewVal;
|
|
1104
|
+
},
|
|
1105
|
+
writeable: true,
|
|
1106
|
+
enumerable: true,
|
|
1107
|
+
configurable: false
|
|
1108
|
+
});
|
|
1109
|
+
}
|
|
1110
|
+
} // If any of the properties has cascade, attach a new mutation observer to the component
|
|
1111
|
+
|
|
1112
|
+
|
|
1113
|
+
if (hasCascade) {
|
|
1114
|
+
this._cascadeObserver = new MutationObserver(this._parseObserver);
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
/**
|
|
1118
|
+
* Intialize the default value for an attribute.
|
|
1119
|
+
*/
|
|
1120
|
+
|
|
1121
|
+
|
|
1122
|
+
_initializeAttributeDefaults() {
|
|
1123
|
+
const properties = this._pfeClass.allProperties;
|
|
1124
|
+
|
|
1125
|
+
for (let propName in properties) {
|
|
1126
|
+
const propDef = properties[propName];
|
|
1127
|
+
|
|
1128
|
+
const attrName = this._pfeClass._prop2attr(propName);
|
|
1129
|
+
|
|
1130
|
+
if (propDef.hasOwnProperty("default")) {
|
|
1131
|
+
let value = propDef.default; // Check if default is a function
|
|
1132
|
+
|
|
1133
|
+
if (typeof propDef.default === "function") {
|
|
1134
|
+
value = propDef.default(this);
|
|
1135
|
+
} // If the attribute has not already been set, assign the default value
|
|
1136
|
+
|
|
1137
|
+
|
|
1138
|
+
if (!this.hasAttribute(attrName)) {
|
|
1139
|
+
// Assign the value to the attribute
|
|
1140
|
+
this._assignValueToAttribute(propDef, attrName, value);
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
/**
|
|
1146
|
+
* Validate the value against provided values.
|
|
1147
|
+
*/
|
|
1148
|
+
// @TODO add support for a validation function
|
|
1149
|
+
|
|
1150
|
+
|
|
1151
|
+
_validateAttributeValue(propDef, attr, value) {
|
|
1152
|
+
if (Array.isArray(propDef.values) && propDef.values.length > 0 && !propDef.values.includes(value) // ||
|
|
1153
|
+
// (typeof propDef.values === "string" && propDef.values !== value) ||
|
|
1154
|
+
// (typeof propDef.values === "function" && !propDef.values(value))
|
|
1155
|
+
) {
|
|
1156
|
+
this.warn(`${value} is not a valid value for ${attr}. Please provide one of the following values: ${propDef.values.join(", ")}`);
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
return value;
|
|
1160
|
+
}
|
|
1161
|
+
/**
|
|
1162
|
+
* Look up an attribute name linked to a given property name.
|
|
1163
|
+
*/
|
|
1164
|
+
|
|
1165
|
+
|
|
1166
|
+
static _prop2attr(propName) {
|
|
1167
|
+
return this._getCache("prop2attr")[propName];
|
|
1168
|
+
}
|
|
1169
|
+
/**
|
|
1170
|
+
* Look up an property name linked to a given attribute name.
|
|
1171
|
+
*/
|
|
1172
|
+
|
|
1173
|
+
|
|
1174
|
+
static _attr2prop(attrName) {
|
|
1175
|
+
return this._getCache("attr2prop")[attrName];
|
|
1176
|
+
}
|
|
1177
|
+
/**
|
|
1178
|
+
* Convert a property name to an attribute name.
|
|
1179
|
+
*/
|
|
1180
|
+
|
|
1181
|
+
|
|
1182
|
+
static _convertPropNameToAttrName(propName) {
|
|
1183
|
+
const propDef = this.allProperties[propName];
|
|
1184
|
+
|
|
1185
|
+
if (propDef.attr) {
|
|
1186
|
+
return propDef.attr;
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
return propName.replace(/^_/, "").replace(/^[A-Z]/, l => l.toLowerCase()).replace(/[A-Z]/g, l => `-${l.toLowerCase()}`);
|
|
1190
|
+
}
|
|
1191
|
+
/**
|
|
1192
|
+
* Convert an attribute name to a property name.
|
|
1193
|
+
*/
|
|
1194
|
+
|
|
1195
|
+
|
|
1196
|
+
static _convertAttrNameToPropName(attrName) {
|
|
1197
|
+
for (let prop in this.allProperties) {
|
|
1198
|
+
if (this.allProperties[prop].attr === attrName) {
|
|
1199
|
+
return prop;
|
|
1200
|
+
}
|
|
1201
|
+
} // Convert the property name to kebab case
|
|
1202
|
+
|
|
1203
|
+
|
|
1204
|
+
const propName = attrName.replace(/-([A-Za-z])/g, l => l[1].toUpperCase());
|
|
1205
|
+
return propName;
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
_cascadeAttributes(selectors, set) {
|
|
1209
|
+
selectors.forEach(selector => {
|
|
1210
|
+
set[selector].forEach(attr => {
|
|
1211
|
+
this._cascadeAttribute(attr, selector);
|
|
1212
|
+
});
|
|
1213
|
+
});
|
|
1214
|
+
}
|
|
1215
|
+
/**
|
|
1216
|
+
* Trigger a cascade of the named attribute to any child elements that match
|
|
1217
|
+
* the `to` selector. The selector can match elements in the light DOM and
|
|
1218
|
+
* shadow DOM.
|
|
1219
|
+
* @param {String} name The name of the attribute to cascade (not necessarily the same as the property name).
|
|
1220
|
+
* @param {String} to A CSS selector that matches the elements that should received the cascaded attribute. The selector will be applied within `this` element's light and shadow DOM trees.
|
|
1221
|
+
*/
|
|
1222
|
+
|
|
1223
|
+
|
|
1224
|
+
_cascadeAttribute(name, to) {
|
|
1225
|
+
const recipients = [...this.querySelectorAll(to), ...this.shadowRoot.querySelectorAll(to)];
|
|
1226
|
+
|
|
1227
|
+
for (const node of recipients) {
|
|
1228
|
+
this._copyAttribute(name, node);
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
/**
|
|
1232
|
+
* Copy the named attribute to a target element.
|
|
1233
|
+
*/
|
|
1234
|
+
|
|
1235
|
+
|
|
1236
|
+
_copyAttribute(name, el) {
|
|
1237
|
+
this.log(`copying ${name} to ${el}`);
|
|
1238
|
+
const value = this.getAttribute(name);
|
|
1239
|
+
const fname = value == null ? "removeAttribute" : "setAttribute";
|
|
1240
|
+
el[fname](name, value);
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
static _convertSelectorsToArray(selectors) {
|
|
1244
|
+
if (selectors) {
|
|
1245
|
+
if (typeof selectors === "string") return selectors.split(",");else if (typeof selectors === "object") return selectors;else {
|
|
1246
|
+
this.warn(`selectors should be provided as a string, array, or object; received: ${typeof selectors}.`);
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
return;
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
static _parsePropertiesForCascade(mergedProperties) {
|
|
1254
|
+
let cascadingProperties = {}; // Parse the properties to pull out attributes that cascade
|
|
1255
|
+
|
|
1256
|
+
for (const [propName, config] of Object.entries(mergedProperties)) {
|
|
1257
|
+
let cascadeTo = this._convertSelectorsToArray(config.cascade); // Iterate over each node in the cascade list for this property
|
|
1258
|
+
|
|
1259
|
+
|
|
1260
|
+
if (cascadeTo) cascadeTo.map(nodeItem => {
|
|
1261
|
+
let attr = this._prop2attr(propName); // Create an object with the node as the key and an array of attributes
|
|
1262
|
+
// that are to be cascaded down to it
|
|
1263
|
+
|
|
1264
|
+
|
|
1265
|
+
if (!cascadingProperties[nodeItem]) cascadingProperties[nodeItem] = [attr];else cascadingProperties[nodeItem].push(attr);
|
|
1266
|
+
});
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
return cascadingProperties;
|
|
1270
|
+
}
|
|
1271
|
+
/**
|
|
1272
|
+
* Caching the attributes and properties data for efficiency
|
|
1273
|
+
*/
|
|
1274
|
+
|
|
1275
|
+
|
|
1276
|
+
static create(pfe) {
|
|
1277
|
+
pfe._createCache();
|
|
1278
|
+
|
|
1279
|
+
pfe._populateCache(pfe);
|
|
1280
|
+
|
|
1281
|
+
pfe._validateProperties();
|
|
1282
|
+
|
|
1283
|
+
try {
|
|
1284
|
+
window.customElements.define(pfe.tag, pfe);
|
|
1285
|
+
} catch (err) {
|
|
1286
|
+
// Capture the class currently using this tag in the registry
|
|
1287
|
+
const prevDefinition = window.customElements.get(pfe.tag); // Check if the previous definition's version matches this one
|
|
1288
|
+
|
|
1289
|
+
if (prevDefinition && prevDefinition.version !== pfe.version) {
|
|
1290
|
+
this.warn(`${pfe.tag} was registered at version ${prevDefinition.version}; cannot register version ${pfe.version}.`);
|
|
1291
|
+
} // @TODO Should this error be reported to the console?
|
|
1292
|
+
|
|
1293
|
+
|
|
1294
|
+
if (err && err.message) this.log(err.message);
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
if (PFElement.trackPerformance()) {
|
|
1298
|
+
try {
|
|
1299
|
+
performance.mark(`${this._markId}-defined`);
|
|
1300
|
+
} catch (err) {
|
|
1301
|
+
this.log(`Performance marks are not supported by this browser.`);
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
static _createCache() {
|
|
1307
|
+
this._cache = {
|
|
1308
|
+
properties: {},
|
|
1309
|
+
globalProperties: {},
|
|
1310
|
+
componentProperties: {},
|
|
1311
|
+
cascadingProperties: {},
|
|
1312
|
+
attr2prop: {},
|
|
1313
|
+
prop2attr: {}
|
|
1314
|
+
};
|
|
1315
|
+
}
|
|
1316
|
+
/**
|
|
1317
|
+
* Cache an object in a given cache namespace. This overwrites anything
|
|
1318
|
+
* already in that namespace.
|
|
1319
|
+
*/
|
|
1320
|
+
|
|
1321
|
+
|
|
1322
|
+
static _setCache(namespace, object) {
|
|
1323
|
+
this._cache[namespace] = object;
|
|
1324
|
+
}
|
|
1325
|
+
/**
|
|
1326
|
+
* Get a cached object by namespace, or get all cached objects.
|
|
1327
|
+
*/
|
|
1328
|
+
|
|
1329
|
+
|
|
1330
|
+
static _getCache(namespace) {
|
|
1331
|
+
return namespace ? this._cache[namespace] : this._cache;
|
|
1332
|
+
}
|
|
1333
|
+
/**
|
|
1334
|
+
* Populate initial values for properties cache.
|
|
1335
|
+
*/
|
|
1336
|
+
|
|
1337
|
+
|
|
1338
|
+
static _populateCache(pfe) {
|
|
1339
|
+
// @TODO add a warning when a component property conflicts with a global property.
|
|
1340
|
+
const mergedProperties = _extends({}, pfe.properties, PFElement.properties);
|
|
1341
|
+
|
|
1342
|
+
pfe._setCache("componentProperties", pfe.properties);
|
|
1343
|
+
|
|
1344
|
+
pfe._setCache("globalProperties", PFElement.properties);
|
|
1345
|
+
|
|
1346
|
+
pfe._setCache("properties", mergedProperties); // create mapping objects to go from prop name to attrname and back
|
|
1347
|
+
|
|
1348
|
+
|
|
1349
|
+
const prop2attr = {};
|
|
1350
|
+
const attr2prop = {};
|
|
1351
|
+
|
|
1352
|
+
for (let propName in mergedProperties) {
|
|
1353
|
+
const attrName = this._convertPropNameToAttrName(propName);
|
|
1354
|
+
|
|
1355
|
+
prop2attr[propName] = attrName;
|
|
1356
|
+
attr2prop[attrName] = propName;
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
pfe._setCache("attr2prop", attr2prop);
|
|
1360
|
+
|
|
1361
|
+
pfe._setCache("prop2attr", prop2attr);
|
|
1362
|
+
|
|
1363
|
+
const cascadingProperties = this._parsePropertiesForCascade(mergedProperties);
|
|
1364
|
+
|
|
1365
|
+
if (Object.keys(cascadingProperties)) pfe._setCache("cascadingProperties", cascadingProperties);
|
|
1366
|
+
}
|
|
1367
|
+
/**
|
|
1368
|
+
* allProperties returns an object containing PFElement's global properties
|
|
1369
|
+
* and the descendents' (such as PfeCard, etc) component properties. The two
|
|
1370
|
+
* objects are merged together and in the case of a property name conflict,
|
|
1371
|
+
* PFElement's properties override the component's properties.
|
|
1372
|
+
*/
|
|
1373
|
+
|
|
1374
|
+
|
|
1375
|
+
static get allProperties() {
|
|
1376
|
+
return this._getCache("properties");
|
|
1377
|
+
}
|
|
1378
|
+
/**
|
|
1379
|
+
* cascadingProperties returns an object containing PFElement's global properties
|
|
1380
|
+
* and the descendents' (such as PfeCard, etc) component properties. The two
|
|
1381
|
+
* objects are merged together and in the case of a property name conflict,
|
|
1382
|
+
* PFElement's properties override the component's properties.
|
|
1383
|
+
*/
|
|
1384
|
+
|
|
1385
|
+
|
|
1386
|
+
static get cascadingProperties() {
|
|
1387
|
+
return this._getCache("cascadingProperties");
|
|
1388
|
+
}
|
|
1389
|
+
/**
|
|
1390
|
+
* Breakpoint object mapping human-readable size names to viewport sizes
|
|
1391
|
+
* To overwrite this at the component-level, include `static get breakpoint` in your component's class definition
|
|
1392
|
+
* @returns {Object} keys are t-shirt sizes and values map to screen-sizes (sourced from PF4)
|
|
1393
|
+
*/
|
|
1394
|
+
|
|
1395
|
+
|
|
1396
|
+
static get breakpoint() {
|
|
1397
|
+
return {
|
|
1398
|
+
xs: "0px",
|
|
1399
|
+
// $pf-global--breakpoint--xs: 0 !default;
|
|
1400
|
+
sm: "576px",
|
|
1401
|
+
// $pf-global--breakpoint--sm: 576px !default;
|
|
1402
|
+
md: "768px",
|
|
1403
|
+
// $pf-global--breakpoint--md: 768px !default;
|
|
1404
|
+
lg: "992px",
|
|
1405
|
+
// $pf-global--breakpoint--lg: 992px !default;
|
|
1406
|
+
xl: "1200px",
|
|
1407
|
+
// $pf-global--breakpoint--xl: 1200px !default;
|
|
1408
|
+
"2xl": "1450px" // $pf-global--breakpoint--2xl: 1450px !default;
|
|
1409
|
+
|
|
1410
|
+
};
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
} // Initialize the global instances
|
|
1414
|
+
|
|
1415
|
+
|
|
1416
|
+
PFElement.allInstances = [];
|
|
1417
|
+
autoReveal(PFElement.log);
|
|
1418
|
+
|
|
1419
|
+
// https://tc39.github.io/ecma262/#sec-array.prototype.findIndex
|
|
1420
|
+
|
|
1421
|
+
if (!Array.prototype.findIndex) {
|
|
1422
|
+
Object.defineProperty(Array.prototype, "findIndex", {
|
|
1423
|
+
value: function (predicate) {
|
|
1424
|
+
// 1. Let O be ? ToObject(this value).
|
|
1425
|
+
if (this == null) {
|
|
1426
|
+
throw new TypeError('"this" is null or not defined');
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
var o = Object(this); // 2. Let len be ? ToLength(? Get(O, "length")).
|
|
1430
|
+
|
|
1431
|
+
var len = o.length >>> 0; // 3. If IsCallable(predicate) is false, throw a TypeError exception.
|
|
1432
|
+
|
|
1433
|
+
if (typeof predicate !== "function") {
|
|
1434
|
+
throw new TypeError("predicate must be a function");
|
|
1435
|
+
} // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
|
|
1436
|
+
|
|
1437
|
+
|
|
1438
|
+
var thisArg = arguments[1]; // 5. Let k be 0.
|
|
1439
|
+
|
|
1440
|
+
var k = 0; // 6. Repeat, while k < len
|
|
1441
|
+
|
|
1442
|
+
while (k < len) {
|
|
1443
|
+
// a. Let Pk be ! ToString(k).
|
|
1444
|
+
// b. Let kValue be ? Get(O, Pk).
|
|
1445
|
+
// c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
|
|
1446
|
+
// d. If testResult is true, return k.
|
|
1447
|
+
var kValue = o[k];
|
|
1448
|
+
|
|
1449
|
+
if (predicate.call(thisArg, kValue, k, o)) {
|
|
1450
|
+
return k;
|
|
1451
|
+
} // e. Increase k by 1.
|
|
1452
|
+
|
|
1453
|
+
|
|
1454
|
+
k++;
|
|
1455
|
+
} // 7. Return -1.
|
|
1456
|
+
|
|
1457
|
+
|
|
1458
|
+
return -1;
|
|
1459
|
+
},
|
|
1460
|
+
configurable: true,
|
|
1461
|
+
writable: true
|
|
1462
|
+
});
|
|
1463
|
+
}
|
|
1464
|
+
/*!
|
|
1465
|
+
* PatternFly Elements: PfeTabs 1.12.3
|
|
1466
|
+
* @license
|
|
1467
|
+
* Copyright 2021 Red Hat, Inc.
|
|
1468
|
+
*
|
|
1469
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
1470
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
1471
|
+
* in the Software without restriction, including without limitation the rights
|
|
1472
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
1473
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
1474
|
+
* furnished to do so, subject to the following conditions:
|
|
1475
|
+
*
|
|
1476
|
+
* The above copyright notice and this permission notice shall be included in
|
|
1477
|
+
* all copies or substantial portions of the Software.
|
|
1478
|
+
*
|
|
1479
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
1480
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
1481
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
1482
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
1483
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
1484
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
1485
|
+
* SOFTWARE.
|
|
1486
|
+
*
|
|
1487
|
+
*/
|
|
1488
|
+
|
|
1489
|
+
|
|
1490
|
+
const TAB_CONTENT_MUTATION_CONFIG = {
|
|
1491
|
+
characterData: true,
|
|
1492
|
+
childList: true,
|
|
1493
|
+
subtree: true
|
|
1494
|
+
};
|
|
1495
|
+
|
|
1496
|
+
class PfeTab extends PFElement {
|
|
1497
|
+
// Injected at build-time
|
|
1498
|
+
static get version() {
|
|
1499
|
+
return "1.12.3";
|
|
1500
|
+
} // Injected at build-time
|
|
1501
|
+
|
|
1502
|
+
|
|
1503
|
+
get html() {
|
|
1504
|
+
return `
|
|
1505
|
+
<style>:host{text-align:left;position:relative;display:block;cursor:pointer;margin:0 0 calc(1px * -1);margin:var(--pfe-tabs__tab--Margin,0 0 calc(var(--pfe-theme--ui--border-width,1px) * -1));padding:1rem calc(1rem * 2) 1rem calc(1rem * 2);padding:var(--pfe-tabs__tab--PaddingTop,var(--pfe-theme--container-padding,1rem)) var(--pfe-tabs__tab--PaddingRight,calc(var(--pfe-theme--container-padding,1rem) * 2)) var(--pfe-tabs__tab--PaddingBottom,var(--pfe-theme--container-padding,1rem)) var(--pfe-tabs__tab--PaddingLeft,calc(var(--pfe-theme--container-padding,1rem) * 2));border-style:solid;border-style:var(--pfe-theme--ui--border-style,solid);border-width:1px;border-width:var(--pfe-theme--ui--border-width,1px);border-color:transparent;border-bottom-width:3px;border-bottom-width:var(--pfe-tabs--BorderWidth,var(--pfe-theme--ui--border-width--active,3px));background-color:none;background-color:var(--pfe-tabs--BackgroundColor--inactive,none);text-align:center;text-align:var(--pfe-tabs__tab--TextAlign,center);text-transform:none;text-transform:var(--pfe-tabs__tab--TextTransform,none);color:#6a6e73;color:var(--pfe-tabs--Color,var(--pfe-theme--color--text--muted,#6a6e73));font-size:1rem;font-size:var(--pfe-tabs__tab--FontSize,var(--pf-global--FontSize--md,1rem));font-family:"Red Hat Text",RedHatText,Overpass,Overpass,Arial,sans-serif;font-family:var(--pfe-tabs__tab--LineHeight, var(--pfe-theme--font-family, "Red Hat Text", "RedHatText", "Overpass", Overpass, Arial, sans-serif));line-height:1.5;line-height:var(--pfe-tabs__tab--LineHeight,var(--pfe-theme--line-height,1.5));font-weight:400;font-weight:var(--pfe-tabs__tab--FontWeight,var(--pfe-theme--font-weight--normal,400));--pf-c--FontSize:var(--pfe-tabs--FontSize)}:host #tab{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;height:100%}:host #tab *{font-size:inherit;font-weight:inherit;color:inherit;margin:0}:host([aria-selected=true]){background-color:transparent;background-color:var(--pfe-tabs--BackgroundColor,transparent);border-bottom-color:#06c;border-bottom-color:var(--pfe-tabs--BorderColor,var(--pfe-tabs--highlight,var(--pfe-theme--color--ui-accent,#06c)))}:host([aria-selected=true]) #tab *{color:#151515;color:var(--pfe-tabs--Color--focus,var(--pfe-tabs--focus,var(--pfe-theme--color--text,#151515)))}:host(:active),:host(:hover){background-color:transparent;background-color:var(--pfe-tabs--BackgroundColor,transparent);border-bottom-color:#b8bbbe;border-bottom-color:var(--pfe-tabs--BorderColor--hover,#b8bbbe)}:host(:active) #tab *,:host(:hover) #tab *{color:#151515;color:var(--pfe-tabs--Color--focus,var(--pfe-tabs--focus,var(--pfe-theme--color--text,#151515)))}@media screen and (min-width:768px){:host([vertical]){border-bottom-color:transparent;border-bottom-width:0;border-left-color:#d2d2d2;border-left-color:var(--pfe-theme--color--surface--border,#d2d2d2);border-left-width:1px;border-left-width:var(--pfe-theme--ui--border-width,1px);padding:1rem;padding:var(--pfe-theme--container-padding,1rem);--pfe-tabs--Margin:0 calc(var(--pfe-theme--ui--border-width, 1px) * -1) 0 0}:host([vertical][aria-selected=true]){border-left-color:#06c;border-left-color:var(--pfe-tabs--BorderColor,var(--pfe-tabs--highlight,var(--pfe-theme--color--ui-accent,#06c)));border-left-width:3px}:host([vertical]:not([variant=earth])){border-left:1px solid #d2d2d2;border-left:var(--pfe-theme--ui--border-width,1px) var(--pfe-theme--ui--border-style,solid) var(--pfe-theme--color--surface--border,#d2d2d2);text-align:left!important}:host([vertical]:not([variant=earth])[aria-selected=true]){border-right:3px solid transparent;border-right:var(--pfe-tabs--BorderWidth,var(--pfe-theme--ui--border-width--active,3px)) var(--pfe-theme--ui--border-style,solid) transparent;border-left:3px solid #06c;border-left:var(--pfe-tabs--BorderWidth,var(--pfe-theme--ui--border-width--active,3px)) var(--pfe-theme--ui--border-style,solid) var(--pfe-tabs--BorderColor,var(--pfe-tabs--highlight,var(--pfe-theme--color--ui-accent,#06c)));padding-left:calc(1rem - 2px);padding-left:calc(var(--pfe-theme--container-padding,1rem) - 2px)}:host([vertical]:not([variant=earth])[aria-selected=false]){border-right:3px solid transparent;border-right:var(--pfe-tabs--BorderWidth,var(--pfe-theme--ui--border-width--active,3px)) var(--pfe-theme--ui--border-style,solid) transparent}:host([vertical]:not([variant=earth])[aria-selected=false]:hover){border-right:3px solid transparent;border-right:var(--pfe-tabs--BorderWidth,var(--pfe-theme--ui--border-width--active,3px)) var(--pfe-theme--ui--border-style,solid) transparent;border-bottom:0;border-left:3px solid #b8bbbe;border-left:var(--pfe-tabs--BorderWidth,var(--pfe-theme--ui--border-width--active,3px)) var(--pfe-theme--ui--border-style,solid) var(--pfe-tabs--BorderColor--hover,#b8bbbe);padding-left:calc(1rem - 2px);padding-left:calc(var(--pfe-theme--container-padding,1rem) - 2px)}}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host([variant=earth]){background-color:#f0f0f0;color:#6a6e73}}:host(:not([vertical])[variant=earth]:not([aria-selected=true]):first-of-type){border-left-color:transparent}:host(:not([vertical])[variant=earth]:not([aria-selected=true]):last-of-type){border-right-color:transparent}:host([variant=earth][aria-selected=false]){background-color:#f0f0f0;background-color:var(--pfe-tabs--BackgroundColor--inactive,var(--pfe-theme--color--surface--lighter,#f0f0f0));border-color:#d2d2d2;border-color:var(--pfe-theme--color--surface--border,#d2d2d2);border-top-width:3px;border-top-width:var(--pfe-tabs--BorderWidth,var(--pfe-theme--ui--border-width--active,3px));border-top-color:transparent;border-bottom-color:#b8bbbe;border-bottom-color:var(--pfe-tabs--BorderColor--hover,#b8bbbe);border-bottom-width:1px;border-bottom-width:var(--pfe-theme--ui--border-width,1px)}:host([variant=earth][aria-selected=false]:hover){border-top-color:#b8bbbe;border-top-color:var(--pfe-tabs--BorderColor--hover,#b8bbbe)}:host([variant=earth][aria-selected=true]){background-color:#fff;background-color:var(--pfe-tabs--BackgroundColor,var(--pfe-theme--color--surface--lightest,#fff));border-bottom:0;border-left-color:#d2d2d2;border-left-color:var(--pfe-theme--color--surface--border,#d2d2d2);border-right-color:#d2d2d2;border-right-color:var(--pfe-theme--color--surface--border,#d2d2d2);border-top:solid #06c 3px;border-top:solid var(--pfe-tabs--BorderColor,var(--pfe-tabs--highlight,var(--pfe-theme--color--ui-accent,#06c))) var(--pfe-tabs--BorderWidth,var(--pfe-theme--ui--border-width--active,3px))}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host([variant=earth][aria-selected=true]){color:#6a6e73;background-color:#fff;border-left:1px solid #d2d2d2;border-top:3px solid #06c;border-top:var(--pfe-tabs--BorderWidth,var(--pfe-theme--ui--border-width--active,3px)) solid var(--pfe-tabs--BorderColor,var(--pfe-tabs--highlight,var(--pfe-theme--color--ui-accent,#06c)));border-bottom:0}}:host([variant=earth][aria-selected=true]:last-of-type){border-right:1px solid #d2d2d2;border-right:var(--pfe-theme--ui--border-width,1px) var(--pfe-theme--ui--border-style,solid) var(--pfe-theme--color--surface--border,#d2d2d2)}@media screen and (min-width:768px){:host([vertical][variant=earth]){border-top:1px solid #d2d2d2;border-top:var(--pfe-theme--ui--border-width,1px) var(--pfe-theme--ui--border-style,solid) var(--pfe-theme--color--surface--border,#d2d2d2);border-bottom:1px solid #d2d2d2;border-bottom:var(--pfe-theme--ui--border-width,1px) var(--pfe-theme--ui--border-style,solid) var(--pfe-theme--color--surface--border,#d2d2d2);border-left-width:3px;border-left-width:var(--pfe-theme--ui--border-width--active,3px);text-align:left}:host([vertical][variant=earth][aria-selected=false]:first-of-type){border-top-color:transparent;border-left:3px solid transparent;border-left:var(--pfe-tabs--BorderWidth,var(--pfe-theme--ui--border-width--active,3px)) var(--pfe-theme--ui--border-style,solid) transparent}:host([vertical][variant=earth][aria-selected=false]:last-of-type){border-bottom-color:transparent}:host([vertical][variant=earth][aria-selected=false]){border-right:0;border-bottom-color:transparent;border-left-color:transparent}:host([vertical][variant=earth][aria-selected=false]:hover){border-left-color:#b8bbbe;border-left-color:var(--pfe-tabs--BorderColor--hover,#b8bbbe);border-top-color:#d2d2d2;border-top-color:var(--pfe-theme--color--surface--border,#d2d2d2)}:host([vertical][variant=earth][aria-selected=false]:first-of-type:hover){border-left-color:#d2d2d2;border-left-color:var(--pfe-theme--color--surface--border,#d2d2d2);border-top-color:transparent}:host([vertical][variant=earth][aria-selected=true]){border-top-color:#d2d2d2;border-top-color:var(--pfe-theme--color--surface--border,#d2d2d2);border-left-color:#06c;border-left-color:var(--pfe-tabs--BorderColor,var(--pfe-tabs--highlight,var(--pfe-theme--color--ui-accent,#06c)));border-right-color:transparent;margin-right:-1px}}:host([on=dark][variant=earth]){--pfe-tabs--Color:var(--pfe-theme--color--text--on-dark, #fff);--pfe-tabs--Color--focus:var(--pfe-theme--color--text--on-dark, #fff);border-right-color:#6a6e73;border-right-color:var(--pfe-theme--color--surface--border--darker,#6a6e73);border-left-color:#6a6e73;border-left-color:var(--pfe-theme--color--surface--border--darker,#6a6e73)}:host([on=dark][variant=earth][aria-selected=false]){--pfe-tabs--Color:var(--pfe-theme--color--text--muted--on-dark, #d2d2d2);--pfe-tabs--BackgroundColor--inactive:var(--pfe-theme--color--surface--darker, #3c3f42)}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host([on=dark][variant=earth][aria-selected=false]){background-color:#fff!important;background-color:var(--pfe-theme--color--surface--lightest,#fff)!important}:host([on=dark][variant=earth][aria-selected=false]) #tab *{color:#151515!important}}:host([on=dark][variant=earth][aria-selected=true]){--pfe-tabs--Color--focus:var(--pfe-theme--color--text--on-dark, #fff);--pfe-tabs--BackgroundColor:var(--pfe-theme--color--surface--darkest, #151515)}:host([variant=earth][on=saturated][aria-selected=false]){--pfe-tabs--BackgroundColor:var(--pfe-theme--color--surface--lighter, #f0f0f0)}:host([variant=earth][on=saturated][aria-selected=true]){--pfe-tabs--BackgroundColor:var(--pfe-theme--color--surface--lightest, #fff)}:host([on=saturated]:not([variant=earth])){--pfe-tabs--Color:var(--pfe-theme--color--text--on-saturated, #fff);--pfe-tabs--Color--focus:var(--pfe-theme--color--text--on-saturated, #fff)}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host([on=saturated]:not([variant=earth])){background-color:transparent}:host([on=saturated]:not([variant=earth])) #tab *{color:#151515!important}}:host([on=saturated]:not([variant=earth])[aria-selected=true]){--pfe-tabs--Color--focus:var(--pfe-theme--color--text--on-saturated, #fff);--pfe-tabs--BorderColor:var(--pfe-theme--color--ui-base--on-saturated, #fff)}:host([on=saturated]:not([variant=earth])[aria-selected=false]){--pfe-tabs--Color:var(--pfe-theme--color--text--muted--on-saturated, #d2d2d2)}:host([on=saturated]:not([variant=earth])[aria-selected=false]:hover){--pfe-tabs--BorderColor:var(--pfe-theme--color--surface--border, #d2d2d2)}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host([on=saturated]:not([variant=earth])[aria-selected=true]:last-of-type){border-left:0!important}}:host([on=dark]:not([variant=earth])){--pfe-tabs--Color:var(--pfe-theme--color--text--on-dark, #fff);--pfe-tabs--Color--focus:var(--pfe-theme--color--text--on-dark, #fff)}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host([on=dark]:not([variant=earth])) #tab *{color:#151515!important}}:host([on=dark]:not([variant=earth])[aria-selected=false]){--pfe-tabs--Color:var(--pfe-theme--color--text--muted--on-saturated, #d2d2d2)}:host([on=dark]:not([variant=earth])[aria-selected=false]:hover){--pfe-tabs--BorderColor:var(--pfe-theme--color--surface--lightest, #fff);border-bottom-color:#f0f0f0;border-bottom-color:var(--pfe-theme--color--surface--base,#f0f0f0);--pfe-tabs__tab--BorderBottom:var(--pfe-tabs--BorderWidth, var(--pfe-theme--ui--border-width--active, 3px)) var(--pfe-theme--ui--border-style, solid) var(--pfe-theme--color--surface--border, #d2d2d2)}:host([on=dark]:not([variant=earth])[vertical][aria-selected=false]:hover){border-bottom-color:transparent} /*# sourceMappingURL=pfe-tab.min.css.map */</style>
|
|
1506
|
+
<span id="tab"></span>`;
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
static get tag() {
|
|
1510
|
+
return "pfe-tab";
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
get styleUrl() {
|
|
1514
|
+
return "pfe-tab.scss";
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
get templateUrl() {
|
|
1518
|
+
return "pfe-tab.html";
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1521
|
+
static get properties() {
|
|
1522
|
+
return {
|
|
1523
|
+
selected: {
|
|
1524
|
+
title: "Selected tab",
|
|
1525
|
+
type: String,
|
|
1526
|
+
default: "false",
|
|
1527
|
+
attr: "aria-selected",
|
|
1528
|
+
values: ["true", "false"],
|
|
1529
|
+
observer: "_selectedHandler"
|
|
1530
|
+
},
|
|
1531
|
+
controls: {
|
|
1532
|
+
title: "Connected panel ID",
|
|
1533
|
+
type: String,
|
|
1534
|
+
attr: "aria-controls"
|
|
1535
|
+
},
|
|
1536
|
+
role: {
|
|
1537
|
+
type: String,
|
|
1538
|
+
default: "tab"
|
|
1539
|
+
},
|
|
1540
|
+
tabindex: {
|
|
1541
|
+
type: Number,
|
|
1542
|
+
default: -1
|
|
1543
|
+
},
|
|
1544
|
+
variant: {
|
|
1545
|
+
title: "Variant",
|
|
1546
|
+
type: String,
|
|
1547
|
+
enum: ["wind", "earth"]
|
|
1548
|
+
},
|
|
1549
|
+
// @TODO: Deprecated in 1.0
|
|
1550
|
+
oldPfeId: {
|
|
1551
|
+
type: String,
|
|
1552
|
+
attr: "pfe-id",
|
|
1553
|
+
observer: "_oldPfeIdChanged"
|
|
1554
|
+
}
|
|
1555
|
+
};
|
|
1556
|
+
} // Declare the type of this component
|
|
1557
|
+
|
|
1558
|
+
|
|
1559
|
+
static get PfeType() {
|
|
1560
|
+
return PFElement.PfeTypes.Content;
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
constructor() {
|
|
1564
|
+
super(PfeTab, {
|
|
1565
|
+
type: PfeTab.PfeType
|
|
1566
|
+
});
|
|
1567
|
+
this._init = this._init.bind(this);
|
|
1568
|
+
this._setTabContent = this._setTabContent.bind(this);
|
|
1569
|
+
this._getTabElement = this._getTabElement.bind(this);
|
|
1570
|
+
this._observer = new MutationObserver(this._init);
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
connectedCallback() {
|
|
1574
|
+
super.connectedCallback();
|
|
1575
|
+
this._tabItem = this.shadowRoot.querySelector(`#tab`);
|
|
1576
|
+
if (this.hasLightDOM()) this._init();
|
|
1577
|
+
|
|
1578
|
+
this._observer.observe(this, TAB_CONTENT_MUTATION_CONFIG);
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
disconnectedCallback() {
|
|
1582
|
+
super.disconnectedCallback();
|
|
1583
|
+
|
|
1584
|
+
this._observer.disconnect();
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
_selectedHandler() {
|
|
1588
|
+
if (this.selected === "true") this.tabindex = 0;else this.tabindex = -1;
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
_oldPfeIdChanged(oldVal, newVal) {
|
|
1592
|
+
if (!this.id) this.id = newVal;
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
_init() {
|
|
1596
|
+
if (window.ShadyCSS) this._observer.disconnect(); // Force role to be set to tab
|
|
1597
|
+
|
|
1598
|
+
this.role = "tab"; // Copy the tab content into the template
|
|
1599
|
+
|
|
1600
|
+
this._setTabContent(); // If an ID is not defined, generate a random one
|
|
1601
|
+
|
|
1602
|
+
|
|
1603
|
+
if (!this.id) this.id = this.randomId;
|
|
1604
|
+
if (window.ShadyCSS) this._observer.observe(this, TAB_CONTENT_MUTATION_CONFIG);
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
_getTabElement() {
|
|
1608
|
+
// Check if there is no nested element or nested textNodes
|
|
1609
|
+
if (!this.firstElementChild && !this.firstChild) {
|
|
1610
|
+
this.warn(`No tab content provided`);
|
|
1611
|
+
return;
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
if (this.firstElementChild && this.firstElementChild.tagName) {
|
|
1615
|
+
// If the first element is a slot, query for it's content
|
|
1616
|
+
if (this.firstElementChild.tagName === "SLOT") {
|
|
1617
|
+
const slotted = this.firstElementChild.assignedNodes(); // If there is no content inside the slot, return empty with a warning
|
|
1618
|
+
|
|
1619
|
+
if (slotted.length === 0) {
|
|
1620
|
+
this.warn(`No heading information exists within this slot.`);
|
|
1621
|
+
return;
|
|
1622
|
+
} // If there is more than 1 element in the slot, capture the first h-tag
|
|
1623
|
+
|
|
1624
|
+
|
|
1625
|
+
if (slotted.length > 1) this.warn(`Tab heading currently only supports 1 heading tag.`);
|
|
1626
|
+
const htags = slotted.filter(slot => slot.tagName.match(/^H[1-6]/) || slot.tagName === "P");
|
|
1627
|
+
if (htags.length > 0) return htags[0];else return;
|
|
1628
|
+
} else if (this.firstElementChild.tagName.match(/^H[1-6]/) || this.firstElementChild.tagName === "P") {
|
|
1629
|
+
return this.firstElementChild;
|
|
1630
|
+
} else {
|
|
1631
|
+
this.warn(`Tab heading should contain at least 1 heading tag for correct semantics.`);
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
return;
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
_setTabContent() {
|
|
1639
|
+
let label = "";
|
|
1640
|
+
let isTag = false;
|
|
1641
|
+
|
|
1642
|
+
let tabElement = this._getTabElement();
|
|
1643
|
+
|
|
1644
|
+
if (tabElement) {
|
|
1645
|
+
// Copy the tab content into the template
|
|
1646
|
+
label = tabElement.textContent.trim().replace(/\s+/g, " ");
|
|
1647
|
+
isTag = true;
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1650
|
+
if (!tabElement) {
|
|
1651
|
+
// If no element is found, try for a text node
|
|
1652
|
+
if (this.textContent.trim().replace(/\s+/g, " ")) {
|
|
1653
|
+
label = this.textContent.trim().replace(/\s+/g, " ");
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1657
|
+
if (!label) {
|
|
1658
|
+
this.warn(`There does not appear to be any content in the tab region.`);
|
|
1659
|
+
return;
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1662
|
+
let semantics = "h3";
|
|
1663
|
+
|
|
1664
|
+
if (isTag) {
|
|
1665
|
+
semantics = tabElement.tagName.toLowerCase();
|
|
1666
|
+
} // Create an h-level tag for the shadow tab, default h3
|
|
1667
|
+
// or use the provided semantics from light DOM
|
|
1668
|
+
|
|
1669
|
+
|
|
1670
|
+
let heading = document.createElement(semantics); // Assign the label content to the new heading
|
|
1671
|
+
|
|
1672
|
+
heading.textContent = label; // Attach the heading to the tabItem
|
|
1673
|
+
|
|
1674
|
+
if (this._tabItem) {
|
|
1675
|
+
this._tabItem.innerHTML = "";
|
|
1676
|
+
|
|
1677
|
+
this._tabItem.appendChild(heading);
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
|
|
1681
|
+
}
|
|
1682
|
+
/*!
|
|
1683
|
+
* PatternFly Elements: PfeTabs 1.12.3
|
|
1684
|
+
* @license
|
|
1685
|
+
* Copyright 2021 Red Hat, Inc.
|
|
1686
|
+
*
|
|
1687
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
1688
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
1689
|
+
* in the Software without restriction, including without limitation the rights
|
|
1690
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
1691
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
1692
|
+
* furnished to do so, subject to the following conditions:
|
|
1693
|
+
*
|
|
1694
|
+
* The above copyright notice and this permission notice shall be included in
|
|
1695
|
+
* all copies or substantial portions of the Software.
|
|
1696
|
+
*
|
|
1697
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
1698
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
1699
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
1700
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
1701
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
1702
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
1703
|
+
* SOFTWARE.
|
|
1704
|
+
*
|
|
1705
|
+
*/
|
|
1706
|
+
|
|
1707
|
+
|
|
1708
|
+
const TAB_PANEL_MUTATION_CONFIG = {
|
|
1709
|
+
childList: true,
|
|
1710
|
+
subtree: true
|
|
1711
|
+
};
|
|
1712
|
+
|
|
1713
|
+
class PfeTabPanel extends PFElement {
|
|
1714
|
+
// Injected at build-time
|
|
1715
|
+
static get version() {
|
|
1716
|
+
return "1.12.3";
|
|
1717
|
+
} // Injected at build-time
|
|
1718
|
+
|
|
1719
|
+
|
|
1720
|
+
get html() {
|
|
1721
|
+
return `
|
|
1722
|
+
<style>:host{display:block;color:#3c3f42;color:var(--pfe-broadcasted--text,#3c3f42)}:host(:focus){outline:0}:host [tabindex]{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;height:100%}:host .container{margin:0;width:100%;background-color:transparent;background-color:var(--pfe-tabs__panel--BackgroundColor,transparent);border-top:0;border-top:var(--pfe-tabs__panel--BorderTop,0);border-right:0;border-right:var(--pfe-tabs__panel--BorderRight,0);border-bottom:0;border-bottom:var(--pfe-tabs__panel--BorderBottom,0);border-left:0;border-left:var(--pfe-tabs__panel--BorderLeft,0);padding-top:calc(1rem * 3);padding-top:var(--pfe-tabs__panel--PaddingTop,calc(var(--pfe-theme--container-padding,1rem) * 3))}@media screen and (min-width:1200px){:host .container{padding-top:calc(1rem * 3);padding-top:var(--pfe-tabs__panel--PaddingTop,calc(var(--pfe-theme--container-padding,1rem) * 3));padding-right:0;padding-right:var(--pfe-tabs__panel--PaddingRight,0);padding-bottom:0;padding-bottom:var(--pfe-tabs__panel--PaddingBottom,0);padding-left:0;padding-left:var(--pfe-tabs__panel--PaddingLeft,0)}}:host .container::after{clear:both;content:"";display:table}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host .container{padding:1em;background-color:#fff!important;color:#151515!important}}:host([hidden]){display:none}:host([variant=earth]){background-color:#fff;background-color:var(--pfe-tabs__panel--BackgroundColor,var(--pfe-theme--color--surface--lightest,#fff))}:host([variant=earth]) .container{padding-top:calc(1rem * 3);padding-top:var(--pfe-tabs__panel--PaddingTop,calc(var(--pfe-theme--container-padding,1rem) * 3));padding-right:calc(1rem * 3);padding-right:var(--pfe-tabs__panel--PaddingRight,calc(var(--pfe-theme--container-padding,1rem) * 3));padding-bottom:calc(1rem * 3);padding-bottom:var(--pfe-tabs__panel--PaddingBottom,calc(var(--pfe-theme--container-padding,1rem) * 3));padding-left:calc(1rem * 3);padding-left:var(--pfe-tabs__panel--PaddingLeft,calc(var(--pfe-theme--container-padding,1rem) * 3))}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host([variant=earth]) .container{background-color:#fff;padding:1em;border-right:1px solid #d2d2d2;border-bottom:1px solid #d2d2d2;border-left:1px solid #d2d2d2}}@media screen and (min-width:768px){:host([variant=wind][vertical]) .container{padding-top:0;padding-top:var(--pfe-tabs__panel--PaddingTop,0);padding-bottom:0;padding-bottom:var(--pfe-tabs__panel--PaddingBottom,0);padding-right:0;padding-right:var(--pfe-tabs__panel--PaddingRight,0);margin:0 calc(1rem - 2px);margin:0 calc(var(--pfe-theme--container-spacer,1rem) - 2px)}}@media screen and (min-width:768px) and (-ms-high-contrast:active),screen and (min-width:768px) and (-ms-high-contrast:none){:host([variant=wind][vertical]) .container{padding:1em 0 1em 2em}}@media screen and (min-width:768px){:host([variant=earth][vertical]){border-top:0;border-top:var(--pfe-tabs--BorderTop,0);border-left:1px solid #d2d2d2;border-left:var(--pfe-tabs--BorderLeft,var(--pfe-theme--ui--border-width,1px) var(--pfe-theme--ui--border-style,solid) var(--pfe-theme--color--surface--border,#d2d2d2));height:100%;background-color:#fff;background-color:var(--pfe-tabs__panel--BackgroundColor,var(--pfe-theme--color--surface--lightest,#fff))}:host([variant=earth][vertical]) .container{padding-left:calc(1rem * 3);padding-left:var(--pfe-tabs__panel--PaddingLeft,calc(var(--pfe-theme--container-padding,1rem) * 3))}}@media screen and (min-width:768px) and (-ms-high-contrast:active),screen and (min-width:768px) and (-ms-high-contrast:none){:host([variant=earth][vertical]) .container{border-top:1px solid #d2d2d2}}:host([variant=earth]) .container{padding-top:calc(1rem * 3);padding-top:var(--pfe-tabs__panel--PaddingTop,calc(var(--pfe-theme--container-padding,1rem) * 3));padding-right:calc(1rem * 3);padding-right:var(--pfe-tabs__panel--PaddingRight,calc(var(--pfe-theme--container-padding,1rem) * 3));padding-bottom:calc(1rem * 3);padding-bottom:var(--pfe-tabs__panel--PaddingBottom,calc(var(--pfe-theme--container-padding,1rem) * 3));padding-left:calc(1rem * 3);padding-left:var(--pfe-tabs__panel--PaddingLeft,calc(var(--pfe-theme--container-padding,1rem) * 3))}:host([on=dark][variant=earth]){background-color:#151515;background-color:var(--pfe-tabs__panel--BackgroundColor,var(--pfe-theme--color--surface--darkest,#151515));--pfe-broadcasted--text:var(--pfe-theme--color--text--on-dark, #fff);--pfe-broadcasted--text--muted:var(--pfe-theme--color--text--muted--on-dark, #d2d2d2);--pfe-broadcasted--link:var(--pfe-theme--color--link--on-dark, #73bcf7);--pfe-broadcasted--link--hover:var(--pfe-theme--color--link--hover--on-dark, #bee1f4);--pfe-broadcasted--link--focus:var(--pfe-theme--color--link--focus--on-dark, #bee1f4);--pfe-broadcasted--link--visited:var(--pfe-theme--color--link--visited--on-dark, #bee1f4);--pfe-broadcasted--link-decoration:var(--pfe-theme--link-decoration--on-dark, none);--pfe-broadcasted--link-decoration--hover:var(--pfe-theme--link-decoration--hover--on-dark, underline);--pfe-broadcasted--link-decoration--focus:var(--pfe-theme--link-decoration--focus--on-dark, underline);--pfe-broadcasted--link-decoration--visited:var(--pfe-theme--link-decoration--visited--on-dark, none)}:host([on=saturated][variant=earth]){background-color:#fff;background-color:var(--pfe-tabs__panel--BackgroundColor,var(--pfe-theme--color--surface--lightest,#fff));--pfe-broadcasted--text:var(--pfe-theme--color--text, #151515);--pfe-broadcasted--text--muted:var(--pfe-theme--color--text--muted, #6a6e73);--pfe-broadcasted--link:var(--pfe-theme--color--link, #06c);--pfe-broadcasted--link--hover:var(--pfe-theme--color--link--hover, #004080);--pfe-broadcasted--link--focus:var(--pfe-theme--color--link--focus, #004080);--pfe-broadcasted--link--visited:var(--pfe-theme--color--link--visited, #6753ac);--pfe-broadcasted--link-decoration:var(--pfe-theme--link-decoration, none);--pfe-broadcasted--link-decoration--hover:var(--pfe-theme--link-decoration--hover, underline);--pfe-broadcasted--link-decoration--focus:var(--pfe-theme--link-decoration--focus, underline);--pfe-broadcasted--link-decoration--visited:var(--pfe-theme--link-decoration--visited, none)}:host([on=saturated]:not([variant=earth])){--pfe-broadcasted--text:var(--pfe-theme--color--text--on-saturated, #fff);--pfe-broadcasted--text--muted:var(--pfe-theme--color--text--muted--on-saturated, #d2d2d2);--pfe-broadcasted--link:var(--pfe-theme--color--link--on-saturated, #fff);--pfe-broadcasted--link--hover:var(--pfe-theme--color--link--hover--on-saturated, #fafafa);--pfe-broadcasted--link--focus:var(--pfe-theme--color--link--focus--on-saturated, #fafafa);--pfe-broadcasted--link--visited:var(--pfe-theme--color--link--visited--on-saturated, #d2d2d2);--pfe-broadcasted--link-decoration:var(--pfe-theme--link-decoration--on-saturated, underline);--pfe-broadcasted--link-decoration--hover:var(--pfe-theme--link-decoration--hover--on-saturated, underline);--pfe-broadcasted--link-decoration--focus:var(--pfe-theme--link-decoration--focus--on-saturated, underline);--pfe-broadcasted--link-decoration--visited:var(--pfe-theme--link-decoration--visited--on-saturated, underline)}:host([on=dark]:not([variant=earth])){--pfe-broadcasted--text:var(--pfe-theme--color--text--on-dark, #fff);--pfe-broadcasted--text--muted:var(--pfe-theme--color--text--muted--on-dark, #d2d2d2);--pfe-broadcasted--link:var(--pfe-theme--color--link--on-dark, #73bcf7);--pfe-broadcasted--link--hover:var(--pfe-theme--color--link--hover--on-dark, #bee1f4);--pfe-broadcasted--link--focus:var(--pfe-theme--color--link--focus--on-dark, #bee1f4);--pfe-broadcasted--link--visited:var(--pfe-theme--color--link--visited--on-dark, #bee1f4);--pfe-broadcasted--link-decoration:var(--pfe-theme--link-decoration--on-dark, none);--pfe-broadcasted--link-decoration--hover:var(--pfe-theme--link-decoration--hover--on-dark, underline);--pfe-broadcasted--link-decoration--focus:var(--pfe-theme--link-decoration--focus--on-dark, underline);--pfe-broadcasted--link-decoration--visited:var(--pfe-theme--link-decoration--visited--on-dark, none)} /*# sourceMappingURL=pfe-tab-panel.min.css.map */</style>
|
|
1723
|
+
<div tabindex="-1" role="tabpanel">
|
|
1724
|
+
<div class="container">
|
|
1725
|
+
<slot></slot>
|
|
1726
|
+
</div>
|
|
1727
|
+
</div>`;
|
|
1728
|
+
}
|
|
1729
|
+
|
|
1730
|
+
static get tag() {
|
|
1731
|
+
return "pfe-tab-panel";
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1734
|
+
get styleUrl() {
|
|
1735
|
+
return "pfe-tab-panel.scss";
|
|
1736
|
+
}
|
|
1737
|
+
|
|
1738
|
+
get templateUrl() {
|
|
1739
|
+
return "pfe-tab-panel.html";
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1742
|
+
static get properties() {
|
|
1743
|
+
return {
|
|
1744
|
+
selected: {
|
|
1745
|
+
title: "Selected tab",
|
|
1746
|
+
type: Boolean,
|
|
1747
|
+
default: false,
|
|
1748
|
+
attr: "aria-selected",
|
|
1749
|
+
observer: "_selectedHandler"
|
|
1750
|
+
},
|
|
1751
|
+
hidden: {
|
|
1752
|
+
title: "Visibility",
|
|
1753
|
+
type: Boolean,
|
|
1754
|
+
default: false
|
|
1755
|
+
},
|
|
1756
|
+
role: {
|
|
1757
|
+
type: String,
|
|
1758
|
+
default: "tabpanel"
|
|
1759
|
+
},
|
|
1760
|
+
tabindex: {
|
|
1761
|
+
type: Number,
|
|
1762
|
+
default: 0
|
|
1763
|
+
},
|
|
1764
|
+
labelledby: {
|
|
1765
|
+
type: String,
|
|
1766
|
+
attr: "aria-labelledby"
|
|
1767
|
+
},
|
|
1768
|
+
variant: {
|
|
1769
|
+
title: "Variant",
|
|
1770
|
+
type: String,
|
|
1771
|
+
enum: ["wind", "earth"]
|
|
1772
|
+
},
|
|
1773
|
+
// @TODO: Deprecated in 1.0
|
|
1774
|
+
oldPfeId: {
|
|
1775
|
+
type: String,
|
|
1776
|
+
attr: "pfe-id",
|
|
1777
|
+
observer: "_oldPfeIdChanged"
|
|
1778
|
+
}
|
|
1779
|
+
};
|
|
1780
|
+
} // Declare the type of this component
|
|
1781
|
+
|
|
1782
|
+
|
|
1783
|
+
static get PfeType() {
|
|
1784
|
+
return PFElement.PfeTypes.Container;
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
constructor() {
|
|
1788
|
+
super(PfeTabPanel, {
|
|
1789
|
+
type: PfeTabPanel.PfeType
|
|
1790
|
+
});
|
|
1791
|
+
this._init = this._init.bind(this);
|
|
1792
|
+
this._observer = new MutationObserver(this._init);
|
|
1793
|
+
}
|
|
1794
|
+
|
|
1795
|
+
connectedCallback() {
|
|
1796
|
+
super.connectedCallback();
|
|
1797
|
+
if (this.hasLightDOM()) this._init();
|
|
1798
|
+
|
|
1799
|
+
this._observer.observe(this, TAB_PANEL_MUTATION_CONFIG);
|
|
1800
|
+
}
|
|
1801
|
+
|
|
1802
|
+
disconnectedCallback() {
|
|
1803
|
+
super.disconnectedCallback();
|
|
1804
|
+
|
|
1805
|
+
this._observer.disconnect();
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1808
|
+
_init() {
|
|
1809
|
+
if (window.ShadyCSS) this._observer.disconnect(); // If an ID is not defined, generate a random one
|
|
1810
|
+
|
|
1811
|
+
if (!this.id) this.id = this.randomId; // Force role to be set to tab
|
|
1812
|
+
|
|
1813
|
+
this.role = "tabpanel";
|
|
1814
|
+
|
|
1815
|
+
if (this.previousElementSibling && this.previousElementSibling.selected !== "true") {
|
|
1816
|
+
this.hidden = true;
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1819
|
+
if (window.ShadyCSS) this._observer.observe(this, TAB_PANEL_MUTATION_CONFIG);
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1822
|
+
_oldPfeIdChanged(oldVal, newVal) {
|
|
1823
|
+
if (!this.id) this.id = newVal;
|
|
1824
|
+
}
|
|
1825
|
+
|
|
1826
|
+
}
|
|
1827
|
+
/*!
|
|
1828
|
+
* PatternFly Elements: PfeTabs 1.12.3
|
|
1829
|
+
* @license
|
|
1830
|
+
* Copyright 2021 Red Hat, Inc.
|
|
1831
|
+
*
|
|
1832
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
1833
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
1834
|
+
* in the Software without restriction, including without limitation the rights
|
|
1835
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
1836
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
1837
|
+
* furnished to do so, subject to the following conditions:
|
|
1838
|
+
*
|
|
1839
|
+
* The above copyright notice and this permission notice shall be included in
|
|
1840
|
+
* all copies or substantial portions of the Software.
|
|
1841
|
+
*
|
|
1842
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
1843
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
1844
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
1845
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
1846
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
1847
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
1848
|
+
* SOFTWARE.
|
|
1849
|
+
*
|
|
1850
|
+
*/
|
|
1851
|
+
|
|
1852
|
+
|
|
1853
|
+
const KEYCODE = {
|
|
1854
|
+
DOWN: 40,
|
|
1855
|
+
LEFT: 37,
|
|
1856
|
+
RIGHT: 39,
|
|
1857
|
+
UP: 38,
|
|
1858
|
+
HOME: 36,
|
|
1859
|
+
END: 35
|
|
1860
|
+
}; // @IE11 doesn't support URLSearchParams
|
|
1861
|
+
// https://caniuse.com/#search=urlsearchparams
|
|
1862
|
+
|
|
1863
|
+
const CAN_USE_URLSEARCHPARAMS = window.URLSearchParams ? true : false;
|
|
1864
|
+
const TABS_MUTATION_CONFIG = {
|
|
1865
|
+
childList: true,
|
|
1866
|
+
subtree: true
|
|
1867
|
+
};
|
|
1868
|
+
|
|
1869
|
+
class PfeTabs extends PFElement {
|
|
1870
|
+
// Injected at build-time
|
|
1871
|
+
static get version() {
|
|
1872
|
+
return "1.12.3";
|
|
1873
|
+
} // Injected at build-time
|
|
1874
|
+
|
|
1875
|
+
|
|
1876
|
+
get html() {
|
|
1877
|
+
return `
|
|
1878
|
+
<style>@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host{color:#151515!important}}:host{display:block;display:var(--pfe-tabs--Display,block);padding:0;padding:var(--pfe-tabs--Padding,0)}:host .tabs{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;flex-direction:var(--pfe-tabs__tabs--FlexDirection,row);width:auto;width:var(--pfe-tabs__tabs--Width,auto);border-top:0;border-top:var(--pfe-tabs__tabs--BorderTop,0);border-right:0;border-right:var(--pfe-tabs__tabs--BorderRight,0);border-bottom:1px solid #d2d2d2;border-bottom:var(--pfe-tabs__tabs--BorderBottom,var(--pfe-theme--ui--border-width,1px) var(--pfe-theme--ui--border-style,solid) var(--pfe-tabs__tabs--BorderColor,var(--pfe-theme--color--surface--border,#d2d2d2)));border-left:0;border-left:var(--pfe-tabs__tabs--BorderLeft,0);padding:0;padding:var(--pfe-tabs__tabs--Padding,0)}:host .panels{width:auto;width:var(--pfe-tabs__panels--Width,auto)}:host(:not([vertical])[tab-align=center]) .tabs{-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}@media screen and (min-width:768px){:host([vertical]){--pfe-tabs--Display:flex;--pfe-tabs__tabs--FlexDirection:column;--pfe-tabs__tabs--Width:20%;--pfe-tabs__tabs--BorderRight:var(--pfe-theme--ui--border-width, 1px) var(--pfe-theme--ui--border-style, solid) var(--pfe-tabs--BorderColor);--pfe-tabs__tabs--BorderBottom:0;--pfe-tabs__panels--Width:80%;--pfe-tabs__panels--PaddingRight:var(--pfe-theme--container-padding, 1rem)}}@media screen and (min-width:768px) and (-ms-high-contrast:active),screen and (min-width:768px) and (-ms-high-contrast:none){:host([vertical]){display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}:host([vertical]) .tabs{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;width:22.22%;border-right:1px solid #d2d2d2;border-right:1px solid var(--pfe-theme--color--surface--border,#d2d2d2);border-bottom:0}:host([vertical]) .panels{width:77.8%;padding-right:1em}}@media screen and (min-width:768px) and (-ms-high-contrast:active),screen and (min-width:768px) and (-ms-high-contrast:none){:host([vertical][variant=earth]) .tabs{padding:1em 0 0 0}}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host(:not([variant=earth])){background-color:#fff;background-color:var(--pfe-theme--color--surface--lightest,#fff);color:#151515;color:var(--pfe-theme--color--text,#151515)}}:host([variant=earth]){--pfe-tabs__tabs--PaddingLeft:var(--pfe-theme--container-padding, 1rem)}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host([variant=earth]) .tabs{padding-left:1em}}:host([on=dark]){--pfe-broadcasted--text:var(--pfe-theme--color--text--on-dark, #fff);--pfe-broadcasted--text--muted:var(--pfe-theme--color--text--muted--on-dark, #d2d2d2);--pfe-broadcasted--link:var(--pfe-theme--color--link--on-dark, #73bcf7);--pfe-broadcasted--link--hover:var(--pfe-theme--color--link--hover--on-dark, #bee1f4);--pfe-broadcasted--link--focus:var(--pfe-theme--color--link--focus--on-dark, #bee1f4);--pfe-broadcasted--link--visited:var(--pfe-theme--color--link--visited--on-dark, #bee1f4);--pfe-broadcasted--link-decoration:var(--pfe-theme--link-decoration--on-dark, none);--pfe-broadcasted--link-decoration--hover:var(--pfe-theme--link-decoration--hover--on-dark, underline);--pfe-broadcasted--link-decoration--focus:var(--pfe-theme--link-decoration--focus--on-dark, underline);--pfe-broadcasted--link-decoration--visited:var(--pfe-theme--link-decoration--visited--on-dark, none)}:host([on=saturated]){--pfe-broadcasted--text:var(--pfe-theme--color--text--on-saturated, #fff);--pfe-broadcasted--text--muted:var(--pfe-theme--color--text--muted--on-saturated, #d2d2d2);--pfe-broadcasted--link:var(--pfe-theme--color--link--on-saturated, #fff);--pfe-broadcasted--link--hover:var(--pfe-theme--color--link--hover--on-saturated, #fafafa);--pfe-broadcasted--link--focus:var(--pfe-theme--color--link--focus--on-saturated, #fafafa);--pfe-broadcasted--link--visited:var(--pfe-theme--color--link--visited--on-saturated, #d2d2d2);--pfe-broadcasted--link-decoration:var(--pfe-theme--link-decoration--on-saturated, underline);--pfe-broadcasted--link-decoration--hover:var(--pfe-theme--link-decoration--hover--on-saturated, underline);--pfe-broadcasted--link-decoration--focus:var(--pfe-theme--link-decoration--focus--on-saturated, underline);--pfe-broadcasted--link-decoration--visited:var(--pfe-theme--link-decoration--visited--on-saturated, underline)}:host([on=light]){--pfe-broadcasted--text:var(--pfe-theme--color--text, #151515);--pfe-broadcasted--text--muted:var(--pfe-theme--color--text--muted, #6a6e73);--pfe-broadcasted--link:var(--pfe-theme--color--link, #06c);--pfe-broadcasted--link--hover:var(--pfe-theme--color--link--hover, #004080);--pfe-broadcasted--link--focus:var(--pfe-theme--color--link--focus, #004080);--pfe-broadcasted--link--visited:var(--pfe-theme--color--link--visited, #6753ac);--pfe-broadcasted--link-decoration:var(--pfe-theme--link-decoration, none);--pfe-broadcasted--link-decoration--hover:var(--pfe-theme--link-decoration--hover, underline);--pfe-broadcasted--link-decoration--focus:var(--pfe-theme--link-decoration--focus, underline);--pfe-broadcasted--link-decoration--visited:var(--pfe-theme--link-decoration--visited, none)}:host([vertical]) .tabs-prefix,:host([vertical]) .tabs-suffix{left:0;top:0;content:" ";height:calc(1rem * 2);height:calc(var(--pfe-theme--container-padding,1rem) * 2);width:1px;position:relative}@media screen and (min-width:768px){:host([vertical]:not([variant=earth])) .tabs-prefix,:host([vertical]:not([variant=earth])) .tabs-suffix{background-color:#d2d2d2;background-color:var(--pfe-tabs__tabs--BorderColor,var(--pfe-theme--color--surface--border,#d2d2d2))}}:host(:not([vertical])[variant=earth]) .tabs-prefix{left:0;top:0;content:" ";height:1px;width:1rem;width:var(--pfe-theme--container-padding,1rem);position:relative}@media screen and (min-width:768px){:host(:not([vertical])[variant=earth]) .tabs-prefix{width:calc(1rem * 2);width:calc(var(--pfe-theme--container-padding,1rem) * 2)}}:host([hidden]){display:none} /*# sourceMappingURL=pfe-tabs.min.css.map */</style>
|
|
1879
|
+
<div class="tabs">
|
|
1880
|
+
<div class="tabs-prefix"></div>
|
|
1881
|
+
<slot name="tab"></slot>
|
|
1882
|
+
<div class="tabs-suffix"></div>
|
|
1883
|
+
</div>
|
|
1884
|
+
<div class="panels">
|
|
1885
|
+
<slot name="panel"></slot>
|
|
1886
|
+
</div>`;
|
|
1887
|
+
}
|
|
1888
|
+
|
|
1889
|
+
static get tag() {
|
|
1890
|
+
return "pfe-tabs";
|
|
1891
|
+
}
|
|
1892
|
+
|
|
1893
|
+
get styleUrl() {
|
|
1894
|
+
return "pfe-tabs.scss";
|
|
1895
|
+
}
|
|
1896
|
+
|
|
1897
|
+
static get meta() {
|
|
1898
|
+
return {
|
|
1899
|
+
title: "Tabs",
|
|
1900
|
+
description: "This element creates a tabbed interface."
|
|
1901
|
+
};
|
|
1902
|
+
}
|
|
1903
|
+
|
|
1904
|
+
get templateUrl() {
|
|
1905
|
+
return "pfe-tabs.html";
|
|
1906
|
+
} // Each set contains a header and a panel
|
|
1907
|
+
|
|
1908
|
+
|
|
1909
|
+
static get contentTemplate() {
|
|
1910
|
+
return `
|
|
1911
|
+
<pfe-tab content-type="header" slot="tab"></pfe-tab>
|
|
1912
|
+
<pfe-tab-panel content-type="panel" slot="panel"></pfe-tab-panel>
|
|
1913
|
+
`;
|
|
1914
|
+
}
|
|
1915
|
+
|
|
1916
|
+
static get properties() {
|
|
1917
|
+
return {
|
|
1918
|
+
vertical: {
|
|
1919
|
+
title: "Vertical orientation",
|
|
1920
|
+
type: Boolean,
|
|
1921
|
+
default: false,
|
|
1922
|
+
cascade: "pfe-tab,pfe-tab-panel",
|
|
1923
|
+
observer: "_verticalHandler"
|
|
1924
|
+
},
|
|
1925
|
+
orientation: {
|
|
1926
|
+
title: "Orientation",
|
|
1927
|
+
type: String,
|
|
1928
|
+
attr: "aria-orientation",
|
|
1929
|
+
default: "horizontal",
|
|
1930
|
+
values: ["horizontal", "vertical"]
|
|
1931
|
+
},
|
|
1932
|
+
// Do not set a default of 0, it causes a the URL history to
|
|
1933
|
+
// be updated on load for every tab; infinite looping goodness
|
|
1934
|
+
// Seriously, don't set a default here unless you do a rewrite
|
|
1935
|
+
selectedIndex: {
|
|
1936
|
+
title: "Index of the selected tab",
|
|
1937
|
+
type: Number,
|
|
1938
|
+
observer: "_selectedIndexHandler"
|
|
1939
|
+
},
|
|
1940
|
+
tabAlign: {
|
|
1941
|
+
title: "Tab alignment",
|
|
1942
|
+
type: String,
|
|
1943
|
+
enum: ["center"]
|
|
1944
|
+
},
|
|
1945
|
+
controls: {
|
|
1946
|
+
type: String,
|
|
1947
|
+
attr: "aria-controls"
|
|
1948
|
+
},
|
|
1949
|
+
variant: {
|
|
1950
|
+
title: "Variant",
|
|
1951
|
+
type: String,
|
|
1952
|
+
enum: ["wind", "earth"],
|
|
1953
|
+
default: "wind",
|
|
1954
|
+
cascade: "pfe-tab,pfe-tab-panel"
|
|
1955
|
+
},
|
|
1956
|
+
tabHistory: {
|
|
1957
|
+
title: "Tab History",
|
|
1958
|
+
type: Boolean,
|
|
1959
|
+
default: false,
|
|
1960
|
+
observer: "_tabHistoryHandler"
|
|
1961
|
+
},
|
|
1962
|
+
role: {
|
|
1963
|
+
type: String,
|
|
1964
|
+
default: "tablist"
|
|
1965
|
+
},
|
|
1966
|
+
// @TODO: Deprecated for 1.0
|
|
1967
|
+
oldVariant: {
|
|
1968
|
+
type: String,
|
|
1969
|
+
attr: "pfe-variant",
|
|
1970
|
+
alias: "variant"
|
|
1971
|
+
},
|
|
1972
|
+
// @TODO: Deprecated for 1.0
|
|
1973
|
+
oldTabHistory: {
|
|
1974
|
+
type: Boolean,
|
|
1975
|
+
alias: "tabHistory",
|
|
1976
|
+
attr: "pfe-tab-history"
|
|
1977
|
+
},
|
|
1978
|
+
// @TODO: Deprecated for 1.0
|
|
1979
|
+
oldPfeId: {
|
|
1980
|
+
type: String,
|
|
1981
|
+
attr: "pfe-id",
|
|
1982
|
+
observer: "_oldPfeIdChanged"
|
|
1983
|
+
}
|
|
1984
|
+
};
|
|
1985
|
+
}
|
|
1986
|
+
|
|
1987
|
+
static get slots() {
|
|
1988
|
+
return {
|
|
1989
|
+
tab: {
|
|
1990
|
+
title: "Tab",
|
|
1991
|
+
type: "array",
|
|
1992
|
+
namedSlot: true,
|
|
1993
|
+
items: {
|
|
1994
|
+
$ref: "pfe-tab"
|
|
1995
|
+
}
|
|
1996
|
+
},
|
|
1997
|
+
panel: {
|
|
1998
|
+
title: "Panel",
|
|
1999
|
+
type: "array",
|
|
2000
|
+
namedSlot: true,
|
|
2001
|
+
items: {
|
|
2002
|
+
$ref: "pfe-tab-panel"
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
};
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
static get events() {
|
|
2009
|
+
return {
|
|
2010
|
+
hiddenTab: `${this.tag}:hidden-tab`,
|
|
2011
|
+
shownTab: `${this.tag}:shown-tab`
|
|
2012
|
+
};
|
|
2013
|
+
} // Declare the type of this component
|
|
2014
|
+
|
|
2015
|
+
|
|
2016
|
+
static get PfeType() {
|
|
2017
|
+
return PFElement.PfeTypes.Combo;
|
|
2018
|
+
}
|
|
2019
|
+
|
|
2020
|
+
constructor() {
|
|
2021
|
+
super(PfeTabs, {
|
|
2022
|
+
type: PfeTabs.PfeType
|
|
2023
|
+
});
|
|
2024
|
+
this._linked = false;
|
|
2025
|
+
this._init = this._init.bind(this);
|
|
2026
|
+
this._onClick = this._onClick.bind(this);
|
|
2027
|
+
this._linkPanels = this._linkPanels.bind(this);
|
|
2028
|
+
this._popstateEventHandler = this._popstateEventHandler.bind(this);
|
|
2029
|
+
this._observer = new MutationObserver(this._init);
|
|
2030
|
+
this._updateHistory = true;
|
|
2031
|
+
}
|
|
2032
|
+
|
|
2033
|
+
connectedCallback() {
|
|
2034
|
+
Promise.all([customElements.whenDefined(PfeTab.tag), customElements.whenDefined(PfeTabPanel.tag)]).then(() => {
|
|
2035
|
+
super.connectedCallback();
|
|
2036
|
+
if (this.hasLightDOM()) this._init();
|
|
2037
|
+
|
|
2038
|
+
this._observer.observe(this, TABS_MUTATION_CONFIG);
|
|
2039
|
+
|
|
2040
|
+
this.addEventListener("keydown", this._onKeyDown);
|
|
2041
|
+
this.addEventListener("click", this._onClick);
|
|
2042
|
+
});
|
|
2043
|
+
}
|
|
2044
|
+
|
|
2045
|
+
disconnectedCallback() {
|
|
2046
|
+
super.disconnectedCallback();
|
|
2047
|
+
this.removeEventListener("keydown", this._onKeyDown);
|
|
2048
|
+
|
|
2049
|
+
this._allTabs().forEach(tab => tab.removeEventListener("click", this._onClick));
|
|
2050
|
+
|
|
2051
|
+
this._observer.disconnect();
|
|
2052
|
+
|
|
2053
|
+
if (this.tabHistory) window.removeEventListener("popstate", this._popstateEventHandler);
|
|
2054
|
+
}
|
|
2055
|
+
|
|
2056
|
+
_verticalHandler() {
|
|
2057
|
+
if (this.vertical) this.orientation = "vertical";else this.orientation = "horizontal";
|
|
2058
|
+
}
|
|
2059
|
+
|
|
2060
|
+
_selectedIndexHandler(oldVal, newVal) {
|
|
2061
|
+
// Wait until the tab and panels are loaded
|
|
2062
|
+
Promise.all([customElements.whenDefined(PfeTab.tag), customElements.whenDefined(PfeTabPanel.tag)]).then(() => {
|
|
2063
|
+
this._linkPanels();
|
|
2064
|
+
|
|
2065
|
+
this.selectIndex(newVal);
|
|
2066
|
+
this._updateHistory = true;
|
|
2067
|
+
});
|
|
2068
|
+
}
|
|
2069
|
+
|
|
2070
|
+
_tabHistoryHandler() {
|
|
2071
|
+
if (!this.tabHistory) window.removeEventListener("popstate", this._popstateEventHandler);else window.addEventListener("popstate", this._popstateEventHandler);
|
|
2072
|
+
}
|
|
2073
|
+
|
|
2074
|
+
_oldPfeIdChanged(oldVal, newVal) {
|
|
2075
|
+
if (!this.id && newVal) this.id = newVal;
|
|
2076
|
+
}
|
|
2077
|
+
|
|
2078
|
+
select(newTab) {
|
|
2079
|
+
if (!newTab) return;
|
|
2080
|
+
|
|
2081
|
+
if (newTab.tagName.toLowerCase() !== PfeTab.tag) {
|
|
2082
|
+
this.warn(`the tab must be a ${PfeTab.tag} element`);
|
|
2083
|
+
return;
|
|
2084
|
+
}
|
|
2085
|
+
|
|
2086
|
+
this.selectedIndex = this._getTabIndex(newTab);
|
|
2087
|
+
}
|
|
2088
|
+
|
|
2089
|
+
selectIndex(_index) {
|
|
2090
|
+
if (_index === undefined || _index === null) return;
|
|
2091
|
+
const index = parseInt(_index, 10);
|
|
2092
|
+
|
|
2093
|
+
const tabs = this._allTabs();
|
|
2094
|
+
|
|
2095
|
+
const tab = tabs[index];
|
|
2096
|
+
|
|
2097
|
+
if (tabs.length > 0 && !tab) {
|
|
2098
|
+
this.warn(`tab ${_index} does not exist`);
|
|
2099
|
+
return;
|
|
2100
|
+
} else if (!tabs && !tab) {
|
|
2101
|
+
// Wait for upgrade?
|
|
2102
|
+
return;
|
|
2103
|
+
}
|
|
2104
|
+
|
|
2105
|
+
if (this.selected && this.tabHistory && this._updateHistory && CAN_USE_URLSEARCHPARAMS) {
|
|
2106
|
+
// @IE11 doesn't support URLSearchParams
|
|
2107
|
+
// https://caniuse.com/#search=urlsearchparams
|
|
2108
|
+
// rebuild the url
|
|
2109
|
+
const pathname = window.location.pathname;
|
|
2110
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
2111
|
+
const hash = window.location.hash;
|
|
2112
|
+
urlParams.set(this.id, tab.id);
|
|
2113
|
+
history.pushState({}, "", `${pathname}?${urlParams.toString()}${hash}`);
|
|
2114
|
+
}
|
|
2115
|
+
|
|
2116
|
+
this._selectTab(tab);
|
|
2117
|
+
|
|
2118
|
+
return tab;
|
|
2119
|
+
}
|
|
2120
|
+
|
|
2121
|
+
_init() {
|
|
2122
|
+
const tabIndexFromURL = this._getTabIndexFromURL();
|
|
2123
|
+
|
|
2124
|
+
this._linked = false;
|
|
2125
|
+
|
|
2126
|
+
this._linkPanels(); // Force role to be set to tablist
|
|
2127
|
+
|
|
2128
|
+
|
|
2129
|
+
if (window.ShadyCSS) this._observer.disconnect();
|
|
2130
|
+
this.role = "tablist";
|
|
2131
|
+
|
|
2132
|
+
if (tabIndexFromURL > -1) {
|
|
2133
|
+
this._setFocus = true;
|
|
2134
|
+
this.selectedIndex = tabIndexFromURL;
|
|
2135
|
+
}
|
|
2136
|
+
|
|
2137
|
+
if (this.selectedIndex === null) this.selectedIndex = 0;
|
|
2138
|
+
if (window.ShadyCSS) this._observer.observe(this, TABS_MUTATION_CONFIG);
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2141
|
+
_linkPanels() {
|
|
2142
|
+
if (this._linked) return;
|
|
2143
|
+
if (window.ShadyCSS) this._observer.disconnect();
|
|
2144
|
+
|
|
2145
|
+
this._allTabs().forEach(tab => {
|
|
2146
|
+
const panel = tab.nextElementSibling;
|
|
2147
|
+
|
|
2148
|
+
if (panel.tagName.toLowerCase() !== PfeTabPanel.tag) {
|
|
2149
|
+
this.warn(`not a sibling of a <${PfeTabPanel.tag}>`);
|
|
2150
|
+
return;
|
|
2151
|
+
} // Connect the 2 items via appropriate aria attributes
|
|
2152
|
+
|
|
2153
|
+
|
|
2154
|
+
tab.controls = panel.id;
|
|
2155
|
+
panel.labelledby = tab.id;
|
|
2156
|
+
tab.addEventListener("click", this._onClick);
|
|
2157
|
+
});
|
|
2158
|
+
|
|
2159
|
+
this._linked = true;
|
|
2160
|
+
if (window.ShadyCSS) this._observer.observe(this, TABS_MUTATION_CONFIG);
|
|
2161
|
+
}
|
|
2162
|
+
|
|
2163
|
+
_allPanels() {
|
|
2164
|
+
return [...this.children].filter(child => child.matches(PfeTabPanel.tag));
|
|
2165
|
+
}
|
|
2166
|
+
|
|
2167
|
+
_allTabs() {
|
|
2168
|
+
return [...this.children].filter(child => child.matches(PfeTab.tag));
|
|
2169
|
+
}
|
|
2170
|
+
|
|
2171
|
+
_panelForTab(tab) {
|
|
2172
|
+
if (!tab || !tab.controls) return;
|
|
2173
|
+
return this.querySelector(`#${tab.controls}`);
|
|
2174
|
+
}
|
|
2175
|
+
|
|
2176
|
+
_prevTab() {
|
|
2177
|
+
const tabs = this._allTabs();
|
|
2178
|
+
|
|
2179
|
+
let newIdx = tabs.findIndex(tab => tab.selected === "true") - 1;
|
|
2180
|
+
return tabs[(newIdx + tabs.length) % tabs.length];
|
|
2181
|
+
}
|
|
2182
|
+
|
|
2183
|
+
_firstTab() {
|
|
2184
|
+
const tabs = this._allTabs();
|
|
2185
|
+
|
|
2186
|
+
return tabs[0];
|
|
2187
|
+
}
|
|
2188
|
+
|
|
2189
|
+
_lastTab() {
|
|
2190
|
+
const tabs = this._allTabs();
|
|
2191
|
+
|
|
2192
|
+
return tabs[tabs.length - 1];
|
|
2193
|
+
}
|
|
2194
|
+
|
|
2195
|
+
_nextTab() {
|
|
2196
|
+
const tabs = this._allTabs();
|
|
2197
|
+
|
|
2198
|
+
let newIdx = tabs.findIndex(tab => tab.selected === "true") + 1;
|
|
2199
|
+
return tabs[newIdx % tabs.length];
|
|
2200
|
+
}
|
|
2201
|
+
|
|
2202
|
+
_getTabIndex(_tab) {
|
|
2203
|
+
if (_tab) {
|
|
2204
|
+
const tabs = this._allTabs();
|
|
2205
|
+
|
|
2206
|
+
return tabs.findIndex(tab => tab.id === _tab.id);
|
|
2207
|
+
} else {
|
|
2208
|
+
this.warn(`No tab was provided to _getTabIndex; required to return the index value.`);
|
|
2209
|
+
return 0;
|
|
2210
|
+
}
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
reset() {
|
|
2214
|
+
const tabs = this._allTabs();
|
|
2215
|
+
|
|
2216
|
+
const panels = this._allPanels();
|
|
2217
|
+
|
|
2218
|
+
tabs.forEach(tab => tab.selected = "false");
|
|
2219
|
+
panels.forEach(panel => panel.hidden = true);
|
|
2220
|
+
}
|
|
2221
|
+
|
|
2222
|
+
_selectTab(newTab) {
|
|
2223
|
+
if (!newTab) return;
|
|
2224
|
+
this.reset();
|
|
2225
|
+
|
|
2226
|
+
const newPanel = this._panelForTab(newTab);
|
|
2227
|
+
|
|
2228
|
+
let newTabSelected = false;
|
|
2229
|
+
if (!newPanel) this.warn(`No panel was found for the selected tab${newTab.id ? `: pfe-tab#${newTab.id}` : ""}`); // this.selected on tabs contains a pointer to the selected tab element
|
|
2230
|
+
|
|
2231
|
+
if (this.selected && this.selected !== newTab) {
|
|
2232
|
+
newTabSelected = true;
|
|
2233
|
+
this.emitEvent(PfeTabs.events.hiddenTab, {
|
|
2234
|
+
detail: {
|
|
2235
|
+
tab: this.selected
|
|
2236
|
+
}
|
|
2237
|
+
});
|
|
2238
|
+
}
|
|
2239
|
+
|
|
2240
|
+
newTab.selected = "true";
|
|
2241
|
+
newPanel.hidden = false; // Update the value of the selected pointer to the new tab
|
|
2242
|
+
|
|
2243
|
+
this.selected = newTab;
|
|
2244
|
+
|
|
2245
|
+
if (newTabSelected) {
|
|
2246
|
+
if (this._setFocus) newTab.focus();
|
|
2247
|
+
this.emitEvent(PfeTabs.events.shownTab, {
|
|
2248
|
+
detail: {
|
|
2249
|
+
tab: this.selected
|
|
2250
|
+
}
|
|
2251
|
+
});
|
|
2252
|
+
}
|
|
2253
|
+
|
|
2254
|
+
this._setFocus = false;
|
|
2255
|
+
}
|
|
2256
|
+
|
|
2257
|
+
_onKeyDown(event) {
|
|
2258
|
+
const tabs = this._allTabs();
|
|
2259
|
+
|
|
2260
|
+
const foundTab = tabs.find(tab => tab === event.target);
|
|
2261
|
+
|
|
2262
|
+
if (!foundTab) {
|
|
2263
|
+
return;
|
|
2264
|
+
}
|
|
2265
|
+
|
|
2266
|
+
if (event.altKey) {
|
|
2267
|
+
return;
|
|
2268
|
+
}
|
|
2269
|
+
|
|
2270
|
+
let newTab;
|
|
2271
|
+
|
|
2272
|
+
switch (event.keyCode) {
|
|
2273
|
+
case KEYCODE.LEFT:
|
|
2274
|
+
case KEYCODE.UP:
|
|
2275
|
+
newTab = this._prevTab();
|
|
2276
|
+
break;
|
|
2277
|
+
|
|
2278
|
+
case KEYCODE.RIGHT:
|
|
2279
|
+
case KEYCODE.DOWN:
|
|
2280
|
+
newTab = this._nextTab();
|
|
2281
|
+
break;
|
|
2282
|
+
|
|
2283
|
+
case KEYCODE.HOME:
|
|
2284
|
+
newTab = this._firstTab();
|
|
2285
|
+
break;
|
|
2286
|
+
|
|
2287
|
+
case KEYCODE.END:
|
|
2288
|
+
newTab = this._lastTab();
|
|
2289
|
+
break;
|
|
2290
|
+
|
|
2291
|
+
default:
|
|
2292
|
+
return;
|
|
2293
|
+
}
|
|
2294
|
+
|
|
2295
|
+
event.preventDefault();
|
|
2296
|
+
|
|
2297
|
+
if (newTab) {
|
|
2298
|
+
this.selectedIndex = this._getTabIndex(newTab);
|
|
2299
|
+
this._setFocus = true;
|
|
2300
|
+
} else {
|
|
2301
|
+
this.warn(`No new tab could be found.`);
|
|
2302
|
+
}
|
|
2303
|
+
}
|
|
2304
|
+
|
|
2305
|
+
_onClick(event) {
|
|
2306
|
+
// Find the clicked tab
|
|
2307
|
+
const foundTab = this._allTabs().find(tab => tab === event.currentTarget); // If the tab wasn't found in the markup, exit the handler
|
|
2308
|
+
|
|
2309
|
+
|
|
2310
|
+
if (!foundTab) return; // Update the selected index to the clicked tab
|
|
2311
|
+
|
|
2312
|
+
this.selectedIndex = this._getTabIndex(event.currentTarget);
|
|
2313
|
+
}
|
|
2314
|
+
|
|
2315
|
+
_getTabIndexFromURL() {
|
|
2316
|
+
let urlParams; // @IE11 doesn't support URLSearchParams
|
|
2317
|
+
// https://caniuse.com/#search=urlsearchparams
|
|
2318
|
+
// @Deprecated in 1.0
|
|
2319
|
+
// the "pfe-" prefix has been deprecated but we'll continue to support it
|
|
2320
|
+
// we'll give priority to the urlParams.has(`${this.id}`) attribute first
|
|
2321
|
+
// and fallback to urlParams.has(`pfe-${this.id}`) if it exists. We should
|
|
2322
|
+
// be able to remove the || part of the if statement in the future
|
|
2323
|
+
|
|
2324
|
+
if (CAN_USE_URLSEARCHPARAMS) {
|
|
2325
|
+
urlParams = new URLSearchParams(window.location.search);
|
|
2326
|
+
const tabsetInUrl = urlParams.has(`${this.id}`) || urlParams.has(`pfe-${this.id}`); // remove this condition when it's no longer used in production
|
|
2327
|
+
|
|
2328
|
+
if (urlParams && tabsetInUrl) {
|
|
2329
|
+
let id = urlParams.get(`${this.id}`) || urlParams.get(`pfe-${this.id}`); // remove this condition when it's no longer used in production
|
|
2330
|
+
|
|
2331
|
+
return this._allTabs().findIndex(tab => tab.id === id);
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
|
|
2335
|
+
return -1;
|
|
2336
|
+
}
|
|
2337
|
+
|
|
2338
|
+
_popstateEventHandler() {
|
|
2339
|
+
const tabIndexFromURL = this._getTabIndexFromURL();
|
|
2340
|
+
|
|
2341
|
+
this._updateHistory = false;
|
|
2342
|
+
if (tabIndexFromURL > -1) this.selectedIndex = tabIndexFromURL;
|
|
2343
|
+
}
|
|
2344
|
+
|
|
2345
|
+
}
|
|
2346
|
+
|
|
2347
|
+
PFElement.create(PfeTab);
|
|
2348
|
+
PFElement.create(PfeTabPanel);
|
|
2349
|
+
PFElement.create(PfeTabs);
|
|
2350
|
+
|
|
2351
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent
|
|
2352
|
+
|
|
2353
|
+
(function () {
|
|
2354
|
+
if (typeof window.CustomEvent === "function") return false;
|
|
2355
|
+
|
|
2356
|
+
function CustomEvent(event, params) {
|
|
2357
|
+
params = params || {
|
|
2358
|
+
bubbles: false,
|
|
2359
|
+
cancelable: false,
|
|
2360
|
+
detail: null
|
|
2361
|
+
};
|
|
2362
|
+
var evt = document.createEvent("CustomEvent");
|
|
2363
|
+
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
|
|
2364
|
+
return evt;
|
|
2365
|
+
}
|
|
2366
|
+
|
|
2367
|
+
window.CustomEvent = CustomEvent;
|
|
2368
|
+
})();
|
|
2369
|
+
|
|
2370
|
+
class PfeIconSet {
|
|
2371
|
+
/**
|
|
2372
|
+
* Run the icon set's name resolver to turn an icon name into an icon path, id, etc.
|
|
2373
|
+
*/
|
|
2374
|
+
resolveIconName(iconName) {
|
|
2375
|
+
return this._resolveIconName(iconName, this.name, this.path);
|
|
2376
|
+
}
|
|
2377
|
+
/**
|
|
2378
|
+
* Create a new icon set. Icon sets have a name (ie, a namespace). For
|
|
2379
|
+
* example, an icon with a name of "rh-logo" represents a "logo" icon from the
|
|
2380
|
+
* "rh" set. Icon set names are always separated from the rest of the icon
|
|
2381
|
+
* name with a hyphen `-`. This means that set names cannot contain a hyphen.
|
|
2382
|
+
*
|
|
2383
|
+
* @param {String} name the namespace of the icon set
|
|
2384
|
+
* @param {String} path the web-accessible path to the icon set (for instance, a CDN)
|
|
2385
|
+
* @param {Function} resolveIconName an optional function to combine the path and an icon name into a final path. The function will be passed the namespaced icon name (for example, "rh-api" where rh is the namespace and api is the individual icon's name)
|
|
2386
|
+
* @returns {Object} an object with the status of the icon set installation, such as `{ result: true, text: 'icon set installed' }` or `{ result: false, text: 'icon set is already installed' }`
|
|
2387
|
+
*/
|
|
2388
|
+
|
|
2389
|
+
|
|
2390
|
+
constructor(name, path, resolveIconName) {
|
|
2391
|
+
this.name = name;
|
|
2392
|
+
this.path = path;
|
|
2393
|
+
this._resolveIconName = resolveIconName;
|
|
2394
|
+
}
|
|
2395
|
+
|
|
2396
|
+
}
|
|
2397
|
+
/**
|
|
2398
|
+
* An 'init' function to add the PFE built-in icon sets to the current page.
|
|
2399
|
+
*/
|
|
2400
|
+
|
|
2401
|
+
|
|
2402
|
+
function addBuiltIns({
|
|
2403
|
+
PfeIcon,
|
|
2404
|
+
config
|
|
2405
|
+
}) {
|
|
2406
|
+
// If the user wants to completely opt out of default icon sets,
|
|
2407
|
+
// allow them to.
|
|
2408
|
+
if (config.IconSets && config.IconSets.length === 0) {
|
|
2409
|
+
return;
|
|
2410
|
+
} // If the user provides their own icon sets, use them. If not, use our defaults.
|
|
2411
|
+
// @TODO: Switch from access.redhat.com to another icon set.
|
|
2412
|
+
|
|
2413
|
+
|
|
2414
|
+
const iconSets = config.IconSets || [{
|
|
2415
|
+
name: "web",
|
|
2416
|
+
path: "https://access.redhat.com/webassets/avalon/j/lib/rh-iconfont-svgs"
|
|
2417
|
+
}, {
|
|
2418
|
+
name: "rh",
|
|
2419
|
+
path: "https://access.redhat.com/webassets/avalon/j/lib/rh-iconfont-svgs"
|
|
2420
|
+
}];
|
|
2421
|
+
|
|
2422
|
+
let resolveDefaultIconName = (name, iconSetName, iconSetPath) => {
|
|
2423
|
+
const regex = new RegExp(`^${iconSetName}(-icon)?-(.*)`);
|
|
2424
|
+
const [,, iconName] = regex.exec(name);
|
|
2425
|
+
const iconId = `${iconSetName}-icon-${iconName}`;
|
|
2426
|
+
const iconPath = `${iconSetPath}/${iconId}.svg`;
|
|
2427
|
+
return iconPath;
|
|
2428
|
+
}; // Register the icon sets.
|
|
2429
|
+
|
|
2430
|
+
|
|
2431
|
+
iconSets.forEach(set => {
|
|
2432
|
+
// If there's a `resolveIconName` function provided, use it. If not, fall back
|
|
2433
|
+
// to the `resolveDefaultIconName` function.
|
|
2434
|
+
if (set.resolveIconName && typeof set.resolveIconName === "function") {
|
|
2435
|
+
resolveDefaultIconName = set.resolveIconName;
|
|
2436
|
+
}
|
|
2437
|
+
|
|
2438
|
+
PfeIcon.addIconSet(set.name, set.path, resolveDefaultIconName);
|
|
2439
|
+
});
|
|
2440
|
+
}
|
|
2441
|
+
/*!
|
|
2442
|
+
* PatternFly Elements: PfeIcon 1.12.3
|
|
2443
|
+
* @license
|
|
2444
|
+
* Copyright 2021 Red Hat, Inc.
|
|
2445
|
+
*
|
|
2446
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
2447
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
2448
|
+
* in the Software without restriction, including without limitation the rights
|
|
2449
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
2450
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
2451
|
+
* furnished to do so, subject to the following conditions:
|
|
2452
|
+
*
|
|
2453
|
+
* The above copyright notice and this permission notice shall be included in
|
|
2454
|
+
* all copies or substantial portions of the Software.
|
|
2455
|
+
*
|
|
2456
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
2457
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
2458
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
2459
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
2460
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
2461
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
2462
|
+
* SOFTWARE.
|
|
2463
|
+
*
|
|
2464
|
+
*/
|
|
2465
|
+
|
|
2466
|
+
/**
|
|
2467
|
+
* Sets the id attribute on the <filter> element and points the CSS `filter` at that id.
|
|
2468
|
+
*/
|
|
2469
|
+
|
|
2470
|
+
|
|
2471
|
+
function _setRandomFilterId(el) {
|
|
2472
|
+
const randomId = "filter-" + Math.random().toString().slice(2, 10); // set the CSS filter property to point at the given id
|
|
2473
|
+
|
|
2474
|
+
el.shadowRoot.querySelector("svg image").style.filter = `url(#${randomId})`; // set the id attribute on the SVG filter element to match
|
|
2475
|
+
|
|
2476
|
+
el.shadowRoot.querySelector("svg filter").setAttribute("id", randomId);
|
|
2477
|
+
}
|
|
2478
|
+
|
|
2479
|
+
class PfeIcon extends PFElement {
|
|
2480
|
+
// Injected at build-time
|
|
2481
|
+
static get version() {
|
|
2482
|
+
return "1.12.3";
|
|
2483
|
+
} // Injected at build-time
|
|
2484
|
+
|
|
2485
|
+
|
|
2486
|
+
get html() {
|
|
2487
|
+
return `
|
|
2488
|
+
<style>@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host{color:#151515!important}}:host([on=dark]){--pfe-broadcasted--text:var(--pfe-theme--color--text--on-dark, #fff);--pfe-broadcasted--text--muted:var(--pfe-theme--color--text--muted--on-dark, #d2d2d2);--pfe-broadcasted--link:var(--pfe-theme--color--link--on-dark, #73bcf7);--pfe-broadcasted--link--hover:var(--pfe-theme--color--link--hover--on-dark, #bee1f4);--pfe-broadcasted--link--focus:var(--pfe-theme--color--link--focus--on-dark, #bee1f4);--pfe-broadcasted--link--visited:var(--pfe-theme--color--link--visited--on-dark, #bee1f4);--pfe-broadcasted--link-decoration:var(--pfe-theme--link-decoration--on-dark, none);--pfe-broadcasted--link-decoration--hover:var(--pfe-theme--link-decoration--hover--on-dark, underline);--pfe-broadcasted--link-decoration--focus:var(--pfe-theme--link-decoration--focus--on-dark, underline);--pfe-broadcasted--link-decoration--visited:var(--pfe-theme--link-decoration--visited--on-dark, none)}:host([on=saturated]){--pfe-broadcasted--text:var(--pfe-theme--color--text--on-saturated, #fff);--pfe-broadcasted--text--muted:var(--pfe-theme--color--text--muted--on-saturated, #d2d2d2);--pfe-broadcasted--link:var(--pfe-theme--color--link--on-saturated, #fff);--pfe-broadcasted--link--hover:var(--pfe-theme--color--link--hover--on-saturated, #fafafa);--pfe-broadcasted--link--focus:var(--pfe-theme--color--link--focus--on-saturated, #fafafa);--pfe-broadcasted--link--visited:var(--pfe-theme--color--link--visited--on-saturated, #d2d2d2);--pfe-broadcasted--link-decoration:var(--pfe-theme--link-decoration--on-saturated, underline);--pfe-broadcasted--link-decoration--hover:var(--pfe-theme--link-decoration--hover--on-saturated, underline);--pfe-broadcasted--link-decoration--focus:var(--pfe-theme--link-decoration--focus--on-saturated, underline);--pfe-broadcasted--link-decoration--visited:var(--pfe-theme--link-decoration--visited--on-saturated, underline)}:host([on=light]){--pfe-broadcasted--text:var(--pfe-theme--color--text, #151515);--pfe-broadcasted--text--muted:var(--pfe-theme--color--text--muted, #6a6e73);--pfe-broadcasted--link:var(--pfe-theme--color--link, #06c);--pfe-broadcasted--link--hover:var(--pfe-theme--color--link--hover, #004080);--pfe-broadcasted--link--focus:var(--pfe-theme--color--link--focus, #004080);--pfe-broadcasted--link--visited:var(--pfe-theme--color--link--visited, #6753ac);--pfe-broadcasted--link-decoration:var(--pfe-theme--link-decoration, none);--pfe-broadcasted--link-decoration--hover:var(--pfe-theme--link-decoration--hover, underline);--pfe-broadcasted--link-decoration--focus:var(--pfe-theme--link-decoration--focus, underline);--pfe-broadcasted--link-decoration--visited:var(--pfe-theme--link-decoration--visited, none)}:host{--context:var(--pfe-icon--context, light);position:relative;display:inline-block;-webkit-box-sizing:content-box!important;box-sizing:content-box!important;width:-webkit-fit-content!important;width:-moz-fit-content!important;width:fit-content!important;height:-webkit-fit-content!important;height:-moz-fit-content!important;height:fit-content!important;line-height:0;max-width:1em;max-width:var(--pfe-icon--size,var(--pfe-theme--icon-size,1em));max-height:1em;max-height:var(--pfe-icon--size,var(--pfe-theme--icon-size,1em))}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host{width:1em!important;width:var(--pfe-theme--icon-size,1em)!important;height:1em!important;height:var(--pfe-theme--icon-size,1em)!important}}:host svg{width:1em;width:var(--pfe-icon--size,var(--pfe-theme--icon-size,1em));height:1em;height:var(--pfe-icon--size,var(--pfe-theme--icon-size,1em))}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host svg{width:1em!important;width:var(--pfe-theme--icon-size,1em)!important;height:1em!important;height:var(--pfe-theme--icon-size,1em)!important}}:host([block]){display:block;margin-bottom:1rem;margin-bottom:var(--pfe-icon--spacing,var(--pfe-theme--container-spacer,1rem));margin-top:1rem;margin-top:var(--pfe-icon--spacing,var(--pfe-theme--container-spacer,1rem))}:host([block]):first-child{margin-top:0}:host(:not(.load-failed)){vertical-align:middle;border-radius:50%;background-color:transparent;background-color:var(--pfe-icon--BackgroundColor,transparent);border:1px solid transparent;border:var(--pfe-icon--BorderWidth,var(--pfe-theme--ui--border-width,1px)) var(--pfe-theme--ui--border-style,solid) var(--pfe-icon--BorderColor,var(--pfe-icon--BackgroundColor,transparent));padding:0;padding:var(--pfe-icon--Padding,0)}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host(:not(.load-failed)){background-color:#fff!important}:host(:not(.load-failed)) svg filter feFlood{flood-color:#000!important}}@supports (-ms-accelerator:true){:host(:not(.load-failed)){background-color:#fff!important}:host(:not(.load-failed)) svg filter feFlood{flood-color:#000!important}}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host(:not(.load-failed)) svg image{-webkit-filter:none;filter:none}}:host(:not(.load-failed)) filter feFlood{flood-color:#3c3f42;flood-color:var(--pfe-icon--color,var(--pfe-icon--Color,var(--pfe-broadcasted--text,#3c3f42)))}:host(:not(.load-failed)) .pfe-icon--fallback{display:none}:host([size="2x"]){max-width:2em;max-width:var(--pfe-icon--size,2em);max-height:2em;max-height:var(--pfe-icon--size,2em)}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host([size="2x"]){width:2em!important;height:2em!important}}:host([size="2x"]) svg{width:2em;width:var(--pfe-icon--size,2em);height:2em;height:var(--pfe-icon--size,2em)}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host([size="2x"]) svg{width:2em!important;height:2em!important}}:host([size="3x"]){max-width:3em;max-width:var(--pfe-icon--size,3em);max-height:3em;max-height:var(--pfe-icon--size,3em)}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host([size="3x"]){width:3em!important;height:3em!important}}:host([size="3x"]) svg{width:3em;width:var(--pfe-icon--size,3em);height:3em;height:var(--pfe-icon--size,3em)}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host([size="3x"]) svg{width:3em!important;height:3em!important}}:host([size="4x"]){max-width:4em;max-width:var(--pfe-icon--size,4em);max-height:4em;max-height:var(--pfe-icon--size,4em)}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host([size="4x"]){width:4em!important;height:4em!important}}:host([size="4x"]) svg{width:4em;width:var(--pfe-icon--size,4em);height:4em;height:var(--pfe-icon--size,4em)}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host([size="4x"]) svg{width:4em!important;height:4em!important}}:host([size=xl]){max-width:100px;max-width:var(--pfe-icon--size,100px);max-height:100px;max-height:var(--pfe-icon--size,100px)}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host([size=xl]){width:100px!important;height:100px!important}}:host([size=xl]) svg{width:100px;width:var(--pfe-icon--size,100px);height:100px;height:var(--pfe-icon--size,100px)}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host([size=xl]) svg{width:100px!important;height:100px!important}}:host([size=lg]){max-width:64px;max-width:var(--pfe-icon--size,64px);max-height:64px;max-height:var(--pfe-icon--size,64px)}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host([size=lg]){width:64px!important;height:64px!important}}:host([size=lg]) svg{width:64px;width:var(--pfe-icon--size,64px);height:64px;height:var(--pfe-icon--size,64px)}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host([size=lg]) svg{width:64px!important;height:64px!important}}:host([size=md]){max-width:32px;max-width:var(--pfe-icon--size,32px);max-height:32px;max-height:var(--pfe-icon--size,32px)}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host([size=md]){width:32px!important;height:32px!important}}:host([size=md]) svg{width:32px;width:var(--pfe-icon--size,32px);height:32px;height:var(--pfe-icon--size,32px)}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host([size=md]) svg{width:32px!important;height:32px!important}}:host([size=sm]){max-width:14px;max-width:var(--pfe-icon--size,14px);max-height:14px;max-height:var(--pfe-icon--size,14px)}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host([size=sm]){width:14px!important;height:14px!important}}:host([size=sm]) svg{width:14px;width:var(--pfe-icon--size,14px);height:14px;height:var(--pfe-icon--size,14px)}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host([size=sm]) svg{width:14px!important;height:14px!important}}:host([circled]:not([circled=false])){padding:.5em;padding:var(--pfe-icon--Padding,.5em);background-color:#fff;background-color:var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--surface--lightest,#fff));border-color:#d2d2d2;border-color:var(--pfe-icon--BorderColor,var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--surface--border,#d2d2d2)))}:host([color=critical]:not([circled])) filter feFlood,:host([color=critical][circled=false]) filter feFlood{flood-color:#a30000;flood-color:var(--pfe-icon--color,var(--pfe-icon--Color,var(--pfe-theme--color--feedback--critical,#a30000)))}:host([color=critical][circled]:not([circled=false])){background-color:#a30000;background-color:var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--feedback--critical,#a30000));border-color:#a30000;border-color:var(--pfe-icon--BorderColor,var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--feedback--critical,#a30000)));--pfe-icon--context:dark}:host([color=important]:not([circled])) filter feFlood,:host([color=important][circled=false]) filter feFlood{flood-color:#c9190b;flood-color:var(--pfe-icon--color,var(--pfe-icon--Color,var(--pfe-theme--color--feedback--important,#c9190b)))}:host([color=important][circled]:not([circled=false])){background-color:#c9190b;background-color:var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--feedback--important,#c9190b));border-color:#c9190b;border-color:var(--pfe-icon--BorderColor,var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--feedback--important,#c9190b)));--pfe-icon--context:dark}:host([color=moderate]:not([circled])) filter feFlood,:host([color=moderate][circled=false]) filter feFlood{flood-color:#f0ab00;flood-color:var(--pfe-icon--color,var(--pfe-icon--Color,var(--pfe-theme--color--feedback--moderate,#f0ab00)))}:host([color=moderate][circled]:not([circled=false])){background-color:#f0ab00;background-color:var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--feedback--moderate,#f0ab00));border-color:#f0ab00;border-color:var(--pfe-icon--BorderColor,var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--feedback--moderate,#f0ab00)))}:host([color=success]:not([circled])) filter feFlood,:host([color=success][circled=false]) filter feFlood{flood-color:#3e8635;flood-color:var(--pfe-icon--color,var(--pfe-icon--Color,var(--pfe-theme--color--feedback--success,#3e8635)))}:host([color=success][circled]:not([circled=false])){background-color:#3e8635;background-color:var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--feedback--success,#3e8635));border-color:#3e8635;border-color:var(--pfe-icon--BorderColor,var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--feedback--success,#3e8635)));--pfe-icon--context:dark}:host([color=info]:not([circled])) filter feFlood,:host([color=info][circled=false]) filter feFlood{flood-color:#06c;flood-color:var(--pfe-icon--color,var(--pfe-icon--Color,var(--pfe-theme--color--feedback--info,#06c)))}:host([color=info][circled]:not([circled=false])){background-color:#06c;background-color:var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--feedback--info,#06c));border-color:#06c;border-color:var(--pfe-icon--BorderColor,var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--feedback--info,#06c)));--pfe-icon--context:dark}:host([color=default]:not([circled])) filter feFlood,:host([color=default][circled=false]) filter feFlood{flood-color:#4f5255;flood-color:var(--pfe-icon--color,var(--pfe-icon--Color,var(--pfe-theme--color--feedback--default,#4f5255)))}:host([color=default][circled]:not([circled=false])){background-color:#4f5255;background-color:var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--feedback--default,#4f5255));border-color:#4f5255;border-color:var(--pfe-icon--BorderColor,var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--feedback--default,#4f5255)));--pfe-icon--context:dark}:host([color=lightest]:not([circled])) filter feFlood,:host([color=lightest][circled=false]) filter feFlood{flood-color:#fff;flood-color:var(--pfe-icon--color,var(--pfe-icon--Color,var(--pfe-theme--color--surface--lightest,#fff)))}:host([color=lightest][circled]:not([circled=false])){--pfe-icon--context:var(--pfe-theme--color--surface--lightest--context, light);background-color:#fff;background-color:var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--surface--lightest,#fff));border-color:#fff;border-color:var(--pfe-icon--BorderColor,var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--surface--lightest,#fff)))}:host([color=base]:not([circled])) filter feFlood,:host([color=base][circled=false]) filter feFlood{flood-color:#f0f0f0;flood-color:var(--pfe-icon--color,var(--pfe-icon--Color,var(--pfe-theme--color--surface--base,#f0f0f0)))}:host([color=base][circled]:not([circled=false])){--pfe-icon--context:var(--pfe-theme--color--surface--base--context, light);background-color:#f0f0f0;background-color:var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--surface--base,#f0f0f0));border-color:#f0f0f0;border-color:var(--pfe-icon--BorderColor,var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--surface--base,#f0f0f0)))}:host([color=darker]:not([circled])) filter feFlood,:host([color=darker][circled=false]) filter feFlood{flood-color:#3c3f42;flood-color:var(--pfe-icon--color,var(--pfe-icon--Color,var(--pfe-theme--color--surface--darker,#3c3f42)))}:host([color=darker][circled]:not([circled=false])){--pfe-icon--context:var(--pfe-theme--color--surface--darker--context, dark);background-color:#3c3f42;background-color:var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--surface--darker,#3c3f42));border-color:#3c3f42;border-color:var(--pfe-icon--BorderColor,var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--surface--darker,#3c3f42)))}:host([color=darkest]:not([circled])) filter feFlood,:host([color=darkest][circled=false]) filter feFlood{flood-color:#151515;flood-color:var(--pfe-icon--color,var(--pfe-icon--Color,var(--pfe-theme--color--surface--darkest,#151515)))}:host([color=darkest][circled]:not([circled=false])){--pfe-icon--context:var(--pfe-theme--color--surface--darkest--context, dark);background-color:#151515;background-color:var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--surface--darkest,#151515));border-color:#151515;border-color:var(--pfe-icon--BorderColor,var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--surface--darkest,#151515)))}:host([color=complement]:not([circled])) filter feFlood,:host([color=complement][circled=false]) filter feFlood{flood-color:#002952;flood-color:var(--pfe-icon--color,var(--pfe-icon--Color,var(--pfe-theme--color--surface--complement,#002952)))}:host([color=complement][circled]:not([circled=false])){--pfe-icon--context:var(--pfe-theme--color--surface--complement--context, saturated);background-color:#002952;background-color:var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--surface--complement,#002952));border-color:#002952;border-color:var(--pfe-icon--BorderColor,var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--surface--complement,#002952)))}:host([color=accent]:not([circled])) filter feFlood,:host([color=accent][circled=false]) filter feFlood{flood-color:#004080;flood-color:var(--pfe-icon--color,var(--pfe-icon--Color,var(--pfe-theme--color--surface--accent,#004080)))}:host([color=accent][circled]:not([circled=false])){--pfe-icon--context:var(--pfe-theme--color--surface--accent--context, saturated);background-color:#004080;background-color:var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--surface--accent,#004080));border-color:#004080;border-color:var(--pfe-icon--BorderColor,var(--pfe-icon--BackgroundColor,var(--pfe-theme--color--surface--accent,#004080)))}:host(.load-failed) svg image,:host(.load-failed.has-fallback) svg,:host(.load-failed[on-fail=collapse]) svg{display:none}:host(.load-failed[on-fail=collapse]){max-width:0;max-width:var(--pfe-icon--size,0);max-height:0;max-height:var(--pfe-icon--size,0)}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host(.load-failed[on-fail=collapse]){width:0!important;height:0!important}}:host(.load-failed[on-fail=collapse]) svg{width:0;width:var(--pfe-icon--size,0);height:0;height:var(--pfe-icon--size,0)}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host(.load-failed[on-fail=collapse]) svg{width:0!important;height:0!important}} /*# sourceMappingURL=pfe-icon.min.css.map */</style>
|
|
2489
|
+
<div class="pfe-icon--fallback">
|
|
2490
|
+
<slot></slot>
|
|
2491
|
+
</div>
|
|
2492
|
+
<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20">
|
|
2493
|
+
<filter color-interpolation-filters="sRGB" x="0" y="0" height="100%" width="100%">
|
|
2494
|
+
<feFlood result="COLOR" />
|
|
2495
|
+
<feComposite operator="in" in="COLOR" in2="SourceAlpha" />
|
|
2496
|
+
</filter>
|
|
2497
|
+
<image xlink:href="" width="100%" height="100%"></image>
|
|
2498
|
+
</svg>`;
|
|
2499
|
+
}
|
|
2500
|
+
|
|
2501
|
+
static get tag() {
|
|
2502
|
+
return "pfe-icon";
|
|
2503
|
+
}
|
|
2504
|
+
|
|
2505
|
+
get templateUrl() {
|
|
2506
|
+
return "pfe-icon.html";
|
|
2507
|
+
}
|
|
2508
|
+
|
|
2509
|
+
get styleUrl() {
|
|
2510
|
+
return "pfe-icon.scss";
|
|
2511
|
+
}
|
|
2512
|
+
|
|
2513
|
+
get schemaUrl() {
|
|
2514
|
+
return "pfe-icon.json";
|
|
2515
|
+
} // Declare the type of this component
|
|
2516
|
+
|
|
2517
|
+
|
|
2518
|
+
static get PfeType() {
|
|
2519
|
+
return PFElement.PfeTypes.Content;
|
|
2520
|
+
}
|
|
2521
|
+
|
|
2522
|
+
static get properties() {
|
|
2523
|
+
return {
|
|
2524
|
+
icon: {
|
|
2525
|
+
type: String,
|
|
2526
|
+
observer: "updateIcon",
|
|
2527
|
+
prefix: false
|
|
2528
|
+
},
|
|
2529
|
+
size: {
|
|
2530
|
+
type: String,
|
|
2531
|
+
values: ["xl", "lg", "md", "sm", "1x", "2x", "3x", "4x"],
|
|
2532
|
+
default: "1x"
|
|
2533
|
+
},
|
|
2534
|
+
color: {
|
|
2535
|
+
type: String,
|
|
2536
|
+
values: ["complement", "accent", "lightest", "base", "darker", "darkest", "critical", "important", "moderate", "success", "info"],
|
|
2537
|
+
observer: "_colorChanged"
|
|
2538
|
+
},
|
|
2539
|
+
onFail: {
|
|
2540
|
+
type: String,
|
|
2541
|
+
values: ["collapse"]
|
|
2542
|
+
},
|
|
2543
|
+
circled: {
|
|
2544
|
+
type: Boolean
|
|
2545
|
+
},
|
|
2546
|
+
block: {
|
|
2547
|
+
type: Boolean
|
|
2548
|
+
},
|
|
2549
|
+
// TODO: Deprecated for 1.0
|
|
2550
|
+
oldColor: {
|
|
2551
|
+
type: String,
|
|
2552
|
+
alias: "color",
|
|
2553
|
+
attr: "pfe-color"
|
|
2554
|
+
},
|
|
2555
|
+
// TODO: Deprecated for 1.0
|
|
2556
|
+
oldSize: {
|
|
2557
|
+
type: String,
|
|
2558
|
+
alias: "size",
|
|
2559
|
+
attr: "pfe-size"
|
|
2560
|
+
},
|
|
2561
|
+
// TODO: Deprecated for 1.0
|
|
2562
|
+
oldCircled: {
|
|
2563
|
+
type: Boolean,
|
|
2564
|
+
alias: "circled",
|
|
2565
|
+
attr: "pfe-circled"
|
|
2566
|
+
},
|
|
2567
|
+
// TODO: Deprecated for 1.0
|
|
2568
|
+
oldBlock: {
|
|
2569
|
+
type: Boolean,
|
|
2570
|
+
alias: "block",
|
|
2571
|
+
attr: "data-block"
|
|
2572
|
+
}
|
|
2573
|
+
};
|
|
2574
|
+
}
|
|
2575
|
+
|
|
2576
|
+
static get EVENTS() {
|
|
2577
|
+
return {
|
|
2578
|
+
ADD_ICON_SET: `${this.tag}:add-icon-set`
|
|
2579
|
+
};
|
|
2580
|
+
}
|
|
2581
|
+
|
|
2582
|
+
get upgraded() {
|
|
2583
|
+
return this.image.hasAttribute("xlink:href");
|
|
2584
|
+
}
|
|
2585
|
+
|
|
2586
|
+
_iconLoad() {
|
|
2587
|
+
this.classList.remove("load-failed");
|
|
2588
|
+
}
|
|
2589
|
+
|
|
2590
|
+
_iconLoadError(e) {
|
|
2591
|
+
this.classList.add("load-failed");
|
|
2592
|
+
if (this.hasLightDOM()) this.classList.add("has-fallback");
|
|
2593
|
+
}
|
|
2594
|
+
|
|
2595
|
+
_colorChanged() {
|
|
2596
|
+
// Update the context
|
|
2597
|
+
this.resetContext();
|
|
2598
|
+
}
|
|
2599
|
+
|
|
2600
|
+
constructor() {
|
|
2601
|
+
super(PfeIcon, {
|
|
2602
|
+
type: PfeIcon.PfeType
|
|
2603
|
+
});
|
|
2604
|
+
this._iconLoad = this._iconLoad.bind(this);
|
|
2605
|
+
this._iconLoadError = this._iconLoadError.bind(this);
|
|
2606
|
+
this.image = this.shadowRoot.querySelector("svg image");
|
|
2607
|
+
|
|
2608
|
+
if (this.image) {
|
|
2609
|
+
this.image.addEventListener("load", this._iconLoad);
|
|
2610
|
+
this.image.addEventListener("error", this._iconLoadError);
|
|
2611
|
+
} // Attach a listener for the registration of an icon set
|
|
2612
|
+
// Leaving this attached allows for the registered set to be updated
|
|
2613
|
+
|
|
2614
|
+
|
|
2615
|
+
document.body.addEventListener(PfeIcon.EVENTS.ADD_ICON_SET, () => this.updateIcon());
|
|
2616
|
+
}
|
|
2617
|
+
|
|
2618
|
+
disconnectedCallback() {
|
|
2619
|
+
super.disconnectedCallback();
|
|
2620
|
+
|
|
2621
|
+
if (this.image) {
|
|
2622
|
+
this.image.removeEventListener("load", this._iconLoad);
|
|
2623
|
+
this.image.removeEventListener("error", this._iconLoadError);
|
|
2624
|
+
}
|
|
2625
|
+
}
|
|
2626
|
+
|
|
2627
|
+
updateIcon() {
|
|
2628
|
+
const {
|
|
2629
|
+
set
|
|
2630
|
+
} = PfeIcon.getIconSet(this.icon);
|
|
2631
|
+
|
|
2632
|
+
if (set) {
|
|
2633
|
+
const iconPath = set.resolveIconName(this.icon);
|
|
2634
|
+
this.image.setAttribute("xlink:href", iconPath);
|
|
2635
|
+
|
|
2636
|
+
_setRandomFilterId(this);
|
|
2637
|
+
}
|
|
2638
|
+
}
|
|
2639
|
+
/**
|
|
2640
|
+
* Get an icon set by providing the set's name, _or_ the name of an icon from that set.
|
|
2641
|
+
*
|
|
2642
|
+
* @param {String} iconName the name of the set, or the name of an icon from that set.
|
|
2643
|
+
* @return {PfeIconSet} the icon set
|
|
2644
|
+
*/
|
|
2645
|
+
|
|
2646
|
+
|
|
2647
|
+
static getIconSet(iconName) {
|
|
2648
|
+
let set;
|
|
2649
|
+
|
|
2650
|
+
if (iconName) {
|
|
2651
|
+
const [setName] = iconName.split("-");
|
|
2652
|
+
set = this._iconSets[setName];
|
|
2653
|
+
}
|
|
2654
|
+
|
|
2655
|
+
return {
|
|
2656
|
+
set
|
|
2657
|
+
};
|
|
2658
|
+
}
|
|
2659
|
+
|
|
2660
|
+
static addIconSet(name, path, resolveIconName) {
|
|
2661
|
+
let resolveFunction;
|
|
2662
|
+
|
|
2663
|
+
if (typeof resolveIconName === "function") {
|
|
2664
|
+
resolveFunction = resolveIconName;
|
|
2665
|
+
} else if (typeof resolveIconName === "undefined" && this._iconSets[name] && typeof this._iconSets[name]._resolveIconName === "function") {
|
|
2666
|
+
resolveFunction = this._iconSets[name]._resolveIconName;
|
|
2667
|
+
} else if (typeof resolveIconName !== "function" && typeof resolveIconName !== "undefined") {
|
|
2668
|
+
PfeIcon.warn(`[${this.tag}]: The third input to addIconSet should be a function that parses and returns the icon's filename.`);
|
|
2669
|
+
} else {
|
|
2670
|
+
PfeIcon.warn(`[${this.tag}]: The set ${name} needs a resolve function for the icon names.`);
|
|
2671
|
+
} // Register the icon set and set up the event indicating the change
|
|
2672
|
+
|
|
2673
|
+
|
|
2674
|
+
this._iconSets[name] = new PfeIconSet(name, path, resolveFunction);
|
|
2675
|
+
document.body.dispatchEvent(new CustomEvent(this.EVENTS.ADD_ICON_SET, {
|
|
2676
|
+
bubbles: false,
|
|
2677
|
+
detail: {
|
|
2678
|
+
set: this._iconSets[name]
|
|
2679
|
+
}
|
|
2680
|
+
}));
|
|
2681
|
+
}
|
|
2682
|
+
|
|
2683
|
+
}
|
|
2684
|
+
|
|
2685
|
+
PfeIcon._iconSets = {}; // Allow the user to supply their own icon sets via config.
|
|
2686
|
+
// See more in the pfe-icon README.md.
|
|
2687
|
+
|
|
2688
|
+
const config = PFElement.config;
|
|
2689
|
+
addBuiltIns({
|
|
2690
|
+
PfeIcon,
|
|
2691
|
+
config
|
|
2692
|
+
});
|
|
2693
|
+
PFElement.create(PfeIcon);
|
|
2694
|
+
|
|
2695
|
+
/*! *****************************************************************************
|
|
2696
|
+
Copyright (c) Microsoft Corporation.
|
|
2697
|
+
|
|
2698
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
2699
|
+
purpose with or without fee is hereby granted.
|
|
2700
|
+
|
|
2701
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
2702
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
2703
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
2704
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
2705
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
2706
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
2707
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
2708
|
+
***************************************************************************** */
|
|
2709
|
+
function __rest(s, e) {
|
|
2710
|
+
var t = {};
|
|
2711
|
+
|
|
2712
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
|
|
2713
|
+
|
|
2714
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
2715
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
|
|
2716
|
+
}
|
|
2717
|
+
return t;
|
|
2718
|
+
}
|
|
2719
|
+
|
|
2720
|
+
import('./inline-edit-b186d03c.js');
|
|
2721
|
+
var inlineStyles = {
|
|
2722
|
+
"button": "pf-c-button",
|
|
2723
|
+
"inlineEdit": "pf-c-inline-edit",
|
|
2724
|
+
"inlineEditAction": "pf-c-inline-edit__action",
|
|
2725
|
+
"inlineEditEditableText": "pf-c-inline-edit__editable-text",
|
|
2726
|
+
"inlineEditGroup": "pf-c-inline-edit__group",
|
|
2727
|
+
"inlineEditInput": "pf-c-inline-edit__input",
|
|
2728
|
+
"inlineEditLabel": "pf-c-inline-edit__label",
|
|
2729
|
+
"inlineEditValue": "pf-c-inline-edit__value",
|
|
2730
|
+
"modifiers": {
|
|
2731
|
+
"iconGroup": "pf-m-icon-group",
|
|
2732
|
+
"footer": "pf-m-footer",
|
|
2733
|
+
"column": "pf-m-column",
|
|
2734
|
+
"valid": "pf-m-valid",
|
|
2735
|
+
"plain": "pf-m-plain",
|
|
2736
|
+
"actionGroup": "pf-m-action-group",
|
|
2737
|
+
"enableEditable": "pf-m-enable-editable",
|
|
2738
|
+
"inlineEditable": "pf-m-inline-editable",
|
|
2739
|
+
"enable": "pf-m-enable",
|
|
2740
|
+
"bold": "pf-m-bold"
|
|
2741
|
+
}
|
|
2742
|
+
};
|
|
2743
|
+
|
|
2744
|
+
/** Joins args into a className string
|
|
2745
|
+
*
|
|
2746
|
+
* @param {any} args list of objects, string, or arrays to reduce
|
|
2747
|
+
*/
|
|
2748
|
+
function css(...args) {
|
|
2749
|
+
// Adapted from https://github.com/JedWatson/classnames/blob/master/index.js
|
|
2750
|
+
const classes = [];
|
|
2751
|
+
const hasOwn = {}.hasOwnProperty;
|
|
2752
|
+
args.filter(Boolean).forEach((arg) => {
|
|
2753
|
+
const argType = typeof arg;
|
|
2754
|
+
if (argType === 'string' || argType === 'number') {
|
|
2755
|
+
classes.push(arg);
|
|
2756
|
+
}
|
|
2757
|
+
else if (Array.isArray(arg) && arg.length) {
|
|
2758
|
+
const inner = css(...arg);
|
|
2759
|
+
if (inner) {
|
|
2760
|
+
classes.push(inner);
|
|
2761
|
+
}
|
|
2762
|
+
}
|
|
2763
|
+
else if (argType === 'object') {
|
|
2764
|
+
for (const key in arg) {
|
|
2765
|
+
if (hasOwn.call(arg, key) && arg[key]) {
|
|
2766
|
+
classes.push(key);
|
|
2767
|
+
}
|
|
2768
|
+
}
|
|
2769
|
+
}
|
|
2770
|
+
});
|
|
2771
|
+
return classes.join(' ');
|
|
2772
|
+
}
|
|
2773
|
+
|
|
2774
|
+
import('./table-ffd0513c.js');
|
|
2775
|
+
var styles$1 = {
|
|
2776
|
+
"button": "pf-c-button",
|
|
2777
|
+
"modifiers": {
|
|
2778
|
+
"hidden": "pf-m-hidden",
|
|
2779
|
+
"hiddenOnSm": "pf-m-hidden-on-sm",
|
|
2780
|
+
"visibleOnSm": "pf-m-visible-on-sm",
|
|
2781
|
+
"hiddenOnMd": "pf-m-hidden-on-md",
|
|
2782
|
+
"visibleOnMd": "pf-m-visible-on-md",
|
|
2783
|
+
"hiddenOnLg": "pf-m-hidden-on-lg",
|
|
2784
|
+
"visibleOnLg": "pf-m-visible-on-lg",
|
|
2785
|
+
"hiddenOnXl": "pf-m-hidden-on-xl",
|
|
2786
|
+
"visibleOnXl": "pf-m-visible-on-xl",
|
|
2787
|
+
"hiddenOn_2xl": "pf-m-hidden-on-2xl",
|
|
2788
|
+
"visibleOn_2xl": "pf-m-visible-on-2xl",
|
|
2789
|
+
"fixed": "pf-m-fixed",
|
|
2790
|
+
"stickyHeader": "pf-m-sticky-header",
|
|
2791
|
+
"striped": "pf-m-striped",
|
|
2792
|
+
"expandable": "pf-m-expandable",
|
|
2793
|
+
"stripedEven": "pf-m-striped-even",
|
|
2794
|
+
"ghostRow": "pf-m-ghost-row",
|
|
2795
|
+
"center": "pf-m-center",
|
|
2796
|
+
"help": "pf-m-help",
|
|
2797
|
+
"favorite": "pf-m-favorite",
|
|
2798
|
+
"borderRight": "pf-m-border-right",
|
|
2799
|
+
"borderLeft": "pf-m-border-left",
|
|
2800
|
+
"nestedColumnHeader": "pf-m-nested-column-header",
|
|
2801
|
+
"truncate": "pf-m-truncate",
|
|
2802
|
+
"wrap": "pf-m-wrap",
|
|
2803
|
+
"nowrap": "pf-m-nowrap",
|
|
2804
|
+
"fitContent": "pf-m-fit-content",
|
|
2805
|
+
"breakWord": "pf-m-break-word",
|
|
2806
|
+
"noBorderRows": "pf-m-no-border-rows",
|
|
2807
|
+
"expanded": "pf-m-expanded",
|
|
2808
|
+
"hoverable": "pf-m-hoverable",
|
|
2809
|
+
"selected": "pf-m-selected",
|
|
2810
|
+
"firstCellOffsetReset": "pf-m-first-cell-offset-reset",
|
|
2811
|
+
"dragOver": "pf-m-drag-over",
|
|
2812
|
+
"favorited": "pf-m-favorited",
|
|
2813
|
+
"noPadding": "pf-m-no-padding",
|
|
2814
|
+
"compact": "pf-m-compact",
|
|
2815
|
+
"width_10": "pf-m-width-10",
|
|
2816
|
+
"width_15": "pf-m-width-15",
|
|
2817
|
+
"width_20": "pf-m-width-20",
|
|
2818
|
+
"width_25": "pf-m-width-25",
|
|
2819
|
+
"width_30": "pf-m-width-30",
|
|
2820
|
+
"width_35": "pf-m-width-35",
|
|
2821
|
+
"width_40": "pf-m-width-40",
|
|
2822
|
+
"width_45": "pf-m-width-45",
|
|
2823
|
+
"width_50": "pf-m-width-50",
|
|
2824
|
+
"width_60": "pf-m-width-60",
|
|
2825
|
+
"width_70": "pf-m-width-70",
|
|
2826
|
+
"width_80": "pf-m-width-80",
|
|
2827
|
+
"width_90": "pf-m-width-90",
|
|
2828
|
+
"width_100": "pf-m-width-100"
|
|
2829
|
+
},
|
|
2830
|
+
"table": "pf-c-table",
|
|
2831
|
+
"tableAction": "pf-c-table__action",
|
|
2832
|
+
"tableButton": "pf-c-table__button",
|
|
2833
|
+
"tableButtonContent": "pf-c-table__button-content",
|
|
2834
|
+
"tableCheck": "pf-c-table__check",
|
|
2835
|
+
"tableColumnHelp": "pf-c-table__column-help",
|
|
2836
|
+
"tableColumnHelpAction": "pf-c-table__column-help-action",
|
|
2837
|
+
"tableCompoundExpansionToggle": "pf-c-table__compound-expansion-toggle",
|
|
2838
|
+
"tableControlRow": "pf-c-table__control-row",
|
|
2839
|
+
"tableDraggable": "pf-c-table__draggable",
|
|
2840
|
+
"tableExpandableRow": "pf-c-table__expandable-row",
|
|
2841
|
+
"tableExpandableRowContent": "pf-c-table__expandable-row-content",
|
|
2842
|
+
"tableFavorite": "pf-c-table__favorite",
|
|
2843
|
+
"tableIcon": "pf-c-table__icon",
|
|
2844
|
+
"tableIconInline": "pf-c-table__icon-inline",
|
|
2845
|
+
"tableInlineEditAction": "pf-c-table__inline-edit-action",
|
|
2846
|
+
"tableSort": "pf-c-table__sort",
|
|
2847
|
+
"tableSortIndicator": "pf-c-table__sort-indicator",
|
|
2848
|
+
"tableSubhead": "pf-c-table__subhead",
|
|
2849
|
+
"tableText": "pf-c-table__text",
|
|
2850
|
+
"tableToggle": "pf-c-table__toggle",
|
|
2851
|
+
"tableToggleIcon": "pf-c-table__toggle-icon",
|
|
2852
|
+
"themeDark": "pf-theme-dark"
|
|
2853
|
+
};
|
|
2854
|
+
|
|
2855
|
+
import('./table-grid-5d7f8359.js');
|
|
2856
|
+
var stylesGrid = {
|
|
2857
|
+
"button": "pf-c-button",
|
|
2858
|
+
"modifiers": {
|
|
2859
|
+
"grid": "pf-m-grid",
|
|
2860
|
+
"compact": "pf-m-compact",
|
|
2861
|
+
"expanded": "pf-m-expanded",
|
|
2862
|
+
"selected": "pf-m-selected",
|
|
2863
|
+
"noPadding": "pf-m-no-padding",
|
|
2864
|
+
"hoverable": "pf-m-hoverable",
|
|
2865
|
+
"nowrap": "pf-m-nowrap",
|
|
2866
|
+
"fitContent": "pf-m-fit-content",
|
|
2867
|
+
"truncate": "pf-m-truncate",
|
|
2868
|
+
"gridMd": "pf-m-grid-md",
|
|
2869
|
+
"gridLg": "pf-m-grid-lg",
|
|
2870
|
+
"gridXl": "pf-m-grid-xl",
|
|
2871
|
+
"grid_2xl": "pf-m-grid-2xl"
|
|
2872
|
+
},
|
|
2873
|
+
"table": "pf-c-table",
|
|
2874
|
+
"tableAction": "pf-c-table__action",
|
|
2875
|
+
"tableButton": "pf-c-table__button",
|
|
2876
|
+
"tableCheck": "pf-c-table__check",
|
|
2877
|
+
"tableCompoundExpansionToggle": "pf-c-table__compound-expansion-toggle",
|
|
2878
|
+
"tableExpandableRow": "pf-c-table__expandable-row",
|
|
2879
|
+
"tableExpandableRowContent": "pf-c-table__expandable-row-content",
|
|
2880
|
+
"tableFavorite": "pf-c-table__favorite",
|
|
2881
|
+
"tableIcon": "pf-c-table__icon",
|
|
2882
|
+
"tableInlineEditAction": "pf-c-table__inline-edit-action",
|
|
2883
|
+
"tableText": "pf-c-table__text",
|
|
2884
|
+
"tableToggle": "pf-c-table__toggle",
|
|
2885
|
+
"tableToggleIcon": "pf-c-table__toggle-icon"
|
|
2886
|
+
};
|
|
2887
|
+
|
|
2888
|
+
import('./table-tree-view-ee6ac38a.js');
|
|
2889
|
+
var stylesTreeView = {
|
|
2890
|
+
"dropdown": "pf-c-dropdown",
|
|
2891
|
+
"modifiers": {
|
|
2892
|
+
"treeView": "pf-m-tree-view",
|
|
2893
|
+
"treeViewGrid": "pf-m-tree-view-grid",
|
|
2894
|
+
"treeViewDetailsExpanded": "pf-m-tree-view-details-expanded",
|
|
2895
|
+
"treeViewGridMd": "pf-m-tree-view-grid-md",
|
|
2896
|
+
"treeViewGridLg": "pf-m-tree-view-grid-lg",
|
|
2897
|
+
"treeViewGridXl": "pf-m-tree-view-grid-xl",
|
|
2898
|
+
"treeViewGrid_2xl": "pf-m-tree-view-grid-2xl"
|
|
2899
|
+
},
|
|
2900
|
+
"table": "pf-c-table",
|
|
2901
|
+
"tableAction": "pf-c-table__action",
|
|
2902
|
+
"tableCheck": "pf-c-table__check",
|
|
2903
|
+
"tableToggle": "pf-c-table__toggle",
|
|
2904
|
+
"tableToggleIcon": "pf-c-table__toggle-icon",
|
|
2905
|
+
"tableTreeViewDetailsToggle": "pf-c-table__tree-view-details-toggle",
|
|
2906
|
+
"tableTreeViewIcon": "pf-c-table__tree-view-icon",
|
|
2907
|
+
"tableTreeViewMain": "pf-c-table__tree-view-main",
|
|
2908
|
+
"tableTreeViewText": "pf-c-table__tree-view-text",
|
|
2909
|
+
"tableTreeViewTitleCell": "pf-c-table__tree-view-title-cell",
|
|
2910
|
+
"tableTreeViewTitleHeaderCell": "pf-c-table__tree-view-title-header-cell"
|
|
2911
|
+
};
|
|
2912
|
+
|
|
2913
|
+
const camelize = (s) => s
|
|
2914
|
+
.toUpperCase()
|
|
2915
|
+
.replace('-', '')
|
|
2916
|
+
.replace('_', '');
|
|
2917
|
+
const toCamel = (s) => s.replace(/([-_][a-z])/gi, camelize);
|
|
2918
|
+
/**
|
|
2919
|
+
* @param {string} input - String to capitalize
|
|
2920
|
+
*/
|
|
2921
|
+
function capitalize(input) {
|
|
2922
|
+
return input[0].toUpperCase() + input.substring(1);
|
|
2923
|
+
}
|
|
2924
|
+
|
|
2925
|
+
var TableGridBreakpoint;
|
|
2926
|
+
(function (TableGridBreakpoint) {
|
|
2927
|
+
TableGridBreakpoint["none"] = "";
|
|
2928
|
+
TableGridBreakpoint["grid"] = "grid";
|
|
2929
|
+
TableGridBreakpoint["gridMd"] = "grid-md";
|
|
2930
|
+
TableGridBreakpoint["gridLg"] = "grid-lg";
|
|
2931
|
+
TableGridBreakpoint["gridXl"] = "grid-xl";
|
|
2932
|
+
TableGridBreakpoint["grid2xl"] = "grid-2xl";
|
|
2933
|
+
})(TableGridBreakpoint || (TableGridBreakpoint = {}));
|
|
2934
|
+
var TableVariant;
|
|
2935
|
+
(function (TableVariant) {
|
|
2936
|
+
TableVariant["compact"] = "compact";
|
|
2937
|
+
})(TableVariant || (TableVariant = {}));
|
|
2938
|
+
|
|
2939
|
+
const TableComposableContext = React.createContext({
|
|
2940
|
+
registerSelectableRow: () => { }
|
|
2941
|
+
});
|
|
2942
|
+
const TableComposableBase = (_a) => {
|
|
2943
|
+
var _b, _c;
|
|
2944
|
+
var { children, className, variant, borders = true, isStickyHeader = false, gridBreakPoint = TableGridBreakpoint.gridMd, 'aria-label': ariaLabel, role = 'grid', innerRef, ouiaId, ouiaSafe = true, isTreeTable = false, isNested = false, isStriped = false, isExpandable = false,
|
|
2945
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2946
|
+
nestedHeaderColumnSpans, hasSelectableRowCaption, selectableRowCaptionText } = _a, props = __rest(_a, ["children", "className", "variant", "borders", "isStickyHeader", "gridBreakPoint", 'aria-label', "role", "innerRef", "ouiaId", "ouiaSafe", "isTreeTable", "isNested", "isStriped", "isExpandable", "nestedHeaderColumnSpans", "hasSelectableRowCaption", "selectableRowCaptionText"]);
|
|
2947
|
+
const tableRef = innerRef || React.useRef(null);
|
|
2948
|
+
const [hasSelectableRows, setHasSelectableRows] = React.useState(false);
|
|
2949
|
+
const [tableCaption, setTableCaption] = React.useState();
|
|
2950
|
+
React.useEffect(() => {
|
|
2951
|
+
document.addEventListener('keydown', handleKeys);
|
|
2952
|
+
// sets up roving tab-index to tree tables only
|
|
2953
|
+
if (tableRef && tableRef.current && tableRef.current.classList.contains('pf-m-tree-view')) {
|
|
2954
|
+
const tbody = tableRef.current.querySelector('tbody');
|
|
2955
|
+
tbody && setTabIndex(Array.from(tbody.querySelectorAll('button, a, input')));
|
|
2956
|
+
}
|
|
2957
|
+
return function cleanup() {
|
|
2958
|
+
document.removeEventListener('keydown', handleKeys);
|
|
2959
|
+
};
|
|
2960
|
+
}, [tableRef, tableRef.current]);
|
|
2961
|
+
React.useEffect(() => {
|
|
2962
|
+
if (selectableRowCaptionText) {
|
|
2963
|
+
setTableCaption(React.createElement("caption", null,
|
|
2964
|
+
selectableRowCaptionText,
|
|
2965
|
+
React.createElement("div", { className: "pf-screen-reader" }, "This table has selectable rows. It can be navigated by row using tab, and each row can be selected using space or enter.")));
|
|
2966
|
+
}
|
|
2967
|
+
else {
|
|
2968
|
+
setTableCaption(React.createElement("caption", { className: "pf-screen-reader" }, "This table has selectable rows. It can be navigated by row using tab, and each row can be selected using space or enter."));
|
|
2969
|
+
}
|
|
2970
|
+
}, [selectableRowCaptionText]);
|
|
2971
|
+
const ouiaProps = useOUIAProps('Table', ouiaId, ouiaSafe);
|
|
2972
|
+
const grid = (_b = stylesGrid.modifiers) === null || _b === void 0 ? void 0 : _b[toCamel(gridBreakPoint || '').replace(/-?2xl/, '_2xl')];
|
|
2973
|
+
const breakPointPrefix = `treeView${gridBreakPoint.charAt(0).toUpperCase() + gridBreakPoint.slice(1)}`;
|
|
2974
|
+
const treeGrid = (_c = stylesTreeView.modifiers) === null || _c === void 0 ? void 0 : _c[toCamel(breakPointPrefix || '').replace(/-?2xl/, '_2xl')];
|
|
2975
|
+
const handleKeys = (event) => {
|
|
2976
|
+
if (isNested ||
|
|
2977
|
+
!(tableRef && tableRef.current && tableRef.current.classList.contains('pf-m-tree-view')) || // implements roving tab-index to tree tables only
|
|
2978
|
+
(tableRef && tableRef.current !== event.target.closest('.pf-c-table:not(.pf-m-nested)'))) {
|
|
2979
|
+
return;
|
|
2980
|
+
}
|
|
2981
|
+
const activeElement = document.activeElement;
|
|
2982
|
+
const key = event.key;
|
|
2983
|
+
const rows = Array.from(tableRef.current.querySelectorAll('tbody tr')).filter(el => !el.classList.contains('pf-m-disabled') && !el.hidden);
|
|
2984
|
+
if (key === 'Space' || key === 'Enter') {
|
|
2985
|
+
activeElement.click();
|
|
2986
|
+
event.preventDefault();
|
|
2987
|
+
}
|
|
2988
|
+
const getFocusableElement = (element) => element.querySelectorAll('button:not(:disabled), input:not(:disabled), a:not(:disabled)')[0];
|
|
2989
|
+
handleArrows(event, rows, (element) => element === activeElement.closest('tr'), getFocusableElement, ['button', 'input', 'a'], undefined, false, true, false);
|
|
2990
|
+
};
|
|
2991
|
+
const registerSelectableRow = () => {
|
|
2992
|
+
!hasSelectableRows && setHasSelectableRows(true);
|
|
2993
|
+
};
|
|
2994
|
+
return (React.createElement(TableComposableContext.Provider, { value: { registerSelectableRow } },
|
|
2995
|
+
React.createElement("table", Object.assign({ "aria-label": ariaLabel, role: role, className: css(className, styles$1.table, isTreeTable ? treeGrid : grid, styles$1.modifiers[variant], !borders && styles$1.modifiers.noBorderRows, isStickyHeader && styles$1.modifiers.stickyHeader, isTreeTable && stylesTreeView.modifiers.treeView, isStriped && styles$1.modifiers.striped, isExpandable && styles$1.modifiers.expandable, isNested && 'pf-m-nested'), ref: tableRef }, (isTreeTable && { role: 'treegrid' }), ouiaProps, props),
|
|
2996
|
+
hasSelectableRowCaption && hasSelectableRows && tableCaption,
|
|
2997
|
+
children)));
|
|
2998
|
+
};
|
|
2999
|
+
const TableComposable = React.forwardRef((props, ref) => (React.createElement(TableComposableBase, Object.assign({}, props, { innerRef: ref }))));
|
|
3000
|
+
TableComposable.displayName = 'TableComposable';
|
|
3001
|
+
|
|
3002
|
+
const TheadBase = (_a) => {
|
|
3003
|
+
var { children, className, noWrap = false, innerRef, hasNestedHeader } = _a, props = __rest(_a, ["children", "className", "noWrap", "innerRef", "hasNestedHeader"]);
|
|
3004
|
+
return (React.createElement("thead", Object.assign({ className: css(className, noWrap && styles$1.modifiers.nowrap, hasNestedHeader && styles$1.modifiers.nestedColumnHeader), ref: innerRef }, props), children));
|
|
3005
|
+
};
|
|
3006
|
+
const Thead = React.forwardRef((props, ref) => (React.createElement(TheadBase, Object.assign({}, props, { innerRef: ref }))));
|
|
3007
|
+
Thead.displayName = 'Thead';
|
|
3008
|
+
|
|
3009
|
+
const TbodyBase = (_a) => {
|
|
3010
|
+
var { children, className, isExpanded, innerRef, isEvenStriped = false, isOddStriped = false } = _a, props = __rest(_a, ["children", "className", "isExpanded", "innerRef", "isEvenStriped", "isOddStriped"]);
|
|
3011
|
+
return (React.createElement("tbody", Object.assign({ role: "rowgroup", className: css(className, isExpanded && styles$1.modifiers.expanded, isOddStriped && styles$1.modifiers.striped, isEvenStriped && styles$1.modifiers.stripedEven), ref: innerRef }, props), children));
|
|
3012
|
+
};
|
|
3013
|
+
const Tbody = React.forwardRef((props, ref) => (React.createElement(TbodyBase, Object.assign({}, props, { innerRef: ref }))));
|
|
3014
|
+
Tbody.displayName = 'Tbody';
|
|
3015
|
+
|
|
3016
|
+
const TrBase = (_a) => {
|
|
3017
|
+
var { children, className, isExpanded, isEditable, isHidden = false, isHoverable = false, isRowSelected = false, isStriped = false, innerRef, ouiaId, ouiaSafe = true, resetOffset = false, onRowClick, isSelectable, 'aria-label': passedAriaLabel } = _a, props = __rest(_a, ["children", "className", "isExpanded", "isEditable", "isHidden", "isHoverable", "isRowSelected", "isStriped", "innerRef", "ouiaId", "ouiaSafe", "resetOffset", "onRowClick", "isSelectable", 'aria-label']);
|
|
3018
|
+
const ouiaProps = useOUIAProps('TableRow', ouiaId, ouiaSafe);
|
|
3019
|
+
const [computedAriaLabel, setComputedAriaLabel] = React.useState('');
|
|
3020
|
+
let onKeyDown = null;
|
|
3021
|
+
if (onRowClick) {
|
|
3022
|
+
onKeyDown = (e) => {
|
|
3023
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
3024
|
+
onRowClick(e);
|
|
3025
|
+
e.preventDefault();
|
|
3026
|
+
}
|
|
3027
|
+
};
|
|
3028
|
+
}
|
|
3029
|
+
const rowIsHidden = isHidden || (isExpanded !== undefined && !isExpanded);
|
|
3030
|
+
const { registerSelectableRow } = React.useContext(TableComposableContext);
|
|
3031
|
+
React.useEffect(() => {
|
|
3032
|
+
if (isSelectable && !rowIsHidden) {
|
|
3033
|
+
setComputedAriaLabel(`${isRowSelected ? 'Selected' : 'Unselected'}, selectable row.`);
|
|
3034
|
+
registerSelectableRow();
|
|
3035
|
+
}
|
|
3036
|
+
else {
|
|
3037
|
+
setComputedAriaLabel(undefined);
|
|
3038
|
+
}
|
|
3039
|
+
}, [isRowSelected, isSelectable, registerSelectableRow, rowIsHidden]);
|
|
3040
|
+
const ariaLabel = passedAriaLabel || computedAriaLabel;
|
|
3041
|
+
return (React.createElement(React.Fragment, null,
|
|
3042
|
+
isSelectable && React.createElement("output", { className: "pf-screen-reader" }, ariaLabel),
|
|
3043
|
+
React.createElement("tr", Object.assign({ className: css(className, isExpanded !== undefined && styles$1.tableExpandableRow, isExpanded && styles$1.modifiers.expanded, isEditable && inlineStyles.modifiers.inlineEditable, isHoverable && styles$1.modifiers.hoverable, isRowSelected && styles$1.modifiers.selected, isStriped && styles$1.modifiers.striped, resetOffset && styles$1.modifiers.firstCellOffsetReset), hidden: rowIsHidden }, (isHoverable && { tabIndex: 0 }), { "aria-label": ariaLabel, ref: innerRef }, (onRowClick && { onClick: onRowClick, onKeyDown }), ouiaProps, props), children)));
|
|
3044
|
+
};
|
|
3045
|
+
const Tr = React.forwardRef((props, ref) => (React.createElement(TrBase, Object.assign({}, props, { innerRef: ref }))));
|
|
3046
|
+
Tr.displayName = 'Tr';
|
|
3047
|
+
|
|
3048
|
+
import('./table-scrollable-01103545.js');
|
|
3049
|
+
var styles = {
|
|
3050
|
+
"modifiers": {
|
|
3051
|
+
"borderRight": "pf-m-border-right",
|
|
3052
|
+
"borderLeft": "pf-m-border-left",
|
|
3053
|
+
"stickyHeader": "pf-m-sticky-header"
|
|
3054
|
+
},
|
|
3055
|
+
"scrollInnerWrapper": "pf-c-scroll-inner-wrapper",
|
|
3056
|
+
"scrollOuterWrapper": "pf-c-scroll-outer-wrapper",
|
|
3057
|
+
"table": "pf-c-table",
|
|
3058
|
+
"tableStickyColumn": "pf-c-table__sticky-column"
|
|
3059
|
+
};
|
|
3060
|
+
|
|
3061
|
+
var IconSize;
|
|
3062
|
+
(function (IconSize) {
|
|
3063
|
+
IconSize["sm"] = "sm";
|
|
3064
|
+
IconSize["md"] = "md";
|
|
3065
|
+
IconSize["lg"] = "lg";
|
|
3066
|
+
IconSize["xl"] = "xl";
|
|
3067
|
+
})(IconSize || (IconSize = {}));
|
|
3068
|
+
const getSize = (size) => {
|
|
3069
|
+
switch (size) {
|
|
3070
|
+
case IconSize.sm:
|
|
3071
|
+
return '1em';
|
|
3072
|
+
case IconSize.md:
|
|
3073
|
+
return '1.5em';
|
|
3074
|
+
case IconSize.lg:
|
|
3075
|
+
return '2em';
|
|
3076
|
+
case IconSize.xl:
|
|
3077
|
+
return '3em';
|
|
3078
|
+
default:
|
|
3079
|
+
return '1em';
|
|
3080
|
+
}
|
|
3081
|
+
};
|
|
3082
|
+
let currentId = 0;
|
|
3083
|
+
/**
|
|
3084
|
+
* Factory to create Icon class components for consumers
|
|
3085
|
+
*/
|
|
3086
|
+
function createIcon({ name, xOffset = 0, yOffset = 0, width, height, svgPath }) {
|
|
3087
|
+
var _a;
|
|
3088
|
+
return _a = class SVGIcon extends React.Component {
|
|
3089
|
+
constructor() {
|
|
3090
|
+
super(...arguments);
|
|
3091
|
+
this.id = `icon-title-${currentId++}`;
|
|
3092
|
+
}
|
|
3093
|
+
render() {
|
|
3094
|
+
const _a = this.props, { size, color, title, noVerticalAlign } = _a, props = __rest(_a, ["size", "color", "title", "noVerticalAlign"]);
|
|
3095
|
+
const hasTitle = Boolean(title);
|
|
3096
|
+
const heightWidth = getSize(size);
|
|
3097
|
+
const baseAlign = -0.125 * Number.parseFloat(heightWidth);
|
|
3098
|
+
const style = noVerticalAlign ? null : { verticalAlign: `${baseAlign}em` };
|
|
3099
|
+
const viewBox = [xOffset, yOffset, width, height].join(' ');
|
|
3100
|
+
return (React.createElement("svg", Object.assign({ style: style, fill: color, height: heightWidth, width: heightWidth, viewBox: viewBox, "aria-labelledby": hasTitle ? this.id : null, "aria-hidden": hasTitle ? null : true, role: "img" }, props),
|
|
3101
|
+
hasTitle && React.createElement("title", { id: this.id }, title),
|
|
3102
|
+
React.createElement("path", { d: svgPath })));
|
|
3103
|
+
}
|
|
3104
|
+
},
|
|
3105
|
+
_a.displayName = name,
|
|
3106
|
+
_a.defaultProps = {
|
|
3107
|
+
color: 'currentColor',
|
|
3108
|
+
size: IconSize.sm,
|
|
3109
|
+
noVerticalAlign: false
|
|
3110
|
+
},
|
|
3111
|
+
_a;
|
|
3112
|
+
}
|
|
3113
|
+
|
|
3114
|
+
const HelpIconConfig = {
|
|
3115
|
+
name: 'HelpIcon',
|
|
3116
|
+
height: 1024,
|
|
3117
|
+
width: 1024,
|
|
3118
|
+
svgPath: 'M521.3,576 C627.5,576 713.7,502 713.7,413.7 C713.7,325.4 627.6,253.6 521.3,253.6 C366,253.6 334.5,337.7 329.2,407.2 C329.2,414.3 335.2,416 343.5,416 L445,416 C450.5,416 458,415.5 460.8,406.5 C460.8,362.6 582.9,357.1 582.9,413.6 C582.9,441.9 556.2,470.9 521.3,473 C486.4,475.1 447.3,479.8 447.3,521.7 L447.3,553.8 C447.3,570.8 456.1,576 472,576 C487.9,576 521.3,576 521.3,576 M575.3,751.3 L575.3,655.3 C575.313862,651.055109 573.620137,646.982962 570.6,644 C567.638831,640.947672 563.552355,639.247987 559.3,639.29884 L463.3,639.29884 C459.055109,639.286138 454.982962,640.979863 452,644 C448.947672,646.961169 447.247987,651.047645 447.29884,655.3 L447.29884,751.3 C447.286138,755.544891 448.979863,759.617038 452,762.6 C454.961169,765.652328 459.047645,767.352013 463.3,767.30116 L559.3,767.30116 C563.544891,767.313862 567.617038,765.620137 570.6,762.6 C573.659349,759.643612 575.360354,755.553963 575.3,751.3 M512,896 C300.2,896 128,723.9 128,512 C128,300.3 300.2,128 512,128 C723.8,128 896,300.2 896,512 C896,723.8 723.7,896 512,896 M512.1,0 C229.7,0 0,229.8 0,512 C0,794.2 229.8,1024 512.1,1024 C794.4,1024 1024,794.3 1024,512 C1024,229.7 794.4,0 512.1,0',
|
|
3119
|
+
yOffset: 0,
|
|
3120
|
+
xOffset: 0,
|
|
3121
|
+
};
|
|
3122
|
+
|
|
3123
|
+
const HelpIcon = createIcon(HelpIconConfig);
|
|
3124
|
+
|
|
3125
|
+
var HelpIcon$1 = HelpIcon;
|
|
3126
|
+
|
|
3127
|
+
var TableTextVariant;
|
|
3128
|
+
(function (TableTextVariant) {
|
|
3129
|
+
TableTextVariant["div"] = "div";
|
|
3130
|
+
TableTextVariant["nav"] = "nav";
|
|
3131
|
+
})(TableTextVariant || (TableTextVariant = {}));
|
|
3132
|
+
var WrapModifier;
|
|
3133
|
+
(function (WrapModifier) {
|
|
3134
|
+
WrapModifier["wrap"] = "wrap";
|
|
3135
|
+
WrapModifier["nowrap"] = "nowrap";
|
|
3136
|
+
WrapModifier["truncate"] = "truncate";
|
|
3137
|
+
WrapModifier["breakWord"] = "breakWord";
|
|
3138
|
+
WrapModifier["fitContent"] = "fitContent";
|
|
3139
|
+
})(WrapModifier || (WrapModifier = {}));
|
|
3140
|
+
const TableText = (_a) => {
|
|
3141
|
+
var { children = null, className = '', variant = 'span', wrapModifier = null, tooltip: tooltipProp = '', tooltipProps = {}, onMouseEnter: onMouseEnterProp = () => { } } = _a, props = __rest(_a, ["children", "className", "variant", "wrapModifier", "tooltip", "tooltipProps", "onMouseEnter"]);
|
|
3142
|
+
const Component = variant;
|
|
3143
|
+
const [tooltip, setTooltip] = React.useState('');
|
|
3144
|
+
const onMouseEnter = (event) => {
|
|
3145
|
+
if (event.target.offsetWidth < event.target.scrollWidth) {
|
|
3146
|
+
setTooltip(tooltipProp || event.target.innerText);
|
|
3147
|
+
}
|
|
3148
|
+
else {
|
|
3149
|
+
setTooltip('');
|
|
3150
|
+
}
|
|
3151
|
+
onMouseEnterProp(event);
|
|
3152
|
+
};
|
|
3153
|
+
const text = (React.createElement(Component, Object.assign({ onMouseEnter: onMouseEnter, className: css(className, wrapModifier && styles$1.modifiers[wrapModifier], styles$1.tableText) }, props), children));
|
|
3154
|
+
return tooltip !== '' ? (React.createElement(Tooltip, Object.assign({ content: tooltip, isVisible: true }, tooltipProps), text)) : (text);
|
|
3155
|
+
};
|
|
3156
|
+
TableText.displayName = 'TableText';
|
|
3157
|
+
|
|
3158
|
+
const HeaderCellInfoWrapper = ({ children, info, className, variant = 'tooltip', popoverProps, tooltipProps, ariaLabel }) => (React.createElement("div", { className: css(styles$1.tableColumnHelp, className) },
|
|
3159
|
+
typeof children === 'string' ? React.createElement(TableText, null, children) : children,
|
|
3160
|
+
React.createElement("span", { className: css(styles$1.tableColumnHelpAction) }, variant === 'tooltip' ? (React.createElement(Tooltip$1, Object.assign({ content: info }, tooltipProps),
|
|
3161
|
+
React.createElement(Button, { variant: "plain", "aria-label": ariaLabel || (typeof info === 'string' && info) || 'More info' },
|
|
3162
|
+
React.createElement(HelpIcon$1, { noVerticalAlign: true })))) : (React.createElement(Popover, Object.assign({ bodyContent: info }, popoverProps),
|
|
3163
|
+
React.createElement(Button, { variant: "plain", "aria-label": ariaLabel || (typeof info === 'string' && info) || 'More info' },
|
|
3164
|
+
React.createElement(HelpIcon$1, { noVerticalAlign: true })))))));
|
|
3165
|
+
HeaderCellInfoWrapper.displayName = 'HeaderCellInfoWrapper';
|
|
3166
|
+
|
|
3167
|
+
const info = ({ tooltip, tooltipProps, popover, popoverProps, className, ariaLabel }) => {
|
|
3168
|
+
const infoObj = (value) => ({
|
|
3169
|
+
className: styles$1.modifiers.help,
|
|
3170
|
+
children: tooltip ? (React.createElement(HeaderCellInfoWrapper, { variant: "tooltip", info: tooltip, tooltipProps: tooltipProps, ariaLabel: ariaLabel, className: className }, value)) : (React.createElement(HeaderCellInfoWrapper, { variant: "popover", info: popover, popoverProps: popoverProps, ariaLabel: ariaLabel, className: className }, value))
|
|
3171
|
+
});
|
|
3172
|
+
return infoObj;
|
|
3173
|
+
};
|
|
3174
|
+
|
|
3175
|
+
const LongArrowAltUpIconConfig = {
|
|
3176
|
+
name: 'LongArrowAltUpIcon',
|
|
3177
|
+
height: 512,
|
|
3178
|
+
width: 256,
|
|
3179
|
+
svgPath: 'M88 166.059V468c0 6.627 5.373 12 12 12h56c6.627 0 12-5.373 12-12V166.059h46.059c21.382 0 32.09-25.851 16.971-40.971l-86.059-86.059c-9.373-9.373-24.569-9.373-33.941 0l-86.059 86.059c-15.119 15.119-4.411 40.971 16.971 40.971H88z',
|
|
3180
|
+
yOffset: 0,
|
|
3181
|
+
xOffset: 0,
|
|
3182
|
+
};
|
|
3183
|
+
|
|
3184
|
+
const LongArrowAltUpIcon = createIcon(LongArrowAltUpIconConfig);
|
|
3185
|
+
|
|
3186
|
+
var LongArrowAltUpIcon$1 = LongArrowAltUpIcon;
|
|
3187
|
+
|
|
3188
|
+
const LongArrowAltDownIconConfig = {
|
|
3189
|
+
name: 'LongArrowAltDownIcon',
|
|
3190
|
+
height: 512,
|
|
3191
|
+
width: 256,
|
|
3192
|
+
svgPath: 'M168 345.941V44c0-6.627-5.373-12-12-12h-56c-6.627 0-12 5.373-12 12v301.941H41.941c-21.382 0-32.09 25.851-16.971 40.971l86.059 86.059c9.373 9.373 24.569 9.373 33.941 0l86.059-86.059c15.119-15.119 4.411-40.971-16.971-40.971H168z',
|
|
3193
|
+
yOffset: 0,
|
|
3194
|
+
xOffset: 0,
|
|
3195
|
+
};
|
|
3196
|
+
|
|
3197
|
+
const LongArrowAltDownIcon = createIcon(LongArrowAltDownIconConfig);
|
|
3198
|
+
|
|
3199
|
+
var LongArrowAltDownIcon$1 = LongArrowAltDownIcon;
|
|
3200
|
+
|
|
3201
|
+
const ArrowsAltVIconConfig = {
|
|
3202
|
+
name: 'ArrowsAltVIcon',
|
|
3203
|
+
height: 512,
|
|
3204
|
+
width: 256,
|
|
3205
|
+
svgPath: 'M214.059 377.941H168V134.059h46.059c21.382 0 32.09-25.851 16.971-40.971L144.971 7.029c-9.373-9.373-24.568-9.373-33.941 0L24.971 93.088c-15.119 15.119-4.411 40.971 16.971 40.971H88v243.882H41.941c-21.382 0-32.09 25.851-16.971 40.971l86.059 86.059c9.373 9.373 24.568 9.373 33.941 0l86.059-86.059c15.12-15.119 4.412-40.971-16.97-40.971z',
|
|
3206
|
+
yOffset: 0,
|
|
3207
|
+
xOffset: 0,
|
|
3208
|
+
};
|
|
3209
|
+
|
|
3210
|
+
const ArrowsAltVIcon = createIcon(ArrowsAltVIconConfig);
|
|
3211
|
+
|
|
3212
|
+
var ArrowsAltVIcon$1 = ArrowsAltVIcon;
|
|
3213
|
+
|
|
3214
|
+
var SortByDirection;
|
|
3215
|
+
(function (SortByDirection) {
|
|
3216
|
+
SortByDirection["asc"] = "asc";
|
|
3217
|
+
SortByDirection["desc"] = "desc";
|
|
3218
|
+
})(SortByDirection || (SortByDirection = {}));
|
|
3219
|
+
const SortColumn = (_a) => {
|
|
3220
|
+
var { children = null, className = '', isSortedBy = false, onSort = null, sortDirection = '', type = 'button' } = _a, props = __rest(_a, ["children", "className", "isSortedBy", "onSort", "sortDirection", "type"]);
|
|
3221
|
+
let SortedByIcon;
|
|
3222
|
+
if (isSortedBy) {
|
|
3223
|
+
SortedByIcon = sortDirection === SortByDirection.asc ? LongArrowAltUpIcon$1 : LongArrowAltDownIcon$1;
|
|
3224
|
+
}
|
|
3225
|
+
else {
|
|
3226
|
+
SortedByIcon = ArrowsAltVIcon$1;
|
|
3227
|
+
}
|
|
3228
|
+
return (React.createElement("button", Object.assign({}, props, { type: type, className: css(className, styles$1.tableButton), onClick: event => onSort && onSort(event) }),
|
|
3229
|
+
React.createElement("div", { className: css(className, styles$1.tableButtonContent) },
|
|
3230
|
+
React.createElement(TableText, null, children),
|
|
3231
|
+
React.createElement("span", { className: css(styles$1.tableSortIndicator) },
|
|
3232
|
+
React.createElement(SortedByIcon, null)))));
|
|
3233
|
+
};
|
|
3234
|
+
SortColumn.displayName = 'SortColumn';
|
|
3235
|
+
|
|
3236
|
+
const StarIconConfig = {
|
|
3237
|
+
name: 'StarIcon',
|
|
3238
|
+
height: 512,
|
|
3239
|
+
width: 576,
|
|
3240
|
+
svgPath: 'M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z',
|
|
3241
|
+
yOffset: 0,
|
|
3242
|
+
xOffset: 0,
|
|
3243
|
+
};
|
|
3244
|
+
|
|
3245
|
+
const StarIcon = createIcon(StarIconConfig);
|
|
3246
|
+
|
|
3247
|
+
var StarIcon$1 = StarIcon;
|
|
3248
|
+
|
|
3249
|
+
const sortableFavorites = (sort) => () => sortable(React.createElement(StarIcon$1, { "aria-hidden": true }), {
|
|
3250
|
+
columnIndex: sort.columnIndex,
|
|
3251
|
+
className: styles$1.modifiers.favorite,
|
|
3252
|
+
ariaLabel: 'Sort favorites',
|
|
3253
|
+
column: {
|
|
3254
|
+
extraParams: {
|
|
3255
|
+
sortBy: sort.sortBy,
|
|
3256
|
+
onSort: sort === null || sort === void 0 ? void 0 : sort.onSort
|
|
3257
|
+
}
|
|
3258
|
+
}
|
|
3259
|
+
});
|
|
3260
|
+
const sortable = (label, { columnIndex, column, property, className, ariaLabel }) => {
|
|
3261
|
+
const { extraParams: { sortBy, onSort } } = column;
|
|
3262
|
+
const extraData = {
|
|
3263
|
+
columnIndex,
|
|
3264
|
+
column,
|
|
3265
|
+
property
|
|
3266
|
+
};
|
|
3267
|
+
const isSortedBy = sortBy && columnIndex === sortBy.index;
|
|
3268
|
+
/**
|
|
3269
|
+
* @param {React.MouseEvent} event - React mouse event
|
|
3270
|
+
*/
|
|
3271
|
+
function sortClicked(event) {
|
|
3272
|
+
let reversedDirection;
|
|
3273
|
+
if (!isSortedBy) {
|
|
3274
|
+
reversedDirection = sortBy.defaultDirection ? sortBy.defaultDirection : SortByDirection.asc;
|
|
3275
|
+
}
|
|
3276
|
+
else {
|
|
3277
|
+
reversedDirection = sortBy.direction === SortByDirection.asc ? SortByDirection.desc : SortByDirection.asc;
|
|
3278
|
+
}
|
|
3279
|
+
// tslint:disable-next-line:no-unused-expression
|
|
3280
|
+
onSort && onSort(event, columnIndex, reversedDirection, extraData);
|
|
3281
|
+
}
|
|
3282
|
+
return {
|
|
3283
|
+
className: css(styles$1.tableSort, isSortedBy && styles$1.modifiers.selected, className),
|
|
3284
|
+
'aria-sort': isSortedBy ? `${sortBy.direction}ending` : 'none',
|
|
3285
|
+
children: (React.createElement(SortColumn, { isSortedBy: isSortedBy, sortDirection: isSortedBy ? sortBy.direction : '', onSort: sortClicked, "aria-label": ariaLabel }, label))
|
|
3286
|
+
};
|
|
3287
|
+
};
|
|
3288
|
+
|
|
3289
|
+
var RowSelectVariant;
|
|
3290
|
+
(function (RowSelectVariant) {
|
|
3291
|
+
RowSelectVariant["radio"] = "radio";
|
|
3292
|
+
RowSelectVariant["checkbox"] = "checkbox";
|
|
3293
|
+
})(RowSelectVariant || (RowSelectVariant = {}));
|
|
3294
|
+
const SelectColumn = (_a) => {
|
|
3295
|
+
var { children = null,
|
|
3296
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
3297
|
+
className, onSelect = null, selectVariant } = _a, props = __rest(_a, ["children", "className", "onSelect", "selectVariant"]);
|
|
3298
|
+
return (React.createElement(React.Fragment, null,
|
|
3299
|
+
React.createElement("label", null,
|
|
3300
|
+
React.createElement("input", Object.assign({}, props, { type: selectVariant, onChange: onSelect }))),
|
|
3301
|
+
children));
|
|
3302
|
+
};
|
|
3303
|
+
SelectColumn.displayName = 'SelectColumn';
|
|
3304
|
+
|
|
3305
|
+
import('./check-317f30b2.js');
|
|
3306
|
+
var checkStyles = {
|
|
3307
|
+
"check": "pf-c-check",
|
|
3308
|
+
"checkBody": "pf-c-check__body",
|
|
3309
|
+
"checkDescription": "pf-c-check__description",
|
|
3310
|
+
"checkInput": "pf-c-check__input",
|
|
3311
|
+
"checkLabel": "pf-c-check__label",
|
|
3312
|
+
"modifiers": {
|
|
3313
|
+
"standalone": "pf-m-standalone",
|
|
3314
|
+
"disabled": "pf-m-disabled"
|
|
3315
|
+
}
|
|
3316
|
+
};
|
|
3317
|
+
|
|
3318
|
+
const selectable = (label, { rowIndex, columnIndex, rowData, column, property }) => {
|
|
3319
|
+
const { extraParams: { onSelect, selectVariant, allRowsSelected, isHeaderSelectDisabled } } = column;
|
|
3320
|
+
const extraData = {
|
|
3321
|
+
rowIndex,
|
|
3322
|
+
columnIndex,
|
|
3323
|
+
column,
|
|
3324
|
+
property
|
|
3325
|
+
};
|
|
3326
|
+
if (rowData && rowData.hasOwnProperty('parent') && !rowData.showSelect && !rowData.fullWidth) {
|
|
3327
|
+
return {
|
|
3328
|
+
component: 'td',
|
|
3329
|
+
isVisible: true
|
|
3330
|
+
};
|
|
3331
|
+
}
|
|
3332
|
+
const rowId = rowIndex !== undefined ? rowIndex : -1;
|
|
3333
|
+
/**
|
|
3334
|
+
* @param {React.FormEvent} event - React form event
|
|
3335
|
+
*/
|
|
3336
|
+
function selectClick(event) {
|
|
3337
|
+
const selected = rowIndex === undefined ? event.currentTarget.checked : rowData && !rowData.selected;
|
|
3338
|
+
// tslint:disable-next-line:no-unused-expression
|
|
3339
|
+
onSelect && onSelect(event, selected, rowId, rowData, extraData);
|
|
3340
|
+
}
|
|
3341
|
+
const customProps = Object.assign(Object.assign(Object.assign({}, (rowId !== -1
|
|
3342
|
+
? {
|
|
3343
|
+
checked: rowData && !!rowData.selected,
|
|
3344
|
+
'aria-label': `Select row ${rowIndex}`
|
|
3345
|
+
}
|
|
3346
|
+
: {
|
|
3347
|
+
checked: allRowsSelected,
|
|
3348
|
+
'aria-label': 'Select all rows'
|
|
3349
|
+
})), (rowData &&
|
|
3350
|
+
(rowData.disableCheckbox || rowData.disableSelection) && {
|
|
3351
|
+
disabled: true,
|
|
3352
|
+
className: checkStyles.checkInput
|
|
3353
|
+
})), (!rowData && isHeaderSelectDisabled && { disabled: true }));
|
|
3354
|
+
let selectName = 'check-all';
|
|
3355
|
+
if (rowId !== -1 && selectVariant === RowSelectVariant.checkbox) {
|
|
3356
|
+
selectName = `checkrow${rowIndex}`;
|
|
3357
|
+
}
|
|
3358
|
+
else if (rowId !== -1) {
|
|
3359
|
+
selectName = 'radioGroup';
|
|
3360
|
+
}
|
|
3361
|
+
return {
|
|
3362
|
+
className: css(styles$1.tableCheck),
|
|
3363
|
+
component: 'td',
|
|
3364
|
+
isVisible: !rowData || !rowData.fullWidth,
|
|
3365
|
+
children: (React.createElement(SelectColumn, Object.assign({}, customProps, { selectVariant: selectVariant, onSelect: selectClick, name: selectName }), label))
|
|
3366
|
+
};
|
|
3367
|
+
};
|
|
3368
|
+
|
|
3369
|
+
const AngleDownIconConfig = {
|
|
3370
|
+
name: 'AngleDownIcon',
|
|
3371
|
+
height: 512,
|
|
3372
|
+
width: 320,
|
|
3373
|
+
svgPath: 'M143 352.3L7 216.3c-9.4-9.4-9.4-24.6 0-33.9l22.6-22.6c9.4-9.4 24.6-9.4 33.9 0l96.4 96.4 96.4-96.4c9.4-9.4 24.6-9.4 33.9 0l22.6 22.6c9.4 9.4 9.4 24.6 0 33.9l-136 136c-9.2 9.4-24.4 9.4-33.8 0z',
|
|
3374
|
+
yOffset: 0,
|
|
3375
|
+
xOffset: 0,
|
|
3376
|
+
};
|
|
3377
|
+
|
|
3378
|
+
const AngleDownIcon = createIcon(AngleDownIconConfig);
|
|
3379
|
+
|
|
3380
|
+
var AngleDownIcon$1 = AngleDownIcon;
|
|
3381
|
+
|
|
3382
|
+
const CollapseColumn = (_a) => {
|
|
3383
|
+
var { className = '', children = null, isOpen, onToggle } = _a, props = __rest(_a, ["className", "children", "isOpen", "onToggle"]);
|
|
3384
|
+
return (React.createElement(React.Fragment, null,
|
|
3385
|
+
isOpen !== undefined && (React.createElement(Button$1, Object.assign({ className: css(className, isOpen && styles$1.modifiers.expanded) }, props, { variant: "plain", "aria-label": props['aria-label'] || 'Details', onClick: onToggle, "aria-expanded": isOpen }),
|
|
3386
|
+
React.createElement("div", { className: css(styles$1.tableToggleIcon) },
|
|
3387
|
+
React.createElement(AngleDownIcon$1, null)))),
|
|
3388
|
+
children));
|
|
3389
|
+
};
|
|
3390
|
+
CollapseColumn.displayName = 'CollapseColumn';
|
|
3391
|
+
|
|
3392
|
+
const collapsible = (value, { rowIndex, columnIndex, rowData, column, property }) => {
|
|
3393
|
+
const { extraParams: { onCollapse, rowLabeledBy = 'simple-node', expandId = 'expand-toggle', allRowsExpanded, collapseAllAriaLabel } } = column;
|
|
3394
|
+
const extraData = {
|
|
3395
|
+
rowIndex,
|
|
3396
|
+
columnIndex,
|
|
3397
|
+
column,
|
|
3398
|
+
property
|
|
3399
|
+
};
|
|
3400
|
+
const rowId = rowIndex !== undefined ? rowIndex : -1;
|
|
3401
|
+
const customProps = Object.assign({}, (rowId !== -1
|
|
3402
|
+
? {
|
|
3403
|
+
isOpen: rowData === null || rowData === void 0 ? void 0 : rowData.isOpen,
|
|
3404
|
+
'aria-labelledby': `${rowLabeledBy}${rowId} ${expandId}${rowId}`
|
|
3405
|
+
}
|
|
3406
|
+
: {
|
|
3407
|
+
isOpen: allRowsExpanded,
|
|
3408
|
+
'aria-label': collapseAllAriaLabel || 'Expand all rows'
|
|
3409
|
+
}));
|
|
3410
|
+
/**
|
|
3411
|
+
* @param {React.MouseEvent} event - Mouse event
|
|
3412
|
+
*/
|
|
3413
|
+
function onToggle(event) {
|
|
3414
|
+
const open = rowData ? !rowData.isOpen : !allRowsExpanded;
|
|
3415
|
+
// tslint:disable-next-line:no-unused-expression
|
|
3416
|
+
onCollapse && onCollapse(event, rowIndex, open, rowData, extraData);
|
|
3417
|
+
}
|
|
3418
|
+
return {
|
|
3419
|
+
className: ((rowData === null || rowData === void 0 ? void 0 : rowData.isOpen) !== undefined || rowId === -1) && css(styles$1.tableToggle),
|
|
3420
|
+
isVisible: !(rowData === null || rowData === void 0 ? void 0 : rowData.fullWidth),
|
|
3421
|
+
children: (React.createElement(CollapseColumn, Object.assign({ "aria-labelledby": `${rowLabeledBy}${rowId} ${expandId}${rowId}`, onToggle: onToggle, id: expandId + rowId }, customProps), value))
|
|
3422
|
+
};
|
|
3423
|
+
};
|
|
3424
|
+
|
|
3425
|
+
const cellWidth = (width) => () => ({
|
|
3426
|
+
className: css(styles$1.modifiers[typeof width === 'number' ? `width_${width}` : `width${capitalize(width)}`])
|
|
3427
|
+
});
|
|
3428
|
+
|
|
3429
|
+
const visibilityModifiers = [
|
|
3430
|
+
'hidden',
|
|
3431
|
+
'hiddenOnSm',
|
|
3432
|
+
'hiddenOnMd',
|
|
3433
|
+
'hiddenOnLg',
|
|
3434
|
+
'hiddenOnXl',
|
|
3435
|
+
'hiddenOn_2xl',
|
|
3436
|
+
'visibleOnSm',
|
|
3437
|
+
'visibleOnMd',
|
|
3438
|
+
'visibleOnLg',
|
|
3439
|
+
'visibleOnXl',
|
|
3440
|
+
'visibleOn_2xl'
|
|
3441
|
+
];
|
|
3442
|
+
const Visibility = visibilityModifiers
|
|
3443
|
+
.filter(key => styles$1.modifiers[key])
|
|
3444
|
+
.reduce((acc, curr) => {
|
|
3445
|
+
const key2 = curr.replace('_2xl', '2Xl');
|
|
3446
|
+
acc[key2] = styles$1.modifiers[curr];
|
|
3447
|
+
return acc;
|
|
3448
|
+
}, {});
|
|
3449
|
+
const classNames = (...classes) => () => ({
|
|
3450
|
+
className: css(...classes)
|
|
3451
|
+
});
|
|
3452
|
+
|
|
3453
|
+
/**
|
|
3454
|
+
* merge-props.js
|
|
3455
|
+
*
|
|
3456
|
+
* Forked from reactabular-table version 8.14.0
|
|
3457
|
+
* https://github.com/reactabular/reactabular/tree/v8.14.0/packages/reactabular-table/src
|
|
3458
|
+
*/
|
|
3459
|
+
/**
|
|
3460
|
+
* @param {any} props - Props
|
|
3461
|
+
*/
|
|
3462
|
+
function mergeProps(...props) {
|
|
3463
|
+
const firstProps = props[0];
|
|
3464
|
+
const restProps = props.slice(1);
|
|
3465
|
+
if (!restProps.length) {
|
|
3466
|
+
return mergeWith({}, firstProps);
|
|
3467
|
+
}
|
|
3468
|
+
// Avoid mutating the first prop collection
|
|
3469
|
+
return mergeWith(mergeWith({}, firstProps), ...restProps, (a, b, key) => {
|
|
3470
|
+
if (key === 'children') {
|
|
3471
|
+
if (a && b) {
|
|
3472
|
+
// compose the two
|
|
3473
|
+
return React.cloneElement(a, {
|
|
3474
|
+
children: b
|
|
3475
|
+
});
|
|
3476
|
+
}
|
|
3477
|
+
// Children have to be merged in reverse order for Reactabular
|
|
3478
|
+
// logic to work.
|
|
3479
|
+
return Object.assign(Object.assign({}, b), a);
|
|
3480
|
+
}
|
|
3481
|
+
if (key === 'className') {
|
|
3482
|
+
// Process class names through classNames to merge properly
|
|
3483
|
+
// as a string.
|
|
3484
|
+
return css(a, b);
|
|
3485
|
+
}
|
|
3486
|
+
return undefined;
|
|
3487
|
+
});
|
|
3488
|
+
}
|
|
3489
|
+
|
|
3490
|
+
const ThBase = (_a) => {
|
|
3491
|
+
var { children, className, component = 'th', dataLabel, scope = 'col', textCenter = false, sort = null, modifier, select = null, expand: collapse = null, tooltip = '', onMouseEnter: onMouseEnterProp = () => { }, width, visibility, innerRef, info: infoProps, isStickyColumn = false, hasRightBorder = false, stickyMinWidth = '120px', stickyLeftOffset, isSubheader = false } = _a, props = __rest(_a, ["children", "className", "component", "dataLabel", "scope", "textCenter", "sort", "modifier", "select", "expand", "tooltip", "onMouseEnter", "width", "visibility", "innerRef", "info", "isStickyColumn", "hasRightBorder", "stickyMinWidth", "stickyLeftOffset", "isSubheader"]);
|
|
3492
|
+
const [showTooltip, setShowTooltip] = React.useState(false);
|
|
3493
|
+
const onMouseEnter = (event) => {
|
|
3494
|
+
if (event.target.offsetWidth < event.target.scrollWidth) {
|
|
3495
|
+
!showTooltip && setShowTooltip(true);
|
|
3496
|
+
}
|
|
3497
|
+
else {
|
|
3498
|
+
showTooltip && setShowTooltip(false);
|
|
3499
|
+
}
|
|
3500
|
+
onMouseEnterProp(event);
|
|
3501
|
+
};
|
|
3502
|
+
let sortParams = null;
|
|
3503
|
+
if (sort) {
|
|
3504
|
+
if (sort.isFavorites) {
|
|
3505
|
+
sortParams = sortableFavorites({
|
|
3506
|
+
onSort: sort === null || sort === void 0 ? void 0 : sort.onSort,
|
|
3507
|
+
columnIndex: sort.columnIndex,
|
|
3508
|
+
sortBy: sort.sortBy
|
|
3509
|
+
})();
|
|
3510
|
+
}
|
|
3511
|
+
else {
|
|
3512
|
+
sortParams = sortable(children, {
|
|
3513
|
+
columnIndex: sort.columnIndex,
|
|
3514
|
+
column: {
|
|
3515
|
+
extraParams: {
|
|
3516
|
+
sortBy: sort.sortBy,
|
|
3517
|
+
onSort: sort === null || sort === void 0 ? void 0 : sort.onSort
|
|
3518
|
+
}
|
|
3519
|
+
}
|
|
3520
|
+
});
|
|
3521
|
+
}
|
|
3522
|
+
}
|
|
3523
|
+
const selectParams = select
|
|
3524
|
+
? selectable(children, {
|
|
3525
|
+
column: {
|
|
3526
|
+
extraParams: {
|
|
3527
|
+
onSelect: select === null || select === void 0 ? void 0 : select.onSelect,
|
|
3528
|
+
selectVariant: 'checkbox',
|
|
3529
|
+
allRowsSelected: select.isSelected,
|
|
3530
|
+
isHeaderSelectDisabled: !!select.isHeaderSelectDisabled
|
|
3531
|
+
}
|
|
3532
|
+
}
|
|
3533
|
+
})
|
|
3534
|
+
: null;
|
|
3535
|
+
const collapseParams = collapse
|
|
3536
|
+
? collapsible(children, {
|
|
3537
|
+
column: {
|
|
3538
|
+
extraParams: {
|
|
3539
|
+
onCollapse: collapse === null || collapse === void 0 ? void 0 : collapse.onToggle,
|
|
3540
|
+
allRowsExpanded: !collapse.areAllExpanded,
|
|
3541
|
+
collapseAllAriaLabel: ''
|
|
3542
|
+
}
|
|
3543
|
+
}
|
|
3544
|
+
})
|
|
3545
|
+
: null;
|
|
3546
|
+
const widthParams = width ? cellWidth(width)() : null;
|
|
3547
|
+
const visibilityParams = visibility
|
|
3548
|
+
? classNames(...visibility.map((vis) => Visibility[vis]))()
|
|
3549
|
+
: null;
|
|
3550
|
+
let transformedChildren = (sortParams === null || sortParams === void 0 ? void 0 : sortParams.children) || (selectParams === null || selectParams === void 0 ? void 0 : selectParams.children) || (collapseParams === null || collapseParams === void 0 ? void 0 : collapseParams.children) || children;
|
|
3551
|
+
// info can wrap other transformedChildren
|
|
3552
|
+
let infoParams = null;
|
|
3553
|
+
if (infoProps) {
|
|
3554
|
+
infoParams = info(infoProps)(transformedChildren);
|
|
3555
|
+
transformedChildren = infoParams.children;
|
|
3556
|
+
}
|
|
3557
|
+
const merged = mergeProps(sortParams, selectParams, collapseParams, widthParams, visibilityParams, infoParams);
|
|
3558
|
+
const {
|
|
3559
|
+
// ignore the merged children since we transform them ourselves so we can wrap it with info
|
|
3560
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
3561
|
+
children: mergedChildren = null,
|
|
3562
|
+
// selectable adds this but we don't want it
|
|
3563
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
3564
|
+
isVisible = null, className: mergedClassName = '', component: MergedComponent = component } = merged, mergedProps = __rest(merged, ["children", "isVisible", "className", "component"]);
|
|
3565
|
+
const cell = (React.createElement(MergedComponent, Object.assign({ "data-label": dataLabel, onMouseEnter: tooltip !== null ? onMouseEnter : onMouseEnterProp, scope: component === 'th' && children ? scope : null, ref: innerRef, className: css(className, textCenter && styles$1.modifiers.center, isSubheader && styles$1.tableSubhead, isStickyColumn && styles.tableStickyColumn, hasRightBorder && styles.modifiers.borderRight, modifier && styles$1.modifiers[modifier], mergedClassName) }, mergedProps, props, (isStickyColumn && {
|
|
3566
|
+
style: Object.assign({ '--pf-c-table__sticky-column--MinWidth': stickyMinWidth ? stickyMinWidth : undefined, '--pf-c-table__sticky-column--Left': stickyLeftOffset ? stickyLeftOffset : undefined }, props.style)
|
|
3567
|
+
})), transformedChildren));
|
|
3568
|
+
const canDefault = tooltip === '' ? typeof children === 'string' : true;
|
|
3569
|
+
return tooltip !== null && canDefault && showTooltip ? (React.createElement(Tooltip, { content: tooltip || (tooltip === '' && children), isVisible: true }, cell)) : (cell);
|
|
3570
|
+
};
|
|
3571
|
+
const Th = React.forwardRef((props, ref) => (React.createElement(ThBase, Object.assign({}, props, { innerRef: ref }))));
|
|
3572
|
+
Th.displayName = 'Th';
|
|
3573
|
+
|
|
3574
|
+
class ActionsColumn extends React.Component {
|
|
3575
|
+
constructor(props) {
|
|
3576
|
+
super(props);
|
|
3577
|
+
this.toggleRef = React.createRef();
|
|
3578
|
+
this.onToggle = (isOpen) => {
|
|
3579
|
+
this.setState({
|
|
3580
|
+
isOpen
|
|
3581
|
+
});
|
|
3582
|
+
};
|
|
3583
|
+
this.onClick = (event, onClick) => {
|
|
3584
|
+
const { rowData, extraData } = this.props;
|
|
3585
|
+
// Only prevent default if onClick is provided. This allows href support.
|
|
3586
|
+
if (onClick) {
|
|
3587
|
+
event.preventDefault();
|
|
3588
|
+
// tslint:disable-next-line:no-unused-expression
|
|
3589
|
+
onClick(event, extraData && extraData.rowIndex, rowData, extraData);
|
|
3590
|
+
}
|
|
3591
|
+
};
|
|
3592
|
+
this.state = {
|
|
3593
|
+
isOpen: false
|
|
3594
|
+
};
|
|
3595
|
+
}
|
|
3596
|
+
render() {
|
|
3597
|
+
const { isOpen } = this.state;
|
|
3598
|
+
const { items, children, dropdownPosition, dropdownDirection, isDisabled, rowData, actionsToggle } = this.props;
|
|
3599
|
+
const actionsToggleClone = actionsToggle ? (actionsToggle({ onToggle: this.onToggle, isOpen, isDisabled })) : (React.createElement(KebabToggle, { isDisabled: isDisabled, onToggle: this.onToggle }));
|
|
3600
|
+
return (React.createElement(React.Fragment, null,
|
|
3601
|
+
items
|
|
3602
|
+
.filter(item => item.isOutsideDropdown)
|
|
3603
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
3604
|
+
.map((_a, key) => {
|
|
3605
|
+
var { title, itemKey, onClick, isOutsideDropdown } = _a, props = __rest(_a, ["title", "itemKey", "onClick", "isOutsideDropdown"]);
|
|
3606
|
+
return typeof title === 'string' ? (React.createElement(Button$1, Object.assign({ onClick: event => this.onClick(event, onClick) }, props, { isDisabled: isDisabled, key: itemKey || `outside_dropdown_${key}`, "data-key": itemKey || `outside_dropdown_${key}` }), title)) : (React.cloneElement(title, Object.assign({ onClick, isDisabled }, props)));
|
|
3607
|
+
}),
|
|
3608
|
+
React.createElement(Dropdown, Object.assign({ toggle: actionsToggleClone, position: dropdownPosition, direction: dropdownDirection, isOpen: isOpen, dropdownItems: items
|
|
3609
|
+
.filter(item => !item.isOutsideDropdown)
|
|
3610
|
+
.map((_a, key) => {
|
|
3611
|
+
var { title, itemKey, onClick, isSeparator } = _a, props = __rest(_a, ["title", "itemKey", "onClick", "isSeparator"]);
|
|
3612
|
+
return isSeparator ? (React.createElement(DropdownSeparator, Object.assign({}, props, { key: itemKey || key, "data-key": itemKey || key }))) : (React.createElement(DropdownItem, Object.assign({ component: "button", onClick: event => {
|
|
3613
|
+
this.onClick(event, onClick);
|
|
3614
|
+
this.onToggle(!isOpen);
|
|
3615
|
+
} }, props, { key: itemKey || key, "data-key": itemKey || key }), title));
|
|
3616
|
+
}), isPlain: true }, (rowData && rowData.actionProps))),
|
|
3617
|
+
children));
|
|
3618
|
+
}
|
|
3619
|
+
}
|
|
3620
|
+
ActionsColumn.displayName = 'ActionsColumn';
|
|
3621
|
+
ActionsColumn.defaultProps = {
|
|
3622
|
+
children: null,
|
|
3623
|
+
items: [],
|
|
3624
|
+
dropdownPosition: DropdownPosition.right,
|
|
3625
|
+
dropdownDirection: DropdownDirection.down,
|
|
3626
|
+
rowData: {},
|
|
3627
|
+
extraData: {}
|
|
3628
|
+
};
|
|
3629
|
+
|
|
3630
|
+
const resolveOrDefault = (resolver, defaultValue, rowData, extraData) => (typeof resolver === 'function' ? resolver(rowData, extraData) : defaultValue);
|
|
3631
|
+
const cellActions = (actions, actionResolver, areActionsDisabled) => (label, { rowData, column, rowIndex, columnIndex, column: { extraParams: { dropdownPosition, dropdownDirection, actionsToggle } }, property }) => {
|
|
3632
|
+
const extraData = {
|
|
3633
|
+
rowIndex,
|
|
3634
|
+
columnIndex,
|
|
3635
|
+
column,
|
|
3636
|
+
property
|
|
3637
|
+
};
|
|
3638
|
+
const resolvedActions = resolveOrDefault(actionResolver, actions, rowData, extraData);
|
|
3639
|
+
const resolvedIsDisabled = resolveOrDefault(areActionsDisabled, rowData && rowData.disableActions, rowData, extraData);
|
|
3640
|
+
const renderProps = resolvedActions && resolvedActions.length > 0
|
|
3641
|
+
? {
|
|
3642
|
+
children: (React.createElement(ActionsColumn, { items: resolvedActions, dropdownPosition: dropdownPosition, dropdownDirection: dropdownDirection, isDisabled: resolvedIsDisabled, rowData: rowData, extraData: extraData, actionsToggle: actionsToggle }, label))
|
|
3643
|
+
}
|
|
3644
|
+
: {};
|
|
3645
|
+
return Object.assign({ className: css(styles$1.tableAction), style: { paddingRight: 0 }, isVisible: true }, renderProps);
|
|
3646
|
+
};
|
|
3647
|
+
|
|
3648
|
+
const compoundExpand = (value, { rowIndex, columnIndex, rowData, column, property }) => {
|
|
3649
|
+
if (!value) {
|
|
3650
|
+
return null;
|
|
3651
|
+
}
|
|
3652
|
+
const { title, props } = value;
|
|
3653
|
+
const { extraParams: { onExpand } } = column;
|
|
3654
|
+
const extraData = {
|
|
3655
|
+
rowIndex,
|
|
3656
|
+
columnIndex,
|
|
3657
|
+
column,
|
|
3658
|
+
property
|
|
3659
|
+
};
|
|
3660
|
+
/**
|
|
3661
|
+
* @param {React.MouseEvent} event - Mouse event
|
|
3662
|
+
*/
|
|
3663
|
+
function onToggle(event) {
|
|
3664
|
+
// tslint:disable-next-line:no-unused-expression
|
|
3665
|
+
onExpand && onExpand(event, rowIndex, columnIndex, props.isOpen, rowData, extraData);
|
|
3666
|
+
}
|
|
3667
|
+
return {
|
|
3668
|
+
className: css(styles$1.tableCompoundExpansionToggle, props.isOpen && styles$1.modifiers.expanded),
|
|
3669
|
+
children: props.isOpen !== undefined && (React.createElement("button", { type: "button", className: css(styles$1.tableButton), onClick: onToggle, "aria-expanded": props.isOpen, "aria-controls": props.ariaControls },
|
|
3670
|
+
React.createElement(TableText, null, title)))
|
|
3671
|
+
};
|
|
3672
|
+
};
|
|
3673
|
+
|
|
3674
|
+
const FavoritesCell = (_a) => {
|
|
3675
|
+
var { className = '', onFavorite, isFavorited, rowIndex } = _a, props = __rest(_a, ["className", "onFavorite", "isFavorited", "rowIndex"]);
|
|
3676
|
+
const ariaProps = rowIndex === undefined
|
|
3677
|
+
? {}
|
|
3678
|
+
: {
|
|
3679
|
+
id: `favorites-button-${rowIndex}`,
|
|
3680
|
+
'aria-labelledby': `favorites-button-${rowIndex}`
|
|
3681
|
+
};
|
|
3682
|
+
return (React.createElement(Button$1, Object.assign({ variant: "plain", className: className, type: "button", "aria-label": isFavorited ? 'Starred' : 'Not starred', onClick: onFavorite }, ariaProps, props),
|
|
3683
|
+
React.createElement(StarIcon$1, { "aria-hidden": true })));
|
|
3684
|
+
};
|
|
3685
|
+
FavoritesCell.displayName = 'FavoritesCell';
|
|
3686
|
+
|
|
3687
|
+
const favoritable = (value, { rowIndex, columnIndex, rowData, column, property }) => {
|
|
3688
|
+
const { extraParams: { onFavorite } } = column;
|
|
3689
|
+
const extraData = {
|
|
3690
|
+
rowIndex,
|
|
3691
|
+
columnIndex,
|
|
3692
|
+
column,
|
|
3693
|
+
property
|
|
3694
|
+
};
|
|
3695
|
+
// this is a child row which should not display the favorites icon
|
|
3696
|
+
if (rowData && rowData.hasOwnProperty('parent') && !rowData.fullWidth) {
|
|
3697
|
+
return {
|
|
3698
|
+
component: 'td',
|
|
3699
|
+
isVisible: true
|
|
3700
|
+
};
|
|
3701
|
+
}
|
|
3702
|
+
/**
|
|
3703
|
+
* @param {React.MouseEvent} event - Mouse event
|
|
3704
|
+
*/
|
|
3705
|
+
function favoritesClick(event) {
|
|
3706
|
+
// tslint:disable-next-line:no-unused-expression
|
|
3707
|
+
onFavorite && onFavorite(event, rowData && !rowData.favorited, rowIndex, rowData, extraData);
|
|
3708
|
+
}
|
|
3709
|
+
const additionalProps = rowData.favoritesProps || {};
|
|
3710
|
+
return {
|
|
3711
|
+
className: css(styles$1.tableFavorite, rowData && rowData.favorited && styles$1.modifiers.favorited),
|
|
3712
|
+
isVisible: !rowData || !rowData.fullWidth,
|
|
3713
|
+
children: (React.createElement(FavoritesCell, Object.assign({ rowIndex: rowIndex, onFavorite: favoritesClick, isFavorited: rowData && rowData.favorited }, additionalProps)))
|
|
3714
|
+
};
|
|
3715
|
+
};
|
|
3716
|
+
|
|
3717
|
+
const GripVerticalIconConfig = {
|
|
3718
|
+
name: 'GripVerticalIcon',
|
|
3719
|
+
height: 512,
|
|
3720
|
+
width: 320,
|
|
3721
|
+
svgPath: 'M96 32H32C14.33 32 0 46.33 0 64v64c0 17.67 14.33 32 32 32h64c17.67 0 32-14.33 32-32V64c0-17.67-14.33-32-32-32zm0 160H32c-17.67 0-32 14.33-32 32v64c0 17.67 14.33 32 32 32h64c17.67 0 32-14.33 32-32v-64c0-17.67-14.33-32-32-32zm0 160H32c-17.67 0-32 14.33-32 32v64c0 17.67 14.33 32 32 32h64c17.67 0 32-14.33 32-32v-64c0-17.67-14.33-32-32-32zM288 32h-64c-17.67 0-32 14.33-32 32v64c0 17.67 14.33 32 32 32h64c17.67 0 32-14.33 32-32V64c0-17.67-14.33-32-32-32zm0 160h-64c-17.67 0-32 14.33-32 32v64c0 17.67 14.33 32 32 32h64c17.67 0 32-14.33 32-32v-64c0-17.67-14.33-32-32-32zm0 160h-64c-17.67 0-32 14.33-32 32v64c0 17.67 14.33 32 32 32h64c17.67 0 32-14.33 32-32v-64c0-17.67-14.33-32-32-32z',
|
|
3722
|
+
yOffset: 0,
|
|
3723
|
+
xOffset: 0,
|
|
3724
|
+
};
|
|
3725
|
+
|
|
3726
|
+
const GripVerticalIcon = createIcon(GripVerticalIconConfig);
|
|
3727
|
+
|
|
3728
|
+
var GripVerticalIcon$1 = GripVerticalIcon;
|
|
3729
|
+
|
|
3730
|
+
const DraggableCell = (_a) => {
|
|
3731
|
+
var { className, onClick, 'aria-label': ariaLabel, id } = _a, props = __rest(_a, ["className", "onClick", 'aria-label', "id"]);
|
|
3732
|
+
return (React.createElement(Button$1, Object.assign({ id: id, variant: "plain", className: className, type: "button", "aria-label": ariaLabel || `Draggable row draggable button`, onClick: onClick }, props),
|
|
3733
|
+
React.createElement(GripVerticalIcon$1, { "aria-hidden": true })));
|
|
3734
|
+
};
|
|
3735
|
+
DraggableCell.displayName = 'DraggableCell';
|
|
3736
|
+
|
|
3737
|
+
const draggable = (value, { rowData }) => {
|
|
3738
|
+
const { id } = rowData;
|
|
3739
|
+
return {
|
|
3740
|
+
className: '',
|
|
3741
|
+
children: React.createElement(DraggableCell, { id: id })
|
|
3742
|
+
};
|
|
3743
|
+
};
|
|
3744
|
+
|
|
3745
|
+
const EllipsisHIconConfig = {
|
|
3746
|
+
name: 'EllipsisHIcon',
|
|
3747
|
+
height: 512,
|
|
3748
|
+
width: 512,
|
|
3749
|
+
svgPath: 'M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z',
|
|
3750
|
+
yOffset: 0,
|
|
3751
|
+
xOffset: 0,
|
|
3752
|
+
};
|
|
3753
|
+
|
|
3754
|
+
const EllipsisHIcon = createIcon(EllipsisHIconConfig);
|
|
3755
|
+
|
|
3756
|
+
var EllipsisHIcon$1 = EllipsisHIcon;
|
|
3757
|
+
|
|
3758
|
+
const treeRow = (onCollapse, onCheckChange, onToggleRowDetails) => (value, { rowIndex, rowData }) => {
|
|
3759
|
+
const { isExpanded, isDetailsExpanded, 'aria-level': level, 'aria-setsize': setsize, toggleAriaLabel, checkAriaLabel, showDetailsAriaLabel, isChecked, checkboxId, icon } = rowData.props;
|
|
3760
|
+
const content = value.title || value;
|
|
3761
|
+
const text = (React.createElement("div", { className: css(stylesTreeView.tableTreeViewText), key: "tree-view-text" },
|
|
3762
|
+
icon && (React.createElement("span", { className: css(stylesTreeView.tableTreeViewIcon), key: "tree-view-text-icon" }, icon)),
|
|
3763
|
+
React.createElement("span", { className: "pf-c-table__text", key: "table-text" }, content)));
|
|
3764
|
+
const onChange = (isChecked, event) => {
|
|
3765
|
+
onCheckChange(event, isChecked, rowIndex, content, rowData);
|
|
3766
|
+
};
|
|
3767
|
+
return {
|
|
3768
|
+
component: 'th',
|
|
3769
|
+
className: 'pf-c-table__tree-view-title-cell',
|
|
3770
|
+
children: level !== undefined ? (React.createElement("div", { className: css(stylesTreeView.tableTreeViewMain) },
|
|
3771
|
+
setsize > 0 && (React.createElement("span", { className: css(stylesTreeView.tableToggle), key: "table-toggle" },
|
|
3772
|
+
React.createElement(Button, { variant: "plain", onClick: event => onCollapse && onCollapse(event, rowIndex, content, rowData), className: css(isExpanded && styles$1.modifiers.expanded), "aria-expanded": isExpanded, "aria-label": toggleAriaLabel || `${isExpanded ? 'Collapse' : 'Expand'} row ${rowIndex}` },
|
|
3773
|
+
React.createElement("div", { className: css(stylesTreeView.tableToggleIcon) },
|
|
3774
|
+
React.createElement(AngleDownIcon$1, { "aria-hidden": "true" }))))),
|
|
3775
|
+
!!onCheckChange && (React.createElement("span", { className: css(stylesTreeView.tableCheck), key: "table-check" },
|
|
3776
|
+
React.createElement("label", { htmlFor: checkboxId || `checkbox_${rowIndex}` },
|
|
3777
|
+
React.createElement(Checkbox, { id: checkboxId || `checkbox_${rowIndex}`, "aria-label": checkAriaLabel || `Row ${rowIndex} checkbox`, isChecked: isChecked, onChange: onChange })))),
|
|
3778
|
+
text,
|
|
3779
|
+
!!onToggleRowDetails && (React.createElement("span", { className: css(stylesTreeView.tableTreeViewDetailsToggle), key: "view-details-toggle" },
|
|
3780
|
+
React.createElement(Button, { variant: "plain", "aria-expanded": isDetailsExpanded, "aria-label": showDetailsAriaLabel || 'Show row details', onClick: event => onToggleRowDetails && onToggleRowDetails(event, rowIndex, content, rowData) },
|
|
3781
|
+
React.createElement("span", { className: "pf-c-table__details-toggle-icon" },
|
|
3782
|
+
React.createElement(EllipsisHIcon$1, { "aria-hidden": true }))))))) : (text)
|
|
3783
|
+
};
|
|
3784
|
+
};
|
|
3785
|
+
|
|
3786
|
+
const TdBase = (_a) => {
|
|
3787
|
+
var { children, className, isActionCell = false, component = 'td', dataLabel, textCenter = false, modifier, select = null, actions = null, expand = null, treeRow: treeRowProp = null, compoundExpand: compoundExpandProp = null, noPadding, width, visibility, innerRef, favorites = null, draggableRow: draggableRowProp = null } = _a, props = __rest(_a, ["children", "className", "isActionCell", "component", "dataLabel", "textCenter", "modifier", "select", "actions", "expand", "treeRow", "compoundExpand", "noPadding", "width", "visibility", "innerRef", "favorites", "draggableRow"]);
|
|
3788
|
+
const selectParams = select
|
|
3789
|
+
? selectable(children, {
|
|
3790
|
+
rowIndex: select.rowIndex,
|
|
3791
|
+
rowData: {
|
|
3792
|
+
selected: select.isSelected,
|
|
3793
|
+
disableSelection: select === null || select === void 0 ? void 0 : select.disable,
|
|
3794
|
+
props: select === null || select === void 0 ? void 0 : select.props
|
|
3795
|
+
},
|
|
3796
|
+
column: {
|
|
3797
|
+
extraParams: {
|
|
3798
|
+
onSelect: select === null || select === void 0 ? void 0 : select.onSelect,
|
|
3799
|
+
selectVariant: select.variant || 'checkbox'
|
|
3800
|
+
}
|
|
3801
|
+
}
|
|
3802
|
+
})
|
|
3803
|
+
: null;
|
|
3804
|
+
const favoriteParams = favorites
|
|
3805
|
+
? favoritable(null, {
|
|
3806
|
+
rowIndex: favorites === null || favorites === void 0 ? void 0 : favorites.rowIndex,
|
|
3807
|
+
rowData: {
|
|
3808
|
+
favorited: favorites.isFavorited,
|
|
3809
|
+
favoritesProps: favorites === null || favorites === void 0 ? void 0 : favorites.props
|
|
3810
|
+
},
|
|
3811
|
+
column: {
|
|
3812
|
+
extraParams: {
|
|
3813
|
+
onFavorite: favorites === null || favorites === void 0 ? void 0 : favorites.onFavorite
|
|
3814
|
+
}
|
|
3815
|
+
}
|
|
3816
|
+
})
|
|
3817
|
+
: null;
|
|
3818
|
+
const draggableParams = draggableRowProp !== null
|
|
3819
|
+
? draggable(null, {
|
|
3820
|
+
rowData: {
|
|
3821
|
+
id: draggableRowProp.id
|
|
3822
|
+
}
|
|
3823
|
+
})
|
|
3824
|
+
: null;
|
|
3825
|
+
const actionParamsFunc = actions ? cellActions(actions.items, null, null) : null;
|
|
3826
|
+
const actionParams = actionParamsFunc
|
|
3827
|
+
? actionParamsFunc(null, {
|
|
3828
|
+
rowIndex: actions === null || actions === void 0 ? void 0 : actions.rowIndex,
|
|
3829
|
+
rowData: {
|
|
3830
|
+
disableActions: actions === null || actions === void 0 ? void 0 : actions.disable
|
|
3831
|
+
},
|
|
3832
|
+
column: {
|
|
3833
|
+
extraParams: {
|
|
3834
|
+
dropdownPosition: actions === null || actions === void 0 ? void 0 : actions.dropdownPosition,
|
|
3835
|
+
dropdownDirection: actions === null || actions === void 0 ? void 0 : actions.dropdownDirection,
|
|
3836
|
+
actionsToggle: actions === null || actions === void 0 ? void 0 : actions.actionsToggle
|
|
3837
|
+
}
|
|
3838
|
+
}
|
|
3839
|
+
})
|
|
3840
|
+
: null;
|
|
3841
|
+
const expandableParams = expand !== null
|
|
3842
|
+
? collapsible(null, {
|
|
3843
|
+
rowIndex: expand.rowIndex,
|
|
3844
|
+
columnIndex: expand === null || expand === void 0 ? void 0 : expand.columnIndex,
|
|
3845
|
+
rowData: {
|
|
3846
|
+
isOpen: expand.isExpanded
|
|
3847
|
+
},
|
|
3848
|
+
column: {
|
|
3849
|
+
extraParams: {
|
|
3850
|
+
onCollapse: expand === null || expand === void 0 ? void 0 : expand.onToggle
|
|
3851
|
+
}
|
|
3852
|
+
}
|
|
3853
|
+
})
|
|
3854
|
+
: null;
|
|
3855
|
+
const compoundParams = compoundExpandProp !== null
|
|
3856
|
+
? compoundExpand({
|
|
3857
|
+
title: children,
|
|
3858
|
+
props: {
|
|
3859
|
+
isOpen: compoundExpandProp.isExpanded
|
|
3860
|
+
}
|
|
3861
|
+
}, {
|
|
3862
|
+
column: {
|
|
3863
|
+
extraParams: {
|
|
3864
|
+
onExpand: compoundExpandProp === null || compoundExpandProp === void 0 ? void 0 : compoundExpandProp.onToggle
|
|
3865
|
+
}
|
|
3866
|
+
}
|
|
3867
|
+
})
|
|
3868
|
+
: null;
|
|
3869
|
+
const widthParams = width ? cellWidth(width)() : null;
|
|
3870
|
+
const visibilityParams = visibility
|
|
3871
|
+
? classNames(...visibility.map((vis) => Visibility[vis]))()
|
|
3872
|
+
: null;
|
|
3873
|
+
const treeRowParams = treeRowProp !== null
|
|
3874
|
+
? treeRow(treeRowProp.onCollapse, treeRowProp.onCheckChange, treeRowProp.onToggleRowDetails)({
|
|
3875
|
+
title: children
|
|
3876
|
+
}, {
|
|
3877
|
+
rowIndex: treeRowProp.rowIndex,
|
|
3878
|
+
rowData: {
|
|
3879
|
+
props: treeRowProp.props
|
|
3880
|
+
}
|
|
3881
|
+
})
|
|
3882
|
+
: null;
|
|
3883
|
+
const merged = mergeProps(selectParams, actionParams, expandableParams, compoundParams, widthParams, visibilityParams, favoriteParams, treeRowParams, draggableParams);
|
|
3884
|
+
const {
|
|
3885
|
+
// selectable adds this but we don't want it
|
|
3886
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
3887
|
+
isVisible = null, children: mergedChildren = null, className: mergedClassName = '', component: MergedComponent = component } = merged, mergedProps = __rest(merged, ["isVisible", "children", "className", "component"]);
|
|
3888
|
+
const treeTableTitleCell = (className && className.includes('pf-c-table__tree-view-title-cell')) ||
|
|
3889
|
+
(mergedClassName && mergedClassName.includes('pf-c-table__tree-view-title-cell'));
|
|
3890
|
+
return (React.createElement(MergedComponent, Object.assign({}, (!treeTableTitleCell && { 'data-label': dataLabel }), { className: css(className, isActionCell && styles$1.tableAction, textCenter && styles$1.modifiers.center, noPadding && styles$1.modifiers.noPadding, styles$1.modifiers[modifier], draggableParams && styles$1.tableDraggable, mergedClassName), ref: innerRef }, mergedProps, props), mergedChildren || children));
|
|
3891
|
+
};
|
|
3892
|
+
const Td = React.forwardRef((props, ref) => (React.createElement(TdBase, Object.assign({}, props, { innerRef: ref }))));
|
|
3893
|
+
Td.displayName = 'Td';
|
|
3894
|
+
|
|
3895
|
+
const SearchIconConfig = {
|
|
3896
|
+
name: 'SearchIcon',
|
|
3897
|
+
height: 512,
|
|
3898
|
+
width: 512,
|
|
3899
|
+
svgPath: 'M505 442.7L405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c48.3 0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9 0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7 0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7 0 128 57.2 128 128 0 70.7-57.2 128-128 128z',
|
|
3900
|
+
yOffset: 0,
|
|
3901
|
+
xOffset: 0,
|
|
3902
|
+
};
|
|
3903
|
+
|
|
3904
|
+
const SearchIcon = createIcon(SearchIconConfig);
|
|
3905
|
+
|
|
3906
|
+
/* eslint-disable no-unused-vars */
|
|
3907
|
+
const DEFAULT_PAGE = 1;
|
|
3908
|
+
const DEFAULT_PERPAGE = 10;
|
|
3909
|
+
function FilterableTable({
|
|
3910
|
+
columns,
|
|
3911
|
+
items,
|
|
3912
|
+
isLoading,
|
|
3913
|
+
renderRow,
|
|
3914
|
+
filters,
|
|
3915
|
+
actions,
|
|
3916
|
+
perPageOptions
|
|
3917
|
+
}) {
|
|
3918
|
+
|
|
3919
|
+
const [page, setPage] = useState(DEFAULT_PAGE);
|
|
3920
|
+
const [perPage, setPerPage] = useState(DEFAULT_PERPAGE );
|
|
3921
|
+
const [sortTableBy, setSortTableBy] = useState({});
|
|
3922
|
+
const [rows, setRows] = useState([]);
|
|
3923
|
+
const [filteredItems, setFilteredItems] = useState(items);
|
|
3924
|
+
const [tableFilters, setTableFilters] = useState([]);
|
|
3925
|
+
/**
|
|
3926
|
+
* Sorts table by the selected column in ascending or decending order
|
|
3927
|
+
* @param _event click
|
|
3928
|
+
* @param index column index
|
|
3929
|
+
* @param direction asc || desc
|
|
3930
|
+
*/
|
|
3931
|
+
|
|
3932
|
+
const onSort = (_event, index, direction) => {
|
|
3933
|
+
var _columns$index, _columns$index2;
|
|
3934
|
+
|
|
3935
|
+
const sortField = columns == null ? void 0 : (_columns$index = columns[index]) == null ? void 0 : _columns$index.sortField;
|
|
3936
|
+
const sortFn = columns == null ? void 0 : (_columns$index2 = columns[index]) == null ? void 0 : _columns$index2.sortFn;
|
|
3937
|
+
const sortedRows = sortFn ? sortBy(filteredItems, sortFn) : sortField ? sortBy(filteredItems, item => item[sortField]) : filteredItems;
|
|
3938
|
+
setPage(1);
|
|
3939
|
+
setSortTableBy({
|
|
3940
|
+
index,
|
|
3941
|
+
direction
|
|
3942
|
+
});
|
|
3943
|
+
setFilteredItems(direction === SortByDirection.asc ? [...sortedRows] : [...(sortedRows == null ? void 0 : sortedRows.reverse())]);
|
|
3944
|
+
};
|
|
3945
|
+
/**
|
|
3946
|
+
* Set table rows to display based on current list of filtered items, page, and perPage settings
|
|
3947
|
+
*/
|
|
3948
|
+
|
|
3949
|
+
|
|
3950
|
+
useEffect(() => {
|
|
3951
|
+
const startIndex = (page - 1) * perPage;
|
|
3952
|
+
const endIndex = startIndex + perPage;
|
|
3953
|
+
const itemsInPage = filteredItems.slice(startIndex, endIndex);
|
|
3954
|
+
setRows(itemsInPage);
|
|
3955
|
+
}, [filteredItems, page, perPage]);
|
|
3956
|
+
/**
|
|
3957
|
+
* If the list of items change, reset to the first page
|
|
3958
|
+
*/
|
|
3959
|
+
|
|
3960
|
+
function handleItemsPropChange() {
|
|
3961
|
+
setPage(1);
|
|
3962
|
+
}
|
|
3963
|
+
|
|
3964
|
+
const handleItemsPropChangeCallback = useCallback(handleItemsPropChange, [setPage, items]);
|
|
3965
|
+
useEffect(handleItemsPropChangeCallback, [handleItemsPropChangeCallback]);
|
|
3966
|
+
/**
|
|
3967
|
+
* Whenever a filter is selected or a user enter a search string, run each item through each filter condition
|
|
3968
|
+
* and check it includes the search string. Only inlcude the item in the table if it passes all filter/search string
|
|
3969
|
+
* conditions.
|
|
3970
|
+
*/
|
|
3971
|
+
|
|
3972
|
+
useEffect(() => setFilteredItems(items.filter(item => tableFilters.map((f, i) => {
|
|
3973
|
+
var _filters$i, _filters$i$props;
|
|
3974
|
+
|
|
3975
|
+
return !f ? true : filters == null ? void 0 : (_filters$i = filters[i]) == null ? void 0 : (_filters$i$props = _filters$i.props) == null ? void 0 : _filters$i$props.onChange(f, item);
|
|
3976
|
+
}).reduce((r, v) => r && v, true))), [filters, items, tableFilters]);
|
|
3977
|
+
/**
|
|
3978
|
+
* Whenever a new filter is selected by the user, update the state of selectedFilters
|
|
3979
|
+
* @param selected filter selections
|
|
3980
|
+
* @param index filter to update with new selections
|
|
3981
|
+
*/
|
|
3982
|
+
|
|
3983
|
+
const onFilterChange = (selected, index) => {
|
|
3984
|
+
setTableFilters(prevState => {
|
|
3985
|
+
prevState[index] = selected;
|
|
3986
|
+
return [...prevState];
|
|
3987
|
+
});
|
|
3988
|
+
};
|
|
3989
|
+
/**
|
|
3990
|
+
* Pagination component
|
|
3991
|
+
* @param variant top or bottom
|
|
3992
|
+
* @returns Pagination component based on variant
|
|
3993
|
+
*/
|
|
3994
|
+
|
|
3995
|
+
|
|
3996
|
+
const renderPagination = variant => {
|
|
3997
|
+
return (filteredItems == null ? void 0 : filteredItems.length) > 0 && React__default.createElement(Pagination, {
|
|
3998
|
+
itemCount: (filteredItems == null ? void 0 : filteredItems.length) || 0,
|
|
3999
|
+
page: page,
|
|
4000
|
+
perPage: perPage,
|
|
4001
|
+
onSetPage: (_, page) => setPage(page),
|
|
4002
|
+
onPerPageSelect: (_, perPage) => {
|
|
4003
|
+
setPage(1);
|
|
4004
|
+
setPerPage(perPage);
|
|
4005
|
+
},
|
|
4006
|
+
perPageOptions: perPageOptions,
|
|
4007
|
+
isCompact: true,
|
|
4008
|
+
variant: variant
|
|
4009
|
+
});
|
|
4010
|
+
};
|
|
4011
|
+
/**
|
|
4012
|
+
* Toolbar populated with provided filters
|
|
4013
|
+
*/
|
|
4014
|
+
|
|
4015
|
+
|
|
4016
|
+
const header = React__default.createElement(Toolbar, null, React__default.createElement(ToolbarContent, null, filters == null ? void 0 : filters.map((el, i) => {
|
|
4017
|
+
return React__default.createElement(ToolbarItem, {
|
|
4018
|
+
key: i,
|
|
4019
|
+
className: 'filterable-table__toolbar__item--filter'
|
|
4020
|
+
}, cloneElement(el, {
|
|
4021
|
+
onChange: selectedFilters => onFilterChange(selectedFilters, i)
|
|
4022
|
+
}));
|
|
4023
|
+
}), actions == null ? void 0 : actions.map((el, i) => {
|
|
4024
|
+
return React__default.createElement(ToolbarItem, {
|
|
4025
|
+
key: i,
|
|
4026
|
+
className: 'filterable-table__toolbar__item--action'
|
|
4027
|
+
}, el);
|
|
4028
|
+
}), React__default.createElement(ToolbarItem, {
|
|
4029
|
+
variant: 'pagination'
|
|
4030
|
+
}, renderPagination('top'))));
|
|
4031
|
+
return React__default.createElement("div", {
|
|
4032
|
+
className: 'filterable-table'
|
|
4033
|
+
}, isLoading ? React__default.createElement(Bullseye, null, React__default.createElement("div", null, React__default.createElement("pfe-progress-indicator", {
|
|
4034
|
+
"pfe-indeterminate": true,
|
|
4035
|
+
size: 'lg'
|
|
4036
|
+
}))) : React__default.createElement(React__default.Fragment, null, header, React__default.createElement(TableComposable, {
|
|
4037
|
+
"aria-label": 'Packages Table'
|
|
4038
|
+
}, React__default.createElement(Thead, null, React__default.createElement(Tr, null, columns.map((col, colIdx) => React__default.createElement(Th, Object.assign({
|
|
4039
|
+
key: `pkg-table-head-${colIdx}`
|
|
4040
|
+
}, col.sortField ? {
|
|
4041
|
+
sort: {
|
|
4042
|
+
onSort: onSort,
|
|
4043
|
+
sortBy: sortTableBy,
|
|
4044
|
+
columnIndex: colIdx
|
|
4045
|
+
}
|
|
4046
|
+
} : {}), col.title)))), React__default.createElement(Tbody, null, rows.length > 0 ? rows.map((row, rowIdx) => React__default.createElement(Tr, {
|
|
4047
|
+
key: `pkg-table-row-${rowIdx}`
|
|
4048
|
+
}, columns.map((_col, colIdx) => {
|
|
4049
|
+
var _renderRow;
|
|
4050
|
+
|
|
4051
|
+
return React__default.createElement(Td, {
|
|
4052
|
+
key: `pkg-table-row-${rowIdx}-col-${colIdx}`
|
|
4053
|
+
}, (_renderRow = renderRow(row)) == null ? void 0 : _renderRow[colIdx]);
|
|
4054
|
+
}))) : React__default.createElement(Td, {
|
|
4055
|
+
colSpan: columns.length
|
|
4056
|
+
}, React__default.createElement(EmptyState, null, React__default.createElement(EmptyStateIcon, {
|
|
4057
|
+
icon: SearchIcon
|
|
4058
|
+
}), React__default.createElement(Title, {
|
|
4059
|
+
headingLevel: 'h5',
|
|
4060
|
+
size: 'lg'
|
|
4061
|
+
}, "No results found")))))), renderPagination('bottom'));
|
|
4062
|
+
}
|
|
4063
|
+
|
|
4064
|
+
const FilterInput = ({
|
|
4065
|
+
onChange: onChangeHandler,
|
|
4066
|
+
placeholder
|
|
4067
|
+
}) => {
|
|
4068
|
+
const [searchStr, setSearchStr] = useState('');
|
|
4069
|
+
|
|
4070
|
+
const onChange = (text, event) => {
|
|
4071
|
+
event.stopPropagation();
|
|
4072
|
+
event.preventDefault();
|
|
4073
|
+
setSearchStr(() => {
|
|
4074
|
+
onChangeHandler && onChangeHandler(text, event);
|
|
4075
|
+
return text;
|
|
4076
|
+
});
|
|
4077
|
+
};
|
|
4078
|
+
|
|
4079
|
+
return React__default.createElement("div", {
|
|
4080
|
+
className: 'filter-input'
|
|
4081
|
+
}, React__default.createElement(TextInput, {
|
|
4082
|
+
value: searchStr,
|
|
4083
|
+
type: 'text',
|
|
4084
|
+
placeholder: placeholder,
|
|
4085
|
+
onChange: onChange,
|
|
4086
|
+
"aria-label": 'Text input filter',
|
|
4087
|
+
onFocus: event => {
|
|
4088
|
+
event.stopPropagation();
|
|
4089
|
+
event.preventDefault();
|
|
4090
|
+
},
|
|
4091
|
+
onClick: event => {
|
|
4092
|
+
event.stopPropagation();
|
|
4093
|
+
event.preventDefault();
|
|
4094
|
+
}
|
|
4095
|
+
}), searchStr && React__default.createElement("pfe-icon", {
|
|
4096
|
+
class: 'clear-icon action-icon',
|
|
4097
|
+
icon: 'fas-times',
|
|
4098
|
+
onClick: event => onChange('', event)
|
|
4099
|
+
}), React__default.createElement("pfe-icon", {
|
|
4100
|
+
class: 'search-icon action-icon',
|
|
4101
|
+
icon: 'fas-search-solid'
|
|
4102
|
+
}));
|
|
4103
|
+
};
|
|
4104
|
+
|
|
4105
|
+
const ExcludedPackagesTable = ({
|
|
4106
|
+
excludedPackages,
|
|
4107
|
+
isLoading
|
|
4108
|
+
}) => {
|
|
4109
|
+
const renderPackagesRow = ({
|
|
4110
|
+
gpg,
|
|
4111
|
+
name,
|
|
4112
|
+
version,
|
|
4113
|
+
release,
|
|
4114
|
+
architecture,
|
|
4115
|
+
nvra,
|
|
4116
|
+
summary
|
|
4117
|
+
}) => {
|
|
4118
|
+
return [gpg ? React__default.createElement("a", {
|
|
4119
|
+
href: `https://access.redhat.com/downloads/content/${name}/${version}}-${release}/${architecture}/${gpg == null ? void 0 : gpg.slice(-8)}/package`,
|
|
4120
|
+
target: '_blank',
|
|
4121
|
+
rel: 'noopener noreferrer'
|
|
4122
|
+
}, nvra) : React__default.createElement("span", null, nvra), summary];
|
|
4123
|
+
};
|
|
4124
|
+
|
|
4125
|
+
const onTextInputFilterChange = (text, {
|
|
4126
|
+
nvra,
|
|
4127
|
+
summary
|
|
4128
|
+
}) => `${nvra + summary}`.toLowerCase().includes(text.toLowerCase());
|
|
4129
|
+
|
|
4130
|
+
return React__default.createElement("div", {
|
|
4131
|
+
className: 'excluded-packages-table'
|
|
4132
|
+
}, React__default.createElement(FilterableTable, {
|
|
4133
|
+
isLoading: isLoading,
|
|
4134
|
+
tableName: 'Excluded packages table',
|
|
4135
|
+
columns: [{
|
|
4136
|
+
title: 'Excluded Package'
|
|
4137
|
+
}, {
|
|
4138
|
+
title: 'Summary'
|
|
4139
|
+
}],
|
|
4140
|
+
items: excludedPackages,
|
|
4141
|
+
renderRow: renderPackagesRow,
|
|
4142
|
+
perPageOptions: [{
|
|
4143
|
+
title: '5',
|
|
4144
|
+
value: 5
|
|
4145
|
+
}, {
|
|
4146
|
+
title: '10',
|
|
4147
|
+
value: 10
|
|
4148
|
+
}, {
|
|
4149
|
+
title: '20',
|
|
4150
|
+
value: 20
|
|
4151
|
+
}],
|
|
4152
|
+
filters: [React__default.createElement(FilterInput, {
|
|
4153
|
+
key: 'excluded-packages-table__filter-input',
|
|
4154
|
+
onChange: onTextInputFilterChange,
|
|
4155
|
+
placeholder: 'Filter excluded packages'
|
|
4156
|
+
})]
|
|
4157
|
+
}));
|
|
4158
|
+
};
|
|
4159
|
+
|
|
4160
|
+
function EcoSelect({
|
|
4161
|
+
variant,
|
|
4162
|
+
placeholderText,
|
|
4163
|
+
options,
|
|
4164
|
+
onChange,
|
|
4165
|
+
'aria-label': ariaLabel
|
|
4166
|
+
}) {
|
|
4167
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
4168
|
+
const [selected, setSelected] = useState([]);
|
|
4169
|
+
|
|
4170
|
+
const onToggle = isOpen => setIsOpen(isOpen);
|
|
4171
|
+
|
|
4172
|
+
const onSelect = (event, selection) => {
|
|
4173
|
+
const result = selected.includes(selection) ? selected.filter(item => item !== selection) : [selection, ...selected];
|
|
4174
|
+
setSelected(() => {
|
|
4175
|
+
onChange && onChange(result, event);
|
|
4176
|
+
return result;
|
|
4177
|
+
});
|
|
4178
|
+
};
|
|
4179
|
+
|
|
4180
|
+
const id = uniqueId('select-');
|
|
4181
|
+
return React__default.createElement("div", {
|
|
4182
|
+
className: 'select'
|
|
4183
|
+
}, React__default.createElement(Select, {
|
|
4184
|
+
id: id,
|
|
4185
|
+
variant: variant,
|
|
4186
|
+
"aria-label": ariaLabel,
|
|
4187
|
+
onToggle: onToggle,
|
|
4188
|
+
onSelect: onSelect,
|
|
4189
|
+
selections: selected,
|
|
4190
|
+
isOpen: isOpen,
|
|
4191
|
+
placeholderText: placeholderText
|
|
4192
|
+
}, options.map(option => React__default.createElement(SelectOption, {
|
|
4193
|
+
key: option,
|
|
4194
|
+
value: option
|
|
4195
|
+
}))));
|
|
4196
|
+
}
|
|
4197
|
+
|
|
4198
|
+
const ToggleGroup = props => {
|
|
4199
|
+
const [selected, setSelected] = useState('');
|
|
4200
|
+
|
|
4201
|
+
const onClick = (_, event) => {
|
|
4202
|
+
const id = event.currentTarget.id;
|
|
4203
|
+
setSelected(() => {
|
|
4204
|
+
props.onChange && props.onChange(id, event);
|
|
4205
|
+
return id;
|
|
4206
|
+
});
|
|
4207
|
+
};
|
|
4208
|
+
|
|
4209
|
+
return React__default.createElement(ToggleGroup$1, {
|
|
4210
|
+
"aria-label": props['aria-label']
|
|
4211
|
+
}, props.options.map((option, index) => React__default.createElement(ToggleGroupItem, {
|
|
4212
|
+
text: option.text,
|
|
4213
|
+
key: index,
|
|
4214
|
+
buttonId: option.id,
|
|
4215
|
+
isSelected: selected === option.id,
|
|
4216
|
+
onChange: onClick
|
|
4217
|
+
})));
|
|
4218
|
+
};
|
|
4219
|
+
|
|
4220
|
+
/* eslint-disable camelcase */
|
|
4221
|
+
const VulnerabilitiesTable = ({
|
|
4222
|
+
vulnerabilities,
|
|
4223
|
+
isLoading
|
|
4224
|
+
}) => {
|
|
4225
|
+
const getImpact = ({
|
|
4226
|
+
severity
|
|
4227
|
+
}) => {
|
|
4228
|
+
return React__default.createElement(React__default.Fragment, null, React__default.createElement("div", {
|
|
4229
|
+
className: 'vulnerabilities-table__impact-cell'
|
|
4230
|
+
}, React__default.createElement("pfe-icon", {
|
|
4231
|
+
class: `color-${severity.toLowerCase()}`,
|
|
4232
|
+
className: `color-${severity.toLowerCase()}`,
|
|
4233
|
+
icon: 'fas-shield-fill-exclamation'
|
|
4234
|
+
}), React__default.createElement("span", null, severity)));
|
|
4235
|
+
};
|
|
4236
|
+
|
|
4237
|
+
const getCVE = ({
|
|
4238
|
+
cve_id
|
|
4239
|
+
}) => {
|
|
4240
|
+
return React__default.createElement(React__default.Fragment, null, React__default.createElement("div", {
|
|
4241
|
+
className: 'vulnerabilities-table__cve-cell'
|
|
4242
|
+
}, React__default.createElement("a", {
|
|
4243
|
+
href: `https://access.redhat.com/security/cve/${cve_id}`,
|
|
4244
|
+
target: '_blank',
|
|
4245
|
+
rel: 'noopener noreferrer'
|
|
4246
|
+
}, cve_id)));
|
|
4247
|
+
};
|
|
4248
|
+
|
|
4249
|
+
const getAffectedPackages = rpms => {
|
|
4250
|
+
return React__default.createElement(React__default.Fragment, null, rpms == null ? void 0 : rpms.map(({
|
|
4251
|
+
gpg,
|
|
4252
|
+
name,
|
|
4253
|
+
version,
|
|
4254
|
+
release,
|
|
4255
|
+
architecture,
|
|
4256
|
+
nvra
|
|
4257
|
+
} = {}, index) => {
|
|
4258
|
+
return gpg ? React__default.createElement("div", {
|
|
4259
|
+
className: 'vulnerabilities-table__affected-packages-cell',
|
|
4260
|
+
key: `affected-package-${index}`
|
|
4261
|
+
}, React__default.createElement("a", {
|
|
4262
|
+
href: `https://access.redhat.com/downloads/content/${name}/${version}-${release}/${architecture}/${gpg == null ? void 0 : gpg.slice(-8)}/package`,
|
|
4263
|
+
target: '_blank',
|
|
4264
|
+
rel: 'noopener noreferrer'
|
|
4265
|
+
}, nvra)) : React__default.createElement("div", {
|
|
4266
|
+
key: `affected-package-${index}`,
|
|
4267
|
+
className: 'vulnerabilities-table__affected-packages-cell'
|
|
4268
|
+
}, React__default.createElement("span", null, nvra));
|
|
4269
|
+
}));
|
|
4270
|
+
};
|
|
4271
|
+
|
|
4272
|
+
const getRPMAdvisory = ({
|
|
4273
|
+
advisory_type,
|
|
4274
|
+
advisory_id
|
|
4275
|
+
}) => {
|
|
4276
|
+
return React__default.createElement(React__default.Fragment, null, React__default.createElement("div", {
|
|
4277
|
+
className: 'vulnerabilities-table__rpm-advisory-cell'
|
|
4278
|
+
}, React__default.createElement("a", {
|
|
4279
|
+
href: `https://access.redhat.com/errata/${advisory_type}-${advisory_id}`,
|
|
4280
|
+
target: '_blank',
|
|
4281
|
+
rel: 'noopener noreferrer'
|
|
4282
|
+
}, advisory_type, "-", advisory_id)));
|
|
4283
|
+
};
|
|
4284
|
+
|
|
4285
|
+
const renderVulnerabilitiesRow = vulnerability => {
|
|
4286
|
+
return [getImpact(vulnerability), getCVE(vulnerability), getAffectedPackages(vulnerability.rpm_nvra_with_link_data), getRPMAdvisory(vulnerability), vulnerability != null && vulnerability.creation_date ? format(new Date(vulnerability == null ? void 0 : vulnerability.creation_date), 'MMM dd, yyyy hh:mm a') : ''];
|
|
4287
|
+
};
|
|
4288
|
+
|
|
4289
|
+
const onTextInputFilterChange = (text, {
|
|
4290
|
+
rpm_nvra_with_link_data,
|
|
4291
|
+
severity,
|
|
4292
|
+
cve_id,
|
|
4293
|
+
advisory_id
|
|
4294
|
+
}) => {
|
|
4295
|
+
const nvraList = rpm_nvra_with_link_data.reduce((result, {
|
|
4296
|
+
nvra
|
|
4297
|
+
}) => result += nvra, '');
|
|
4298
|
+
return `${severity + cve_id + advisory_id + nvraList}`.toLowerCase().includes(text.toLowerCase());
|
|
4299
|
+
};
|
|
4300
|
+
|
|
4301
|
+
const onStatusFilterChange = (selected, vulnerability) => {
|
|
4302
|
+
return selected === 'fixed' ? vulnerability.advisory_id !== null : selected === 'unfixed' ? vulnerability.advisory_id === null : true;
|
|
4303
|
+
};
|
|
4304
|
+
|
|
4305
|
+
const onImpactFilterChange = (selected, vulnerability) => {
|
|
4306
|
+
return selected.length > 0 ? selected.includes(vulnerability.severity) : true;
|
|
4307
|
+
};
|
|
4308
|
+
|
|
4309
|
+
return React__default.createElement("div", {
|
|
4310
|
+
className: 'vulnerabilities-table'
|
|
4311
|
+
}, React__default.createElement(FilterableTable, {
|
|
4312
|
+
tableName: 'Vulnerabilities impact table',
|
|
4313
|
+
columns: [{
|
|
4314
|
+
title: 'Impact',
|
|
4315
|
+
sortField: 'severity',
|
|
4316
|
+
sortFn: vulnerability => severitySortOrder[vulnerability.severity]
|
|
4317
|
+
}, {
|
|
4318
|
+
title: 'CVE',
|
|
4319
|
+
sortField: 'cve_id'
|
|
4320
|
+
}, {
|
|
4321
|
+
title: 'Affected Package(s)'
|
|
4322
|
+
}, {
|
|
4323
|
+
title: 'RPM Advisory',
|
|
4324
|
+
sortField: 'advisory_id'
|
|
4325
|
+
}, {
|
|
4326
|
+
title: 'Created',
|
|
4327
|
+
sortField: 'creation_date',
|
|
4328
|
+
sortFn: vulnerability => new Date(vulnerability == null ? void 0 : vulnerability.creation_date).getTime()
|
|
4329
|
+
}],
|
|
4330
|
+
items: vulnerabilities,
|
|
4331
|
+
renderRow: renderVulnerabilitiesRow,
|
|
4332
|
+
isLoading: isLoading,
|
|
4333
|
+
perPageOptions: [{
|
|
4334
|
+
title: '5',
|
|
4335
|
+
value: 5
|
|
4336
|
+
}, {
|
|
4337
|
+
title: '10',
|
|
4338
|
+
value: 10
|
|
4339
|
+
}, {
|
|
4340
|
+
title: '20',
|
|
4341
|
+
value: 20
|
|
4342
|
+
}],
|
|
4343
|
+
filters: [React__default.createElement(FilterInput, {
|
|
4344
|
+
key: 'vulnerabilities-table__filter-input',
|
|
4345
|
+
onChange: onTextInputFilterChange,
|
|
4346
|
+
placeholder: 'Filter vulnerabilities'
|
|
4347
|
+
}), React__default.createElement(ToggleGroup, {
|
|
4348
|
+
key: 'vulnerabilities-table__toggle-group',
|
|
4349
|
+
onChange: onStatusFilterChange,
|
|
4350
|
+
"aria-label": 'Vulnerability status filter',
|
|
4351
|
+
options: [{
|
|
4352
|
+
id: 'all',
|
|
4353
|
+
text: 'All'
|
|
4354
|
+
}, {
|
|
4355
|
+
id: 'fixed',
|
|
4356
|
+
text: 'Fixed'
|
|
4357
|
+
}, {
|
|
4358
|
+
id: 'unfixed',
|
|
4359
|
+
text: 'Unfixed'
|
|
4360
|
+
}]
|
|
4361
|
+
}), React__default.createElement(EcoSelect, {
|
|
4362
|
+
key: 'vulnerabilities-table__select',
|
|
4363
|
+
onChange: onImpactFilterChange,
|
|
4364
|
+
"aria-label": 'Impact filter',
|
|
4365
|
+
placeholderText: 'Impact',
|
|
4366
|
+
variant: 'checkbox',
|
|
4367
|
+
options: Array.from(new Set(vulnerabilities.map(vulnerability => vulnerability.severity)))
|
|
4368
|
+
})]
|
|
4369
|
+
}));
|
|
4370
|
+
};
|
|
4371
|
+
|
|
4372
|
+
/* eslint-disable camelcase */
|
|
4373
|
+
const severitySortOrder = {
|
|
4374
|
+
Critical: 1,
|
|
4375
|
+
Important: 2,
|
|
4376
|
+
Moderate: 3,
|
|
4377
|
+
Low: 4
|
|
4378
|
+
};
|
|
4379
|
+
PfeIcon.addIconSet('fas', './img', (iconName, _, path) => {
|
|
4380
|
+
const name = iconName.replace('fas-', '');
|
|
4381
|
+
return `${path}/${name}.svg`;
|
|
4382
|
+
});
|
|
4383
|
+
|
|
4384
|
+
const InsertCss = () => {
|
|
4385
|
+
const styleId = 'example-component-styles';
|
|
4386
|
+
|
|
4387
|
+
if (!document.getElementById(styleId)) {
|
|
4388
|
+
const styleTag = document.createElement('style');
|
|
4389
|
+
styleTag.id = styleId;
|
|
4390
|
+
styleTag.innerHTML = css_248z;
|
|
4391
|
+
document.body.appendChild(styleTag);
|
|
4392
|
+
}
|
|
4393
|
+
};
|
|
4394
|
+
|
|
4395
|
+
const PackagesTable = ({
|
|
4396
|
+
vulnerabilities: _vulnerabilities = [],
|
|
4397
|
+
rpms: _rpms = [],
|
|
4398
|
+
isLoading: _isLoading = false
|
|
4399
|
+
}) => {
|
|
4400
|
+
const [excludedPackages, setExcludedPackages] = React.useState([]);
|
|
4401
|
+
const [uniqueVulnerabilities, setUniqueVulnerabilities] = React.useState([]);
|
|
4402
|
+
React.useEffect(() => {
|
|
4403
|
+
const VALID_REDHAT_GPG_KEYS = ['199e2f91fd431d51', '5326810137017186', '45689c882fa658e0', '219180cddb42a60e', '7514f77d8366b0d9', 'fd372689897da07a', '938a80caf21541eb', '08b871e6a5787476'];
|
|
4404
|
+
|
|
4405
|
+
const packages = _rpms.filter(({
|
|
4406
|
+
gpg
|
|
4407
|
+
}) => !VALID_REDHAT_GPG_KEYS.includes(gpg));
|
|
4408
|
+
|
|
4409
|
+
setExcludedPackages(packages);
|
|
4410
|
+
const uniqueVulnerabilities = [..._vulnerabilities]; // augment vulnerabilities with link data
|
|
4411
|
+
|
|
4412
|
+
uniqueVulnerabilities.forEach(vulnerability => {
|
|
4413
|
+
var _vulnerability$packag;
|
|
4414
|
+
|
|
4415
|
+
vulnerability.rpm_nvra_with_link_data = [];
|
|
4416
|
+
return vulnerability == null ? void 0 : (_vulnerability$packag = vulnerability.packages) == null ? void 0 : _vulnerability$packag.forEach(p => {
|
|
4417
|
+
var _p$rpm_nvra;
|
|
4418
|
+
|
|
4419
|
+
return p == null ? void 0 : (_p$rpm_nvra = p.rpm_nvra) == null ? void 0 : _p$rpm_nvra.forEach(rpm_nvra => {
|
|
4420
|
+
const link_data = _rpms == null ? void 0 : _rpms.filter(pk => pk.nvra === rpm_nvra);
|
|
4421
|
+
vulnerability.rpm_nvra_with_link_data.push(link_data[0]);
|
|
4422
|
+
});
|
|
4423
|
+
});
|
|
4424
|
+
}); // sort vulnerabilities by severity
|
|
4425
|
+
|
|
4426
|
+
uniqueVulnerabilities.sort(vulnerability => severitySortOrder[vulnerability.severity]); // filter out vulnerabilities with duplicate CVE IDs
|
|
4427
|
+
|
|
4428
|
+
uniqueVulnerabilities.filter((value, index, self) => self.findIndex(vulnerability => vulnerability.cve_id === value.cve_id) === index);
|
|
4429
|
+
setUniqueVulnerabilities(uniqueVulnerabilities);
|
|
4430
|
+
}, [_rpms, _vulnerabilities]);
|
|
4431
|
+
InsertCss();
|
|
4432
|
+
return React.createElement(React.Fragment, null, (uniqueVulnerabilities.length > 0 || excludedPackages.length > 0) && React.createElement("div", {
|
|
4433
|
+
className: 'packages-table'
|
|
4434
|
+
}, React.createElement("pfe-tabs", {
|
|
4435
|
+
"pfe-variant": 'earth',
|
|
4436
|
+
on: 'light'
|
|
4437
|
+
}, uniqueVulnerabilities.length > 0 && React.createElement(React.Fragment, null, React.createElement("pfe-tab", {
|
|
4438
|
+
slot: 'tab',
|
|
4439
|
+
role: 'heading'
|
|
4440
|
+
}, "Vulnerabilities ", `(${uniqueVulnerabilities.length})`), React.createElement("pfe-tab-panel", {
|
|
4441
|
+
slot: 'panel',
|
|
4442
|
+
role: 'region'
|
|
4443
|
+
}, React.createElement(VulnerabilitiesTable, {
|
|
4444
|
+
vulnerabilities: uniqueVulnerabilities,
|
|
4445
|
+
isLoading: _isLoading
|
|
4446
|
+
}))), excludedPackages.length > 0 && React.createElement(React.Fragment, null, React.createElement("pfe-tab", {
|
|
4447
|
+
slot: 'tab',
|
|
4448
|
+
role: 'heading'
|
|
4449
|
+
}, "Excluded Packages ", `(${excludedPackages.length})`), React.createElement("pfe-tab-panel", {
|
|
4450
|
+
slot: 'panel',
|
|
4451
|
+
role: 'region'
|
|
4452
|
+
}, React.createElement("p", {
|
|
4453
|
+
className: 'packages-table__excluded-packages-disclaimer'
|
|
4454
|
+
}, "The following packages were found in this image and cannot be scanned or compared to public vulnerability information. This image may include additional packages or content not found or listed below."), React.createElement(ExcludedPackagesTable, {
|
|
4455
|
+
excludedPackages: excludedPackages,
|
|
4456
|
+
isLoading: _isLoading
|
|
4457
|
+
}))))));
|
|
4458
|
+
};
|
|
4459
|
+
|
|
4460
|
+
export { PackagesTable, severitySortOrder };
|