All checks were successful
Build-und-Deploy / build (push) Successful in 11s
minor change for pipeline test minor change for pipeline test minor change for pipeline test minor change for pipeline test minor change for pipeline test minor change for pipeline test minor change for pipeline test minor change for pipeline test minor change for pipeline test minor change for pipeline test minor change for pipeline test minor change for pipeline test Add Gitea Actions build workflow Add CI/CD pipeline Test Build & Deploy add pipeline add pipeline2 add pipeline3 add pipeline4 add pipeline 5 add pipeline 6 add pipeline 7 add pipeline 8 add pipeline 9 add pipeline 10 add pipeline 11 add pipeline 12 add pipeline 13 add pipeline 14 add pipeline 15 add pipeline 16 add pipeline 17 add pipeline 18 add pipeline 19 add pipeline 20 add pipeline 21 add pipeline 22 add pipeline 23 add pipeline 24 1 2 3
199 lines
5.8 KiB
JavaScript
199 lines
5.8 KiB
JavaScript
import '@polymer/polymer/lib/elements/dom-if.js';
|
|
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
|
|
import { Debouncer } from '@polymer/polymer/lib/utils/debounce.js';
|
|
import { idlePeriod } from '@polymer/polymer/lib/utils/async.js';
|
|
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
|
|
import { flowComponentDirective } from './flow-component-directive.js';
|
|
import { render, html as litHtml } from 'lit';
|
|
|
|
/**
|
|
* Returns the requested node in a form suitable for Lit template interpolation.
|
|
* @param {string} appid
|
|
* @param {number} nodeid
|
|
* @returns {any} a Lit directive
|
|
*/
|
|
function getNode(appid, nodeid) {
|
|
return flowComponentDirective(appid, nodeid);
|
|
}
|
|
|
|
/**
|
|
* Sets the nodes defined by the given node ids as the child nodes of the
|
|
* given root element.
|
|
* @param {string} appid
|
|
* @param {number[]} nodeIds
|
|
* @param {Element} root
|
|
*/
|
|
function setChildNodes(appid, nodeIds, root) {
|
|
render(litHtml`${nodeIds.map((id) => flowComponentDirective(appid, id))}`, root);
|
|
}
|
|
|
|
/**
|
|
* SimpleElementBindingStrategy::addChildren uses insertBefore to add child
|
|
* elements to the container. When the children are manually placed under
|
|
* another element, the call to insertBefore can occasionally fail due to
|
|
* an invalid reference node.
|
|
*
|
|
* This is a temporary workaround which patches the container's native API
|
|
* to not fail when called with invalid arguments.
|
|
*/
|
|
function patchVirtualContainer(container) {
|
|
const originalInsertBefore = container.insertBefore;
|
|
|
|
container.insertBefore = function (newNode, referenceNode) {
|
|
if (referenceNode && referenceNode.parentNode === this) {
|
|
return originalInsertBefore.call(this, newNode, referenceNode);
|
|
} else {
|
|
return originalInsertBefore.call(this, newNode, null);
|
|
}
|
|
};
|
|
}
|
|
|
|
window.Vaadin ||= {};
|
|
window.Vaadin.FlowComponentHost ||= { patchVirtualContainer, getNode, setChildNodes };
|
|
|
|
class FlowComponentRenderer extends PolymerElement {
|
|
static get template() {
|
|
return html`
|
|
<style>
|
|
:host {
|
|
animation: 1ms flow-component-renderer-appear;
|
|
}
|
|
|
|
@keyframes flow-component-renderer-appear {
|
|
to {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
</style>
|
|
<slot></slot>
|
|
`;
|
|
}
|
|
|
|
static get is() {
|
|
return 'flow-component-renderer';
|
|
}
|
|
static get properties() {
|
|
return {
|
|
nodeid: Number,
|
|
appid: String
|
|
};
|
|
}
|
|
static get observers() {
|
|
return ['_attachRenderedComponentIfAble(appid, nodeid)'];
|
|
}
|
|
|
|
ready() {
|
|
super.ready();
|
|
this.addEventListener('click', function (event) {
|
|
if (this.firstChild && typeof this.firstChild.click === 'function' && event.target === this) {
|
|
event.stopPropagation();
|
|
this.firstChild.click();
|
|
}
|
|
});
|
|
this.addEventListener('animationend', this._onAnimationEnd);
|
|
}
|
|
|
|
_asyncAttachRenderedComponentIfAble() {
|
|
this._debouncer = Debouncer.debounce(this._debouncer, idlePeriod, () => this._attachRenderedComponentIfAble());
|
|
}
|
|
|
|
_attachRenderedComponentIfAble() {
|
|
if (this.appid == null) {
|
|
return;
|
|
}
|
|
if (this.nodeid == null) {
|
|
if (this.firstChild) {
|
|
this.removeChild(this.firstChild);
|
|
}
|
|
return;
|
|
}
|
|
const renderedComponent = this._getRenderedComponent();
|
|
if (this.firstChild) {
|
|
if (!renderedComponent) {
|
|
this._asyncAttachRenderedComponentIfAble();
|
|
} else if (this.firstChild !== renderedComponent) {
|
|
this.replaceChild(renderedComponent, this.firstChild);
|
|
this._defineFocusTarget();
|
|
this.onComponentRendered();
|
|
} else {
|
|
this._defineFocusTarget();
|
|
this.onComponentRendered();
|
|
}
|
|
} else {
|
|
if (renderedComponent) {
|
|
this.appendChild(renderedComponent);
|
|
this._defineFocusTarget();
|
|
this.onComponentRendered();
|
|
} else {
|
|
this._asyncAttachRenderedComponentIfAble();
|
|
}
|
|
}
|
|
}
|
|
|
|
_getRenderedComponent() {
|
|
try {
|
|
return window.Vaadin.Flow.clients[this.appid].getByNodeId(this.nodeid);
|
|
} catch (error) {
|
|
console.error('Could not get node %s from app %s', this.nodeid, this.appid);
|
|
console.error(error);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
onComponentRendered() {
|
|
// subclasses can override this method to execute custom logic on resize
|
|
}
|
|
|
|
/* Setting the `focus-target` attribute to the first focusable descendant
|
|
starting from the firstChild necessary for the focus to be delegated
|
|
within the flow-component-renderer when used inside a vaadin-grid cell */
|
|
_defineFocusTarget() {
|
|
var focusable = this._getFirstFocusableDescendant(this.firstChild);
|
|
if (focusable !== null) {
|
|
focusable.setAttribute('focus-target', 'true');
|
|
}
|
|
}
|
|
|
|
_getFirstFocusableDescendant(node) {
|
|
if (this._isFocusable(node)) {
|
|
return node;
|
|
}
|
|
if (node.hasAttribute && (node.hasAttribute('disabled') || node.hasAttribute('hidden'))) {
|
|
return null;
|
|
}
|
|
if (!node.children) {
|
|
return null;
|
|
}
|
|
for (var i = 0; i < node.children.length; i++) {
|
|
var focusable = this._getFirstFocusableDescendant(node.children[i]);
|
|
if (focusable !== null) {
|
|
return focusable;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
_isFocusable(node) {
|
|
if (
|
|
node.hasAttribute &&
|
|
typeof node.hasAttribute === 'function' &&
|
|
(node.hasAttribute('disabled') || node.hasAttribute('hidden'))
|
|
) {
|
|
return false;
|
|
}
|
|
|
|
return node.tabIndex === 0;
|
|
}
|
|
|
|
_onAnimationEnd(e) {
|
|
// ShadyCSS applies scoping suffixes to animation names
|
|
// To ensure that child is attached once element is unhidden
|
|
// for when it was filtered out from, eg, ComboBox
|
|
// https://github.com/vaadin/vaadin-flow-components/issues/437
|
|
if (e.animationName.indexOf('flow-component-renderer-appear') === 0) {
|
|
this._attachRenderedComponentIfAble();
|
|
}
|
|
}
|
|
}
|
|
window.customElements.define(FlowComponentRenderer.is, FlowComponentRenderer);
|