Canvas: build application infrastructure with drag and drop

Change-Id: I5cfd12e67794f3376c5c025af29470d52d77cf16
diff --git a/apps/canvas/src/components/node-rect.tsx b/apps/canvas/src/components/node-rect.tsx
new file mode 100644
index 0000000..5164a13
--- /dev/null
+++ b/apps/canvas/src/components/node-rect.tsx
@@ -0,0 +1,38 @@
+import { NodeType, useNodeMessages } from "@/lib/state";
+import { Icon } from "./icon";
+
+export type Props = {
+    id: string;
+    selected?: boolean;
+    children: any;
+    type: NodeType;
+};
+
+export function NodeRect(p: Props) {
+    const { id, selected, children } = p;
+    const messages = useNodeMessages(id);
+    const hasFatal = messages.some((m) => m.type === "FATAL");
+    const hasWarning = messages.some((m) => m.type === "WARNING");
+    const classes = ["px-4", "py-2", "rounded-md", "bg-white"];
+    if (hasFatal) {
+        classes.push("border-red-500");
+    } else if (hasWarning) {
+        classes.push("border-yellow-500");
+    } else {
+        classes.push("border-black");
+    }
+    if (selected) {
+        classes.push("border-2");
+    } else {
+        classes.push("border");
+    }
+    return (
+        <div className={classes.join(" ")}>
+            <div style={{ position: "absolute", top: "5px", left: "5px"}}>
+                {Icon(p.type)}
+            </div>
+            {children}
+        </div>
+    )
+
+}
\ No newline at end of file