UNPKG

@handcrafted-market/vue3-numeric

Version:

Input field component to display currency value based on vue-numeric.

401 lines (400 loc) 12.3 kB
import { toRefs, ref, computed, watch, nextTick, onMounted, unref, withDirectives, openBlock, createElementBlock, vModelText, toDisplayString } from "vue"; function __commonjs(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } var settings = { symbol: "$", format: "%s%v", decimal: ".", thousand: ",", precision: 2, grouping: 3, stripZeros: false, fallback: 0 }; function unformat(value) { var decimal = arguments.length <= 1 || arguments[1] === void 0 ? settings.decimal : arguments[1]; var fallback = arguments.length <= 2 || arguments[2] === void 0 ? settings.fallback : arguments[2]; if (Array.isArray(value)) { return value.map(function(val) { return unformat(val, decimal, fallback); }); } if (typeof value === "number") return value; var regex = new RegExp("[^0-9-(-)-" + decimal + "]", ["g"]); var unformattedValueString = ("" + value).replace(regex, "").replace(decimal, ".").replace(/\(([-]*\d*[^)]?\d+)\)/g, "-$1").replace(/\((.*)\)/, ""); var negative = (unformattedValueString.match(/-/g) || 2).length % 2, absUnformatted = parseFloat(unformattedValueString.replace(/-/g, "")), unformatted = absUnformatted * (negative ? -1 : 1); return !isNaN(unformatted) ? unformatted : fallback; } function _checkPrecision(val, base) { val = Math.round(Math.abs(val)); return isNaN(val) ? base : val; } function toFixed(value, precision) { precision = _checkPrecision(precision, settings.precision); var power = Math.pow(10, precision); return (Math.round((value + 1e-8) * power) / power).toFixed(precision); } var index = __commonjs(function(module) { var hasOwnProperty = Object.prototype.hasOwnProperty; var propIsEnumerable = Object.prototype.propertyIsEnumerable; function toObject(val) { if (val === null || val === void 0) { throw new TypeError("Object.assign cannot be called with null or undefined"); } return Object(val); } module.exports = Object.assign || function(target, source) { var from; var to = toObject(target); var symbols; for (var s = 1; s < arguments.length; s++) { from = Object(arguments[s]); for (var key in from) { if (hasOwnProperty.call(from, key)) { to[key] = from[key]; } } if (Object.getOwnPropertySymbols) { symbols = Object.getOwnPropertySymbols(from); for (var i = 0; i < symbols.length; i++) { if (propIsEnumerable.call(from, symbols[i])) { to[symbols[i]] = from[symbols[i]]; } } } } return to; }; }); var objectAssign = index && typeof index === "object" && "default" in index ? index["default"] : index; function _stripInsignificantZeros(str, decimal) { var parts = str.split(decimal); var integerPart = parts[0]; var decimalPart = parts[1].replace(/0+$/, ""); if (decimalPart.length > 0) { return integerPart + decimal + decimalPart; } return integerPart; } function formatNumber(number) { var opts = arguments.length <= 1 || arguments[1] === void 0 ? {} : arguments[1]; if (Array.isArray(number)) { return number.map(function(val) { return formatNumber(val, opts); }); } opts = objectAssign({}, settings, opts); var negative = number < 0 ? "-" : ""; var base = parseInt(toFixed(Math.abs(number), opts.precision), 10) + ""; var mod = base.length > 3 ? base.length % 3 : 0; var formatted = negative + (mod ? base.substr(0, mod) + opts.thousand : "") + base.substr(mod).replace(/(\d{3})(?=\d)/g, "$1" + opts.thousand) + (opts.precision > 0 ? opts.decimal + toFixed(Math.abs(number), opts.precision).split(".")[1] : ""); return opts.stripZeros ? _stripInsignificantZeros(formatted, opts.decimal) : formatted; } var index$1 = __commonjs(function(module) { var strValue = String.prototype.valueOf; var tryStringObject = function tryStringObject2(value) { try { strValue.call(value); return true; } catch (e) { return false; } }; var toStr = Object.prototype.toString; var strClass = "[object String]"; var hasToStringTag = typeof Symbol === "function" && typeof Symbol.toStringTag === "symbol"; module.exports = function isString2(value) { if (typeof value === "string") { return true; } if (typeof value !== "object") { return false; } return hasToStringTag ? tryStringObject(value) : toStr.call(value) === strClass; }; }); var isString = index$1 && typeof index$1 === "object" && "default" in index$1 ? index$1["default"] : index$1; function _checkCurrencyFormat(format) { if (isString(format) && format.match("%v")) { return { pos: format, neg: format.replace("-", "").replace("%v", "-%v"), zero: format }; } return format; } function formatMoney(number) { var opts = arguments.length <= 1 || arguments[1] === void 0 ? {} : arguments[1]; if (Array.isArray(number)) { return number.map(function(val) { return formatMoney(val, opts); }); } opts = objectAssign({}, settings, opts); var formats = _checkCurrencyFormat(opts.format); var useFormat = void 0; if (number > 0) { useFormat = formats.pos; } else if (number < 0) { useFormat = formats.neg; } else { useFormat = formats.zero; } return useFormat.replace("%s", opts.symbol).replace("%v", formatNumber(Math.abs(number), opts)); } const _hoisted_1 = ["placeholder", "disabled"]; const _sfc_main = { props: { currency: { type: String, default: "", required: false }, max: { type: Number, default: Number.MAX_SAFE_INTEGER || 9007199254740991, required: false }, min: { type: Number, default: Number.MIN_SAFE_INTEGER || -9007199254740991, required: false }, minus: { type: Boolean, default: false, required: false }, placeholder: { type: String, default: "", required: false }, emptyValue: { type: [Number, String], default: "", required: false }, precision: { type: Number, default: 0, required: false }, separator: { type: String, default: ",", required: false }, thousandSeparator: { default: void 0, required: false, type: String }, decimalSeparator: { default: void 0, required: false, type: String }, outputType: { required: false, type: String, default: "Number" }, modelValue: { type: [Number, String], default: 0, required: true }, readOnly: { type: Boolean, default: false, required: false }, readOnlyClass: { type: String, default: "", required: false }, disabled: { type: Boolean, default: false, required: false }, currencySymbolPosition: { type: String, default: "prefix", required: false }, currencySymbolSpacing: { type: Boolean, default: true, required: false } }, emits: ["change", "blur", "focus", "update:modelValue"], setup(__props, { emit }) { const props = __props; const { readOnly, separator, currency, precision } = toRefs(props); const amount = ref(""); const numeric = ref(null); const spanReadOnly = ref(null); const amountNumber = computed(() => unformat$1(amount.value)); const valueNumber = computed(() => unformat$1(props.modelValue)); const decimalSeparatorSymbol = computed(() => { if (typeof props.decimalSeparator !== "undefined") { return props.decimalSeparator; } if (separator.value === ",") { return "."; } return ","; }); const thousandSeparatorSymbol = computed(() => { if (typeof props.thousandSeparator !== "undefined") { return props.thousandSeparator; } if (separator.value === ".") { return "."; } if (separator.value === "space") { return " "; } return ","; }); const symbolPosition = computed(() => { let suffix = "%v %s"; let prefix = "%s %v"; if (!currency.value) { return "%v"; } if (props.currencySymbolSpacing === false) { suffix = "%v%s"; prefix = "%s%v"; } return props.currencySymbolPosition === "suffix" ? suffix : prefix; }); watch(valueNumber, (newValue, oldValue) => { if (numeric.value !== document.activeElement) { amount.value = format(newValue); } }); watch(readOnly, async (newValue, oldValue) => { if (oldValue === false && newValue === true) { await nextTick(); spanReadOnly.className = props.readOnlyClass; } }); watch(separator, (newValue, oldValue) => { process(valueNumber.value); amount.value = format(valueNumber.value); }); watch(currency, (newValue, oldValue) => { process(valueNumber.value); amount.value = format(valueNumber.value); }); watch(precision, (newValue, oldValue) => { process(valueNumber.value); amount.value = format(valueNumber.value); }); onMounted(() => { if (valueNumber.value || isDeliberatelyZero()) { process(valueNumber.value); amount.value = format(valueNumber.value); setTimeout(() => { process(valueNumber.value); amount.value = format(valueNumber.value); }, 500); } if (readOnly.value) spanReadOnly.className = props.readOnlyClass; }); function onChangeHandler(e) { emit("change", e); } function onBlurHandler(e) { emit("blur", e); amount.value = format(valueNumber.value); } function onFocusHandler(e) { emit("focus", e); if (valueNumber.value === 0) { amount.value = null; } else { amount.value = formatMoney(valueNumber.value, { symbol: "", format: "%v", thousand: "", decimal: decimalSeparatorSymbol.value, precision: Number(precision.value) }); } } function onInputHandler() { process(amountNumber.value); } function process(value) { if (value >= props.max) { update(props.max); } if (value <= props.min) { update(props.min); } if (value > props.min && value < props.max) { update(value); } if (!props.minus && value < 0) { props.min >= 0 ? update(props.min) : update(0); } } function update(value) { const fixedValue = toFixed(value, precision.value); const output = props.outputType.toLowerCase() === "string" ? fixedValue : Number(fixedValue); emit("update:modelValue", output); } function format(value) { return formatMoney(value, { symbol: currency.value, format: symbolPosition.value, precision: Number(precision.value), decimal: decimalSeparatorSymbol.value, thousand: thousandSeparatorSymbol.value }); } function unformat$1(value) { const toUnformat = typeof value === "string" && value === "" ? props.emptyValue : value; return unformat(toUnformat, decimalSeparatorSymbol.value); } function isDeliberatelyZero() { return valueNumber.value === 0 && props.modelValue !== ""; } return (_ctx, _cache) => { return !unref(readOnly) ? withDirectives((openBlock(), createElementBlock("input", { key: 0, ref: (_value, _refs) => { _refs["numeric"] = _value; numeric.value = _value; }, placeholder: __props.placeholder, disabled: __props.disabled, "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => amount.value = $event), type: "tel", onBlur: onBlurHandler, onInput: onInputHandler, onFocus: onFocusHandler, onChange: onChangeHandler }, null, 40, _hoisted_1)), [ [vModelText, amount.value] ]) : (openBlock(), createElementBlock("span", { key: 1, ref: (_value, _refs) => { _refs["spanReadOnly"] = _value; spanReadOnly.value = _value; } }, toDisplayString(amount.value), 513)); }; } }; export { _sfc_main as default };