63 lines
1.9 KiB
TypeScript
63 lines
1.9 KiB
TypeScript
// <BoxFace> — what one node's box shows: its kind, when it runs among its
|
|
// siblings, how many events reached it, and what it does. The editor's canvas
|
|
// and the list's read-only graph both draw their boxes with it, inside a
|
|
// `<g>` of their own that carries the pointer and key handling.
|
|
//
|
|
// The line of text is cut by the browser to the box's own width, so a long
|
|
// description ends in an ellipsis inside the box instead of running out of it;
|
|
// the full text is the box's tooltip.
|
|
import { NODE_HEIGHT, NODE_WIDTH } from "./FlowLayout.js";
|
|
|
|
const PAD = 10;
|
|
|
|
// The long kind name would run into the aside beside it.
|
|
const SHORT_KIND: Record<string, string> = { request_reviewer: "reviewer" };
|
|
|
|
// "1 hit", "0 hits": how the box says how many events reached it.
|
|
export function hitsText(hits: number): string {
|
|
return `${hits} ${hits === 1 ? "hit" : "hits"}`;
|
|
}
|
|
|
|
export function BoxFace({
|
|
kind,
|
|
text,
|
|
order,
|
|
hits,
|
|
}: {
|
|
kind: string;
|
|
text: string;
|
|
// "runs 2nd" when the node has siblings, else nothing.
|
|
order?: string;
|
|
// The events of the last dry run that reached the node, when one covers it.
|
|
hits?: number;
|
|
}) {
|
|
const aside = [order, hits === undefined ? undefined : hitsText(hits)]
|
|
.filter((part) => part !== undefined)
|
|
.join(" · ");
|
|
return (
|
|
<>
|
|
<rect width={NODE_WIDTH} height={NODE_HEIGHT} rx="6" />
|
|
<text class="notify-box-kind" x={PAD} y="17">
|
|
{SHORT_KIND[kind] ?? kind}
|
|
</text>
|
|
{aside ? (
|
|
<text
|
|
class="notify-box-kind notify-box-order"
|
|
x={NODE_WIDTH - PAD}
|
|
y="17"
|
|
text-anchor="end"
|
|
>
|
|
{aside}
|
|
</text>
|
|
) : null}
|
|
<foreignObject
|
|
x={PAD}
|
|
y="23"
|
|
width={NODE_WIDTH - 2 * PAD}
|
|
height={NODE_HEIGHT - 25}
|
|
>
|
|
<div class="notify-box-text">{text}</div>
|
|
</foreignObject>
|
|
</>
|
|
);
|
|
}
|