diff --git a/modules/rflows/components/folk-flow-river.ts b/modules/rflows/components/folk-flow-river.ts index 91d0e15..e049b69 100644 --- a/modules/rflows/components/folk-flow-river.ts +++ b/modules/rflows/components/folk-flow-river.ts @@ -373,31 +373,93 @@ function renderWaterfall(wf: WaterfallLayout): string { const topCx = isInflow ? wf.xSource : wf.x; const bottomCx = isInflow ? wf.x : wf.xSource; - const cpFrac1 = isInflow ? 0.55 : 0.2; - const cpFrac2 = isInflow ? 0.75 : 0.45; - const cpY1 = wf.yStart + height * cpFrac1; - const cpY2 = wf.yStart + height * cpFrac2; - const tl = topCx - topWidth / 2; const tr = topCx + topWidth / 2; const bl = bottomCx - bottomWidth / 2; const br = bottomCx + bottomWidth / 2; - const shapePath = `M ${tl} ${wf.yStart} C ${tl} ${cpY1}, ${bl} ${cpY2}, ${bl} ${wf.yEnd} L ${br} ${wf.yEnd} C ${br} ${cpY2}, ${tr} ${cpY1}, ${tr} ${wf.yStart} Z`; + // L-shaped paths: vertical drop + horizontal merge (inflow) + // or horizontal departure + vertical drop (outflow) + const hDisplacement = Math.abs(topCx - bottomCx); + const maxR = Math.min(height * 0.2, hDisplacement > 3 ? hDisplacement * 0.4 : height * 0.15, 15); + const r = Math.max(3, maxR); + + let shapePath: string; + let spinePath: string; + let leftEdge: string; + let rightEdge: string; + + if (hDisplacement < 3) { + // Source directly above river — simple tapered rectangle + shapePath = `M ${tl} ${wf.yStart} L ${bl} ${wf.yEnd} L ${br} ${wf.yEnd} L ${tr} ${wf.yStart} Z`; + spinePath = `M ${topCx} ${wf.yStart} L ${bottomCx} ${wf.yEnd}`; + leftEdge = `M ${tl} ${wf.yStart} L ${bl} ${wf.yEnd}`; + rightEdge = `M ${tr} ${wf.yStart} L ${br} ${wf.yEnd}`; + } else if (isInflow) { + // Inflow L-shape: vertical drop → rounded corner → horizontal merge into river + const hDir = Math.sign(bl - tl); // direction of horizontal leg + + shapePath = [ + `M ${tl} ${wf.yStart}`, + `L ${tl} ${wf.yEnd - r}`, + `Q ${tl} ${wf.yEnd}, ${tl + hDir * r} ${wf.yEnd}`, + `L ${bl} ${wf.yEnd}`, + `L ${br} ${wf.yEnd}`, + `L ${tr + hDir * r} ${wf.yEnd}`, + `Q ${tr} ${wf.yEnd}, ${tr} ${wf.yEnd - r}`, + `L ${tr} ${wf.yStart}`, + `Z`, + ].join(" "); + + spinePath = [ + `M ${topCx} ${wf.yStart}`, + `L ${topCx} ${wf.yEnd - r}`, + `Q ${topCx} ${wf.yEnd}, ${topCx + hDir * r} ${wf.yEnd}`, + `L ${bottomCx} ${wf.yEnd}`, + ].join(" "); + + leftEdge = `M ${tl} ${wf.yStart} L ${tl} ${wf.yEnd - r} Q ${tl} ${wf.yEnd}, ${tl + hDir * r} ${wf.yEnd} L ${bl} ${wf.yEnd}`; + rightEdge = `M ${tr} ${wf.yStart} L ${tr} ${wf.yEnd - r} Q ${tr} ${wf.yEnd}, ${tr + hDir * r} ${wf.yEnd} L ${br} ${wf.yEnd}`; + } else { + // Outflow inverted-L: horizontal departure from river → rounded corner → vertical drop + const hDir = Math.sign(tl - bl); // direction from destination back toward river + + shapePath = [ + `M ${tl} ${wf.yStart}`, + `L ${bl + hDir * r} ${wf.yStart}`, + `Q ${bl} ${wf.yStart}, ${bl} ${wf.yStart + r}`, + `L ${bl} ${wf.yEnd}`, + `L ${br} ${wf.yEnd}`, + `L ${br} ${wf.yStart + r}`, + `Q ${br} ${wf.yStart}, ${br + hDir * r} ${wf.yStart}`, + `L ${tr} ${wf.yStart}`, + `Z`, + ].join(" "); + + spinePath = [ + `M ${topCx} ${wf.yStart}`, + `L ${bottomCx + Math.sign(topCx - bottomCx) * r} ${wf.yStart}`, + `Q ${bottomCx} ${wf.yStart}, ${bottomCx} ${wf.yStart + r}`, + `L ${bottomCx} ${wf.yEnd}`, + ].join(" "); + + leftEdge = `M ${tl} ${wf.yStart} L ${bl + hDir * r} ${wf.yStart} Q ${bl} ${wf.yStart}, ${bl} ${wf.yStart + r} L ${bl} ${wf.yEnd}`; + rightEdge = `M ${tr} ${wf.yStart} L ${br + hDir * r} ${wf.yStart} Q ${br} ${wf.yStart}, ${br} ${wf.yStart + r} L ${br} ${wf.yEnd}`; + } + const clipId = `sankey-clip-${wf.id}`; const gradId = `sankey-grad-${wf.id}`; const glowId = `sankey-glow-${wf.id}`; const pathMinX = Math.min(tl, bl) - 5; const pathMaxW = Math.max(topWidth, bottomWidth) + 10; - const spinePath = `M ${topCx} ${wf.yStart} C ${topCx} ${cpY1}, ${bottomCx} ${cpY2}, ${bottomCx} ${wf.yEnd}`; const entryCx = isInflow ? bottomCx : topCx; const entryY = isInflow ? wf.yEnd : wf.yStart; const entryWidth = isInflow ? bottomWidth : topWidth; const exitCx = isInflow ? topCx : bottomCx; const exitY = isInflow ? wf.yStart : wf.yEnd; - const labelX = (topCx + bottomCx) / 2; + const labelX = isInflow ? topCx : bottomCx; const labelY = wf.yStart + height * 0.45; const flowLabel = wf.flowAmount >= 1000 ? `$${(wf.flowAmount / 1000).toFixed(1)}k` : `$${Math.floor(wf.flowAmount)}`; @@ -422,8 +484,8 @@ function renderWaterfall(wf: WaterfallLayout): string { ${[0, 1, 2, 3, 4].map((i) => ``).join("")} - - + + @@ -436,14 +498,13 @@ function renderBranch(b: BranchLayout): string { const dy = b.y2 - b.y1; const halfW = b.width / 2; - // Pipe exits horizontally from lip, then curves down to target - const exitX = b.side === "left" ? b.x1 - 40 : b.x1 + 40; - const cp1x = exitX; - const cp1y = b.y1; - const cp2x = b.x2; - const cp2y = b.y1 + (b.y2 - b.y1) * 0.3; + // Pipe exits horizontally from lip, then turns down to target (L-shape) + const dirX = Math.sign(b.x2 - b.x1); + const r = Math.min(12, Math.abs(dy) * 0.2, Math.abs(b.x2 - b.x1) * 0.3); - const spinePath = `M ${b.x1} ${b.y1} L ${exitX} ${b.y1} C ${cp1x} ${b.y1 + Math.abs(dy) * 0.4}, ${cp2x} ${cp2y}, ${b.x2} ${b.y2}`; + const spinePath = r > 2 + ? `M ${b.x1} ${b.y1} L ${b.x2 - dirX * r} ${b.y1} Q ${b.x2} ${b.y1}, ${b.x2} ${b.y1 + r} L ${b.x2} ${b.y2}` + : `M ${b.x1} ${b.y1} L ${b.x2} ${b.y1} L ${b.x2} ${b.y2}`; // Outer wall (dark) const outerStroke = ``; diff --git a/modules/rwallet/components/folk-wallet-viewer.ts b/modules/rwallet/components/folk-wallet-viewer.ts index d7258f3..8669a0e 100644 --- a/modules/rwallet/components/folk-wallet-viewer.ts +++ b/modules/rwallet/components/folk-wallet-viewer.ts @@ -242,13 +242,9 @@ class FolkWalletViewer extends HTMLElement { this.render(); this.loadYieldData(); } else { - // Auto-load address or demo - if (!this.address) { - if (this.passKeyEOA) { - this.address = this.passKeyEOA; - } else { - this.address = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"; - } + // Auto-load address from passkey or linked wallet + if (!this.address && this.passKeyEOA) { + this.address = this.passKeyEOA; } this.render();