UNPKG

@opentiny/vue-renderless

Version:

An enterprise-class UI component library, support both Vue.js 2 and Vue.js 3, as well as PC and mobile.

353 lines (352 loc) 14 kB
import "../chunk-G2ADBYYC.js"; import { omitText } from "@opentiny/utils"; const isArr = Array.isArray; const some = (arr, predicate) => arr.some(predicate); const filter = (arr, predicate) => arr.filter(predicate); const lower = (string) => string.toLowerCase(); const layout = (data, config, el) => { const { nodes, links } = data; const { iconSpacing, iconRadius, iconPadding, labelOffset, nameField, cols, rows } = config; const { heightStart, heightStep, nodeAnchor, posOffsetX, posOffsetY, riverColor, riverSpacing } = config; const { statusColor, statusName, endOpacity, backOpacity, nameSplit, legend, showLegend, legendPosY } = config; const riverNodes = initRiverNodes(nodes); calcRiverNodeWidth({ iconSpacing, riverNodes }); calcRiverNodeHeight({ links, riverNodes }); const heightMap = calcHeightMap({ riverNodes, links, heightStart, heightStep }); calcRiverNodePos({ cols, el, riverNodes, rows, posOffsetX, posOffsetY }); const nameInfo = calcRiverPath({ links, nodes, nameField, nameSplit }); const { dataLinkRiverLinkMap, riverLinks } = initRiverLinks(links); calcRiverLinkPos({ dataLinkRiverLinkMap, links, riverNodes, heightMap, nodeAnchor, riverSpacing }); calcRiverLinkPath(riverLinks); const riverIcons = calcRiverIcons({ iconRadius, iconSpacing, riverNodes }); riverNodes.forEach((riverNode) => riverNode.lp = [riverNode.x, riverNode.y - labelOffset, riverNode.width]); riverIcons.forEach((riverIcon) => { riverIcon.lp = [ riverIcon.x - iconSpacing / 2 + iconPadding, riverIcon.y + labelOffset, iconSpacing - iconPadding * 2 ]; }); calcGradient({ riverNodes, riverLinks, riverColor, statusColor, endOpacity, backOpacity }); const leges = showLegend ? calcLegend({ statusColor, statusName, cols, rows, legend, posOffsetX, el, iconPadding, legendPosY }) : []; return riverNodes.concat(riverLinks).concat(riverIcons).concat(nameInfo).concat(leges); }; const calcHeightMap = ({ riverNodes, links, heightStart, heightStep }) => { const set = /* @__PURE__ */ new Set(); riverNodes.forEach((riverNode) => set.add(riverNode.height)); links.forEach((dataLink) => set.add(dataLink.value)); const arr = [...set].sort(); const map = /* @__PURE__ */ new Map(); const start = heightStart; const step = heightStep; arr.forEach((v, i) => map.set(v, start + step * i)); return map; }; const initRiverNodes = (nodes) => nodes.map((dataNode) => { return { type: "node", x: 0, y: 0, width: 0, height: 0, level: 0, data: dataNode }; }); const calcRiverNodeWidth = ({ iconSpacing, riverNodes }) => riverNodes.forEach((riverNode) => { const { data: dataNode } = riverNode; const { nodes: icons } = dataNode; riverNode.width = isArr(icons) && icons.length > 1 ? iconSpacing * icons.length : iconSpacing; }); const calcRiverNodeHeight = ({ links, riverNodes }) => { riverNodes.forEach((riverNode) => { let heightRatio = 0; const { data: dataNode } = riverNode; const prdc = (type) => (dataLink) => dataLink[type] === dataNode.name; const targetPrdc = prdc("target"); const sourcePrdc = prdc("source"); const accumulator = (dataLink) => heightRatio += dataLink.value; if (some(links, targetPrdc)) { filter(links, targetPrdc).forEach(accumulator); } else if (some(links, sourcePrdc)) { filter(links, sourcePrdc).forEach(accumulator); } if (heightRatio > 0) { riverNode.height = heightRatio; } }); }; const calcRiverNodePos = ({ cols, el, riverNodes, rows, posOffsetX, posOffsetY }) => { if (cols && rows) { calcRiverNodePosUser({ cols, el, riverNodes, rows, posOffsetX, posOffsetY }); } }; const calcRiverPath = ({ links, nodes, nameField = "$$name", nameSplit = ";" }) => { const names = []; const iconNames = []; nodes.forEach((dataNode) => { names.push(dataNode[nameField] = lower(`n${dataNode.name}`)); const { nodes: icons } = dataNode; icons.forEach((icon, i) => iconNames.push(icon[nameField] = `${dataNode[nameField]}/${i}`)); }); links.forEach((dataLink) => names.push(dataLink[nameField] = lower(`l${dataLink.source}t${dataLink.target}`))); const nodesCopy = JSON.parse(JSON.stringify(nodes)); links.forEach(({ source, target }) => { let sourceDataNode, targetDataNode; nodesCopy.forEach((dataNode) => { if (dataNode.name === source) sourceDataNode = dataNode; if (dataNode.name === target) targetDataNode = dataNode; }); if (sourceDataNode._children) { sourceDataNode._children.push(targetDataNode); } else { sourceDataNode._children = [targetDataNode]; } if (targetDataNode._parent) { targetDataNode._parent.push(sourceDataNode); } else { targetDataNode._parent = [sourceDataNode]; } }); let parent = nodesCopy[0]; while (parent._parent) parent = parent._parent; const paths = []; const travel = (node, str = "") => { if (str) str += nameSplit; str += node[nameField]; if (node._children) { node._children.forEach((child) => { const dataLink = links.find(({ source, target }) => source === node.name && target === child.name); travel(child, str + nameSplit + dataLink[nameField]); }); } else { paths.push(str); } }; travel(parent); return { type: "name", names, iconNames, paths, nameField, nameSplit }; }; const calcRiverNodePosUser = ({ cols, el, riverNodes, rows, posOffsetX, posOffsetY }) => { const { clientWidth, clientHeight } = el; const areaWidth = clientWidth / cols; const areaHeight = clientHeight / rows; riverNodes.forEach((riverNode) => { const { data: dataNode } = riverNode; const { col, row } = dataNode; const areaPosX = areaWidth * col; const areaPosY = areaHeight * row; riverNode.x = areaPosX + posOffsetX; riverNode.y = areaPosY + posOffsetY; }); }; const initRiverLinks = (links) => { const dataLinkRiverLinkMap = /* @__PURE__ */ new WeakMap(); const riverLinks = links.map((dataLink) => { const value = { type: "link", lt: [0, 0], lb: [0, 0], rt: [0, 0], rb: [0, 0], data: dataLink }; dataLinkRiverLinkMap.set(dataLink, value); return value; }); return { dataLinkRiverLinkMap, riverLinks }; }; const calcRiverLinkPos1 = ({ links, riverNodes, heightMap, nodeAnchor }) => { riverNodes.forEach((riverNode) => { const { data: dataNode } = riverNode; const prdc = (type) => (dataLink) => dataLink[type] === dataNode.name; const targetPrdc = prdc("target"); const sourcePrdc = prdc("source"); let offset1 = 0; let offset2 = 0; if (some(links, targetPrdc)) { filter(links, targetPrdc).forEach((dataLink) => { offset1 += heightMap.get(dataLink.value); }); } if (some(links, sourcePrdc)) { filter(links, sourcePrdc).forEach((dataLink) => { offset2 += heightMap.get(dataLink.value); }); } riverNode.height = offset1 > offset2 ? offset1 : offset2; if (nodeAnchor === "left-middle") { riverNode.y = riverNode.y - riverNode.height / 2; } }); }; const adjustRiverPos = ({ riverNodes, nodeAnchor, riverSpacing }) => { if (riverSpacing > 0) { let posx = /* @__PURE__ */ new Set(); riverNodes.forEach((riverNode) => posx.add(riverNode.x)); posx = [...posx].sort(); posx.forEach((x) => { const group = riverNodes.filter((riverNode) => riverNode.x === x); if (group.length > 1) { group.sort((riverNode1, riverNode2) => riverNode1.y - riverNode2.y); for (let i = 0; i < group.length - 1; i++) { const riverNode0 = group[i]; const riverNode1 = group[i + 1]; const nodePart = nodeAnchor === "left-top" ? riverNode0.height : (riverNode0.height + riverNode1.height) / 2; riverNode1.y = riverNode0.y + nodePart + (riverNode1.data.row - riverNode0.data.row) * riverSpacing; } } }); } }; const calcRiverLinkPos2 = ({ dataLinkRiverLinkMap, links, riverNodes, heightMap }) => { riverNodes.forEach((riverNode) => { const { data: dataNode, x, width } = riverNode; const prdc = (type) => (dataLink) => dataLink[type] === dataNode.name; const targetPrdc = prdc("target"); const sourcePrdc = prdc("source"); const { y } = riverNode; let offset1 = 0; let offset2 = 0; if (some(links, targetPrdc)) { filter(links, targetPrdc).forEach((dataLink) => { const riverLink = dataLinkRiverLinkMap.get(dataLink); riverLink.rt[0] = x; riverLink.rt[1] = y + offset1; offset1 += heightMap.get(dataLink.value); riverLink.rb[0] = x; riverLink.rb[1] = y + offset1; }); } if (some(links, sourcePrdc)) { filter(links, sourcePrdc).forEach((dataLink) => { const riverLink = dataLinkRiverLinkMap.get(dataLink); riverLink.lt[0] = x + width; riverLink.lt[1] = y + offset2; offset2 += heightMap.get(dataLink.value); riverLink.lb[0] = x + width; riverLink.lb[1] = y + offset2; }); } }); }; const calcRiverLinkPos = ({ dataLinkRiverLinkMap, links, riverNodes, heightMap, nodeAnchor, riverSpacing }) => { calcRiverLinkPos1({ links, riverNodes, heightMap, nodeAnchor }); adjustRiverPos({ riverNodes, nodeAnchor, riverSpacing }); calcRiverLinkPos2({ dataLinkRiverLinkMap, links, riverNodes, heightMap }); }; const calcRiverLinkPath = (riverLinks) => { riverLinks.forEach((riverLink) => { riverLink.p = []; }); }; const parse = (hexStr) => parseInt(hexStr, 16); const hexToRgba = (hexStr, opcity = 1) => { const twice = (str) => str + str; if (hexStr.length === 7) { return `rgba(${parse(hexStr.slice(1, 3))},${parse(hexStr.slice(3, 5))},${parse(hexStr.slice(5, 7))},${opcity})`; } else if (hexStr.length === 4) { const r = parse(twice(hexStr.slice(1, 2))); const g = parse(twice(hexStr.slice(2, 3))); const b = parse(twice(hexStr.slice(3, 4))); return `rgba(${r},${g},${b},${opcity})`; } }; const calcGradient = ({ riverNodes, riverLinks, riverColor, statusColor, endOpacity, backOpacity }) => { riverNodes.forEach((riverNode) => { const { data: dataNode } = riverNode; const { nodes: icons } = dataNode; const g = []; if (!icons || !icons.length) { const endColor = hexToRgba(riverColor, endOpacity); g.push([0, 1]); g.push([endColor, endColor]); } else { const seg = 1 / (icons.length + 1); const segs = []; const colors = []; icons.forEach((icon, i) => { const { skip } = icon; const color = statusColor[String(icon.status)]; if (i === 0) { segs.push(0); colors.push(hexToRgba(color, endOpacity)); } !skip && segs.push(seg * (i + 1)); !skip && colors.push(hexToRgba(color, backOpacity)); if (i === icons.length - 1) { segs.push(1); colors.push(hexToRgba(color, endOpacity)); } }); g.push(segs); g.push(colors); } riverNode.g = g; }); riverLinks.forEach((riverLink) => { const { data: dataLink } = riverLink; const { source, target } = dataLink; const sourceRiverNode = riverNodes.find((riverNode) => riverNode.data.name === source); const targetRiverNode = riverNodes.find((riverNode) => riverNode.data.name === target); const last = (arr) => arr[arr.length - 1]; const first = (arr) => arr[0]; riverLink.g = [ [0, 1], [last(sourceRiverNode.g[1]), first(targetRiverNode.g[1])] ]; }); }; const calcLegend = ({ statusColor, statusName, cols, rows, legend = {}, posOffsetX, el, iconPadding, legendPosY }) => { const { dotRadius = 8, itemWidth = 80, itemHeight = 30, col = 0, row = rows - 1, offsetY = 100 } = legend; const { clientWidth, clientHeight } = el; const areaWidth = clientWidth / cols; const areaHeight = clientHeight / rows; const posx = col * areaWidth + posOffsetX; const posy = typeof legendPosY === "number" ? legendPosY : (row + 0.5) * areaHeight - itemHeight / 2 + offsetY; const legends = []; Object.keys(statusColor).forEach((statusKey, i) => { const cx = posx + itemWidth * i + dotRadius; const cy = posy; const color = statusColor[statusKey]; const x = cx + dotRadius + iconPadding; const y = posy; const t = statusName[statusKey]; const tw = itemWidth - 2 * (dotRadius + iconPadding); legends.push({ type: "lege", cx, cy, radius: dotRadius, color, x, y, t, tw }); }); return legends; }; const calcRiverIcons = ({ iconRadius, iconSpacing, riverNodes }) => { const riverIcons = []; riverNodes.forEach((riverNode) => { const { x, y, height, data: dataNode } = riverNode; const { nodes: icons } = dataNode; const iconPosY = y + height / 2; icons.forEach((icon, i) => { const iconPosX = (i + 0.5) * iconSpacing + x; riverIcons.push({ type: "icon", x: iconPosX, y: iconPosY, radius: iconRadius, data: icon }); }); }); return riverIcons; }; const bpath = ({ lt, lb, rt, rb }) => { const w = (rt[0] - lt[0]) * 0.42; const tune = 0.1; const [offsetX, offsetY] = lb; const _lb = [0 - tune, 0]; const _lt = [lt[0] - offsetX - tune, lt[1] - offsetY]; const _rt = [rt[0] - offsetX + tune, rt[1] - offsetY]; const _rb = [rb[0] - offsetX + tune, rb[1] - offsetY]; let path = `M${_lb[0]},${_lb[1]} `; path += `C${_lb[0] + w},${_lb[1]} ${_rb[0] - w},${_rb[1]} ${_rb[0]},${_rb[1]} `; path += `L${_rt[0]},${_rt[1]} `; path += `C${_rt[0] - w},${_rt[1]} ${_lt[0] + w},${_lt[1]} ${_lt[0]},${_lt[1]} `; path += `L${_lb[0]},${_lb[1]} z`; return path; }; const bc = (p0, p1, p2, p3) => (t) => { const ip = (t2, p12, p22) => [(1 - t2) * p12[0] + t2 * p22[0], (1 - t2) * p12[1] + t2 * p22[1]]; const tmp0 = ip(t, p0, p1); const tmp1 = ip(t, p1, p2); const tmp2 = ip(t, p2, p3); const tmp3 = ip(t, tmp0, tmp1); const tmp4 = ip(t, tmp1, tmp2); return ip(t, tmp3, tmp4); }; const txt = omitText; export { bc, bpath, hexToRgba, layout, txt };