From 7bfaa02ef2a688a3f2a3d1c16b48e0dff3287659 Mon Sep 17 00:00:00 2001 From: Kris McGinnes Date: Mon, 20 Jul 2026 22:16:29 -0500 Subject: [PATCH] Derive edge arrow icons from cytoscape arrow geometry The 11 hand-drawn Arrow* icons duplicated the arrow-head geometry that arrowShapes.ts already ports verbatim from cytoscape. Replace them with a single ArrowStyleIcon that renders the resolved geometry for any ArrowStyle, so the picker and edge details always match what the canvas draws. - Add ArrowStyleIcon: a short edge line ending in the arrow head, with a shared viewBox so line thickness and zoom are constant and head trailing edges align across styles; line length varies with head depth. - Extract ArrowPrimitiveShape from EdgePreview as the shared primitive renderer for both the preview and the icon. - Rewire the arrow-style picker and EdgeDetail to ArrowStyleIcon; delete the 11 Arrow* icon files and their barrel exports. --- .../EdgePreview/ArrowPrimitiveShape.tsx | 21 ++++ .../EdgePreview/ArrowStyleIcon.test.tsx | 80 +++++++++++++ .../components/EdgePreview/ArrowStyleIcon.tsx | 106 ++++++++++++++++++ .../components/EdgePreview/EdgePreview.tsx | 13 +-- .../src/components/EdgePreview/index.ts | 1 + .../src/components/icons/ArrowCircle.tsx | 22 ---- .../src/components/icons/ArrowDiamond.tsx | 22 ---- .../src/components/icons/ArrowNone.tsx | 18 --- .../src/components/icons/ArrowSquare.tsx | 19 ---- .../src/components/icons/ArrowTee.tsx | 24 ---- .../src/components/icons/ArrowTriangle.tsx | 22 ---- .../icons/ArrowTriangleBackCurve.tsx | 22 ---- .../components/icons/ArrowTriangleCircle.tsx | 26 ----- .../components/icons/ArrowTriangleCross.tsx | 28 ----- .../src/components/icons/ArrowTriangleTee.tsx | 28 ----- .../src/components/icons/ArrowVee.tsx | 22 ---- .../src/components/icons/index.ts | 11 -- .../modules/EdgesStyling/EdgeStyleDialog.tsx | 11 +- .../modules/EdgesStyling/arrowsStyling.tsx | 82 +++----------- .../src/modules/EntityDetails/EdgeDetail.tsx | 46 +------- 20 files changed, 236 insertions(+), 388 deletions(-) create mode 100644 packages/graph-explorer/src/components/EdgePreview/ArrowPrimitiveShape.tsx create mode 100644 packages/graph-explorer/src/components/EdgePreview/ArrowStyleIcon.test.tsx create mode 100644 packages/graph-explorer/src/components/EdgePreview/ArrowStyleIcon.tsx delete mode 100644 packages/graph-explorer/src/components/icons/ArrowCircle.tsx delete mode 100644 packages/graph-explorer/src/components/icons/ArrowDiamond.tsx delete mode 100644 packages/graph-explorer/src/components/icons/ArrowNone.tsx delete mode 100644 packages/graph-explorer/src/components/icons/ArrowSquare.tsx delete mode 100644 packages/graph-explorer/src/components/icons/ArrowTee.tsx delete mode 100644 packages/graph-explorer/src/components/icons/ArrowTriangle.tsx delete mode 100644 packages/graph-explorer/src/components/icons/ArrowTriangleBackCurve.tsx delete mode 100644 packages/graph-explorer/src/components/icons/ArrowTriangleCircle.tsx delete mode 100644 packages/graph-explorer/src/components/icons/ArrowTriangleCross.tsx delete mode 100644 packages/graph-explorer/src/components/icons/ArrowTriangleTee.tsx delete mode 100644 packages/graph-explorer/src/components/icons/ArrowVee.tsx diff --git a/packages/graph-explorer/src/components/EdgePreview/ArrowPrimitiveShape.tsx b/packages/graph-explorer/src/components/EdgePreview/ArrowPrimitiveShape.tsx new file mode 100644 index 000000000..9fa21988c --- /dev/null +++ b/packages/graph-explorer/src/components/EdgePreview/ArrowPrimitiveShape.tsx @@ -0,0 +1,21 @@ +import type { ArrowPrimitive } from "./arrowShapes"; + +/** + * Renders a single resolved arrow primitive (polygon, path, or circle) as an + * SVG child. Shared by the edge preview and the arrow-style icon so both draw + * cytoscape's arrow geometry identically. + */ +export function ArrowPrimitiveShape({ + primitive, +}: { + primitive: ArrowPrimitive; +}) { + if (primitive.kind === "circle") { + return ; + } + if (primitive.kind === "path") { + return ; + } + const points = primitive.points.map(([x, y]) => `${x},${y}`).join(" "); + return ; +} diff --git a/packages/graph-explorer/src/components/EdgePreview/ArrowStyleIcon.test.tsx b/packages/graph-explorer/src/components/EdgePreview/ArrowStyleIcon.test.tsx new file mode 100644 index 000000000..5e44a58c8 --- /dev/null +++ b/packages/graph-explorer/src/components/EdgePreview/ArrowStyleIcon.test.tsx @@ -0,0 +1,80 @@ +// @vitest-environment happy-dom +import { render } from "@testing-library/react"; + +import { ARROW_STYLES } from "@/core"; + +import { ArrowStyleIcon, type ArrowStyleIconProps } from "./ArrowStyleIcon"; + +function renderIcon(props: ArrowStyleIconProps) { + const { container } = render(); + const svg = container.querySelector("svg"); + if (!svg) { + throw new Error("expected an svg element"); + } + return svg; +} + +describe("ArrowStyleIcon", () => { + it.each(ARROW_STYLES)("renders %s with a shared viewBox", arrowStyle => { + const svg = renderIcon({ arrowStyle }); + expect(svg.getAttribute("viewBox")).toBe( + renderIcon({ arrowStyle: "triangle" }).getAttribute("viewBox"), + ); + }); + + it("always draws the edge shaft", () => { + for (const arrowStyle of ARROW_STYLES) { + const svg = renderIcon({ arrowStyle }); + expect(svg.querySelector("rect")).not.toBeNull(); + } + }); + + it("draws a head for every style except none", () => { + for (const arrowStyle of ARROW_STYLES) { + const svg = renderIcon({ arrowStyle }); + const hasHead = svg.querySelector("polygon, path, circle") !== null; + expect(hasHead).toBe(arrowStyle !== "none"); + } + }); + + it("draws two head primitives for compound styles", () => { + for (const arrowStyle of [ + "triangle-tee", + "triangle-cross", + "circle-triangle", + ] as const) { + const svg = renderIcon({ arrowStyle }); + expect(svg.querySelectorAll("polygon, path, circle")).toHaveLength(2); + } + }); + + it("starts every shaft at the same left edge", () => { + const lefts = ARROW_STYLES.map(arrowStyle => + renderIcon({ arrowStyle }).querySelector("rect")!.getAttribute("x"), + ); + expect(new Set(lefts).size).toBe(1); + }); + + it("forwards svg attributes such as className", () => { + const svg = renderIcon({ arrowStyle: "triangle", className: "rotate-180" }); + expect(svg.getAttribute("class")).toBe("rotate-180"); + }); + + it("does not shift a tip-at-origin head like triangle", () => { + // triangle's tip sits at the frame origin (bbox.maxX = 0), so its head + // needs no shift to reach the shared right anchor. + const svg = renderIcon({ arrowStyle: "triangle" }); + expect(svg.querySelector("g")!.getAttribute("transform")).toBe( + "translate(0 0)", + ); + }); + + it("shifts a head that pokes past the origin like circle onto the anchor", () => { + // circle straddles the origin (bbox.maxX > 0), so it is translated left by + // that overshoot to land its trailing edge on the shared right anchor. + const svg = renderIcon({ arrowStyle: "circle" }); + const transform = svg.querySelector("g")!.getAttribute("transform")!; + const shift = Number(transform.match(/translate\(([-\d.]+) 0\)/)![1]); + expect(shift).toBeLessThan(0); + }); +}); diff --git a/packages/graph-explorer/src/components/EdgePreview/ArrowStyleIcon.tsx b/packages/graph-explorer/src/components/EdgePreview/ArrowStyleIcon.tsx new file mode 100644 index 000000000..d0a6e34bb --- /dev/null +++ b/packages/graph-explorer/src/components/EdgePreview/ArrowStyleIcon.tsx @@ -0,0 +1,106 @@ +import type { SVGAttributes } from "react"; + +import { ARROW_STYLES, type ArrowStyle } from "@/core"; + +import { ArrowPrimitiveShape } from "./ArrowPrimitiveShape"; +import { + type ArrowGeometry, + getArrowWidth, + resolveArrowGeometry, +} from "./arrowShapes"; + +// --- Icon geometry --- +// +// An arrow-style icon is a short horizontal edge ending in the arrow head, all +// drawn from the same cytoscape geometry the canvas and edge preview use. The +// three visual invariants across every style: +// 1. the edge line STARTS at a shared left edge, +// 2. the head's TRAILING edge lands on a shared right anchor (x=0), and +// 3. every icon shares one viewBox, so line thickness and zoom are identical. +// Line LENGTH therefore varies with how deep the head is. + +/** Conceptual edge width the icon geometry is drawn at. */ +const LINE_THICKNESS = 2; +/** Pixels per cytoscape unit — the multiplier applied to normalized points. */ +const UNIT = getArrowWidth(LINE_THICKNESS); +/** Shaft length beyond the leftmost head body, as a fraction of the unit. */ +const SHAFT_FRACTION = 0.12; +/** Padding around the drawn content, in cytoscape units. */ +const PADDING = 3; + +/** Shift that lands a head's rightmost point on the shared right anchor (0). */ +function headShift(geometry: ArrowGeometry | null): number { + return geometry ? -geometry.bbox.maxX : 0; +} + +/** + * The viewBox and shaft-start shared by every arrow-style icon, computed once + * from the union of all head geometries so the icons form a consistent set. + */ +function computeSharedFrame() { + let bodyMinX = 0; + let yExtent = LINE_THICKNESS / 2; + for (const style of ARROW_STYLES) { + const geometry = resolveArrowGeometry(style, UNIT, LINE_THICKNESS); + if (!geometry) { + continue; + } + const shift = headShift(geometry); + bodyMinX = Math.min(bodyMinX, geometry.bbox.minX + shift); + yExtent = Math.max(yExtent, -geometry.bbox.minY, geometry.bbox.maxY); + } + const shaftLeft = bodyMinX - UNIT * SHAFT_FRACTION; + const minX = shaftLeft - PADDING; + const maxX = PADDING; + const minY = -(yExtent + PADDING); + const height = 2 * (yExtent + PADDING); + return { + shaftLeft, + viewBox: `${minX} ${minY} ${maxX - minX} ${height}`, + }; +} + +const sharedFrame = computeSharedFrame(); + +export type ArrowStyleIconProps = { + arrowStyle: ArrowStyle; +} & SVGAttributes; + +/** + * Icon for an edge arrow style: a short edge line ending in the arrow head, + * drawn from the same cytoscape geometry as the canvas so the picker and edge + * details always match what renders. The head points right; rotate with CSS to + * reorient. Fills with `currentColor`, so it takes the surrounding text color. + */ +export function ArrowStyleIcon({ arrowStyle, ...props }: ArrowStyleIconProps) { + const geometry = resolveArrowGeometry(arrowStyle, UNIT, LINE_THICKNESS); + const shift = headShift(geometry); + // The shaft meets the head at cytoscape's (spacing - gap) point, in the + // shifted frame; with no head it runs to the shared right anchor at x=0. + const shaftRight = geometry ? geometry.spacing - geometry.gap + shift : 0; + + return ( + + + {geometry && ( + + {geometry.primitives.map((primitive, i) => ( + + ))} + + )} + + ); +} diff --git a/packages/graph-explorer/src/components/EdgePreview/EdgePreview.tsx b/packages/graph-explorer/src/components/EdgePreview/EdgePreview.tsx index f1b671566..660b6ec19 100644 --- a/packages/graph-explorer/src/components/EdgePreview/EdgePreview.tsx +++ b/packages/graph-explorer/src/components/EdgePreview/EdgePreview.tsx @@ -7,9 +7,9 @@ import { cn } from "@/utils"; import { LabelPreview } from "../LabelPreview"; import { edgePreviewLabel } from "../previewLabels"; +import { ArrowPrimitiveShape } from "./ArrowPrimitiveShape"; import { type ArrowGeometry, - type ArrowPrimitive, getArrowWidth, resolveArrowGeometry, } from "./arrowShapes"; @@ -233,14 +233,3 @@ function ArrowHead({ ); } - -function ArrowPrimitiveShape({ primitive }: { primitive: ArrowPrimitive }) { - if (primitive.kind === "circle") { - return ; - } - if (primitive.kind === "path") { - return ; - } - const points = primitive.points.map(([x, y]) => `${x},${y}`).join(" "); - return ; -} diff --git a/packages/graph-explorer/src/components/EdgePreview/index.ts b/packages/graph-explorer/src/components/EdgePreview/index.ts index 22e1b1b57..76b0073d6 100644 --- a/packages/graph-explorer/src/components/EdgePreview/index.ts +++ b/packages/graph-explorer/src/components/EdgePreview/index.ts @@ -1 +1,2 @@ export { EdgePreview } from "./EdgePreview"; +export { ArrowStyleIcon } from "./ArrowStyleIcon"; diff --git a/packages/graph-explorer/src/components/icons/ArrowCircle.tsx b/packages/graph-explorer/src/components/icons/ArrowCircle.tsx deleted file mode 100644 index 6e0f7f4ac..000000000 --- a/packages/graph-explorer/src/components/icons/ArrowCircle.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import type { IconBaseProps } from "./IconBase"; - -import IconBase from "./IconBase"; - -export const ArrowCircle = (props: IconBaseProps) => { - return ( - - - - - ); -}; - -export default ArrowCircle; diff --git a/packages/graph-explorer/src/components/icons/ArrowDiamond.tsx b/packages/graph-explorer/src/components/icons/ArrowDiamond.tsx deleted file mode 100644 index 0a3c40c96..000000000 --- a/packages/graph-explorer/src/components/icons/ArrowDiamond.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import type { IconBaseProps } from "./IconBase"; - -import IconBase from "./IconBase"; - -export const ArrowDiamond = (props: IconBaseProps) => { - return ( - - - - - ); -}; - -export default ArrowDiamond; diff --git a/packages/graph-explorer/src/components/icons/ArrowNone.tsx b/packages/graph-explorer/src/components/icons/ArrowNone.tsx deleted file mode 100644 index 08183f9f1..000000000 --- a/packages/graph-explorer/src/components/icons/ArrowNone.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import type { IconBaseProps } from "./IconBase"; - -import IconBase from "./IconBase"; - -export const ArrowNone = (props: IconBaseProps) => { - return ( - - - - ); -}; - -export default ArrowNone; diff --git a/packages/graph-explorer/src/components/icons/ArrowSquare.tsx b/packages/graph-explorer/src/components/icons/ArrowSquare.tsx deleted file mode 100644 index 2f59499bc..000000000 --- a/packages/graph-explorer/src/components/icons/ArrowSquare.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import type { IconBaseProps } from "./IconBase"; - -import IconBase from "./IconBase"; - -export const ArrowSquare = (props: IconBaseProps) => { - return ( - - - - - ); -}; - -export default ArrowSquare; diff --git a/packages/graph-explorer/src/components/icons/ArrowTee.tsx b/packages/graph-explorer/src/components/icons/ArrowTee.tsx deleted file mode 100644 index c8351d28e..000000000 --- a/packages/graph-explorer/src/components/icons/ArrowTee.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import type { IconBaseProps } from "./IconBase"; - -import IconBase from "./IconBase"; - -export const ArrowTee = (props: IconBaseProps) => { - return ( - - - - - ); -}; - -export default ArrowTee; diff --git a/packages/graph-explorer/src/components/icons/ArrowTriangle.tsx b/packages/graph-explorer/src/components/icons/ArrowTriangle.tsx deleted file mode 100644 index cb8cba4d1..000000000 --- a/packages/graph-explorer/src/components/icons/ArrowTriangle.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import type { IconBaseProps } from "./IconBase"; - -import IconBase from "./IconBase"; - -export const ArrowTriangle = (props: IconBaseProps) => { - return ( - - - - - ); -}; - -export default ArrowTriangle; diff --git a/packages/graph-explorer/src/components/icons/ArrowTriangleBackCurve.tsx b/packages/graph-explorer/src/components/icons/ArrowTriangleBackCurve.tsx deleted file mode 100644 index 3c876f5b3..000000000 --- a/packages/graph-explorer/src/components/icons/ArrowTriangleBackCurve.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import type { IconBaseProps } from "./IconBase"; - -import IconBase from "./IconBase"; - -export const ArrowTriangleBackCurve = (props: IconBaseProps) => { - return ( - - - - - ); -}; - -export default ArrowTriangleBackCurve; diff --git a/packages/graph-explorer/src/components/icons/ArrowTriangleCircle.tsx b/packages/graph-explorer/src/components/icons/ArrowTriangleCircle.tsx deleted file mode 100644 index d5412ff8a..000000000 --- a/packages/graph-explorer/src/components/icons/ArrowTriangleCircle.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import type { IconBaseProps } from "./IconBase"; - -import IconBase from "./IconBase"; - -export const ArrowTriangleCircle = (props: IconBaseProps) => { - return ( - - - - - - ); -}; - -export default ArrowTriangleCircle; diff --git a/packages/graph-explorer/src/components/icons/ArrowTriangleCross.tsx b/packages/graph-explorer/src/components/icons/ArrowTriangleCross.tsx deleted file mode 100644 index 374b205a0..000000000 --- a/packages/graph-explorer/src/components/icons/ArrowTriangleCross.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import type { IconBaseProps } from "./IconBase"; - -import IconBase from "./IconBase"; - -export const ArrowTriangleCross = (props: IconBaseProps) => { - return ( - - - - - - ); -}; - -export default ArrowTriangleCross; diff --git a/packages/graph-explorer/src/components/icons/ArrowTriangleTee.tsx b/packages/graph-explorer/src/components/icons/ArrowTriangleTee.tsx deleted file mode 100644 index 41fdcf2e3..000000000 --- a/packages/graph-explorer/src/components/icons/ArrowTriangleTee.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import type { IconBaseProps } from "./IconBase"; - -import IconBase from "./IconBase"; - -export const ArrowTriangleTee = (props: IconBaseProps) => { - return ( - - - - - - ); -}; - -export default ArrowTriangleTee; diff --git a/packages/graph-explorer/src/components/icons/ArrowVee.tsx b/packages/graph-explorer/src/components/icons/ArrowVee.tsx deleted file mode 100644 index 61a2ab040..000000000 --- a/packages/graph-explorer/src/components/icons/ArrowVee.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import type { IconBaseProps } from "./IconBase"; - -import IconBase from "./IconBase"; - -export const ArrowVee = (props: IconBaseProps) => { - return ( - - - - - ); -}; - -export default ArrowVee; diff --git a/packages/graph-explorer/src/components/icons/index.ts b/packages/graph-explorer/src/components/icons/index.ts index 18ae24291..4a9fdc22d 100644 --- a/packages/graph-explorer/src/components/icons/index.ts +++ b/packages/graph-explorer/src/components/icons/index.ts @@ -1,15 +1,4 @@ export { default as AddIcon } from "./AddIcon"; -export { default as ArrowCircle } from "./ArrowCircle"; -export { default as ArrowDiamond } from "./ArrowDiamond"; -export { default as ArrowNone } from "./ArrowNone"; -export { default as ArrowSquare } from "./ArrowSquare"; -export { default as ArrowTee } from "./ArrowTee"; -export { default as ArrowTriangle } from "./ArrowTriangle"; -export { default as ArrowTriangleBackCurve } from "./ArrowTriangleBackCurve"; -export { default as ArrowTriangleCircle } from "./ArrowTriangleCircle"; -export { default as ArrowTriangleCross } from "./ArrowTriangleCross"; -export { default as ArrowTriangleTee } from "./ArrowTriangleTee"; -export { default as ArrowVee } from "./ArrowVee"; export { default as AutoFitLeftIcon } from "./AutoFitLeftIcon"; export { default as CenterGraphIcon } from "./CenterGraphIcon"; export { default as CheckIcon } from "./CheckIcon"; diff --git a/packages/graph-explorer/src/modules/EdgesStyling/EdgeStyleDialog.tsx b/packages/graph-explorer/src/modules/EdgesStyling/EdgeStyleDialog.tsx index c36014407..6aecb761e 100644 --- a/packages/graph-explorer/src/modules/EdgesStyling/EdgeStyleDialog.tsx +++ b/packages/graph-explorer/src/modules/EdgesStyling/EdgeStyleDialog.tsx @@ -1,6 +1,7 @@ import { atom, useAtom, useSetAtom } from "jotai"; import { + ArrowStyleIcon, Button, ColorPopover, EdgePreview, @@ -275,8 +276,11 @@ function Content({ edgeType }: { edgeType: EdgeType }) { {ARROW_STYLE_OPTIONS.map(option => (
+ {option.label} -
))} @@ -298,8 +302,11 @@ function Content({ edgeType }: { edgeType: EdgeType }) { {ARROW_STYLE_OPTIONS.map(option => (
+ {option.label} -
))} diff --git a/packages/graph-explorer/src/modules/EdgesStyling/arrowsStyling.tsx b/packages/graph-explorer/src/modules/EdgesStyling/arrowsStyling.tsx index 7b6ba0616..3a31e8a2c 100644 --- a/packages/graph-explorer/src/modules/EdgesStyling/arrowsStyling.tsx +++ b/packages/graph-explorer/src/modules/EdgesStyling/arrowsStyling.tsx @@ -1,71 +1,15 @@ -import { - ArrowCircle, - ArrowDiamond, - ArrowNone, - ArrowSquare, - ArrowTee, - ArrowTriangle, - ArrowTriangleBackCurve, - ArrowTriangleCircle, - ArrowTriangleCross, - ArrowTriangleTee, - ArrowVee, -} from "@/components"; +import type { ArrowStyle } from "@/core"; -export const ARROW_STYLE_OPTIONS = [ - { - label: "Triangle", - value: "triangle", - Icon: ArrowTriangle, - }, - { - label: "Triangle Tee", - value: "triangle-tee", - Icon: ArrowTriangleTee, - }, - { - label: "Triangle Circle", - value: "circle-triangle", - Icon: ArrowTriangleCircle, - }, - { - label: "Triangle Cross", - value: "triangle-cross", - Icon: ArrowTriangleCross, - }, - { - label: "Triangle Backcurve", - value: "triangle-backcurve", - Icon: ArrowTriangleBackCurve, - }, - { - label: "Tee", - value: "tee", - Icon: ArrowTee, - }, - { - label: "Vee", - value: "vee", - Icon: ArrowVee, - }, - { - label: "Square", - value: "square", - Icon: ArrowSquare, - }, - { - label: "Circle", - value: "circle", - Icon: ArrowCircle, - }, - { - label: "Diamond", - value: "diamond", - Icon: ArrowDiamond, - }, - { - label: "None", - value: "none", - Icon: ArrowNone, - }, +export const ARROW_STYLE_OPTIONS: { label: string; value: ArrowStyle }[] = [ + { label: "Triangle", value: "triangle" }, + { label: "Triangle Tee", value: "triangle-tee" }, + { label: "Triangle Circle", value: "circle-triangle" }, + { label: "Triangle Cross", value: "triangle-cross" }, + { label: "Triangle Backcurve", value: "triangle-backcurve" }, + { label: "Tee", value: "tee" }, + { label: "Vee", value: "vee" }, + { label: "Square", value: "square" }, + { label: "Circle", value: "circle" }, + { label: "Diamond", value: "diamond" }, + { label: "None", value: "none" }, ]; diff --git a/packages/graph-explorer/src/modules/EntityDetails/EdgeDetail.tsx b/packages/graph-explorer/src/modules/EntityDetails/EdgeDetail.tsx index 1d85c6425..dec46cc39 100644 --- a/packages/graph-explorer/src/modules/EntityDetails/EdgeDetail.tsx +++ b/packages/graph-explorer/src/modules/EntityDetails/EdgeDetail.tsx @@ -1,24 +1,7 @@ import type { CSSProperties } from "react"; -import type { IconBaseProps } from "@/components/icons/IconBase"; - -import { - ArrowCircle, - ArrowDiamond, - ArrowNone, - ArrowSquare, - ArrowTee, - ArrowTriangle, - ArrowTriangleBackCurve, - ArrowTriangleCircle, - ArrowTriangleCross, - ArrowTriangleTee, - ArrowVee, - EdgeRow, - VertexRow, -} from "@/components"; +import { ArrowStyleIcon, EdgeRow, VertexRow } from "@/components"; import { - type ArrowStyle, type DisplayAttribute, type DisplayEdge, type LineStyle, @@ -96,16 +79,16 @@ const EdgeDetail = ({ edge }: EdgeDetailProps) => { className="row-span-2 flex flex-col items-center" style={{ color: style.lineColor || DEFAULT_LINE_COLOR }} > -
- @@ -157,23 +140,4 @@ function styleForLineStyle(style: LineStyle): CSSProperties { return {}; } -/** Renders the right SVG icon for the given arrow style. */ -function Arrow({ kind, ...props }: { kind: ArrowStyle } & IconBaseProps) { - return ( - <> - {kind === "triangle" && } - {kind === "triangle-tee" && } - {kind === "circle-triangle" && } - {kind === "triangle-cross" && } - {kind === "triangle-backcurve" && } - {kind === "tee" && } - {kind === "vee" && } - {kind === "square" && } - {kind === "circle" && } - {kind === "diamond" && } - {kind === "none" && } - - ); -} - export default EdgeDetail;