UNPKG

@farris/ui-vue

Version:

Farris Vue, a Farris Design based Vue3 component library.

1,702 lines 104 kB
import { defineComponent as Y, ref as B, watch as j, createVNode as c, createTextVNode as Z, computed as L, onMounted as _, onUnmounted as de, reactive as X, inject as ye, withDirectives as ce, vModelText as Re, resolveDirective as qe, Fragment as ae, mergeProps as $e, vModelSelect as We, watchEffect as Ge, nextTick as le } from "vue"; import je, { FButtonEdit as Ue } from "../button-edit/index.esm.js"; import { useResizeObserver as ze, useTouchMomentum as Ke, useTouch as Ye, useCommonUtils as ie, useBem as Fe, useFarrisConfig as _e, FormSchemaEntityFieldType$Type as ne, EVENT_PROPERTY_TAB_IDS as Je, withInstall as Te, useTextBox as Ze, useClear as De } from "../common/index.esm.js"; import { LocaleService as oe } from "../locale/index.esm.js"; import { resolveAppearance as Qe, createPropsResolver as Xe, getPropsResolverGenerator as et } from "../dynamic-resolver/index.esm.js"; import tt from "../list-view/index.esm.js"; import { isUndefined as lt, flatten as nt } from "lodash-es"; import "bignumber.js"; import at from "../../designer/button-edit/index.esm.js"; import { InputBaseProperty as it } from "../property-panel/index.esm.js"; import { useDesignerComponent as ot } from "../designer-canvas/index.esm.js"; import { useNumber as ut, useFormat as rt, useSpinner as st, useTextBox as dt, getSpinnerRender as ct, getNumberTextBoxRender as ft, FNumberSpinner as se } from "../number-spinner/index.esm.js"; import { useInputExpand as mt } from "../common/index.esm.js/text-box/use-input-expand"; import { FSwitch as vt } from "../switch/index.esm.js"; import { FDatePicker as pe } from "../components/index.esm.js"; import { FRadioGroup as ht } from "../radio-group/index.esm.js"; import { FCheckboxGroup as gt } from "../checkbox-group/index.esm.js"; const yt = { fields: { type: Array, default: [] }, defaultValue: { type: Object, default: null } }; var I = /* @__PURE__ */ ((e) => (e[e.Equal = 0] = "Equal", e[e.NotEqual = 1] = "NotEqual", e[e.Greater = 2] = "Greater", e[e.GreaterEqual = 3] = "GreaterEqual", e[e.Less = 4] = "Less", e[e.LessEqual = 5] = "LessEqual", e[e.Contains = 6] = "Contains", e[e.NotContains = 9] = "NotContains", e[e.IsEmpty = 12] = "IsEmpty", e[e.IsNotEmpty = 13] = "IsNotEmpty", e))(I || {}), R = /* @__PURE__ */ ((e) => (e[e.Empty = 0] = "Empty", e[e.And = 1] = "And", e[e.Or = 2] = "Or", e))(R || {}); const be = [ { label: "包含", value: 6 /* Contains */ }, { label: "不包含", value: 9 /* NotContains */ }, { label: "等于", value: 0 /* Equal */ }, { label: "不等于", value: 1 /* NotEqual */ } ], pt = /* @__PURE__ */ Y({ name: "SearchFieldsPanel", props: { fields: Array, searchValue: { type: String, default: "" }, maxWidth: { type: Number, default: 300 }, locales: Object }, emits: ["fieldSelected"], setup(e, t) { const l = B(e.fields || []); j(() => e.fields, (i) => { l.value = i || []; }); function n(i, h) { h.dataType === "boolean" ? h.value = { value: null, isEmpty: null } : e.searchValue ? h.value = { compare: I.Contains, value: e.searchValue } : h.value = { value: null, isEmpty: null, compare: void 0 }, t.emit("fieldSelected", h); } function a() { return e.searchValue.trim().split(" ").join('<span class="text-muted" style="margin: 0 5px;"> 或 </span>'); } const f = (i) => { var S, g, d, v; const h = " " + (((g = (S = e.locales) == null ? void 0 : S.operators) == null ? void 0 : g.contains) || "包含") + " ", p = " " + ((v = (d = e.locales) == null ? void 0 : d.relation) == null ? void 0 : v.or) || "或 "; return i.title + (e.searchValue ? h + e.searchValue.trim().split(" ").join(p) : ""); }; return () => { var i; return c("div", { class: "search-fields-list p-2", style: { maxWidth: e.maxWidth + "px" } }, [c("span", { style: "font-weight: bold;" }, [((i = e.locales) == null ? void 0 : i.chooseField) || "选择搜索字段", Z(":")]), c("div", { class: "search-fields-list-content mt-2" }, [c("ul", null, [l.value.map((h) => { var S, g; const p = f(h); return e.searchValue ? c("li", { class: "search-fields-list-item d-flex flex-row", attr_field: h.field, title: p, onClick: (d) => n(d, h) }, [c("span", { class: "search-field-title", title: h.title }, [h.title]), c("span", { class: "mx-2 text-muted" }, [((g = (S = e.locales) == null ? void 0 : S.operators) == null ? void 0 : g.contains) || "包含"]), c("div", { class: "f-utils-fill text-primary search-box-keyword", style: "text-overflow: ellipsis;", innerHTML: a() }, null)]) : c("li", { class: "search-fields-list-item", attr_field: h.field, title: p, onClick: (d) => n(d, h) }, [h.title]); })])])]); }; } }), bt = /* @__PURE__ */ Y({ name: "SearchInput", props: { placeholder: String, fields: Array, popoverOffsetWidth: Number, beforeOpenFieldsPanel: Function, locales: Object }, emits: ["fieldSelected", "inputKeydown", "valueChange"], setup(e, t) { const l = B(), n = B(), a = B(""), f = B(e.popoverOffsetWidth || 20), i = L(() => { var y; const v = (y = l.value) == null ? void 0 : y.popoverRef; return v ? v.shown : !1; }), h = (v) => { var y, w, V; if ((v.keyCode === 8 || v.keyCode === 13) && !a.value) (y = l.value) == null || y.hidePopup(), t.emit("inputKeydown", { key: v.keyCode === 8 ? "backspace" : "enter", event: v }); else if (!((w = e.fields) != null && w.length)) { (V = l.value) == null || V.clear(), v.preventDefault(); return; } }, p = (v) => { var y; a.value = v.trim().replace(/\s+/g, " "), t.emit("valueChange", a.value), i.value || (y = l.value) == null || y.showPopup(); }; function S(v) { var w, V; const y = !!a.value; (w = l.value) == null || w.clear(), (V = l.value) == null || V.hidePopup(), t.emit("fieldSelected", v, y); } const g = B(0); let d = null; return _(() => { var y; const v = (y = l.value) == null ? void 0 : y.getTextbox(); v && (d = ze(v, () => { g.value = window.innerWidth - v.getBoundingClientRect().left - f.value; })); }), de(() => { d && d(); }), t.expose({ showPopover: i, focus: () => { var v; return (v = l.value) == null ? void 0 : v.getTextbox().focus(); }, focusAndShow: () => { var v, y; (v = l.value) == null || v.getTextbox().focus(), (y = l.value) == null || y.showPopup(); } }), () => { var v; return (v = e.fields) != null && v.length ? c(Ue, { ref: l, readonly: !1, editable: !0, placeholder: e.placeholder, enableClear: !1, maxLength: 100, inputType: "text", popupOnClick: !0, placement: "auto", popupMinWidth: 180, showAppendButton: !1, keepWidthWithReference: !1, popupClass: "search-fields-panel", beforeOpen: e.beforeOpenFieldsPanel, onKeydown: h, onChange: p, popupOffsetY: -4 }, { default: () => [i.value && c(pt, { maxWidth: g.value, ref: n, locales: e.locales, fields: e.fields, searchValue: a.value, onFieldSelected: (y) => S(y) }, null)] }) : c("input", { type: "text", class: "form-control", onKeydown: h, onInput: (y) => { y.target.value = "", y.preventDefault(); }, placeholder: "" }, null); }; } }), we = /* @__PURE__ */ new Map([ ["appearance", Qe] ]), xt = "https://json-schema.org/draft/2020-12/schema", Ct = "https://farris-design.gitee.io/combo-list.schema.json", St = "combo-list", Ft = "A Farris Input Component", Tt = "object", wt = { 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: "" } }, Et = [ "type" ], Bt = [ "id", "appearance", "binding", "visible" ], Vt = { onClear: "清空事件", onShown: "面板打开事件", onHidden: "面板关闭事件", onChange: "值变化事件", beforeOpen: "打开面板前事件", beforeHide: "关闭面板前事件" }, Ee = { $schema: xt, $id: Ct, title: St, description: Ft, type: Tt, properties: wt, required: Et, ignore: Bt, events: Vt }; function Be(e, t, l) { return t; } function kt() { function e(t, l, n) { const a = {}; return a.beforeOpen = (f) => l.call("beforeOpen", t, [f, t], n), a; } return { resolve: e }; } const ue = { /** * 组件标识 */ 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 } }, It = Object.assign({}, ue, { readonly: {} }); Xe(ue, Ee, we, Be); const Ve = et( ue, Ee, we, Be ), Pt = kt(), At = { 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 } }, Lt = /* @__PURE__ */ Y({ name: "FComboListContainer", props: At, emits: ["selectionChange"], setup(e, t) { const l = B(), n = B(e.dataSource), a = B(e.dataSource), f = B([]), i = B(e.separator), h = B(e.width), p = B(e.maxHeight), S = L(() => e.multiSelect), g = B(e.multiSelect ? String(e.selectedValues).split(i.value) : [e.selectedValues]), d = L(() => ({ enableSelectRow: !0, multiSelect: e.multiSelect, multiSelectMode: "OnCheckAndClick", showCheckbox: S.value, showSelectAll: !1, showSelection: !0 })); j(e.dataSource, () => { n.value = e.dataSource, a.value = e.dataSource; }), L(() => e.enableSearch ? "SearchBar" : "ContentHeader"); const v = L(() => { const o = {}; return h.value !== void 0 && (o.width = `${h.value}px`), p.value !== void 0 && p.value > 0 && (o.maxHeight = `${p.value}px`), o; }); function y(o) { l.value.search(o); } function w(o) { f.value = o.map((m) => Object.assign({}, m)), g.value = o.map((m) => m[e.idField]), t.emit("selectionChange", f.value); } function V(o) { if (e.enableHighlightSearch) return; let m = []; const { searchOption: F } = e; typeof F == "function" ? m = n.value.filter((s) => F(o, s)) : m = n.value.filter((s) => s[e.valueField].indexOf(o) > -1 || s[e.textField].indexOf(o) > -1), l.value.updateDataSource(m); } j([() => e.selectedValues], ([o]) => { e.multiSelect ? g.value = o.split(i.value) : g.value = [o]; }); function P(o) { l.value.activeRowById(o); } return _(() => { var o, m; if (!e.multiSelect) { const F = (o = g.value) == null ? void 0 : o[0]; let s = F; const u = n.value.map((r) => r[e.valueField || e.idField]); if (!lt(F) && u.includes(F)) { const r = typeof F, b = typeof ((m = n.value[0]) == null ? void 0 : m[e.valueField || e.idField]); b === "number" && r !== b && (s = Number(F)), b === "boolean" && r !== b && (s = F === "true" ? !0 : F === "false" ? !1 : F), P(s); } } }), t.expose({ search: y, activeRowById: P }), () => c("div", { class: "f-combo-list-container", style: v.value }, [c(tt, { ref: l, size: "small", itemClass: "f-combo-list-item", itemContentClass: "text-truncate", header: "ContentHeader", headerClass: "f-combo-list-search-box", data: n.value, idField: e.idField, textField: e.textField, titleField: e.titleField, multiSelect: e.multiSelect, selection: d.value, enableHighlightSearch: e.enableHighlightSearch, selectionValues: g.value, onSelectionUpdate: w, onAfterSearch: V }, null)]); } }), xe = { property: "all", duration: 0.3, timingFunction: "cubic-bezier(0.17, 0.89, 0.45, 1)", delay: 0 }, Mt = (e, t) => { const l = e.lineHeight / 2, n = Ke({ maxOverflowY: 44 }), a = X({ ...xe }), f = (s) => { t.emit("change", s); }, i = X({ value: 0, max: 0, min: 0, start: 0, index: 0, currentItem: void 0, active: !1 }), h = () => { i.max = e.visiableOptionCount / 2 * e.lineHeight; const s = e.column.length * e.lineHeight; i.min = i.max - s + e.lineHeight; }, p = (s = 0) => { h(), i.index = s, i.value = i.max - s * e.lineHeight, i.currentItem = e.column[s]; }, S = (s) => { const u = e.column.length - 1, r = Math.min(i.index, u), b = e.column.findIndex((C) => C[e.valueField] === s); return b >= 0 ? b : r; }, g = (s) => { const u = e.column.length - 1; return i.index > u ? e.column[u] : e.column[s]; }, d = (s) => { s && (i.currentItem = s, a.duration = 0); const u = i.currentItem[e.valueField], r = S(u), b = g(i.index)[e.valueField]; p(r), u !== b && setTimeout(() => { f(i.currentItem); }, a.duration * 1e3); }, v = () => { const s = Array.isArray(e.value) ? e.value[0] : e.value; p(S(s)); }; v(), j(() => e.value, () => { e.multiSelect || v(); }), j(() => e.column, () => d()); const y = (s, u = i.max, r = i.min) => { const b = i.start + s; i.value = b > l ? Math.min(b, u) : Math.max(b, r), i.index = Math.round((i.max - i.value) / e.lineHeight), i.currentItem = g(i.index); }, w = Ye(), V = (s) => { w.start(s), i.active = !0, i.start = i.value, n.start(i.start), a.duration = 0; }, P = (s) => { s.preventDefault(), w.move(s), y( w.deltaY.value, i.max + e.lineHeight, i.min - e.lineHeight ), n.move(w.deltaY.value), a.duration = xe.duration; }, o = (s) => { const u = s < 0, r = s % e.lineHeight > l ? 1 : 0, b = Math.floor(s / e.lineHeight); return (u ? b - r : b + r) * e.lineHeight + l; }; return { translateY: i, transition: a, onTouchStart: V, onTouchMove: P, onTouchEnd: () => { i.start = 0; const s = n.end(); let u = 0; if (s) { const { destination: r, duration: b } = n.get(i.value, i.min, i.max); u = r, a.duration = b / 1e3; } else u = i.value; y(o(u)), f(i.currentItem); }, onTransitionend: () => { i.active = !1; }, updateTranslate: d }; }, Ot = { 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 } }, Ht = /* @__PURE__ */ Y({ props: Ot, emits: ["change", "click"], setup(e, t) { const { addUnit: l } = ie(), { bem: n } = Fe("FComboTouchList"), { translateY: a, transition: f, onTouchStart: i, onTouchMove: h, onTouchEnd: p, onTransitionend: S } = Mt(e, t), g = (y) => { t.emit("click", y); }, d = L(() => ({ transform: `translateY(${l(a.value)})`, transition: `all ${a.active ? f.duration : 0}s ${f.timingFunction} 0s` })), v = (y) => e.showIcon ? Array.isArray(e.value) && e.value.includes(y[e.valueField]) : !1; return () => c("div", { class: n("column"), style: d.value, onTouchstart: i, onTouchmove: h, onTouchend: p, onTransitionend: S }, [e.column.map((y) => c("div", { class: n("column-item"), onClick: () => g(y) }, [c("span", null, [y[e.textField]]), v(y) && c("span", { class: `f-icon f-icon-check ${n("column-item-icon")}` }, null)]))]); } }), Nt = { 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: "," } }, Rt = (e, t) => { const { finalValue: l, initValue: n, setSelectedByIndex: a, getSelectedValueByIndex: f } = t, { isArray: i, isFunction: h, isObject: p } = ie(), S = (u) => u && u[0], g = L(() => { var u; return ((u = e.columns) == null ? void 0 : u.length) > 0 && i(e.columns[0]); }), d = (u) => { if ((u == null ? void 0 : u.length) === 0) return !1; const r = S(u); return r && i(r[e.childrenField]); }, v = (u, r) => { const b = S(u), C = f(r); let H = u.find((q) => q[e.valueField] === C); H = H || b; const M = H[e.childrenField] || []; if (d(M)) { const q = v(M, r + 1); return [M, ...q]; } return [M]; }, y = () => { const u = e.columns, r = v(u, 0); return [u, ...r]; }, w = (u, r) => { const b = u[e.textField]; return h(e.optionFormatter) ? e.optionFormatter(r, u) : b; }, V = (u, r) => u.map((b) => { const C = p(b) ? b : { [e.valueField]: b, [e.textField]: b }; return C[e.textField] = w(C, r), C; }), P = L(() => { let u = []; return g.value ? u = e.columns : d(e.columns) ? u = y() : u = [e.columns], u.map(V); }), o = () => P.value.map((u, r) => { const b = l.value[r]; return u.find((H) => H[e.valueField] === b); }).filter((u) => u), m = () => o().map((u) => u[e.valueField]), F = () => o().map((u) => u[e.textField]).join("-"), s = () => { P.value.forEach((u, r) => { if (e.multiSelect) l.value[r].forEach((C) => { const H = u.find((M) => M[e.valueField] === C); H && a(r, H); }); else { const b = l.value[r], C = u.find((H) => H[e.valueField] === b); C ? a(r, C) : a(r, S(u)); } }); }; return j( () => e.modelValue, () => { n(e.modelValue), s(); }, { immediate: !0 } ), { columns: P, getPickeds: o, getValue: m, getTextValue: F }; }, qt = (e) => { const { isArray: t, isMultiArray: l, isString: n, isDef: a } = ie(), f = (o) => { let m = []; return t(o) ? m = o : n(o) ? m = o.split(e.separator) : a(o) && (m = [o]), e.multiSelect ? l(m) ? m : [m] : m; }, i = B([]), h = (o) => { i.value = f(o); }, p = X([]), S = L(() => p.map((o) => o[e.valueField])), g = X([]), d = L(() => g.map((o) => o.map((m) => m[e.valueField]))); return { finalValue: i, initValue: h, getSelected: () => e.multiSelect ? g : p, getSelectedValue: () => e.multiSelect ? d.value : S.value, setSelectedByIndex: (o, m) => { if (e.multiSelect) { const F = g[o] || []; F.includes(m) ? g[o] = F.filter((s) => s !== m) : g[o] = [...F, m]; } else p[o] = m; }, getSelectedByIndex: (o) => e.multiSelect ? g[o] : p[o], getSelectedValueByIndex: (o) => e.multiSelect ? d.value[o] : S.value[o] }; }, $t = /* @__PURE__ */ Y({ props: Nt, emits: ["change", "confirm", "cancel", "update:modelValue"], setup(e, t) { const { emit: l } = t, { addUnit: n } = ie(), a = qt(e), { finalValue: f, getSelectedValue: i, getSelectedValueByIndex: h, getSelected: p, setSelectedByIndex: S } = a, { columns: g } = Rt(e, a), d = (F, s = !0) => { const { value: u, index: r } = F; (s && !e.multiSelect || !s && e.multiSelect) && (l("change", F), S(r, u)); }, v = () => { f.value = i(), l("confirm", p()), l("update:modelValue", f.value); }, y = () => { l("cancel"); }, { bem: w } = Fe("FComboTouchList"), V = () => c("div", { class: w("toolbar") }, [c("div", { class: w("toolbar-left"), onClick: y }, [c("span", null, [e.cancelText])]), c("div", { class: w("toolbar-title") }, [c("span", null, [e.title])]), c("div", { class: w("toolbar-right"), onClick: v }, [c("span", null, [e.confirmText])])]), P = L(() => { const F = (e.visiableOptionCount + 1) * e.lineHeight; return { height: n(F) }; }), o = L(() => { const F = e.visiableOptionCount * e.lineHeight / 2; return { backgroundSize: `100% ${n(F)}` }; }), m = () => c("div", { class: w("content") }, [c("div", { class: w("columns"), style: P.value }, [g.value.map((F, s) => c(Ht, { column: F, value: h(s), showIcon: e.multiSelect, textField: e.textField, multiSelect: e.multiSelect, valueField: e.valueField, lineHeight: e.lineHeight, visiableOptionCount: e.visiableOptionCount, onChange: (u) => d({ value: u, index: s }), onClick: (u) => d({ value: u, index: s }, !1) }, null)), !e.multiSelect && c("div", { class: w("mask"), style: o.value }, null), c("div", { class: w("frame") }, null)])]); return () => c("div", { class: w("") }, [e.showToolbar && V(), m()]); } }); function Wt(e, t) { const l = B(""), n = B(e.modelValue), a = B(e.data || []), f = B(e.editable), i = L(() => e.hideDisabledItems ? a.value.filter((o) => !o.disabled) : a.value); function h(o) { const m = e.multiSelect ? String(o).split(e.separator) : [String(o)], F = m.map((r) => [r, !0]), s = new Map(F); return a.value.filter((r) => s.has(String(r[e.valueField]))).sort((r, b) => { const C = m.indexOf(r[e.valueField]), H = m.indexOf(b[e.valueField]); return C - H; }); } function p(o) { const m = h(o).map((F) => F[e.textField]).join(e.separator); l.value = f.value ? m || o : m; } function S(o) { if (e.multiSelect) { const m = o.split(e.separator).map((s) => [s, !0]), F = new Map(m); return a.value.filter((s) => F.has(s[e.textField])); } return a.value.filter((m) => "" + m[e.textField] === o); } function g(o) { const m = {}; return m[e.idField] = o, m[e.textField] = o, [m]; } function d(o) { let m = S(o); const F = m && m.length > 0; return f.value && !F && (m = g(o)), m; } function v() { const { url: o, method: m = "GET", headers: F = { "Content-Type": "application/json;charset=utf-8;" }, body: s = null } = e.remote; if (!o) return; const { basePath: u } = _e().value, r = m.toLowerCase() === "get" ? { method: m, headers: F } : { method: m, headers: F, body: s }; let b = !1; fetch(new Request(u + o, r)).then((C) => { var M, q; if (C.status === 200) return b = !!((q = (M = C.headers) == null ? void 0 : M.get("content-type")) != null && q.includes("application/json")), b ? C.text() : C.json(); throw C.status === 405 ? new Error(oe.getLocaleValue("comboList.remoteError")) : new Error(C.statusText); }).then((C) => { C.length && (a.value = b ? JSON.parse(C) : C, n.value && p(n.value)); }).catch((C) => { console.warn(C); }); } e.remote && (e.load ? e.load().then((o) => { a.value = o; }).catch((o) => { console.log(o); }) : v()), j(() => e.data, () => { a.value = e.data; }), j([a], ([o], [m]) => { if (e.modelValue != null && !e.multiSelect) { const F = o.find((s) => s[e.valueField] === n.value); F ? F[e.valueField] !== n.value ? (n.value = F[e.valueField], l.value = F[e.textField], t.emit("update:modelValue", F[e.valueField]), t.emit("change", [F], F[e.valueField])) : l.value !== F[e.textField] && (l.value = F[e.textField]) : n.value !== "" && (n.value = "", l.value = "", t.emit("update:modelValue", ""), t.emit("change", [], "")); } }), j(() => e.modelValue, (o, m) => { m !== o && (n.value = o, p(o)); }); function y(o) { a.value = o, t.emit("dataChanged", o); } function w() { return a.value; } function V() { return l.value; } async function P() { const o = typeof e.beforeOpen == "function"; return !e.beforeOpen || !o ? Promise.resolve(!0) : Promise.resolve().then(() => e.beforeOpen({ instance: { updateDataSource: y, getData: w, getDisplayText: V } })).then((m) => typeof (m == null ? void 0 : m.canOpen) == "boolean" ? m == null ? void 0 : m.canOpen : !0); } return p(e.modelValue), { dataSource: a, filteredDataSource: i, displayText: l, editable: f, modelValue: n, beforeOpenList: P, getItemsByDisplayText: S, getItemsByValue: h, getSelectedItemsByDisplayText: d }; } const Gt = ["moz", "ms", "webkit"]; function jt() { let e = 0; return (t) => { const l = (/* @__PURE__ */ new Date()).getTime(), n = Math.max(0, 16 - (l - e)), a = setTimeout(() => { t(l + n); }, n); return e = l + n, a; }; } function Ut() { if (typeof window > "u") return () => 0; if (window.requestAnimationFrame) return window.requestAnimationFrame.bind(window); const e = Gt.filter((t) => `${t}RequestAnimationFrame` in window)[0]; return e ? window[`${e}RequestAnimationFrame`] : jt(); } Ut(); B(""); function Ce() { 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 ], l = [ /iPad/i, /Android(?!.*Mobile)/i, // Android 平板通常不含 "Mobile" /Tablet/i, /PlayBook/i, /Kindle/i, /Silk/i ]; for (const h of l) if (h.test(e)) return !1; for (const h of t) if (h.test(e)) return !0; const n = "ontouchstart" in window || navigator.maxTouchPoints > 0, a = screen.width, f = screen.height, i = Math.min(a, f); return !!(n && i <= 768); } const ee = /* @__PURE__ */ Y({ name: "FComboList", props: ue, emits: ["clear", "update:modelValue", "change", "input", "dataChanged", "expandClick"], setup(e, t) { const l = B(), n = B(), a = B(e.disabled || e.readonly), f = B(e.enableClear), i = B(e.enableSearch), h = B(e.readonly), { dataSource: p, displayText: S, editable: g, modelValue: d, filteredDataSource: v, getItemsByDisplayText: y, getItemsByValue: w, beforeOpenList: V } = Wt(e, t), P = B(e.dropDownIcon); P.value === '<span class="f-icon f-icon-arrow-chevron-down"></span>' && (P.value = '<span id="' + e.id + '-icon-dropdown" class="f-icon f-icon-arrow-chevron-down"></span>'); const o = L(() => e.multiSelect), m = L(() => n.value ? n.value.elementRef.getBoundingClientRect().width : 0); function F() { !o.value && n.value && n.value.hidePopup(); } function s(k) { S.value = k.map((U) => U[e.textField]).join(e.separator) || d.value; let N = ""; k.length === 1 ? N = k[0][e.valueField] : N = k.map((U) => U[e.valueField]).join(e.separator), d.value !== N && (d.value = N, t.emit("update:modelValue", d.value), t.emit("change", k, d.value)); } function u() { const k = w(d.value); s(k); } function r() { h.value || S.value; } function b(k) { var N; d.value = "", (N = l.value) == null || N.activeRowById(""), t.emit("clear"); } function C(k) { var N, U; e.enableSearch && e.enableHighlightSearch && ((N = l.value) == null || N.search(k)), (U = l.value) == null || U.activeRowById(k), t.emit("change", [d.value], d.value); } function H(k) { if (e.multiSelect) { const N = y(k); e.viewType; const K = N.map((J) => J[e.idField || e.valueField]).join(e.separator); d.value !== K && (d.value = K, t.emit("update:modelValue", d.value), t.emit("change", N, d.value)); } else k !== d.value && (d.value = k, t.emit("update:modelValue", d.value), t.emit("change", [], k)); } function M() { return S.value; } function q(k) { const { value: N } = k.target; C(N), t.emit("input", N); } function z() { n.value.hidePopup(); } function T(k) { p.value = k; } function A() { return p.value; } const W = { getDisplayText: M, hidePopup: z, updateDataSource: T, getData: A }; t.expose(W), j([() => e.disabled, () => e.editable, () => e.enableClear, () => e.enableSearch, () => e.readonly], ([k, N, U, K, J]) => { a.value = k, g.value = N, f.value = U, i.value = K, h.value = J; }); const $ = () => { t.emit("expandClick"); }; return () => c(je, { ref: n, id: e.id, disable: a.value, readonly: h.value, forcePlaceholder: e.forcePlaceholder, editable: g.value, buttonContent: P.value, placeholder: e.placeholder === "请选择" ? oe.getLocaleValue("comboList.placeholder") : e.placeholder, enableClear: f.value, maxLength: e.maxLength, tabIndex: e.tabIndex, enableTitle: e.enableTitle, multiSelect: e.multiSelect, inputType: e.multiSelect ? e.viewType : "text", modelValue: S.value, "onUpdate:modelValue": (k) => S.value = k, focusOnCreated: e.focusOnCreated, selectOnCreated: e.selectOnCreated, onClear: b, onClick: r, onChange: H, onBlur: u, onInput: q, beforeOpen: V, placement: Ce() ? "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: $ }, { default: () => [Ce() ? c($t, { modelValue: d.value, valueField: e.valueField, textField: e.textField, columns: p.value, multiSelect: e.multiSelect, separator: e.separator, onConfirm: (k) => { const N = e.multiSelect ? k[0] || [] : k; s(N), n == null || n.value.hidePopup(); }, onCancel: () => { n == null || n.value.hidePopup(); } }, null) : c(Lt, { class: e.popupClass, ref: l, idField: e.idField, valueField: e.valueField, textField: e.textField, titleField: e.titleField, dataSource: v.value, selectedValues: d.value, separator: e.separator, multiSelect: e.multiSelect, enableSearch: i.value, maxHeight: e.maxHeight, enableHighlightSearch: e.enableHighlightSearch, width: e.fitEditor ? m.value : void 0, onSelectionChange: (k) => { s(k), F(); } }, null)] }); } }), Se = { convertFrom: (e, t) => (e.editor.remote || {})[t], convertTo: (e, t, l) => { e.editor.remote = e.editor.remote || {}, e.editor.remote[t] = l; } }; class zt extends it { constructor(t, l) { super(t, l); } getCommonEditorProperties(t) { var l, n, a; return { viewType: { visible: !!((l = t.editor) != null && l.multiSelect), description: "数据展示类型,有标签和文本两种方式", title: "数据展示类型", type: "enum", editor: { data: [ { id: "tag", name: "标签" }, { id: "text", name: "文本" } ] }, refreshPanelAfterChanged: !0 }, separator: { visible: !!((n = t.editor) != null && n.multiSelect) && ((a = t.editor) == null ? void 0 : a.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 p, S, g, d, v, y, w, V, P, o, m, F, s; const l = this; let n = ""; if (((p = t == null ? void 0 : t.binding) == null ? void 0 : p.type) === "Form") { const u = this.schemaService.getFieldByIDAndVMID(t.binding.field, this.viewModelId); (S = u == null ? void 0 : u.schemaField) != null && S.type && (n = u.schemaField.type.$type); } const a = this.getPropertyEditorParams(t, ["Variable"]), f = !t.editor.dataSourceType || t.editor.dataSourceType === "static", i = (((d = (g = this.designViewModelField) == null ? void 0 : g.type) == null ? void 0 : d.$type) === ne.StringType || !!this.formRule && ((v = this.designerHostService.schemaService.getFieldByID(t.binding.field)) == null ? void 0 : v.type.$type) === ne.StringType) && ((y = t.editor) == null ? void 0 : y.type) === "combo-list" && ((w = t.editor) == null ? void 0 : w.dataSourceType) === "dynamic" && !((P = (V = t.editor) == null ? void 0 : V.remote) != null && P.url) && !((o = t.editor) != null && o.multiSelect); return l.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: i, title: "数据", editor: { ...a, controlName: "", enableClear: !0 }, refreshPanelAfterChanged: !0 }, data: { description: "", title: "数据", type: "array", visible: f, ...l.getItemCollectionEditor(t, t.editor.valueField, t.editor.textField), // 这个属性,标记当属性变更得时候触发重新更新属性 refreshPanelAfterChanged: !0 }, url: { visible: t.editor.dataSourceType === "dynamic" && !((m = t.editor) != null && m.dataSource), $converter: Se, 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: Se, 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: !n || n === "StringType", readonly: ((F = t.editor) == null ? void 0 : F.dataSourceType) === "dynamic" && !!((s = t.editor) != null && s.dataSource), type: "boolean", refreshPanelAfterChanged: !0 }, maxLength: { description: "", title: "最大输入长度", type: "number", editor: { nullable: !0, min: 0, useThousands: !1, needValid: !0 } }, ...this.getCommonEditorProperties(t) }, (u, r) => { if (!u || !r.editor) return; const b = this; switch (u.propertyID) { case "dataSourceType": { u.propertyValue === "static" ? (r.editor.valueField = "value", r.editor.textField = "name", r.editor.remote = null) : u.propertyValue === "dynamic" && (r.editor.remote = { method: "GET" }, r.editor.valueField = "value", r.editor.textField = "name"); break; } case "data": { !b.checkEnumDataReadonly(r) && r.formatter && (r.formatter.data = [...u.propertyValue]); break; } case "viewType": { u.propertyValue === "tag" && (r.editor.editable = !1); break; } case "dataSource": b.afterMutilEditorChanged(r, u); break; } } ); } getGridFieldEdtiorProperties(t, l) { var p, S, g, d, v, y, w, V, P, o, m, F, s; const n = this; let a = ""; if (((p = t == null ? void 0 : t.binding) == null ? void 0 : p.type) === "Form") { const u = this.schemaService.getFieldByIDAndVMID(t.binding.field, this.viewModelId); (S = u == null ? void 0 : u.schemaField) != null && S.type && (a = u.schemaField.type.$type); } const f = ((d = (g = this.designViewModelField) == null ? void 0 : g.type) == null ? void 0 : d.$type) === ne.StringType && ((v = t.editor) == null ? void 0 : v.type) === "combo-list" && ((y = t.editor) == null ? void 0 : y.dataSourceType) === "dynamic" && !((w = t.editor) != null && w.multiSelect), i = this.getPropertyEditorParams(t, ["Variable"]); return n.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: f, title: "数据", editor: { ...i, controlName: "", enableClear: !0 }, refreshPanelAfterChanged: !0 }, data: { description: "", title: "数据", type: "array", visible: !((V = t.editor) != null && V.dataSourceType) || ((P = t.editor) == null ? void 0 : P.dataSourceType) === "static", ...n.getItemCollectionEditor(t, (o = t.editor) == null ? void 0 : o.valueField, (m = t.editor) == null ? void 0 : m.textField), // 这个属性,标记当属性变更得时候触发重新更新属性 refreshPanelAfterChanged: !0 }, textField: { description: "", title: "数据源显示字段", type: "string", readonly: !0 }, valueField: { description: "", title: "数据源值字段", type: "string", readonly: !0 }, multiSelect: { description: "", title: "启用多选", visible: a === "StringType", readonly: ((F = t.editor) == null ? void 0 : F.dataSourceType) === "dynamic" && !!((s = t.editor) != null && s.dataSource), type: "boolean", refreshPanelAfterChanged: !0 }, maxLength: { description: "", title: "最大输入长度", type: "number", editor: { nullable: !0, min: 0, useThousands: !1, needValid: !0 } }, ...this.getCommonEditorProperties(t) }, (u, r) => { if (!u || !r.editor) return; const b = this; switch (u.propertyID) { case "dataSourceType": { u.propertyValue === "static" ? (r.editor.valueField = "value", r.editor.textField = "name", r.editor.remote = null) : u.propertyValue === "dynamic" && (r.editor.remote = { method: "GET" }, r.editor.valueField = "value", r.editor.textField = "name"); break; } case "data": { !b.checkEnumDataReadonly(r) && r.formatter && (r.formatter.data = [...u.propertyValue]); break; } case "dataSource": b.afterMutilEditorChanged(r, u); } } ); } setEditorPropertyRelates(t, l, n) { if (!t || !l.editor) return; const a = this; switch (t.pro