UNPKG

@farris/ui-vue

Version:

Farris Vue, a Farris Design based Vue3 component library.

388 lines (387 loc) 13.3 kB
import { ref as y, computed as b, defineComponent as tt, watch as et, onMounted as ot, createVNode as g, Fragment as nt, Teleport as lt, nextTick as R, mergeProps as G, reactive as it, createApp as rt, onUnmounted as ct } from "vue"; const st = { /** 提示内容 */ content: { type: Object, default: "" }, /** 模板提示内容 */ contentTemplate: { type: Object }, /** 提示框宽度,例如'200px' */ width: { type: String }, /** 提示框自定义样式,应用与提示框最外层 */ customClass: { type: String }, /** 提示方向 */ placement: { type: String, default: "top" }, /** 触发提示的时机 */ trigger: { type: String, default: "hover" }, // 此变量在指令中不对外 reference: { type: Object, require: !0 }, horizontalRelative: { type: String, default: "" }, verticalRelative: { type: String, default: "" }, clickToHide: { type: Boolean, default: !0 }, // 是否启用 enable: { type: Boolean, default: !0 }, // 是否根据溢出自动显示提示 overflowShown: { type: Boolean, default: !1 } }; function at(t, o) { const i = /* @__PURE__ */ new Map([ ["top", "bottom"], ["bottom", "top"], ["left", "right"], ["right", "left"] ]), c = /* @__PURE__ */ new Map([ ["top", "height"], ["bottom", "height"], ["left", "width"], ["right", "width"] ]); function d(e, r) { const u = i.get(r) || r; return e.replace(r, u); } function s(e, r, u, l, v) { let h = e; const a = e.split("-")[0], f = c.get(a), m = l[f] + v[f]; return Math.abs(u[a] - r[a]) < m && (h = d(e, a)), h; } return { adjustPlacement: s }; } function ut(t, o) { function c(s, e, r) { let u = !1, l = r; return (e === "left" || e === "top") && r <= s[e] && (u = !0, l = s[e] + 6), (e === "right" || e === "bottom") && r >= s[e] && (u = !0, l = s[e] - 6), { overBound: u, fixedValue: l }; } function d(s, e, r, u, l, v, h) { let a = e.tooltip.left, f = e.tooltip.top, m = e.arrow.left, w = e.arrow.top; const S = s.split("-")[0]; if (["top", "bottom"].includes(S)) { const E = c(r, "left", e.tooltip.left), j = c(r, "right", e.tooltip.left + l.width); a = E.overBound ? E.fixedValue : j.overBound ? j.fixedValue - l.width : e.tooltip.left, m = E.overBound ? l.width - (a + l.width - u.right) - h.width : j.overBound ? u.left - a : e.arrow.left; } const x = c(r, "top", e.tooltip.top), k = c(r, "bottom", e.tooltip.top + l.height); return f = x.overBound ? x.fixedValue : k.overBound ? k.fixedValue - l.height : e.tooltip.top, w = x.overBound ? e.arrow.top : k.overBound ? l.height - (f + l.height - u.top) : e.arrow.top, { arrow: { left: m, top: w }, tooltip: { left: a, top: f } }; } return { adjustPosition: d }; } function ft(t, o) { function c(e, r, u, l, v) { const h = e.split("-"), a = h[0], f = h[1] || "middle", m = ["top", "bottom"].includes(a) ? f === "middle" ? (l.width - v.width) / 2 : f === "right" ? l.width - v.width - 6 : 6 : 0, w = ["left", "right"].includes(a) ? f === "middle" ? (l.height - v.height) / 2 : f === "bottom" ? l.height - v.height - 6 : 6 : 0, P = a === "left" ? l.width + v.width : 0, S = a === "top" ? l.height + v.height : 0; return { left: P + m, top: S + w, right: 0 }; } function d(e, r, u, l, v) { const h = e.split("-"), a = h[0], f = h[1] || "middle", m = (u.width - l.width) / 2, w = (u.height - l.height) / 2, P = a === "right" ? r.right : r.left, S = a === "bottom" ? r.bottom : r.top, x = a === "top" ? 0 - w - l.height - v.height : a === "bottom" ? 0 - w + v.height : 0, k = ["left", "right"].includes(a) ? f === "middle" ? (r.height - l.height) / 2 : f === "bottom" ? r.height - l.height : 0 : 0, C = a === "left" ? 0 - m - l.width - v.width : a === "right" ? 0 - m + v.width : 0, O = ["top", "bottom"].includes(a) ? f === "middle" ? (r.width - l.width) / 2 : f === "right" ? r.width - l.width : 0 : 0, E = S + x + k; return { left: P + C + O, top: E }; } function s(e, r, u, l, v) { const h = d(e, r, u, l, v); return { arrow: c(e, r, u, l, v), tooltip: h }; } return { calculate: s }; } function dt(t, o) { const i = y(t.horizontalRelative), c = y(t.verticalRelative); function d(e) { return typeof e == "string" ? document.querySelector(e) : e; } function s() { let e = document.documentElement.clientWidth, r = document.documentElement.clientHeight, u = 0, l = 0, v = 0, h = 0, a = r - u, f = e - l; return i.value && ({ left: l, right: e, x: v, width: f } = d(i.value).getBoundingClientRect()), c.value && ({ bottom: r, top: u, y: h, height: a } = d(c.value).getBoundingClientRect()), { top: u, left: l, right: e, bottom: r, height: a, width: f, x: v, y: h }; } return { getRelativeElementBound: s }; } function vt(t, o, i, c, d, s) { const e = y(t.placement), { getRelativeElementBound: r } = dt(t), { calculate: u } = ft(), { adjustPlacement: l } = at(), { adjustPosition: v } = ut(), h = b(() => e.value.split("-")[0]), a = b(() => { const f = r(); e.value = l(e.value, f, i, c, s); const m = u(e.value, i, c, d, s); return v( e.value, m, f, i, c, d, s ); }); return { tooltipPlacement: h, tooltipPosition: a }; } function pt(t) { const o = y(), i = y(!1), c = b(() => ({ display: i.value ? "block" : "none" })), d = b(() => { var e; const s = (e = t.customClass) == null ? void 0 : e.split(" "); return s == null ? void 0 : s.reduce((r, u) => (r[u] = !0, r), {}); }); return { showTooltip: i, tooltipDisplayStyle: c, tooltipCustomClass: d, tooltipContainerRef: o }; } const H = /* @__PURE__ */ tt({ name: "FTooltip", props: st, emits: ["click"], setup(t, o) { const i = y(), c = y(), d = y(), s = y(), e = y(), r = y(t.placement.split("-")[0]), u = pt(t), { showTooltip: l, tooltipCustomClass: v } = u, h = y(!1), a = b(() => { let n = { "fv-tooltip": !0, tooltip: !0, show: !0 }; const p = `bs-tooltip-${r.value}`; return n[p] = !0, o.slots.default && (n = { ...n, ...v.value }), n; }), f = (n) => { n.target !== e.value && (n.stopPropagation(), document.body.removeEventListener("click", f), l.value = !1); }, m = b(() => t.content && !t.contentTemplate), w = b(() => t.content), P = y("0px"), S = y("0px"), x = b(() => { const n = { left: P.value, top: S.value }; return o.slots.default, n; }), k = y(""), C = y(""), O = b(() => ({ left: k.value, top: C.value })), E = b(() => ({ "tooltip-inner": !0, "tooltip-inner-lg": s.value && s.value && s.value.scrollHeight > s.value.clientHeight })), j = b(() => { const n = {}; return t.width && Object.assign(n, { width: t.width, "max-width": "none" }), n; }), V = (n) => { c.value && d.value && s.value && (E.value, R(() => { const { tooltipPlacement: p, tooltipPosition: T } = vt(t, o, n.getBoundingClientRect(), d.value.getBoundingClientRect(), s.value.getBoundingClientRect(), c.value.getBoundingClientRect()); P.value = `${T.value.tooltip.left + document.documentElement.scrollLeft}px`, S.value = `${T.value.tooltip.top + document.documentElement.scrollTop}px`, k.value = `${T.value.arrow.left}px`, C.value = `${T.value.arrow.top}px`, r.value = p.value; })); }, A = (n) => { var T; const p = (T = i.value) == null ? void 0 : T.nextElementSibling; p && (t.overflowShown && p.scrollWidth === p.clientWidth || (n.stopPropagation(), l.value = !0, R(() => { V(p); }), t.trigger === "click" && document.body.addEventListener("click", f))); }, D = (n, p = !0) => { n.removeEventListener("mouseenter", A), n.removeEventListener("mouseleave", f), p && (n.addEventListener("mouseenter", A), n.addEventListener("mouseleave", f)); }; function N(n, p = !0) { n.removeEventListener("mouseenter", A), n.removeEventListener("mouseleave", f), p && n.addEventListener("click", A); } function M() { var p; if (!t.enable) return; const n = (p = i.value) == null ? void 0 : p.nextElementSibling; n && (t.trigger === "click" && N(n), t.trigger === "hover" && D(n)); } function Y() { var p; const n = (p = i.value) == null ? void 0 : p.nextElementSibling; n && (t.trigger === "click" && N(n, !1), t.trigger === "hover" && D(n, !1)); } et(() => t.enable, (n) => { n ? M() : Y(); }); function _() { i.value && i.value.nodeName === "#text" && !i.value.nextElementSibling && (h.value = !0, R(() => { M(); })); } ot(() => { _(), M(), !m.value && t.contentTemplate && e.value && e.value.appendChild(t.contentTemplate), t.reference && V(t.reference); }); function F(n) { o.emit("click", n); } const B = () => g("div", { ref: d, class: a.value, style: x.value, onClick: F }, [g("div", { ref: c, class: "arrow", style: O.value }, null), g("div", { ref: s, class: E.value, style: j.value }, [g("div", { class: "tooltip-tmpl" }, [m.value && g("div", { class: "tooltip-text", innerHTML: w.value }, null), !m.value && g("div", { class: "tooltip-text", ref: e }, null)])])]); function K() { const n = { class: "tooltip-text", ref: e }; if (o.slots.contentTemplate) return g("div", n, [o.slots.contentTemplate()]); if (t.content) { let p = t.content; return typeof t.content == "function" && (p = t.content()), g("div", G(n, { innerHTML: p }), null); } return g("div", n, null); } const Q = () => g("div", { ref: d, class: a.value, style: x.value, onClick: F }, [g("div", { ref: c, class: "arrow", style: O.value }, null), g("div", { ref: s, class: E.value, style: j.value }, [g("div", { class: "tooltip-tmpl" }, [K()])])]); function Z() { var n, p, T, I; return h.value ? g("span", null, [(p = (n = o.slots).default) == null ? void 0 : p.call(n)]) : (I = (T = o.slots).default) == null ? void 0 : I.call(T); } return () => o.slots.default ? g(nt, { ref: i }, [Z(), g(lt, { to: "body" }, { default: () => [l.value && Q()] })]) : B(); } }); function ht(t, o) { const i = document.createElement("div"); t.customClass && (i.className = t.customClass); const c = rt({ setup() { function d() { t.clickToHide && c.unmount(); } return ct(() => { document.body.removeChild(i); }), () => g(H, G(t, { onClick: d }), null); } }); return document.body.appendChild(i), c.mount(i), c; } function J(t) { const o = it({ ...t }); return ht(o); } const L = /* @__PURE__ */ new WeakMap(); function U(t) { if (!t) return; const o = L.get(t); o && (o.unmount(), L.delete(t)); } function mt(t, o) { let i; t.addEventListener("mouseenter", (c) => { if (o.value.enable !== !1 && !(o.value.overflowShown && t.scrollWidth === t.clientWidth) && (c.stopPropagation(), !i)) { const d = t.dataset.tooltip && JSON.parse(t.dataset.tooltip) || {}, s = Object.assign({ reference: t, contentTemplate: o.value.contentTemplate }, d); i = J(s), L.set(t, i); } }), t.addEventListener("mouseleave", (c) => { c.stopPropagation(), i && (L.delete(t), i.unmount(), i = null); }); } let X = null; const W = "_farris-tooltip-directive_"; function z() { document.querySelectorAll(`.${W}`).forEach((t) => { U(t); }); } function gt(t, o) { t.addEventListener("click", (i) => { if (o.value.enable === !1 || o.value.overflowShown === !0 && t.scrollWidth === t.clientWidth) return; i.stopPropagation(); let c = L.get(t); if (c) c.unmount(), L.delete(t); else { z(); const d = t.dataset.tooltip && JSON.parse(t.dataset.tooltip) || {}, s = Object.assign({ trigger: "hover", reference: t }, d); c = J(s), L.set(t, c); } }); } function $(t, o) { if (!o.value) t.dataset.tooltip = ""; else { const { contentTemplate: i, ...c } = o.value; t.dataset.tooltip = JSON.stringify(c); } } function q(t, o) { o.value.trigger === "click" || U(t); } const yt = { mounted: (t, o, i) => { switch (t.classList.add(W), $(t, o), o.value.trigger) { case "click": { gt(t, o); break; } default: mt(t, o); } }, beforeUnmount: (t, o, i) => { q(t, o); }, unmounted: (t, o, i) => { q(t, o); }, beforeUpdate: (t, o) => { $(t, o); } }; window.clearAllTooltips = z; document.body.removeEventListener("click", X, !0); document.body.addEventListener("click", X = (t) => { const o = t.target, i = o.closest(`.${W}`); i && L.has(i) || o.closest(".tooltip") || z(); }, !0); H.install = (t) => { t.component(H.name, H), t.directive("tooltip", yt); }; export { H as FTooltip, yt as FTooltipDirective, H as default, st as tooltipProps };