You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
635 lines
21 KiB
635 lines
21 KiB
(function (global, factory) {
|
|
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
|
typeof define === 'function' && define.amd ? define(factory) :
|
|
(global.PFElement = factory());
|
|
}(this, (function () { 'use strict';
|
|
|
|
var logger = function logger() {
|
|
return null;
|
|
};
|
|
|
|
function reveal() {
|
|
logger("[reveal] elements ready, revealing the body");
|
|
window.document.body.removeAttribute("unresolved");
|
|
}
|
|
|
|
function autoReveal(logFunction) {
|
|
logger = logFunction;
|
|
// If Web Components are already ready, run the handler right away. If they
|
|
// are not yet ready, wait.
|
|
//
|
|
// see https://github.com/github/webcomponentsjs#webcomponents-loaderjs for
|
|
// info about web component readiness events
|
|
var polyfillPresent = window.WebComponents;
|
|
var polyfillReady = polyfillPresent && window.WebComponents.ready;
|
|
|
|
if (!polyfillPresent || polyfillReady) {
|
|
handleWebComponentsReady();
|
|
} else {
|
|
window.addEventListener("WebComponentsReady", handleWebComponentsReady);
|
|
}
|
|
}
|
|
|
|
function handleWebComponentsReady() {
|
|
logger("[reveal] web components ready");
|
|
reveal();
|
|
}
|
|
|
|
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
|
|
return typeof obj;
|
|
} : function (obj) {
|
|
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
|
|
};
|
|
|
|
var classCallCheck = function (instance, Constructor) {
|
|
if (!(instance instanceof Constructor)) {
|
|
throw new TypeError("Cannot call a class as a function");
|
|
}
|
|
};
|
|
|
|
var createClass = function () {
|
|
function defineProperties(target, props) {
|
|
for (var i = 0; i < props.length; i++) {
|
|
var descriptor = props[i];
|
|
descriptor.enumerable = descriptor.enumerable || false;
|
|
descriptor.configurable = true;
|
|
if ("value" in descriptor) descriptor.writable = true;
|
|
Object.defineProperty(target, descriptor.key, descriptor);
|
|
}
|
|
}
|
|
|
|
return function (Constructor, protoProps, staticProps) {
|
|
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
|
if (staticProps) defineProperties(Constructor, staticProps);
|
|
return Constructor;
|
|
};
|
|
}();
|
|
|
|
var inherits = function (subClass, superClass) {
|
|
if (typeof superClass !== "function" && superClass !== null) {
|
|
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
|
|
}
|
|
|
|
subClass.prototype = Object.create(superClass && superClass.prototype, {
|
|
constructor: {
|
|
value: subClass,
|
|
enumerable: false,
|
|
writable: true,
|
|
configurable: true
|
|
}
|
|
});
|
|
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
|
|
};
|
|
|
|
var possibleConstructorReturn = function (self, call) {
|
|
if (!self) {
|
|
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
|
}
|
|
|
|
return call && (typeof call === "object" || typeof call === "function") ? call : self;
|
|
};
|
|
|
|
var toConsumableArray = function (arr) {
|
|
if (Array.isArray(arr)) {
|
|
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
|
|
|
|
return arr2;
|
|
} else {
|
|
return Array.from(arr);
|
|
}
|
|
};
|
|
|
|
/*!
|
|
* PatternFly Elements: PFElement 1.0.0-prerelease.55
|
|
* @license
|
|
* Copyright 2020 Red Hat, Inc.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*
|
|
*/
|
|
var prefix = "pfe-";
|
|
|
|
var PFElement = function (_HTMLElement) {
|
|
inherits(PFElement, _HTMLElement);
|
|
createClass(PFElement, [{
|
|
key: "cssVariable",
|
|
value: function cssVariable(name, value) {
|
|
var element = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this;
|
|
|
|
name = name.substr(0, 2) !== "--" ? "--" + name : name;
|
|
if (value) {
|
|
element.style.setProperty(name, value);
|
|
}
|
|
return window.getComputedStyle(element).getPropertyValue(name).trim();
|
|
}
|
|
|
|
// Returns a single element assigned to that slot; if multiple, it returns the first
|
|
|
|
}, {
|
|
key: "has_slot",
|
|
value: function has_slot(name) {
|
|
return this.querySelector("[slot='" + name + "']");
|
|
}
|
|
|
|
// Returns an array with all elements assigned to that slot
|
|
|
|
}, {
|
|
key: "has_slots",
|
|
value: function has_slots(name) {
|
|
return [].concat(toConsumableArray(this.querySelectorAll("[slot='" + name + "']")));
|
|
}
|
|
|
|
// Update the theme context for self and children
|
|
|
|
}, {
|
|
key: "context_update",
|
|
value: function context_update() {
|
|
// TODO: update this to use :defined?
|
|
var children = this.querySelectorAll("[pfelement]");
|
|
var theme = this.cssVariable("theme");
|
|
|
|
// Manually adding `pfe-theme` overrides the css variable
|
|
if (this.hasAttribute("pfe-theme")) {
|
|
theme = this.getAttribute("pfe-theme");
|
|
// Update the css variable to match the data attribute
|
|
this.cssVariable("theme", theme);
|
|
}
|
|
|
|
// Update theme for self
|
|
this.context_set(theme);
|
|
|
|
// For each nested, already upgraded component
|
|
// set the context based on the child's value of --theme
|
|
// Note: this prevents contexts from parents overriding
|
|
// the child's context should it exist
|
|
[].concat(toConsumableArray(children)).map(function (child) {
|
|
if (child.connected) {
|
|
child.context_set(theme);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Get the theme variable if it exists, set it as an attribute
|
|
|
|
}, {
|
|
key: "context_set",
|
|
value: function context_set(fallback) {
|
|
var theme = this.cssVariable("theme");
|
|
if (!theme) {
|
|
theme = this.getAttribute("pfe-theme");
|
|
}
|
|
if (!theme && fallback) {
|
|
theme = fallback;
|
|
}
|
|
if (theme && this.hasAttribute("pfelement")) {
|
|
this.setAttribute("on", theme);
|
|
}
|
|
}
|
|
}, {
|
|
key: "randomId",
|
|
get: function get$$1() {
|
|
return "pfe-" + Math.random().toString(36).substr(2, 9);
|
|
}
|
|
}, {
|
|
key: "version",
|
|
get: function get$$1() {
|
|
return this._pfeClass.version;
|
|
}
|
|
}, {
|
|
key: "pfeType",
|
|
get: function get$$1() {
|
|
return this.getAttribute(prefix + "type");
|
|
},
|
|
set: function set$$1(value) {
|
|
this.setAttribute(prefix + "type", value);
|
|
}
|
|
}], [{
|
|
key: "create",
|
|
value: function create(pfe) {
|
|
window.customElements.define(pfe.tag, pfe);
|
|
}
|
|
}, {
|
|
key: "debugLog",
|
|
value: function debugLog() {
|
|
var preference = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
|
|
|
if (preference !== null) {
|
|
PFElement._debugLog = !!preference;
|
|
}
|
|
return PFElement._debugLog;
|
|
}
|
|
}, {
|
|
key: "log",
|
|
value: function log() {
|
|
if (PFElement.debugLog()) {
|
|
var _console;
|
|
|
|
(_console = console).log.apply(_console, arguments);
|
|
}
|
|
}
|
|
}, {
|
|
key: "PfeTypes",
|
|
get: function get$$1() {
|
|
return {
|
|
Container: "container",
|
|
Content: "content",
|
|
Combo: "combo"
|
|
};
|
|
}
|
|
}, {
|
|
key: "version",
|
|
get: function get$$1() {
|
|
return "{{version}}";
|
|
}
|
|
}, {
|
|
key: "observedAttributes",
|
|
get: function get$$1() {
|
|
return ["pfe-theme"];
|
|
}
|
|
}]);
|
|
|
|
function PFElement(pfeClass) {
|
|
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
|
|
_ref$type = _ref.type,
|
|
type = _ref$type === undefined ? null : _ref$type,
|
|
_ref$delayRender = _ref.delayRender,
|
|
delayRender = _ref$delayRender === undefined ? false : _ref$delayRender;
|
|
|
|
classCallCheck(this, PFElement);
|
|
|
|
var _this = possibleConstructorReturn(this, (PFElement.__proto__ || Object.getPrototypeOf(PFElement)).call(this));
|
|
|
|
_this.connected = false;
|
|
_this._pfeClass = pfeClass;
|
|
_this.tag = pfeClass.tag;
|
|
_this.props = pfeClass.properties;
|
|
_this.slots = pfeClass.slots;
|
|
_this._queue = [];
|
|
_this.template = document.createElement("template");
|
|
|
|
_this.log("Constructing...");
|
|
|
|
_this.attachShadow({ mode: "open" });
|
|
|
|
if (type) {
|
|
_this._queueAction({
|
|
type: "setProperty",
|
|
data: {
|
|
name: "pfeType",
|
|
value: type
|
|
}
|
|
});
|
|
}
|
|
|
|
if (!delayRender) {
|
|
_this.log("Render...");
|
|
_this.render();
|
|
_this.log("Rendered.");
|
|
}
|
|
|
|
_this.log("Constructed.");
|
|
return _this;
|
|
}
|
|
|
|
createClass(PFElement, [{
|
|
key: "connectedCallback",
|
|
value: function connectedCallback() {
|
|
this.connected = true;
|
|
this.log("Connecting...");
|
|
|
|
if (window.ShadyCSS) {
|
|
this.log("Styling...");
|
|
window.ShadyCSS.styleElement(this);
|
|
this.log("Styled.");
|
|
}
|
|
|
|
// Throw a warning if the on attribute was manually added before upgrade
|
|
if (!this.hasAttribute("pfelement") && this.hasAttribute("on")) {
|
|
console.warn("" + this.tag + (this.id ? "[#" + this.id + "]" : "") + ": The \"on\" attribute is protected and should not be manually added to a component. The base class will manage this value for you on upgrade.");
|
|
}
|
|
|
|
// @TODO maybe we should use just the attribute instead of the class?
|
|
// https://github.com/angular/angular/issues/15399#issuecomment-318785677
|
|
this.classList.add("PFElement");
|
|
this.setAttribute("pfelement", "");
|
|
|
|
if (_typeof(this.props) === "object") {
|
|
this._mapSchemaToProperties(this.tag, this.props);
|
|
this.log("Properties attached.");
|
|
}
|
|
|
|
if (_typeof(this.slots) === "object") {
|
|
this._mapSchemaToSlots(this.tag, this.slots);
|
|
this.log("Slots attached.");
|
|
}
|
|
|
|
if (this._queue.length) {
|
|
this._processQueue();
|
|
}
|
|
|
|
// Initialize the on attribute if a theme variable is set
|
|
// do not update the on attribute if a user has manually added it
|
|
// then trigger an update in nested components
|
|
this.context_update();
|
|
|
|
this.log("Connected.");
|
|
}
|
|
}, {
|
|
key: "disconnectedCallback",
|
|
value: function disconnectedCallback() {
|
|
this.log("Disconnecting...");
|
|
|
|
this.connected = false;
|
|
|
|
this.log("Disconnected.");
|
|
}
|
|
}, {
|
|
key: "attributeChangedCallback",
|
|
value: function attributeChangedCallback(attr, oldVal, newVal) {
|
|
if (!this._pfeClass.cascadingAttributes) {
|
|
return;
|
|
}
|
|
|
|
var cascadeTo = this._pfeClass.cascadingAttributes[attr];
|
|
if (cascadeTo) {
|
|
this._copyAttribute(attr, cascadeTo);
|
|
}
|
|
|
|
if (attr === "pfe-theme") {
|
|
this.context_update();
|
|
}
|
|
}
|
|
}, {
|
|
key: "_copyAttribute",
|
|
value: function _copyAttribute(name, to) {
|
|
var recipients = [].concat(toConsumableArray(this.querySelectorAll(to)), toConsumableArray(this.shadowRoot.querySelectorAll(to)));
|
|
var value = this.getAttribute(name);
|
|
var fname = value == null ? "removeAttribute" : "setAttribute";
|
|
var _iteratorNormalCompletion = true;
|
|
var _didIteratorError = false;
|
|
var _iteratorError = undefined;
|
|
|
|
try {
|
|
for (var _iterator = recipients[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
|
var node = _step.value;
|
|
|
|
node[fname](name, value);
|
|
}
|
|
} catch (err) {
|
|
_didIteratorError = true;
|
|
_iteratorError = err;
|
|
} finally {
|
|
try {
|
|
if (!_iteratorNormalCompletion && _iterator.return) {
|
|
_iterator.return();
|
|
}
|
|
} finally {
|
|
if (_didIteratorError) {
|
|
throw _iteratorError;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Map the imported properties json to real props on the element
|
|
// @notice static getter of properties is built via tooling
|
|
// to edit modify src/element.json
|
|
|
|
}, {
|
|
key: "_mapSchemaToProperties",
|
|
value: function _mapSchemaToProperties(tag, properties) {
|
|
var _this2 = this;
|
|
|
|
this.log("Mapping properties...");
|
|
// Loop over the properties provided by the schema
|
|
Object.keys(properties).forEach(function (attr) {
|
|
var data = properties[attr];
|
|
|
|
// Only attach the information if the data provided is a schema object
|
|
if ((typeof data === "undefined" ? "undefined" : _typeof(data)) === "object") {
|
|
// Prefix default is true
|
|
var hasPrefix = true;
|
|
var attrName = attr;
|
|
// Set the attribute's property equal to the schema input
|
|
_this2[attr] = data;
|
|
// Initialize the value to null
|
|
_this2[attr].value = null;
|
|
|
|
if (typeof _this2[attr].prefixed !== "undefined") {
|
|
hasPrefix = _this2[attr].prefixed;
|
|
}
|
|
|
|
if (hasPrefix) {
|
|
attrName = "" + prefix + attr;
|
|
}
|
|
|
|
// If the attribute exists on the host
|
|
if (_this2.hasAttribute(attrName)) {
|
|
// Set property value based on the existing attribute
|
|
_this2[attr].value = _this2.getAttribute(attrName);
|
|
}
|
|
// Otherwise, look for a default and use that instead
|
|
else if (data.default) {
|
|
var dependency_exists = _this2._hasDependency(tag, data.options);
|
|
var no_dependencies = !data.options || data.options && !data.options.dependencies.length;
|
|
// If the dependency exists or there are no dependencies, set the default
|
|
if (dependency_exists || no_dependencies) {
|
|
_this2.setAttribute(attrName, data.default);
|
|
_this2[attr].value = data.default;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
this.log("Properties mapped.");
|
|
}
|
|
|
|
// Test whether expected dependencies exist
|
|
|
|
}, {
|
|
key: "_hasDependency",
|
|
value: function _hasDependency(tag, opts) {
|
|
// Get any possible dependencies for this attribute to exist
|
|
var dependencies = opts ? opts.dependencies : [];
|
|
// Initialize the dependency return value
|
|
var hasDependency = false;
|
|
// Check that dependent item exists
|
|
// Loop through the dependencies defined
|
|
for (var i = 0; i < dependencies.length; i += 1) {
|
|
var slot_exists = dependencies[i].type === "slot" && this.has_slots(tag + "--" + dependencies[i].id).length > 0;
|
|
var attribute_exists = dependencies[i].type === "attribute" && this.getAttribute("" + prefix + dependencies[i].id);
|
|
// If the type is slot, check that it exists OR
|
|
// if the type is an attribute, check if the attribute is defined
|
|
if (slot_exists || attribute_exists) {
|
|
// If the slot does exist, add the attribute with the default value
|
|
hasDependency = true;
|
|
// Exit the loop
|
|
break;
|
|
}
|
|
}
|
|
// Return a boolean if the dependency exists
|
|
return hasDependency;
|
|
}
|
|
|
|
// Map the imported slots json
|
|
// @notice static getter of properties is built via tooling
|
|
// to edit modify src/element.json
|
|
|
|
}, {
|
|
key: "_mapSchemaToSlots",
|
|
value: function _mapSchemaToSlots(tag, slots) {
|
|
var _this3 = this;
|
|
|
|
this.log("Validate slots...");
|
|
// Loop over the properties provided by the schema
|
|
Object.keys(slots).forEach(function (slot) {
|
|
var slotObj = slots[slot];
|
|
|
|
// Only attach the information if the data provided is a schema object
|
|
if ((typeof slotObj === "undefined" ? "undefined" : _typeof(slotObj)) === "object") {
|
|
var slotExists = false;
|
|
var result = [];
|
|
// If it's a named slot, look for that slot definition
|
|
if (slotObj.namedSlot) {
|
|
// Check prefixed slots
|
|
result = _this3.has_slots(tag + "--" + slot);
|
|
if (result.length > 0) {
|
|
slotObj.nodes = result;
|
|
slotExists = true;
|
|
}
|
|
|
|
// Check for unprefixed slots
|
|
result = _this3.has_slots("" + slot);
|
|
if (result.length > 0) {
|
|
slotObj.nodes = result;
|
|
slotExists = true;
|
|
}
|
|
// If it's the default slot, look for direct children not assigned to a slot
|
|
} else {
|
|
result = [].concat(toConsumableArray(_this3.children)).filter(function (child) {
|
|
return !child.hasAttribute("slot");
|
|
});
|
|
|
|
if (result.length > 0) {
|
|
slotObj.nodes = result;
|
|
slotExists = true;
|
|
}
|
|
}
|
|
|
|
// If the slot exists, attach an attribute to the parent to indicate that
|
|
if (slotExists) {
|
|
_this3.setAttribute("has_" + slot, "");
|
|
} else {
|
|
_this3.removeAttribute("has_" + slot);
|
|
}
|
|
}
|
|
});
|
|
this.log("Slots validated.");
|
|
}
|
|
}, {
|
|
key: "_queueAction",
|
|
value: function _queueAction(action) {
|
|
this._queue.push(action);
|
|
}
|
|
}, {
|
|
key: "_processQueue",
|
|
value: function _processQueue() {
|
|
var _this4 = this;
|
|
|
|
this._queue.forEach(function (action) {
|
|
_this4["_" + action.type](action.data);
|
|
});
|
|
|
|
this._queue = [];
|
|
}
|
|
}, {
|
|
key: "_setProperty",
|
|
value: function _setProperty(_ref2) {
|
|
var name = _ref2.name,
|
|
value = _ref2.value;
|
|
|
|
this[name] = value;
|
|
}
|
|
|
|
// @TODO This is a duplicate function to cssVariable above, combine them
|
|
|
|
}, {
|
|
key: "var",
|
|
value: function _var(name) {
|
|
return PFElement.var(name, this);
|
|
}
|
|
}, {
|
|
key: "render",
|
|
value: function render() {
|
|
this.shadowRoot.innerHTML = "";
|
|
this.template.innerHTML = this.html;
|
|
|
|
if (window.ShadyCSS) {
|
|
window.ShadyCSS.prepareTemplate(this.template, this.tag);
|
|
}
|
|
|
|
this.shadowRoot.appendChild(this.template.content.cloneNode(true));
|
|
}
|
|
}, {
|
|
key: "log",
|
|
value: function log() {
|
|
for (var _len = arguments.length, msgs = Array(_len), _key = 0; _key < _len; _key++) {
|
|
msgs[_key] = arguments[_key];
|
|
}
|
|
|
|
PFElement.log.apply(PFElement, ["[" + this.tag + "]"].concat(msgs));
|
|
}
|
|
}, {
|
|
key: "emitEvent",
|
|
value: function emitEvent(name) {
|
|
var _ref3 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
|
|
_ref3$bubbles = _ref3.bubbles,
|
|
bubbles = _ref3$bubbles === undefined ? true : _ref3$bubbles,
|
|
_ref3$cancelable = _ref3.cancelable,
|
|
cancelable = _ref3$cancelable === undefined ? false : _ref3$cancelable,
|
|
_ref3$composed = _ref3.composed,
|
|
composed = _ref3$composed === undefined ? false : _ref3$composed,
|
|
_ref3$detail = _ref3.detail,
|
|
detail = _ref3$detail === undefined ? {} : _ref3$detail;
|
|
|
|
this.log("Custom event: " + name);
|
|
this.dispatchEvent(new CustomEvent(name, {
|
|
bubbles: bubbles,
|
|
cancelable: cancelable,
|
|
composed: composed,
|
|
detail: detail
|
|
}));
|
|
}
|
|
}], [{
|
|
key: "var",
|
|
value: function _var(name) {
|
|
var element = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : document.body;
|
|
|
|
return window.getComputedStyle(element).getPropertyValue(name).trim();
|
|
}
|
|
}]);
|
|
return PFElement;
|
|
}(HTMLElement);
|
|
|
|
autoReveal(PFElement.log);
|
|
|
|
return PFElement;
|
|
|
|
})));
|
|
//# sourceMappingURL=pfelement.umd.js.map
|