mirror of
https://github.com/kemko/nomad.git
synced 2026-01-03 17:05:43 +03:00
Barebones StepperInput component
This commit is contained in:
68
ui/app/components/stepper-input.js
Normal file
68
ui/app/components/stepper-input.js
Normal 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);
|
||||
}
|
||||
22
ui/app/templates/components/stepper-input.hbs
Normal file
22
ui/app/templates/components/stepper-input.hbs
Normal 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>
|
||||
Reference in New Issue
Block a user