primevue
Version:
PrimeVue is an open source UI library for Vue featuring a rich set of 80+ components, a theme designer, various theme alternatives such as Material, Bootstrap, Tailwind, premium templates and professional support. In addition, it integrates with PrimeBloc
1 lines • 138 kB
Source Map (JSON)
{"version":3,"file":"index.mjs","sources":["../../src/inputnumber/BaseInputNumber.vue","../../src/inputnumber/InputNumber.vue","../../src/inputnumber/InputNumber.vue?vue&type=template&id=70ff69c5&lang.js"],"sourcesContent":["<script>\nimport BaseInput from '@primevue/core/baseinput';\nimport InputNumberStyle from 'primevue/inputnumber/style';\n\nexport default {\n name: 'BaseInputNumber',\n extends: BaseInput,\n props: {\n format: {\n type: Boolean,\n default: true\n },\n showButtons: {\n type: Boolean,\n default: false\n },\n buttonLayout: {\n type: String,\n default: 'stacked'\n },\n incrementButtonClass: {\n type: String,\n default: null\n },\n decrementButtonClass: {\n type: String,\n default: null\n },\n incrementButtonIcon: {\n type: String,\n default: undefined\n },\n incrementIcon: {\n type: String,\n default: undefined\n },\n decrementButtonIcon: {\n type: String,\n default: undefined\n },\n decrementIcon: {\n type: String,\n default: undefined\n },\n locale: {\n type: String,\n default: undefined\n },\n localeMatcher: {\n type: String,\n default: undefined\n },\n mode: {\n type: String,\n default: 'decimal'\n },\n prefix: {\n type: String,\n default: null\n },\n suffix: {\n type: String,\n default: null\n },\n currency: {\n type: String,\n default: undefined\n },\n currencyDisplay: {\n type: String,\n default: undefined\n },\n useGrouping: {\n type: Boolean,\n default: true\n },\n minFractionDigits: {\n type: Number,\n default: undefined\n },\n maxFractionDigits: {\n type: Number,\n default: undefined\n },\n roundingMode: {\n type: String,\n default: 'halfExpand',\n validator(value) {\n return ['ceil', 'floor', 'expand', 'trunc', 'halfCeil', 'halfFloor', 'halfExpand', 'halfTrunc', 'halfEven'].includes(value);\n }\n },\n min: {\n type: Number,\n default: null\n },\n max: {\n type: Number,\n default: null\n },\n step: {\n type: Number,\n default: 1\n },\n allowEmpty: {\n type: Boolean,\n default: true\n },\n highlightOnFocus: {\n type: Boolean,\n default: false\n },\n readonly: {\n type: Boolean,\n default: false\n },\n placeholder: {\n type: String,\n default: null\n },\n inputId: {\n type: String,\n default: null\n },\n inputClass: {\n type: [String, Object],\n default: null\n },\n inputStyle: {\n type: Object,\n default: null\n },\n ariaLabelledby: {\n type: String,\n default: null\n },\n ariaLabel: {\n type: String,\n default: null\n },\n required: {\n type: Boolean,\n default: false\n }\n },\n style: InputNumberStyle,\n provide() {\n return {\n $pcInputNumber: this,\n $parentInstance: this\n };\n }\n};\n</script>\n","<template>\n <span :class=\"cx('root')\" v-bind=\"ptmi('root')\" :data-p=\"dataP\">\n <InputText\n ref=\"input\"\n :id=\"inputId\"\n :name=\"$formName\"\n role=\"spinbutton\"\n :class=\"[cx('pcInputText'), inputClass]\"\n :style=\"inputStyle\"\n :value=\"formattedValue\"\n :aria-valuemin=\"min\"\n :aria-valuemax=\"max\"\n :aria-valuenow=\"d_value\"\n :inputmode=\"mode === 'decimal' && !minFractionDigits ? 'numeric' : 'decimal'\"\n :disabled=\"disabled\"\n :readonly=\"readonly\"\n :placeholder=\"placeholder\"\n :aria-labelledby=\"ariaLabelledby\"\n :aria-label=\"ariaLabel\"\n :required=\"required\"\n :size=\"size\"\n :invalid=\"invalid\"\n :variant=\"variant\"\n @input=\"onUserInput\"\n @keydown=\"onInputKeyDown\"\n @keypress=\"onInputKeyPress\"\n @paste=\"onPaste\"\n @click=\"onInputClick\"\n @focus=\"onInputFocus\"\n @blur=\"onInputBlur\"\n :pt=\"ptm('pcInputText')\"\n :unstyled=\"unstyled\"\n :data-p=\"dataP\"\n />\n <span v-if=\"showButtons && buttonLayout === 'stacked'\" :class=\"cx('buttonGroup')\" v-bind=\"ptm('buttonGroup')\" :data-p=\"dataP\">\n <slot name=\"incrementbutton\" :listeners=\"upButtonListeners\">\n <button :class=\"[cx('incrementButton'), incrementButtonClass]\" v-on=\"upButtonListeners\" :disabled=\"disabled\" :tabindex=\"-1\" aria-hidden=\"true\" type=\"button\" v-bind=\"ptm('incrementButton')\" :data-p=\"dataP\">\n <slot :name=\"$slots.incrementicon ? 'incrementicon' : 'incrementbuttonicon'\">\n <component :is=\"incrementIcon || incrementButtonIcon ? 'span' : 'AngleUpIcon'\" :class=\"[incrementIcon, incrementButtonIcon]\" v-bind=\"ptm('incrementIcon')\" data-pc-section=\"incrementicon\" />\n </slot>\n </button>\n </slot>\n <slot name=\"decrementbutton\" :listeners=\"downButtonListeners\">\n <button :class=\"[cx('decrementButton'), decrementButtonClass]\" v-on=\"downButtonListeners\" :disabled=\"disabled\" :tabindex=\"-1\" aria-hidden=\"true\" type=\"button\" v-bind=\"ptm('decrementButton')\" :data-p=\"dataP\">\n <slot :name=\"$slots.decrementicon ? 'decrementicon' : 'decrementbuttonicon'\">\n <component :is=\"decrementIcon || decrementButtonIcon ? 'span' : 'AngleDownIcon'\" :class=\"[decrementIcon, decrementButtonIcon]\" v-bind=\"ptm('decrementIcon')\" data-pc-section=\"decrementicon\" />\n </slot>\n </button>\n </slot>\n </span>\n <slot name=\"incrementbutton\" :listeners=\"upButtonListeners\">\n <button\n v-if=\"showButtons && buttonLayout !== 'stacked'\"\n :class=\"[cx('incrementButton'), incrementButtonClass]\"\n v-on=\"upButtonListeners\"\n :disabled=\"disabled\"\n :tabindex=\"-1\"\n aria-hidden=\"true\"\n type=\"button\"\n v-bind=\"ptm('incrementButton')\"\n :data-p=\"dataP\"\n >\n <slot :name=\"$slots.incrementicon ? 'incrementicon' : 'incrementbuttonicon'\">\n <component :is=\"incrementIcon || incrementButtonIcon ? 'span' : 'AngleUpIcon'\" :class=\"[incrementIcon, incrementButtonIcon]\" v-bind=\"ptm('incrementIcon')\" data-pc-section=\"incrementicon\" />\n </slot>\n </button>\n </slot>\n <slot name=\"decrementbutton\" :listeners=\"downButtonListeners\">\n <button\n v-if=\"showButtons && buttonLayout !== 'stacked'\"\n :class=\"[cx('decrementButton'), decrementButtonClass]\"\n v-on=\"downButtonListeners\"\n :disabled=\"disabled\"\n :tabindex=\"-1\"\n aria-hidden=\"true\"\n type=\"button\"\n v-bind=\"ptm('decrementButton')\"\n :data-p=\"dataP\"\n >\n <slot :name=\"$slots.decrementicon ? 'decrementicon' : 'decrementbuttonicon'\">\n <component :is=\"decrementIcon || decrementButtonIcon ? 'span' : 'AngleDownIcon'\" :class=\"[decrementIcon, decrementButtonIcon]\" v-bind=\"ptm('decrementIcon')\" data-pc-section=\"decrementicon\" />\n </slot>\n </button>\n </slot>\n <!-- TODO: decrementButton* and incrementButton* are deprecated since v4.0-->\n </span>\n</template>\n\n<script>\nimport { cn } from '@primeuix/utils';\nimport { clearSelection, getSelection } from '@primeuix/utils/dom';\nimport { isNotEmpty } from '@primeuix/utils/object';\nimport AngleDownIcon from '@primevue/icons/angledown';\nimport AngleUpIcon from '@primevue/icons/angleup';\nimport InputText from 'primevue/inputtext';\nimport BaseInputNumber from './BaseInputNumber.vue';\n\nexport default {\n name: 'InputNumber',\n extends: BaseInputNumber,\n inheritAttrs: false,\n emits: ['input', 'focus', 'blur'],\n inject: {\n $pcFluid: { default: null }\n },\n numberFormat: null,\n _numeral: null,\n _decimal: null,\n _group: null,\n _minusSign: null,\n _currency: null,\n _suffix: null,\n _prefix: null,\n _index: null,\n groupChar: '',\n isSpecialChar: null,\n prefixChar: null,\n suffixChar: null,\n timer: null,\n data() {\n return {\n // @deprecated\n d_modelValue: this.d_value,\n focused: false\n };\n },\n watch: {\n d_value(newValue) {\n // @deprecated since v4.2.0\n this.d_modelValue = newValue;\n },\n locale(newValue, oldValue) {\n this.updateConstructParser(newValue, oldValue);\n },\n localeMatcher(newValue, oldValue) {\n this.updateConstructParser(newValue, oldValue);\n },\n mode(newValue, oldValue) {\n this.updateConstructParser(newValue, oldValue);\n },\n currency(newValue, oldValue) {\n this.updateConstructParser(newValue, oldValue);\n },\n currencyDisplay(newValue, oldValue) {\n this.updateConstructParser(newValue, oldValue);\n },\n useGrouping(newValue, oldValue) {\n this.updateConstructParser(newValue, oldValue);\n },\n minFractionDigits(newValue, oldValue) {\n this.updateConstructParser(newValue, oldValue);\n },\n maxFractionDigits(newValue, oldValue) {\n this.updateConstructParser(newValue, oldValue);\n },\n suffix(newValue, oldValue) {\n this.updateConstructParser(newValue, oldValue);\n },\n prefix(newValue, oldValue) {\n this.updateConstructParser(newValue, oldValue);\n }\n },\n created() {\n this.constructParser();\n },\n methods: {\n getOptions() {\n return {\n localeMatcher: this.localeMatcher,\n style: this.mode,\n currency: this.currency,\n currencyDisplay: this.currencyDisplay,\n useGrouping: this.useGrouping,\n minimumFractionDigits: this.minFractionDigits,\n maximumFractionDigits: this.maxFractionDigits,\n roundingMode: this.roundingMode\n };\n },\n constructParser() {\n this.numberFormat = new Intl.NumberFormat(this.locale, this.getOptions());\n const numerals = [...new Intl.NumberFormat(this.locale, { useGrouping: false }).format(9876543210)].reverse();\n const index = new Map(numerals.map((d, i) => [d, i]));\n\n this._numeral = new RegExp(`[${numerals.join('')}]`, 'g');\n this._group = this.getGroupingExpression();\n this._minusSign = this.getMinusSignExpression();\n this._currency = this.getCurrencyExpression();\n this._decimal = this.getDecimalExpression();\n this._suffix = this.getSuffixExpression();\n this._prefix = this.getPrefixExpression();\n this._index = (d) => index.get(d);\n },\n updateConstructParser(newValue, oldValue) {\n if (newValue !== oldValue) {\n this.constructParser();\n }\n },\n escapeRegExp(text) {\n return text.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&');\n },\n getDecimalExpression() {\n const formatter = new Intl.NumberFormat(this.locale, { ...this.getOptions(), useGrouping: false });\n\n return new RegExp(`[${formatter.format(1.1).replace(this._currency, '').trim().replace(this._numeral, '')}]`, 'g');\n },\n getGroupingExpression() {\n const formatter = new Intl.NumberFormat(this.locale, { useGrouping: true });\n\n this.groupChar = formatter.format(1000000).trim().replace(this._numeral, '').charAt(0);\n\n return new RegExp(`[${this.groupChar}]`, 'g');\n },\n getMinusSignExpression() {\n const formatter = new Intl.NumberFormat(this.locale, { useGrouping: false });\n\n return new RegExp(`[${formatter.format(-1).trim().replace(this._numeral, '')}]`, 'g');\n },\n getCurrencyExpression() {\n if (this.currency) {\n const formatter = new Intl.NumberFormat(this.locale, { style: 'currency', currency: this.currency, currencyDisplay: this.currencyDisplay, minimumFractionDigits: 0, maximumFractionDigits: 0, roundingMode: this.roundingMode });\n\n return new RegExp(`[${formatter.format(1).replace(/\\s/g, '').replace(this._numeral, '').replace(this._group, '')}]`, 'g');\n }\n\n return new RegExp(`[]`, 'g');\n },\n getPrefixExpression() {\n if (this.prefix) {\n this.prefixChar = this.prefix;\n } else {\n const formatter = new Intl.NumberFormat(this.locale, { style: this.mode, currency: this.currency, currencyDisplay: this.currencyDisplay });\n\n this.prefixChar = formatter.format(1).split('1')[0];\n }\n\n return new RegExp(`${this.escapeRegExp(this.prefixChar || '')}`, 'g');\n },\n getSuffixExpression() {\n if (this.suffix) {\n this.suffixChar = this.suffix;\n } else {\n const formatter = new Intl.NumberFormat(this.locale, { style: this.mode, currency: this.currency, currencyDisplay: this.currencyDisplay, minimumFractionDigits: 0, maximumFractionDigits: 0, roundingMode: this.roundingMode });\n\n this.suffixChar = formatter.format(1).split('1')[1];\n }\n\n return new RegExp(`${this.escapeRegExp(this.suffixChar || '')}`, 'g');\n },\n formatValue(value) {\n if (value != null) {\n if (value === '-') {\n // Minus sign\n return value;\n }\n\n if (this.format) {\n let formatter = new Intl.NumberFormat(this.locale, this.getOptions());\n let formattedValue = formatter.format(value);\n\n if (this.prefix) {\n formattedValue = this.prefix + formattedValue;\n }\n\n if (this.suffix) {\n formattedValue = formattedValue + this.suffix;\n }\n\n return formattedValue;\n }\n\n return value.toString();\n }\n\n return '';\n },\n parseValue(text) {\n let filteredText = text\n .replace(this._suffix, '')\n .replace(this._prefix, '')\n .trim()\n .replace(/\\s/g, '')\n .replace(this._currency, '')\n .replace(this._group, '')\n .replace(this._minusSign, '-')\n .replace(this._decimal, '.')\n .replace(this._numeral, this._index);\n\n if (filteredText) {\n if (filteredText === '-')\n // Minus sign\n return filteredText;\n\n let parsedValue = +filteredText;\n\n return isNaN(parsedValue) ? null : parsedValue;\n }\n\n return null;\n },\n repeat(event, interval, dir) {\n if (this.readonly) {\n return;\n }\n\n let i = interval || 500;\n\n this.clearTimer();\n this.timer = setTimeout(() => {\n this.repeat(event, 40, dir);\n }, i);\n\n this.spin(event, dir);\n },\n spin(event, dir) {\n if (this.$refs.input) {\n let step = this.step * dir;\n let currentValue = this.parseValue(this.$refs.input.$el.value) || 0;\n let newValue = this.validateValue(currentValue + step);\n\n this.updateInput(newValue, null, 'spin');\n this.updateModel(event, newValue);\n\n this.handleOnInput(event, currentValue, newValue);\n }\n },\n onUpButtonMouseDown(event) {\n if (!this.disabled) {\n this.$refs.input.$el.focus();\n this.repeat(event, null, 1);\n event.preventDefault();\n }\n },\n onUpButtonMouseUp() {\n if (!this.disabled) {\n this.clearTimer();\n }\n },\n onUpButtonMouseLeave() {\n if (!this.disabled) {\n this.clearTimer();\n }\n },\n onUpButtonKeyUp() {\n if (!this.disabled) {\n this.clearTimer();\n }\n },\n onUpButtonKeyDown(event) {\n if (event.code === 'Space' || event.code === 'Enter' || event.code === 'NumpadEnter') {\n this.repeat(event, null, 1);\n }\n },\n onDownButtonMouseDown(event) {\n if (!this.disabled) {\n this.$refs.input.$el.focus();\n this.repeat(event, null, -1);\n event.preventDefault();\n }\n },\n onDownButtonMouseUp() {\n if (!this.disabled) {\n this.clearTimer();\n }\n },\n onDownButtonMouseLeave() {\n if (!this.disabled) {\n this.clearTimer();\n }\n },\n onDownButtonKeyUp() {\n if (!this.disabled) {\n this.clearTimer();\n }\n },\n onDownButtonKeyDown(event) {\n if (event.code === 'Space' || event.code === 'Enter' || event.code === 'NumpadEnter') {\n this.repeat(event, null, -1);\n }\n },\n onUserInput() {\n if (this.isSpecialChar) {\n this.$refs.input.$el.value = this.lastValue;\n }\n\n this.isSpecialChar = false;\n },\n onInputKeyDown(event) {\n if (this.readonly) {\n return;\n }\n\n if (event.altKey || event.ctrlKey || event.metaKey) {\n this.isSpecialChar = true;\n this.lastValue = this.$refs.input.$el.value;\n\n return;\n }\n\n this.lastValue = event.target.value;\n\n let selectionStart = event.target.selectionStart;\n let selectionEnd = event.target.selectionEnd;\n let selectionRange = selectionEnd - selectionStart;\n let inputValue = event.target.value;\n let newValueStr = null;\n const code = event.code || event.key;\n\n switch (code) {\n case 'ArrowUp':\n this.spin(event, 1);\n event.preventDefault();\n break;\n\n case 'ArrowDown':\n this.spin(event, -1);\n event.preventDefault();\n break;\n\n case 'ArrowLeft':\n if (selectionRange > 1) {\n const cursorPosition = this.isNumeralChar(inputValue.charAt(selectionStart)) ? selectionStart + 1 : selectionStart + 2;\n\n this.$refs.input.$el.setSelectionRange(cursorPosition, cursorPosition);\n } else if (!this.isNumeralChar(inputValue.charAt(selectionStart - 1))) {\n event.preventDefault();\n }\n\n break;\n\n case 'ArrowRight':\n if (selectionRange > 1) {\n const cursorPosition = selectionEnd - 1;\n\n this.$refs.input.$el.setSelectionRange(cursorPosition, cursorPosition);\n } else if (!this.isNumeralChar(inputValue.charAt(selectionStart))) {\n event.preventDefault();\n }\n\n break;\n\n case 'Tab':\n case 'Enter':\n case 'NumpadEnter':\n newValueStr = this.validateValue(this.parseValue(inputValue));\n this.$refs.input.$el.value = this.formatValue(newValueStr);\n this.$refs.input.$el.setAttribute('aria-valuenow', newValueStr);\n this.updateModel(event, newValueStr);\n break;\n\n case 'Backspace': {\n event.preventDefault();\n\n if (selectionStart === selectionEnd) {\n const deleteChar = inputValue.charAt(selectionStart - 1);\n const { decimalCharIndex, decimalCharIndexWithoutPrefix } = this.getDecimalCharIndexes(inputValue);\n\n if (this.isNumeralChar(deleteChar)) {\n const decimalLength = this.getDecimalLength(inputValue);\n\n if (this._group.test(deleteChar)) {\n this._group.lastIndex = 0;\n newValueStr = inputValue.slice(0, selectionStart - 2) + inputValue.slice(selectionStart - 1);\n } else if (this._decimal.test(deleteChar)) {\n this._decimal.lastIndex = 0;\n\n if (decimalLength) {\n this.$refs.input.$el.setSelectionRange(selectionStart - 1, selectionStart - 1);\n } else {\n newValueStr = inputValue.slice(0, selectionStart - 1) + inputValue.slice(selectionStart);\n }\n } else if (decimalCharIndex > 0 && selectionStart > decimalCharIndex) {\n const insertedText = this.isDecimalMode() && (this.minFractionDigits || 0) < decimalLength ? '' : '0';\n\n newValueStr = inputValue.slice(0, selectionStart - 1) + insertedText + inputValue.slice(selectionStart);\n } else if (decimalCharIndexWithoutPrefix === 1) {\n newValueStr = inputValue.slice(0, selectionStart - 1) + '0' + inputValue.slice(selectionStart);\n newValueStr = this.parseValue(newValueStr) > 0 ? newValueStr : '';\n } else {\n newValueStr = inputValue.slice(0, selectionStart - 1) + inputValue.slice(selectionStart);\n }\n }\n\n this.updateValue(event, newValueStr, null, 'delete-single');\n } else {\n newValueStr = this.deleteRange(inputValue, selectionStart, selectionEnd);\n this.updateValue(event, newValueStr, null, 'delete-range');\n }\n\n break;\n }\n\n case 'Delete':\n event.preventDefault();\n\n if (selectionStart === selectionEnd) {\n const deleteChar = inputValue.charAt(selectionStart);\n const { decimalCharIndex, decimalCharIndexWithoutPrefix } = this.getDecimalCharIndexes(inputValue);\n\n if (this.isNumeralChar(deleteChar)) {\n const decimalLength = this.getDecimalLength(inputValue);\n\n if (this._group.test(deleteChar)) {\n this._group.lastIndex = 0;\n newValueStr = inputValue.slice(0, selectionStart) + inputValue.slice(selectionStart + 2);\n } else if (this._decimal.test(deleteChar)) {\n this._decimal.lastIndex = 0;\n\n if (decimalLength) {\n this.$refs.input.$el.setSelectionRange(selectionStart + 1, selectionStart + 1);\n } else {\n newValueStr = inputValue.slice(0, selectionStart) + inputValue.slice(selectionStart + 1);\n }\n } else if (decimalCharIndex > 0 && selectionStart > decimalCharIndex) {\n const insertedText = this.isDecimalMode() && (this.minFractionDigits || 0) < decimalLength ? '' : '0';\n\n newValueStr = inputValue.slice(0, selectionStart) + insertedText + inputValue.slice(selectionStart + 1);\n } else if (decimalCharIndexWithoutPrefix === 1) {\n newValueStr = inputValue.slice(0, selectionStart) + '0' + inputValue.slice(selectionStart + 1);\n newValueStr = this.parseValue(newValueStr) > 0 ? newValueStr : '';\n } else {\n newValueStr = inputValue.slice(0, selectionStart) + inputValue.slice(selectionStart + 1);\n }\n }\n\n this.updateValue(event, newValueStr, null, 'delete-back-single');\n } else {\n newValueStr = this.deleteRange(inputValue, selectionStart, selectionEnd);\n this.updateValue(event, newValueStr, null, 'delete-range');\n }\n\n break;\n\n case 'Home':\n event.preventDefault();\n\n if (isNotEmpty(this.min)) {\n this.updateModel(event, this.min);\n }\n\n break;\n\n case 'End':\n event.preventDefault();\n\n if (isNotEmpty(this.max)) {\n this.updateModel(event, this.max);\n }\n\n break;\n\n default:\n break;\n }\n },\n onInputKeyPress(event) {\n if (this.readonly) {\n return;\n }\n\n let char = event.key;\n let isDecimalSign = this.isDecimalSign(char);\n const isMinusSign = this.isMinusSign(char);\n\n if (event.code !== 'Enter') {\n event.preventDefault();\n }\n\n if ((Number(char) >= 0 && Number(char) <= 9) || isMinusSign || isDecimalSign) {\n this.insert(event, char, { isDecimalSign, isMinusSign });\n }\n },\n onPaste(event) {\n event.preventDefault();\n let data = (event.clipboardData || window['clipboardData']).getData('Text');\n\n if (data) {\n let filteredData = this.parseValue(data);\n\n if (filteredData != null) {\n this.insert(event, filteredData.toString());\n }\n }\n },\n allowMinusSign() {\n return this.min === null || this.min < 0;\n },\n isMinusSign(char) {\n if (this._minusSign.test(char) || char === '-') {\n this._minusSign.lastIndex = 0;\n\n return true;\n }\n\n return false;\n },\n isDecimalSign(char) {\n if ((this.locale?.includes('fr') && ['.', ','].includes(char)) || this._decimal.test(char)) {\n this._decimal.lastIndex = 0;\n\n return true;\n }\n\n return false;\n },\n isDecimalMode() {\n return this.mode === 'decimal';\n },\n getDecimalCharIndexes(val) {\n let decimalCharIndex = val.search(this._decimal);\n\n this._decimal.lastIndex = 0;\n\n const filteredVal = val.replace(this._prefix, '').trim().replace(/\\s/g, '').replace(this._currency, '');\n const decimalCharIndexWithoutPrefix = filteredVal.search(this._decimal);\n\n this._decimal.lastIndex = 0;\n\n return { decimalCharIndex, decimalCharIndexWithoutPrefix };\n },\n getCharIndexes(val) {\n const decimalCharIndex = val.search(this._decimal);\n\n this._decimal.lastIndex = 0;\n const minusCharIndex = val.search(this._minusSign);\n\n this._minusSign.lastIndex = 0;\n const suffixCharIndex = val.search(this._suffix);\n\n this._suffix.lastIndex = 0;\n const currencyCharIndex = val.search(this._currency);\n\n this._currency.lastIndex = 0;\n\n return { decimalCharIndex, minusCharIndex, suffixCharIndex, currencyCharIndex };\n },\n insert(event, text, sign = { isDecimalSign: false, isMinusSign: false }) {\n const minusCharIndexOnText = text.search(this._minusSign);\n\n this._minusSign.lastIndex = 0;\n\n if (!this.allowMinusSign() && minusCharIndexOnText !== -1) {\n return;\n }\n\n const selectionStart = this.$refs.input.$el.selectionStart;\n const selectionEnd = this.$refs.input.$el.selectionEnd;\n let inputValue = this.$refs.input.$el.value.trim();\n const { decimalCharIndex, minusCharIndex, suffixCharIndex, currencyCharIndex } = this.getCharIndexes(inputValue);\n let newValueStr;\n\n if (sign.isMinusSign) {\n const isNewMinusSign = minusCharIndex === -1;\n\n if (selectionStart === 0 || selectionStart === currencyCharIndex + 1) {\n newValueStr = inputValue;\n\n if (isNewMinusSign || selectionEnd !== 0) {\n newValueStr = this.insertText(inputValue, text, 0, selectionEnd);\n }\n\n this.updateValue(event, newValueStr, text, 'insert');\n }\n } else if (sign.isDecimalSign) {\n if (decimalCharIndex > 0 && selectionStart === decimalCharIndex) {\n this.updateValue(event, inputValue, text, 'insert');\n } else if (decimalCharIndex > selectionStart && decimalCharIndex < selectionEnd) {\n newValueStr = this.insertText(inputValue, text, selectionStart, selectionEnd);\n this.updateValue(event, newValueStr, text, 'insert');\n } else if (decimalCharIndex === -1 && this.maxFractionDigits) {\n newValueStr = this.insertText(inputValue, text, selectionStart, selectionEnd);\n this.updateValue(event, newValueStr, text, 'insert');\n }\n } else {\n const maxFractionDigits = this.numberFormat.resolvedOptions().maximumFractionDigits;\n const operation = selectionStart !== selectionEnd ? 'range-insert' : 'insert';\n\n if (decimalCharIndex > 0 && selectionStart > decimalCharIndex) {\n if (selectionStart + text.length - (decimalCharIndex + 1) <= maxFractionDigits) {\n const charIndex = currencyCharIndex >= selectionStart ? currencyCharIndex - 1 : suffixCharIndex >= selectionStart ? suffixCharIndex : inputValue.length;\n\n newValueStr = inputValue.slice(0, selectionStart) + text + inputValue.slice(selectionStart + text.length, charIndex) + inputValue.slice(charIndex);\n this.updateValue(event, newValueStr, text, operation);\n }\n } else {\n newValueStr = this.insertText(inputValue, text, selectionStart, selectionEnd);\n this.updateValue(event, newValueStr, text, operation);\n }\n }\n },\n insertText(value, text, start, end) {\n let textSplit = text === '.' ? text : text.split('.');\n\n if (textSplit.length === 2) {\n const decimalCharIndex = value.slice(start, end).search(this._decimal);\n\n this._decimal.lastIndex = 0;\n\n return decimalCharIndex > 0 ? value.slice(0, start) + this.formatValue(text) + value.slice(end) : this.formatValue(text) || value;\n } else if (end - start === value.length) {\n return this.formatValue(text);\n } else if (start === 0) {\n return text + value.slice(end);\n } else if (end === value.length) {\n return value.slice(0, start) + text;\n } else {\n return value.slice(0, start) + text + value.slice(end);\n }\n },\n deleteRange(value, start, end) {\n let newValueStr;\n\n if (end - start === value.length) newValueStr = '';\n else if (start === 0) newValueStr = value.slice(end);\n else if (end === value.length) newValueStr = value.slice(0, start);\n else newValueStr = value.slice(0, start) + value.slice(end);\n\n return newValueStr;\n },\n initCursor() {\n let selectionStart = this.$refs.input.$el.selectionStart;\n let inputValue = this.$refs.input.$el.value;\n let valueLength = inputValue.length;\n let index = null;\n\n // remove prefix\n let prefixLength = (this.prefixChar || '').length;\n\n inputValue = inputValue.replace(this._prefix, '');\n selectionStart = selectionStart - prefixLength;\n\n let char = inputValue.charAt(selectionStart);\n\n if (this.isNumeralChar(char)) {\n return selectionStart + prefixLength;\n }\n\n //left\n let i = selectionStart - 1;\n\n while (i >= 0) {\n char = inputValue.charAt(i);\n\n if (this.isNumeralChar(char)) {\n index = i + prefixLength;\n break;\n } else {\n i--;\n }\n }\n\n if (index !== null) {\n this.$refs.input.$el.setSelectionRange(index + 1, index + 1);\n } else {\n i = selectionStart;\n\n while (i < valueLength) {\n char = inputValue.charAt(i);\n\n if (this.isNumeralChar(char)) {\n index = i + prefixLength;\n break;\n } else {\n i++;\n }\n }\n\n if (index !== null) {\n this.$refs.input.$el.setSelectionRange(index, index);\n }\n }\n\n return index || 0;\n },\n onInputClick() {\n const currentValue = this.$refs.input.$el.value;\n\n if (!this.readonly && currentValue !== getSelection()) {\n this.initCursor();\n }\n },\n isNumeralChar(char) {\n if (char.length === 1 && (this._numeral.test(char) || this._decimal.test(char) || this._group.test(char) || this._minusSign.test(char))) {\n this.resetRegex();\n\n return true;\n }\n\n return false;\n },\n resetRegex() {\n this._numeral.lastIndex = 0;\n this._decimal.lastIndex = 0;\n this._group.lastIndex = 0;\n this._minusSign.lastIndex = 0;\n },\n updateValue(event, valueStr, insertedValueStr, operation) {\n let currentValue = this.$refs.input.$el.value;\n let newValue = null;\n\n if (valueStr != null) {\n newValue = this.parseValue(valueStr);\n newValue = !newValue && !this.allowEmpty ? this.min || 0 : newValue;\n this.updateInput(newValue, insertedValueStr, operation, valueStr);\n\n this.handleOnInput(event, currentValue, newValue);\n }\n },\n handleOnInput(event, currentValue, newValue) {\n if (this.isValueChanged(currentValue, newValue)) {\n this.$emit('input', { originalEvent: event, value: newValue, formattedValue: currentValue });\n this.formField.onInput?.({ originalEvent: event, value: newValue });\n }\n },\n isValueChanged(currentValue, newValue) {\n if (newValue === null && currentValue !== null) {\n return true;\n }\n\n if (newValue != null) {\n let parsedCurrentValue = typeof currentValue === 'string' ? this.parseValue(currentValue) : currentValue;\n\n return newValue !== parsedCurrentValue;\n }\n\n return false;\n },\n validateValue(value) {\n if (value === '-' || value == null) {\n return null;\n }\n\n if (this.min != null && value < this.min) {\n return this.min;\n }\n\n if (this.max != null && value > this.max) {\n return this.max;\n }\n\n return value;\n },\n updateInput(value, insertedValueStr, operation, valueStr) {\n insertedValueStr = insertedValueStr || '';\n\n let inputValue = this.$refs.input.$el.value;\n let newValue = this.formatValue(value);\n let currentLength = inputValue.length;\n\n if (newValue !== valueStr) {\n newValue = this.concatValues(newValue, valueStr);\n }\n\n if (currentLength === 0) {\n this.$refs.input.$el.value = newValue;\n this.$refs.input.$el.setSelectionRange(0, 0);\n const index = this.initCursor();\n const selectionEnd = index + insertedValueStr.length;\n\n this.$refs.input.$el.setSelectionRange(selectionEnd, selectionEnd);\n } else {\n let selectionStart = this.$refs.input.$el.selectionStart;\n let selectionEnd = this.$refs.input.$el.selectionEnd;\n\n this.$refs.input.$el.value = newValue;\n let newLength = newValue.length;\n\n if (operation === 'range-insert') {\n const startValue = this.parseValue((inputValue || '').slice(0, selectionStart));\n const startValueStr = startValue !== null ? startValue.toString() : '';\n const startExpr = startValueStr.split('').join(`(${this.groupChar})?`);\n const sRegex = new RegExp(startExpr, 'g');\n\n sRegex.test(newValue);\n\n const tExpr = insertedValueStr.split('').join(`(${this.groupChar})?`);\n const tRegex = new RegExp(tExpr, 'g');\n\n tRegex.test(newValue.slice(sRegex.lastIndex));\n\n selectionEnd = sRegex.lastIndex + tRegex.lastIndex;\n this.$refs.input.$el.setSelectionRange(selectionEnd, selectionEnd);\n } else if (newLength === currentLength) {\n if (operation === 'insert' || operation === 'delete-back-single') {\n this.$refs.input.$el.setSelectionRange(selectionEnd + 1, selectionEnd + 1);\n } else if (operation === 'delete-single') {\n this.$refs.input.$el.setSelectionRange(selectionEnd - 1, selectionEnd - 1);\n } else if (operation === 'delete-range' || operation === 'spin') {\n this.$refs.input.$el.setSelectionRange(selectionEnd, selectionEnd);\n }\n } else if (operation === 'delete-back-single') {\n let prevChar = inputValue.charAt(selectionEnd - 1);\n let nextChar = inputValue.charAt(selectionEnd);\n let diff = currentLength - newLength;\n let isGroupChar = this._group.test(nextChar);\n\n if (isGroupChar && diff === 1) {\n selectionEnd += 1;\n } else if (!isGroupChar && this.isNumeralChar(prevChar)) {\n selectionEnd += -1 * diff + 1;\n }\n\n this._group.lastIndex = 0;\n this.$refs.input.$el.setSelectionRange(selectionEnd, selectionEnd);\n } else if (inputValue === '-' && operation === 'insert') {\n this.$refs.input.$el.setSelectionRange(0, 0);\n const index = this.initCursor();\n const selectionEnd = index + insertedValueStr.length + 1;\n\n this.$refs.input.$el.setSelectionRange(selectionEnd, selectionEnd);\n } else {\n selectionEnd = selectionEnd + (newLength - currentLength);\n this.$refs.input.$el.setSelectionRange(selectionEnd, selectionEnd);\n }\n }\n\n this.$refs.input.$el.setAttribute('aria-valuenow', value);\n },\n concatValues(val1, val2) {\n if (val1 && val2) {\n let decimalCharIndex = val2.search(this._decimal);\n\n this._decimal.lastIndex = 0;\n\n if (this.suffixChar) {\n return decimalCharIndex !== -1 ? val1.replace(this.suffixChar, '').split(this._decimal)[0] + val2.replace(this.suffixChar, '').slice(decimalCharIndex) + this.suffixChar : val1;\n } else {\n return decimalCharIndex !== -1 ? val1.split(this._decimal)[0] + val2.slice(decimalCharIndex) : val1;\n }\n }\n\n return val1;\n },\n getDecimalLength(value) {\n if (value) {\n const valueSplit = value.split(this._decimal);\n\n if (valueSplit.length === 2) {\n return valueSplit[1].replace(this._suffix, '').trim().replace(/\\s/g, '').replace(this._currency, '').length;\n }\n }\n\n return 0;\n },\n updateModel(event, value) {\n this.writeValue(value, event);\n },\n onInputFocus(event) {\n this.focused = true;\n\n if (!this.disabled && !this.readonly && this.$refs.input.$el.value !== getSelection() && this.highlightOnFocus) {\n event.target.select();\n }\n\n this.$emit('focus', event);\n },\n onInputBlur(event) {\n this.focused = false;\n\n let input = event.target;\n let newValue = this.validateValue(this.parseValue(input.value));\n\n this.$emit('blur', { originalEvent: event, value: input.value });\n this.formField.onBlur?.(event);\n\n input.value = this.formatValue(newValue);\n input.setAttribute('aria-valuenow', newValue);\n this.updateModel(event, newValue);\n\n if (!this.disabled && !this.readonly && this.highlightOnFocus) {\n clearSelection();\n }\n },\n clearTimer() {\n if (this.timer) {\n clearTimeout(this.timer);\n }\n },\n maxBoundry() {\n return this.d_value >= this.max;\n },\n minBoundry() {\n return this.d_value <= this.min;\n }\n },\n computed: {\n upButtonListeners() {\n return {\n mousedown: (event) => this.onUpButtonMouseDown(event),\n mouseup: (event) => this.onUpButtonMouseUp(event),\n mouseleave: (event) => this.onUpButtonMouseLeave(event),\n keydown: (event) => this.onUpButtonKeyDown(event),\n keyup: (event) => this.onUpButtonKeyUp(event)\n };\n },\n downButtonListeners() {\n return {\n mousedown: (event) => this.onDownButtonMouseDown(event),\n mouseup: (event) => this.onDownButtonMouseUp(event),\n mouseleave: (event) => this.onDownButtonMouseLeave(event),\n keydown: (event) => this.onDownButtonKeyDown(event),\n keyup: (event) => this.onDownButtonKeyUp(event)\n };\n },\n formattedValue() {\n const val = !this.d_value && !this.allowEmpty ? 0 : this.d_value;\n\n return this.formatValue(val);\n },\n getFormatter() {\n return this.numberFormat;\n },\n dataP() {\n return cn({\n invalid: this.$invalid,\n fluid: this.$fluid,\n filled: this.$variant === 'filled',\n [this.size]: this.size,\n [this.buttonLayout]: this.showButtons && this.buttonLayout\n });\n }\n },\n components: {\n InputText,\n AngleUpIcon,\n AngleDownIcon\n }\n};\n</script>\n","<template>\n <span :class=\"cx('root')\" v-bind=\"ptmi('root')\" :data-p=\"dataP\">\n <InputText\n ref=\"input\"\n :id=\"inputId\"\n :name=\"$formName\"\n role=\"spinbutton\"\n :class=\"[cx('pcInputText'), inputClass]\"\n :style=\"inputStyle\"\n :value=\"formattedValue\"\n :aria-valuemin=\"min\"\n :aria-valuemax=\"max\"\n :aria-valuenow=\"d_value\"\n :inputmode=\"mode === 'decimal' && !minFractionDigits ? 'numeric' : 'decimal'\"\n :disabled=\"disabled\"\n :readonly=\"readonly\"\n :placeholder=\"placeholder\"\n :aria-labelledby=\"ariaLabelledby\"\n :aria-label=\"ariaLabel\"\n :required=\"required\"\n :size=\"size\"\n :invalid=\"invalid\"\n :variant=\"variant\"\n @input=\"onUserInput\"\n @keydown=\"onInputKeyDown\"\n @keypress=\"onInputKeyPress\"\n @paste=\"onPaste\"\n @click=\"onInputClick\"\n @focus=\"onInputFocus\"\n @blur=\"onInputBlur\"\n :pt=\"ptm('pcInputText')\"\n :unstyled=\"unstyled\"\n :data-p=\"dataP\"\n />\n <span v-if=\"showButtons && buttonLayout === 'stacked'\" :class=\"cx('buttonGroup')\" v-bind=\"ptm('buttonGroup')\" :data-p=\"dataP\">\n <slot name=\"incrementbutton\" :listeners=\"upButtonListeners\">\n <button :class=\"[cx('incrementButton'), incrementButtonClass]\" v-on=\"upButtonListeners\" :disabled=\"disabled\" :tabindex=\"-1\" aria-hidden=\"true\" type=\"button\" v-bind=\"ptm('incrementButton')\" :data-p=\"dataP\">\n <slot :name=\"$slots.incrementicon ? 'incrementicon' : 'incrementbuttonicon'\">\n <component :is=\"incrementIcon || incrementButtonIcon ? 'span' : 'AngleUpIcon'\" :class=\"[incrementIcon, incrementButtonIcon]\" v-bind=\"ptm('incrementIcon')\" data-pc-section=\"incrementicon\" />\n </slot>\n </button>\n </slot>\n <slot name=\"decrementbutton\" :listeners=\"downButtonListeners\">\n <button :class=\"[cx('decrementButton'), decrementButtonClass]\" v-on=\"downButtonListeners\" :disabled=\"disabled\" :tabindex=\"-1\" aria-hidden=\"true\" type=\"button\" v-bind=\"ptm('decrementButton')\" :data-p=\"dataP\">\n <slot :name=\"$slots.decrementicon ? 'decrementicon' : 'decrementbuttonicon'\">\n <component :is=\"decrementIcon || decrementButtonIcon ? 'span' : 'AngleDownIcon'\" :class=\"[decrementIcon, decrementButtonIcon]\" v-bind=\"ptm('decrementIcon')\" data-pc-section=\"decrementicon\" />\n </slot>\n </button>\n </slot>\n </span>\n <slot name=\"incrementbutton\" :listeners=\"upButtonListeners\">\n <button\n v-if=\"showButtons && buttonLayout !== 'stacked'\"\n :class=\"[cx('incrementButton'), incrementButtonClass]\"\n v-on=\"upButtonListeners\"\n :disabled=\"disabled\"\n :tabindex=\"-1\"\n aria-hidden=\"true\"\n type=\"button\"\n v-bind=\"ptm('incrementButton')\"\n :data-p=\"dataP\"\n >\n <slot :name=\"$slots.incrementicon ? 'incrementicon' : 'incrementbuttonicon'\">\n <component :is=\"incrementIcon || incrementButtonIcon ? 'span' : 'AngleUpIcon'