diff --git a/web/package-lock.json b/web/package-lock.json index 2b9e8dd..25905b8 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -8,6 +8,7 @@ "name": "silo-web", "version": "0.0.0", "dependencies": { + "lucide-react": "^0.564.0", "react": "^19.0.0", "react-dom": "^19.0.0", "react-router-dom": "^7.0.0" @@ -1499,6 +1500,15 @@ "yallist": "^3.0.2" } }, + "node_modules/lucide-react": { + "version": "0.564.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.564.0.tgz", + "integrity": "sha512-JJ8GVTQqFwuliifD48U6+h7DXEHdkhJ/E87kksGByII3qHxtPciVb8T8woQONHBQgHVOl7rSMrrip3SeVNy7Fg==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", diff --git a/web/package.json b/web/package.json index b30bec5..ad2910d 100644 --- a/web/package.json +++ b/web/package.json @@ -9,6 +9,7 @@ "preview": "vite preview" }, "dependencies": { + "lucide-react": "^0.564.0", "react": "^19.0.0", "react-dom": "^19.0.0", "react-router-dom": "^7.0.0" diff --git a/web/src/components/ContextMenu.tsx b/web/src/components/ContextMenu.tsx index 13e4e6c..a3e71d3 100644 --- a/web/src/components/ContextMenu.tsx +++ b/web/src/components/ContextMenu.tsx @@ -1,4 +1,5 @@ -import { useEffect, useRef } from 'react'; +import { useEffect, useRef } from "react"; +import { Check } from "lucide-react"; export interface ContextMenuItem { label: string; @@ -24,76 +25,95 @@ export function ContextMenu({ x, y, items, onClose }: ContextMenuProps) { if (ref.current && !ref.current.contains(e.target as Node)) onClose(); }; const handleKey = (e: KeyboardEvent) => { - if (e.key === 'Escape') onClose(); + if (e.key === "Escape") onClose(); }; const handleScroll = () => onClose(); - document.addEventListener('mousedown', handleClick); - document.addEventListener('keydown', handleKey); - window.addEventListener('scroll', handleScroll, true); + document.addEventListener("mousedown", handleClick); + document.addEventListener("keydown", handleKey); + window.addEventListener("scroll", handleScroll, true); return () => { - document.removeEventListener('mousedown', handleClick); - document.removeEventListener('keydown', handleKey); - window.removeEventListener('scroll', handleScroll, true); + document.removeEventListener("mousedown", handleClick); + document.removeEventListener("keydown", handleKey); + window.removeEventListener("scroll", handleScroll, true); }; }, [onClose]); // Clamp position to viewport const style: React.CSSProperties = { - position: 'fixed', + position: "fixed", left: Math.min(x, window.innerWidth - 220), top: Math.min(y, window.innerHeight - items.length * 32 - 16), zIndex: 9999, - backgroundColor: 'var(--ctp-surface0)', - border: '1px solid var(--ctp-surface1)', - borderRadius: '0.5rem', - padding: '0.25rem 0', + backgroundColor: "var(--ctp-surface0)", + border: "1px solid var(--ctp-surface1)", + borderRadius: "0.5rem", + padding: "0.25rem 0", minWidth: 200, - boxShadow: '0 4px 12px rgba(0,0,0,0.4)', + boxShadow: "0 4px 12px rgba(0,0,0,0.4)", }; return (
| Rev | @@ -143,17 +231,32 @@ export function RevisionsTab({ partNumber, isEditor }: RevisionsTabProps) {||||||||
|---|---|---|---|---|---|---|---|---|
| {rev.revision_number} |
{isEditor ? (
|
{formatDate(rev.created_at)} | -{rev.created_by ?? '—'} | -{rev.comment ?? ''} | +{rev.created_by ?? "—"} | ++ {rev.comment ?? ""} + |
{rev.file_key ? (
|
{isEditor && (
Loading projects... ; @@ -199,8 +210,16 @@ export function ProjectsPage() { >Projects ({projects.length}){isEditor && mode === "list" && ( - |