diff --git a/src/components/CursorOverlay.tsx b/src/components/CursorOverlay.tsx
index a99bac9..ec82bf0 100644
--- a/src/components/CursorOverlay.tsx
+++ b/src/components/CursorOverlay.tsx
@@ -1,5 +1,6 @@
"use client";
+import { useEffect, useState } from "react";
import { truncateAddress } from "@stellar-split/sdk";
interface RemoteCursor {
@@ -7,6 +8,7 @@ interface RemoteCursor {
field: string;
color: string;
timestamp: number;
+ displayName?: string;
}
interface Props {
@@ -14,6 +16,27 @@ interface Props {
fieldName: string;
}
+const LABEL_FADE_MS = 3000;
+
+function CursorLabel({ cursor }: { cursor: RemoteCursor }) {
+ const [faded, setFaded] = useState(false);
+
+ useEffect(() => {
+ setFaded(false);
+ const timer = setTimeout(() => setFaded(true), LABEL_FADE_MS);
+ return () => clearTimeout(timer);
+ }, [cursor.timestamp]);
+
+ return (
+
+ {cursor.displayName ?? truncateAddress(cursor.address)}
+
+ );
+}
+
export default function CursorOverlay({ cursors, fieldName }: Props) {
const active = cursors.filter((c) => c.field === fieldName);
if (active.length === 0) return null;
@@ -35,7 +58,7 @@ export default function CursorOverlay({ cursors, fieldName }: Props) {
className="w-1.5 h-1.5 rounded-full inline-block"
style={{ backgroundColor: cursor.color }}
/>
- {truncateAddress(cursor.address)}
+
))}
diff --git a/src/components/FlowDiagram.tsx b/src/components/FlowDiagram.tsx
index 1a936d4..7c33498 100644
--- a/src/components/FlowDiagram.tsx
+++ b/src/components/FlowDiagram.tsx
@@ -1,6 +1,6 @@
"use client"
-import React from "react";
+import React, { useRef } from "react";
import type { Payment, Invoice } from "@stellar-split/sdk";
type FlowDiagramProps = {
@@ -18,9 +18,30 @@ function formatAmount(a: bigint) {
}
export default function FlowDiagram({ invoice }: FlowDiagramProps) {
+ const svgRef = useRef(null);
const payers = invoice.payments.map((p: Payment) => ({ address: p.payer, amount: p.amount }));
const recipients = invoice.recipients.map((r) => ({ address: r.address, amount: r.amount }));
+ const handleDownloadSvg = () => {
+ const svgEl = svgRef.current;
+ if (!svgEl) return;
+
+ const serialized = new XMLSerializer().serializeToString(svgEl);
+ const svgString = serialized.startsWith("\n${serialized}`;
+
+ const blob = new Blob([svgString], { type: "image/svg+xml" });
+ const url = URL.createObjectURL(blob);
+ const link = document.createElement("a");
+ link.href = url;
+ link.download = "flow-diagram.svg";
+ document.body.appendChild(link);
+ link.click();
+ document.body.removeChild(link);
+ URL.revokeObjectURL(url);
+ };
+
const width = 800;
const height = 240;
@@ -36,7 +57,14 @@ export default function FlowDiagram({ invoice }: FlowDiagramProps) {
return (
-