diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..c2fe7b1
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,227 @@
+{
+ "name": "@tp/tp-element",
+ "version": "0.0.1",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "@tp/tp-element",
+ "version": "0.0.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@tp/helpers": "^2.3.1",
+ "@tp/tp-input": "^1.0.6",
+ "lit": "^3.0.0"
+ }
+ },
+ "node_modules/@lit-labs/ssr-dom-shim": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.0.tgz",
+ "integrity": "sha512-yWJKmpGE6lUURKAaIltoPIE/wrbY3TEkqQt+X0m+7fQNnAv0keydnYvbiJFP1PnMhizmIWRWOG5KLhYyc/xl+g=="
+ },
+ "node_modules/@lit/reactive-element": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.4.tgz",
+ "integrity": "sha512-GFn91inaUa2oHLak8awSIigYz0cU0Payr1rcFsrkf5OJ5eSPxElyZfKh0f2p9FsTiZWXQdWGJeXZICEfXXYSXQ==",
+ "dependencies": {
+ "@lit-labs/ssr-dom-shim": "^1.2.0"
+ }
+ },
+ "node_modules/@tp/helpers": {
+ "version": "2.3.1",
+ "resolved": "https://gitea.codeblob.work/api/packages/tp-elements/npm/%40tp%2Fhelpers/-/2.3.1/helpers-2.3.1.tgz",
+ "integrity": "sha512-LjwqF6wHy6SrdY+0m5+fMP0CG8mwb85rVd7ZkMTpmkJXn4PiTYMaLXNcCjq6k4R5AwhzWUasUOteBJNyl9pynw==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@tp/tp-input": {
+ "version": "1.0.6",
+ "resolved": "https://gitea.codeblob.work/api/packages/tp-elements/npm/%40tp%2Ftp-input/-/1.0.6/tp-input-1.0.6.tgz",
+ "integrity": "sha512-i24LTVNX8taafWEcO4FII1YwrLQO5RvA0f4KDGpxU0Ca+WWfSkq3xwJEbiC9eovP/wrB9e2XoLQ1mjm0S79+mg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@tp/helpers": "^1.0.0",
+ "lit": "^2.2.0"
+ }
+ },
+ "node_modules/@tp/tp-input/node_modules/@lit/reactive-element": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.3.tgz",
+ "integrity": "sha512-QuTgnG52Poic7uM1AN5yJ09QMe0O28e10XzSvWDz02TJiiKee4stsiownEIadWm8nYzyDAyT+gKzUoZmiWQtsQ==",
+ "dependencies": {
+ "@lit-labs/ssr-dom-shim": "^1.0.0"
+ }
+ },
+ "node_modules/@tp/tp-input/node_modules/@tp/helpers": {
+ "version": "1.3.0",
+ "resolved": "https://gitea.codeblob.work/api/packages/tp-elements/npm/%40tp%2Fhelpers/-/1.3.0/helpers-1.3.0.tgz",
+ "integrity": "sha512-mOAVP45kkEYXwonaOd5jkFQLX1nbeKtl8YX8FpL2ytON0cOSsh6TUAbCEcMU5xqgyD6L1ZEZNvxCjhOKOKdGyA==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@tp/tp-input/node_modules/lit": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/lit/-/lit-2.8.0.tgz",
+ "integrity": "sha512-4Sc3OFX9QHOJaHbmTMk28SYgVxLN3ePDjg7hofEft2zWlehFL3LiAuapWc4U/kYwMYJSh2hTCPZ6/LIC7ii0MA==",
+ "dependencies": {
+ "@lit/reactive-element": "^1.6.0",
+ "lit-element": "^3.3.0",
+ "lit-html": "^2.8.0"
+ }
+ },
+ "node_modules/@tp/tp-input/node_modules/lit-element": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-3.3.3.tgz",
+ "integrity": "sha512-XbeRxmTHubXENkV4h8RIPyr8lXc+Ff28rkcQzw3G6up2xg5E8Zu1IgOWIwBLEQsu3cOVFqdYwiVi0hv0SlpqUA==",
+ "dependencies": {
+ "@lit-labs/ssr-dom-shim": "^1.1.0",
+ "@lit/reactive-element": "^1.3.0",
+ "lit-html": "^2.8.0"
+ }
+ },
+ "node_modules/@tp/tp-input/node_modules/lit-html": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.8.0.tgz",
+ "integrity": "sha512-o9t+MQM3P4y7M7yNzqAyjp7z+mQGa4NS4CxiyLqFPyFWyc4O+nodLrkrxSaCTrla6M5YOLaT3RpbbqjszB5g3Q==",
+ "dependencies": {
+ "@types/trusted-types": "^2.0.2"
+ }
+ },
+ "node_modules/@types/trusted-types": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
+ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="
+ },
+ "node_modules/lit": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/lit/-/lit-3.1.4.tgz",
+ "integrity": "sha512-q6qKnKXHy2g1kjBaNfcoLlgbI3+aSOZ9Q4tiGa9bGYXq5RBXxkVTqTIVmP2VWMp29L4GyvCFm8ZQ2o56eUAMyA==",
+ "dependencies": {
+ "@lit/reactive-element": "^2.0.4",
+ "lit-element": "^4.0.4",
+ "lit-html": "^3.1.2"
+ }
+ },
+ "node_modules/lit-element": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.0.6.tgz",
+ "integrity": "sha512-U4sdJ3CSQip7sLGZ/uJskO5hGiqtlpxndsLr6mt3IQIjheg93UKYeGQjWMRql1s/cXNOaRrCzC2FQwjIwSUqkg==",
+ "dependencies": {
+ "@lit-labs/ssr-dom-shim": "^1.2.0",
+ "@lit/reactive-element": "^2.0.4",
+ "lit-html": "^3.1.2"
+ }
+ },
+ "node_modules/lit-html": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.1.4.tgz",
+ "integrity": "sha512-yKKO2uVv7zYFHlWMfZmqc+4hkmSbFp8jgjdZY9vvR9jr4J8fH6FUMXhr+ljfELgmjpvlF7Z1SJ5n5/Jeqtc9YA==",
+ "dependencies": {
+ "@types/trusted-types": "^2.0.2"
+ }
+ }
+ },
+ "dependencies": {
+ "@lit-labs/ssr-dom-shim": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.0.tgz",
+ "integrity": "sha512-yWJKmpGE6lUURKAaIltoPIE/wrbY3TEkqQt+X0m+7fQNnAv0keydnYvbiJFP1PnMhizmIWRWOG5KLhYyc/xl+g=="
+ },
+ "@lit/reactive-element": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.4.tgz",
+ "integrity": "sha512-GFn91inaUa2oHLak8awSIigYz0cU0Payr1rcFsrkf5OJ5eSPxElyZfKh0f2p9FsTiZWXQdWGJeXZICEfXXYSXQ==",
+ "requires": {
+ "@lit-labs/ssr-dom-shim": "^1.2.0"
+ }
+ },
+ "@tp/helpers": {
+ "version": "2.3.1",
+ "resolved": "https://gitea.codeblob.work/api/packages/tp-elements/npm/%40tp%2Fhelpers/-/2.3.1/helpers-2.3.1.tgz",
+ "integrity": "sha512-LjwqF6wHy6SrdY+0m5+fMP0CG8mwb85rVd7ZkMTpmkJXn4PiTYMaLXNcCjq6k4R5AwhzWUasUOteBJNyl9pynw=="
+ },
+ "@tp/tp-input": {
+ "version": "1.0.6",
+ "resolved": "https://gitea.codeblob.work/api/packages/tp-elements/npm/%40tp%2Ftp-input/-/1.0.6/tp-input-1.0.6.tgz",
+ "integrity": "sha512-i24LTVNX8taafWEcO4FII1YwrLQO5RvA0f4KDGpxU0Ca+WWfSkq3xwJEbiC9eovP/wrB9e2XoLQ1mjm0S79+mg==",
+ "requires": {
+ "@tp/helpers": "^1.0.0",
+ "lit": "^2.2.0"
+ },
+ "dependencies": {
+ "@lit/reactive-element": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.3.tgz",
+ "integrity": "sha512-QuTgnG52Poic7uM1AN5yJ09QMe0O28e10XzSvWDz02TJiiKee4stsiownEIadWm8nYzyDAyT+gKzUoZmiWQtsQ==",
+ "requires": {
+ "@lit-labs/ssr-dom-shim": "^1.0.0"
+ }
+ },
+ "@tp/helpers": {
+ "version": "1.3.0",
+ "resolved": "https://gitea.codeblob.work/api/packages/tp-elements/npm/%40tp%2Fhelpers/-/1.3.0/helpers-1.3.0.tgz",
+ "integrity": "sha512-mOAVP45kkEYXwonaOd5jkFQLX1nbeKtl8YX8FpL2ytON0cOSsh6TUAbCEcMU5xqgyD6L1ZEZNvxCjhOKOKdGyA=="
+ },
+ "lit": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/lit/-/lit-2.8.0.tgz",
+ "integrity": "sha512-4Sc3OFX9QHOJaHbmTMk28SYgVxLN3ePDjg7hofEft2zWlehFL3LiAuapWc4U/kYwMYJSh2hTCPZ6/LIC7ii0MA==",
+ "requires": {
+ "@lit/reactive-element": "^1.6.0",
+ "lit-element": "^3.3.0",
+ "lit-html": "^2.8.0"
+ }
+ },
+ "lit-element": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-3.3.3.tgz",
+ "integrity": "sha512-XbeRxmTHubXENkV4h8RIPyr8lXc+Ff28rkcQzw3G6up2xg5E8Zu1IgOWIwBLEQsu3cOVFqdYwiVi0hv0SlpqUA==",
+ "requires": {
+ "@lit-labs/ssr-dom-shim": "^1.1.0",
+ "@lit/reactive-element": "^1.3.0",
+ "lit-html": "^2.8.0"
+ }
+ },
+ "lit-html": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.8.0.tgz",
+ "integrity": "sha512-o9t+MQM3P4y7M7yNzqAyjp7z+mQGa4NS4CxiyLqFPyFWyc4O+nodLrkrxSaCTrla6M5YOLaT3RpbbqjszB5g3Q==",
+ "requires": {
+ "@types/trusted-types": "^2.0.2"
+ }
+ }
+ }
+ },
+ "@types/trusted-types": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
+ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="
+ },
+ "lit": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/lit/-/lit-3.1.4.tgz",
+ "integrity": "sha512-q6qKnKXHy2g1kjBaNfcoLlgbI3+aSOZ9Q4tiGa9bGYXq5RBXxkVTqTIVmP2VWMp29L4GyvCFm8ZQ2o56eUAMyA==",
+ "requires": {
+ "@lit/reactive-element": "^2.0.4",
+ "lit-element": "^4.0.4",
+ "lit-html": "^3.1.2"
+ }
+ },
+ "lit-element": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.0.6.tgz",
+ "integrity": "sha512-U4sdJ3CSQip7sLGZ/uJskO5hGiqtlpxndsLr6mt3IQIjheg93UKYeGQjWMRql1s/cXNOaRrCzC2FQwjIwSUqkg==",
+ "requires": {
+ "@lit-labs/ssr-dom-shim": "^1.2.0",
+ "@lit/reactive-element": "^2.0.4",
+ "lit-html": "^3.1.2"
+ }
+ },
+ "lit-html": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.1.4.tgz",
+ "integrity": "sha512-yKKO2uVv7zYFHlWMfZmqc+4hkmSbFp8jgjdZY9vvR9jr4J8fH6FUMXhr+ljfELgmjpvlF7Z1SJ5n5/Jeqtc9YA==",
+ "requires": {
+ "@types/trusted-types": "^2.0.2"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
index 24f0225..28da72f 100644
--- a/package.json
+++ b/package.json
@@ -1,18 +1,20 @@
{
- "name": "@tp/tp-element",
- "version": "0.0.1",
+ "name": "@tp/tp-number-input",
+ "version": "1.0.0",
"description": "",
- "main": "tp-element.js",
+ "main": "tp-number-input.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
- "url": "https://gitea.codeblob.work/tp-elements/tp-element.git"
+ "url": "https://gitea.codeblob.work/tp-elements/tp-number-input.git"
},
"author": "trading_peter",
"license": "Apache-2.0",
"dependencies": {
+ "@tp/helpers": "^2.3.1",
+ "@tp/tp-input": "^1.0.6",
"lit": "^3.0.0"
}
}
diff --git a/tp-element.js b/tp-element.js
deleted file mode 100644
index 6195006..0000000
--- a/tp-element.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
-@license
-Copyright (c) 2024 trading_peter
-This program is available under Apache License Version 2.0
-*/
-
-import { LitElement, html, css } from 'lit';
-
-class TpElement extends LitElement {
- static get styles() {
- return [
- css`
- :host {
- display: block;
- }
- `
- ];
- }
-
- render() {
- const { } = this;
-
- return html`
-
- `;
- }
-
- static get properties() {
- return { };
- }
-
-
-}
-
-window.customElements.define('tp-element', TpElement);
diff --git a/tp-number-input.js b/tp-number-input.js
new file mode 100644
index 0000000..8e79f84
--- /dev/null
+++ b/tp-number-input.js
@@ -0,0 +1,345 @@
+/**
+@license
+Copyright (c) 2024 trading_peter
+This program is available under Apache License Version 2.0
+*/
+
+import '@tp/tp-input/tp-input.js';
+import { LitElement, html, css, svg } from 'lit';
+import { FormElement } from '@tp/helpers/form-element.js';
+import { EventHelpers } from '@tp/helpers/event-helpers.js';
+import { DomQuery } from '@tp/helpers/dom-query.js';
+import { closest } from '@tp/helpers/closest.js'
+
+class TpNumberInput extends FormElement(EventHelpers(DomQuery(LitElement))) {
+ static get styles() {
+ return [
+ css`
+ :host {
+ display: block;
+ }
+
+ tp-input input {
+ text-align: center;
+ }
+
+ div[slot="prefix"],
+ div[slot="suffix"] {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ cursor: pointer;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ }
+
+ div[slot="prefix"] > tp-icon,
+ div[slot="suffix"] > tp-icon {
+ display: inline;
+ --tp-icon-width: var(--tp-number-input-icon-width, 17px);
+ --tp-icon-height: var(--tp-number-input-icon-height, 17px);
+ }
+ `
+ ];
+ }
+
+ render() {
+ const { disabled, invalid, errorMessage, required, autofocus, _internValue } = this;
+
+ return html`
+
+
+
+
+
+
+
+
+
+ `;
+ }
+
+ static get properties() {
+ return {
+ disabled: { type: Boolean },
+ invalid: { type: Boolean },
+ errorMessage: { type: String },
+ required: { type: Boolean },
+ autofocus: { type: Boolean },
+ step: { type: Number },
+ value: { type: String },
+ min: { type: Number },
+ max: { type: Number },
+ increaseIcon: { type: Object },
+ decreaseIcon: { type: Object },
+ increaseTooltip: { type: String },
+ decreaseTooltip: { type: String },
+
+ // Calculation speed after medium long press time.
+ fastInterval: { type: Number },
+
+ // Calculation speed after really long press on one of the buttons.
+ superFastInterval: { type: Number },
+
+ // String to add after the number. Use this to show a unit for example.
+ // `13` becomes `13px` for example.
+ suffix: { type: String },
+
+ // If true don't include the suffix in the `value` property.
+ ignoreSuffix: { type: Boolean },
+
+ // Value to set if the input is NaN or user tries to go under `min`.
+ // Useful if you need to support something like `0px` -> `user tabs decrease` -> `inherit` for example.
+ specialMin: { type: String },
+
+ // If true the controls allows to switch through time in intervals defined by step.
+ // Most other settings are ignore if the control is in this mode.
+ timeMode: { type: Boolean },
+
+ _internValue: { type: String }
+ };
+ }
+
+ static get defaultIncreaseIcon() {
+ return svg``;
+ }
+
+ static get defaultDecreaseIcon() {
+ return svg``;
+ }
+
+ constructor() {
+ super();
+ this._internValue = '0';
+ this.value = '0';
+ this.step = 1;
+ this.min = Number.MIN_SAFE_INTEGER;
+ this.max = Number.MAX_SAFE_INTEGER;
+ this.fastInterval = 50;
+ this.superFastInterval = 100;
+ }
+
+ firstUpdated() {
+ this.listen(this, 'click', '_onTap');
+ this.listen(this.$.innerInput, 'blur', '_onBlur');
+ this.listen(this.$.innerInput, 'keydown', '_onKey');
+ }
+
+ updated(changes) {
+ if (changes.has('timeMode')) {
+ this._timeModeChanged();
+ }
+
+ if (changes.has('value') || changes.has('min') || changes.has('max') || changes.has('suffix') || changes.has('ignoreSuffix') || changes.has('timeMode')) {
+ this._updateValue(this.value);
+ }
+ }
+
+ _timeModeChanged() {
+ if (this.timeMode) {
+ this.unlisten(this, 'mousedown', '_onMouseDown');
+ } else {
+ this.listen(this, 'mousedown', '_onMouseDown');
+ }
+ }
+
+ _onTap(e) {
+ let val = parseInt(this.value, 10) || 0;
+ const op = this._getOperation(e);
+
+ if(!op) {
+ return;
+ }
+
+ if(this.timeMode) {
+ val = this._calcTime(op);
+ } else {
+ if(op === 'add') {
+ val = Math.max(val + this.step, this.min);
+ } else {
+ val -= this.step;
+ }
+ }
+
+ this._updateValue(val);
+ }
+
+ _calcTime(op) {
+ const parts = this.value.split(':');
+ if(parts.length)
+ if(op === 'add') {
+ this._updateTime(this.step);
+ } else {
+ this._updateTime(-this.step);
+ }
+ }
+
+ _timeValueChanged(value) {
+ if(!this.timeMode) return;
+ const parts = this._parseTime(value);
+ const h = parts[0];
+ const m = parts[1];
+ this.value = this._prefix(h) + ':' + this._prefix(m);
+
+ this.$.input.value = this.value;
+ }
+
+ _parseTime(value) {
+ if(!/[0-9]{1,2}:[0-9]{1,2}/.test(value)) {
+ value = '00:00';
+ }
+
+ const parts = value.split(':');
+ let h = parts[0];
+ let m = parts[1];
+ h = parseInt(h, 10) % 24;
+ m = parseInt(m, 10) % 59;
+ return [h, m];
+ }
+
+ _updateTime(amount) {
+ const parts = this._parseTime(this.$.input.value);
+ let h = parts[0];
+ let m = parts[1];
+
+ // if (amount > 0) {
+ // 1. Calculate how many hours were made full.
+ const addHours = Math.floor((m + amount) / 60);
+
+ // 2. Calculate the rest of the minutes after we added to hours.
+ const minuteRest = m + amount - 60 * addHours;
+
+ h += addHours;
+
+ if(h < 0) {
+ h += 24;
+ }
+
+ // 3. Update the time.
+ this.value = h + ':' + minuteRest;
+ }
+
+ _prefix(val) {
+ val = val.toString();
+ if(val.length === 1) {
+ return '0' + val;
+ } else {
+ return val;
+ }
+ }
+
+ _onMouseDown(e) {
+ this.unlisten(window, 'mouseup', '_onMouseUp');
+ this.listen(window, 'mouseup', '_onMouseUp');
+ const op = this._getOperation(e);
+
+ this._asyncJob = setTimeout(() => {
+ let val = parseInt(this.value, 10) || 0;
+
+ const func = function () {
+ if (op == 'add') {
+ val += this.step;
+ } else {
+ val -= this.step;
+ }
+
+ this._updateValue(val);
+ }.bind(this);
+
+ this._timer = setInterval(func, this.slowInterval);
+
+ // Speed up the interval.
+ this._speedUpJob = setTimeout(() => {
+ clearInterval(this._timer);
+ this._timer = null;
+ this._timer = setInterval(func, this.fastInterval);
+ }, 2000);
+
+ // Switch to super fast interval.
+ this._superSpeedUpJob = setTimeout(() => {
+ clearInterval(this._timer);
+ this._timer = null;
+ this._timer = setInterval(func, this.superFastInterval);
+ }, 5000);
+ }, 500);
+ }
+
+ _onMouseUp(e) {
+ this.unlisten(window, 'mouseup', '_onMouseUp');
+ clearTimeout(this._asyncJob);
+ clearTimeout(this._speedUpJob);
+ clearTimeout(this._superSpeedUpJob);
+ clearInterval(this._timer);
+ this._speedUpJob = null;
+ this._superSpeedUpJob = null;
+ this._asyncJob = null;
+ this._timer = null;
+ }
+
+ _onBlur() {
+ if(this.timeMode) {
+ this._timeValueChanged(this.$.input.value);
+ } else {
+ this._updateValue(parseInt(this.$.input.value, 10));
+ }
+ }
+
+ _onKey(e) {
+ if(e.keyCode === 13) {
+ this._updateValue(parseInt(this.$.input.value, 10));
+ }
+ }
+
+ _getOperation(e) {
+ const btn = e.composedPath()[0];
+
+ if(closest(btn, '#sub', true)) {
+ return 'sub';
+ } else if(closest(btn, '#add', true)) {
+ return 'add';
+ }
+ }
+
+ _internValueChanged(val) {
+ if(val === '') return;
+
+ if(this.timeMode) {
+ this._timeValueChanged(val);
+ } else {
+ this._updateValue(val);
+ }
+ }
+
+ _updateValue(val) {
+ if(this.timeMode) return;
+
+ if(typeof this.specialMin === 'string' && val === this.specialMin) {
+ this.value = this.specialMin;
+ this.$.input.value = this.value;
+ return;
+ }
+
+ val = parseInt(val, 10);
+
+ // If val is NaN and an specialMin is defined, then set it.
+ // Else set the min value.
+ if(isNaN(val)) {
+ val = typeof this.specialMin === 'string' ? this.specialMin : this.min;
+ }
+
+ if((typeof this.specialMin === 'string' && val === this.specialMin) || (val < this.min && typeof this.specialMin === 'string')) {
+ this.value = this.specialMin;
+ this.$.input.value = this.value;
+ return;
+ }
+
+ val = Math.min(this.max, val);
+ val = Math.max(this.min, val);
+ this.value = this.ignoreSuffix ? val : (!!this.suffix ? val + this.suffix : val);
+ this.$.input.value = !!this.suffix ? val + this.suffix : val;
+ }
+}
+
+window.customElements.define('tp-number-input', TpNumberInput);