Barebones StepperInput component

This commit is contained in:
Michael Lange
2020-06-18 13:19:47 -07:00
parent 0b0be1b63b
commit 2b88651fca
2 changed files with 90 additions and 0 deletions

View File

@@ -0,0 +1,68 @@
import Component from '@ember/component';
import { action } from '@ember/object';
import { debounce } from '@ember/runloop';
import { oneWay } from '@ember/object/computed';
import { classNames } from '@ember-decorators/component';
import classic from 'ember-classic-decorator';
const ESC = 27;
@classic
@classNames('stepper-input')
export default class StepperInput extends Component {
min = 0;
max = 10;
value = 0;
debounce = 500;
onChange() {}
// Internal value changes immediately for instant visual feedback.
// Value is still the public API and is expected to mutate and re-render
// On onChange which is debounced.
@oneWay('value') internalValue;
// text change: debounce set value if value changed
// debouncing here means when the text input blurs to click a button
// things don't get weird and send two change events
// text focus ESC: revert value
//
// Also add the xsmall button to the existing button story
@action
increment() {
if (this.internalValue < this.max) {
this.incrementProperty('internalValue');
this.update(this.internalValue);
}
}
@action
decrement() {
if (this.internalValue > this.min) {
this.decrementProperty('internalValue');
this.update(this.internalValue);
}
}
@action
setValue(e) {
const newValue = Math.min(this.max, Math.max(this.min, e.target.value));
this.set('internalValue', newValue);
this.update(this.internalValue);
}
@action
resetTextInput(e) {
if (e.keyCode === ESC) {
e.target.value = this.internalValue;
}
}
update(value) {
debounce(this, sendUpdateAction, value, this.debounce);
}
}
function sendUpdateAction(value) {
return this.onChange(value);
}

View File

@@ -0,0 +1,22 @@
<label>{{yield}}</label>
<input
type="number"
min={{min}}
max={{max}}
value={{internalValue}}
onKeyDown={{action "resetTextInput"}}
onChange={{action "setValue"}}>
<button
role="button"
class="button"
disabled={{lte internalValue min}}
onclick={{action "decrement"}}>
{{x-icon "minus-plain"}}
</button>
<button
role="button"
class="button"
disabled={{gte internalValue max}}
onclick={{action "increment"}}>
{{x-icon "plus-plain"}}
</button>