{"version":3,"file":"input-number2.mjs","sources":["../../../../../../packages/components/input-number/src/input-number.vue"],"sourcesContent":["<template>\r\n  <div\r\n    :class=\"[\r\n      outerClass,\r\n      ns.b(),\r\n      ns.m(inputNumberSize),\r\n      ns.is('disabled', inputNumberDisabled as boolean),\r\n      ns.is('without-controls', !controls),\r\n      ns.is('controls-right', controlsAtRight),\r\n    ]\"\r\n    @dragstart.prevent\r\n  >\r\n    <span\r\n      v-if=\"controls\"\r\n      v-repeat-click=\"decrease\"\r\n      role=\"button\"\r\n      :class=\"[ns.e('decrease'), ns.is('disabled', minDisabled)]\"\r\n      @keydown.enter=\"decrease\"\r\n    >\r\n      <sg-icon>\r\n        <CaretBottomSolid v-if=\"controlsAtRight\" />\r\n        <Minus v-else />\r\n      </sg-icon>\r\n    </span>\r\n    <span\r\n      v-if=\"controls\"\r\n      v-repeat-click=\"increase\"\r\n      role=\"button\"\r\n      :class=\"[ns.e('increase'), ns.is('disabled', maxDisabled)]\"\r\n      @keydown.enter=\"increase\"\r\n    >\r\n      <sg-icon>\r\n        <CaretTopSolid v-if=\"controlsAtRight\" />\r\n        <Plus v-else />\r\n      </sg-icon>\r\n    </span>\r\n    <sg-input\r\n      ref=\"input\"\r\n      type=\"number\"\r\n      :step=\"step\"\r\n      v-bind=\"attrs\"\r\n      :model-value=\"displayValue\"\r\n      :disabled=\"(inputNumberDisabled as boolean)\"\r\n      :size=\"inputNumberSize\"\r\n      :validate-event=\"false\"\r\n      @keydown.up.prevent=\"increase\"\r\n      @keydown.down.prevent=\"decrease\"\r\n      @on-input=\"handleInput\"\r\n      @on-blur=\"handleBlur\"\r\n      @on-focus=\"handleFocus\"\r\n      @on-change=\"handleInputChange\"\r\n    >\r\n      <template v-if=\"!controls && closable\" #suffix>\r\n        <sg-icon\r\n          class=\"sg-input__icon closable\"\r\n          @click=\"handleClearClick\"\r\n        >\r\n          <Close />\r\n        </sg-icon>\r\n      </template>\r\n    </sg-input>\r\n  </div>\r\n</template>\r\n<script lang=\"ts\">\r\nimport {\r\n  computed,\r\n  defineComponent,\r\n  reactive,\r\n  ref,\r\n  watch,\r\n  onMounted,\r\n  onUpdated,\r\n} from 'vue'\r\n\r\nimport { SgIcon } from '@sgui-plus/components/icon'\r\nimport { RepeatClick } from '@sgui-plus/directives'\r\nimport {\r\n  useDisabled,\r\n  useSize,\r\n  useNamespace,\r\n  useFormItem\r\n} from '@sgui-plus/hooks'\r\nimport SgInput from '@sgui-plus/components/input'\r\nimport { isNumber, isString, isUndefined } from '@sgui-plus/utils/util'\r\nimport { debugWarn } from '@sgui-plus/utils/error'\r\nimport { CaretTopSolid, CaretBottomSolid, Plus, Minus, Close } from '@sgui-plus/icons-vue'\r\nimport { inputNumberProps, inputNumberEmits } from './input-number'\r\nimport { isNil } from 'lodash'\r\n\r\nimport type { ComponentPublicInstance } from 'vue'\r\n\r\ninterface IData {\r\n  currentValue: number | undefined | null\r\n  userInput: null | number | string\r\n}\r\n\r\nexport default defineComponent({\r\n  name: 'SgInputNumber',\r\n  components: {\r\n    SgInput,\r\n    SgIcon,\r\n    CaretTopSolid, CaretBottomSolid, Plus, Minus, Close\r\n  },\r\n  directives: {\r\n    RepeatClick,\r\n  },\r\n  props: inputNumberProps,\r\n  emits: inputNumberEmits,\r\n  setup(props, { emit, attrs }) {\r\n    const { formItem } = useFormItem()\r\n    const input = ref<ComponentPublicInstance<typeof SgInput>>()\r\n    const data = reactive<IData>({\r\n      currentValue: props.modelValue,\r\n      userInput: null,\r\n    })\r\n    const ns = useNamespace('input-number')\r\n    const outerClass = props.class\r\n    const minDisabled = computed(() => _decrease(props.modelValue as number)! < (attrs.min as number))\r\n    const maxDisabled = computed(() => _increase(props.modelValue as number)! > (attrs.max as number))\r\n\r\n    const numPrecision = computed(() => {\r\n      const stepPrecision = getPrecision(props.step)\r\n      if (props.precision !== undefined) {\r\n        if (stepPrecision > props.precision) {\r\n          debugWarn(\r\n            'InputNumber',\r\n            'precision should not be less than the decimal places of step'\r\n          )\r\n        }\r\n        return props.precision\r\n      } else {\r\n        return Math.max(getPrecision(props.modelValue), stepPrecision)\r\n      }\r\n    })\r\n    const controlsAtRight = computed(() => {\r\n      return props.controls && props.controlsPosition === 'right'\r\n    })\r\n\r\n    const inputNumberSize = useSize()\r\n    const inputNumberDisabled = useDisabled()\r\n\r\n    const displayValue = computed(() => {\r\n      if (data.userInput !== null) {\r\n        return data.userInput\r\n      }\r\n      let currentValue: number | string | undefined | null = data.currentValue\r\n      if (isNil(currentValue)) return ''\r\n      if (isNumber(currentValue)) {\r\n        if (Number.isNaN(currentValue)) return ''\r\n        if (props.precision !== undefined) {\r\n          currentValue = currentValue.toFixed(props.precision)\r\n        }\r\n      }\r\n      return currentValue\r\n    })\r\n    const toPrecision = (num: number, pre?: number) => {\r\n      if (pre === undefined) pre = numPrecision.value\r\n      return parseFloat(\r\n        `${Math.round(num * Math.pow(10, pre)) / Math.pow(10, pre)}`\r\n      )\r\n    }\r\n    const getPrecision = (value: number | undefined) => {\r\n      if (value === undefined) return 0\r\n      const valueString = value.toString()\r\n      const dotPosition = valueString.indexOf('.')\r\n      let precision = 0\r\n      if (dotPosition !== -1) {\r\n        precision = valueString.length - dotPosition - 1\r\n      }\r\n      return precision\r\n    }\r\n    const _increase = (val: number) => {\r\n      if (!isNumber(val)) return data.currentValue\r\n      const precisionFactor = Math.pow(10, numPrecision.value)\r\n      // Solve the accuracy problem of JS decimal calculation by converting the value to integer.\r\n      val = isNumber(val) ? val : NaN\r\n      return toPrecision(\r\n        (precisionFactor * val + precisionFactor * props.step) / precisionFactor\r\n      )\r\n    }\r\n    const _decrease = (val: number) => {\r\n      if (!isNumber(val)) return data.currentValue\r\n      const precisionFactor = Math.pow(10, numPrecision.value)\r\n      // Solve the accuracy problem of JS decimal calculation by converting the value to integer.\r\n      val = isNumber(val) ? val : NaN\r\n      return toPrecision(\r\n        (precisionFactor * val - precisionFactor * props.step) / precisionFactor\r\n      )\r\n    }\r\n    const increase = () => {\r\n      if (inputNumberDisabled.value || maxDisabled.value) return\r\n      const value = props.modelValue || 0\r\n      const newVal = _increase(value)\r\n      setCurrentValue(newVal as number, 'increase')\r\n    }\r\n    const decrease = () => {\r\n      if (inputNumberDisabled.value || minDisabled.value) return\r\n      const value = props.modelValue || 0\r\n      const newVal = _decrease(value)\r\n      setCurrentValue(newVal as number, 'decrease')\r\n    }\r\n    const verifyValue = (\r\n      value: number | string | null | undefined,\r\n      update?: boolean\r\n    ): number | null | undefined => {\r\n      const { step, precision, stepStrictly, valueOnClear } = props\r\n      const  { min, max } = attrs\r\n      let newVal = Number(value)\r\n      if (isNil(value) || Number.isNaN(newVal)) {\r\n        return null\r\n      }\r\n      if (value === '') {\r\n        if (valueOnClear === null) {\r\n          return null\r\n        }\r\n        newVal = isString(valueOnClear) ? { min, max }[valueOnClear] : valueOnClear\r\n      }\r\n      if (stepStrictly) {\r\n        newVal = Math.round(newVal / step) * step\r\n      }\r\n      if (!isUndefined(precision)) {\r\n        newVal = toPrecision(newVal, precision)\r\n      }\r\n      if (newVal > (attrs.max as number) || newVal < (attrs.min as number)) {\r\n        newVal = newVal > (attrs.max as number) ? (attrs.max as number) : (attrs.min as number)\r\n        update && emit('update:modelValue', newVal)\r\n      }\r\n      return newVal\r\n    }\r\n    const setCurrentValue = (val: number | string | undefined | null, mode?: string) => {\r\n      const oldVal = data.currentValue\r\n      const newVal = verifyValue(val)\r\n      if (oldVal === newVal) return\r\n      data.userInput = null\r\n      emit('update:modelValue', newVal!)\r\n      emit('onInput', newVal!)\r\n      emit('onChange', newVal!, oldVal!)\r\n      if(mode == 'decrease'){\r\n        emit('onDown', newVal!, oldVal!)\r\n      }\r\n      if(mode == 'increase'){\r\n        emit('onUp', newVal!, oldVal!)\r\n      }\r\n      if (props.validateEvent) {\r\n        formItem?.validate?.('change').catch((err) => debugWarn(err))\r\n      }\r\n      data.currentValue = newVal\r\n    }\r\n    const handleInput = (value: string) => {\r\n      return (data.userInput = value)\r\n    }\r\n    const handleInputChange = (value: string) => {\r\n      const newVal = value !== '' ? Number(value) : ''\r\n      if ((isNumber(newVal) && !Number.isNaN(newVal)) || value === '') {\r\n        setCurrentValue(newVal)\r\n      }\r\n      data.userInput = null\r\n    }\r\n\r\n    const focus = () => {\r\n      input.value?.focus?.()\r\n    }\r\n\r\n    const blur = () => {\r\n      input.value?.blur?.()\r\n    }\r\n\r\n    const select = () => {\r\n      input.value?.select?.()\r\n    }\r\n    const handleFocus = (event: FocusEvent) => {\r\n      emit('onFocus', event)\r\n    }\r\n\r\n    const handleBlur = (event: FocusEvent) => {\r\n      emit('onBlur', event)\r\n      if (props.validateEvent) {\r\n        formItem?.validate?.('blur').catch((err) => debugWarn(err))\r\n      }\r\n    }\r\n    const handleClearClick = () => {\r\n      setCurrentValue('')\r\n      emit('onClear')\r\n    }\r\n\r\n    watch(\r\n      () => props.modelValue,\r\n      (value) => {\r\n        data.currentValue = verifyValue(value, true)\r\n        data.userInput = null\r\n      },\r\n      { immediate: true }\r\n    )\r\n    onMounted(() => {\r\n      const innerInput = input.value?.input as HTMLInputElement\r\n      innerInput.setAttribute('role', 'spinbutton')\r\n      innerInput.setAttribute('aria-valuemax', String((attrs.max as number)))\r\n      innerInput.setAttribute('aria-valuemin', String((attrs.min as number)))\r\n      innerInput.setAttribute('aria-valuenow', String(data.currentValue))\r\n      innerInput.setAttribute(\r\n        'aria-disabled',\r\n        String(inputNumberDisabled.value)\r\n      )\r\n      if (!isNumber(props.modelValue)) {\r\n        let val: number | undefined = Number(props.modelValue)\r\n        if (isNaN(val)) {\r\n          val = undefined\r\n        }\r\n        emit('update:modelValue', val)\r\n      }\r\n    })\r\n    onUpdated(() => {\r\n      const innerInput = input.value?.input\r\n      innerInput.setAttribute('aria-valuenow', data.currentValue)\r\n    })\r\n    return {\r\n      outerClass,\r\n      attrs,\r\n      input,\r\n      displayValue,\r\n      handleInput,\r\n      handleInputChange,\r\n      controlsAtRight,\r\n      decrease,\r\n      increase,\r\n      inputNumberSize,\r\n      inputNumberDisabled,\r\n      maxDisabled,\r\n      minDisabled,\r\n      focus,\r\n      blur,\r\n      select,\r\n      handleFocus,\r\n      handleBlur,\r\n      handleClearClick,\r\n      ns,\r\n    }\r\n  },\r\n})\r\n</script>\r\n"],"names":["_resolveDirective","_openBlock","_createElementBlock","_normalizeClass","_withModifiers","_withDirectives","_withKeys","_withCtx","_createBlock","_createCommentVNode","_createVNode","_mergeProps","_createSlots"],"mappings":"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"}