@opentiny/vue-renderless
Version:
An enterprise-class UI component library, support both Vue.js 2 and Vue.js 3, as well as PC and mobile.
307 lines (306 loc) • 9.72 kB
JavaScript
import {
__spreadProps,
__spreadValues
} from "../chunk-G2ADBYYC.js";
import { on, off } from "@opentiny/utils";
import { formatNumber } from "@opentiny/utils";
import { getMiniDecimal, equalsDecimal } from "@opentiny/utils";
import { isNumber } from "@opentiny/utils";
const initService = (service) => {
const { utils = {} } = service || {};
const noopFn = () => null;
return {
getCurrencyPrecision: utils.getCurrencyPrecision || noopFn,
getNumberFormat: utils.getNumberFormat || noopFn
};
};
const getDecimal = (props) => (value) => getMiniDecimal(value, props.plugin);
const closePopper = (state) => () => {
state.visible = false;
state.editorPhase = "close";
};
const popInput = ({ editorState, props, state, api }) => (value) => {
value = api.onInputPreprocess(value);
const { fraction, groupSeparator } = state.format;
value = value.replace(/^-+/, "-");
const groups = value.split(groupSeparator).map((val) => val.trim());
value = groups.join("");
if (value !== "-" && api.getDecimal(value).isNaN()) {
value = editorState.lastInput;
} else {
value = value.split(".").map((a, i) => i && props.strictInput && typeof fraction === "number" ? a.substr(0, fraction) : a).join(".");
}
editorState.lastInput = value;
editorState.amount = value;
};
const toggleVisible = ({ api, props, state, editorState, uiMode, isMobileFirstMode: mf }) => () => {
if (state.disabled || !props.popUp) {
return;
}
state.lock = true;
state.visible = !state.visible;
if (state.visible) {
const { date, currency } = state;
if (!state.clearValues) {
Object.assign(editorState, {
amount: state.amount,
date,
currency
});
}
if (props.date || props.dateAllowEmpty) {
state.editorPhase = "selection";
} else {
state.editorPhase = "currency";
}
if (!mf || uiMode.value !== "default") {
api.addOutSideEvent(state.visible);
}
} else {
state.editorPhase = "close";
}
};
const openDetailEditor = ({ state }) => (option, index) => {
const optionPhase = ["currency", "date"];
state.editorPhase = optionPhase[index];
state.visible = true;
};
const closeDetailEidtor = ({ state, props, api }) => (triggerCondition) => {
if (!triggerCondition) {
return;
}
const inSelectionPhase = state.editorPhase === "selection";
const isMultipleStep = props.date || props.dateAllowEmpty;
if (!inSelectionPhase && isMultipleStep) {
state.editorPhase = "selection";
state.visible = true;
} else {
api.toggleVisible();
}
setTimeout(() => {
api.save(true);
}, 0);
};
const innerFormat = ({ state, props }) => (value) => {
const { fraction, zeroize, rounding } = state.format;
const { modelTruncation } = props;
const fractionLen = (value.split(".")[1] || "").length;
if (value === "-") {
return 0;
}
if (!modelTruncation && fractionLen > fraction) {
return value;
}
return formatNumber(value, {
fraction,
zeroize,
groupSeparator: "",
decimalSeparator: ".",
rounding
});
};
const save = ({ api, state, editorState }) => (keepOpen) => {
const { amount, date, currency } = editorState;
Object.assign(state, { amount, date, currency });
if (keepOpen !== true) {
api.closePopper();
}
let num = api.innerFormat(state.amount + "");
state.amount = isNaN(num) ? 0 : num;
if (!equalsDecimal(state.lastInput, state.amount) || state.lastCurrency !== currency || state.lastDate !== date) {
api.emitChange();
}
state.lastInput = state.amount;
state.lastCurrency = currency;
state.lastDate = date;
api.initText();
};
const reset = ({ state, editorState }) => () => {
const { amount, date, currency } = state;
Object.assign(editorState, { amount, date, currency });
};
const emitChange = ({ emit, state, props, api }) => () => {
const { date, currency } = state;
let emitAmount = props.stringMode ? api.getDecimal(state.amount).toString() : Number(state.amount);
if (props.numAllowEmpty && state.amount === "") {
emitAmount = state.amount;
}
state.amount && (state.clearValues = false);
!state.clearValues && emit("update:modelValue", emitAmount);
emit("update:currency", currency);
emit("update:date", date);
emit("change", { amount: emitAmount, date, currency });
};
const inputFocus = ({ state, props }) => () => {
let amount = state.amount + "";
state.isFocus = true;
state.lock = false;
const { fraction } = state.format;
const fractionLen = (amount.split(".")[1] || "").length;
if (fractionLen < fraction && props.holdZero) {
amount = formatNumber(amount, { fraction });
}
state.amountText = amount;
};
const inputBlur = ({ api, state, props }) => () => {
if (state.amountText !== "") {
let amount = api.innerFormat(state.amountText + "");
if (isNaN(amount)) {
state.amount = "";
}
state.amount = props.holdZero ? amount : api.getDecimal(amount).toString();
}
state.isFocus = false;
state.amountText = formatNumber(state.amount, state.format);
if (!equalsDecimal(state.lastInput, state.amount)) {
api.emitChange();
}
state.lastInput = state.amount;
};
const handelClick = ({ api, vm }) => (e) => {
const contains = vm.$refs.root.contains(e.target);
if (!contains) {
api.closePopper();
}
};
const addOutSideEvent = (api) => (visible) => {
if (visible) {
on(document, "click", api.handelClick);
} else {
off(document, "click", api.handelClick);
}
};
const initText = ({ state }) => () => {
let amount = state.amount + "";
state.amountText = amount ? state.isFocus ? amount : formatNumber(state.amount, state.format) : "";
};
const onInputPreprocess = (props) => (value) => {
const inputElem = event.target;
if (value) {
const i = value.lastIndexOf("-");
if (i === 0 && !props.negative || i > 0) {
const tmpArr = value.split("");
tmpArr.splice(i, 1);
inputElem.value = value = tmpArr.join("");
inputElem.selectionStart = inputElem.selectionEnd = i;
}
}
return value;
};
const onInput = ({ state, props, api }) => (value) => {
value = api.onInputPreprocess(value);
const { fraction, groupSeparator } = state.format;
value = event.target.value !== void 0 ? event.target.value.replace(/^-+/, "-") : value.replace(/^-+/, "-");
const groups = value.split(groupSeparator).map((val) => val.trim());
value = groups.join("");
if (value !== "-" && api.getDecimal(value).isNaN()) {
value = state.lastInput;
} else {
value = value.split(".").map((a, i) => i && props.strictInput && typeof fraction === "number" ? a.substr(0, fraction) : a).join(".");
}
event.target.value = value;
state.amount = value;
state.amountText = value;
};
const getPrecision = ({ service, props, currency }) => {
const { format = {}, rounding: r, digits, type } = props;
let fraction;
let rounding = format.rounding;
const { getCurrencyPrecision, getNumberFormat } = service;
const serFra = getCurrencyPrecision(type, currency) || {};
const serFmt = getNumberFormat() || {};
const defaultFmt = {
groupSeparator: ",",
groupSize: 3,
decimalSeparator: ".",
zeroize: props.holdZero
};
fraction = isNumber(format.fraction) ? format.fraction : isNumber(serFra.fraction) ? serFra.fraction : digits;
if (r === false) {
rounding = 0;
} else {
rounding = isNumber(rounding) ? rounding : isNumber(serFra.rounding) ? serFra.rounding : 5;
}
return __spreadValues(__spreadValues(__spreadProps(__spreadValues({}, defaultFmt), { fraction, rounding }), serFmt), format);
};
const getAmountText = ({ state, props }) => () => {
const isFilter = props.shape === "filter" && props.filter;
if (props.hideCurrency && typeof state.amountText === "string") {
return isFilter ? state.radioVal + state.amountText.replace(state.currency, "") : state.amountText.replace(state.currency, "");
} else {
return isFilter ? state.radioVal + state.amountText : state.amountText;
}
};
const getAmountTextWithoutCurrncy = ({ state }) => () => {
return state.amountText.replace(state.currency, "");
};
const watchModelValue = ({ api, state }) => () => {
let value = api.initAmount();
state.amount = value;
state.lastInput = value;
api.initText();
};
const watchCurrency = ({ api, state, editorState }) => (value) => {
state.currency = value;
editorState.currency = value;
state.lastCurrency = value;
api.initText();
};
const watchUiMode = ({ api, isMobileFirstMode: mf }) => (value) => {
if (mf && value === "default") {
api.addOutSideEvent(false);
}
};
const initAmount = ({ props, api }) => () => {
let value = props.modelValue;
value = value === null || isNaN(Number(value)) ? "" : value;
if (!props.negative && value && Number(value) < 0) {
if (props.stringMode) {
value = api.getDecimal(String(value).replace(/^-/, "")).toString();
} else {
value -= 0;
value = Math.abs(value);
}
}
return value;
};
const handleClearClick = ({ state, emit, editorState }) => (event2) => {
event2.stopPropagation();
state.amountText = "";
state.radioVal = "";
editorState.amount = "";
state.clearValues = true;
emit("clear");
};
const handleChange = ({ state, emit }) => () => {
emit("filter-change", state.radioVal);
};
export {
addOutSideEvent,
closeDetailEidtor,
closePopper,
emitChange,
getAmountText,
getAmountTextWithoutCurrncy,
getDecimal,
getPrecision,
handelClick,
handleChange,
handleClearClick,
initAmount,
initService,
initText,
innerFormat,
inputBlur,
inputFocus,
onInput,
onInputPreprocess,
openDetailEditor,
popInput,
reset,
save,
toggleVisible,
watchCurrency,
watchModelValue,
watchUiMode
};