Files
invyone/frontend/components/control/TableNode.tsx
T
2026-04-10 13:33:37 +09:00

78 lines
2.5 KiB
TypeScript

'use client';
import { useRef, useCallback } from 'react';
interface TableNodeProps {
tableName: string;
label: string;
icon: string;
columns: Record<string, any>[];
x: number;
y: number;
style?: React.CSSProperties;
onMove?: (name: string, x: number, y: number) => void;
}
export function TableNode({ tableName, label, icon, columns, x, y, style, onMove }: TableNodeProps) {
const nodeRef = useRef<HTMLDivElement>(null);
const handleMouseDown = useCallback((e: React.MouseEvent) => {
if (!onMove) return;
e.preventDefault();
const sx = e.clientX, sy = e.clientY;
const sl = x, st = y;
const el = nodeRef.current;
if (el) el.style.zIndex = '30';
const move = (ev: MouseEvent) => {
onMove(tableName, sl + ev.clientX - sx, st + ev.clientY - sy);
};
const up = () => {
if (el) el.style.zIndex = '20';
document.removeEventListener('mousemove', move);
document.removeEventListener('mouseup', up);
};
document.addEventListener('mousemove', move);
document.addEventListener('mouseup', up);
}, [onMove, tableName, x, y]);
const dtypeIcons: Record<string, string> = {
text: 'Aa', number: '#', date: '📅', select: '▼', checkbox: '☑', file: '📎', code: '⚡',
textarea: 'Aa', datetime: '📅', entity: '🔗',
};
return (
<div
ref={nodeRef}
className="tbl-node"
data-table={tableName}
style={{ left: x, top: y, ...style }}
>
<div className="tbl-node-head" onMouseDown={handleMouseDown}>
<div className="tbl-icon">{icon}</div>
<span className="tbl-name">{tableName}</span>
<span className="tbl-badge">{label}</span>
</div>
<div className="tbl-node-cols">
{columns.map((col) => {
const name = col.column ?? col.name ?? col.COLUMN_NAME ?? '';
const type = col.type ?? col.dtype ?? 'text';
const mark = col.pk ? 'PK' : col.mark === 'FK' ? 'FK' : '';
const portCls = mark === 'PK' ? 'pk' : mark === 'FK' ? 'fk' : '';
const displayName = col.label ?? col.dname ?? name;
const dtIcon = dtypeIcons[type] || 'Aa';
return (
<div key={name} className="tbl-col" data-col={name}>
<div className={`tbl-port ${portCls}`} />
<span className="tbl-col-name">{displayName}</span>
<span className="tbl-col-type">{dtIcon} {type}</span>
{mark && <span className={`tbl-col-mark ${mark.toLowerCase()}`}>{mark}</span>}
</div>
);
})}
</div>
</div>
);
}