@farris/ui-vue
Version:
Farris Vue, a Farris Design based Vue3 component library.
513 lines (512 loc) • 14.6 kB
JavaScript
import { ref as u, onMounted as E, defineComponent as W, createVNode as n, withDirectives as L, vShow as T, Teleport as O, inject as V, Fragment as Z } from "vue";
import { resolveAppearance as G, createPropsResolver as J } from "../dynamic-resolver/index.esm.js";
import { useDesignerComponent as K } from "../designer-canvas/index.esm.js";
function M(e, l, a) {
return l;
}
const Q = /* @__PURE__ */ new Map([
["appearance", G]
]), U = "https://json-schema.org/draft/2020-12/schema", _ = "https://farris-design.gitee.io/dropdown.schema.json", P = "dropdown", ee = "A Farris Component", te = "object", oe = {
id: {
description: "The unique identifier for dropdown",
type: "string"
},
type: {
description: "The type string of dropdown",
type: "string",
default: "dropdown"
},
appearance: {
description: "",
type: "object",
properties: {
class: {
type: "string"
},
style: {
type: "string"
}
},
default: {}
},
binding: {
description: "",
type: "object",
default: {}
},
disable: {
type: "string",
default: !1
},
editable: {
description: "",
type: "boolean",
default: !0
},
placeholder: {
description: "",
type: "string",
default: ""
},
readonly: {
description: "",
type: "boolean",
default: !1
},
require: {
description: "",
type: "boolean",
default: !1
},
tabindex: {
description: "",
type: "number",
default: -1
},
visible: {
description: "",
type: "boolean",
default: !0
}
}, ne = [
"id",
"type"
], ie = {
$schema: U,
$id: _,
title: P,
description: ee,
type: te,
properties: oe,
required: ne
}, se = "dropdown", le = "A Farris Component", re = "object", ae = {
basic: {
description: "Basic Infomation",
title: "基本信息",
properties: {
id: {
description: "组件标识",
title: "标识",
type: "string",
readonly: !0
},
type: {
description: "组件类型",
title: "控件类型",
type: "select",
editor: {
type: "waiting for modification",
enum: []
}
}
}
},
behavior: {
description: "Basic Infomation",
title: "行为",
properties: {
readonly: {
description: "",
title: "只读",
type: "string"
},
required: {
description: "",
title: "必填",
type: "boolean"
},
visible: {
description: "",
title: "可见",
type: "boolean"
},
placeholder: {
description: "",
title: "提示文本",
type: "string"
},
tabindex: {
description: "",
title: "tab索引",
type: "number"
}
}
}
}, de = {
title: se,
description: le,
type: re,
categories: ae
}, z = {
/** 默认展开或折叠
* 注意:
* 1、这个属性在出现滚动条的情况下,滚动会导致收折,看不到展开的面板。
* 2、如果是放置在没有滚动条的界面,可有实际效果
*/
show: { type: Boolean, default: !1 },
/** 下拉按钮是否禁用 */
disabled: { type: Boolean, default: !1 },
/** 下拉按钮对应文字 */
title: { type: String, default: "下拉示例" },
/** 下拉按钮大小 */
size: { type: String, default: "" },
/** 下拉按钮类型 */
type: { type: String, default: "primary" },
/** 图标样式 */
iconClass: { type: String, default: "" },
/** 下拉框内容是否被选中
* ---未被使用
*/
active: { type: Boolean, default: !1 },
/** 下拉按钮是否分开展示 */
splitButton: { type: Boolean, default: !1 },
/** 下拉框展示方向 */
position: { type: String, default: "bottom" },
/** 下拉框内容 */
model: {
type: Array,
default: [
{ label: "项目一", value: "XM1" },
{ label: "项目二", value: "XM2" },
{ label: "项目三", value: "XM3" }
]
},
onSelect: { type: Function, default: () => {
} }
}, N = J(z, ie, Q, M, de);
function X(e, l) {
let a;
const i = u(e.show), m = u(), p = u(), w = u(), s = 10;
E(() => {
a = p.value;
});
const b = (o = 1) => {
const t = [
"body>.f-datagrid-settings-simple-host",
"body>div",
"body>farris-dialog>.farris-modal.show",
"body>.farris-modal.show",
"body>farris-filter-panel>.f-filter-panel-wrapper",
"body .f-sidebar-show>.f-sidebar-main",
"body>.popover.show",
"body>filter-row-panel>.f-datagrid-filter-panel",
"body>.f-section-maximize"
], f = Array.from(document.body.querySelectorAll(t.join(","))).filter((r) => r).map((r) => {
const { display: R, zIndex: S } = window.getComputedStyle(r);
return R === "none" ? 0 : parseInt(S, 10);
}).filter((r) => r);
let c = Math.max(...f);
return c < 1040 && (c = 1040), c + o;
}, x = (o, t) => {
const {
height: f,
left: c,
top: r,
width: R
} = o.getBoundingClientRect(), { width: S, height: A, top: pe } = t.getBoundingClientRect();
if (o.className.indexOf("dropdown-submenu") > -1 || o.closest(".dropdown-submenu") || o.classList.contains("dropright")) {
const H = window.innerWidth - c - o.offsetWidth, k = window.innerHeight - r, { position: h } = getComputedStyle(t);
if (h === "fixed") {
let y = c + o.offsetWidth;
t.offsetWidth > H && c > H && (y = c - S), t.style.left = y + "px", t.style.right = "auto", window.innerHeight - 2 * s < t.offsetHeight ? (t.style.top = s + "px", t.style.bottom = s + "px", t.style.maxHeight = window.innerHeight - 2 * s + "px", t.style.overflowY = "auto", t.className += " dropdown-menu-maxheight") : k < t.offsetHeight ? (t.style.top = "auto", t.style.bottom = s + "px") : (t.style.top = r + "px", t.style.bottom = "auto");
} else {
if (t.offsetWidth > H) {
const y = -S;
t.style.left = y + "px";
}
window.innerHeight - 2 * s < t.offsetHeight ? (t.style.top = -1 * (r - s) + "px", t.style.bottom = "auto", t.style.maxHeight = window.innerHeight - 2 * s + "px", t.style.overflowY = "auto", t.className += " dropdown-menu-maxheight") : k < t.offsetHeight && (t.style.top = k - t.offsetHeight - s + "px", t.style.bottom = "auto");
}
} else {
const { marginTop: H, marginBottom: k } = getComputedStyle(t);
let h = 0;
const y = Math.ceil(parseFloat(H)) + Math.ceil(parseFloat(k));
let g = r + f, q = c;
window.innerHeight - g - y < A && (g = r - A, g < 0 && (window.innerHeight - r - f > r ? (g = r + f, h = window.innerHeight - g - y - s) : (g = s, h = r - g - y))), window.innerWidth - c < S && window.innerWidth - c < c + R && (q = c - S + R), document.body.append(t), t.style.cssText = `position:fixed;bottom:unset;left:${q}px
!important;top:${g}px !important;right: unset;${h ? "max-height:" + h + "px;overflow-y:auto;" : ""}`, h && (t.className += " dropdown-menu-maxheight"), t.style.zIndex = b().toString();
}
}, v = () => {
x(m.value, p.value);
}, d = () => {
e.hover || (i.value = !1, p.value.style = null, document.removeEventListener("click", d), a.removeEventListener("click", d), document.removeEventListener("scroll", d), a.removeEventListener("scroll", d));
}, C = (o = null, t = !1) => {
e.hover || e.disabled || (o == null || o.stopPropagation(), t ? (setTimeout(() => {
v();
}), i.value = !0) : (i.value || setTimeout(() => {
v();
}), i.value = !i.value), document.addEventListener("click", d), document.addEventListener("scroll", d), e.hideOnClick || (a.addEventListener("click", (f) => {
f.stopPropagation();
}), a.addEventListener("scroll", (f) => {
f.stopPropagation();
})));
};
return {
show: i,
dropdownRef: m,
dropdownMenuRef: p,
clickEventRef: w,
showDropMenu: (o) => {
C(o, !1);
},
showDropMenuByForce: C,
hoverDropdown: (o) => {
e.hover && (i.value || setTimeout(() => {
}), i.value = !i.value);
},
leftButtonClick: () => {
},
closeDropMenu: d,
selectItem: (o) => {
l.emit("select", o);
},
resolveSize: (o) => {
const t = /px|em|rem|pt|%/;
return t.test(o) ? `${parseInt(o, 10)}${o.match(t)[0]}` : `${o}px`;
}
};
}
const ce = {
/** 下拉框标签 */
label: { type: String, default: "XM1" },
/** 下拉框名称 */
value: { type: String || Number, default: "项目一" },
/** 是否禁用该下拉框属性 */
disabled: { type: Boolean, default: !1 },
active: { type: Boolean, default: !1 },
divide: { type: Boolean, default: !1 },
onSelect: { type: Function, default: () => {
} }
}, Y = /* @__PURE__ */ W({
name: "FDropdownItem",
props: ce,
emits: ["select"],
setup(e, l) {
const a = u(e.value), i = u(e.label), m = u(e.disabled), p = u(e.active), w = u(e.divide), s = () => {
m.value || l.emit("select", e);
};
return () => n("div", null, [L(n("div", {
class: "dropdown-divider"
}, null), [[T, w.value]]), n("li", {
class: `dropdown-item${p.value ? " active" : ""} ${m.value ? " disabled" : ""}`,
onClick: s,
title: a.value.toString()
}, [i.value])]);
}
}), F = /* @__PURE__ */ W({
name: "FDropdown",
props: z,
emits: ["select"],
setup(e, l) {
const a = u(e.model), i = u(!1), {
show: m,
dropdownMenuRef: p,
dropdownRef: w,
clickEventRef: s,
showDropMenu: b,
hoverDropdown: x,
leftButtonClick: v,
showDropMenuByForce: d,
closeDropMenu: C
} = X(e, l);
function $(B) {
C(), l.emit("select", B);
}
function D() {
return [{
"dropdown-item": e.nest
}, {
"btn-lg": e.size === "large"
}, {
"btn-sm": e.size === "small"
}, {
"btn-primary": e.type === "primary"
}, {
"btn-success": e.type === "success"
}, {
"btn-warning": e.type === "warning"
}, {
"btn-danger": e.type === "danger"
}, {
"btn-info": e.type === "info"
}, {
"btn-secondary": e.type === "secondary"
}, {
"btn-link": e.type === "link"
}, {
disabled: e.disabled
}];
}
return E(() => {
i.value = !0, m.value && d(null, !0);
}), () => n("div", {
ref: w
}, [n("div", {
class: ["farris-dropdown", "btn-group", {
dropup: e.position === "top"
}, {
dropdown: e.position === "bottom"
}, {
dropleft: e.position === "left"
}, {
dropright: e.position === "right"
}]
}, [e.splitButton && n("span", {
class: ["btn", ...D()],
style: "width:100%",
onClick: v
}, [e.title]), n("span", {
ref: s,
class: ["dropdown-toggle", {
btn: !e.nest
}, {
"dropdown-toggle-split": e.splitButton
}, ...D()],
style: "width:100%",
onClick: b,
onMouseenter: x,
onMouseleave: x
}, [e.splitButton ? "" : e.title, e.iconClass && n("span", {
class: `f-icon ${e.iconClass}`
}, null)]), i.value && n(O, {
to: "body"
}, {
default: () => [n("div", {
ref: p,
class: `dropdown-menu${m.value ? " show" : ""}`
}, [a.value.map(({
label: B,
value: I,
disabled: j,
active: o,
divide: t
}) => n(Y, {
value: I.toString(),
label: B,
disabled: j,
active: o,
divide: t,
onSelect: (f) => $(f)
}, null))])]
})])]);
}
}), ue = /* @__PURE__ */ W({
name: "FDropdownDesign",
props: z,
emits: ["select"],
setup(e, l) {
const a = u(e.model), {
show: i,
showDropMenu: m,
hoverDropdown: p,
leftButtonClick: w
} = X(e, l);
function s(d) {
l.emit("select", d);
}
const b = u(), x = V("design-item-context"), v = K(b, x);
return E(() => {
b.value.componentInstance = v;
}), l.expose(v.value), () => n("div", {
ref: b
}, [n("div", {
class: ["farris-dropdown", "btn-group", {
dropup: e.position === "top"
}, {
dropdown: e.position === "bottom"
}, {
dropleft: e.position === "left"
}, {
dropright: e.position === "right"
}],
style: {
width: e.width
}
}, [e.splitButton && n("span", {
class: ["btn", {
"dropdown-item": e.nest
}, {
"btn-lg": e.size === "large"
}, {
"btn-sm": e.size === "small"
}, {
"btn-primary": e.type === "primary"
}, {
"btn-success": e.type === "success"
}, {
"btn-warning": e.type === "warning"
}, {
"btn-danger": e.type === "danger"
}, {
"btn-info": e.type === "info"
}],
style: "width:100%",
onClick: w
}, [e.title]), n("span", {
class: ["dropdown-toggle", {
btn: !e.nest
}, {
"dropdown-item": e.nest
}, {
"dropdown-toggle-split": e.splitButton
}, {
"btn-lg": e.size === "large"
}, {
"btn-sm": e.size === "small"
}, {
"btn-primary": e.type === "primary"
}, {
"btn-success": e.type === "success"
}, {
"btn-warning": e.type === "warning"
}, {
"btn-danger": e.type === "danger"
}, {
"btn-info": e.type === "info"
}, {
"btn-secondary": e.type === "secondary"
}, {
"btn-link": e.type === "link"
}, {
disabled: e.disabled
}],
style: "width:100%",
onClick: m,
onMouseenter: p,
onMouseleave: p
}, [L(n("span", {
class: "sr-only"
}, null), [[T, e.splitButton]]), e.splitButton ? "" : e.title, L(n("span", {
class: `f-icon ${e.iconClass.toString()}`
}, null), [[T, e.iconClass]])]), n("div", {
class: `dropdown-menu${i.value ? " show" : ""}`
}, [n(Z, null, [a.value.map(({
label: d,
value: C,
disabled: $,
active: D,
divide: B
}) => n(Y, {
value: C.toString(),
label: d,
disabled: $,
active: D,
divide: B,
onSelect: (I) => s(I)
}, null))])])])]);
}
}), we = {
install(e) {
e.component(F.name, F);
},
register(e, l, a, i) {
e.dropdown = F, l.dropdown = N;
},
registerDesigner(e, l, a) {
e.dropdown = ue, l.dropdown = N;
}
};
export {
F as Dropdown,
we as default,
z as dropdownProps,
N as propsResolver
};