@furo/ui5
Version:
SAP UI5 Web Components data bindings for furo-web
247 lines (223 loc) • 7.66 kB
JavaScript
import { LitElement, html, css } from 'lit';
import { FBP } from '@furo/fbp/src/fbp.js';
/**
* The furo-ui5-form-field-container gives the user a layout to manage
* input field and labels according to the design specification of SAP Fiori.
*
* Example
*
* ```html
* <furo-ui5-form-field-container>
* <ui5-label label slot="label" for="Custom" show-colon>Currency / Units (custom)</ui5-label>
* <furo-horizontal-flex id="Custom" content space>
* <furo-ui5-text-input flex fn-bind-data="--entity(*.data.furo_data_money_input.currency_code)"></furo-ui5-text-input>
* <furo-ui5-number-input flex fn-bind-data="--entity(*.data.furo_data_money_input.units)"></furo-ui5-number-input>
* </furo-horizontal-flex>
* </furo-ui5-form-field-container>
* ```
*
* The form and simple form in size L use a two-column layout within the responsive grid layout by default.
* That means that the form groups are placed next to each other to have all the information on one screen and to
* avoid scrolling. In these columns, the labels are positioned in the same row as the corresponding input field or value.
* So the form groups adopt the Z layout (reading direction in rows, not in columns).
*
* The label-field ratio is 4:8:0 by default:
*
* 4 grid columns of the responsive grid layout are used by the labels.
* 8 grid columns of the responsive grid layout are used by fields.
* 0 grid columns of the responsive grid layout are used by empty columns.
*
*
* Size M of the form and simple form also has a single-column layout within the responsive grid layout by default.
* However, in size M the labels are positioned in the same row as the corresponding input field or value, and form
* groups are positioned below each other.
*
* The label-field ratio is 3:9:0 by default:
*
* 2 grid columns of the responsive grid layout are used by the labels.
* 10 grid columns of the responsive grid layout are used by the fields.
* 0 columns of the responsive grid layout are used by empty columns.
*
*
* Size S (Smartphones and Dialogs)
* The form and simple form use a single-column layout within the responsive grid layout in size S by default.
* This means that the form groups are positioned below each other in a single column and the labels are positioned
* `above` the fields to avoid truncation of the labels.
*
* The label-field ratio is 12:12:0 by default:
*
* 12 grid columns of the responsive grid layout are used by the labels.
* (A label handles the space of a whole row.)
* 12 grid columns of the responsive grid layout are used by the fields.
* (A field handles the space of a whole row.)
* 0 grid columns of the responsive grid layout are used by empty columns.
* (There is no empty space on the right of the field.)
*
* @cssprop {N/A} [--furo-ui5-form-field-container-grid-row-gap=0] - grid row gap
* @cssprop {N/A} [--furo-ui5-form-field-container-grid-column-gap=1em] - grid column gap
* @cssprop {N/A} [--furo-ui5-form-field-container-label-justify-gap=end] - label alignment (start, end)
*
* @slot {HTMLElement} label - defines the label to be displayed.
* @slot {HTMLElement} - defines the form field to be displayed in the container element.
*
* @summary responsive labels for your input elements
* @element furo-ui5-form-field-container
* @appliesMixin FBP
*/
export class FuroUi5FormFieldContainer extends FBP(LitElement) {
/**
* flow is ready lifecycle method
* @private
*/
_FBPReady() {
super._FBPReady();
// this._FBPTraceWires();
this.updateComplete.then(() => {
if (window.ResizeObserver) {
const ro = new ResizeObserver(entries => {
window.requestAnimationFrame(() => {
for (const entry of entries) {
this._checkSize(entry.contentRect.width);
}
});
});
ro.observe(this);
} else {
// fallback, just listen to the resize event
setTimeout(() => {
const cr = this.getBoundingClientRect();
this._checkSize(cr.width);
}, 1);
window.addEventListener('resize', () => {
const cr = this.getBoundingClientRect();
this._checkSize(cr.width);
});
}
});
}
/**
* Form breakpoints according to SAP Fiori Design System
* https://experience.sap.com/fiori-design-web/form/
* @param size
* @private
*/
_checkSize(size) {
// do nothing on invisible
if (size === 0) {
return;
}
if (size <= 600 || this.getAttribute('full') != null) {
this._setSizeAttribute('size-s');
} else if (size > 600 && size <= 1023) {
this._setSizeAttribute('size-m');
} else if (size > 1023 && size <= 1439) {
this._setSizeAttribute('size-l');
} else if (size > 1439) {
this._setSizeAttribute('size-xl');
} else {
this._setSizeAttribute('size-m');
}
}
/**
* Sets data-size attribute
* @param attrValue
* @private
*/
_setSizeAttribute(attrValue) {
// eslint-disable-next-line no-plusplus
for (let i = 0; i < this.children.length; i++) {
this.children[i].setAttribute('data-size', attrValue);
}
}
static get properties() {
return {};
}
static get styles() {
// language=CSS
return css`
:host {
display: block;
}
:host([hidden]) {
display: none;
}
.container {
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-row-gap: var(--furo-ui5-form-field-container-grid-row-gap, 0);
grid-column-gap: var(
--furo-ui5-form-field-container-grid-column-gap,
1em
);
}
::slotted(*[content]) {
grid-column: span 8;
width: 100%;
}
::slotted(*[label]) {
grid-column: span 4;
place-self: start
var(--furo-ui5-form-field-container-label-justify, end);
padding-top: 0.5rem;
}
:host([disabled]) ::slotted(*[content]) {
opacity: var(--_ui5_input_disabled_opacity);
}
/* ui5 components have a min width, this does not work with well with a furo-form-layouter six */
::slotted(*[content][data-size*='size-s']) {
grid-column: span 12;
width: 100%;
min-width: 80px;
}
::slotted(*[label][data-size*='size-s']) {
padding-top: 0;
grid-column: span 12;
justify-self: start;
}
::slotted(*[content][data-size*='size-m']) {
grid-column: span 9;
width: 100%;
}
::slotted(*[label][data-size*='size-m']) {
grid-column: span 3;
place-self: start
var(--furo-ui5-form-field-container-label-justify, end);
}
::slotted(*[content][data-size*='size-l']) {
grid-column: span 8;
width: 100%;
}
::slotted(*[label][data-size*='size-l']) {
grid-column: span 4;
place-self: start
var(--furo-ui5-form-field-container-label-justify, end);
}
::slotted(*[content][data-size*='size-xl']) {
grid-column: span 8;
width: 100%;
}
::slotted(*[label][data-size*='size-xl']) {
grid-column: span 4;
place-self: start
var(--furo-ui5-form-field-container-label-justify, end);
}
`;
}
/**
* @private
* @returns {TemplateResult|TemplateResult}
*/
render() {
// language=HTML
return html`
<div class="container">
<slot name="label"></slot>
<slot></slot>
</div>
`;
}
}
window.customElements.define(
'furo-ui5-form-field-container',
FuroUi5FormFieldContainer
);