UNPKG

jmn-basic-elements

Version:

A collection of HMI elements representing P&ID entities made with JS-HMI.

277 lines (271 loc) 9.09 kB
import { hmiElement } from 'jahmin'; import { css, html, VarStatusCodesLit as vsc, VarStatusCodes as vs, shadow_normalize } from 'jahmin'; import './miscellaneus.js'; export class numericIndicator extends hmiElement { constructor() { super(); this.precision = 2; this.unit = ""; } static get properties() { let p = super.properties; p['precision'] = { type: Number }; p['unit'] = { type: String }; return p; } static get styles() { return [shadow_normalize, css ` :host{ display:flex; flex-direction: column; justify-content : center; align-items : center; font-family: 'Roboto', sans-serif; color:var(--base-color,#333333); } div.display{ max-width:10rem; min-width:5rem; display :flex; flex-direction : row; align-items : center; justify-content : space-evenly; } .val { margin-right : 0.5rem; color: #555555 } x-loader{ margin-right : 0.5rem; width:0.9rem; } x-loader:not([show]){ display : none; } .val:not([show]){ display : none; } :host([no-label])>label{ display : none; } `]; } render() { return html ` <label><strong><slot>${this.name}</slot></strong> </label> <div class="display"> <x-loader ?show="${this.status === "PENDING"}"></x-loader> <strong class="val" ?show="${this.status !== "PENDING"}" > ${Number.parseFloat(this.value).toFixed(this.precision)} </strong> <span>${this.unit}</span> </div> `; } } customElements.define("numeric-ind", numericIndicator); export class setNumber extends hmiElement { constructor() { super(); this.precision = 2; this.unit = ""; this.onmousedown = this.show.bind(this); this.onkeydown = this.send.bind(this); this.inpt_val = ""; this.onblur = this.hide.bind(this); this.size = ""; } static get properties() { let p = super.properties; p['precision'] = { type: Number }; p['unit'] = { type: String }; p['showinpt'] = { type: Boolean }; p['size'] = { type: String }; return p; } static get styles() { return [shadow_normalize, css ` :host{ display:flex; flex-direction: column; justify-content : center; align-items : center; font-family: 'Roboto', sans-serif; color:var(--base-color,#333333); cursor: pointer; width: 100%; max-width : 8rem; padding-top: 0.3rem; padding-bottom: 0.2rem; } :host([status="${vsc.Error}"]) { cursor: not-allowed; } :host([status="${vsc.Error}"]) { cursor: not-allowed; } :host([err]){ background-color:red; } .set{ font-size : smaller; align-self : flex-start; display:flex; justify-content : flex-start; align-items : center; color : blue; width:100%; margin-bottom: 0.2rem; } .set[size="medium"]{ font-size : medium; } .set[size="large"]{ font-size : large; } :host([status="${vsc.Error}"]) > .set{ color : #8B0000; } :host([status="${vsc.Unsubscribed}"]) > .set{ color : #999900; } .inpt{ display:flex; justify-content:center; align-items: center; max-width:0rem; max-height: 0rem; transition: max-height 0.2s ease-out, max-width 0.2s ease-out; transition-delay: 0s; overflow:hidden; } .inpt[show]{ max-width: 10rem; max-height : 5rem; } input{ width: 3rem; margin:0px; margin-right : 0.1rem; color: hsl(0, 0%, 41%) ; background-color:hsl(0, 0%, 100%); border-radius:.4rem; padding:0.5rem; font-family: inherit; /* 1 */ font-size: 0.8rem; /* 1 */ font-weight: 500; line-height: 1; /* 1 */ border: 1px solid hsl(0, 0%, 86%); } input.medium{ width:7rem; font-size: medium; } input.large{ width:7rem; font-size: medium; } input:focus{ border-color : #00d1b2; } input:invalid{ border-color:red; } x-triangle{ margin-left: 0.5rem; width:0.5rem; } x-triangle[rotate]{ transform: rotate(90deg); } button { margin : 0; box-sizing : border-box; text-align: center; text-decoration: none; font-size: .8rem; font-weight: 700; letter-spacing: .1rem; padding: 0.2rem; background-color: hsl(0, 0%, 100%); border: 1px solid hsl(0, 0%, 86%); border-radius: .4rem; color: hsl(0, 0%, 41%) ; cursor: pointer; -moz-appearance: none; -webkit-appearance: none; } button:hover{ border-color : #00d1b2; } x-loader{ margin-left : 0.2rem; width:0.8rem; } x-loader:not([show]){ display : none; } span[show]{ display:none; } `]; } render() { return html ` <label><strong><slot></slot></strong></label> <div class="set" id="setcont" size="${this.size}"><span style="margin-right:0.4rem"><slot name="set-txt">set:</slot></span> <span ?show="${this.status === "PENDING"}">${Number.parseFloat(this.value).toFixed(this.precision)}</span> <x-loader ?show="${this.status === "PENDING"}"></x-loader> <x-triangle ?rotate="${this.showinpt}"></x-triangle> </div> <div id="form" class="inpt" ?show="${this.showinpt}"> <input class="${this.size}" id="inpt" type="number" ?disabled="${(this.status === "ERROR" || this.status === "UNSUBSCRIBED")}" value="" step="${Math.pow(10, -1 * this.precision)}"> <button id="btn" type="submit" ?disabled="${(this.status === "ERROR" || this.status === "UNSUBSCRIBED")}" @click="${this.send}">Set</button> </div> `; } hide(e) { //e.preventDefault(); if (this.showinpt === false) return; this.showinpt = false; this.removeAttribute("err"); let inpt = this.shadowRoot.getElementById('inpt'); let btn = this.shadowRoot.getElementById('btn'); inpt.blur(); btn.blur(); this.blur(); } show(e) { if (this.status === "ERROR" || this.status === "UNSUBSCRIBED") { this.showinpt = true; setTimeout(this.hide.bind(this), 1000); } //e.preventDefault(); //if(this.showinpt === true) this.hide if (this.showinpt === true) return; this.showinpt = true; let el = this.shadowRoot.getElementById('inpt'); setTimeout(() => { el.focus(); }, 0); //el.focus(); } async send(e) { if (this.status === vs.Error || this.status === vs.Unsubscribed) return; if (e instanceof KeyboardEvent && e.keyCode !== 13) return; let num = this.shadowRoot.getElementById('inpt').valueAsNumber; if (Number.isNaN(num)) { return; } let resp = await this.Write(num); if (resp[0].success) { this.hide(null); } else { this.setAttribute("err", "true"); } } } customElements.define("set-number", setNumber);