@farris/ui-vue
Version:
Farris Vue, a Farris Design based Vue3 component library.
486 lines (485 loc) • 14.4 kB
JavaScript
import { isMobilePhone as W, withInstall as X } from "../common/index.esm.js";
import { computed as S, ref as O, createVNode as C, onMounted as U, nextTick as A, defineComponent as Y, watch as E } from "vue";
import N from "bignumber.js";
import { LocaleService as $ } from "../locale/index.esm.js";
import { useInputExpand as ee } from "../common/index.esm.js/text-box/use-input-expand";
const te = {
/**
* 组件标识
*/
id: String,
/**
* 是否禁用
* @default false
*/
disabled: { type: Boolean, default: !1 },
/**
* 是否只读
* @default false
*/
readonly: { type: Boolean, default: !1 },
/**
* 是否可编辑
* @default true
*/
editable: { type: Boolean, default: !0 },
/**
* 格式化 formatter 和 parser 必须同时存在 formatter: (val: number) => string; parser: (val: string | number) => number;
*/
formatter: { type: Function },
/**
* number) => number
*/
parser: { type: Function },
/**
* 空白提示文本
* @default 请输入数字
*/
placeholder: { type: String, default: "请输入数字" },
/**
* up or down 步长
*/
step: { type: Number, default: 1 },
/**
* 最大值
*/
max: { type: [Number, String] },
/**
* 最小值
*/
min: { type: [Number, String] },
/**
* 是否显示微调按钮
* @default true
*/
showButton: { type: Boolean, default: !0 },
/**
* 是否使用千分值
* @default true
*/
useThousands: { type: Boolean, default: !0 },
/**
* 文本对齐方式 : 左对齐left; 居中对齐center ;右对齐 right
* @default left
*/
textAlign: { type: String, default: "left" },
/**
* 自动补全小数---未实现
*/
autoDecimal: { type: Boolean, default: !0 },
/**
* 是否允许为空
* @default false
*/
nullable: { type: Boolean, default: !1 },
/**
* 精度
* @default 0
*/
precision: { type: Number, default: 0 },
/**
* 前缀
* @default ''
*/
prefix: { type: String, default: "" },
/**
* 后缀
* @default ''
*/
suffix: { type: String, default: "" },
/**
* 小数点符号
* @default .
*/
decimalSeparator: { type: String, default: "." },
/**
* 始终显示占位符文本
*/
forcePlaceholder: { Type: Boolean, default: !1 },
/**
* 千分位符号
* @default ,
*/
groupSeparator: { type: String, default: "," },
/**
* 使用千分位时,每组显示的字符数
* @default 3
*/
groupSize: { type: Number, default: 3 },
/**
* 值
*/
value: { type: [Number, String], default: "" },
/**
* 是否显示0值
* @default true
*/
showZero: { type: Boolean, default: !0 },
/**
* 组件值
*/
modelValue: { type: [Number, String], default: "" },
/**
* 作为内嵌编辑器被创建后默认获得焦点
*/
focusOnCreated: { type: Boolean, default: !1 },
/**
* 作为内嵌编辑器被创建后默认选中文本
*/
selectOnCreated: { type: Boolean, default: !1 },
/**
* 是否启用快捷键
*/
keyboard: { type: Boolean, default: !0 },
/**
* 是否启用大数
*/
bigNumber: { type: Boolean, default: !1 },
/**
* 是否需要验证
*/
needValid: { type: Boolean, default: !1 },
/**
* 更新方式 blur | change
*/
updateOn: { type: String, default: "change" },
/**
* 是否可扩展
*/
expandable: { type: Boolean, default: !1 },
/**
* 扩展模式 text | button
*/
expandMode: { type: String, default: "text" },
/**
* 扩展文本内容
*/
expandContent: { type: String, default: "" },
/**
* 扩展按钮是否禁用
*/
expandDisabled: { type: Boolean, default: !1 }
};
function ne(e, c, b, g) {
const { format: f } = b, { displayValue: m, getRealValue: y, modelValue: l, onNumberValueChanged: d } = g;
function n() {
const u = new N(l.value || 0);
return !((e.max || e.max === 0) && !new N(e.max).isNaN() && u.gte(new N(e.max)) && (l.value || l.value === 0));
}
function x() {
const u = new N(l.value || 0);
return !((e.min || e.min === 0) && !new N(e.min).isNaN() && u.lte(new N(e.min)) && (l.value || l.value === 0));
}
function t(u) {
if (e.readonly || e.disabled)
return;
const V = u === "up" ? n : x, j = u === "up" ? "plus" : "minus";
if (V()) {
const p = new N(l.value || 0)[j](Number(e.step)), D = p.toFixed();
m.value = f(D), d(y(p));
}
}
function o() {
t("up");
}
function i() {
t("down");
}
function v(u) {
o();
}
function h(u) {
i();
}
return { canDownward: x, canUpward: n, downward: i, onClickDownButton: h, onClickUpButton: v, upward: o };
}
function ae(e, c, b) {
const g = S(() => ({
prefix: e.prefix,
suffix: e.suffix,
decimalSeparator: e.decimalSeparator,
groupSeparator: e.useThousands ? e.groupSeparator : "",
groupSize: e.groupSize
})), { getValidNumberObject: f, precision: m } = b;
function y(n) {
return n = n == null || n === "" ? "" : String(n), n = n.replace(new RegExp(e.prefix, "g"), "").replace(new RegExp(e.suffix, "g"), "").replace(/,/g, ""), e.groupSeparator && e.groupSeparator !== "," && (n = n.replace(new RegExp(`\\${e.groupSeparator}`, "g"), "")), e.decimalSeparator && e.decimalSeparator !== "." && (n = n.replace(new RegExp(`\\${e.decimalSeparator}`, "g"), ".")), n;
}
function l(n, x) {
return e.precision !== null && e.precision !== void 0 ? n.toFormat(m.value, x) : n.toFormat(x);
}
function d(n, x = !0) {
const t = y(n), o = new N(t, 10);
let i = o;
return x && (i = f(o)), i.valueOf() === "0" && !e.showZero || i.isNaN() ? "" : e.formatter ? e.formatter(i.toNumber()) : l(i, g.value);
}
return { cleanFormat: y, format: d };
}
function ue(e, c) {
const b = O(""), g = O(e.modelValue), f = S(() => Number(e.precision) || 0), m = O(e.bigNumber);
function y(t) {
return t.toFixed(f.value);
}
function l(t) {
return isNaN(t) || t === null || t === void 0 || t === "";
}
function d(t) {
const o = l(e.max) ? null : new N(String(e.max), 10), i = l(e.min) ? null : new N(String(e.min), 10);
return o && t.gt(o) ? o : i && t.lt(i) ? i : t;
}
function n(t, o = !0) {
if (e.parser)
return isNaN(Number(t)) ? e.parser(t) : t;
let i = new N(t, 10);
if (o && (i = d(i)), i.isNaN()) {
if (e.nullable)
return null;
if (e.showZero)
return 0;
if (!o)
return null;
const h = new N("" + e.min, 10), u = new N("" + e.max, 10);
if (!h.isNaN())
i = h;
else if (!u.isNaN())
i = u;
else
return 0;
}
return y(i);
}
function x(t) {
let o = m.value ? t : Number(t);
e.nullable && t === null && (o = null), o !== e.modelValue && (c.emit("update:modelValue", o), c.emit("valueChange", o), c.emit("change", o));
}
return { displayValue: b, getRealValue: n, modelValue: g, isEmpty: l, onNumberValueChanged: x, precision: f, getValidNumberObject: d, toFixed: y };
}
function le(e, c, b, g, f) {
const { cleanFormat: m, format: y } = b, { displayValue: l, getRealValue: d, modelValue: n, isEmpty: x, onNumberValueChanged: t, getValidNumberObject: o, toFixed: i } = g, { downward: v, upward: h } = f, u = O(!1), V = S(() => l.value);
function j(a) {
var B;
if (a.stopPropagation(), u.value = !1, e.readonly || e.disabled)
return;
const r = (B = a.target) == null ? void 0 : B.value, s = m(r);
let w = d(s, e.needValid);
e.needValid && w != null && (w = i(o(new N(w, 10)))), l.value = y(w, e.needValid), e.updateOn === "blur" && t(w), c.emit("blur", { event: a, formatted: l.value, value: n.value });
}
function P() {
const a = n.value;
if (x(a) || !e.showZero && a === 0)
return "";
const r = d(a, e.needValid);
if (!r && r !== 0)
return "";
try {
const s = new N(r, 10);
return s.isNaN() || !s.isFinite() ? "" : s.toFixed();
} catch {
return "";
}
}
function p(a) {
if (a.stopPropagation(), u.value = !0, e.readonly || e.disabled)
return;
const r = d(n.value, e.needValid);
l.value = P(), c.emit("focus", { event: a, formatted: r, value: n.value });
}
function D(a) {
var B;
a.stopPropagation();
let r = (B = a.target) == null ? void 0 : B.value;
e.nullable || (r = r || 0);
const s = m(r);
let w = d(s, e.needValid);
e.updateOn === "change" && (e.needValid && (w = i(o(new N(w, 10)))), l.value = r, t(w)), c.emit("input", w);
}
function Z(a) {
const r = a;
return r.value.substring((r == null ? void 0 : r.selectionStart) || 0, (r == null ? void 0 : r.selectionEnd) || 0);
}
function L(a) {
const { key: r, keyCode: s, target: w, ctrlKey: B, metaKey: z, shiftKey: R } = a;
if (!w)
return;
const I = w, F = I.value, G = Number(e.precision), _ = /* @__PURE__ */ new Set([".", "-", "%"]), q = Z(w);
if (_.has(r) && F.includes(r) && !q.includes(r) || e.precision === 0 && [110, 190].includes(s)) {
a.preventDefault();
return;
}
const H = /* @__PURE__ */ new Set([46, 8, 9, 27, 13, 110, 190, 173]), J = /* @__PURE__ */ new Set([65, 67, 86, 88]), Q = /* @__PURE__ */ new Set([...Array.from({ length: 5 }, (k, T) => 35 + T), 189, 109]);
if (H.has(s) || J.has(s) && (B || z) || Q.has(s))
return;
if (!(!R && (s >= 48 && s <= 57 || s >= 96 && s <= 105))) {
a.preventDefault();
return;
}
if ((R || s < 48 || s > 57) && (s < 96 || s > 105) && a.preventDefault(), F.includes(".") && e.precision) {
const k = F.indexOf("."), T = F.length - k - 1;
if ((I.selectionStart || 0) > k && T >= G)
return a.preventDefault(), !1;
}
}
const K = (a) => {
var w;
let r = (w = a.target) == null ? void 0 : w.value;
e.nullable || (r = r || 0);
const s = m(r);
n.value = d(s);
};
function M(a) {
return e.keyboard && a.key === "ArrowDown" && (a.preventDefault(), K(a), v(), a.stopPropagation()), e.keyboard && a.key === "ArrowUp" && (a.preventDefault(), K(a), h(), a.stopPropagation()), L(a);
}
return { textBoxValue: V, onBlurTextBox: j, onFocusTextBox: p, onInput: D, onKeyDown: M, isFocus: u };
}
function re(e, c, b) {
const {
canDownward: g,
canUpward: f,
onClickDownButton: m,
onClickUpButton: y
} = b, l = S(() => ({
"f-cmp-inputgroup": !0,
"input-group-append": !0,
"btn-group": !0,
"btn-group-number": !0
})), d = S(() => ({
btn: !0,
"btn-secondary": !0,
"btn-number-flag": !0
})), n = S(() => ({
cursor: f() ? "pointer" : "not-allowed",
"margin-left": 0
})), x = S(() => ({
cursor: g() ? "pointer" : "not-allowed",
"margin-left": 0
}));
return () => C("div", {
class: l.value
}, [C("button", {
class: d.value,
style: n.value,
onClick: y,
disabled: !f()
}, [C("span", {
class: "f-icon f-icon-arrow-chevron-up number-arrow-chevron",
style: "cursor: inherit"
}, null)]), C("button", {
class: d.value,
style: x.value,
onClick: m,
disabled: !g()
}, [C("span", {
class: "f-icon f-icon-arrow-chevron-down number-arrow-chevron",
style: "cursor: inherit"
}, null)])]);
}
function ie(e) {
function c(f, m, y) {
return m === y ? $.getLocaleValue(f) : m || "";
}
const b = c("numberSpinner.placeholder", e.placeholder, "请输入数字"), g = {
begin: c("numberSpinner.range.begin", e.beginPlaceholder, "开始数字"),
end: c("numberSpinner.range.end", e.endPlaceholder, "结束数字")
};
return { placeholder: b, range: g };
}
function oe(e, c, b) {
const g = ie(e), f = O(), {
onBlurTextBox: m,
onFocusTextBox: y,
onInput: l,
onKeyDown: d,
textBoxValue: n
} = b, x = S(() => (e.disabled || e.readonly || !e.editable) && !e.forcePlaceholder ? "" : g.placeholder), t = S(() => ({
"form-control": !0,
"f-utils-fill": !0
})), o = S(() => ({
"text-align": e.textAlign
}));
function i(u) {
u.stopPropagation();
}
function v() {
var u, V;
e.selectOnCreated && ((u = f.value) == null || u.select()), e.focusOnCreated && ((V = f.value) == null || V.focus({
preventScroll: !0
}));
}
async function h(u) {
y(u), await A, v();
}
return U(async () => {
await A, v();
}), () => C("input", {
ref: f,
class: t.value,
style: o.value,
type: "text",
value: n.value,
disabled: e.disabled,
readonly: e.readonly || !e.editable,
placeholder: x.value,
onBlur: m,
onChange: i,
onFocus: h,
onInput: l,
onKeydown: d,
title: n.value
}, null);
}
const ce = /* @__PURE__ */ Y({
name: "FNumberSpinner",
props: te,
emits: ["update:modelValue", "valueChange", "change", "blur", "focus", "click", "input", "expandClick"],
setup(e, c) {
const b = ue(e, c), g = ae(e, c, b), f = ne(e, c, g, b), m = le(e, c, g, b, f), y = re(e, c, f), {
displayValue: l,
modelValue: d,
getRealValue: n
} = b, x = oe(e, c, m), {
format: t
} = g, {
isFocus: o
} = m, i = S(() => !e.disabled && !e.readonly && e.showButton && !W()), v = S(() => ({
"f-cmp-inputgroup": !0,
"input-group": !0,
"flex-row": !0,
"f-cmp-number-spinner": !0,
"f-state-disabled": e.disable,
"f-state-readonly": e.readonly && !e.disable,
"f-state-focus": o.value && !e.readonly && !e.disable,
"spinner-hidden": !i.value
}));
U(() => {
const u = n(e.modelValue, !1);
l.value = t(u, !1);
}), E(() => [e.value], ([u]) => {
const V = n(u, !1);
d.value = V, l.value = t(V, !1);
}), E(() => [e.modelValue], ([u]) => {
u !== d.value && (d.value = u, !o.value && (l.value = t(n(u, !1), !1)));
}), E(() => [e.precision, e.useThousands, e.prefix, e.suffix, e.showZero], () => {
l.value = t(d.value, !1);
});
const {
renderExpandContent: h
} = ee(e, c);
return () => C("div", {
class: v.value,
id: e.id
}, [x(), i.value && y(), h(e.expandMode === "button" ? {
"padding-left": "8px"
} : void 0)]);
}
}), we = X(ce);
export {
ce as FNumberSpinner,
we as default,
oe as getNumberTextBoxRender,
re as getSpinnerRender,
te as numberSpinnerProps,
ae as useFormat,
ue as useNumber,
ie as useNumberLocales,
ne as useSpinner,
le as useTextBox
};