RegisterAddressInput.vue 2.38 KB
<script lang="ts" setup>
  import { InputGroup, InputNumber, Select, Input } from 'ant-design-vue';
  import { unref } from 'vue';
  import { computed } from 'vue';
  import { ref } from 'vue';

  enum AddressTypeEnum {
    DEC = 'DEC',
    HEX = 'HEX',
  }

  const emit = defineEmits(['update:value']);

  const DEC_MAX_VALUE = parseInt('0xffff', 16);

  withDefaults(
    defineProps<{
      value?: number | string;
      inputProps?: Recordable;
    }>(),
    {
      value: 0,
      inputProps: () => ({}),
    }
  );

  const addressTypeOptions = [
    { label: AddressTypeEnum.DEC, value: AddressTypeEnum.DEC },
    { label: AddressTypeEnum.HEX, value: AddressTypeEnum.HEX },
  ];

  const type = ref(AddressTypeEnum.DEC);

  const inputValue = ref<number | string>(0);

  const getHexValue = computed(() => {
    return parseInt(unref(inputValue) || 0, 16);
  });

  const getDecValue = computed(() => {
    let formatValue = Number(unref(inputValue) || 0).toString(16);
    formatValue = `0x${formatValue.padStart(4, '0')}`;
    return (inputValue.value as number) > DEC_MAX_VALUE ? '0x0000' : formatValue;
  });

  const toDEC = (value: number | string) => {
    return unref(type) === AddressTypeEnum.DEC
      ? isNaN(value as number)
        ? 0
        : Number(value)
      : parseInt(value, 16);
  };

  const handleEmit = () => {
    const syncValue = toDEC(unref(inputValue));
    emit('update:value', syncValue);
  };

  const handleChange = (value: AddressTypeEnum) => {
    const syncValue = value === AddressTypeEnum.DEC ? unref(getHexValue) : unref(getDecValue);
    inputValue.value = syncValue;
    emit('update:value', toDEC(syncValue));
  };
</script>

<template>
  <InputGroup compact class="!flex">
    <Select
      v-model:value="type"
      :options="addressTypeOptions"
      @change="handleChange"
      class="bg-gray-200 max-w-20"
    />
    <InputNumber
      v-if="type === AddressTypeEnum.DEC"
      v-model:value="inputValue"
      :step="1"
      class="flex-1"
      v-bind="inputProps"
      @change="handleEmit"
    />
    <Input v-if="type === AddressTypeEnum.HEX" v-model:value="inputValue" @change="handleEmit" />
    <div class="text-center h-8 leading-8 px-2 bg-gray-200 cursor-pointer rounded-1 w-20">
      <div v-if="type === AddressTypeEnum.DEC">{{ getDecValue }}</div>
      <div v-if="type === AddressTypeEnum.HEX">{{ getHexValue }}</div>
    </div>
  </InputGroup>
</template>