chromium/tools/android/dependency_analysis/js/src/vue_components/numeric_input.vue

<!-- Copyright 2020 The Chromium Authors
     Use of this source code is governed by a BSD-style license that can be
     found in the LICENSE file. -->

<template>
  <div class="numeric-input-container">
    <MdField
        class="input-field">
      <label :for="inputId">{{ description }}</label>
      <MdInput
          :id="inputId"
          v-model="internalInputValue"
          class="numeric-input-value"
          type="number"/>
    </MdField>
    <div class="button-group">
      <MdButton
          class="numeric-input-button md-icon-button md-dense"
          @click="internalInputValue++">
        <MdIcon>expand_less</MdIcon>
      </MdButton>
      <MdButton
          class="numeric-input-button md-icon-button md-dense"
          @click="internalInputValue--">
        <MdIcon>expand_more</MdIcon>
      </MdButton>
    </div>
  </div>
</template>

<script>
// @vue/component
const NumericInput = {
  props: {
    description: String,
    inputId: String,
    inputValue: Number,
    minValue: Number,
  },
  computed: {
    internalInputValue: {
      get: function() {
        return this.inputValue;
      },
      set: function(newValue, oldValue) {
        const validNewValue = Math.max(this.minValue, newValue);
        this.$emit('update:inputValue', validNewValue);
        // If `inputValue` is currently `minValue` and the user submits input <
        // `minValue`, `inputValue` will be updated to `minValue` (which, since
        // it already was `minValue`, does not trigger a rerender from Vue's
        // reactivity system). In these cases, we need to force an update to
        // sync the UI with the data.
        if (validNewValue === oldValue) {
          this.$forceUpdate();
        }
      },
    },
  },
};

export default NumericInput;
</script>

<style scoped>
.numeric-input-container {
  display: flex;
  flex-direction: row;
}

.button-group {
  align-items: center;
  display: flex;
  flex-direction: column;
}

.numeric-input-button {
  margin: 0;
}

.numeric-input-value {
  width: 100%;
}

.input-field {
  width: 50%;
}

input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
</style>