@farris/ui-vue
Version:
Farris Vue, a Farris Design based Vue3 component library.
1,616 lines (1,615 loc) • 48.8 kB
JavaScript
import { defineComponent as E, ref as I, computed as H, watch as k, onMounted as _, createVNode as w, reactive as $, inject as G } from "vue";
import ae from "../button-edit/index.esm.js";
import { LocaleService as J } from "../locale/index.esm.js";
import { resolveAppearance as oe, createPropsResolver as de, getPropsResolverGenerator as ue } from "../dynamic-resolver/index.esm.js";
import ce from "../list-view/index.esm.js";
import { isUndefined as re } from "lodash-es";
import { useTouchMomentum as se, useTouch as me, useCommonUtils as q, useBem as K, useFarrisConfig as fe, FormSchemaEntityFieldType$Type as R, EVENT_PROPERTY_TAB_IDS as he, withInstall as ve } from "../common/index.esm.js";
import "bignumber.js";
import ge from "../../designer/button-edit/index.esm.js";
import { InputBaseProperty as ye } from "../property-panel/index.esm.js";
import { useDesignerComponent as be } from "../designer-canvas/index.esm.js";
const Q = /* @__PURE__ */ new Map([
["appearance", oe]
]), Se = "https://json-schema.org/draft/2020-12/schema", Ce = "https://farris-design.gitee.io/combo-list.schema.json", Fe = "combo-list", xe = "A Farris Input Component", Te = "object", Ve = {
id: {
description: "The unique identifier for a combo list",
type: "string"
},
type: {
description: "The type string of number combo list component",
type: "string",
default: "combo-list"
},
appearance: {
description: "",
type: "object",
properties: {
class: {
type: "string"
},
style: {
type: "string"
}
},
default: {}
},
binding: {
description: "",
type: "object",
default: {}
},
disabled: {
description: "",
type: "boolean",
default: !1
},
enableClear: {
description: "",
type: "boolean",
default: !1
},
editable: {
description: "",
type: "boolean",
default: !1
},
enableLinkLabel: {
description: "",
type: "boolean",
default: !1
},
label: {
description: "",
type: "string",
default: ""
},
lableWidth: {
description: "",
type: "number"
},
placeholder: {
description: "",
type: "string",
default: "请选择"
},
idField: {
description: "",
type: "string",
default: "id"
},
valueField: {
description: "",
type: "string",
default: "id"
},
titleField: {
description: "",
type: "string",
default: "name"
},
textField: {
description: "",
type: "string",
default: "name"
},
dataSourceType: {
description: "",
type: "string",
default: "static"
},
data: {
description: "",
type: "array"
},
dataSource: {
description: "",
type: "string"
},
remote: {
description: "",
type: "string"
},
readonly: {
description: "",
type: "boolean",
default: !1
},
required: {
description: "",
type: "boolean",
default: !1
},
tabindex: {
description: "",
type: "number",
default: -1
},
textAlign: {
description: "",
type: "string",
enum: [
"left",
"middle",
"right"
],
default: "left"
},
multiSelect: {
description: "",
type: "boolean",
default: !1
},
maxLength: {
description: "",
type: "number",
default: null
},
visible: {
description: "",
type: "boolean",
default: !0
},
onBlur: {
description: "",
type: "string",
default: ""
},
onClickLinkLabel: {
description: "",
type: "string",
default: ""
},
maxHeight: {
description: "",
type: "number",
default: 350
},
minPanelWidth: {
description: "",
type: "number",
default: 160
},
popupOnClick: {
description: "",
type: "boolean",
default: !0
},
separator: {
description: "",
type: "string",
default: ","
},
viewType: {
description: "",
type: "string",
default: "tag"
},
enableSearch: {
description: "启用搜索",
type: "boolean",
default: !0
},
enableHighlightSearch: {
description: "启用高亮搜索",
type: "boolean",
default: !1
},
beforeOpen: {
description: "打开下拉面板前回调",
type: "string"
},
beforeHide: {
description: "关闭下拉面板前回调",
type: "string"
},
onShown: {
description: "面板打开事件",
type: "string"
},
onHidden: {
description: "面板关闭事件",
type: "string"
},
onChange: {
description: "值变化事件",
type: "string",
default: ""
},
onInput: {
description: "输入事件",
type: "string",
default: ""
},
onClear: {
description: "清空事件",
type: "string",
default: ""
},
onDataChanged: {
description: "清空事件",
type: "string",
default: ""
},
hideDisabledItems: {
description: "隐藏禁用项",
type: "boolean",
default: !1
},
expandable: {
description: "",
type: "boolean",
default: !1
},
expandMode: {
description: "",
type: "string",
default: "text"
},
expandContent: {
description: "",
type: "string",
default: ""
},
expandDisabled: {
description: "",
type: "boolean",
default: !1
},
onExpandClick: {
description: "",
type: "string",
default: ""
}
}, we = [
"type"
], Ie = [
"id",
"appearance",
"binding",
"visible"
], Pe = {
onClear: "清空事件",
onShown: "面板打开事件",
onHidden: "面板关闭事件",
onChange: "值变化事件",
beforeOpen: "打开面板前事件",
beforeHide: "关闭面板前事件"
}, X = {
$schema: Se,
$id: Ce,
title: Fe,
description: xe,
type: Te,
properties: Ve,
required: we,
ignore: Ie,
events: Pe
};
function Z(e, t, a) {
return t;
}
function Be() {
function e(t, a, l) {
const r = {};
return r.beforeOpen = (m) => a.call("beforeOpen", t, [m, t], l), r;
}
return {
resolve: e
};
}
var pe = /* @__PURE__ */ ((e) => (e.top = "top", e.bottom = "bottom", e.auto = "auto", e))(pe || {});
const U = {
/**
* 组件标识
*/
id: { type: String },
/**
* 下拉数据源
*/
data: { type: Array, default: [] },
/**
* 可选,展示文本
* 默认为空字符串 -----内部需要根据value重新生成展示文本,此属性不生效
* displayText: { type: String, default: '' },
*/
/**
* 可选,是否禁用
* 默认为`false`
*/
disabled: { default: !1, type: Boolean },
/**
* 可选,下拉图标
* 默认为'<span class="f-icon f-icon-arrow-60-down"></span>'
*/
dropDownIcon: { type: String, default: '<span class="f-icon f-icon-arrow-chevron-down"></span>' },
/**
* 可选,是否可编辑
* 默认`false`
*/
editable: { default: !1, type: Boolean },
/**
* 可选,是否启用清空
* 默认启用
*/
enableClear: { default: !0, type: Boolean },
/**
* 可选,启用搜索
* 默认为`false`
*/
enableSearch: { type: Boolean, default: !1 },
/**
* 可选,鼠标悬停时是否显示控件值
* 默认显示
*/
enableTitle: { default: !0, type: Boolean },
fitEditor: { default: !1, type: Boolean },
/**
* 可选,强制显示占位符
* 默认`false`
*/
forcePlaceholder: { default: !1, type: Boolean },
/**
* 可选,清空值时隐藏面板
* 默认`true`
*/
hidePanelOnClear: { default: !0, type: Boolean },
/**
* 可选,数据源id字段
* 默认为`id`
*/
idField: { default: "id", type: String },
/**
* 可选,字段映射
*/
mapFields: { type: Object },
/**
* 可选,最大高度
* 默认`350`
*/
maxHeight: { default: 350, type: Number },
/**
* 最大输入长度
*/
maxLength: { type: Number },
/**
* 可选,是否支持多选
* 默认`false`
*/
multiSelect: { type: Boolean, default: !1 },
/**
* 绑定值
*/
modelValue: { type: String, default: "" },
/**
* 占位符
*/
placeholder: { type: String, default: "请选择" },
/**
* 可选,下拉面板展示位置
* 默认为`auto`
*/
placement: {
type: String,
default: "auto"
/* auto */
},
/**
* 可选,是否只读
* 默认为`false`
*/
readonly: { default: !1, type: Boolean },
/**
* 远端数据源信息
*/
remote: { default: null, type: Object },
/**
* 可选,是否支持远端过滤
* 默认`false`
*/
remoteSearch: { default: !1, type: Boolean },
/**
* 可选,分隔符
* 默认`,`
*/
separator: { default: ",", type: String },
/**
* tabIndex
*/
tabIndex: { type: Number, default: -1 },
/**
* 可选,数据源显示字段
* 默认为`name`
*/
textField: { default: "name", type: String },
/**
* 可选,数据源的title
* 默认为`name`
*/
titleField: { default: "name", type: String },
/**
* 可选,数据源值字段
* 默认为`id`
*/
valueField: { default: "id", type: String },
/**
* 可选,启用多选下,下拉列表值在输入框中的展示方式
* 支持text | tag
* 因为ButtonEdit内部处理类型只有在批量的情况下才会有展示类型区分
*/
viewType: { default: "tag", type: String },
/**
* 值变化事件
*/
change: { type: Function, default: () => {
} },
/**
* 作为内嵌编辑器被创建后默认获得焦点
*/
focusOnCreated: { type: Boolean, default: !1 },
/**
* 作为内嵌编辑器被创建后默认选中文本
*/
selectOnCreated: { type: Boolean, default: !1 },
/**
* 此属性废弃
*/
autoHeight: { type: Boolean, default: !0 },
/**
* 打开前
*/
beforeOpen: { type: Function, default: null },
load: { type: Function },
searchOption: {
type: [Boolean, Function],
default: !1
},
// 搜索启用高亮
enableHighlightSearch: { type: Boolean, default: !0 },
minPanelWidth: { type: Number, default: 160 },
popupOnClick: { type: Boolean, default: !0 },
/** 是否可扩展 */
expandable: { type: Boolean, default: !1 },
/** 扩展模式 text | button */
expandMode: { type: String, default: "text" },
/** 扩展文本内容 */
expandContent: { type: String, default: "" },
/** 扩展按钮是否禁用 */
expandDisabled: { type: Boolean, default: !1 },
popupClass: { type: String, default: "" },
/**
* 可选,是否隐藏禁用的数据项
* 默认`false`(禁用项显示为置灰状态)
* 设置为`true`时,禁用的数据项将不会在下拉列表中显示
*/
hideDisabledItems: { type: Boolean, default: !1 }
}, He = Object.assign({}, U, {
readonly: {}
}), at = de(U, X, Q, Z), D = ue(
U,
X,
Q,
Z
), Me = Be(), Ae = {
dataSource: { type: Array, default: [] },
enableSearch: { type: Boolean, default: !1 },
idField: { type: String, default: "id" },
multiSelect: { type: Boolean, default: !1 },
selectedValues: { type: String, default: "" },
separator: { type: String, default: "," },
textField: { type: String, default: "name" },
titleField: { type: String, default: "name" },
width: { type: Number },
maxHeight: { type: Number },
valueField: { type: String, default: "id" },
/** 值变化事件 */
onSelectionChange: { type: Function, default: () => {
} },
searchOption: {
type: [Boolean, Function],
default: !1
},
// 搜索启用高亮
enableHighlightSearch: { type: Boolean, default: !0 }
}, ke = /* @__PURE__ */ E({
name: "FComboListContainer",
props: Ae,
emits: ["selectionChange"],
setup(e, t) {
const a = I(), l = I(e.dataSource), r = I(e.dataSource), m = I([]), o = I(e.separator), T = I(e.width), g = I(e.maxHeight), y = H(() => e.multiSelect), v = I(e.multiSelect ? String(e.selectedValues).split(o.value) : [e.selectedValues]), h = H(() => ({
enableSelectRow: !0,
multiSelect: e.multiSelect,
multiSelectMode: "OnCheckAndClick",
showCheckbox: y.value,
showSelectAll: !1,
showSelection: !0
}));
k(e.dataSource, () => {
l.value = e.dataSource, r.value = e.dataSource;
}), H(() => e.enableSearch ? "SearchBar" : "ContentHeader");
const F = H(() => {
const n = {};
return T.value !== void 0 && (n.width = `${T.value}px`), g.value !== void 0 && g.value > 0 && (n.maxHeight = `${g.value}px`), n;
});
function b(n) {
a.value.search(n);
}
function x(n) {
m.value = n.map((u) => Object.assign({}, u)), v.value = n.map((u) => u[e.idField]), t.emit("selectionChange", m.value);
}
function B(n) {
if (e.enableHighlightSearch)
return;
let u = [];
const {
searchOption: s
} = e;
typeof s == "function" ? u = l.value.filter((c) => s(n, c)) : u = l.value.filter((c) => c[e.valueField].indexOf(n) > -1 || c[e.textField].indexOf(n) > -1), a.value.updateDataSource(u);
}
k([() => e.selectedValues], ([n]) => {
e.multiSelect ? v.value = n.split(o.value) : v.value = [n];
});
function V(n) {
a.value.activeRowById(n);
}
return _(() => {
var n, u;
if (!e.multiSelect) {
const s = (n = v.value) == null ? void 0 : n[0];
let c = s;
const i = l.value.map((d) => d[e.valueField || e.idField]);
if (!re(s) && i.includes(s)) {
const d = typeof s, f = typeof ((u = l.value[0]) == null ? void 0 : u[e.valueField || e.idField]);
f === "number" && d !== f && (c = Number(s)), f === "boolean" && d !== f && (c = s === "true" ? !0 : s === "false" ? !1 : s), V(c);
}
}
}), t.expose({
search: b,
activeRowById: V
}), () => w("div", {
class: "f-combo-list-container",
style: F.value
}, [w(ce, {
ref: a,
size: "small",
itemClass: "f-combo-list-item",
itemContentClass: "text-truncate",
header: "ContentHeader",
headerClass: "f-combo-list-search-box",
data: l.value,
idField: e.idField,
textField: e.textField,
titleField: e.titleField,
multiSelect: e.multiSelect,
selection: h.value,
enableHighlightSearch: e.enableHighlightSearch,
selectionValues: v.value,
onSelectionUpdate: x,
onAfterSearch: B
}, null)]);
}
}), W = {
property: "all",
duration: 0.3,
timingFunction: "cubic-bezier(0.17, 0.89, 0.45, 1)",
delay: 0
}, Le = (e, t) => {
const a = e.lineHeight / 2, l = se({ maxOverflowY: 44 }), r = $({ ...W }), m = (c) => {
t.emit("change", c);
}, o = $({
value: 0,
max: 0,
min: 0,
start: 0,
index: 0,
currentItem: void 0,
active: !1
}), T = () => {
o.max = e.visiableOptionCount / 2 * e.lineHeight;
const c = e.column.length * e.lineHeight;
o.min = o.max - c + e.lineHeight;
}, g = (c = 0) => {
T(), o.index = c, o.value = o.max - c * e.lineHeight, o.currentItem = e.column[c];
}, y = (c) => {
const i = e.column.length - 1, d = Math.min(o.index, i), f = e.column.findIndex((S) => S[e.valueField] === c);
return f >= 0 ? f : d;
}, v = (c) => {
const i = e.column.length - 1;
return o.index > i ? e.column[i] : e.column[c];
}, h = (c) => {
c && (o.currentItem = c, r.duration = 0);
const i = o.currentItem[e.valueField], d = y(i), f = v(o.index)[e.valueField];
g(d), i !== f && setTimeout(() => {
m(o.currentItem);
}, r.duration * 1e3);
}, F = () => {
const c = Array.isArray(e.value) ? e.value[0] : e.value;
g(y(c));
};
F(), k(() => e.value, () => {
e.multiSelect || F();
}), k(() => e.column, () => h());
const b = (c, i = o.max, d = o.min) => {
const f = o.start + c;
o.value = f > a ? Math.min(f, i) : Math.max(f, d), o.index = Math.round((o.max - o.value) / e.lineHeight), o.currentItem = v(o.index);
}, x = me(), B = (c) => {
x.start(c), o.active = !0, o.start = o.value, l.start(o.start), r.duration = 0;
}, V = (c) => {
c.preventDefault(), x.move(c), b(
x.deltaY.value,
o.max + e.lineHeight,
o.min - e.lineHeight
), l.move(x.deltaY.value), r.duration = W.duration;
}, n = (c) => {
const i = c < 0, d = c % e.lineHeight > a ? 1 : 0, f = Math.floor(c / e.lineHeight);
return (i ? f - d : f + d) * e.lineHeight + a;
};
return {
translateY: o,
transition: r,
onTouchStart: B,
onTouchMove: V,
onTouchEnd: () => {
o.start = 0;
const c = l.end();
let i = 0;
if (c) {
const { destination: d, duration: f } = l.get(o.value, o.min, o.max);
i = d, r.duration = f / 1e3;
} else
i = o.value;
b(n(i)), m(o.currentItem);
},
onTransitionend: () => {
o.active = !1;
},
updateTranslate: h
};
}, Ee = {
column: { type: Array, default: () => [] },
valueField: { type: String, default: "value" },
textField: { type: String, default: "text" },
value: { type: [Array, String, Number], default: () => [] },
multiSelect: { type: Boolean, default: !1 },
showIcon: { type: Boolean, default: !1 },
lineHeight: { type: Number, default: 0 },
visiableOptionCount: { type: Number, default: 5 }
}, Oe = /* @__PURE__ */ E({
props: Ee,
emits: ["change", "click"],
setup(e, t) {
const {
addUnit: a
} = q(), {
bem: l
} = K("FComboTouchList"), {
translateY: r,
transition: m,
onTouchStart: o,
onTouchMove: T,
onTouchEnd: g,
onTransitionend: y
} = Le(e, t), v = (b) => {
t.emit("click", b);
}, h = H(() => ({
transform: `translateY(${a(r.value)})`,
transition: `all ${r.active ? m.duration : 0}s ${m.timingFunction} 0s`
})), F = (b) => e.showIcon ? Array.isArray(e.value) && e.value.includes(b[e.valueField]) : !1;
return () => w("div", {
class: l("column"),
style: h.value,
onTouchstart: o,
onTouchmove: T,
onTouchend: g,
onTransitionend: y
}, [e.column.map((b) => w("div", {
class: l("column-item"),
onClick: () => v(b)
}, [w("span", null, [b[e.textField]]), F(b) && w("span", {
class: `f-icon f-icon-check ${l("column-item-icon")}`
}, null)]))]);
}
}), Re = {
modelValue: { type: [String, Array], default: "" },
columns: { type: Array, default: () => [] },
title: { type: String, default: "" },
valueField: { type: String, default: "value" },
textField: { type: String, default: "text" },
childrenField: { type: String, default: "children" },
multiSelect: { type: Boolean, default: !1 },
lineHeight: { type: Number, default: 44 },
cancelText: { type: String, default: "取消" },
confirmText: { type: String, default: "确定" },
optionFormatter: { type: Function, default: void 0 },
visiableOptionCount: { type: Number, default: 5 },
showToolbar: { type: Boolean, default: !0 },
separator: { type: String, default: "," }
}, $e = (e, t) => {
const { finalValue: a, initValue: l, setSelectedByIndex: r, getSelectedValueByIndex: m } = t, { isArray: o, isFunction: T, isObject: g } = q(), y = (i) => i && i[0], v = H(() => {
var i;
return ((i = e.columns) == null ? void 0 : i.length) > 0 && o(e.columns[0]);
}), h = (i) => {
if ((i == null ? void 0 : i.length) === 0)
return !1;
const d = y(i);
return d && o(d[e.childrenField]);
}, F = (i, d) => {
const f = y(i), S = m(d);
let p = i.find((L) => L[e.valueField] === S);
p = p || f;
const M = p[e.childrenField] || [];
if (h(M)) {
const L = F(M, d + 1);
return [M, ...L];
}
return [M];
}, b = () => {
const i = e.columns, d = F(i, 0);
return [i, ...d];
}, x = (i, d) => {
const f = i[e.textField];
return T(e.optionFormatter) ? e.optionFormatter(d, i) : f;
}, B = (i, d) => i.map((f) => {
const S = g(f) ? f : { [e.valueField]: f, [e.textField]: f };
return S[e.textField] = x(S, d), S;
}), V = H(() => {
let i = [];
return v.value ? i = e.columns : h(e.columns) ? i = b() : i = [e.columns], i.map(B);
}), n = () => V.value.map((i, d) => {
const f = a.value[d];
return i.find((p) => p[e.valueField] === f);
}).filter((i) => i), u = () => n().map((i) => i[e.valueField]), s = () => n().map((i) => i[e.textField]).join("-"), c = () => {
V.value.forEach((i, d) => {
if (e.multiSelect)
a.value[d].forEach((S) => {
const p = i.find((M) => M[e.valueField] === S);
p && r(d, p);
});
else {
const f = a.value[d], S = i.find((p) => p[e.valueField] === f);
S ? r(d, S) : r(d, y(i));
}
});
};
return k(
() => e.modelValue,
() => {
l(e.modelValue), c();
},
{ immediate: !0 }
), {
columns: V,
getPickeds: n,
getValue: u,
getTextValue: s
};
}, Ne = (e) => {
const { isArray: t, isMultiArray: a, isString: l, isDef: r } = q(), m = (n) => {
let u = [];
return t(n) ? u = n : l(n) ? u = n.split(e.separator) : r(n) && (u = [n]), e.multiSelect ? a(u) ? u : [u] : u;
}, o = I([]), T = (n) => {
o.value = m(n);
}, g = $([]), y = H(() => g.map((n) => n[e.valueField])), v = $([]), h = H(() => v.map((n) => n.map((u) => u[e.valueField])));
return {
finalValue: o,
initValue: T,
getSelected: () => e.multiSelect ? v : g,
getSelectedValue: () => e.multiSelect ? h.value : y.value,
setSelectedByIndex: (n, u) => {
if (e.multiSelect) {
const s = v[n] || [];
s.includes(u) ? v[n] = s.filter((c) => c !== u) : v[n] = [...s, u];
} else
g[n] = u;
},
getSelectedByIndex: (n) => e.multiSelect ? v[n] : g[n],
getSelectedValueByIndex: (n) => e.multiSelect ? h.value[n] : y.value[n]
};
}, qe = /* @__PURE__ */ E({
props: Re,
emits: ["change", "confirm", "cancel", "update:modelValue"],
setup(e, t) {
const {
emit: a
} = t, {
addUnit: l
} = q(), r = Ne(e), {
finalValue: m,
getSelectedValue: o,
getSelectedValueByIndex: T,
getSelected: g,
setSelectedByIndex: y
} = r, {
columns: v
} = $e(e, r), h = (s, c = !0) => {
const {
value: i,
index: d
} = s;
(c && !e.multiSelect || !c && e.multiSelect) && (a("change", s), y(d, i));
}, F = () => {
m.value = o(), a("confirm", g()), a("update:modelValue", m.value);
}, b = () => {
a("cancel");
}, {
bem: x
} = K("FComboTouchList"), B = () => w("div", {
class: x("toolbar")
}, [w("div", {
class: x("toolbar-left"),
onClick: b
}, [w("span", null, [e.cancelText])]), w("div", {
class: x("toolbar-title")
}, [w("span", null, [e.title])]), w("div", {
class: x("toolbar-right"),
onClick: F
}, [w("span", null, [e.confirmText])])]), V = H(() => {
const s = (e.visiableOptionCount + 1) * e.lineHeight;
return {
height: l(s)
};
}), n = H(() => {
const s = e.visiableOptionCount * e.lineHeight / 2;
return {
backgroundSize: `100% ${l(s)}`
};
}), u = () => w("div", {
class: x("content")
}, [w("div", {
class: x("columns"),
style: V.value
}, [v.value.map((s, c) => w(Oe, {
column: s,
value: T(c),
showIcon: e.multiSelect,
textField: e.textField,
multiSelect: e.multiSelect,
valueField: e.valueField,
lineHeight: e.lineHeight,
visiableOptionCount: e.visiableOptionCount,
onChange: (i) => h({
value: i,
index: c
}),
onClick: (i) => h({
value: i,
index: c
}, !1)
}, null)), !e.multiSelect && w("div", {
class: x("mask"),
style: n.value
}, null), w("div", {
class: x("frame")
}, null)])]);
return () => w("div", {
class: x("")
}, [e.showToolbar && B(), u()]);
}
});
function Ue(e, t) {
const a = I(""), l = I(e.modelValue), r = I(e.data || []), m = I(e.editable), o = H(() => e.hideDisabledItems ? r.value.filter((n) => !n.disabled) : r.value);
function T(n) {
const u = e.multiSelect ? String(n).split(e.separator) : [String(n)], s = u.map((d) => [d, !0]), c = new Map(s);
return r.value.filter((d) => c.has(String(d[e.valueField]))).sort((d, f) => {
const S = u.indexOf(d[e.valueField]), p = u.indexOf(f[e.valueField]);
return S - p;
});
}
function g(n) {
const u = T(n).map((s) => s[e.textField]).join(e.separator);
a.value = m.value ? u || n : u;
}
function y(n) {
if (e.multiSelect) {
const u = n.split(e.separator).map((c) => [c, !0]), s = new Map(u);
return r.value.filter((c) => s.has(c[e.textField]));
}
return r.value.filter((u) => "" + u[e.textField] === n);
}
function v(n) {
const u = {};
return u[e.idField] = n, u[e.textField] = n, [u];
}
function h(n) {
let u = y(n);
const s = u && u.length > 0;
return m.value && !s && (u = v(n)), u;
}
function F() {
const { url: n, method: u = "GET", headers: s = { "Content-Type": "application/json;charset=utf-8;" }, body: c = null } = e.remote;
if (!n)
return;
const { basePath: i } = fe().value, d = u.toLowerCase() === "get" ? { method: u, headers: s } : { method: u, headers: s, body: c };
let f = !1;
fetch(new Request(i + n, d)).then((S) => {
var M, L;
if (S.status === 200)
return f = !!((L = (M = S.headers) == null ? void 0 : M.get("content-type")) != null && L.includes("application/json")), f ? S.text() : S.json();
throw S.status === 405 ? new Error(J.getLocaleValue("comboList.remoteError")) : new Error(S.statusText);
}).then((S) => {
S.length && (r.value = f ? JSON.parse(S) : S, l.value && g(l.value));
}).catch((S) => {
console.warn(S);
});
}
e.remote && (e.load ? e.load().then((n) => {
r.value = n;
}).catch((n) => {
console.log(n);
}) : F()), k(() => e.data, () => {
r.value = e.data;
}), k([r], ([n], [u]) => {
if (e.modelValue != null && !e.multiSelect) {
const s = n.find((c) => c[e.valueField] === l.value);
s ? s[e.valueField] !== l.value ? (l.value = s[e.valueField], a.value = s[e.textField], t.emit("update:modelValue", s[e.valueField]), t.emit("change", [s], s[e.valueField])) : a.value !== s[e.textField] && (a.value = s[e.textField]) : l.value !== "" && (l.value = "", a.value = "", t.emit("update:modelValue", ""), t.emit("change", [], ""));
}
}), k(() => e.modelValue, (n, u) => {
u !== n && (l.value = n, g(n));
});
function b(n) {
r.value = n, t.emit("dataChanged", n);
}
function x() {
return r.value;
}
function B() {
return a.value;
}
async function V() {
const n = typeof e.beforeOpen == "function";
return !e.beforeOpen || !n ? Promise.resolve(!0) : Promise.resolve().then(() => e.beforeOpen({ instance: { updateDataSource: b, getData: x, getDisplayText: B } })).then((u) => typeof (u == null ? void 0 : u.canOpen) == "boolean" ? u == null ? void 0 : u.canOpen : !0);
}
return g(e.modelValue), {
dataSource: r,
filteredDataSource: o,
displayText: a,
editable: m,
modelValue: l,
beforeOpenList: V,
getItemsByDisplayText: y,
getItemsByValue: T,
getSelectedItemsByDisplayText: h
};
}
const Ye = ["moz", "ms", "webkit"];
function Ge() {
let e = 0;
return (t) => {
const a = (/* @__PURE__ */ new Date()).getTime(), l = Math.max(0, 16 - (a - e)), r = setTimeout(() => {
t(a + l);
}, l);
return e = a + l, r;
};
}
function We() {
if (typeof window > "u")
return () => 0;
if (window.requestAnimationFrame)
return window.requestAnimationFrame.bind(window);
const e = Ye.filter((t) => `${t}RequestAnimationFrame` in window)[0];
return e ? window[`${e}RequestAnimationFrame`] : Ge();
}
We();
I("");
function j() {
const e = navigator.userAgent || navigator.vendor || window.opera, t = [
/iPhone/i,
/iPod/i,
/Android.*Mobile/i,
// Android 手机通常包含 "Mobile" 字样,而平板不包含
/webOS/i,
/BlackBerry/i,
/IEMobile/i,
/Opera Mini/i,
/Harmony/i
], a = [
/iPad/i,
/Android(?!.*Mobile)/i,
// Android 平板通常不含 "Mobile"
/Tablet/i,
/PlayBook/i,
/Kindle/i,
/Silk/i
];
for (const T of a)
if (T.test(e))
return !1;
for (const T of t)
if (T.test(e))
return !0;
const l = "ontouchstart" in window || navigator.maxTouchPoints > 0, r = screen.width, m = screen.height, o = Math.min(r, m);
return !!(l && o <= 768);
}
const N = /* @__PURE__ */ E({
name: "FComboList",
props: U,
emits: ["clear", "update:modelValue", "change", "input", "dataChanged", "expandClick"],
setup(e, t) {
const a = I(), l = I(), r = I(e.disabled || e.readonly), m = I(e.enableClear), o = I(e.enableSearch), T = I(e.readonly), {
dataSource: g,
displayText: y,
editable: v,
modelValue: h,
filteredDataSource: F,
getItemsByDisplayText: b,
getItemsByValue: x,
beforeOpenList: B
} = Ue(e, t), V = I(e.dropDownIcon);
V.value === '<span class="f-icon f-icon-arrow-chevron-down"></span>' && (V.value = '<span id="' + e.id + '-icon-dropdown" class="f-icon f-icon-arrow-chevron-down"></span>');
const n = H(() => e.multiSelect), u = H(() => l.value ? l.value.elementRef.getBoundingClientRect().width : 0);
function s() {
!n.value && l.value && l.value.hidePopup();
}
function c(C) {
y.value = C.map((A) => A[e.textField]).join(e.separator) || h.value;
let P = "";
C.length === 1 ? P = C[0][e.valueField] : P = C.map((A) => A[e.valueField]).join(e.separator), h.value !== P && (h.value = P, t.emit("update:modelValue", h.value), t.emit("change", C, h.value));
}
function i() {
const C = x(h.value);
c(C);
}
function d() {
T.value || y.value;
}
function f(C) {
var P;
h.value = "", (P = a.value) == null || P.activeRowById(""), t.emit("clear");
}
function S(C) {
var P, A;
e.enableSearch && e.enableHighlightSearch && ((P = a.value) == null || P.search(C)), (A = a.value) == null || A.activeRowById(C), t.emit("change", [h.value], h.value);
}
function p(C) {
if (e.multiSelect) {
const P = b(C);
e.viewType;
const O = P.map((Y) => Y[e.idField || e.valueField]).join(e.separator);
h.value !== O && (h.value = O, t.emit("update:modelValue", h.value), t.emit("change", P, h.value));
} else C !== h.value && (h.value = C, t.emit("update:modelValue", h.value), t.emit("change", [], C));
}
function M() {
return y.value;
}
function L(C) {
const {
value: P
} = C.target;
S(P), t.emit("input", P);
}
function ee() {
l.value.hidePopup();
}
function te(C) {
g.value = C;
}
function ne() {
return g.value;
}
const ie = {
getDisplayText: M,
hidePopup: ee,
updateDataSource: te,
getData: ne
};
t.expose(ie), k([() => e.disabled, () => e.editable, () => e.enableClear, () => e.enableSearch, () => e.readonly], ([C, P, A, O, Y]) => {
r.value = C, v.value = P, m.value = A, o.value = O, T.value = Y;
});
const le = () => {
t.emit("expandClick");
};
return () => w(ae, {
ref: l,
id: e.id,
disable: r.value,
readonly: T.value,
forcePlaceholder: e.forcePlaceholder,
editable: v.value,
buttonContent: V.value,
placeholder: e.placeholder === "请选择" ? J.getLocaleValue("comboList.placeholder") : e.placeholder,
enableClear: m.value,
maxLength: e.maxLength,
tabIndex: e.tabIndex,
enableTitle: e.enableTitle,
multiSelect: e.multiSelect,
inputType: e.multiSelect ? e.viewType : "text",
modelValue: y.value,
"onUpdate:modelValue": (C) => y.value = C,
focusOnCreated: e.focusOnCreated,
selectOnCreated: e.selectOnCreated,
onClear: f,
onClick: d,
onChange: p,
onBlur: i,
onInput: L,
beforeOpen: B,
placement: j() ? "bottom" : e.placement,
popupMinWidth: e.minPanelWidth,
popupClass: "f-combo-list-wrapper",
popupOnClick: e.popupOnClick,
limitContentBySpace: !0,
expandable: e.expandable,
expandMode: e.expandMode,
expandContent: e.expandContent,
expandDisabled: e.expandDisabled,
onExpandClick: le
}, {
default: () => [j() ? w(qe, {
modelValue: h.value,
valueField: e.valueField,
textField: e.textField,
columns: g.value,
multiSelect: e.multiSelect,
separator: e.separator,
onConfirm: (C) => {
const P = e.multiSelect ? C[0] || [] : C;
c(P), l == null || l.value.hidePopup();
},
onCancel: () => {
l == null || l.value.hidePopup();
}
}, null) : w(ke, {
class: e.popupClass,
ref: a,
idField: e.idField,
valueField: e.valueField,
textField: e.textField,
titleField: e.titleField,
dataSource: F.value,
selectedValues: h.value,
separator: e.separator,
multiSelect: e.multiSelect,
enableSearch: o.value,
maxHeight: e.maxHeight,
enableHighlightSearch: e.enableHighlightSearch,
width: e.fitEditor ? u.value : void 0,
onSelectionChange: (C) => {
c(C), s();
}
}, null)]
});
}
}), z = {
convertFrom: (e, t) => (e.editor.remote || {})[t],
convertTo: (e, t, a) => {
e.editor.remote = e.editor.remote || {}, e.editor.remote[t] = a;
}
};
class je extends ye {
constructor(t, a) {
super(t, a);
}
getCommonEditorProperties(t) {
var a, l, r;
return {
viewType: {
visible: !!((a = t.editor) != null && a.multiSelect),
description: "数据展示类型,有标签和文本两种方式",
title: "数据展示类型",
type: "enum",
editor: {
data: [
{ id: "tag", name: "标签" },
{ id: "text", name: "文本" }
]
},
refreshPanelAfterChanged: !0
},
separator: {
visible: !!((l = t.editor) != null && l.multiSelect) && ((r = t.editor) == null ? void 0 : r.viewType) === "text",
description: "下拉列表启用多选且数据展示类型为文本时的分隔符",
title: "分隔符",
type: "enum",
editor: {
data: [
{ id: ",", name: "逗号(,)" },
{ id: "#", name: "井号(#)" },
{ id: ".", name: "句号(.)" },
{ id: "|", name: "竖线(|)" }
]
}
},
editable: {
description: "",
title: "允许编辑",
type: "boolean",
refreshPanelAfterChanged: !0,
readonly: !0
// readonly: !!propertyData.editor?.multiSelect && (propertyData.editor?.viewType === 'tag' || !propertyData.editor!.viewType)
},
hideDisabledItems: {
description: "当数据项禁用时,隐藏数据项",
title: "隐藏禁用项",
type: "boolean",
refreshPanelAfterChanged: !0
}
// enableHighlightSearch: {
// visible: !!propertyData.editor?.editable,
// description: "编辑状态下启用高亮搜索",
// title: "启用高亮搜索",
// type: "boolean"
// },
};
}
getEditorProperties(t) {
var g, y, v, h, F, b, x, B, V, n, u, s, c;
const a = this;
let l = "";
if (((g = t == null ? void 0 : t.binding) == null ? void 0 : g.type) === "Form") {
const i = this.schemaService.getFieldByIDAndVMID(t.binding.field, this.viewModelId);
(y = i == null ? void 0 : i.schemaField) != null && y.type && (l = i.schemaField.type.$type);
}
const r = this.getPropertyEditorParams(t, ["Variable"]), m = !t.editor.dataSourceType || t.editor.dataSourceType === "static", o = (((h = (v = this.designViewModelField) == null ? void 0 : v.type) == null ? void 0 : h.$type) === R.StringType || !!this.formRule && ((F = this.designerHostService.schemaService.getFieldByID(t.binding.field)) == null ? void 0 : F.type.$type) === R.StringType) && ((b = t.editor) == null ? void 0 : b.type) === "combo-list" && ((x = t.editor) == null ? void 0 : x.dataSourceType) === "dynamic" && !((V = (B = t.editor) == null ? void 0 : B.remote) != null && V.url) && !((n = t.editor) != null && n.multiSelect);
return a.getComponentConfig(
t,
{ type: "combo-list" },
{
// enableSearch: {
// description: "编辑状态下启用搜索",
// title: "允许编辑",
// type: "boolean",
// },
enableClear: {
description: "是否显示清除按钮",
title: "启用清除按钮",
type: "boolean"
},
dataSourceType: {
description: "",
title: "数据源类型",
type: "enum",
editor: {
default: "static",
data: [
{ id: "static", name: "静态" },
{ id: "dynamic", name: "动态" }
]
},
refreshPanelAfterChanged: !0
},
dataSource: {
description: "动态数据源绑定变量",
visible: o,
title: "数据",
editor: {
...r,
controlName: "",
enableClear: !0
},
refreshPanelAfterChanged: !0
},
data: {
description: "",
title: "数据",
type: "array",
visible: m,
...a.getItemCollectionEditor(t, t.editor.valueField, t.editor.textField),
// 这个属性,标记当属性变更得时候触发重新更新属性
refreshPanelAfterChanged: !0
},
url: {
visible: t.editor.dataSourceType === "dynamic" && !((u = t.editor) != null && u.dataSource),
$converter: z,
description: "",
title: "服务端API",
type: "string",
refreshPanelAfterChanged: !0
},
// method: {
// visible: propertyData.editor.dataSourceType === "dynamic",
// $converter: comboListRemoteConverter,
// description: "",
// title: "服务端API类型",
// type: "enum",
// editor: {
// default: "GET",
// data: [
// { id: "GET", name: "GET" },
// { id: "PUT", name: "PUT" },
// { id: "POST", name: "POST" }
// ]
// },
// },
body: {
visible: !1,
$converter: z,
description: "",
title: "服务端API参数",
type: "string"
},
textField: {
description: "",
title: "数据源显示字段",
type: "string",
readonly: t.editor.dataSourceType !== "dynamic"
},
valueField: {
description: "",
title: "数据源值字段",
type: "string",
readonly: t.editor.dataSourceType !== "dynamic"
},
multiSelect: {
description: "",
title: "启用多选",
visible: !l || l === "StringType",
readonly: ((s = t.editor) == null ? void 0 : s.dataSourceType) === "dynamic" && !!((c = t.editor) != null && c.dataSource),
type: "boolean",
refreshPanelAfterChanged: !0
},
maxLength: {
description: "",
title: "最大输入长度",
type: "number",
editor: {
nullable: !0,
min: 0,
useThousands: !1,
needValid: !0
}
},
...this.getCommonEditorProperties(t)
},
(i, d) => {
if (!i || !d.editor)
return;
const f = this;
switch (i.propertyID) {
case "dataSourceType": {
i.propertyValue === "static" ? (d.editor.valueField = "value", d.editor.textField = "name", d.editor.remote = null) : i.propertyValue === "dynamic" && (d.editor.remote = { method: "GET" }, d.editor.valueField = "value", d.editor.textField = "name");
break;
}
case "data": {
!f.checkEnumDataReadonly(d) && d.formatter && (d.formatter.data = [...i.propertyValue]);
break;
}
case "viewType": {
i.propertyValue === "tag" && (d.editor.editable = !1);
break;
}
case "dataSource":
f.afterMutilEditorChanged(d, i);
break;
}
}
);
}
getGridFieldEdtiorProperties(t, a) {
var g, y, v, h, F, b, x, B, V, n, u, s, c;
const l = this;
let r = "";
if (((g = t == null ? void 0 : t.binding) == null ? void 0 : g.type) === "Form") {
const i = this.schemaService.getFieldByIDAndVMID(t.binding.field, this.viewModelId);
(y = i == null ? void 0 : i.schemaField) != null && y.type && (r = i.schemaField.type.$type);
}
const m = ((h = (v = this.designViewModelField) == null ? void 0 : v.type) == null ? void 0 : h.$type) === R.StringType && ((F = t.editor) == null ? void 0 : F.type) === "combo-list" && ((b = t.editor) == null ? void 0 : b.dataSourceType) === "dynamic" && !((x = t.editor) != null && x.multiSelect), o = this.getPropertyEditorParams(t, ["Variable"]);
return l.getComponentConfig(
t,
{ type: "combo-list" },
{
// editable: {
// description: "",
// title: "允许编辑",
// type: "boolean",
// readonly: propertyData.editor?.type === 'combo-list'
// },
enableClear: {
description: "",
title: "启用清空",
type: "boolean"
},
dataSourceType: {
description: "",
title: "数据源类型",
type: "enum",
editor: {
default: "static",
data: [
{ id: "static", name: "静态" },
{ id: "dynamic", name: "动态" }
]
},
refreshPanelAfterChanged: !0
},
dataSource: {
description: "动态数据源绑定变量",
visible: m,
title: "数据",
editor: {
...o,
controlName: "",
enableClear: !0
},
refreshPanelAfterChanged: !0
},
data: {
description: "",
title: "数据",
type: "array",
visible: !((B = t.editor) != null && B.dataSourceType) || ((V = t.editor) == null ? void 0 : V.dataSourceType) === "static",
...l.getItemCollectionEditor(t, (n = t.editor) == null ? void 0 : n.valueField, (u = t.editor) == null ? void 0 : u.textField),
// 这个属性,标记当属性变更得时候触发重新更新属性
refreshPanelAfterChanged: !0
},
textField: {
description: "",
title: "数据源显示字段",
type: "string",
readonly: !0
},
valueField: {
description: "",
title: "数据源值字段",
type: "string",
readonly: !0
},
multiSelect: {
description: "",
title: "启用多选",
visible: r === "StringType",
readonly: ((s = t.editor) == null ? void 0 : s.dataSourceType) === "dynamic" && !!((c = t.editor) != null && c.dataSource),
type: "boolean",
refreshPanelAfterChanged: !0
},
maxLength: {
description: "",
title: "最大输入长度",
type: "number",
editor: {
nullable: !0,
min: 0,
useThousands: !1,
needValid: !0
}
},
...this.getCommonEditorProperties(t)
},
(i, d) => {
if (!i || !d.editor)
return;
const f = this;
switch (i.propertyID) {
case "dataSourceType": {
i.propertyValue === "static" ? (d.editor.valueField = "value", d.editor.textField = "name", d.editor.remote = null) : i.propertyValue === "dynamic" && (d.editor.remote = { method: "GET" }, d.editor.valueField = "value", d.editor.textField = "name");
break;
}
case "data": {
!f.checkEnumDataReadonly(d) && d.formatter && (d.formatter.data = [...i.propertyValue]);
break;
}
case "dataSource":
f.afterMutilEditorChanged(d, i);
}
}
);
}
setEditorPropertyRelates(t, a, l) {
if (!t || !a.editor)
return;
const r = this;
switch (t.propertyID) {
case "dataSourceType": {
t.propertyValue === "static" && (a.editor.valueField = "value", a.editor.textField = "name", a.editor.remote = {});
break;
}
case "data": {
!r.checkEnumDataReadonly(a) && a.formatter && (a.formatter.data = [...t.propertyValue]);
break;
}
}
}
/**
* 切换绑定属性
*/
changeBindingField(t, a, l) {
var m;
super.changeBindingField(t, a);
const r = l;
t.editor && ((m = r == null ? void 0 : r.type) == null ? void 0 : m.$type) === R.EnumType && (t.editor.data = r.type.enumValues || []);
}
/**
* 组装输入类控件的交互面板:包含标签超链、绑定字段值变化前后事件等。
* @param propertyData 属性值
* @param viewModelId 视图模型id
* @param showPosition 面板展示位置
* @param customEvent 输入控件特有的事件配置
*/
getEventPropertyConfig(t, a = "card", l, r) {
const m = this;
let o = [
{
label: "onChange",
name: "值变化事件"
},
// {
// label: 'onClear',
// name: '清空事件'
// },
{
label: "beforeOpen",
name: "打开面板前事件"
},
{
label: "beforeHide",
name: "关闭面板前事件"
},
{
label: "onShown",
name: "面板打开事件"
},
{
label: "onHidden",
name: "面板关闭事件"
}
];
o = [...o, ...this.getInputCommonEvents(t)], l && (o = o.concat(l)), this.formRule && (o = o.filter((v) => v.label !== "onChange")), this.appendFieldValueChangeEvents(t, o);
const T = m.eventsEditorUtils.formProperties(t, m.viewModelId, o);
return {
title: "事件",
hideTitle: !0,
properties: m.createBaseEventProperty(T),
tabId: he,
tabName: "交互",
setPropertyRelates(v, h) {
const F = v.propertyValue;
delete t[m.viewModelId], F && (F.setPropertyRelates = this.setPropertyRelates, m.eventsEditorUtils.saveRelatedParameters(t, m.viewModelId, F.events, F), m.updateLinkedLabel(F, h)), r && r(v, h, F);
const b = m.designViewModelUtils.getDgViewModel(m.viewModelId);
b && m.designViewModelField && b.changeField(m.designViewModelField.id, {
valueChanging: t.fieldValueChanging || "",
valueChanged: t.fieldValueChanged || ""
}), t.editor.onShown = t.onShown, t.editor.onHidden = t.onHidden, t.editor.beforeHide = t.beforeHide, t.editor.beforeOpen = t.beforeOpen, t.editor.onChange = t.onChange, t.editor.onClear = t.onClear;
}
};
}
}
function ze(e, t) {
const a = e.schema;
function l(r, m) {
return new je(r, t).getPropertyConfig(a, m);
}
return {
getPropsConfig: l
};
}
const _e = /* @__PURE__ */ E({
name: "FComboListDesign",
props: He,
emits: ["clear", "update:modelValue", "change"],
setup(e, t) {
const a = I(), l = G("designer-host-service"), r = G("design-item-context"), m = ze(r, l), o = be(a, r, m);
return _(() => {
a.value.componentInstance = o;
}), t.expose(o.value), () => w(ge, {
ref: a,
buttonContent: e.dropDownIcon,
readonly: !0,
editable: !1,
forcePlaceholder: !0,
placeholder: e.placeholder,
expandable: e.expandable,
expandMode: e.expandMode,
expandContent: e.expandContent,
expandDisabled: e.expandDisabled
}, null);
}
});
N.register = (e, t, a, l, r) => {
e["combo-list"] = N, t["combo-list"] = D(r), l["combo-list"] = { callbackResolver: Me };
};
N.registerDesigner = (e, t, a, l) => {
e["combo-list"] = _e, t["combo-list"] = D(l);
};
const ot = ve(N);
export {
N as FComboList,
ke as FComboListContainer,
qe as FTouchComboListContainer,
pe as Placement,
Me as callbackResolver,
He as comboListDesignProps,
U as comboListProps,
ot as default,
at as propsResolver,
D as propsResolverGenerator,
Ue as useDataSource
};