UNPKG

@farris/ui-vue

Version:

Farris Vue, a Farris Design based Vue3 component library.

1,616 lines (1,615 loc) 48.8 kB
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 };