New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

vue-currency-input

Package Overview
Dependencies
Maintainers
1
Versions
91
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

vue-currency-input - npm Package Compare versions

Comparing version 1.21.0 to 1.22.0

src/caretPosition.js

445

dist/vue-currency-input.esm.js
/**
* Vue Currency Input 1.21.0
* Vue Currency Input 1.22.0
* (c) 2018-2020 Matthias Stiller
* @license MIT
*/
function dispatchEvent (el, eventName, data) {
var event = document.createEvent('CustomEvent');
event.initCustomEvent(eventName, true, true, data);
el.dispatchEvent(event);
}
var toExternalNumberModel = function (number, valueAsInteger, fractionDigits) {
return valueAsInteger && number != null ? Number(number.toFixed(fractionDigits).split('.').join('')) : number
};
var DEFAULT_OPTIONS = {
locale: undefined,
currency: 'EUR',
valueAsInteger: false,
distractionFree: true,
precision: undefined,
autoDecimalMode: false,
valueRange: undefined,
allowNegative: true
};
var getValue = function (el) {
var ref = el.$ci;
var numberValue = ref.numberValue;
var currencyFormat = ref.currencyFormat;
var options = ref.options;
return toExternalNumberModel(numberValue, options.valueAsInteger, currencyFormat.maximumFractionDigits)
};
var setValue = function (el, value) { return dispatchEvent(el, 'format', { value: value }); };
var escapeRegExp = function (str) { return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); };

@@ -41,54 +12,2 @@ var removeLeadingZeros = function (str) { return str.replace(/^0+(0$|[^0])/, '$1'); };

var setCaretPosition = function (el, position) { return el.setSelectionRange(position, position); };
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;
}
}
return options.distractionFree.hideCurrencySymbol
? newValue.length - caretPositionFromLeft
: Math.max(newValue.length - Math.max(caretPositionFromLeft, suffix.length), prefix.length === 0 ? 0 : prefix.length + 1)
}
};
var getDistractionFreeCaretPosition = function (numberFormat, options, value, caretPosition) {
var result = caretPosition;
if (options.distractionFree.hideCurrencySymbol) {
result -= numberFormat.prefix.length;
}
if (options.distractionFree.hideGroupingSymbol) {
result -= count(value.substring(0, caretPosition), numberFormat.groupingSymbol);
}
return Math.max(0, result)
};
var equal = function (a, b) {
if (a === b) {
return true
}
if (!a || !b || typeof a !== 'object' || typeof b !== 'object') {
return false
}
var keys = Object.keys(a);
if (keys.length !== Object.keys(b).length) {
return false
}
if (!keys.every(Object.prototype.hasOwnProperty.bind(b))) {
return false
}
return keys.every(function (key) { return equal(a[key], b[key]); })
};
var DECIMAL_SYMBOLS = [',', '.', '٫'];

@@ -132,11 +51,15 @@ var NumberFormat = function NumberFormat (options) {

};
NumberFormat.prototype.parse = function parse (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) {
return Number(("" + (negative ? '-' : '') + ((this.onlyDigits(match[1]))) + "." + ((this.onlyDigits(match[3] || '')))))
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
}
}

@@ -201,2 +124,38 @@ return null

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
}
if (!a || !b || typeof a !== 'object' || typeof b !== 'object') {
return false
}
var keys = Object.keys(a);
if (keys.length !== Object.keys(b).length) {
return false
}
if (!keys.every(Object.prototype.hasOwnProperty.bind(b))) {
return false
}
return keys.every(function (key) { return equal(a[key], b[key]); })
};
var DefaultNumberMask = function DefaultNumberMask (numberFormat) {

@@ -263,13 +222,50 @@ this.numberFormat = numberFormat;

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;
}
}
return options.distractionFree.hideCurrencySymbol
? newValue.length - caretPositionFromLeft
: Math.max(newValue.length - Math.max(caretPositionFromLeft, suffix.length), prefix.length === 0 ? 0 : prefix.length + 1)
}
};
var getDistractionFreeCaretPosition = function (numberFormat, options, value, caretPosition) {
var result = caretPosition;
if (options.distractionFree.hideCurrencySymbol) {
result -= numberFormat.prefix.length;
}
if (options.distractionFree.hideGroupingSymbol) {
result -= count(value.substring(0, caretPosition), numberFormat.groupingSymbol);
}
return Math.max(0, result)
};
var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1;
var init = function (el, optionsFromBinding, ref) {
var $ci = ref.$ci;
var inputElement = el.tagName.toLowerCase() === 'input' ? el : el.querySelector('input');
if (!inputElement) {
throw new Error('No input element found')
}
var options = Object.assign({}, ($ci ? $ci.GLOBAL_OPTIONS : DEFAULT_OPTIONS), optionsFromBinding);
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));
};
NumberInput.prototype.init = function init (newOptions) {
var options = Object.assign({}, newOptions);
var distractionFree = options.distractionFree;
var autoDecimalMode = options.autoDecimalMode;
var valueRange = options.valueRange;
var autoDecimalMode = options.autoDecimalMode;
var valueRange = options.valueRange;
if (typeof distractionFree === 'boolean') {

@@ -295,58 +291,51 @@ options.distractionFree = {

options.distractionFree.hideNegligibleDecimalDigits = false;
inputElement.setAttribute('inputmode', 'numeric');
this.el.setAttribute('inputmode', 'numeric');
} else {
inputElement.setAttribute('inputmode', 'decimal');
this.el.setAttribute('inputmode', 'decimal');
}
var currencyFormat = new NumberFormat(options);
inputElement.$ci = Object.assign({}, inputElement.$ci || { numberValue: null },
{options: options,
numberMask: options.autoDecimalMode ? new AutoDecimalModeNumberMask(currencyFormat) : new DefaultNumberMask(currencyFormat),
currencyFormat: currencyFormat});
return inputElement
this.options = options;
this.currencyFormat = new NumberFormat(this.options);
this.numberMask = options.autoDecimalMode ? new AutoDecimalModeNumberMask(this.currencyFormat) : new DefaultNumberMask(this.currencyFormat);
};
var triggerEvent = function (el, eventName) {
var ref = el.$ci;
var numberValue = ref.numberValue;
var currencyFormat = ref.currencyFormat;
var options = ref.options;
numberValue = toExternalNumberModel(numberValue, options.valueAsInteger, currencyFormat.maximumFractionDigits);
dispatchEvent(el, eventName, { numberValue: numberValue });
NumberInput.prototype.setOptions = function setOptions (options) {
this.init(options);
this.applyFixedFractionFormat(this.numberValue, true);
};
var applyFixedFractionFormat = function (el, value, forcedChange) {
if ( forcedChange === void 0 ) forcedChange = false;
var ref = el.$ci;
var currencyFormat = ref.currencyFormat;
var options = ref.options;
var ref$1 = options.valueRange;
var min = ref$1.min;
var max = ref$1.max;
var validateValueRange = function () { return Math.min(Math.max(value, min), max); };
format(el, value != null ? currencyFormat.format(validateValueRange()) : null);
if (value !== el.$ci.numberValue || forcedChange) {
triggerEvent(el, 'change');
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());
}
};
var updateInputValue = function (el, value, hideNegligibleDecimalDigits) {
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);
}
};
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) {
var ref = el.$ci;
var focus = ref.focus;
var decimalSymbolInsertedAt = ref.decimalSymbolInsertedAt;
var options = ref.options;
var numberMask = ref.numberMask;
var currencyFormat = ref.currencyFormat;
var previousConformedValue = ref.previousConformedValue;
var allowNegative = options.allowNegative;
var distractionFree = options.distractionFree;
if (decimalSymbolInsertedAt !== undefined) {
value = currencyFormat.normalizeDecimalSymbol(value, decimalSymbolInsertedAt);
el.$ci.decimalSymbolInsertedAt = undefined;
if (this.decimalSymbolInsertedAt !== undefined) {
value = this.currencyFormat.normalizeDecimalSymbol(value, this.decimalSymbolInsertedAt);
this.decimalSymbolInsertedAt = undefined;
}
var conformedValue = numberMask.conformToMask(value, previousConformedValue);
var conformedValue = this.numberMask.conformToMask(value, this.formattedValue);
var formattedValue;
if (typeof conformedValue === 'object') {
var numberValue = conformedValue.numberValue;
var fractionDigits = conformedValue.fractionDigits;
var maximumFractionDigits = currencyFormat.maximumFractionDigits;
var minimumFractionDigits = currencyFormat.minimumFractionDigits;
if (focus) {
var fractionDigits = conformedValue.fractionDigits;
var ref = this.currencyFormat;
var maximumFractionDigits = ref.maximumFractionDigits;
var minimumFractionDigits = ref.minimumFractionDigits;
if (this.focus) {
minimumFractionDigits = maximumFractionDigits;

@@ -358,5 +347,5 @@ }

formattedValue = numberValue > MAX_SAFE_INTEGER
? previousConformedValue
: currencyFormat.format(numberValue, {
useGrouping: !(focus && distractionFree.hideGroupingSymbol),
? this.formattedValue
: this.currencyFormat.format(numberValue, {
useGrouping: !(this.focus && this.options.distractionFree.hideGroupingSymbol),
minimumFractionDigits: minimumFractionDigits,

@@ -368,71 +357,52 @@ maximumFractionDigits: maximumFractionDigits

}
if (!allowNegative) {
formattedValue = formattedValue.replace(currencyFormat.negativePrefix, currencyFormat.prefix);
if (!this.options.allowNegative) {
formattedValue = formattedValue.replace(this.currencyFormat.negativePrefix, this.currencyFormat.prefix);
}
if (focus && distractionFree.hideCurrencySymbol) {
if (this.focus && this.options.distractionFree.hideCurrencySymbol) {
formattedValue = formattedValue
.replace(currencyFormat.negativePrefix, currencyFormat.minusSymbol)
.replace(currencyFormat.prefix, '')
.replace(currencyFormat.suffix, '');
.replace(this.currencyFormat.negativePrefix, this.currencyFormat.minusSymbol)
.replace(this.currencyFormat.prefix, '')
.replace(this.currencyFormat.suffix, '');
}
el.value = formattedValue;
el.$ci.numberValue = currencyFormat.parse(el.value);
this.el.value = formattedValue;
this.numberValue = this.currencyFormat.parse(formattedValue);
} else {
el.value = el.$ci.numberValue = null;
this.el.value = this.numberValue = null;
}
el.$ci.previousConformedValue = el.value;
this.formattedValue = this.el.value;
};
var format = function (el, value, hideNegligibleDecimalDigits) {
if ( hideNegligibleDecimalDigits === void 0 ) hideNegligibleDecimalDigits = false;
updateInputValue(el, value, hideNegligibleDecimalDigits);
triggerEvent(el, 'input');
NumberInput.prototype.format = function format (value) {
this.updateInputValue(value);
this.callbackFns.onInput(this.getValue());
};
var addEventListener = function (el) {
el.addEventListener('input', function (e) {
if (!e.detail) {
var value = el.value;
var selectionStart = el.selectionStart;
var el_$ci = el.$ci;
var currencyFormat = el_$ci.currencyFormat;
var options = el_$ci.options;
format(el, value);
if (el.$ci.focus) {
setCaretPosition(el, getCaretPositionAfterFormat(el.value, value, selectionStart, currencyFormat, options));
}
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 });
el.addEventListener('keypress', function (e) {
if (DECIMAL_SYMBOLS.includes(e.key)) {
el.$ci.decimalSymbolInsertedAt = el.selectionStart;
}
});
el.addEventListener('format', function (e) {
var ref = el.$ci;
var currencyFormat = ref.currencyFormat;
var options = ref.options;
var numberValue = ref.numberValue;
var toInternalNumberModel = function (n) { return options.valueAsInteger && n != null ? n / Math.pow(10, currencyFormat.maximumFractionDigits) : n; };
var newValue = toInternalNumberModel(e.detail.value);
if (numberValue !== newValue) {
applyFixedFractionFormat(el, newValue);
}
});
el.addEventListener('focus', function () {
el.$ci.focus = true;
var ref = el.$ci.options.distractionFree;
var hideCurrencySymbol = ref.hideCurrencySymbol;
var hideGroupingSymbol = ref.hideGroupingSymbol;
var hideNegligibleDecimalDigits = ref.hideNegligibleDecimalDigits;
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 value = el.value;
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
var ref = this$1.el;
var value = ref.value;
var selectionStart = ref.selectionStart;
var selectionEnd = ref.selectionEnd;
if (value) {
format(el, value, hideNegligibleDecimalDigits);
this$1.updateInputValue(this$1.el.value, hideNegligibleDecimalDigits);
}
if (Math.abs(selectionStart - selectionEnd) > 0) {
el.setSelectionRange(0, el.value.length);
this$1.setCaretPosition(0, this$1.el.value.length);
} else {
setCaretPosition(el, getDistractionFreeCaretPosition(el.$ci.currencyFormat, el.$ci.options, value, selectionStart));
this$1.setCaretPosition(getDistractionFreeCaretPosition(this$1.currencyFormat, this$1.options, value, selectionStart));
}

@@ -442,29 +412,47 @@ });

});
el.addEventListener('blur', function () {
el.$ci.focus = false;
if (el.$ci.numberValue != null) {
applyFixedFractionFormat(el, el.$ci.numberValue);
this.el.addEventListener('keypress', function (e) {
if (DECIMAL_SYMBOLS.includes(e.key)) {
this$1.decimalSymbolInsertedAt = this$1.el.selectionStart;
}
});
el.addEventListener('change', function (e) {
if (!e.detail) {
triggerEvent(el, 'change');
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, ref$1) {
var value = ref.value;
var context = ref$1.context;
var inputElement = init(el, value, context);
addEventListener(inputElement);
setValue(inputElement, inputElement.$ci.currencyFormat.parse(inputElement.value));
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].fns(vnode.componentOptions ? data : { target: { value: data } });
}
};
el.$ci = new NumberInput(inputElement, options, {
onChange: function () { return emit('change', inputElement.value); },
onInput: function () { emit('input', inputElement.value); }
});
},
componentUpdated: function componentUpdated (el, ref, ref$1) {
componentUpdated: function componentUpdated (el, ref) {
var value = ref.value;
var oldValue = ref.oldValue;
var context = ref$1.context;
if (!equal(value, oldValue)) {
var inputElement = init(el, value, context);
applyFixedFractionFormat(inputElement, inputElement.$ci.numberValue, true);
el.$ci.setOptions(value);
}

@@ -483,10 +471,9 @@ }

on: Object.assign({}, this.$listeners,
{change: function (e) {
if (e.detail) {
this$1.$emit('change', e.detail.numberValue);
}
{change: function () {
this$1.$emit('change', getValue(this$1.$el));
},
input: function (e) {
if (e.detail && this$1.value !== e.detail.numberValue) {
this$1.$emit('input', e.detail.numberValue);
input: function () {
var numberValue = getValue(this$1.$el);
if (this$1.value !== numberValue) {
this$1.$emit('input', numberValue);
}

@@ -544,3 +531,4 @@ }})

var this$1 = this;
var options = Object.assign({}, this.$ci ? this.$ci.GLOBAL_OPTIONS : DEFAULT_OPTIONS);
var options = Object.assign({}, DEFAULT_OPTIONS,
(this.$ci || {}).globalOptions);
Object.keys(DEFAULT_OPTIONS).forEach(function (key) {

@@ -573,5 +561,6 @@ if (this$1[key] !== undefined) {

Vue.prototype.$ci = {
parse: function (formattedValue, options) { return parse(formattedValue, Object.assign({}, globalOptions, options)); },
getValue: getValue,
setValue: setValue,
GLOBAL_OPTIONS: Object.assign({}, DEFAULT_OPTIONS, globalOptions)
globalOptions: globalOptions
};

@@ -578,0 +567,0 @@ }

/**
* Vue Currency Input 1.21.0
* Vue Currency Input 1.22.0
* (c) 2018-2020 Matthias Stiller

@@ -12,31 +12,2 @@ * @license MIT

function dispatchEvent (el, eventName, data) {
var event = document.createEvent('CustomEvent');
event.initCustomEvent(eventName, true, true, data);
el.dispatchEvent(event);
}
var toExternalNumberModel = function (number, valueAsInteger, fractionDigits) {
return valueAsInteger && number != null ? Number(number.toFixed(fractionDigits).split('.').join('')) : number
};
var DEFAULT_OPTIONS = {
locale: undefined,
currency: 'EUR',
valueAsInteger: false,
distractionFree: true,
precision: undefined,
autoDecimalMode: false,
valueRange: undefined,
allowNegative: true
};
var getValue = function (el) {
var ref = el.$ci;
var numberValue = ref.numberValue;
var currencyFormat = ref.currencyFormat;
var options = ref.options;
return toExternalNumberModel(numberValue, options.valueAsInteger, currencyFormat.maximumFractionDigits)
};
var setValue = function (el, value) { return dispatchEvent(el, 'format', { value: value }); };
var escapeRegExp = function (str) { return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); };

@@ -48,54 +19,2 @@ var removeLeadingZeros = function (str) { return str.replace(/^0+(0$|[^0])/, '$1'); };

var setCaretPosition = function (el, position) { return el.setSelectionRange(position, position); };
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;
}
}
return options.distractionFree.hideCurrencySymbol
? newValue.length - caretPositionFromLeft
: Math.max(newValue.length - Math.max(caretPositionFromLeft, suffix.length), prefix.length === 0 ? 0 : prefix.length + 1)
}
};
var getDistractionFreeCaretPosition = function (numberFormat, options, value, caretPosition) {
var result = caretPosition;
if (options.distractionFree.hideCurrencySymbol) {
result -= numberFormat.prefix.length;
}
if (options.distractionFree.hideGroupingSymbol) {
result -= count(value.substring(0, caretPosition), numberFormat.groupingSymbol);
}
return Math.max(0, result)
};
var equal = function (a, b) {
if (a === b) {
return true
}
if (!a || !b || typeof a !== 'object' || typeof b !== 'object') {
return false
}
var keys = Object.keys(a);
if (keys.length !== Object.keys(b).length) {
return false
}
if (!keys.every(Object.prototype.hasOwnProperty.bind(b))) {
return false
}
return keys.every(function (key) { return equal(a[key], b[key]); })
};
var DECIMAL_SYMBOLS = [',', '.', '٫'];

@@ -139,11 +58,15 @@ var NumberFormat = function NumberFormat (options) {

};
NumberFormat.prototype.parse = function parse (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) {
return Number(("" + (negative ? '-' : '') + ((this.onlyDigits(match[1]))) + "." + ((this.onlyDigits(match[3] || '')))))
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
}
}

@@ -208,2 +131,38 @@ return null

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
}
if (!a || !b || typeof a !== 'object' || typeof b !== 'object') {
return false
}
var keys = Object.keys(a);
if (keys.length !== Object.keys(b).length) {
return false
}
if (!keys.every(Object.prototype.hasOwnProperty.bind(b))) {
return false
}
return keys.every(function (key) { return equal(a[key], b[key]); })
};
var DefaultNumberMask = function DefaultNumberMask (numberFormat) {

@@ -270,13 +229,50 @@ this.numberFormat = numberFormat;

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;
}
}
return options.distractionFree.hideCurrencySymbol
? newValue.length - caretPositionFromLeft
: Math.max(newValue.length - Math.max(caretPositionFromLeft, suffix.length), prefix.length === 0 ? 0 : prefix.length + 1)
}
};
var getDistractionFreeCaretPosition = function (numberFormat, options, value, caretPosition) {
var result = caretPosition;
if (options.distractionFree.hideCurrencySymbol) {
result -= numberFormat.prefix.length;
}
if (options.distractionFree.hideGroupingSymbol) {
result -= count(value.substring(0, caretPosition), numberFormat.groupingSymbol);
}
return Math.max(0, result)
};
var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1;
var init = function (el, optionsFromBinding, ref) {
var $ci = ref.$ci;
var inputElement = el.tagName.toLowerCase() === 'input' ? el : el.querySelector('input');
if (!inputElement) {
throw new Error('No input element found')
}
var options = Object.assign({}, ($ci ? $ci.GLOBAL_OPTIONS : DEFAULT_OPTIONS), optionsFromBinding);
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));
};
NumberInput.prototype.init = function init (newOptions) {
var options = Object.assign({}, newOptions);
var distractionFree = options.distractionFree;
var autoDecimalMode = options.autoDecimalMode;
var valueRange = options.valueRange;
var autoDecimalMode = options.autoDecimalMode;
var valueRange = options.valueRange;
if (typeof distractionFree === 'boolean') {

@@ -302,58 +298,51 @@ options.distractionFree = {

options.distractionFree.hideNegligibleDecimalDigits = false;
inputElement.setAttribute('inputmode', 'numeric');
this.el.setAttribute('inputmode', 'numeric');
} else {
inputElement.setAttribute('inputmode', 'decimal');
this.el.setAttribute('inputmode', 'decimal');
}
var currencyFormat = new NumberFormat(options);
inputElement.$ci = Object.assign({}, inputElement.$ci || { numberValue: null },
{options: options,
numberMask: options.autoDecimalMode ? new AutoDecimalModeNumberMask(currencyFormat) : new DefaultNumberMask(currencyFormat),
currencyFormat: currencyFormat});
return inputElement
this.options = options;
this.currencyFormat = new NumberFormat(this.options);
this.numberMask = options.autoDecimalMode ? new AutoDecimalModeNumberMask(this.currencyFormat) : new DefaultNumberMask(this.currencyFormat);
};
var triggerEvent = function (el, eventName) {
var ref = el.$ci;
var numberValue = ref.numberValue;
var currencyFormat = ref.currencyFormat;
var options = ref.options;
numberValue = toExternalNumberModel(numberValue, options.valueAsInteger, currencyFormat.maximumFractionDigits);
dispatchEvent(el, eventName, { numberValue: numberValue });
NumberInput.prototype.setOptions = function setOptions (options) {
this.init(options);
this.applyFixedFractionFormat(this.numberValue, true);
};
var applyFixedFractionFormat = function (el, value, forcedChange) {
if ( forcedChange === void 0 ) forcedChange = false;
var ref = el.$ci;
var currencyFormat = ref.currencyFormat;
var options = ref.options;
var ref$1 = options.valueRange;
var min = ref$1.min;
var max = ref$1.max;
var validateValueRange = function () { return Math.min(Math.max(value, min), max); };
format(el, value != null ? currencyFormat.format(validateValueRange()) : null);
if (value !== el.$ci.numberValue || forcedChange) {
triggerEvent(el, 'change');
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());
}
};
var updateInputValue = function (el, value, hideNegligibleDecimalDigits) {
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);
}
};
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) {
var ref = el.$ci;
var focus = ref.focus;
var decimalSymbolInsertedAt = ref.decimalSymbolInsertedAt;
var options = ref.options;
var numberMask = ref.numberMask;
var currencyFormat = ref.currencyFormat;
var previousConformedValue = ref.previousConformedValue;
var allowNegative = options.allowNegative;
var distractionFree = options.distractionFree;
if (decimalSymbolInsertedAt !== undefined) {
value = currencyFormat.normalizeDecimalSymbol(value, decimalSymbolInsertedAt);
el.$ci.decimalSymbolInsertedAt = undefined;
if (this.decimalSymbolInsertedAt !== undefined) {
value = this.currencyFormat.normalizeDecimalSymbol(value, this.decimalSymbolInsertedAt);
this.decimalSymbolInsertedAt = undefined;
}
var conformedValue = numberMask.conformToMask(value, previousConformedValue);
var conformedValue = this.numberMask.conformToMask(value, this.formattedValue);
var formattedValue;
if (typeof conformedValue === 'object') {
var numberValue = conformedValue.numberValue;
var fractionDigits = conformedValue.fractionDigits;
var maximumFractionDigits = currencyFormat.maximumFractionDigits;
var minimumFractionDigits = currencyFormat.minimumFractionDigits;
if (focus) {
var fractionDigits = conformedValue.fractionDigits;
var ref = this.currencyFormat;
var maximumFractionDigits = ref.maximumFractionDigits;
var minimumFractionDigits = ref.minimumFractionDigits;
if (this.focus) {
minimumFractionDigits = maximumFractionDigits;

@@ -365,5 +354,5 @@ }

formattedValue = numberValue > MAX_SAFE_INTEGER
? previousConformedValue
: currencyFormat.format(numberValue, {
useGrouping: !(focus && distractionFree.hideGroupingSymbol),
? this.formattedValue
: this.currencyFormat.format(numberValue, {
useGrouping: !(this.focus && this.options.distractionFree.hideGroupingSymbol),
minimumFractionDigits: minimumFractionDigits,

@@ -375,71 +364,52 @@ maximumFractionDigits: maximumFractionDigits

}
if (!allowNegative) {
formattedValue = formattedValue.replace(currencyFormat.negativePrefix, currencyFormat.prefix);
if (!this.options.allowNegative) {
formattedValue = formattedValue.replace(this.currencyFormat.negativePrefix, this.currencyFormat.prefix);
}
if (focus && distractionFree.hideCurrencySymbol) {
if (this.focus && this.options.distractionFree.hideCurrencySymbol) {
formattedValue = formattedValue
.replace(currencyFormat.negativePrefix, currencyFormat.minusSymbol)
.replace(currencyFormat.prefix, '')
.replace(currencyFormat.suffix, '');
.replace(this.currencyFormat.negativePrefix, this.currencyFormat.minusSymbol)
.replace(this.currencyFormat.prefix, '')
.replace(this.currencyFormat.suffix, '');
}
el.value = formattedValue;
el.$ci.numberValue = currencyFormat.parse(el.value);
this.el.value = formattedValue;
this.numberValue = this.currencyFormat.parse(formattedValue);
} else {
el.value = el.$ci.numberValue = null;
this.el.value = this.numberValue = null;
}
el.$ci.previousConformedValue = el.value;
this.formattedValue = this.el.value;
};
var format = function (el, value, hideNegligibleDecimalDigits) {
if ( hideNegligibleDecimalDigits === void 0 ) hideNegligibleDecimalDigits = false;
updateInputValue(el, value, hideNegligibleDecimalDigits);
triggerEvent(el, 'input');
NumberInput.prototype.format = function format (value) {
this.updateInputValue(value);
this.callbackFns.onInput(this.getValue());
};
var addEventListener = function (el) {
el.addEventListener('input', function (e) {
if (!e.detail) {
var value = el.value;
var selectionStart = el.selectionStart;
var el_$ci = el.$ci;
var currencyFormat = el_$ci.currencyFormat;
var options = el_$ci.options;
format(el, value);
if (el.$ci.focus) {
setCaretPosition(el, getCaretPositionAfterFormat(el.value, value, selectionStart, currencyFormat, options));
}
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 });
el.addEventListener('keypress', function (e) {
if (DECIMAL_SYMBOLS.includes(e.key)) {
el.$ci.decimalSymbolInsertedAt = el.selectionStart;
}
});
el.addEventListener('format', function (e) {
var ref = el.$ci;
var currencyFormat = ref.currencyFormat;
var options = ref.options;
var numberValue = ref.numberValue;
var toInternalNumberModel = function (n) { return options.valueAsInteger && n != null ? n / Math.pow(10, currencyFormat.maximumFractionDigits) : n; };
var newValue = toInternalNumberModel(e.detail.value);
if (numberValue !== newValue) {
applyFixedFractionFormat(el, newValue);
}
});
el.addEventListener('focus', function () {
el.$ci.focus = true;
var ref = el.$ci.options.distractionFree;
var hideCurrencySymbol = ref.hideCurrencySymbol;
var hideGroupingSymbol = ref.hideGroupingSymbol;
var hideNegligibleDecimalDigits = ref.hideNegligibleDecimalDigits;
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 value = el.value;
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
var ref = this$1.el;
var value = ref.value;
var selectionStart = ref.selectionStart;
var selectionEnd = ref.selectionEnd;
if (value) {
format(el, value, hideNegligibleDecimalDigits);
this$1.updateInputValue(this$1.el.value, hideNegligibleDecimalDigits);
}
if (Math.abs(selectionStart - selectionEnd) > 0) {
el.setSelectionRange(0, el.value.length);
this$1.setCaretPosition(0, this$1.el.value.length);
} else {
setCaretPosition(el, getDistractionFreeCaretPosition(el.$ci.currencyFormat, el.$ci.options, value, selectionStart));
this$1.setCaretPosition(getDistractionFreeCaretPosition(this$1.currencyFormat, this$1.options, value, selectionStart));
}

@@ -449,29 +419,47 @@ });

});
el.addEventListener('blur', function () {
el.$ci.focus = false;
if (el.$ci.numberValue != null) {
applyFixedFractionFormat(el, el.$ci.numberValue);
this.el.addEventListener('keypress', function (e) {
if (DECIMAL_SYMBOLS.includes(e.key)) {
this$1.decimalSymbolInsertedAt = this$1.el.selectionStart;
}
});
el.addEventListener('change', function (e) {
if (!e.detail) {
triggerEvent(el, 'change');
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, ref$1) {
var value = ref.value;
var context = ref$1.context;
var inputElement = init(el, value, context);
addEventListener(inputElement);
setValue(inputElement, inputElement.$ci.currencyFormat.parse(inputElement.value));
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].fns(vnode.componentOptions ? data : { target: { value: data } });
}
};
el.$ci = new NumberInput(inputElement, options, {
onChange: function () { return emit('change', inputElement.value); },
onInput: function () { emit('input', inputElement.value); }
});
},
componentUpdated: function componentUpdated (el, ref, ref$1) {
componentUpdated: function componentUpdated (el, ref) {
var value = ref.value;
var oldValue = ref.oldValue;
var context = ref$1.context;
if (!equal(value, oldValue)) {
var inputElement = init(el, value, context);
applyFixedFractionFormat(inputElement, inputElement.$ci.numberValue, true);
el.$ci.setOptions(value);
}

@@ -490,10 +478,9 @@ }

on: Object.assign({}, this.$listeners,
{change: function (e) {
if (e.detail) {
this$1.$emit('change', e.detail.numberValue);
}
{change: function () {
this$1.$emit('change', getValue(this$1.$el));
},
input: function (e) {
if (e.detail && this$1.value !== e.detail.numberValue) {
this$1.$emit('input', e.detail.numberValue);
input: function () {
var numberValue = getValue(this$1.$el);
if (this$1.value !== numberValue) {
this$1.$emit('input', numberValue);
}

@@ -551,3 +538,4 @@ }})

var this$1 = this;
var options = Object.assign({}, this.$ci ? this.$ci.GLOBAL_OPTIONS : DEFAULT_OPTIONS);
var options = Object.assign({}, DEFAULT_OPTIONS,
(this.$ci || {}).globalOptions);
Object.keys(DEFAULT_OPTIONS).forEach(function (key) {

@@ -580,5 +568,6 @@ if (this$1[key] !== undefined) {

Vue.prototype.$ci = {
parse: function (formattedValue, options) { return parse(formattedValue, Object.assign({}, globalOptions, options)); },
getValue: getValue,
setValue: setValue,
GLOBAL_OPTIONS: Object.assign({}, DEFAULT_OPTIONS, globalOptions)
globalOptions: globalOptions
};

@@ -585,0 +574,0 @@ }

{
"name": "vue-currency-input",
"description": "Easy input of currency formatted numbers for Vue.js.",
"version": "1.21.0",
"version": "1.22.0",
"license": "MIT",

@@ -60,3 +60,2 @@ "unpkg": "dist/vue-currency-input.umd.js",

"eslint-plugin-vue": "^6.2.2",
"node-sass": "^4.13.0",
"rollup": "^2.15.0",

@@ -66,3 +65,2 @@ "rollup-plugin-buble": "^0.19.8",

"rollup-plugin-filesize": "^9.0.0",
"sass-loader": "^8.0.0",
"vue": "^2.6.11",

@@ -69,0 +67,0 @@ "vue-template-compiler": "^2.6.11",

@@ -1,3 +0,2 @@

import dispatchEvent from './utils/dispatchEvent'
import { toExternalNumberModel } from './utils/numberUtils'
import NumberFormat from './numberFormat'

@@ -16,11 +15,20 @@ export const DEFAULT_OPTIONS = {

/**
* Parses a number from a currency formatted string.
*
* @param {String} formattedValue The currency formatted string to be parsed, for example `$1,234.50`.
* @param {Object} options The configured options of the respective `v-currency` directive.
* @returns {Number | null} The parsed number or `null` if the formatted string does not match.
*/
export const parse = (formattedValue, options) => {
const mergedOptions = { ...DEFAULT_OPTIONS, ...options }
return new NumberFormat(mergedOptions).parse(formattedValue, mergedOptions.valueAsInteger)
}
/**
* Returns the current number value of an input.
*
* @param {HTMLInputElement} el The input element the `v-currency` directive is bound to.
* @param ref {Element | VueConstructor} The element or Vue component the `v-currency` directive is bound to.
* @returns {Number | null} The current number value or `null` if empty.
*/
export const getValue = el => {
const { numberValue, currencyFormat, options } = el.$ci
return toExternalNumberModel(numberValue, options.valueAsInteger, currencyFormat.maximumFractionDigits)
}
export const getValue = (ref) => (ref.$el || ref).$ci.getValue()

@@ -30,5 +38,7 @@ /**

*
* @param {HTMLInputElement} el The input element the `v-currency` directive is bound to.
* @param ref {Element | VueConstructor} The element or Vue component the `v-currency` directive is bound to.
* @param {Number} value The number to be set.
*/
export const setValue = (el, value) => dispatchEvent(el, 'format', { value })
export const setValue = (ref, value) => {
(ref.$el || ref).$ci.setValue(value)
}

@@ -1,2 +0,2 @@

import { DEFAULT_OPTIONS, setValue } from './api'
import { DEFAULT_OPTIONS, getValue, setValue } from './api'
import currencyDirective from './directive'

@@ -13,10 +13,9 @@

...this.$listeners,
change: e => {
if (e.detail) {
this.$emit('change', e.detail.numberValue)
}
change: () => {
this.$emit('change', getValue(this.$el))
},
input: e => {
if (e.detail && this.value !== e.detail.numberValue) {
this.$emit('input', e.detail.numberValue)
input: () => {
const numberValue = getValue(this.$el)
if (this.value !== numberValue) {
this.$emit('input', numberValue)
}

@@ -74,4 +73,7 @@ }

options () {
const options = { ...this.$ci ? this.$ci.GLOBAL_OPTIONS : DEFAULT_OPTIONS }
Object.keys(DEFAULT_OPTIONS).forEach(key => {
const options = {
...DEFAULT_OPTIONS,
...(this.$ci || {}).globalOptions
}
Object.keys(DEFAULT_OPTIONS).forEach((key) => {
if (this[key] !== undefined) {

@@ -78,0 +80,0 @@ options[key] = this[key]

@@ -1,191 +0,34 @@

import { DEFAULT_OPTIONS, setValue } from './api'
import { getCaretPositionAfterFormat, getDistractionFreeCaretPosition, setCaretPosition } from './utils/caretPosition'
import dispatchEvent from './utils/dispatchEvent'
import { DEFAULT_OPTIONS } from './api'
import equal from './utils/equal'
import { toExternalNumberModel } from './utils/numberUtils'
import NumberFormat, { DECIMAL_SYMBOLS } from './numberFormat'
import { AutoDecimalModeNumberMask, DefaultNumberMask } from './numberMask'
import { NumberInput } from './numberInput'
const MAX_SAFE_INTEGER = Math.pow(2, 53) - 1
const init = (el, optionsFromBinding, { $ci }) => {
const inputElement = el.tagName.toLowerCase() === 'input' ? el : el.querySelector('input')
if (!inputElement) {
throw new Error('No input element found')
}
const options = { ...($ci ? $ci.GLOBAL_OPTIONS : DEFAULT_OPTIONS), ...optionsFromBinding }
const { distractionFree, autoDecimalMode, valueRange } = options
if (typeof distractionFree === 'boolean') {
options.distractionFree = {
hideCurrencySymbol: distractionFree,
hideNegligibleDecimalDigits: distractionFree,
hideGroupingSymbol: distractionFree
export default {
bind (el, { value: optionsFromBinding }, vnode) {
const inputElement = el.tagName.toLowerCase() === 'input' ? el : el.querySelector('input')
if (!inputElement) {
throw new Error('No input element found')
}
}
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
const options = {
...DEFAULT_OPTIONS,
...(vnode.context.$ci || {}).globalOptions,
...optionsFromBinding
}
} else {
options.valueRange = {
min: -MAX_SAFE_INTEGER,
max: MAX_SAFE_INTEGER
}
}
const listeners = (vnode.data && vnode.data.on) || (vnode.componentOptions && vnode.componentOptions.listeners)
if (autoDecimalMode) {
options.distractionFree.hideNegligibleDecimalDigits = false
inputElement.setAttribute('inputmode', 'numeric')
} else {
inputElement.setAttribute('inputmode', 'decimal')
}
const currencyFormat = new NumberFormat(options)
inputElement.$ci = {
...inputElement.$ci || { numberValue: null },
options,
numberMask: options.autoDecimalMode ? new AutoDecimalModeNumberMask(currencyFormat) : new DefaultNumberMask(currencyFormat),
currencyFormat
}
return inputElement
}
const triggerEvent = (el, eventName) => {
let { numberValue, currencyFormat, options } = el.$ci
numberValue = toExternalNumberModel(numberValue, options.valueAsInteger, currencyFormat.maximumFractionDigits)
dispatchEvent(el, eventName, { numberValue })
}
const applyFixedFractionFormat = (el, value, forcedChange = false) => {
const { currencyFormat, options } = el.$ci
const { min, max } = options.valueRange
const validateValueRange = () => Math.min(Math.max(value, min), max)
format(el, value != null ? currencyFormat.format(validateValueRange()) : null)
if (value !== el.$ci.numberValue || forcedChange) {
triggerEvent(el, 'change')
}
}
const updateInputValue = (el, value, hideNegligibleDecimalDigits) => {
if (value != null) {
const { focus, decimalSymbolInsertedAt, options, numberMask, currencyFormat, previousConformedValue } = el.$ci
const { allowNegative, distractionFree } = options
if (decimalSymbolInsertedAt !== undefined) {
value = currencyFormat.normalizeDecimalSymbol(value, decimalSymbolInsertedAt)
el.$ci.decimalSymbolInsertedAt = undefined
}
const conformedValue = numberMask.conformToMask(value, previousConformedValue)
let formattedValue
if (typeof conformedValue === 'object') {
const { numberValue, fractionDigits } = conformedValue
let { maximumFractionDigits, minimumFractionDigits } = currencyFormat
if (focus) {
minimumFractionDigits = maximumFractionDigits
const emit = (event, data) => {
if (listeners[event]) {
listeners[event].fns(vnode.componentOptions ? data : { target: { value: data } })
}
minimumFractionDigits = hideNegligibleDecimalDigits
? fractionDigits.replace(/0+$/, '').length
: Math.min(minimumFractionDigits, fractionDigits.length)
formattedValue = numberValue > MAX_SAFE_INTEGER
? previousConformedValue
: currencyFormat.format(numberValue, {
useGrouping: !(focus && distractionFree.hideGroupingSymbol),
minimumFractionDigits,
maximumFractionDigits
})
} else {
formattedValue = conformedValue
}
if (!allowNegative) {
formattedValue = formattedValue.replace(currencyFormat.negativePrefix, currencyFormat.prefix)
}
if (focus && distractionFree.hideCurrencySymbol) {
formattedValue = formattedValue
.replace(currencyFormat.negativePrefix, currencyFormat.minusSymbol)
.replace(currencyFormat.prefix, '')
.replace(currencyFormat.suffix, '')
}
el.value = formattedValue
el.$ci.numberValue = currencyFormat.parse(el.value)
} else {
el.value = el.$ci.numberValue = null
}
el.$ci.previousConformedValue = el.value
}
const format = (el, value, hideNegligibleDecimalDigits = false) => {
updateInputValue(el, value, hideNegligibleDecimalDigits)
triggerEvent(el, 'input')
}
const addEventListener = el => {
el.addEventListener('input', e => {
if (!e.detail) {
const { value, selectionStart, $ci: { currencyFormat, options } } = el
format(el, value)
if (el.$ci.focus) {
setCaretPosition(el, getCaretPositionAfterFormat(el.value, value, selectionStart, currencyFormat, options))
}
}
}, { capture: true })
el.addEventListener('keypress', e => {
if (DECIMAL_SYMBOLS.includes(e.key)) {
el.$ci.decimalSymbolInsertedAt = el.selectionStart
}
})
el.addEventListener('format', e => {
const { currencyFormat, options, numberValue } = el.$ci
const toInternalNumberModel = n => options.valueAsInteger && n != null ? n / Math.pow(10, currencyFormat.maximumFractionDigits) : n
const newValue = toInternalNumberModel(e.detail.value)
if (numberValue !== newValue) {
applyFixedFractionFormat(el, newValue)
}
})
el.addEventListener('focus', () => {
el.$ci.focus = true
const { hideCurrencySymbol, hideGroupingSymbol, hideNegligibleDecimalDigits } = el.$ci.options.distractionFree
if (hideCurrencySymbol || hideGroupingSymbol || hideNegligibleDecimalDigits) {
setTimeout(() => {
const { value, selectionStart, selectionEnd } = el
if (value) {
format(el, value, hideNegligibleDecimalDigits)
}
if (Math.abs(selectionStart - selectionEnd) > 0) {
el.setSelectionRange(0, el.value.length)
} else {
setCaretPosition(el, getDistractionFreeCaretPosition(el.$ci.currencyFormat, el.$ci.options, value, selectionStart))
}
})
}
})
el.addEventListener('blur', () => {
el.$ci.focus = false
if (el.$ci.numberValue != null) {
applyFixedFractionFormat(el, el.$ci.numberValue)
}
})
el.addEventListener('change', e => {
if (!e.detail) {
triggerEvent(el, 'change')
}
})
}
export default {
bind (el, { value }, { context }) {
const inputElement = init(el, value, context)
addEventListener(inputElement)
setValue(inputElement, inputElement.$ci.currencyFormat.parse(inputElement.value))
el.$ci = new NumberInput(inputElement, options, {
onChange: () => emit('change', inputElement.value),
onInput: () => { emit('input', inputElement.value) }
})
},
componentUpdated (el, { value, oldValue }, { context }) {
componentUpdated (el, { value, oldValue }) {
if (!equal(value, oldValue)) {
const inputElement = init(el, value, context)
applyFixedFractionFormat(inputElement, inputElement.$ci.numberValue, true)
el.$ci.setOptions(value)
}
}
}

@@ -48,2 +48,4 @@ import { Component, DirectiveOptions, PluginFunction } from 'vue'

export function parse (formattedValue: string, options: CurrencyInputOptions): number | null
export function getValue (el: HTMLInputElement): number | null

@@ -55,8 +57,12 @@

interface Vue {
GLOBAL_OPTIONS: CurrencyInputOptions
$ci: {
globalOptions: CurrencyInputOptions
$getValue (el: HTMLInputElement): number | null
parse (formattedValue: string, options: CurrencyInputOptions): number | null
$setValue (el: HTMLInputElement, value: Number): void
getValue (el: HTMLInputElement): number | null
setValue (el: HTMLInputElement, value: Number): void
}
}
}

@@ -13,3 +13,3 @@ import { count, escapeRegExp, startsWith, substringBefore } from './utils/stringUtils'

this.currency = currency
this.digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(i => i.toLocaleString(locale))
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

@@ -44,11 +44,14 @@ this.groupingSymbol = ps.substr(ps.indexOf(this.digits[3]) + 1, 1)

parse (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] || ''))}`)
parse (str, valueAsInteger = false) {
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) {
const number = Number(`${negative ? '-' : ''}${(this.onlyDigits(match[1]))}.${(this.onlyDigits(match[3] || ''))}`)
return valueAsInteger ? Number(number.toFixed(this.maximumFractionDigits).split('.').join('')) : number
}
}

@@ -102,3 +105,3 @@ return null

normalizeDecimalSymbol (str, from) {
DECIMAL_SYMBOLS.forEach(s => {
DECIMAL_SYMBOLS.forEach((s) => {
str = str.substr(0, from) + str.substr(from).replace(s, this.decimalSymbol)

@@ -105,0 +108,0 @@ })

@@ -1,2 +0,2 @@

import { DEFAULT_OPTIONS, getValue, setValue } from './api'
import { getValue, parse, setValue } from './api'
import component from './component'

@@ -14,7 +14,8 @@ import directive from './directive'

Vue.prototype.$ci = {
parse: (formattedValue, options) => parse(formattedValue, { ...globalOptions, ...options }),
getValue,
setValue,
GLOBAL_OPTIONS: { ...DEFAULT_OPTIONS, ...globalOptions }
globalOptions
}
}
}

@@ -15,5 +15,5 @@ const equal = (a, b) => {

}
return keys.every(key => equal(a[key], b[key]))
return keys.every((key) => equal(a[key], b[key]))
}
export default equal
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc