Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@ui5/webcomponents-base

Package Overview
Dependencies
Maintainers
2
Versions
493
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ui5/webcomponents-base - npm Package Compare versions

Comparing version 0.11.1 to 0.12.0

src/events/ManagedEvents.js

18

CHANGELOG.md

@@ -6,2 +6,20 @@ # Change Log

# [0.12.0](https://github.com/SAP/ui5-webcomponents/compare/v0.11.0...v0.12.0) (2019-06-10)
### Bug Fixes
* access DOM in connectedCallback instead of constructor ([#524](https://github.com/SAP/ui5-webcomponents/issues/524)) ([0f3b8e4](https://github.com/SAP/ui5-webcomponents/commit/0f3b8e4))
* do not use assignedElements ([#432](https://github.com/SAP/ui5-webcomponents/issues/432)) ([c54c812](https://github.com/SAP/ui5-webcomponents/commit/c54c812))
### Features
* inline english texts if no translation is fetched ([#479](https://github.com/SAP/ui5-webcomponents/issues/479)) ([abfb221](https://github.com/SAP/ui5-webcomponents/commit/abfb221))
* **base:** implement late validation ([#522](https://github.com/SAP/ui5-webcomponents/issues/522)) ([c452d60](https://github.com/SAP/ui5-webcomponents/commit/c452d60))
## [0.11.1](https://github.com/SAP/ui5-webcomponents/compare/v0.11.0...v0.11.1) (2019-05-30)

@@ -8,0 +26,0 @@

4

package.json
{
"name": "@ui5/webcomponents-base",
"version": "0.11.1",
"version": "0.12.0",
"description": "UI5 Web Components: webcomponents.base",

@@ -24,3 +24,3 @@ "author": "SAP SE (https://www.sap.com)",

"dependencies": {
"@ui5/webcomponents-core": "0.11.1",
"@ui5/webcomponents-core": "0.12.0",
"lit-html": "^1.0.0",

@@ -27,0 +27,0 @@ "regenerator-runtime": "0.12.1",

import { getTheme } from "./Configuration.js";
import { getEffectiveStyle } from "./Theming.js";
import { injectWebComponentStyle } from "./theming/StyleInjection.js";
const styleMap = new Map();
const createStyleElement = css => {
// Create a local <style> tag for the real shadow DOM
const style = document.createElement("style");
style.innerHTML = css;
return style;
/**
* Creates the needed CSS for a web component class in the head tag
* Note: IE11, Edge
* @param ElementClass
*/
const createHeadStyle = ElementClass => {
const tag = ElementClass.getMetadata().getTag();
const cssContent = getEffectiveStyle(ElementClass);
injectWebComponentStyle(tag, cssContent);
};
const createConstructableStyleSheet = css => {
const elementStyleSheet = new CSSStyleSheet();
elementStyleSheet.replaceSync(css);
return elementStyleSheet;
};
const _createStyle = (tagName, styleContent) => {
/**
* Returns (and caches) a constructable style sheet for a web component class
* Note: Chrome
* @param ElementClass
* @returns {*}
*/
const getConstructableStyle = ElementClass => {
const tagName = ElementClass.getMetadata().getTag();
const styleContent = getEffectiveStyle(ElementClass);
const theme = getTheme();

@@ -26,8 +33,4 @@ const key = theme + tagName;

let style;
if (document.adoptedStyleSheets) {
style = createConstructableStyleSheet(styleContent);
} else {
style = createStyleElement(styleContent);
}
const style = new CSSStyleSheet();
style.replaceSync(styleContent);

@@ -38,9 +41,18 @@ styleMap.set(key, style);

const createStyle = ElementClass => {
const tagName = ElementClass.getMetadata().getTag();
/**
* Returns the CSS to be injected inside a web component shadow root, or undefined if not needed
* Note: FF, Safari
* @param ElementClass
* @returns {string}
*/
const getShadowRootStyle = ElementClass => {
if (document.adoptedStyleSheets || window.ShadyDOM) {
return;
}
const styleContent = getEffectiveStyle(ElementClass);
return _createStyle(tagName, styleContent);
return styleContent;
};
// eslint-disable-next-line
export { createStyle };
export { createHeadStyle, getConstructableStyle, getShadowRootStyle};

@@ -15,3 +15,3 @@ import {

class ItemNavigation extends EventProvider {
constructor(rootControl, options = {}) {
constructor(rootWebComponent, options = {}) {
super();

@@ -23,3 +23,3 @@

this.rootControl = rootControl;
this.rootWebComponent = rootWebComponent;
}

@@ -193,7 +193,7 @@

if (!this.rootControl.getDomRef()) {
if (!this.rootWebComponent.getDomRef()) {
return;
}
return this.rootControl.getDomRef().querySelector(`#${currentItem.id}`);
return this.rootWebComponent.getDomRef().querySelector(`#${currentItem.id}`);
}

@@ -200,0 +200,0 @@

@@ -36,3 +36,3 @@ import UI5Element from "../UI5Element.js";

* @public
* @param {*} ref Reference to a UI5 Control or DOM Element to be observed
* @param {*} ref Reference to a UI5 Web Component or DOM Element to be observed
* @param {*} callback Callback to be executed

@@ -53,3 +53,3 @@ * @memberof ResizeHandler

* @public
* @param {*} ref Reference to UI5 Control or DOM Element to be unobserved
* @param {*} ref Reference to UI5 Web Component or DOM Element to be unobserved
* @memberof ResizeHandler

@@ -56,0 +56,0 @@ */

@@ -1,2 +0,2 @@

import ControlEvents from "./events/ControlEvents.js";
import ManagedEvents from "./events/ManagedEvents.js";
import getOriginalEventTarget from "./events/getOriginalEventTarget.js";

@@ -61,7 +61,7 @@ import UI5Element from "./UI5Element.js";

static start() {
ControlEvents.bindAnyEvent(handleEvent);
ManagedEvents.bindAllEvents(handleEvent);
}
static stop() {
ControlEvents.unbindAnyEvent(handleEvent);
ManagedEvents.unbindAllEvents(handleEvent);
}

@@ -68,0 +68,0 @@ }

@@ -31,3 +31,3 @@ import KeyCodes from "@ui5/webcomponents-core/dist/sap/ui/events/KeyCodes.js";

if (event.key) {
return (event.key === "F4" && !hasModifierKeys(event)) || ((event.key === "ArrowDown" || event.key === "Down") && checkModifierKeys(event, /* Ctrl */ false, /* Alt */ true, /* Shift */ false));
return (event.key === "F4" && !hasModifierKeys(event)) || (((event.key === "ArrowDown" || event.key === "Down") || (event.key === "ArrowUp" || event.key === "Up")) && checkModifierKeys(event, /* Ctrl */ false, /* Alt */ true, /* Shift */ false));
}

@@ -34,0 +34,0 @@

@@ -1,6 +0,16 @@

import { render } from "lit-html";
import { html, render } from "lit-html";
class LitRenderer {
static render(renderResult, domNode) {
render(renderResult, domNode);
/**
* Renders "templateResult" by replacing the content of "domNode", and optionally prepends a style tag containing "styles"
* @param templateResult - lit template result object
* @param domNode - the node whose content will be replaced
* @param eventContext - the context of events, bound via the template
* @param styles - if given, will be prepended in a style tag
*/
static render(templateResult, domNode, eventContext, styles) {
if (styles) {
templateResult = html`<style data-ui5-shadow-root-styles>${styles}</style>${templateResult}`;
}
render(templateResult, domNode, { eventContext });
}

@@ -11,3 +21,5 @@ }

export { repeat } from "lit-html/directives/repeat";
export { classMap } from "lit-html/directives/class-map";
export { styleMap } from "lit-html/directives/style-map";
export default LitRenderer;
class RenderQueue {
constructor() {
this.list = []; // Used to store the controls in order
this.promises = new Map(); // Used to store promises for control rendering
this.list = []; // Used to store the web components in order
this.promises = new Map(); // Used to store promises for web component rendering
}
add(control) {
if (this.promises.has(control)) {
return this.promises.get(control);
add(webComponent) {
if (this.promises.has(webComponent)) {
return this.promises.get(webComponent);
}

@@ -18,4 +18,4 @@

this.list.push(control);
this.promises.set(control, promise);
this.list.push(webComponent);
this.promises.set(webComponent, promise);

@@ -26,7 +26,7 @@ return promise;

shift() {
const control = this.list.shift();
if (control) {
const promise = this.promises.get(control);
this.promises.delete(control);
return { control, promise };
const webComponent = this.list.shift();
if (webComponent) {
const promise = this.promises.get(webComponent);
this.promises.delete(webComponent);
return { webComponent, promise };
}

@@ -39,4 +39,4 @@ }

isAdded(control) {
return this.promises.has(control);
isAdded(webComponent) {
return this.promises.has(webComponent);
}

@@ -43,0 +43,0 @@ }

@@ -8,4 +8,4 @@ import RenderQueue from "./RenderQueue.js";

// Queue for invalidated controls
const invalidatedControls = new RenderQueue();
// Queue for invalidated web components
const invalidatedWebComponents = new RenderQueue();

@@ -17,3 +17,3 @@ let renderTaskPromise,

/**
* Class that manages the rendering/re-rendering of controls
* Class that manages the rendering/re-rendering of web components
* This is always asynchronous

@@ -27,8 +27,8 @@ */

/**
* Queues a control for re-rendering
* @param control
* Queues a web component for re-rendering
* @param webComponent
*/
static renderDeferred(control) {
// Enqueue the control
const res = invalidatedControls.add(control);
static renderDeferred(webComponent) {
// Enqueue the web component
const res = invalidatedWebComponents.add(webComponent);

@@ -40,5 +40,5 @@ // Schedule a rendering task

static renderImmediately(control) {
// Enqueue the control
const res = invalidatedControls.add(control);
static renderImmediately(webComponent) {
// Enqueue the web component
const res = invalidatedWebComponents.add(webComponent);

@@ -55,5 +55,5 @@ // Immediately start a render task

if (!renderTaskId) {
// renderTaskId = window.setTimeout(RenderScheduler.renderControls, 3000); // Task
// renderTaskId = Promise.resolve().then(RenderScheduler.renderControls); // Micro task
renderTaskId = window.requestAnimationFrame(RenderScheduler.renderControls); // AF
// renderTaskId = window.setTimeout(RenderScheduler.renderWebComponents, 3000); // Task
// renderTaskId = Promise.resolve().then(RenderScheduler.renderWebComponents); // Micro task
renderTaskId = window.requestAnimationFrame(RenderScheduler.renderWebComponents); // AF
}

@@ -64,26 +64,26 @@ }

if (!renderTaskId) {
renderTaskId = 1; // prevent another rendering task from being scheduled, all controls should use this task
RenderScheduler.renderControls();
renderTaskId = 1; // prevent another rendering task from being scheduled, all web components should use this task
RenderScheduler.renderWebComponents();
}
}
static renderControls() {
static renderWebComponents() {
// console.log("------------- NEW RENDER TASK ---------------");
let controlInfo,
control,
let webComponentInfo,
webComponent,
promise;
const renderStats = new Map();
while (controlInfo = invalidatedControls.shift()) { // eslint-disable-line
control = controlInfo.control;
promise = controlInfo.promise;
while (webComponentInfo = invalidatedWebComponents.shift()) { // eslint-disable-line
webComponent = webComponentInfo.webComponent;
promise = webComponentInfo.promise;
const timesRerendered = renderStats.get(control) || 0;
const timesRerendered = renderStats.get(webComponent) || 0;
if (timesRerendered > MAX_RERENDER_COUNT) {
// console.warn("WARNING RERENDER", control);
throw new Error(`Control re-rendered too many times this task, max allowed is: ${MAX_RERENDER_COUNT}`);
// console.warn("WARNING RERENDER", webComponent);
throw new Error(`Web component re-rendered too many times this task, max allowed is: ${MAX_RERENDER_COUNT}`);
}
control._render();
webComponent._render();
promise._deferredResolve();
renderStats.set(control, timesRerendered + 1);
renderStats.set(webComponent, timesRerendered + 1);
}

@@ -93,3 +93,3 @@

setTimeout(() => {
if (invalidatedControls.getList().length === 0) {
if (invalidatedWebComponents.getList().length === 0) {
RenderScheduler._resolveTaskPromise();

@@ -103,3 +103,3 @@ }

/**
* return a promise that will be resolved once all invalidated controls are rendered
* return a promise that will be resolved once all invalidated web components are rendered
*/

@@ -114,3 +114,3 @@ static whenDOMUpdated() {

window.requestAnimationFrame(() => {
if (invalidatedControls.getList().length === 0) {
if (invalidatedWebComponents.getList().length === 0) {
renderTaskPromise = undefined;

@@ -159,3 +159,3 @@ resolve();

static _resolveTaskPromise() {
if (invalidatedControls.getList().length > 0) {
if (invalidatedWebComponents.getList().length > 0) {
// More updates are pending. Resolve will be called again

@@ -162,0 +162,0 @@ return;

import "./shims/jquery-shim.js";
import ResourceBundle from "@ui5/webcomponents-core/dist/sap/base/i18n/ResourceBundle.js";
import formatMessage from "@ui5/webcomponents-core/dist/sap/base/strings/formatMessage.js";
import { getLanguage } from "./LocaleProvider.js";

@@ -8,29 +9,4 @@ import { registerModuleContent } from "./ResourceLoaderOverrides.js";

const bundleURLs = new Map();
const singletonPromises = new Map();
/**
* Creates a new promise for the specified key (or returns a new one and stores it for next calls).
* The same promise is always returned for multiple calls to this method for the same key.
* This promise can also be resolved so that all usages that await its resolution can continue.
* @param {key} key the unique key identifying the promise
* @private
*/
const _getSingletonPromise = key => {
const prevPromise = singletonPromises.get(key);
if (prevPromise) {
return prevPromise;
}
let resolveFn;
const newPromise = new Promise(resolve => {
resolveFn = resolve;
});
// private usage for making a deferred-like API to avoid storing resolve functions in a second map
newPromise._deferredResolve = resolveFn;
singletonPromises.set(key, newPromise);
return newPromise;
};
/**
* This method preforms the asyncronous task of fething the actual text resources. It will fetch

@@ -45,6 +21,10 @@ * each text resource over the network once (even for multiple calls to the same method).

const fetchResourceBundle = async packageId => {
// depending on the module resolution order, the fetch might run before the bundle URLs are registered - sync them here
await _getSingletonPromise(packageId);
const bundlesForPackage = bundleURLs.get(packageId);
if (!bundlesForPackage) {
console.warn(`Message bundle assets are not configured. Falling back to english texts.`, /* eslint-disable-line */
` You need to import @ui5/webcomponents/dist/MessageBundleAssets.js with a build tool that supports JSON imports.`); /* eslint-disable-line */
return;
}
const language = getLanguage();

@@ -77,11 +57,32 @@

bundleURLs.set(packageId, bundlesMap);
_getSingletonPromise(packageId)._deferredResolve();
};
const getResourceBundle = library => {
return ResourceBundle.create({
url: `${library}.properties`,
});
class ResourceBundleFallback {
getText(textObj, ...params) {
return formatMessage(textObj.defaultText, params);
}
}
class ResourceBundleWrapper {
constructor(resouceBundle) {
this._resourceBundle = resouceBundle;
}
getText(textObj, ...params) {
return this._resourceBundle.getText(textObj.key, ...params);
}
}
const getResourceBundle = packageId => {
const bundleLoaded = bundleURLs.has(packageId);
if (bundleLoaded) {
return new ResourceBundleWrapper(ResourceBundle.create({
url: `${packageId}.properties`,
}));
}
return new ResourceBundleFallback();
};
export { fetchResourceBundle, registerMessageBundles, getResourceBundle };
import { getWCNoConflict, getCompactSize } from "./Configuration.js";
import DOMObserver from "./compatibility/DOMObserver.js";
import ShadowDOM from "./compatibility/ShadowDOM.js";
import UI5ElementMetadata from "./UI5ElementMetadata.js";
import Integer from "./types/Integer.js";
import ControlRenderer from "./ControlRenderer.js";
import Renderer from "./Renderer.js";
import RenderScheduler from "./RenderScheduler.js";
import TemplateContext from "./TemplateContext.js";
import State from "./State.js";
import { createStyle } from "./CSS.js";
import { getConstructableStyle, createHeadStyle } from "./CSS.js";
import { attachThemeChange } from "./Theming.js";
const metadata = {
properties: {
/**
* CSS classes that will be applied to the top-level element of the control
*/
_customClasses: {
type: String,
multiple: true,
},
/**
* Attributes (most commonly accessibility-related) that will be passed to the control.
* The control has the responsibility to render these attributes
*/
_customAttributes: {
type: Object,
},
},
events: {

@@ -67,3 +47,3 @@ _propertyChange: {},

}
const newStyle = createStyle(this.constructor);
const newStyle = getConstructableStyle(this.constructor);
if (document.adoptedStyleSheets) {

@@ -82,8 +62,2 @@ this.shadowRoot.adoptedStyleSheets = [newStyle];

async _initializeShadowRoot() {
const isCompact = getCompactSize();
if (isCompact) {
this.setAttribute("data-ui5-compact-size", "");
}
if (this.constructor.getMetadata().getNoShadowDOM()) {

@@ -94,7 +68,11 @@ return Promise.resolve();

this.attachShadow({ mode: "open" });
const shadowDOM = await ShadowDOM.prepareShadowDOM(this.constructor);
this.shadowRoot.appendChild(shadowDOM);
// IE11, Edge
if (window.ShadyDOM) {
createHeadStyle(this.constructor);
}
// Chrome
if (document.adoptedStyleSheets) {
const style = createStyle(this.constructor);
const style = getConstructableStyle(this.constructor);
this.shadowRoot.adoptedStyleSheets = [style];

@@ -105,2 +83,7 @@ }

async connectedCallback() {
const isCompact = getCompactSize();
if (isCompact) {
this.setAttribute("data-ui5-compact-size", "");
}
if (this.constructor.getMetadata().getNoShadowDOM()) {

@@ -172,8 +155,4 @@ return;

// Init the _state object based on the supported slots
for (const [prop, propData] of Object.entries(slotsMap)) { // eslint-disable-line
if (propData.multiple) {
this._state[prop] = [];
} else {
this._state[prop] = null;
}
for (const [slot, slotData] of Object.entries(slotsMap)) { // eslint-disable-line
this._clearSlot(slot);
}

@@ -201,4 +180,5 @@

// Distribute the child in the _state object
child = this._prepareForSlot(slotName, child);
if (slotsMap[slotName].multiple) {
this._state[slotName] = [...this._state[slotName], child];
this._state[slotName].push(child);
} else {

@@ -208,6 +188,41 @@ this._state[slotName] = child;

});
this._invalidate();
}
// Removes all children from the slot and detaches listeners, if any
_clearSlot(slot) {
const slotData = this.constructor.getMetadata().getSlots()[slot];
let children = this._state[slot];
if (!Array.isArray(children)) {
children = [children];
}
children.forEach(child => {
if (child && child._attachChildPropertyUpdated) {
this._detachChildPropertyUpdated(child);
}
});
if (slotData.multiple) {
this._state[slot] = [];
} else {
this._state[slot] = null;
}
}
_prepareForSlot(slot, child) {
const slotData = this.constructor.getMetadata().getSlots()[slot];
child = this.constructor.getMetadata().constructor.validateSlotValue(child, slotData);
if (child._attachChildPropertyUpdated) {
this._attachChildPropertyUpdated(child, slotData);
}
return child;
}
static get observedAttributes() {
const observedProps = this.getMetadata().getObservedProps();
const observedProps = this.getMetadata().getPublicPropsList();
return observedProps.map(camelToKebabCase);

@@ -263,4 +278,4 @@ }

_upgradeAllProperties() {
const observedProps = this.constructor.getMetadata().getObservedProps();
observedProps.forEach(this._upgradeProperty.bind(this));
const allProps = this.constructor.getMetadata().getPropsList();
allProps.forEach(this._upgradeProperty.bind(this));
}

@@ -271,5 +286,10 @@

if (!DefinitionsSet.has(tag)) {
const definedLocally = DefinitionsSet.has(tag);
const definedGlobally = customElements.get(tag);
if (definedGlobally && !definedLocally) {
console.warn(`Skipping definition of tag ${tag}, because it was already defined by another instance of ui5-webcomponents.`); // eslint-disable-line
} else if (!definedGlobally) {
this.generateAccessors();
DefinitionsSet.add(tag);
this.generateAccessors();
window.customElements.define(tag, this);

@@ -289,17 +309,7 @@ }

_initializeState() {
const StateClass = this.constructor.StateClass;
this._state = new StateClass(this);
const defaultState = this.constructor._getDefaultState();
this._state = Object.assign({}, defaultState);
this._delegates = [];
}
static get StateClass() {
if (!this.hasOwnProperty("_StateClass")) { // eslint-disable-line
this._StateClass = class extends State {};
this._StateClass.generateAccessors(this.getMetadata());
}
return this._StateClass;
}
static getMetadata() {

@@ -342,8 +352,2 @@ let klass = this; // eslint-disable-line

static calculateTemplateContext(state) {
return {
ctr: state,
};
}
_attachChildPropertyUpdated(child, propData) {

@@ -401,3 +405,3 @@ const listenFor = propData.listenFor,

/**
* Asynchronously re-renders an already rendered control
* Asynchronously re-renders an already rendered web component
* @private

@@ -428,3 +432,3 @@ */

delete this._invalidated;
ControlRenderer.render(this);
Renderer.render(this);

@@ -481,6 +485,2 @@ // Safari requires that children get the slot attribute only after the slot tags have been rendered in the shadow DOM

_getTemplateContext() {
return TemplateContext.calculate(this);
}
getDomRef() {

@@ -491,3 +491,4 @@ if (!this.shadowRoot || this.shadowRoot.children.length === 0) {

return this._getRoot().children[0];
return this.shadowRoot.children.length === 1
? this.shadowRoot.children[0] : this.shadowRoot.children[1];
}

@@ -499,6 +500,2 @@

_getRoot() {
return this.shadowRoot.querySelector("[data-sap-ui-wc-root]");
}
getFocusDomRef() {

@@ -523,3 +520,3 @@ const domRef = this.getDomRef();

/**
* Calls the event handler on the control for a native event
* Calls the event handler on the web component for a native event
*

@@ -599,3 +596,3 @@ * @param event The event object

}
return acc.concat(curr.assignedElements({ flatten: true }));
return acc.concat(curr.assignedNodes({ flatten: true }).filter(item => item instanceof HTMLElement));
};

@@ -608,3 +605,2 @@

* Used to generate the next auto-increment id for the current class
* Note: do not call Control._nextID (static) but rather this.constructor._nextID (polymorphic)
* @returns {string}

@@ -646,2 +642,47 @@ * @private

static _getDefaultState() {
if (this._defaultState) {
return this._defaultState;
}
const MetadataClass = this.getMetadata();
const defaultState = {};
// Initialize properties
const props = MetadataClass.getProperties();
for (const propName in props) { // eslint-disable-line
const propType = props[propName].type;
const propDefaultValue = props[propName].defaultValue;
if (propType === Boolean) {
defaultState[propName] = false;
if (propDefaultValue !== undefined) {
console.warn("The 'defaultValue' metadata key is ignored for all booleans properties, they would be initialized with 'false' by default"); // eslint-disable-line
}
} else if (props[propName].multiple) {
defaultState[propName] = [];
} else if (propType === Object) {
defaultState[propName] = "defaultValue" in props[propName] ? props[propName].defaultValue : {};
} else if (propType === String) {
defaultState[propName] = propDefaultValue || "";
} else {
defaultState[propName] = propDefaultValue;
}
}
// Initialize slots
const slots = MetadataClass.getSlots();
for (const slotName in slots) { // eslint-disable-line
if (slots[slotName].multiple) {
defaultState[slotName] = [];
} else {
defaultState[slotName] = null;
}
}
this._defaultState = defaultState;
return defaultState;
}
static generateAccessors() {

@@ -663,6 +704,38 @@ const proto = this.prototype;

get() {
return this._state[prop];
if (this._state[prop] !== undefined) {
return this._state[prop];
}
const propDefaultValue = propData.defaultValue;
if (propData.type === Boolean) {
return false;
} else if (propData.type === String) { // eslint-disable-line
return propDefaultValue || "";
} else if (propData.multiple) { // eslint-disable-line
return [];
} else {
return propDefaultValue;
}
},
set(value) {
this._state[prop] = value;
let isDifferent = false;
value = this.constructor.getMetadata().constructor.validatePropertyValue(value, propData);
const oldState = this._state[prop];
if (propData.deepEqual) {
isDifferent = JSON.stringify(oldState) !== JSON.stringify(value);
} else {
isDifferent = oldState !== value;
}
if (isDifferent) {
this._state[prop] = value;
if (propData.nonVisual) {
return;
}
this._invalidate(prop, value);
this._propertyChange(prop, value);
}
},

@@ -674,3 +747,3 @@ });

const slots = this.getMetadata().getSlots();
for (const [slot] of Object.entries(slots)) { // eslint-disable-line
for (const [slot, slotData] of Object.entries(slots)) { // eslint-disable-line
if (nameCollidesWithNative(slot)) {

@@ -682,3 +755,9 @@ throw new Error(`"${slot}" is not a valid property name. Use a name that does not collide with DOM APIs`);

get() {
return this._state[slot];
if (this._state[slot] !== undefined) {
return this._state[slot];
}
if (slotData.multiple) {
return [];
}
return null;
},

@@ -685,0 +764,0 @@ set() {

import DataType from "./types/DataType.js";
import Function from "./types/Function.js";

@@ -21,9 +20,10 @@ class UI5ElementMetadata {

getObservedProps() {
const properties = this.getProperties();
const allProps = Object.keys(properties);
const observedProps = allProps.filter(UI5ElementMetadata.isPublicProperty);
return observedProps;
getPropsList() {
return Object.keys(this.getProperties());
}
getPublicPropsList() {
return this.getPropsList().filter(UI5ElementMetadata.isPublicProperty);
}
getSlots() {

@@ -58,6 +58,2 @@ return this.metadata.slots || {};

static validateSlotValue(value, slotData) {
const isMultiple = slotData.multiple;
if (isMultiple) {
return value.map(propValue => validateSingleSlot(propValue, slotData));
}
return validateSingleSlot(value, slotData);

@@ -84,5 +80,2 @@ }

}
if (propertyType === Function) {
return typeof value === "function" ? value : undefined;
}
if (isDescendantOf(propertyType, DataType)) {

@@ -93,3 +86,3 @@ return propertyType.isValid(value) ? value : propData.defaultValue;

const validateSingleSlot = (value, propData) => {
const validateSingleSlot = (value, slotData) => {
if (value === null) {

@@ -104,3 +97,3 @@ return value;

if (isSlot) {
return el.assignedElements({ flatten: true });
return el.assignedNodes({ flatten: true }).filter(item => item instanceof HTMLElement);
}

@@ -110,3 +103,3 @@

};
const propertyType = propData.type;
const propertyType = slotData.type;

@@ -116,3 +109,12 @@ const slottedNodes = getSlottedNodes(value);

if (!(el instanceof propertyType)) {
throw new Error(`${el} is not of type ${propertyType}`);
const isHTMLElement = el instanceof HTMLElement;
const tagName = isHTMLElement && el.tagName.toLowerCase();
const isCustomElement = isHTMLElement && tagName.includes("-");
if (isCustomElement) {
window.customElements.whenDefined(tagName).then(() => {
if (!(el instanceof propertyType)) {
throw new Error(`${el} is not of type ${propertyType}`);
}
});
}
}

@@ -119,0 +121,0 @@ });

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc