UNPKG

@farris/ui-vue

Version:

Farris Vue, a Farris Design based Vue3 component library.

351 lines (350 loc) 12.4 kB
import { ref as g, computed as b, defineComponent as X, watch as Y, onMounted as U, createVNode as y, Fragment as _, Teleport as B, nextTick as K, reactive as Q, createApp as Z, onUnmounted as tt, mergeProps as et } from "vue"; const ot = { /** 提示内容 */ content: { type: String, 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 lt(t, l) { const c = /* @__PURE__ */ new Map([ ["top", "bottom"], ["bottom", "top"], ["left", "right"], ["right", "left"] ]), n = /* @__PURE__ */ new Map([ ["top", "height"], ["bottom", "height"], ["left", "width"], ["right", "width"] ]); function f(e, i) { const u = c.get(i) || i; return e.replace(i, u); } function s(e, i, u, o, d) { let v = e; const a = e.split("-")[0], p = n.get(a), h = o[p] + d[p]; return Math.abs(u[a] - i[a]) < h && (v = f(e, a)), v; } return { adjustPlacement: s }; } function nt(t, l) { function n(s, e, i) { let u = !1, o = i; return (e === "left" || e === "top") && i <= s[e] && (u = !0, o = s[e] + 6), (e === "right" || e === "bottom") && i >= s[e] && (u = !0, o = s[e] - 6), { overBound: u, fixedValue: o }; } function f(s, e, i, u, o, d, v) { let a = e.tooltip.left, p = e.tooltip.top, h = e.arrow.left, w = e.arrow.top; const T = s.split("-")[0]; if (["top", "bottom"].includes(T)) { const x = n(i, "left", e.tooltip.left), k = n(i, "right", e.tooltip.left + o.width); a = x.overBound ? x.fixedValue : k.overBound ? k.fixedValue - o.width : e.tooltip.left, h = x.overBound ? o.width - (a + o.width - u.right) - v.width : k.overBound ? u.left - a : e.arrow.left; } const S = n(i, "top", e.tooltip.top), E = n(i, "bottom", e.tooltip.top + o.height); return p = S.overBound ? S.fixedValue : E.overBound ? E.fixedValue - o.height : e.tooltip.top, w = S.overBound ? e.arrow.top : E.overBound ? o.height - (p + o.height - u.top) : e.arrow.top, { arrow: { left: h, top: w }, tooltip: { left: a, top: p } }; } return { adjustPosition: f }; } function it(t, l) { function n(e, i, u, o, d) { const v = e.split("-"), a = v[0], p = v[1] || "middle", h = ["top", "bottom"].includes(a) ? p === "middle" ? (o.width - d.width) / 2 : p === "right" ? o.width - d.width - 6 : 6 : 0, w = ["left", "right"].includes(a) ? p === "middle" ? (o.height - d.height) / 2 : p === "bottom" ? o.height - d.height - 6 : 6 : 0, L = a === "left" ? o.width + d.width : 0, T = a === "top" ? o.height + d.height : 0; return { left: L + h, top: T + w, right: 0 }; } function f(e, i, u, o, d) { const v = e.split("-"), a = v[0], p = v[1] || "middle", h = (u.width - o.width) / 2, w = (u.height - o.height) / 2, L = a === "right" ? i.right : i.left, T = a === "bottom" ? i.bottom : i.top, S = a === "top" ? 0 - w - o.height - d.height : a === "bottom" ? 0 - w + d.height : 0, E = ["left", "right"].includes(a) ? p === "middle" ? (i.height - o.height) / 2 : p === "bottom" ? i.height - o.height : 0 : 0, C = a === "left" ? 0 - h - o.width - d.width : a === "right" ? 0 - h + d.width : 0, O = ["top", "bottom"].includes(a) ? p === "middle" ? (i.width - o.width) / 2 : p === "right" ? i.width - o.width : 0 : 0, x = T + S + E; return { left: L + C + O, top: x }; } function s(e, i, u, o, d) { const v = f(e, i, u, o, d); return { arrow: n(e, i, u, o, d), tooltip: v }; } return { calculate: s }; } function rt(t, l) { const c = g(t.horizontalRelative), n = g(t.verticalRelative); function f(e) { return typeof e == "string" ? document.querySelector(e) : e; } function s() { let e = document.documentElement.clientWidth, i = document.documentElement.clientHeight, u = 0, o = 0, d = 0, v = 0, a = i - u, p = e - o; return c.value && ({ left: o, right: e, x: d, width: p } = f(c.value).getBoundingClientRect()), n.value && ({ bottom: i, top: u, y: v, height: a } = f(n.value).getBoundingClientRect()), { top: u, left: o, right: e, bottom: i, height: a, width: p, x: d, y: v }; } return { getRelativeElementBound: s }; } function ct(t, l, c, n, f, s) { const e = g(t.placement), { getRelativeElementBound: i } = rt(t), { calculate: u } = it(), { adjustPlacement: o } = lt(), { adjustPosition: d } = nt(), v = b(() => e.value.split("-")[0]), a = b(() => { const p = i(); e.value = o(e.value, p, c, n, s); const h = u(e.value, c, n, f, s); return d( e.value, h, p, c, n, f, s ); }); return { tooltipPlacement: v, tooltipPosition: a }; } function st(t) { const l = g(), c = g(!1), n = b(() => ({ display: c.value ? "block" : "none" })), f = b(() => { var e; const s = (e = t.customClass) == null ? void 0 : e.split(" "); return s == null ? void 0 : s.reduce((i, u) => (i[u] = !0, i), {}); }); return { showTooltip: c, tooltipDisplayStyle: n, tooltipCustomClass: f, tooltipContainerRef: l }; } const H = /* @__PURE__ */ X({ name: "FTooltip", props: ot, emits: ["click"], setup(t, l) { const c = g(), n = g(), f = g(), s = g(), e = g(), i = g(t.placement.split("-")[0]), u = st(t), { showTooltip: o, tooltipDisplayStyle: d, tooltipCustomClass: v, tooltipContainerRef: a } = u, p = b(() => { let r = { "fv-tooltip": !0, tooltip: !0, show: !0 }; const m = `bs-tooltip-${i.value}`; return r[m] = !0, l.slots.default && (r = { ...r, ...v.value }), r; }), h = (r) => { r.stopPropagation(), r.target !== e.value && (o.value = !1); }, w = b(() => t.content && !t.contentTemplate), L = b(() => t.content), T = g("0px"), S = g("0px"), E = b(() => { const r = { left: T.value, top: S.value }; return l.slots.default, r; }), C = g(""), O = g(""), x = b(() => ({ left: C.value, top: O.value })), k = b(() => ({ "tooltip-inner": !0, "tooltip-inner-lg": s.value && s.value && s.value.scrollHeight > s.value.clientHeight })), W = b(() => { const r = {}; return t.width && Object.assign(r, { width: t.width, "max-width": "none" }), r; }), z = (r) => { if (n.value && f.value && s.value) { const { tooltipPlacement: m, tooltipPosition: P } = ct(t, l, r.getBoundingClientRect(), f.value.getBoundingClientRect(), s.value.getBoundingClientRect(), n.value.getBoundingClientRect()); T.value = `${P.value.tooltip.left + document.documentElement.scrollLeft}px`, S.value = `${P.value.tooltip.top + document.documentElement.scrollTop}px`, C.value = `${P.value.arrow.left}px`, O.value = `${P.value.arrow.top}px`, i.value = m.value; } }, A = (r) => { var P; const m = (P = c.value) == null ? void 0 : P.nextElementSibling; m && (t.overflowShown && m.scrollWidth === m.clientWidth || (r.stopPropagation(), o.value = !0, K(() => { z(m); }))); }, V = (r, m = !0) => { r.removeEventListener("mouseenter", A), r.removeEventListener("mouseleave", h), m && (r.addEventListener("mouseenter", A), r.addEventListener("mouseleave", h)); }; function D(r, m = !0) { r.removeEventListener("mouseenter", A), r.removeEventListener("mouseleave", h), m && (r.addEventListener("click", A), document.body.addEventListener("click", h)); } function N() { var m; if (!t.enable) return; const r = (m = c.value) == null ? void 0 : m.nextElementSibling; r && (t.trigger === "click" && D(r), t.trigger === "hover" && V(r)); } function q() { var m; const r = (m = c.value) == null ? void 0 : m.nextElementSibling; r && (t.trigger === "click" && D(r, !1), t.trigger === "hover" && V(r, !1)); } Y(() => t.enable, (r) => { r ? N() : q(); }), U(() => { N(), !w.value && t.contentTemplate && e.value && e.value.appendChild(t.contentTemplate), t.reference && z(t.reference); }); function $(r) { l.emit("click", r); } const G = () => y("div", { ref: f, class: p.value, style: E.value, onClick: $ }, [y("div", { ref: n, class: "arrow", style: x.value }, null), y("div", { ref: s, class: k.value, style: W.value }, [y("div", { class: "tooltip-tmpl" }, [w.value && y("div", { class: "tooltip-text", innerHTML: L.value }, null), !w.value && y("div", { class: "tooltip-text", ref: e }, null)])])]), J = () => y("div", { ref: f, class: p.value, style: E.value, onClick: $ }, [y("div", { ref: n, class: "arrow", style: x.value }, null), y("div", { ref: s, class: k.value, style: W.value }, [y("div", { class: "tooltip-tmpl" }, [y("div", { class: "tooltip-text", ref: e }, [l.slots.contentTemplate ? l.slots.contentTemplate() : t.content])])])]); return () => l.slots.default ? y(_, { ref: c }, [l.slots.default(), y(B, { to: "body" }, { default: () => [o.value && J()] })]) : G(); } }); function at(t, l) { const c = document.createElement("div"); t.customClass && (c.className = t.customClass); const n = Z({ setup() { function f() { t.clickToHide && n.unmount(); } return tt(() => { document.body.removeChild(c); }), () => y(H, et(t, { onClick: f }), null); } }); return document.body.appendChild(c), n.mount(c), n; } function F(t) { const l = Q({ ...t }); return at(l); } function ut(t, l) { let c; t.addEventListener("mouseenter", (n) => { if (l.value.enable !== !1 && !(l.value.overflowShown && t.scrollWidth === t.clientWidth) && (n.stopPropagation(), !c)) { const f = t.dataset.tooltip && JSON.parse(t.dataset.tooltip) || {}, s = Object.assign({ reference: t, contentTemplate: l.value.contentTemplate }, f); c = F(s); } }), t.addEventListener("mouseleave", (n) => { n.stopPropagation(), c && (c.unmount(), c = null); }); } let M = null; const j = /* @__PURE__ */ new WeakMap(), R = "_farris-tooltip-directive_"; function ft() { document.querySelectorAll(`.${R}`).forEach((t) => { const l = j.get(t); l && (l.unmount(), j.delete(t)); }); } function pt(t, l) { t.addEventListener("click", (c) => { if (l.value.enable === !1 || l.value.overflowShown === !0 && t.scrollWidth === t.clientWidth) return; c.stopPropagation(); let n = j.get(t); if (n) n.unmount(), j.delete(t); else { const f = t.dataset.tooltip && JSON.parse(t.dataset.tooltip) || {}, s = Object.assign({ trigger: "hover", reference: t }, f); n = F(s), j.set(t, n); } }), !M && document.body.addEventListener("click", M = (c) => { const n = c.target, f = n.closest(`.${R}`); f && j.has(f) || n.closest(".tooltip") || ft(); }, !0); } function I(t, l) { if (!l.value) t.dataset.tooltip = ""; else { const { contentTemplate: c, ...n } = l.value; t.dataset.tooltip = JSON.stringify(n); } } const dt = { mounted: (t, l, c) => { switch (t.classList.add(R), I(t, l), l.value.trigger) { case "click": { pt(t, l); break; } default: ut(t, l); } }, unMounted: (t, l, c) => { l.value.trigger === "click" && document.body.removeEventListener("click", M, !0); }, beforeUpdate: (t, l) => { I(t, l); } }; H.install = (t) => { t.component(H.name, H), t.directive("tooltip", dt); }; export { H as FTooltip, dt as FTooltipDirective, H as default, ot as tooltipProps };