Skip to content

Commit

Permalink
Enhance metadata (#735)
Browse files Browse the repository at this point in the history
  • Loading branch information
vladitasev authored Aug 26, 2019
1 parent 171a36f commit b610aeb
Show file tree
Hide file tree
Showing 23 changed files with 208 additions and 119 deletions.
6 changes: 3 additions & 3 deletions docs/PublicModuleImports.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ For API documentation and samples, please check the [UI5 Web Components Playgrou
| Tab | `ui5-tab` | `import "@ui5/webcomponents/dist/Tab.js";` |
| Tab Separator | `ui5-tab-separator` | `import "@ui5/webcomponents/dist/TabSeparator.js";` |
| Table | `ui5-table` | `import "@ui5/webcomponents/dist/Table.js";` |
| Table Column | `ui5-table-column` | comes with ui5-table |
| Table Row | `ui5-table-row` | comes with ui5-table |
| Table Cell | `ui5-table-cell` | comes with ui5-table |
| Table Column | `ui5-table-column` | `import "@ui5/webcomponents/dist/TableColumn.js";` |
| Table Row | `ui5-table-row` | `import "@ui5/webcomponents/dist/TableRow.js";` |
| Table Cell | `ui5-table-cell` | `import "@ui5/webcomponents/dist/TableCell.js";` |
| Textarea | `ui5-textarea` | `import "@ui5/webcomponents/dist/TextArea.js";` |
| Timeline | `ui5-timeline` | `import "@ui5/webcomponents/dist/Timeline.js";` |
| Timeline Item | `ui5-timeline-item` | comes with ui5-timeline |
Expand Down
136 changes: 136 additions & 0 deletions docs/dev/Metadata.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# Metadata

Metadata is a JavaScript object, containing information about the public interface of a UI5 Web Component (tag name, properties, etc...)

*Disclaimer: The information below is for UI5 Web Components development only. It is experimental and may change*

## Tag

Defines the HTML tag for the Web Component.

#### Example:

```json
{
"tag": "ui5-my-element",
}
```

## Properties / Attributes

Defines the HTML properties for the Web Component.

*Note about attributes:* By default, for each property an equivalent attribute is supported. Attributes have the same names as properties, but in `kebab-case` rather than `camelCase`.
Properties of type `Object`, properties with `multiple` set to`true` and properties with `noAttribute` set to `true` do not have an attribute equivalent.

#### Example

```json
{
"properties": {
"message": {
"type": String,
"defaultValue": "Hello",
},
"shown": {
"type": Boolean,
"noAttribute": true,
},
"settings": {
"type": Object,
"deepEqual": true,
},
"nums": {
"type": Integer,
"multiple": true,
},
"animationDuration": {
"type": Integer,
"nonVisual": true,
},
"width": {
"type": CSSSize,
"defaultValue": "",
},
},
}
```

#### Property configuration settings

Setting | Type | Default | Description
--------|------|--------| -----------
`type` | Property type | N/A | The type of the property. For more information on types see the table below.
`defaultValue` | Any valid value for the type | undefined | Default value of the property. Cannot be set for type "Boolean". Booleans are always false by default in HTML
`multiple` | Boolean | false | Indicates whether the property represents a single value or is an array of values of the given type
`noAttribute` | Boolean | false | No attribute equivalent will be created for that property. Always false for properties of type Object.
`deepEqual` | Boolean | false | Deep equal object comparison, rather than reference comparison, will be used to determine if the value of the property changed.
`nonVisual` | Boolean | false | Changes to this property will not lead to invalidation of the Web Component. Use for properties, not related to rendering.

The `type` setting is required.

#### Types

Type | Class to use | Description
-----|-------|------
string | `String` | String value
boolean | `Boolean` | Boolean value - always false by default
object | `Object` | JS Object
custom type | Extend `@ui5/webcomponents-base/dist/types/DataType.js` | Used mainly for enumerations

#### Examples of prebuilt custom types

Type | Class to use | Description
-----|-------|------
Integer | `@ui5/webcomponents-base/dist/types/Integer.js` | Integer value
CSSSize | `@ui5/webcomponents-base/dist/types/CSSSize.js` | Any valid CSS size definition (`px`, `rem`, etc...)
ValueState | `@ui5/webcomponents-base/dist/types/ValueState.js` | Enumeration with: `None`, `Error`, `Warning`, `Success` values

## Slots

Defines the `slots` that will be provided by this UI5 Web Component.

#### Example

```json
{
"slots": {
"default": {
"type": Node,
},
"footer": {
"type": HTMLElement,
},
"rows": {
"type": HTMLElement,
"individualSlots": true,
}
}
}
```

#### Slot configuration settings

Setting | Type | Default | Description
--------|------|--------|-----------
type | `HTMLElement` or `Node` | N/A | The type of the children that can go into that slot
individualSlots | `Boolean` | false | If set to `true`, each child will have its own slot, allowing you to arrange/wrap the children arbitrarily.
propertyName | `String` | N/A | Allows to set the name of the property on the Web Component, where the children belonging to this slot will be stored.
listenFor | `Object` | N/A | **Experimental, do not use.** If set, whenever the children, belonging to this slot have their properties changed, the Web Component will be invalidated.

The `type` setting is required.

Notes:
- Children without a `slot` attribute will be assigned to the `default` slot.
- All HTML text nodes will be assigned to the `default` slot, as they cannot have a `slot` attribute.
- For all slots the Web Component will have a property created, with the name of the slot, to hold a list of all children assigned to this slot.
For example, if you have a slot named "rows", "this.rows" will be an array, holding references to all children with `slot="rows"`, or no slot, if rows was default.
- For the `default` slot you can provide a `propertyName` setting.
For example, if your default slot has a `propertyName: "items"`, then "this.items" will hold all children that were assigned to the default slot.

#### Allowed slot types

Type | Description
-----|-------------
Node | Accepts both Text nodes and HTML Elements
HTMLElement | Accepts HTML Elements only
2 changes: 1 addition & 1 deletion packages/base/src/DOMEventHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const handleEvent = function handleEvent(event) {


const processDOMNode = function processDOMNode(node, event) {
if (node && node._isUI5Element) {
if (node && node.isUI5Element) {
return dispatchEvent(node, event);
}
return true;
Expand Down
4 changes: 2 additions & 2 deletions packages/base/src/RenderScheduler.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ class RenderScheduler {
}

static getNotDefinedComponents() {
return Array.from(document.querySelectorAll("*")).filter(el => el.localName.startsWith("ui5-") && !el._isUI5Element);
return Array.from(document.querySelectorAll("*")).filter(el => el.localName.startsWith("ui5-") && !el.isUI5Element);
}

/**
Expand All @@ -132,7 +132,7 @@ class RenderScheduler {
const stillUndefined = this.getNotDefinedComponents();
if (stillUndefined.length) {
// eslint-disable-next-line
console.warn("undefined elements after 5 seconds: ", [...stillUndefined].map(el => el.localName));
console.warn("undefined elements after 5 seconds are: " + [...stillUndefined].map(el => el.localName).join(" ; "));
}

return Promise.resolve();
Expand Down
26 changes: 10 additions & 16 deletions packages/base/src/UI5Element.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ class UI5Element extends HTMLElement {

child = this.constructor.getMetadata().constructor.validateSlotValue(child, slotData);

if (child._isUI5Element) {
if (child.isUI5Element) {
this._attachChildPropertyUpdated(child, slotData);
}

Expand All @@ -210,7 +210,7 @@ class UI5Element extends HTMLElement {
}

children.forEach(child => {
if (child && child._isUI5Element) {
if (child && child.isUI5Element) {
this._detachChildPropertyUpdated(child);
}
});
Expand Down Expand Up @@ -322,21 +322,15 @@ class UI5Element extends HTMLElement {
const result = metadatas[0];

// merge properties
result.properties = metadatas.reverse().reduce((result, current) => { // eslint-disable-line
Object.assign(result, current.properties);
return result;
result.properties = metadatas.reverse().reduce((allProperties, current) => { // eslint-disable-line
Object.assign(allProperties, current.properties || {});
return allProperties;
}, {});

// merge slots
result.slots = metadatas.reverse().reduce((result, current) => { // eslint-disable-line
Object.assign(result, current.slots);
return result;
}, {});

// merge events
result.events = metadatas.reverse().reduce((result, current) => { // eslint-disable-line
Object.assign(result, current.events);
return result;
result.slots = metadatas.reverse().reduce((allSlots, current) => { // eslint-disable-line
Object.assign(allSlots, current.slots || {});
return allSlots;
}, {});

this._metadata = new UI5ElementMetadata(result);
Expand Down Expand Up @@ -565,9 +559,9 @@ class UI5Element extends HTMLElement {
/**
* Used to duck-type UI5 elements without using instanceof
* @returns {boolean}
* @private
* @public
*/
get _isUI5Element() {
get isUI5Element() {
return true;
}

Expand Down
9 changes: 2 additions & 7 deletions packages/base/src/UI5ElementMetadata.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,6 @@ class UI5ElementMetadata {
return this.metadata.properties || {};
}

getEvents() {
return this.metadata.events || {};
}

static validatePropertyValue(value, propData) {
const isMultiple = propData.multiple;
if (isMultiple) {
Expand Down Expand Up @@ -84,12 +80,11 @@ const validateSingleSlot = (value, slotData) => {

return [el];
};
const propertyType = slotData.type;

const slottedNodes = getSlottedNodes(value);
slottedNodes.forEach(el => {
if (!(el instanceof propertyType)) {
throw new Error(`${el} is not of type ${propertyType}`);
if (!(el instanceof slotData.type)) {
throw new Error(`${el} is not of type ${slotData.type}`);
}
});

Expand Down
5 changes: 5 additions & 0 deletions packages/main/bundle.esm.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import Popover from "./dist/Popover.js";
import Panel from "./dist/Panel.js";
import RadioButton from "./dist/RadioButton.js";
import Select from "./dist/Select.js";
import Option from "./dist/Option.js";
import ShellBar from "./dist/ShellBar.js";
import ShellBarItem from "./dist/ShellBarItem.js";
import Switch from "./dist/Switch.js";
Expand All @@ -36,8 +37,12 @@ import TabContainer from "./dist/TabContainer.js";
import Tab from "./dist/Tab.js";
import TabSeparator from "./dist/TabSeparator.js";
import Table from "./dist/Table.js";
import TableColumn from "./dist/TableColumn.js";
import TableRow from "./dist/TableRow.js";
import TableCell from "./dist/TableCell.js";
import TextArea from "./dist/TextArea.js";
import Timeline from "./dist/Timeline.js";
import TimelineItem from "./dist/TimelineItem.js";
import Title from "./dist/Title.js";
import ToggleButton from "./dist/ToggleButton.js";

Expand Down
5 changes: 2 additions & 3 deletions packages/main/src/Badge.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
import { fetchResourceBundle, getResourceBundle } from "@ui5/webcomponents-base/dist/ResourceBundle.js";
import { getRTL } from "@ui5/webcomponents-base/dist/config/RTL.js";
import Icon from "./Icon.js";

// Template
import BadgeTemplate from "./generated/templates/BadgeTemplate.lit.js";
Expand Down Expand Up @@ -50,12 +49,12 @@ const metadata = {
/**
* Defines the <code>ui5-icon</code> to be displayed in the <code>ui5-badge</code>.
*
* @type {Icon}
* @type {HTMLElement[]}
* @slot
* @public
*/
icon: {
type: Icon,
type: HTMLElement,
},

},
Expand Down
3 changes: 1 addition & 2 deletions packages/main/src/Input.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
isEnter,
} from "@ui5/webcomponents-base/dist/events/PseudoEvents.js";
import { fetchResourceBundle, getResourceBundle } from "@ui5/webcomponents-base/dist/ResourceBundle.js";
// import Icon from "./Icon.js";
import InputType from "./types/InputType.js";
// Template
import InputTemplate from "./generated/templates/InputTemplate.lit.js";
Expand All @@ -35,7 +34,7 @@ const metadata = {
/**
* Defines the icon to be displayed in the <code>ui5-input</code>.
*
* @type {Icon[]}
* @type {HTMLElement[]}
* @slot
* @public
*/
Expand Down
16 changes: 8 additions & 8 deletions packages/main/src/List.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
import ItemNavigation from "@ui5/webcomponents-base/dist/delegate/ItemNavigation.js";
import FocusHelper from "@ui5/webcomponents-base/dist/FocusHelper.js";
import { isTabNext } from "@ui5/webcomponents-base/dist/events/PseudoEvents.js";
import ListItemBase from "./ListItemBase.js";
import ListMode from "./types/ListMode.js";
import ListSeparators from "./types/ListSeparators.js";
import ListItemType from "./types/ListItemType.js";

// Template
import ListTemplate from "./generated/templates/ListTemplate.lit.js";

Expand Down Expand Up @@ -35,15 +35,15 @@ const metadata = {

/**
* Defines the items of the <code>ui5-list</code>.
* <br><b>Note:</b> Only <code>ui5-li</code>, <code>ui5-li-custom</code> and <code>ui5-li-groupheader</code> are allowed.
* <br><b>Note:</b> Use <code>ui5-li</code>, <code>ui5-li-custom</code> and <code>ui5-li-groupheader</code> for the intended design.
*
* @type {ListItemBase[]}
* @type {HTMLElement[]}
* @slot
* @public
*/
"default": {
propertyName: "items",
type: ListItemBase,
type: HTMLElement,
},
},
properties: /** @lends sap.ui.webcomponents.main.List.prototype */ {
Expand Down Expand Up @@ -201,13 +201,13 @@ const metadata = {
*
* <h3>ES6 Module Import</h3>
*
* <code>import "@ui5/webcomponents/dist/List";</code>
* <code>import "@ui5/webcomponents/dist/List.js";</code>
* <br>
* <code>import "@ui5/webcomponents/dist/StandardListItem";</code> (for <code>ui5-li</code>)
* <code>import "@ui5/webcomponents/dist/StandardListItem.js";</code> (for <code>ui5-li</code>)
* <br>
* <code>import "@ui5/webcomponents/dist/CustomListItem";</code> (for <code>ui5-li-custom</code>)
* <code>import "@ui5/webcomponents/dist/CustomListItem.js";</code> (for <code>ui5-li-custom</code>)
* <br>
* <code>import "@ui5/webcomponents/dist/GroupHeaderListItem";</code> (for <code>ui5-li-group-header</code>)
* <code>import "@ui5/webcomponents/dist/GroupHeaderListItem.js";</code> (for <code>ui5-li-group-header</code>)
*
* @constructor
* @author SAP SE
Expand Down
1 change: 0 additions & 1 deletion packages/main/src/ListItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import styles from "./generated/themes/ListItem.css.js";
* @public
*/
const metadata = {
"abstract": true,
properties: /** @lends sap.ui.webcomponents.main.ListItem.prototype */ {

/**
Expand Down
1 change: 0 additions & 1 deletion packages/main/src/ListItemBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import styles from "./generated/themes/ListItemBase.css.js";
* @public
*/
const metadata = {
"abstract": true,
properties: /** @lends sap.ui.webcomponents.main.ListItemBase.prototype */ {

/**
Expand Down
1 change: 0 additions & 1 deletion packages/main/src/Popup.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import styles from "./generated/themes/Popup.css.js";
* @public
*/
const metadata = {
"abstract": true,
slots: /** @lends sap.ui.webcomponents.main.Popup.prototype */ {

/**
Expand Down
Loading

0 comments on commit b610aeb

Please sign in to comment.