vue-currency-input
Advanced tools
Comparing version 1.22.3 to 2.0.0-beta.0
/** | ||
* Vue Currency Input 1.22.3 | ||
* Vue Currency Input 2.0.0-beta.0 | ||
* (c) 2018-2020 Matthias Stiller | ||
* @license MIT | ||
*/ | ||
var escapeRegExp = function (str) { return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); }; | ||
var removeLeadingZeros = function (str) { return str.replace(/^0+(0$|[^0])/, '$1'); }; | ||
var count = function (str, search) { return (str.match(new RegExp(escapeRegExp(search), 'g')) || []).length; }; | ||
var startsWith = function (str, search) { return str.substring(0, search.length) === search; }; | ||
var substringBefore = function (str, search) { return str.substring(0, str.indexOf(search)); }; | ||
import { getCurrentInstance, isVue3, ref, computed, onMounted, watch } from 'vue-demi'; | ||
var DECIMAL_SYMBOLS = [',', '.', '٫']; | ||
var NumberFormat = function NumberFormat (options) { | ||
var currency = options.currency; | ||
var locale = options.locale; | ||
var precision = options.precision; | ||
var autoDecimalMode = options.autoDecimalMode; | ||
var valueAsInteger = options.valueAsInteger; | ||
var numberFormat = new Intl.NumberFormat(locale, typeof currency === 'string' ? { currency: currency, style: 'currency' } : { minimumFractionDigits: 1 }); | ||
var ps = numberFormat.format(123456); | ||
this.locale = locale; | ||
this.currency = currency; | ||
this.digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(function (i) { return i.toLocaleString(locale); }); | ||
this.decimalSymbol = count(ps, this.digits[0]) ? ps.substr(ps.indexOf(this.digits[6]) + 1, 1) : undefined; | ||
this.groupingSymbol = ps.substr(ps.indexOf(this.digits[3]) + 1, 1); | ||
this.minusSymbol = substringBefore(Number(-1).toLocaleString(locale), this.digits[1]); | ||
if (this.decimalSymbol === undefined) { | ||
this.minimumFractionDigits = this.maximumFractionDigits = 0; | ||
} else if (typeof precision === 'number') { | ||
this.minimumFractionDigits = this.maximumFractionDigits = precision; | ||
} else if (typeof precision === 'object' && !autoDecimalMode && !valueAsInteger) { | ||
this.minimumFractionDigits = precision.min || 0; | ||
this.maximumFractionDigits = precision.max !== undefined ? precision.max : 20; | ||
} else if (typeof currency === 'string') { | ||
this.minimumFractionDigits = numberFormat.resolvedOptions().minimumFractionDigits; | ||
this.maximumFractionDigits = numberFormat.resolvedOptions().maximumFractionDigits; | ||
} else { | ||
this.minimumFractionDigits = this.maximumFractionDigits = 2; | ||
} | ||
if (typeof currency === 'string') { | ||
const escapeRegExp = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); | ||
const removeLeadingZeros = (str) => str.replace(/^0+(0$|[^0])/, '$1'); | ||
const count = (str, search) => (str.match(new RegExp(escapeRegExp(search), 'g')) || []).length; | ||
const startsWith = (str, search) => str.substring(0, search.length) === search; | ||
const substringBefore = (str, search) => str.substring(0, str.indexOf(search)); | ||
const DECIMAL_SYMBOLS = [',', '.', '٫']; | ||
class NumberFormat { | ||
constructor (options) { | ||
const { currency, locale, precision, autoDecimalDigits } = options; | ||
const numberFormat = new Intl.NumberFormat(locale, { currency, style: 'currency' }); | ||
const ps = numberFormat.format(123456); | ||
this.locale = locale; | ||
this.currency = currency; | ||
this.digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map((i) => i.toLocaleString(locale)); | ||
this.decimalSymbol = count(ps, this.digits[0]) ? ps.substr(ps.indexOf(this.digits[6]) + 1, 1) : undefined; | ||
this.groupingSymbol = ps.substr(ps.indexOf(this.digits[3]) + 1, 1); | ||
this.minusSymbol = substringBefore(Number(-1).toLocaleString(locale), this.digits[1]); | ||
if (this.decimalSymbol === undefined) { | ||
this.minimumFractionDigits = this.maximumFractionDigits = 0; | ||
} else if (typeof precision === 'number') { | ||
this.minimumFractionDigits = this.maximumFractionDigits = precision; | ||
} else if (typeof precision === 'object' && !autoDecimalDigits) { | ||
this.minimumFractionDigits = precision.min || 0; | ||
this.maximumFractionDigits = precision.max !== undefined ? precision.max : 20; | ||
} else { | ||
this.minimumFractionDigits = numberFormat.resolvedOptions().minimumFractionDigits; | ||
this.maximumFractionDigits = numberFormat.resolvedOptions().maximumFractionDigits; | ||
} | ||
this.prefix = substringBefore(ps, this.digits[1]); | ||
this.negativePrefix = substringBefore(numberFormat.format(-1), this.digits[1]); | ||
this.suffix = ps.substring(ps.lastIndexOf(this.decimalSymbol ? this.digits[0] : this.digits[6]) + 1); | ||
} else { | ||
this.prefix = (currency || {}).prefix || ''; | ||
this.negativePrefix = "" + (this.minusSymbol) + (this.prefix); | ||
this.suffix = (currency || {}).suffix || ''; | ||
} | ||
}; | ||
NumberFormat.prototype.parse = function parse (str, valueAsInteger) { | ||
if ( valueAsInteger === void 0 ) valueAsInteger = false; | ||
if (str) { | ||
var negative = this.isNegative(str); | ||
str = this.normalizeDigits(str); | ||
str = this.stripCurrencySymbol(str); | ||
str = this.stripMinusSymbol(str); | ||
var fraction = this.decimalSymbol ? ("(" + (escapeRegExp(this.decimalSymbol)) + "\\d*)?") : ''; | ||
var match = str.match(new RegExp(("^" + (this.integerPattern()) + fraction + "$"))); | ||
if (match) { | ||
var number = Number(("" + (negative ? '-' : '') + ((this.onlyDigits(match[1]))) + "." + ((this.onlyDigits(match[3] || ''))))); | ||
return valueAsInteger ? Number(number.toFixed(this.maximumFractionDigits).split('.').join('')) : number | ||
parse (str) { | ||
if (str) { | ||
const negative = this.isNegative(str); | ||
str = this.normalizeDigits(str); | ||
str = this.stripCurrencySymbol(str); | ||
str = this.stripMinusSymbol(str); | ||
const fraction = this.decimalSymbol ? `(${escapeRegExp(this.decimalSymbol)}\\d*)?` : ''; | ||
const match = str.match(new RegExp(`^${this.integerPattern()}${fraction}$`)); | ||
if (match) { | ||
return Number(`${negative ? '-' : ''}${(this.onlyDigits(match[1]))}.${(this.onlyDigits(match[3] || ''))}`) | ||
} | ||
} | ||
return null | ||
} | ||
return null | ||
}; | ||
NumberFormat.prototype.format = function format (number, options) { | ||
if ( options === void 0 ) options = { | ||
minimumFractionDigits: this.minimumFractionDigits, | ||
maximumFractionDigits: this.maximumFractionDigits | ||
}; | ||
if (typeof this.currency === 'string') { | ||
return number.toLocaleString(this.locale, Object.assign({}, {style: 'currency', | ||
currency: this.currency}, | ||
options)) | ||
} else { | ||
return this.insertCurrencySymbol(Math.abs(number).toLocaleString(this.locale, options), number < 0 || (number === 0 && (1 / number < 0))) | ||
format (number, options = { | ||
minimumFractionDigits: this.minimumFractionDigits, | ||
maximumFractionDigits: this.maximumFractionDigits | ||
}) { | ||
return number.toLocaleString(this.locale, { | ||
style: 'currency', | ||
currency: this.currency, | ||
...options | ||
}) | ||
} | ||
}; | ||
NumberFormat.prototype.integerPattern = function integerPattern () { | ||
return ("(0|[1-9]\\d{0,2}(" + (escapeRegExp(this.groupingSymbol)) + "?\\d{3})*)") | ||
}; | ||
NumberFormat.prototype.toFraction = function toFraction (str) { | ||
return ("" + (this.digits[0]) + (this.decimalSymbol) + ((this.onlyLocaleDigits(str.substr(1)).substr(0, this.maximumFractionDigits)))) | ||
}; | ||
NumberFormat.prototype.isFractionIncomplete = function isFractionIncomplete (str) { | ||
return !!this.normalizeDigits(str).match(new RegExp(("^" + (this.integerPattern()) + (escapeRegExp(this.decimalSymbol)) + "$"))) | ||
}; | ||
NumberFormat.prototype.isNegative = function isNegative (str) { | ||
return startsWith(str, this.negativePrefix) || startsWith(str.replace('-', this.minusSymbol), this.minusSymbol) | ||
}; | ||
NumberFormat.prototype.insertCurrencySymbol = function insertCurrencySymbol (str, negative) { | ||
return ("" + (negative ? this.negativePrefix : this.prefix) + str + (this.suffix)) | ||
}; | ||
NumberFormat.prototype.stripMinusSymbol = function stripMinusSymbol (str) { | ||
return str.replace('-', this.minusSymbol).replace(this.minusSymbol, '') | ||
}; | ||
NumberFormat.prototype.stripCurrencySymbol = function stripCurrencySymbol (str) { | ||
return str.replace(this.negativePrefix, '').replace(this.prefix, '').replace(this.suffix, '') | ||
}; | ||
NumberFormat.prototype.normalizeDecimalSymbol = function normalizeDecimalSymbol (str, from) { | ||
var this$1 = this; | ||
DECIMAL_SYMBOLS.forEach(function (s) { | ||
str = str.substr(0, from) + str.substr(from).replace(s, this$1.decimalSymbol); | ||
}); | ||
return str | ||
}; | ||
NumberFormat.prototype.normalizeDigits = function normalizeDigits (str) { | ||
if (this.digits[0] !== '0') { | ||
this.digits.forEach(function (digit, index) { | ||
str = str.replace(new RegExp(digit, 'g'), index); | ||
}); | ||
integerPattern () { | ||
return `(0|[1-9]\\d{0,2}(${escapeRegExp(this.groupingSymbol)}?\\d{3})*)` | ||
} | ||
return str | ||
}; | ||
NumberFormat.prototype.onlyDigits = function onlyDigits (str) { | ||
return this.normalizeDigits(str).replace(/\D+/g, '') | ||
}; | ||
NumberFormat.prototype.onlyLocaleDigits = function onlyLocaleDigits (str) { | ||
return str.replace(new RegExp(("[^" + (this.digits.join('')) + "]*"), 'g'), '') | ||
}; | ||
var DEFAULT_OPTIONS = { | ||
locale: undefined, | ||
currency: 'EUR', | ||
valueAsInteger: false, | ||
distractionFree: true, | ||
precision: undefined, | ||
autoDecimalMode: false, | ||
valueRange: undefined, | ||
allowNegative: true | ||
}; | ||
var parse = function (formattedValue, options) { | ||
var mergedOptions = Object.assign({}, DEFAULT_OPTIONS, options); | ||
return new NumberFormat(mergedOptions).parse(formattedValue, mergedOptions.valueAsInteger) | ||
}; | ||
var getValue = function (ref) { return (ref.$el || ref).$ci.getValue(); }; | ||
var setValue = function (ref, value) { | ||
(ref.$el || ref).$ci.setValue(value); | ||
}; | ||
var equal = function (a, b) { | ||
if (a === b) { | ||
return true | ||
toFraction (str) { | ||
return `${this.digits[0]}${this.decimalSymbol}${(this.onlyLocaleDigits(str.substr(1)).substr(0, this.maximumFractionDigits))}` | ||
} | ||
if (!a || !b || typeof a !== 'object' || typeof b !== 'object') { | ||
return false | ||
isFractionIncomplete (str) { | ||
return !!this.normalizeDigits(str).match(new RegExp(`^${this.integerPattern()}${escapeRegExp(this.decimalSymbol)}$`)) | ||
} | ||
var keys = Object.keys(a); | ||
if (keys.length !== Object.keys(b).length) { | ||
return false | ||
isNegative (str) { | ||
return startsWith(str, this.negativePrefix) || startsWith(str.replace('-', this.minusSymbol), this.minusSymbol) | ||
} | ||
if (!keys.every(Object.prototype.hasOwnProperty.bind(b))) { | ||
return false | ||
insertCurrencySymbol (str, negative) { | ||
return `${negative ? this.negativePrefix : this.prefix}${str}${this.suffix}` | ||
} | ||
return keys.every(function (key) { return equal(a[key], b[key]); }) | ||
}; | ||
var DefaultNumberMask = function DefaultNumberMask (numberFormat) { | ||
this.numberFormat = numberFormat; | ||
}; | ||
DefaultNumberMask.prototype.conformToMask = function conformToMask (str, previousConformedValue) { | ||
var this$1 = this; | ||
if ( previousConformedValue === void 0 ) previousConformedValue = ''; | ||
var negative = this.numberFormat.isNegative(str); | ||
var checkIncompleteValue = function (str) { | ||
if (str === '' && negative && previousConformedValue !== this$1.numberFormat.negativePrefix) { | ||
return '' | ||
} else if (this$1.numberFormat.maximumFractionDigits > 0) { | ||
if (this$1.numberFormat.isFractionIncomplete(str)) { | ||
return str | ||
} else if (startsWith(str, this$1.numberFormat.decimalSymbol)) { | ||
return this$1.numberFormat.toFraction(str) | ||
} | ||
} | ||
return null | ||
}; | ||
var value = str; | ||
value = this.numberFormat.stripCurrencySymbol(value); | ||
value = this.numberFormat.stripMinusSymbol(value); | ||
var incompleteValue = checkIncompleteValue(value); | ||
if (incompleteValue != null) { | ||
return this.numberFormat.insertCurrencySymbol(incompleteValue, negative) | ||
stripMinusSymbol (str) { | ||
return str.replace('-', this.minusSymbol).replace(this.minusSymbol, '') | ||
} | ||
var ref = value.split(this.numberFormat.decimalSymbol); | ||
var integer = ref[0]; | ||
var fraction = ref.slice(1); | ||
var integerDigits = removeLeadingZeros(this.numberFormat.onlyDigits(integer)); | ||
var fractionDigits = this.numberFormat.onlyDigits(fraction.join('')).substr(0, this.numberFormat.maximumFractionDigits); | ||
var invalidFraction = fraction.length > 0 && fractionDigits.length === 0; | ||
var invalidNegativeValue = integerDigits === '' && negative && (previousConformedValue === str.slice(0, -1) || previousConformedValue !== this.numberFormat.negativePrefix); | ||
if (invalidFraction || invalidNegativeValue) { | ||
return previousConformedValue | ||
} else if (integerDigits.match(/\d+/)) { | ||
return { | ||
numberValue: Number(("" + (negative ? '-' : '') + integerDigits + "." + fractionDigits)), | ||
fractionDigits: fractionDigits | ||
stripCurrencySymbol (str) { | ||
return str.replace(this.negativePrefix, '').replace(this.prefix, '').replace(this.suffix, '') | ||
} | ||
normalizeDecimalSymbol (str, from) { | ||
DECIMAL_SYMBOLS.forEach((s) => { | ||
str = str.substr(0, from) + str.substr(from).replace(s, this.decimalSymbol); | ||
}); | ||
return str | ||
} | ||
normalizeDigits (str) { | ||
if (this.digits[0] !== '0') { | ||
this.digits.forEach((digit, index) => { | ||
str = str.replace(new RegExp(digit, 'g'), index); | ||
}); | ||
} | ||
} else { | ||
return '' | ||
return str | ||
} | ||
}; | ||
var AutoDecimalModeNumberMask = function AutoDecimalModeNumberMask (numberFormat) { | ||
this.numberFormat = numberFormat; | ||
}; | ||
AutoDecimalModeNumberMask.prototype.conformToMask = function conformToMask (str) { | ||
if (str === '') { | ||
return '' | ||
onlyDigits (str) { | ||
return this.normalizeDigits(str).replace(/\D+/g, '') | ||
} | ||
var negative = this.numberFormat.isNegative(str); | ||
var numberValue = this.numberFormat.stripMinusSymbol(str) === '' | ||
? -0 | ||
: Number(("" + (negative ? '-' : '') + (removeLeadingZeros(this.numberFormat.onlyDigits(str))))) / Math.pow(10, this.numberFormat.minimumFractionDigits); | ||
return { | ||
numberValue: numberValue, | ||
fractionDigits: numberValue.toFixed(this.numberFormat.minimumFractionDigits).slice(-this.numberFormat.minimumFractionDigits) | ||
onlyLocaleDigits (str) { | ||
return str.replace(new RegExp(`[^${this.digits.join('')}]*`, 'g'), '') | ||
} | ||
}; | ||
} | ||
var getCaretPositionAfterFormat = function (newValue, inputtedValue, caretPosition, numberFormat, options) { | ||
var prefix = numberFormat.prefix; | ||
var suffix = numberFormat.suffix; | ||
var decimalSymbol = numberFormat.decimalSymbol; | ||
var maximumFractionDigits = numberFormat.maximumFractionDigits; | ||
var groupingSymbol = numberFormat.groupingSymbol; | ||
var decimalSymbolPosition = inputtedValue.indexOf(decimalSymbol) + 1; | ||
var caretPositionFromLeft = inputtedValue.length - caretPosition; | ||
if (Math.abs(newValue.length - inputtedValue.length) > 1 && caretPosition <= decimalSymbolPosition) { | ||
return newValue.indexOf(decimalSymbol) + 1 | ||
} else if (newValue.substr(caretPosition, 1) === groupingSymbol && count(newValue, groupingSymbol) === count(inputtedValue, groupingSymbol) + 1) { | ||
return newValue.length - caretPositionFromLeft - 1 | ||
} else { | ||
if (!options.autoDecimalMode && decimalSymbolPosition !== 0 && caretPosition > decimalSymbolPosition) { | ||
if (numberFormat.onlyDigits(inputtedValue.substr(decimalSymbolPosition)).length - 1 === maximumFractionDigits) { | ||
caretPositionFromLeft -= 1; | ||
class DefaultNumberMask { | ||
constructor (numberFormat) { | ||
this.numberFormat = numberFormat; | ||
} | ||
conformToMask (str, previousConformedValue = '') { | ||
const negative = this.numberFormat.isNegative(str); | ||
const checkIncompleteValue = (str) => { | ||
if (str === '' && negative && previousConformedValue !== this.numberFormat.negativePrefix) { | ||
return '' | ||
} else if (this.numberFormat.maximumFractionDigits > 0) { | ||
if (this.numberFormat.isFractionIncomplete(str)) { | ||
return str | ||
} else if (startsWith(str, this.numberFormat.decimalSymbol)) { | ||
return this.numberFormat.toFraction(str) | ||
} | ||
} | ||
return null | ||
}; | ||
let value = str; | ||
value = this.numberFormat.stripCurrencySymbol(value); | ||
value = this.numberFormat.stripMinusSymbol(value); | ||
const incompleteValue = checkIncompleteValue(value); | ||
if (incompleteValue != null) { | ||
return this.numberFormat.insertCurrencySymbol(incompleteValue, negative) | ||
} | ||
return options.distractionFree.hideCurrencySymbol | ||
? newValue.length - caretPositionFromLeft | ||
: Math.max(newValue.length - Math.max(caretPositionFromLeft, suffix.length), prefix.length === 0 ? 0 : prefix.length + 1) | ||
const [integer, ...fraction] = value.split(this.numberFormat.decimalSymbol); | ||
const integerDigits = removeLeadingZeros(this.numberFormat.onlyDigits(integer)); | ||
const fractionDigits = this.numberFormat.onlyDigits(fraction.join('')).substr(0, this.numberFormat.maximumFractionDigits); | ||
const invalidFraction = fraction.length > 0 && fractionDigits.length === 0; | ||
const invalidNegativeValue = integerDigits === '' && negative && (previousConformedValue === str.slice(0, -1) || previousConformedValue !== this.numberFormat.negativePrefix); | ||
if (invalidFraction || invalidNegativeValue) { | ||
return previousConformedValue | ||
} else if (integerDigits.match(/\d+/)) { | ||
return { | ||
numberValue: Number(`${negative ? '-' : ''}${integerDigits}.${fractionDigits}`), | ||
fractionDigits | ||
} | ||
} else { | ||
return '' | ||
} | ||
} | ||
}; | ||
var getDistractionFreeCaretPosition = function (numberFormat, options, value, caretPosition) { | ||
var result = caretPosition; | ||
if (options.distractionFree.hideCurrencySymbol) { | ||
result -= numberFormat.prefix.length; | ||
} | ||
class AutoDecimalDigitsNumberMask { | ||
constructor (numberFormat) { | ||
this.numberFormat = numberFormat; | ||
} | ||
if (options.distractionFree.hideGroupingSymbol) { | ||
result -= count(value.substring(0, caretPosition), numberFormat.groupingSymbol); | ||
conformToMask (str) { | ||
if (str === '') { | ||
return '' | ||
} | ||
const negative = this.numberFormat.isNegative(str); | ||
const numberValue = this.numberFormat.stripMinusSymbol(str) === '' | ||
? -0 | ||
: Number(`${negative ? '-' : ''}${removeLeadingZeros(this.numberFormat.onlyDigits(str))}`) / Math.pow(10, this.numberFormat.minimumFractionDigits); | ||
return { | ||
numberValue, | ||
fractionDigits: numberValue.toFixed(this.numberFormat.minimumFractionDigits).slice(-this.numberFormat.minimumFractionDigits) | ||
} | ||
} | ||
return Math.max(0, result) | ||
}; | ||
} | ||
var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1; | ||
var NumberInput = function NumberInput (el, options, callbackFns) { | ||
this.el = el; | ||
this.callbackFns = callbackFns; | ||
this.numberValue = null; | ||
this.addEventListener(); | ||
this.init(options); | ||
this.setValue(this.currencyFormat.parse(this.el.value)); | ||
const MAX_SAFE_INTEGER = Math.pow(2, 53) - 1; | ||
const DEFAULT_OPTIONS = { | ||
locale: undefined, | ||
currency: undefined, | ||
valueAsInteger: false, | ||
distractionFree: true, | ||
precision: undefined, | ||
autoDecimalDigits: false, | ||
valueRange: undefined, | ||
allowNegative: true | ||
}; | ||
NumberInput.prototype.init = function init (newOptions) { | ||
var options = Object.assign({}, newOptions); | ||
var distractionFree = options.distractionFree; | ||
var autoDecimalMode = options.autoDecimalMode; | ||
var valueRange = options.valueRange; | ||
if (typeof distractionFree === 'boolean') { | ||
options.distractionFree = { | ||
hideCurrencySymbol: distractionFree, | ||
hideNegligibleDecimalDigits: distractionFree, | ||
hideGroupingSymbol: distractionFree | ||
}; | ||
class NumberInput { | ||
constructor (el, options, callbackFns) { | ||
this.el = el; | ||
this.callbackFns = callbackFns; | ||
this.numberValue = null; | ||
this.addEventListener(); | ||
this.init(options); | ||
this.setValue(this.currencyFormat.parse(this.el.value)); | ||
} | ||
if (valueRange) { | ||
options.valueRange = { | ||
min: valueRange.min !== undefined ? Math.max(valueRange.min, -MAX_SAFE_INTEGER) : -MAX_SAFE_INTEGER, | ||
max: valueRange.max !== undefined ? Math.min(valueRange.max, MAX_SAFE_INTEGER) : MAX_SAFE_INTEGER | ||
}; | ||
} else { | ||
options.valueRange = { | ||
min: -MAX_SAFE_INTEGER, | ||
max: MAX_SAFE_INTEGER | ||
}; | ||
init (options) { | ||
const { distractionFree, autoDecimalDigits, valueRange, valueAsInteger, allowNegative } = { ...DEFAULT_OPTIONS, ...options }; | ||
this.autoDecimalDigits = autoDecimalDigits; | ||
this.valueAsInteger = valueAsInteger; | ||
this.allowNegative = allowNegative; | ||
this.hideCurrencySymbolOnFocus = distractionFree === true || !!(distractionFree || {}).hideCurrencySymbol; | ||
this.hideNegligibleDecimalDigitsOnFocus = distractionFree === true || !!(distractionFree || {}).hideNegligibleDecimalDigits; | ||
this.hideGroupingSymbolOnFocus = distractionFree === true || !!(distractionFree || {}).hideGroupingSymbol; | ||
if (valueRange) { | ||
this.valueRange = { | ||
min: valueRange.min !== undefined ? Math.max(valueRange.min, -MAX_SAFE_INTEGER) : -MAX_SAFE_INTEGER, | ||
max: valueRange.max !== undefined ? Math.min(valueRange.max, MAX_SAFE_INTEGER) : MAX_SAFE_INTEGER | ||
}; | ||
} else { | ||
this.valueRange = { | ||
min: -MAX_SAFE_INTEGER, | ||
max: MAX_SAFE_INTEGER | ||
}; | ||
} | ||
if (autoDecimalDigits) { | ||
this.hideNegligibleDecimalDigitsOnFocus = false; | ||
this.el.setAttribute('inputmode', 'numeric'); | ||
} else { | ||
this.el.setAttribute('inputmode', 'decimal'); | ||
} | ||
this.currencyFormat = new NumberFormat(options); | ||
this.numberMask = autoDecimalDigits ? new AutoDecimalDigitsNumberMask(this.currencyFormat) : new DefaultNumberMask(this.currencyFormat); | ||
} | ||
if (autoDecimalMode) { | ||
options.distractionFree.hideNegligibleDecimalDigits = false; | ||
this.el.setAttribute('inputmode', 'numeric'); | ||
} else { | ||
this.el.setAttribute('inputmode', 'decimal'); | ||
setOptions (options) { | ||
this.init(options); | ||
this.applyFixedFractionFormat(this.numberValue, true); | ||
} | ||
this.options = options; | ||
this.currencyFormat = new NumberFormat(this.options); | ||
this.numberMask = options.autoDecimalMode ? new AutoDecimalModeNumberMask(this.currencyFormat) : new DefaultNumberMask(this.currencyFormat); | ||
}; | ||
NumberInput.prototype.setOptions = function setOptions (options) { | ||
this.init(options); | ||
this.applyFixedFractionFormat(this.numberValue, true); | ||
}; | ||
NumberInput.prototype.applyFixedFractionFormat = function applyFixedFractionFormat (number, forcedChange) { | ||
this.format(number != null ? this.currencyFormat.format(this.validateValueRange(number)) : null); | ||
if (number !== this.numberValue || forcedChange) { | ||
this.callbackFns.onChange(this.getValue()); | ||
applyFixedFractionFormat (number, forcedChange) { | ||
this.format(number != null ? this.currencyFormat.format(this.validateValueRange(number)) : null); | ||
if (number !== this.numberValue || forcedChange) { | ||
this.callbackFns.onChange(this.getValue()); | ||
} | ||
} | ||
}; | ||
NumberInput.prototype.getValue = function getValue () { | ||
return this.currencyFormat.parse(this.formattedValue, this.options.valueAsInteger) | ||
}; | ||
NumberInput.prototype.setValue = function setValue (value) { | ||
var newValue = this.options.valueAsInteger && value != null ? value / Math.pow(10, this.currencyFormat.maximumFractionDigits) : value; | ||
if (newValue !== this.numberValue) { | ||
this.applyFixedFractionFormat(newValue); | ||
getValue () { | ||
const numberValue = this.valueAsInteger && this.numberValue != null ? Number(this.numberValue.toFixed(this.currencyFormat.maximumFractionDigits).split('.').join('')) : this.numberValue; | ||
return { | ||
number: numberValue, | ||
formatted: this.formattedValue | ||
} | ||
} | ||
}; | ||
NumberInput.prototype.validateValueRange = function validateValueRange (value) { | ||
var ref = this.options.valueRange; | ||
var min = ref.min; | ||
var max = ref.max; | ||
return Math.min(Math.max(value, min), max) | ||
}; | ||
NumberInput.prototype.updateInputValue = function updateInputValue (value, hideNegligibleDecimalDigits) { | ||
if ( hideNegligibleDecimalDigits === void 0 ) hideNegligibleDecimalDigits = false; | ||
if (value != null) { | ||
if (this.decimalSymbolInsertedAt !== undefined) { | ||
value = this.currencyFormat.normalizeDecimalSymbol(value, this.decimalSymbolInsertedAt); | ||
this.decimalSymbolInsertedAt = undefined; | ||
setValue (value) { | ||
const newValue = this.valueAsInteger && value != null ? value / Math.pow(10, this.currencyFormat.maximumFractionDigits) : value; | ||
if (newValue !== this.numberValue) { | ||
this.applyFixedFractionFormat(newValue); | ||
} | ||
var conformedValue = this.numberMask.conformToMask(value, this.formattedValue); | ||
var formattedValue; | ||
if (typeof conformedValue === 'object') { | ||
var numberValue = conformedValue.numberValue; | ||
var fractionDigits = conformedValue.fractionDigits; | ||
var ref = this.currencyFormat; | ||
var maximumFractionDigits = ref.maximumFractionDigits; | ||
var minimumFractionDigits = ref.minimumFractionDigits; | ||
if (this.focus) { | ||
minimumFractionDigits = maximumFractionDigits; | ||
} | ||
validateValueRange (value) { | ||
const { min, max } = this.valueRange; | ||
return Math.min(Math.max(value, min), max) | ||
} | ||
format (value, hideNegligibleDecimalDigits = false) { | ||
if (value != null) { | ||
if (this.decimalSymbolInsertedAt !== undefined) { | ||
value = this.currencyFormat.normalizeDecimalSymbol(value, this.decimalSymbolInsertedAt); | ||
this.decimalSymbolInsertedAt = undefined; | ||
} | ||
minimumFractionDigits = hideNegligibleDecimalDigits | ||
? fractionDigits.replace(/0+$/, '').length | ||
: Math.min(minimumFractionDigits, fractionDigits.length); | ||
formattedValue = numberValue > MAX_SAFE_INTEGER | ||
? this.formattedValue | ||
: this.currencyFormat.format(numberValue, { | ||
useGrouping: !(this.focus && this.options.distractionFree.hideGroupingSymbol), | ||
minimumFractionDigits: minimumFractionDigits, | ||
maximumFractionDigits: maximumFractionDigits | ||
}); | ||
const conformedValue = this.numberMask.conformToMask(value, this.formattedValue); | ||
let formattedValue; | ||
if (typeof conformedValue === 'object') { | ||
const { numberValue, fractionDigits } = conformedValue; | ||
let { maximumFractionDigits, minimumFractionDigits } = this.currencyFormat; | ||
if (this.focus) { | ||
minimumFractionDigits = maximumFractionDigits; | ||
} | ||
minimumFractionDigits = hideNegligibleDecimalDigits | ||
? fractionDigits.replace(/0+$/, '').length | ||
: Math.min(minimumFractionDigits, fractionDigits.length); | ||
formattedValue = numberValue > MAX_SAFE_INTEGER | ||
? this.formattedValue | ||
: this.currencyFormat.format(numberValue, { | ||
useGrouping: !(this.focus && this.hideGroupingSymbolOnFocus), | ||
minimumFractionDigits, | ||
maximumFractionDigits | ||
}); | ||
} else { | ||
formattedValue = conformedValue; | ||
} | ||
if (!this.allowNegative) { | ||
formattedValue = formattedValue.replace(this.currencyFormat.negativePrefix, this.currencyFormat.prefix); | ||
} | ||
if (this.focus && this.hideCurrencySymbolOnFocus) { | ||
formattedValue = formattedValue | ||
.replace(this.currencyFormat.negativePrefix, this.currencyFormat.minusSymbol) | ||
.replace(this.currencyFormat.prefix, '') | ||
.replace(this.currencyFormat.suffix, ''); | ||
} | ||
this.el.value = formattedValue; | ||
this.numberValue = this.currencyFormat.parse(formattedValue); | ||
} else { | ||
formattedValue = conformedValue; | ||
this.el.value = this.numberValue = null; | ||
} | ||
if (!this.options.allowNegative) { | ||
formattedValue = formattedValue.replace(this.currencyFormat.negativePrefix, this.currencyFormat.prefix); | ||
} | ||
if (this.focus && this.options.distractionFree.hideCurrencySymbol) { | ||
formattedValue = formattedValue | ||
.replace(this.currencyFormat.negativePrefix, this.currencyFormat.minusSymbol) | ||
.replace(this.currencyFormat.prefix, '') | ||
.replace(this.currencyFormat.suffix, ''); | ||
} | ||
this.el.value = formattedValue; | ||
this.numberValue = this.currencyFormat.parse(formattedValue); | ||
} else { | ||
this.el.value = this.numberValue = null; | ||
this.formattedValue = this.el.value; | ||
this.callbackFns.onInput(this.getValue()); | ||
} | ||
this.formattedValue = this.el.value; | ||
}; | ||
NumberInput.prototype.format = function format (value) { | ||
this.updateInputValue(value); | ||
this.callbackFns.onInput(this.getValue()); | ||
}; | ||
NumberInput.prototype.addEventListener = function addEventListener () { | ||
var this$1 = this; | ||
this.el.addEventListener('input', function () { | ||
var ref = this$1.el; | ||
var value = ref.value; | ||
var selectionStart = ref.selectionStart; | ||
this$1.format(value); | ||
if (this$1.focus) { | ||
this$1.setCaretPosition(getCaretPositionAfterFormat(this$1.formattedValue, value, selectionStart, this$1.currencyFormat, this$1.options)); | ||
} | ||
}, { capture: true }); | ||
this.el.addEventListener('focus', function () { | ||
this$1.focus = true; | ||
var ref = this$1.options.distractionFree; | ||
var hideCurrencySymbol = ref.hideCurrencySymbol; | ||
var hideGroupingSymbol = ref.hideGroupingSymbol; | ||
var hideNegligibleDecimalDigits = ref.hideNegligibleDecimalDigits; | ||
if (hideCurrencySymbol || hideGroupingSymbol || hideNegligibleDecimalDigits) { | ||
setTimeout(function () { | ||
var ref = this$1.el; | ||
var value = ref.value; | ||
var selectionStart = ref.selectionStart; | ||
var selectionEnd = ref.selectionEnd; | ||
if (value) { | ||
this$1.updateInputValue(this$1.el.value, hideNegligibleDecimalDigits); | ||
addEventListener () { | ||
this.el.addEventListener('input', () => { | ||
const { value, selectionStart } = this.el; | ||
this.format(value); | ||
if (this.focus) { | ||
const getCaretPositionAfterFormat = () => { | ||
const { prefix, suffix, decimalSymbol, maximumFractionDigits, groupingSymbol } = this.currencyFormat; | ||
let caretPositionFromLeft = value.length - selectionStart; | ||
const newValueLength = this.formattedValue.length; | ||
if (this.formattedValue.substr(selectionStart, 1) === groupingSymbol && count(this.formattedValue, groupingSymbol) === count(value, groupingSymbol) + 1) { | ||
return newValueLength - caretPositionFromLeft - 1 | ||
} | ||
if (decimalSymbol) { | ||
const decimalSymbolPosition = value.indexOf(decimalSymbol) + 1; | ||
if (Math.abs(newValueLength - value.length) > 1 && selectionStart <= decimalSymbolPosition) { | ||
return this.formattedValue.indexOf(decimalSymbol) + 1 | ||
} else { | ||
if (!this.autoDecimalDigits && selectionStart > decimalSymbolPosition) { | ||
if (this.currencyFormat.onlyDigits(value.substr(decimalSymbolPosition)).length - 1 === maximumFractionDigits) { | ||
caretPositionFromLeft -= 1; | ||
} | ||
} | ||
} | ||
} | ||
return this.hideCurrencySymbolOnFocus ? newValueLength - caretPositionFromLeft : Math.max(newValueLength - Math.max(caretPositionFromLeft, suffix.length), prefix.length) | ||
}; | ||
this.setCaretPosition(getCaretPositionAfterFormat()); | ||
} | ||
}, { capture: true }); | ||
this.el.addEventListener('focus', () => { | ||
this.focus = true; | ||
setTimeout(() => { | ||
const { value, selectionStart, selectionEnd } = this.el; | ||
if ((this.hideCurrencySymbolOnFocus || this.hideGroupingSymbolOnFocus || this.hideNegligibleDecimalDigitsOnFocus) && value) { | ||
this.format(value, this.hideNegligibleDecimalDigitsOnFocus); | ||
} | ||
if (Math.abs(selectionStart - selectionEnd) > 0) { | ||
this$1.setCaretPosition(0, this$1.el.value.length); | ||
this.setCaretPosition(0, this.el.value.length); | ||
} else { | ||
this$1.setCaretPosition(getDistractionFreeCaretPosition(this$1.currencyFormat, this$1.options, value, selectionStart)); | ||
const getSelectionStart = () => { | ||
const { prefix, suffix, groupingSymbol } = this.currencyFormat; | ||
if (!this.hideCurrencySymbolOnFocus) { | ||
if (selectionStart > value.length - suffix.length) { | ||
return this.formattedValue.length - suffix.length | ||
} else if (selectionStart < prefix.length) { | ||
return prefix.length | ||
} | ||
} | ||
let result = selectionStart; | ||
if (this.hideCurrencySymbolOnFocus) { | ||
result -= prefix.length; | ||
} | ||
if (this.hideGroupingSymbolOnFocus) { | ||
result -= count(value.substring(0, selectionStart), groupingSymbol); | ||
} | ||
return result | ||
}; | ||
this.setCaretPosition(getSelectionStart()); | ||
} | ||
}); | ||
} | ||
}); | ||
this.el.addEventListener('keypress', function (e) { | ||
if (DECIMAL_SYMBOLS.includes(e.key)) { | ||
this$1.decimalSymbolInsertedAt = this$1.el.selectionStart; | ||
} | ||
}); | ||
this.el.addEventListener('blur', function () { | ||
this$1.focus = false; | ||
if (this$1.numberValue != null) { | ||
this$1.applyFixedFractionFormat(this$1.numberValue); | ||
} | ||
}); | ||
this.el.addEventListener('change', function () { | ||
this$1.callbackFns.onChange(this$1.getValue()); | ||
}); | ||
}; | ||
NumberInput.prototype.setCaretPosition = function setCaretPosition (start, end) { | ||
if ( end === void 0 ) end = start; | ||
this.el.setSelectionRange(start, end); }; | ||
var directive = { | ||
bind: function bind (el, ref, vnode) { | ||
var optionsFromBinding = ref.value; | ||
var inputElement = el.tagName.toLowerCase() === 'input' ? el : el.querySelector('input'); | ||
if (!inputElement) { | ||
throw new Error('No input element found') | ||
} | ||
var options = Object.assign({}, DEFAULT_OPTIONS, | ||
(vnode.context.$ci || {}).globalOptions, | ||
optionsFromBinding); | ||
var listeners = (vnode.data && vnode.data.on) || (vnode.componentOptions && vnode.componentOptions.listeners) || {}; | ||
var emit = function (event, data) { | ||
if (listeners[event]) { | ||
listeners[event](vnode.componentOptions ? data : { target: { value: data } }); | ||
}); | ||
this.el.addEventListener('keypress', (e) => { | ||
if (DECIMAL_SYMBOLS.includes(e.key)) { | ||
this.decimalSymbolInsertedAt = this.el.selectionStart; | ||
} | ||
}; | ||
el.$ci = new NumberInput(inputElement, options, { | ||
onChange: function () { emit('change', inputElement.value); }, | ||
onInput: function () { emit('input', inputElement.value); } | ||
}); | ||
}, | ||
componentUpdated: function componentUpdated (el, ref) { | ||
var value = ref.value; | ||
var oldValue = ref.oldValue; | ||
if (!equal(value, oldValue)) { | ||
el.$ci.setOptions(value); | ||
} | ||
this.el.addEventListener('blur', () => { | ||
this.focus = false; | ||
if (this.numberValue != null) { | ||
this.applyFixedFractionFormat(this.numberValue); | ||
} | ||
}); | ||
this.el.addEventListener('change', () => { | ||
this.callbackFns.onChange(this.getValue()); | ||
}); | ||
} | ||
}; | ||
setCaretPosition (start, end = start) { this.el.setSelectionRange(start, end); } | ||
} | ||
var component = { | ||
render: function render (h) { | ||
var this$1 = this; | ||
return h('input', { | ||
directives: [{ | ||
name: 'currency', | ||
value: this.options | ||
}], | ||
on: Object.assign({}, this.$listeners, | ||
{change: function () { | ||
this$1.$emit('change', getValue(this$1.$el)); | ||
}, | ||
input: function () { | ||
var numberValue = getValue(this$1.$el); | ||
if (this$1.value !== numberValue) { | ||
this$1.$emit('input', numberValue); | ||
const findInput = (el) => el.tagName.toLowerCase() === 'input' ? el : el.querySelector('input'); | ||
var useCurrencyInput = ({ inputRef, props, emit }) => { | ||
let numberInput; | ||
const currentInstance = getCurrentInstance(); | ||
const lazy = isVue3 && (currentInstance.attrs.modelModifiers || {}).lazy; | ||
const inputEvent = isVue3 ? 'update:modelValue' : 'input'; | ||
const changeEvent = isVue3 ? 'update:modelValue' : 'change'; | ||
const formattedValue = ref(null); | ||
const numberValue = computed(() => props[isVue3 ? 'modelValue' : 'value']); | ||
const options = computed(() => Object.keys(DEFAULT_OPTIONS).reduce((options, key) => { | ||
if (props[key] !== undefined) { | ||
options[key] = props[key]; | ||
} | ||
return options | ||
}, {})); | ||
onMounted(() => { | ||
if (inputRef.value) { | ||
const input = '$el' in inputRef.value ? findInput(inputRef.value.$el) : inputRef.value; | ||
if (input == null) { | ||
throw new Error('No input element found') | ||
} else { | ||
numberInput = new NumberInput(input, options.value, { | ||
onInput (value) { | ||
if (!lazy && numberValue.value !== value.number) { | ||
emit(inputEvent, value.number); | ||
} | ||
formattedValue.value = value.formatted; | ||
}, | ||
onChange (value) { | ||
emit(changeEvent, value.number); | ||
formattedValue.value = value.formatted; | ||
} | ||
}}) | ||
}) | ||
}, | ||
directives: { | ||
currency: directive | ||
}, | ||
name: 'CurrencyInput', | ||
props: { | ||
value: { | ||
type: Number, | ||
default: null | ||
}, | ||
locale: { | ||
type: String, | ||
default: undefined | ||
}, | ||
currency: { | ||
type: [String, Object], | ||
default: undefined | ||
}, | ||
distractionFree: { | ||
type: [Boolean, Object], | ||
default: undefined | ||
}, | ||
precision: { | ||
type: [Number, Object], | ||
default: undefined | ||
}, | ||
autoDecimalMode: { | ||
type: Boolean, | ||
default: undefined | ||
}, | ||
valueAsInteger: { | ||
type: Boolean, | ||
default: undefined | ||
}, | ||
valueRange: { | ||
type: Object, | ||
default: undefined | ||
}, | ||
allowNegative: { | ||
type: Boolean, | ||
default: undefined | ||
}); | ||
numberInput.setValue(numberValue.value); | ||
} | ||
} | ||
}, | ||
mounted: function mounted () { | ||
this.setValue(this.value); | ||
}, | ||
computed: { | ||
options: function options () { | ||
var this$1 = this; | ||
var options = Object.assign({}, DEFAULT_OPTIONS, | ||
(this.$ci || {}).globalOptions); | ||
Object.keys(DEFAULT_OPTIONS).forEach(function (key) { | ||
if (this$1[key] !== undefined) { | ||
options[key] = this$1[key]; | ||
} | ||
}); | ||
return options | ||
} | ||
}, | ||
watch: { | ||
value: 'setValue' | ||
}, | ||
methods: { | ||
setValue: function setValue$1 (value) { | ||
setValue(this.$el, value); | ||
} | ||
} | ||
}); | ||
watch(numberValue, (value) => { | ||
numberInput.setValue(value); | ||
}); | ||
watch(options, (options) => { | ||
numberInput.setOptions(options); | ||
}); | ||
return { formattedValue } | ||
}; | ||
var plugin = { | ||
install: function install (Vue, ref) { | ||
if ( ref === void 0 ) ref = {}; | ||
var componentName = ref.componentName; if ( componentName === void 0 ) componentName = component.name; | ||
var directiveName = ref.directiveName; if ( directiveName === void 0 ) directiveName = 'currency'; | ||
var globalOptions = ref.globalOptions; if ( globalOptions === void 0 ) globalOptions = {}; | ||
Vue.component(componentName, component); | ||
Vue.directive(directiveName, directive); | ||
Vue.prototype.$ci = { | ||
parse: function (formattedValue, options) { return parse(formattedValue, Object.assign({}, globalOptions, options)); }, | ||
getValue: getValue, | ||
setValue: setValue, | ||
globalOptions: globalOptions | ||
}; | ||
} | ||
}; | ||
if (typeof window !== 'undefined' && window.Vue) { | ||
window.Vue.use(plugin); | ||
} | ||
export default plugin; | ||
export { directive as CurrencyDirective, component as CurrencyInput, getValue, parse, setValue }; | ||
export default useCurrencyInput; |
/** | ||
* Vue Currency Input 1.22.3 | ||
* Vue Currency Input 2.0.0-beta.0 | ||
* (c) 2018-2020 Matthias Stiller | ||
@@ -7,573 +7,416 @@ * @license MIT | ||
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | ||
typeof define === 'function' && define.amd ? define(['exports'], factory) : | ||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.VueCurrencyInput = {})); | ||
}(this, (function (exports) { 'use strict'; | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('vue-demi')) : | ||
typeof define === 'function' && define.amd ? define(['exports', 'vue-demi'], factory) : | ||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.VueCurrencyInput = {}, global.VueDemi)); | ||
}(this, (function (exports, vueDemi) { 'use strict'; | ||
var escapeRegExp = function (str) { return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); }; | ||
var removeLeadingZeros = function (str) { return str.replace(/^0+(0$|[^0])/, '$1'); }; | ||
var count = function (str, search) { return (str.match(new RegExp(escapeRegExp(search), 'g')) || []).length; }; | ||
var startsWith = function (str, search) { return str.substring(0, search.length) === search; }; | ||
var substringBefore = function (str, search) { return str.substring(0, str.indexOf(search)); }; | ||
const escapeRegExp = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); | ||
const removeLeadingZeros = (str) => str.replace(/^0+(0$|[^0])/, '$1'); | ||
const count = (str, search) => (str.match(new RegExp(escapeRegExp(search), 'g')) || []).length; | ||
const startsWith = (str, search) => str.substring(0, search.length) === search; | ||
const substringBefore = (str, search) => str.substring(0, str.indexOf(search)); | ||
var DECIMAL_SYMBOLS = [',', '.', '٫']; | ||
var NumberFormat = function NumberFormat (options) { | ||
var currency = options.currency; | ||
var locale = options.locale; | ||
var precision = options.precision; | ||
var autoDecimalMode = options.autoDecimalMode; | ||
var valueAsInteger = options.valueAsInteger; | ||
var numberFormat = new Intl.NumberFormat(locale, typeof currency === 'string' ? { currency: currency, style: 'currency' } : { minimumFractionDigits: 1 }); | ||
var ps = numberFormat.format(123456); | ||
this.locale = locale; | ||
this.currency = currency; | ||
this.digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(function (i) { return i.toLocaleString(locale); }); | ||
this.decimalSymbol = count(ps, this.digits[0]) ? ps.substr(ps.indexOf(this.digits[6]) + 1, 1) : undefined; | ||
this.groupingSymbol = ps.substr(ps.indexOf(this.digits[3]) + 1, 1); | ||
this.minusSymbol = substringBefore(Number(-1).toLocaleString(locale), this.digits[1]); | ||
if (this.decimalSymbol === undefined) { | ||
this.minimumFractionDigits = this.maximumFractionDigits = 0; | ||
} else if (typeof precision === 'number') { | ||
this.minimumFractionDigits = this.maximumFractionDigits = precision; | ||
} else if (typeof precision === 'object' && !autoDecimalMode && !valueAsInteger) { | ||
this.minimumFractionDigits = precision.min || 0; | ||
this.maximumFractionDigits = precision.max !== undefined ? precision.max : 20; | ||
} else if (typeof currency === 'string') { | ||
this.minimumFractionDigits = numberFormat.resolvedOptions().minimumFractionDigits; | ||
this.maximumFractionDigits = numberFormat.resolvedOptions().maximumFractionDigits; | ||
} else { | ||
this.minimumFractionDigits = this.maximumFractionDigits = 2; | ||
} | ||
if (typeof currency === 'string') { | ||
const DECIMAL_SYMBOLS = [',', '.', '٫']; | ||
class NumberFormat { | ||
constructor (options) { | ||
const { currency, locale, precision, autoDecimalDigits } = options; | ||
const numberFormat = new Intl.NumberFormat(locale, { currency, style: 'currency' }); | ||
const ps = numberFormat.format(123456); | ||
this.locale = locale; | ||
this.currency = currency; | ||
this.digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map((i) => i.toLocaleString(locale)); | ||
this.decimalSymbol = count(ps, this.digits[0]) ? ps.substr(ps.indexOf(this.digits[6]) + 1, 1) : undefined; | ||
this.groupingSymbol = ps.substr(ps.indexOf(this.digits[3]) + 1, 1); | ||
this.minusSymbol = substringBefore(Number(-1).toLocaleString(locale), this.digits[1]); | ||
if (this.decimalSymbol === undefined) { | ||
this.minimumFractionDigits = this.maximumFractionDigits = 0; | ||
} else if (typeof precision === 'number') { | ||
this.minimumFractionDigits = this.maximumFractionDigits = precision; | ||
} else if (typeof precision === 'object' && !autoDecimalDigits) { | ||
this.minimumFractionDigits = precision.min || 0; | ||
this.maximumFractionDigits = precision.max !== undefined ? precision.max : 20; | ||
} else { | ||
this.minimumFractionDigits = numberFormat.resolvedOptions().minimumFractionDigits; | ||
this.maximumFractionDigits = numberFormat.resolvedOptions().maximumFractionDigits; | ||
} | ||
this.prefix = substringBefore(ps, this.digits[1]); | ||
this.negativePrefix = substringBefore(numberFormat.format(-1), this.digits[1]); | ||
this.suffix = ps.substring(ps.lastIndexOf(this.decimalSymbol ? this.digits[0] : this.digits[6]) + 1); | ||
} else { | ||
this.prefix = (currency || {}).prefix || ''; | ||
this.negativePrefix = "" + (this.minusSymbol) + (this.prefix); | ||
this.suffix = (currency || {}).suffix || ''; | ||
} | ||
}; | ||
NumberFormat.prototype.parse = function parse (str, valueAsInteger) { | ||
if ( valueAsInteger === void 0 ) valueAsInteger = false; | ||
if (str) { | ||
var negative = this.isNegative(str); | ||
str = this.normalizeDigits(str); | ||
str = this.stripCurrencySymbol(str); | ||
str = this.stripMinusSymbol(str); | ||
var fraction = this.decimalSymbol ? ("(" + (escapeRegExp(this.decimalSymbol)) + "\\d*)?") : ''; | ||
var match = str.match(new RegExp(("^" + (this.integerPattern()) + fraction + "$"))); | ||
if (match) { | ||
var number = Number(("" + (negative ? '-' : '') + ((this.onlyDigits(match[1]))) + "." + ((this.onlyDigits(match[3] || ''))))); | ||
return valueAsInteger ? Number(number.toFixed(this.maximumFractionDigits).split('.').join('')) : number | ||
parse (str) { | ||
if (str) { | ||
const negative = this.isNegative(str); | ||
str = this.normalizeDigits(str); | ||
str = this.stripCurrencySymbol(str); | ||
str = this.stripMinusSymbol(str); | ||
const fraction = this.decimalSymbol ? `(${escapeRegExp(this.decimalSymbol)}\\d*)?` : ''; | ||
const match = str.match(new RegExp(`^${this.integerPattern()}${fraction}$`)); | ||
if (match) { | ||
return Number(`${negative ? '-' : ''}${(this.onlyDigits(match[1]))}.${(this.onlyDigits(match[3] || ''))}`) | ||
} | ||
} | ||
return null | ||
} | ||
return null | ||
}; | ||
NumberFormat.prototype.format = function format (number, options) { | ||
if ( options === void 0 ) options = { | ||
minimumFractionDigits: this.minimumFractionDigits, | ||
maximumFractionDigits: this.maximumFractionDigits | ||
}; | ||
if (typeof this.currency === 'string') { | ||
return number.toLocaleString(this.locale, Object.assign({}, {style: 'currency', | ||
currency: this.currency}, | ||
options)) | ||
} else { | ||
return this.insertCurrencySymbol(Math.abs(number).toLocaleString(this.locale, options), number < 0 || (number === 0 && (1 / number < 0))) | ||
format (number, options = { | ||
minimumFractionDigits: this.minimumFractionDigits, | ||
maximumFractionDigits: this.maximumFractionDigits | ||
}) { | ||
return number.toLocaleString(this.locale, { | ||
style: 'currency', | ||
currency: this.currency, | ||
...options | ||
}) | ||
} | ||
}; | ||
NumberFormat.prototype.integerPattern = function integerPattern () { | ||
return ("(0|[1-9]\\d{0,2}(" + (escapeRegExp(this.groupingSymbol)) + "?\\d{3})*)") | ||
}; | ||
NumberFormat.prototype.toFraction = function toFraction (str) { | ||
return ("" + (this.digits[0]) + (this.decimalSymbol) + ((this.onlyLocaleDigits(str.substr(1)).substr(0, this.maximumFractionDigits)))) | ||
}; | ||
NumberFormat.prototype.isFractionIncomplete = function isFractionIncomplete (str) { | ||
return !!this.normalizeDigits(str).match(new RegExp(("^" + (this.integerPattern()) + (escapeRegExp(this.decimalSymbol)) + "$"))) | ||
}; | ||
NumberFormat.prototype.isNegative = function isNegative (str) { | ||
return startsWith(str, this.negativePrefix) || startsWith(str.replace('-', this.minusSymbol), this.minusSymbol) | ||
}; | ||
NumberFormat.prototype.insertCurrencySymbol = function insertCurrencySymbol (str, negative) { | ||
return ("" + (negative ? this.negativePrefix : this.prefix) + str + (this.suffix)) | ||
}; | ||
NumberFormat.prototype.stripMinusSymbol = function stripMinusSymbol (str) { | ||
return str.replace('-', this.minusSymbol).replace(this.minusSymbol, '') | ||
}; | ||
NumberFormat.prototype.stripCurrencySymbol = function stripCurrencySymbol (str) { | ||
return str.replace(this.negativePrefix, '').replace(this.prefix, '').replace(this.suffix, '') | ||
}; | ||
NumberFormat.prototype.normalizeDecimalSymbol = function normalizeDecimalSymbol (str, from) { | ||
var this$1 = this; | ||
DECIMAL_SYMBOLS.forEach(function (s) { | ||
str = str.substr(0, from) + str.substr(from).replace(s, this$1.decimalSymbol); | ||
}); | ||
return str | ||
}; | ||
NumberFormat.prototype.normalizeDigits = function normalizeDigits (str) { | ||
if (this.digits[0] !== '0') { | ||
this.digits.forEach(function (digit, index) { | ||
str = str.replace(new RegExp(digit, 'g'), index); | ||
}); | ||
integerPattern () { | ||
return `(0|[1-9]\\d{0,2}(${escapeRegExp(this.groupingSymbol)}?\\d{3})*)` | ||
} | ||
return str | ||
}; | ||
NumberFormat.prototype.onlyDigits = function onlyDigits (str) { | ||
return this.normalizeDigits(str).replace(/\D+/g, '') | ||
}; | ||
NumberFormat.prototype.onlyLocaleDigits = function onlyLocaleDigits (str) { | ||
return str.replace(new RegExp(("[^" + (this.digits.join('')) + "]*"), 'g'), '') | ||
}; | ||
var DEFAULT_OPTIONS = { | ||
locale: undefined, | ||
currency: 'EUR', | ||
valueAsInteger: false, | ||
distractionFree: true, | ||
precision: undefined, | ||
autoDecimalMode: false, | ||
valueRange: undefined, | ||
allowNegative: true | ||
}; | ||
var parse = function (formattedValue, options) { | ||
var mergedOptions = Object.assign({}, DEFAULT_OPTIONS, options); | ||
return new NumberFormat(mergedOptions).parse(formattedValue, mergedOptions.valueAsInteger) | ||
}; | ||
var getValue = function (ref) { return (ref.$el || ref).$ci.getValue(); }; | ||
var setValue = function (ref, value) { | ||
(ref.$el || ref).$ci.setValue(value); | ||
}; | ||
var equal = function (a, b) { | ||
if (a === b) { | ||
return true | ||
toFraction (str) { | ||
return `${this.digits[0]}${this.decimalSymbol}${(this.onlyLocaleDigits(str.substr(1)).substr(0, this.maximumFractionDigits))}` | ||
} | ||
if (!a || !b || typeof a !== 'object' || typeof b !== 'object') { | ||
return false | ||
isFractionIncomplete (str) { | ||
return !!this.normalizeDigits(str).match(new RegExp(`^${this.integerPattern()}${escapeRegExp(this.decimalSymbol)}$`)) | ||
} | ||
var keys = Object.keys(a); | ||
if (keys.length !== Object.keys(b).length) { | ||
return false | ||
isNegative (str) { | ||
return startsWith(str, this.negativePrefix) || startsWith(str.replace('-', this.minusSymbol), this.minusSymbol) | ||
} | ||
if (!keys.every(Object.prototype.hasOwnProperty.bind(b))) { | ||
return false | ||
insertCurrencySymbol (str, negative) { | ||
return `${negative ? this.negativePrefix : this.prefix}${str}${this.suffix}` | ||
} | ||
return keys.every(function (key) { return equal(a[key], b[key]); }) | ||
}; | ||
var DefaultNumberMask = function DefaultNumberMask (numberFormat) { | ||
this.numberFormat = numberFormat; | ||
}; | ||
DefaultNumberMask.prototype.conformToMask = function conformToMask (str, previousConformedValue) { | ||
var this$1 = this; | ||
if ( previousConformedValue === void 0 ) previousConformedValue = ''; | ||
var negative = this.numberFormat.isNegative(str); | ||
var checkIncompleteValue = function (str) { | ||
if (str === '' && negative && previousConformedValue !== this$1.numberFormat.negativePrefix) { | ||
return '' | ||
} else if (this$1.numberFormat.maximumFractionDigits > 0) { | ||
if (this$1.numberFormat.isFractionIncomplete(str)) { | ||
return str | ||
} else if (startsWith(str, this$1.numberFormat.decimalSymbol)) { | ||
return this$1.numberFormat.toFraction(str) | ||
} | ||
} | ||
return null | ||
}; | ||
var value = str; | ||
value = this.numberFormat.stripCurrencySymbol(value); | ||
value = this.numberFormat.stripMinusSymbol(value); | ||
var incompleteValue = checkIncompleteValue(value); | ||
if (incompleteValue != null) { | ||
return this.numberFormat.insertCurrencySymbol(incompleteValue, negative) | ||
stripMinusSymbol (str) { | ||
return str.replace('-', this.minusSymbol).replace(this.minusSymbol, '') | ||
} | ||
var ref = value.split(this.numberFormat.decimalSymbol); | ||
var integer = ref[0]; | ||
var fraction = ref.slice(1); | ||
var integerDigits = removeLeadingZeros(this.numberFormat.onlyDigits(integer)); | ||
var fractionDigits = this.numberFormat.onlyDigits(fraction.join('')).substr(0, this.numberFormat.maximumFractionDigits); | ||
var invalidFraction = fraction.length > 0 && fractionDigits.length === 0; | ||
var invalidNegativeValue = integerDigits === '' && negative && (previousConformedValue === str.slice(0, -1) || previousConformedValue !== this.numberFormat.negativePrefix); | ||
if (invalidFraction || invalidNegativeValue) { | ||
return previousConformedValue | ||
} else if (integerDigits.match(/\d+/)) { | ||
return { | ||
numberValue: Number(("" + (negative ? '-' : '') + integerDigits + "." + fractionDigits)), | ||
fractionDigits: fractionDigits | ||
stripCurrencySymbol (str) { | ||
return str.replace(this.negativePrefix, '').replace(this.prefix, '').replace(this.suffix, '') | ||
} | ||
normalizeDecimalSymbol (str, from) { | ||
DECIMAL_SYMBOLS.forEach((s) => { | ||
str = str.substr(0, from) + str.substr(from).replace(s, this.decimalSymbol); | ||
}); | ||
return str | ||
} | ||
normalizeDigits (str) { | ||
if (this.digits[0] !== '0') { | ||
this.digits.forEach((digit, index) => { | ||
str = str.replace(new RegExp(digit, 'g'), index); | ||
}); | ||
} | ||
} else { | ||
return '' | ||
return str | ||
} | ||
}; | ||
var AutoDecimalModeNumberMask = function AutoDecimalModeNumberMask (numberFormat) { | ||
this.numberFormat = numberFormat; | ||
}; | ||
AutoDecimalModeNumberMask.prototype.conformToMask = function conformToMask (str) { | ||
if (str === '') { | ||
return '' | ||
onlyDigits (str) { | ||
return this.normalizeDigits(str).replace(/\D+/g, '') | ||
} | ||
var negative = this.numberFormat.isNegative(str); | ||
var numberValue = this.numberFormat.stripMinusSymbol(str) === '' | ||
? -0 | ||
: Number(("" + (negative ? '-' : '') + (removeLeadingZeros(this.numberFormat.onlyDigits(str))))) / Math.pow(10, this.numberFormat.minimumFractionDigits); | ||
return { | ||
numberValue: numberValue, | ||
fractionDigits: numberValue.toFixed(this.numberFormat.minimumFractionDigits).slice(-this.numberFormat.minimumFractionDigits) | ||
onlyLocaleDigits (str) { | ||
return str.replace(new RegExp(`[^${this.digits.join('')}]*`, 'g'), '') | ||
} | ||
}; | ||
} | ||
var getCaretPositionAfterFormat = function (newValue, inputtedValue, caretPosition, numberFormat, options) { | ||
var prefix = numberFormat.prefix; | ||
var suffix = numberFormat.suffix; | ||
var decimalSymbol = numberFormat.decimalSymbol; | ||
var maximumFractionDigits = numberFormat.maximumFractionDigits; | ||
var groupingSymbol = numberFormat.groupingSymbol; | ||
var decimalSymbolPosition = inputtedValue.indexOf(decimalSymbol) + 1; | ||
var caretPositionFromLeft = inputtedValue.length - caretPosition; | ||
if (Math.abs(newValue.length - inputtedValue.length) > 1 && caretPosition <= decimalSymbolPosition) { | ||
return newValue.indexOf(decimalSymbol) + 1 | ||
} else if (newValue.substr(caretPosition, 1) === groupingSymbol && count(newValue, groupingSymbol) === count(inputtedValue, groupingSymbol) + 1) { | ||
return newValue.length - caretPositionFromLeft - 1 | ||
} else { | ||
if (!options.autoDecimalMode && decimalSymbolPosition !== 0 && caretPosition > decimalSymbolPosition) { | ||
if (numberFormat.onlyDigits(inputtedValue.substr(decimalSymbolPosition)).length - 1 === maximumFractionDigits) { | ||
caretPositionFromLeft -= 1; | ||
class DefaultNumberMask { | ||
constructor (numberFormat) { | ||
this.numberFormat = numberFormat; | ||
} | ||
conformToMask (str, previousConformedValue = '') { | ||
const negative = this.numberFormat.isNegative(str); | ||
const checkIncompleteValue = (str) => { | ||
if (str === '' && negative && previousConformedValue !== this.numberFormat.negativePrefix) { | ||
return '' | ||
} else if (this.numberFormat.maximumFractionDigits > 0) { | ||
if (this.numberFormat.isFractionIncomplete(str)) { | ||
return str | ||
} else if (startsWith(str, this.numberFormat.decimalSymbol)) { | ||
return this.numberFormat.toFraction(str) | ||
} | ||
} | ||
return null | ||
}; | ||
let value = str; | ||
value = this.numberFormat.stripCurrencySymbol(value); | ||
value = this.numberFormat.stripMinusSymbol(value); | ||
const incompleteValue = checkIncompleteValue(value); | ||
if (incompleteValue != null) { | ||
return this.numberFormat.insertCurrencySymbol(incompleteValue, negative) | ||
} | ||
return options.distractionFree.hideCurrencySymbol | ||
? newValue.length - caretPositionFromLeft | ||
: Math.max(newValue.length - Math.max(caretPositionFromLeft, suffix.length), prefix.length === 0 ? 0 : prefix.length + 1) | ||
const [integer, ...fraction] = value.split(this.numberFormat.decimalSymbol); | ||
const integerDigits = removeLeadingZeros(this.numberFormat.onlyDigits(integer)); | ||
const fractionDigits = this.numberFormat.onlyDigits(fraction.join('')).substr(0, this.numberFormat.maximumFractionDigits); | ||
const invalidFraction = fraction.length > 0 && fractionDigits.length === 0; | ||
const invalidNegativeValue = integerDigits === '' && negative && (previousConformedValue === str.slice(0, -1) || previousConformedValue !== this.numberFormat.negativePrefix); | ||
if (invalidFraction || invalidNegativeValue) { | ||
return previousConformedValue | ||
} else if (integerDigits.match(/\d+/)) { | ||
return { | ||
numberValue: Number(`${negative ? '-' : ''}${integerDigits}.${fractionDigits}`), | ||
fractionDigits | ||
} | ||
} else { | ||
return '' | ||
} | ||
} | ||
}; | ||
var getDistractionFreeCaretPosition = function (numberFormat, options, value, caretPosition) { | ||
var result = caretPosition; | ||
if (options.distractionFree.hideCurrencySymbol) { | ||
result -= numberFormat.prefix.length; | ||
} | ||
class AutoDecimalDigitsNumberMask { | ||
constructor (numberFormat) { | ||
this.numberFormat = numberFormat; | ||
} | ||
if (options.distractionFree.hideGroupingSymbol) { | ||
result -= count(value.substring(0, caretPosition), numberFormat.groupingSymbol); | ||
conformToMask (str) { | ||
if (str === '') { | ||
return '' | ||
} | ||
const negative = this.numberFormat.isNegative(str); | ||
const numberValue = this.numberFormat.stripMinusSymbol(str) === '' | ||
? -0 | ||
: Number(`${negative ? '-' : ''}${removeLeadingZeros(this.numberFormat.onlyDigits(str))}`) / Math.pow(10, this.numberFormat.minimumFractionDigits); | ||
return { | ||
numberValue, | ||
fractionDigits: numberValue.toFixed(this.numberFormat.minimumFractionDigits).slice(-this.numberFormat.minimumFractionDigits) | ||
} | ||
} | ||
return Math.max(0, result) | ||
}; | ||
} | ||
var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1; | ||
var NumberInput = function NumberInput (el, options, callbackFns) { | ||
this.el = el; | ||
this.callbackFns = callbackFns; | ||
this.numberValue = null; | ||
this.addEventListener(); | ||
this.init(options); | ||
this.setValue(this.currencyFormat.parse(this.el.value)); | ||
const MAX_SAFE_INTEGER = Math.pow(2, 53) - 1; | ||
const DEFAULT_OPTIONS = { | ||
locale: undefined, | ||
currency: undefined, | ||
valueAsInteger: false, | ||
distractionFree: true, | ||
precision: undefined, | ||
autoDecimalDigits: false, | ||
valueRange: undefined, | ||
allowNegative: true | ||
}; | ||
NumberInput.prototype.init = function init (newOptions) { | ||
var options = Object.assign({}, newOptions); | ||
var distractionFree = options.distractionFree; | ||
var autoDecimalMode = options.autoDecimalMode; | ||
var valueRange = options.valueRange; | ||
if (typeof distractionFree === 'boolean') { | ||
options.distractionFree = { | ||
hideCurrencySymbol: distractionFree, | ||
hideNegligibleDecimalDigits: distractionFree, | ||
hideGroupingSymbol: distractionFree | ||
}; | ||
class NumberInput { | ||
constructor (el, options, callbackFns) { | ||
this.el = el; | ||
this.callbackFns = callbackFns; | ||
this.numberValue = null; | ||
this.addEventListener(); | ||
this.init(options); | ||
this.setValue(this.currencyFormat.parse(this.el.value)); | ||
} | ||
if (valueRange) { | ||
options.valueRange = { | ||
min: valueRange.min !== undefined ? Math.max(valueRange.min, -MAX_SAFE_INTEGER) : -MAX_SAFE_INTEGER, | ||
max: valueRange.max !== undefined ? Math.min(valueRange.max, MAX_SAFE_INTEGER) : MAX_SAFE_INTEGER | ||
}; | ||
} else { | ||
options.valueRange = { | ||
min: -MAX_SAFE_INTEGER, | ||
max: MAX_SAFE_INTEGER | ||
}; | ||
init (options) { | ||
const { distractionFree, autoDecimalDigits, valueRange, valueAsInteger, allowNegative } = { ...DEFAULT_OPTIONS, ...options }; | ||
this.autoDecimalDigits = autoDecimalDigits; | ||
this.valueAsInteger = valueAsInteger; | ||
this.allowNegative = allowNegative; | ||
this.hideCurrencySymbolOnFocus = distractionFree === true || !!(distractionFree || {}).hideCurrencySymbol; | ||
this.hideNegligibleDecimalDigitsOnFocus = distractionFree === true || !!(distractionFree || {}).hideNegligibleDecimalDigits; | ||
this.hideGroupingSymbolOnFocus = distractionFree === true || !!(distractionFree || {}).hideGroupingSymbol; | ||
if (valueRange) { | ||
this.valueRange = { | ||
min: valueRange.min !== undefined ? Math.max(valueRange.min, -MAX_SAFE_INTEGER) : -MAX_SAFE_INTEGER, | ||
max: valueRange.max !== undefined ? Math.min(valueRange.max, MAX_SAFE_INTEGER) : MAX_SAFE_INTEGER | ||
}; | ||
} else { | ||
this.valueRange = { | ||
min: -MAX_SAFE_INTEGER, | ||
max: MAX_SAFE_INTEGER | ||
}; | ||
} | ||
if (autoDecimalDigits) { | ||
this.hideNegligibleDecimalDigitsOnFocus = false; | ||
this.el.setAttribute('inputmode', 'numeric'); | ||
} else { | ||
this.el.setAttribute('inputmode', 'decimal'); | ||
} | ||
this.currencyFormat = new NumberFormat(options); | ||
this.numberMask = autoDecimalDigits ? new AutoDecimalDigitsNumberMask(this.currencyFormat) : new DefaultNumberMask(this.currencyFormat); | ||
} | ||
if (autoDecimalMode) { | ||
options.distractionFree.hideNegligibleDecimalDigits = false; | ||
this.el.setAttribute('inputmode', 'numeric'); | ||
} else { | ||
this.el.setAttribute('inputmode', 'decimal'); | ||
setOptions (options) { | ||
this.init(options); | ||
this.applyFixedFractionFormat(this.numberValue, true); | ||
} | ||
this.options = options; | ||
this.currencyFormat = new NumberFormat(this.options); | ||
this.numberMask = options.autoDecimalMode ? new AutoDecimalModeNumberMask(this.currencyFormat) : new DefaultNumberMask(this.currencyFormat); | ||
}; | ||
NumberInput.prototype.setOptions = function setOptions (options) { | ||
this.init(options); | ||
this.applyFixedFractionFormat(this.numberValue, true); | ||
}; | ||
NumberInput.prototype.applyFixedFractionFormat = function applyFixedFractionFormat (number, forcedChange) { | ||
this.format(number != null ? this.currencyFormat.format(this.validateValueRange(number)) : null); | ||
if (number !== this.numberValue || forcedChange) { | ||
this.callbackFns.onChange(this.getValue()); | ||
applyFixedFractionFormat (number, forcedChange) { | ||
this.format(number != null ? this.currencyFormat.format(this.validateValueRange(number)) : null); | ||
if (number !== this.numberValue || forcedChange) { | ||
this.callbackFns.onChange(this.getValue()); | ||
} | ||
} | ||
}; | ||
NumberInput.prototype.getValue = function getValue () { | ||
return this.currencyFormat.parse(this.formattedValue, this.options.valueAsInteger) | ||
}; | ||
NumberInput.prototype.setValue = function setValue (value) { | ||
var newValue = this.options.valueAsInteger && value != null ? value / Math.pow(10, this.currencyFormat.maximumFractionDigits) : value; | ||
if (newValue !== this.numberValue) { | ||
this.applyFixedFractionFormat(newValue); | ||
getValue () { | ||
const numberValue = this.valueAsInteger && this.numberValue != null ? Number(this.numberValue.toFixed(this.currencyFormat.maximumFractionDigits).split('.').join('')) : this.numberValue; | ||
return { | ||
number: numberValue, | ||
formatted: this.formattedValue | ||
} | ||
} | ||
}; | ||
NumberInput.prototype.validateValueRange = function validateValueRange (value) { | ||
var ref = this.options.valueRange; | ||
var min = ref.min; | ||
var max = ref.max; | ||
return Math.min(Math.max(value, min), max) | ||
}; | ||
NumberInput.prototype.updateInputValue = function updateInputValue (value, hideNegligibleDecimalDigits) { | ||
if ( hideNegligibleDecimalDigits === void 0 ) hideNegligibleDecimalDigits = false; | ||
if (value != null) { | ||
if (this.decimalSymbolInsertedAt !== undefined) { | ||
value = this.currencyFormat.normalizeDecimalSymbol(value, this.decimalSymbolInsertedAt); | ||
this.decimalSymbolInsertedAt = undefined; | ||
setValue (value) { | ||
const newValue = this.valueAsInteger && value != null ? value / Math.pow(10, this.currencyFormat.maximumFractionDigits) : value; | ||
if (newValue !== this.numberValue) { | ||
this.applyFixedFractionFormat(newValue); | ||
} | ||
var conformedValue = this.numberMask.conformToMask(value, this.formattedValue); | ||
var formattedValue; | ||
if (typeof conformedValue === 'object') { | ||
var numberValue = conformedValue.numberValue; | ||
var fractionDigits = conformedValue.fractionDigits; | ||
var ref = this.currencyFormat; | ||
var maximumFractionDigits = ref.maximumFractionDigits; | ||
var minimumFractionDigits = ref.minimumFractionDigits; | ||
if (this.focus) { | ||
minimumFractionDigits = maximumFractionDigits; | ||
} | ||
validateValueRange (value) { | ||
const { min, max } = this.valueRange; | ||
return Math.min(Math.max(value, min), max) | ||
} | ||
format (value, hideNegligibleDecimalDigits = false) { | ||
if (value != null) { | ||
if (this.decimalSymbolInsertedAt !== undefined) { | ||
value = this.currencyFormat.normalizeDecimalSymbol(value, this.decimalSymbolInsertedAt); | ||
this.decimalSymbolInsertedAt = undefined; | ||
} | ||
minimumFractionDigits = hideNegligibleDecimalDigits | ||
? fractionDigits.replace(/0+$/, '').length | ||
: Math.min(minimumFractionDigits, fractionDigits.length); | ||
formattedValue = numberValue > MAX_SAFE_INTEGER | ||
? this.formattedValue | ||
: this.currencyFormat.format(numberValue, { | ||
useGrouping: !(this.focus && this.options.distractionFree.hideGroupingSymbol), | ||
minimumFractionDigits: minimumFractionDigits, | ||
maximumFractionDigits: maximumFractionDigits | ||
}); | ||
const conformedValue = this.numberMask.conformToMask(value, this.formattedValue); | ||
let formattedValue; | ||
if (typeof conformedValue === 'object') { | ||
const { numberValue, fractionDigits } = conformedValue; | ||
let { maximumFractionDigits, minimumFractionDigits } = this.currencyFormat; | ||
if (this.focus) { | ||
minimumFractionDigits = maximumFractionDigits; | ||
} | ||
minimumFractionDigits = hideNegligibleDecimalDigits | ||
? fractionDigits.replace(/0+$/, '').length | ||
: Math.min(minimumFractionDigits, fractionDigits.length); | ||
formattedValue = numberValue > MAX_SAFE_INTEGER | ||
? this.formattedValue | ||
: this.currencyFormat.format(numberValue, { | ||
useGrouping: !(this.focus && this.hideGroupingSymbolOnFocus), | ||
minimumFractionDigits, | ||
maximumFractionDigits | ||
}); | ||
} else { | ||
formattedValue = conformedValue; | ||
} | ||
if (!this.allowNegative) { | ||
formattedValue = formattedValue.replace(this.currencyFormat.negativePrefix, this.currencyFormat.prefix); | ||
} | ||
if (this.focus && this.hideCurrencySymbolOnFocus) { | ||
formattedValue = formattedValue | ||
.replace(this.currencyFormat.negativePrefix, this.currencyFormat.minusSymbol) | ||
.replace(this.currencyFormat.prefix, '') | ||
.replace(this.currencyFormat.suffix, ''); | ||
} | ||
this.el.value = formattedValue; | ||
this.numberValue = this.currencyFormat.parse(formattedValue); | ||
} else { | ||
formattedValue = conformedValue; | ||
this.el.value = this.numberValue = null; | ||
} | ||
if (!this.options.allowNegative) { | ||
formattedValue = formattedValue.replace(this.currencyFormat.negativePrefix, this.currencyFormat.prefix); | ||
} | ||
if (this.focus && this.options.distractionFree.hideCurrencySymbol) { | ||
formattedValue = formattedValue | ||
.replace(this.currencyFormat.negativePrefix, this.currencyFormat.minusSymbol) | ||
.replace(this.currencyFormat.prefix, '') | ||
.replace(this.currencyFormat.suffix, ''); | ||
} | ||
this.el.value = formattedValue; | ||
this.numberValue = this.currencyFormat.parse(formattedValue); | ||
} else { | ||
this.el.value = this.numberValue = null; | ||
this.formattedValue = this.el.value; | ||
this.callbackFns.onInput(this.getValue()); | ||
} | ||
this.formattedValue = this.el.value; | ||
}; | ||
NumberInput.prototype.format = function format (value) { | ||
this.updateInputValue(value); | ||
this.callbackFns.onInput(this.getValue()); | ||
}; | ||
NumberInput.prototype.addEventListener = function addEventListener () { | ||
var this$1 = this; | ||
this.el.addEventListener('input', function () { | ||
var ref = this$1.el; | ||
var value = ref.value; | ||
var selectionStart = ref.selectionStart; | ||
this$1.format(value); | ||
if (this$1.focus) { | ||
this$1.setCaretPosition(getCaretPositionAfterFormat(this$1.formattedValue, value, selectionStart, this$1.currencyFormat, this$1.options)); | ||
} | ||
}, { capture: true }); | ||
this.el.addEventListener('focus', function () { | ||
this$1.focus = true; | ||
var ref = this$1.options.distractionFree; | ||
var hideCurrencySymbol = ref.hideCurrencySymbol; | ||
var hideGroupingSymbol = ref.hideGroupingSymbol; | ||
var hideNegligibleDecimalDigits = ref.hideNegligibleDecimalDigits; | ||
if (hideCurrencySymbol || hideGroupingSymbol || hideNegligibleDecimalDigits) { | ||
setTimeout(function () { | ||
var ref = this$1.el; | ||
var value = ref.value; | ||
var selectionStart = ref.selectionStart; | ||
var selectionEnd = ref.selectionEnd; | ||
if (value) { | ||
this$1.updateInputValue(this$1.el.value, hideNegligibleDecimalDigits); | ||
addEventListener () { | ||
this.el.addEventListener('input', () => { | ||
const { value, selectionStart } = this.el; | ||
this.format(value); | ||
if (this.focus) { | ||
const getCaretPositionAfterFormat = () => { | ||
const { prefix, suffix, decimalSymbol, maximumFractionDigits, groupingSymbol } = this.currencyFormat; | ||
let caretPositionFromLeft = value.length - selectionStart; | ||
const newValueLength = this.formattedValue.length; | ||
if (this.formattedValue.substr(selectionStart, 1) === groupingSymbol && count(this.formattedValue, groupingSymbol) === count(value, groupingSymbol) + 1) { | ||
return newValueLength - caretPositionFromLeft - 1 | ||
} | ||
if (decimalSymbol) { | ||
const decimalSymbolPosition = value.indexOf(decimalSymbol) + 1; | ||
if (Math.abs(newValueLength - value.length) > 1 && selectionStart <= decimalSymbolPosition) { | ||
return this.formattedValue.indexOf(decimalSymbol) + 1 | ||
} else { | ||
if (!this.autoDecimalDigits && selectionStart > decimalSymbolPosition) { | ||
if (this.currencyFormat.onlyDigits(value.substr(decimalSymbolPosition)).length - 1 === maximumFractionDigits) { | ||
caretPositionFromLeft -= 1; | ||
} | ||
} | ||
} | ||
} | ||
return this.hideCurrencySymbolOnFocus ? newValueLength - caretPositionFromLeft : Math.max(newValueLength - Math.max(caretPositionFromLeft, suffix.length), prefix.length) | ||
}; | ||
this.setCaretPosition(getCaretPositionAfterFormat()); | ||
} | ||
}, { capture: true }); | ||
this.el.addEventListener('focus', () => { | ||
this.focus = true; | ||
setTimeout(() => { | ||
const { value, selectionStart, selectionEnd } = this.el; | ||
if ((this.hideCurrencySymbolOnFocus || this.hideGroupingSymbolOnFocus || this.hideNegligibleDecimalDigitsOnFocus) && value) { | ||
this.format(value, this.hideNegligibleDecimalDigitsOnFocus); | ||
} | ||
if (Math.abs(selectionStart - selectionEnd) > 0) { | ||
this$1.setCaretPosition(0, this$1.el.value.length); | ||
this.setCaretPosition(0, this.el.value.length); | ||
} else { | ||
this$1.setCaretPosition(getDistractionFreeCaretPosition(this$1.currencyFormat, this$1.options, value, selectionStart)); | ||
const getSelectionStart = () => { | ||
const { prefix, suffix, groupingSymbol } = this.currencyFormat; | ||
if (!this.hideCurrencySymbolOnFocus) { | ||
if (selectionStart > value.length - suffix.length) { | ||
return this.formattedValue.length - suffix.length | ||
} else if (selectionStart < prefix.length) { | ||
return prefix.length | ||
} | ||
} | ||
let result = selectionStart; | ||
if (this.hideCurrencySymbolOnFocus) { | ||
result -= prefix.length; | ||
} | ||
if (this.hideGroupingSymbolOnFocus) { | ||
result -= count(value.substring(0, selectionStart), groupingSymbol); | ||
} | ||
return result | ||
}; | ||
this.setCaretPosition(getSelectionStart()); | ||
} | ||
}); | ||
} | ||
}); | ||
this.el.addEventListener('keypress', function (e) { | ||
if (DECIMAL_SYMBOLS.includes(e.key)) { | ||
this$1.decimalSymbolInsertedAt = this$1.el.selectionStart; | ||
} | ||
}); | ||
this.el.addEventListener('blur', function () { | ||
this$1.focus = false; | ||
if (this$1.numberValue != null) { | ||
this$1.applyFixedFractionFormat(this$1.numberValue); | ||
} | ||
}); | ||
this.el.addEventListener('change', function () { | ||
this$1.callbackFns.onChange(this$1.getValue()); | ||
}); | ||
}; | ||
NumberInput.prototype.setCaretPosition = function setCaretPosition (start, end) { | ||
if ( end === void 0 ) end = start; | ||
this.el.setSelectionRange(start, end); }; | ||
var directive = { | ||
bind: function bind (el, ref, vnode) { | ||
var optionsFromBinding = ref.value; | ||
var inputElement = el.tagName.toLowerCase() === 'input' ? el : el.querySelector('input'); | ||
if (!inputElement) { | ||
throw new Error('No input element found') | ||
} | ||
var options = Object.assign({}, DEFAULT_OPTIONS, | ||
(vnode.context.$ci || {}).globalOptions, | ||
optionsFromBinding); | ||
var listeners = (vnode.data && vnode.data.on) || (vnode.componentOptions && vnode.componentOptions.listeners) || {}; | ||
var emit = function (event, data) { | ||
if (listeners[event]) { | ||
listeners[event](vnode.componentOptions ? data : { target: { value: data } }); | ||
}); | ||
this.el.addEventListener('keypress', (e) => { | ||
if (DECIMAL_SYMBOLS.includes(e.key)) { | ||
this.decimalSymbolInsertedAt = this.el.selectionStart; | ||
} | ||
}; | ||
el.$ci = new NumberInput(inputElement, options, { | ||
onChange: function () { emit('change', inputElement.value); }, | ||
onInput: function () { emit('input', inputElement.value); } | ||
}); | ||
}, | ||
componentUpdated: function componentUpdated (el, ref) { | ||
var value = ref.value; | ||
var oldValue = ref.oldValue; | ||
if (!equal(value, oldValue)) { | ||
el.$ci.setOptions(value); | ||
} | ||
this.el.addEventListener('blur', () => { | ||
this.focus = false; | ||
if (this.numberValue != null) { | ||
this.applyFixedFractionFormat(this.numberValue); | ||
} | ||
}); | ||
this.el.addEventListener('change', () => { | ||
this.callbackFns.onChange(this.getValue()); | ||
}); | ||
} | ||
}; | ||
setCaretPosition (start, end = start) { this.el.setSelectionRange(start, end); } | ||
} | ||
var component = { | ||
render: function render (h) { | ||
var this$1 = this; | ||
return h('input', { | ||
directives: [{ | ||
name: 'currency', | ||
value: this.options | ||
}], | ||
on: Object.assign({}, this.$listeners, | ||
{change: function () { | ||
this$1.$emit('change', getValue(this$1.$el)); | ||
}, | ||
input: function () { | ||
var numberValue = getValue(this$1.$el); | ||
if (this$1.value !== numberValue) { | ||
this$1.$emit('input', numberValue); | ||
const findInput = (el) => el.tagName.toLowerCase() === 'input' ? el : el.querySelector('input'); | ||
var useCurrencyInput = ({ inputRef, props, emit }) => { | ||
let numberInput; | ||
const currentInstance = vueDemi.getCurrentInstance(); | ||
const lazy = vueDemi.isVue3 && (currentInstance.attrs.modelModifiers || {}).lazy; | ||
const inputEvent = vueDemi.isVue3 ? 'update:modelValue' : 'input'; | ||
const changeEvent = vueDemi.isVue3 ? 'update:modelValue' : 'change'; | ||
const formattedValue = vueDemi.ref(null); | ||
const numberValue = vueDemi.computed(() => props[vueDemi.isVue3 ? 'modelValue' : 'value']); | ||
const options = vueDemi.computed(() => Object.keys(DEFAULT_OPTIONS).reduce((options, key) => { | ||
if (props[key] !== undefined) { | ||
options[key] = props[key]; | ||
} | ||
return options | ||
}, {})); | ||
vueDemi.onMounted(() => { | ||
if (inputRef.value) { | ||
const input = '$el' in inputRef.value ? findInput(inputRef.value.$el) : inputRef.value; | ||
if (input == null) { | ||
throw new Error('No input element found') | ||
} else { | ||
numberInput = new NumberInput(input, options.value, { | ||
onInput (value) { | ||
if (!lazy && numberValue.value !== value.number) { | ||
emit(inputEvent, value.number); | ||
} | ||
formattedValue.value = value.formatted; | ||
}, | ||
onChange (value) { | ||
emit(changeEvent, value.number); | ||
formattedValue.value = value.formatted; | ||
} | ||
}}) | ||
}) | ||
}, | ||
directives: { | ||
currency: directive | ||
}, | ||
name: 'CurrencyInput', | ||
props: { | ||
value: { | ||
type: Number, | ||
default: null | ||
}, | ||
locale: { | ||
type: String, | ||
default: undefined | ||
}, | ||
currency: { | ||
type: [String, Object], | ||
default: undefined | ||
}, | ||
distractionFree: { | ||
type: [Boolean, Object], | ||
default: undefined | ||
}, | ||
precision: { | ||
type: [Number, Object], | ||
default: undefined | ||
}, | ||
autoDecimalMode: { | ||
type: Boolean, | ||
default: undefined | ||
}, | ||
valueAsInteger: { | ||
type: Boolean, | ||
default: undefined | ||
}, | ||
valueRange: { | ||
type: Object, | ||
default: undefined | ||
}, | ||
allowNegative: { | ||
type: Boolean, | ||
default: undefined | ||
}); | ||
numberInput.setValue(numberValue.value); | ||
} | ||
} | ||
}, | ||
mounted: function mounted () { | ||
this.setValue(this.value); | ||
}, | ||
computed: { | ||
options: function options () { | ||
var this$1 = this; | ||
var options = Object.assign({}, DEFAULT_OPTIONS, | ||
(this.$ci || {}).globalOptions); | ||
Object.keys(DEFAULT_OPTIONS).forEach(function (key) { | ||
if (this$1[key] !== undefined) { | ||
options[key] = this$1[key]; | ||
} | ||
}); | ||
return options | ||
} | ||
}, | ||
watch: { | ||
value: 'setValue' | ||
}, | ||
methods: { | ||
setValue: function setValue$1 (value) { | ||
setValue(this.$el, value); | ||
} | ||
} | ||
}); | ||
vueDemi.watch(numberValue, (value) => { | ||
numberInput.setValue(value); | ||
}); | ||
vueDemi.watch(options, (options) => { | ||
numberInput.setOptions(options); | ||
}); | ||
return { formattedValue } | ||
}; | ||
var plugin = { | ||
install: function install (Vue, ref) { | ||
if ( ref === void 0 ) ref = {}; | ||
var componentName = ref.componentName; if ( componentName === void 0 ) componentName = component.name; | ||
var directiveName = ref.directiveName; if ( directiveName === void 0 ) directiveName = 'currency'; | ||
var globalOptions = ref.globalOptions; if ( globalOptions === void 0 ) globalOptions = {}; | ||
Vue.component(componentName, component); | ||
Vue.directive(directiveName, directive); | ||
Vue.prototype.$ci = { | ||
parse: function (formattedValue, options) { return parse(formattedValue, Object.assign({}, globalOptions, options)); }, | ||
getValue: getValue, | ||
setValue: setValue, | ||
globalOptions: globalOptions | ||
}; | ||
} | ||
}; | ||
exports.default = useCurrencyInput; | ||
if (typeof window !== 'undefined' && window.Vue) { | ||
window.Vue.use(plugin); | ||
} | ||
exports.CurrencyDirective = directive; | ||
exports.CurrencyInput = component; | ||
exports.default = plugin; | ||
exports.getValue = getValue; | ||
exports.parse = parse; | ||
exports.setValue = setValue; | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
}))); |
{ | ||
"name": "vue-currency-input", | ||
"description": "Easy input of currency formatted numbers for Vue.js.", | ||
"version": "1.22.3", | ||
"version": "2.0.0-beta.0", | ||
"license": "MIT", | ||
@@ -13,4 +13,3 @@ "unpkg": "dist/vue-currency-input.umd.js", | ||
"dist/*.js", | ||
"src", | ||
"nuxt" | ||
"src/index.d.ts" | ||
], | ||
@@ -26,2 +25,4 @@ "sideeffects": false, | ||
"vue", | ||
"composition api", | ||
"composable", | ||
"text mask", | ||
@@ -31,5 +32,6 @@ "input mask", | ||
"money input", | ||
"format", | ||
"number format", | ||
"i18n", | ||
"ISO 4217" | ||
"ISO 4217", | ||
"ECMA-402" | ||
], | ||
@@ -45,3 +47,4 @@ "scripts": { | ||
"peerDependencies": { | ||
"vue": "^2.5" | ||
"@vue/composition-api": "^1.0.0-beta.1", | ||
"vue": "^2.5 || ^3.0.0" | ||
}, | ||
@@ -54,4 +57,6 @@ "devDependencies": { | ||
"@vue/cli-service": "~4.4.1", | ||
"@vue/composition-api": "^1.0.0-beta.14", | ||
"@vue/eslint-config-standard": "^5.1.2", | ||
"@vue/test-utils": "^1.0.3", | ||
"@vuepress/plugin-pwa": "^1.6.0", | ||
"babel-eslint": "^10.1.0", | ||
@@ -66,3 +71,2 @@ "core-js": "^3.6.5", | ||
"rollup": "^2.15.0", | ||
"rollup-plugin-buble": "^0.19.8", | ||
"rollup-plugin-cleanup": "^3.1.1", | ||
@@ -72,5 +76,8 @@ "rollup-plugin-filesize": "^9.0.0", | ||
"vue-template-compiler": "^2.6.11", | ||
"vuepress": "^1.5.1", | ||
"vuepress": "^1.6.0", | ||
"vuetify": "^2.1.15" | ||
}, | ||
"dependencies": { | ||
"vue-demi": "^0.4.0" | ||
} | ||
} |
@@ -9,54 +9,26 @@ [![Build Status](https://travis-ci.com/dm4t2/vue-currency-input.svg?branch=master)](https://travis-ci.com/dm4t2/vue-currency-input) | ||
# Vue Currency Input | ||
The Vue Currency Input plugin allows an easy input of currency formatted numbers. It provides both a standalone component (`<currency-input>`) and a custom Vue directive (`v-currency`) for decorating existing input components with currency format capabilities. | ||
Vue Currency Input allows an easy input of currency formatted numbers. Powered by the [Vue Composition API](https://v3.vuejs.org/guide/composition-api-introduction.html), it provides a Vue composable for decorating input components with currency format capabilities. | ||
[![](docs/vue-currency-input.gif)](https://dm4t2.github.io/vue-currency-input) | ||
[![](docs/vue-currency-input.gif)](https://vue-currency-input-next.netlify.app/) | ||
## Features | ||
* [Tiny bundle size](https://bundlephobia.com/result?p=vue-currency-input) and zero dependencies | ||
* Supports both Vue 2 and Vue 3 | ||
* [Tiny bundle size](https://bundlephobia.com/result?p=vue-currency-input) | ||
* Format as you type | ||
* Locale dependent, ISO-compliant currency formatting based on [Intl.NumberFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat) | ||
* Built on standards: Uses the [ECMAScript Internationalization API (ECMA-402)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) for currency formatting | ||
* Distraction free (hides the formatting on focus for easier input) | ||
* Allows handling values as integer numbers for full precision | ||
* Auto decimal mode (automatically inserts the decimal symbol, using the last inputted digits as decimal digits) | ||
* Auto decimal digits (automatically inserts the decimal symbol, using the last inputted digits as decimal digits) | ||
* Built-in value range validation | ||
* Works with input components of popular frameworks like [Vuetify](https://codesandbox.io/s/using-vue-currency-input-with-vuetify-kd7d1) or [Element](https://codesandbox.io/s/using-vue-currency-input-with-element-ui-z8gik) | ||
* Works with input components of popular frameworks like [Vuetify](https://vuetifyjs.com/en/components/text-fields/), [Quasar](https://quasar.dev/vue-components/input) or [Element](https://element.eleme.io/#/en-US/component/input) | ||
## Live Demo | ||
Check out the [playground](https://dm4t2.github.io/vue-currency-input/playground/) to see it in action. | ||
Check out the [playground](https://vue-currency-input-next.netlify.app/playground/) to see it in action. | ||
## Quick Start | ||
Install the npm package: | ||
``` bash | ||
npm install vue-currency-input | ||
# OR | ||
yarn add vue-currency-input | ||
``` | ||
Add the Vue plugin in your `main.js`: | ||
``` js | ||
import Vue from 'vue' | ||
import VueCurrencyInput from 'vue-currency-input' | ||
Vue.use(VueCurrencyInput) | ||
``` | ||
Use the `<currency-input`> component: | ||
``` vue | ||
<template> | ||
<currency-input v-model="value" /> | ||
</template> | ||
<script> | ||
export default { | ||
data: () => ({ value: 1000 }) | ||
} | ||
</script> | ||
``` | ||
## Documentation | ||
Please refer to the [project home page](https://dm4t2.github.io/vue-currency-input) for a detailed documentation. | ||
Please refer to the [project home page](https://vue-currency-input-next.netlify.app/) for a detailed documentation. | ||
## Support me | ||
If you find this plugin helpful or you want to support the development, buy me a coffee: | ||
If you find my work helpful, or you want to support the development, star the repo or buy me a coffee: | ||
[![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/D1D6SXEA) |
@@ -1,8 +0,3 @@ | ||
import { Component, DirectiveOptions, PluginFunction } from 'vue' | ||
import { Ref } from 'vue-demi' | ||
export interface CurrencyOptions { | ||
prefix?: string, | ||
suffix?: string | ||
} | ||
export interface DistractionFreeOptions { | ||
@@ -21,7 +16,7 @@ hideCurrencySymbol?: boolean, | ||
locale?: string, | ||
currency?: string | CurrencyOptions, | ||
currency: string, | ||
valueAsInteger?: boolean, | ||
distractionFree?: boolean | DistractionFreeOptions, | ||
precision?: number | NumberRange, | ||
autoDecimalMode?: boolean, | ||
autoDecimalDigits?: boolean, | ||
valueRange?: NumberRange, | ||
@@ -31,38 +26,13 @@ allowNegative?: boolean | ||
export interface PluginOptions { | ||
globalOptions?: CurrencyInputOptions, | ||
componentName?: string, | ||
directiveName?: string | ||
export interface ComposableOptions { | ||
inputRef: Ref, | ||
props: any, | ||
emit (event: string, value: number | null): void | ||
} | ||
export interface VueCurrencyInput { | ||
install: PluginFunction<PluginOptions> | ||
declare const useCurrencyInput: ({ emit, inputRef, props }: ComposableOptions) => { | ||
formattedValue: string | ||
} | ||
declare const VueCurrencyInput: VueCurrencyInput | ||
export default VueCurrencyInput | ||
export const CurrencyDirective: DirectiveOptions | ||
export const CurrencyInput: Component | ||
export function parse (formattedValue: string, options: CurrencyInputOptions): number | null | ||
export function getValue (el: HTMLInputElement): number | null | ||
export function setValue (el: HTMLInputElement, value: Number): void | ||
declare module 'vue/types/vue' { | ||
interface Vue { | ||
$ci: { | ||
globalOptions: CurrencyInputOptions | ||
parse (formattedValue: string, options: CurrencyInputOptions): number | null | ||
getValue (el: HTMLInputElement): number | null | ||
setValue (el: HTMLInputElement, value: Number): void | ||
} | ||
} | ||
} | ||
export default useCurrencyInput |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
42092
3
24
6
849
1
34
1
+ Addedvue-demi@^0.4.0
+ Added@jridgewell/sourcemap-codec@1.4.15(transitive)
+ Added@vue/compiler-core@3.4.27(transitive)
+ Added@vue/compiler-dom@3.4.27(transitive)
+ Added@vue/compiler-sfc@3.4.27(transitive)
+ Added@vue/compiler-ssr@3.4.27(transitive)
+ Added@vue/composition-api@1.7.2(transitive)
+ Added@vue/reactivity@3.4.27(transitive)
+ Added@vue/runtime-core@3.4.27(transitive)
+ Added@vue/runtime-dom@3.4.27(transitive)
+ Added@vue/server-renderer@3.4.27(transitive)
+ Added@vue/shared@3.4.27(transitive)
+ Addedentities@4.5.0(transitive)
+ Addedestree-walker@2.0.2(transitive)
+ Addedmagic-string@0.30.10(transitive)
+ Addedvue@2.6.143.4.27(transitive)
+ Addedvue-demi@0.4.5(transitive)
- Removed@vue/compiler-sfc@2.7.16(transitive)
- Removedprettier@2.8.8(transitive)
- Removedsource-map@0.6.1(transitive)
- Removedvue@2.7.16(transitive)