diff --git a/src/components/range/style.scss b/src/components/range/style.scss
index 7fbc05e8..ffe0d54e 100644
--- a/src/components/range/style.scss
+++ b/src/components/range/style.scss
@@ -43,7 +43,6 @@
color: #000;
}
-
// Remove the number controls
-moz-appearance: textfield;
diff --git a/src/custom-els/RangeInput/index.ts b/src/custom-els/RangeInput/index.ts
index 58ed63b5..5759bedb 100644
--- a/src/custom-els/RangeInput/index.ts
+++ b/src/custom-els/RangeInput/index.ts
@@ -1,5 +1,5 @@
import { bind } from '../../lib/initial-util';
-import './styles.css';
+import * as style from './styles.css';
const RETARGETED_EVENTS = ['focus', 'blur'];
const UPDATE_EVENTS = ['input', 'change'];
@@ -7,9 +7,8 @@ const REFLECTED_PROPERTIES = ['name', 'min', 'max', 'step', 'value', 'disabled']
const REFLECTED_ATTRIBUTES = ['name', 'min', 'max', 'step', 'value', 'disabled'];
class RangeInputElement extends HTMLElement {
- private _input = document.createElement('input');
- private _valueDisplayWrapper = document.createElement('div');
- private _valueDisplay = document.createElement('span');
+ private _input: HTMLInputElement;
+ private _valueDisplay?: HTMLDivElement;
private _ignoreChange = false;
static get observedAttributes() {
@@ -18,7 +17,9 @@ class RangeInputElement extends HTMLElement {
constructor() {
super();
+ this._input = document.createElement('input');
this._input.type = 'range';
+ this._input.className = style.input;
for (const event of RETARGETED_EVENTS) {
this._input.addEventListener(event, this._retargetEvent, true);
@@ -29,6 +30,18 @@ class RangeInputElement extends HTMLElement {
}
}
+ connectedCallback() {
+ if (this.contains(this._input)) return;
+ this.innerHTML =
+ `
';
+
+ this.insertBefore(this._input, this.firstChild);
+ this._valueDisplay = this.querySelector('.' + style.valueDisplay) as HTMLDivElement;
+ }
+
get labelPrecision(): string {
return this.getAttribute('label-precision') || '';
}
@@ -37,14 +50,6 @@ class RangeInputElement extends HTMLElement {
this.setAttribute('label-precision', precision);
}
- connectedCallback() {
- if (this._input.parentNode !== this) {
- this.appendChild(this._input);
- this._valueDisplayWrapper.appendChild(this._valueDisplay);
- this.appendChild(this._valueDisplayWrapper);
- }
- }
-
attributeChangedCallback(name: string, oldValue: string, newValue: string | null) {
if (this._ignoreChange) return;
if (newValue === null) {
@@ -65,15 +70,15 @@ class RangeInputElement extends HTMLElement {
@bind
private _update() {
- const value = parseFloat(this.value || '0');
- const min = parseFloat(this.min || '0');
- const max = parseFloat(this.max || '100');
- const labelPrecision = parseFloat(this.labelPrecision || '0');
+ const value = Number(this.value) || 0;
+ const min = Number(this.min) || 0;
+ const max = Number(this.max) || 100;
+ const labelPrecision = Number(this.labelPrecision) || 0;
const percent = 100 * (value - min) / (max - min);
const displayValue = labelPrecision ? value.toPrecision(labelPrecision) :
Math.round(value).toString();
- this._valueDisplay.textContent = displayValue;
+ this._valueDisplay!.textContent = displayValue;
this.style.setProperty('--value-percent', percent + '%');
this.style.setProperty('--value-width', '' + displayValue.length);
}
diff --git a/src/custom-els/RangeInput/styles.css b/src/custom-els/RangeInput/styles.css
index c0397d80..f48483b3 100644
--- a/src/custom-els/RangeInput/styles.css
+++ b/src/custom-els/RangeInput/styles.css
@@ -14,41 +14,6 @@ range-input[disabled] {
filter: grayscale(1);
}
-/* Reversed Variant */
-range-input[reversed] input,
-range-input[reversed]::before,
-range-input[reversed] > div {
- transform: scaleX(-1);
-}
-range-input[reversed] > div > span {
- transform: scaleX(-1) scale(.2);
-}
-range-input[reversed] input:focus + div span {
- transform: scaleX(-1) scale(1);
-}
-
-
-range-input input {
- position: relative;
- flex: 1;
- vertical-align: middle;
- width: 100%;
- padding: 0 !important;
- margin: 0 !important;
- background: none;
- appearance: none;
- -webkit-appearance: none;
- outline: none;
-}
-range-input input::-webkit-slider-runnable-track,
-range-input input::-moz-range-track,
-range-input input::-ms-track {
- appearance: none;
- -ms-appearance: none;
- -moz-appearance: none;
- -webkit-appearance: none;
-}
-
range-input::before {
content: '';
display: block;
@@ -57,32 +22,33 @@ range-input::before {
left: 0;
width: 100%;
height: 2px;
- outline: none;
- border: none;
- background: #eee;
border-radius: 1px;
box-shadow: 0 -.5px 0 rgba(0,0,0,0.3), inset 0 .5px 0 rgba(255,255,255,0.2), 0 .5px 0 rgba(255,255,255,0.3);
background: linear-gradient(#34B9EB, #218ab1) 0/ var(--value-percent, 0%) 100% no-repeat #eee;
}
-range-input input::-webkit-slider-thumb {
- appearance: none;
- -webkit-appearance: none;
- background: url('data:image/svg+xml,') center no-repeat #34B9EB;
- box-sizing: content-box;
+.input {
+ position: relative;
+ width: 100%;
+ padding: 0;
+ margin: 0;
+ opacity: 0;
+}
+
+.thumb {
+ pointer-events: none;
+ position: absolute;
+ bottom: 3px;
+ left: var(--value-percent, 0%);
+ margin-left: -6px;
+ background: url('data:image/svg+xml,') center no-repeat #34B9EB;
border-radius: 50%;
width: 12px;
height: 12px;
- border: none;
box-shadow: 0 0.5px 2px rgba(0,0,0,0.3);
- outline: none;
}
-range-input input:focus::-webkit-slider-thumb {
- box-shadow: 0 1px 3px rgba(0,0,0,0.5);
-}
-
-range-input > div {
+.thumb-wrapper {
position: absolute;
left: 6px;
right: 6px;
@@ -91,8 +57,8 @@ range-input > div {
overflow: visible;
}
-range-input > div > span {
- background: url('data:image/svg+xml,') top center no-repeat;
+.value-display {
+ background: url('data:image/svg+xml,') top center no-repeat;
position: absolute;
box-sizing: border-box;
left: var(--value-percent, 0%);
@@ -111,12 +77,18 @@ range-input > div > span {
font-size: calc(100% - var(--value-width, 3) / 5 * .2em);
text-overflow: clip;
text-shadow: 0 -.5px 0 rgba(0,0,0,0.4);
- transition: transform 200ms ease, opacity 200ms ease;
+ transition: all 200ms ease;
+ transition-property: opacity, transform;
will-change: transform;
pointer-events: none;
overflow: hidden;
}
-range-input input:focus + div span {
+
+.input:active + .thumb-wrapper .value-display {
opacity: 1;
transform: scale(1);
}
+
+.input:active + .thumb-wrapper .thumb {
+ box-shadow: 0 1px 3px rgba(0,0,0,0.5);
+}