chore: add prettier with config and format all files
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import React, { useRef, useState, useCallback } from 'react';
|
||||
|
||||
interface HeaderProps {
|
||||
title: string;
|
||||
onEdit: () => void;
|
||||
title: string;
|
||||
onEdit: () => void;
|
||||
onDelete: () => void;
|
||||
}
|
||||
|
||||
@@ -11,8 +11,18 @@ export function Header({ title, onEdit, onDelete }: HeaderProps) {
|
||||
<div className="flex items-center justify-between px-3 py-1.5 border-b border-gray-700 shrink-0">
|
||||
<span className="text-sm font-medium text-gray-200 truncate">{title}</span>
|
||||
<div className="flex gap-1 ml-2 shrink-0">
|
||||
<button onClick={onEdit} className="text-xs text-gray-400 hover:text-white px-1.5 py-0.5 rounded hover:bg-gray-700">✏️</button>
|
||||
<button onClick={onDelete} className="text-xs text-gray-400 hover:text-red-400 px-1.5 py-0.5 rounded hover:bg-gray-700">🗑</button>
|
||||
<button
|
||||
onClick={onEdit}
|
||||
className="text-xs text-gray-400 hover:text-white px-1.5 py-0.5 rounded hover:bg-gray-700"
|
||||
>
|
||||
✏️
|
||||
</button>
|
||||
<button
|
||||
onClick={onDelete}
|
||||
className="text-xs text-gray-400 hover:text-red-400 px-1.5 py-0.5 rounded hover:bg-gray-700"
|
||||
>
|
||||
🗑
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -25,64 +35,81 @@ export function EmptyState() {
|
||||
}
|
||||
|
||||
interface CardShellProps extends HeaderProps {
|
||||
empty: boolean;
|
||||
children: React.ReactNode;
|
||||
empty: boolean;
|
||||
children: React.ReactNode;
|
||||
/** Ref to the div where the uPlot legend will be mounted */
|
||||
legendContainerRef?: React.RefObject<HTMLDivElement>;
|
||||
}
|
||||
|
||||
export function CardShell({ title, onEdit, onDelete, empty, children, legendContainerRef }: CardShellProps) {
|
||||
export function CardShell({
|
||||
title,
|
||||
onEdit,
|
||||
onDelete,
|
||||
empty,
|
||||
children,
|
||||
legendContainerRef,
|
||||
}: CardShellProps) {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const [legendHeight, setLegendHeight] = useState<number | null>(null);
|
||||
const dragRef = useRef<{ startY: number; startH: number } | null>(null);
|
||||
|
||||
const handleMouseDown = useCallback((e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const el = legendContainerRef?.current;
|
||||
if (!el) return;
|
||||
dragRef.current = { startY: e.clientY, startH: el.offsetHeight };
|
||||
const handleMouseDown = useCallback(
|
||||
(e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const el = legendContainerRef?.current;
|
||||
if (!el) return;
|
||||
dragRef.current = { startY: e.clientY, startH: el.offsetHeight };
|
||||
|
||||
function onMove(ev: MouseEvent) {
|
||||
if (!dragRef.current) return;
|
||||
const delta = dragRef.current.startY - ev.clientY;
|
||||
const containerH = containerRef.current?.offsetHeight ?? 400;
|
||||
const newH = Math.max(32, Math.min(containerH - 64, dragRef.current.startH + delta));
|
||||
setLegendHeight(newH);
|
||||
}
|
||||
function onUp() {
|
||||
dragRef.current = null;
|
||||
document.removeEventListener('mousemove', onMove);
|
||||
document.removeEventListener('mouseup', onUp);
|
||||
}
|
||||
document.addEventListener('mousemove', onMove);
|
||||
document.addEventListener('mouseup', onUp);
|
||||
}, [legendContainerRef]);
|
||||
function onMove(ev: MouseEvent) {
|
||||
if (!dragRef.current) return;
|
||||
const delta = dragRef.current.startY - ev.clientY;
|
||||
const containerH = containerRef.current?.offsetHeight ?? 400;
|
||||
const newH = Math.max(32, Math.min(containerH - 64, dragRef.current.startH + delta));
|
||||
setLegendHeight(newH);
|
||||
}
|
||||
function onUp() {
|
||||
dragRef.current = null;
|
||||
document.removeEventListener('mousemove', onMove);
|
||||
document.removeEventListener('mouseup', onUp);
|
||||
}
|
||||
document.addEventListener('mousemove', onMove);
|
||||
document.addEventListener('mouseup', onUp);
|
||||
},
|
||||
[legendContainerRef],
|
||||
);
|
||||
|
||||
return (
|
||||
<div ref={containerRef} className="h-full flex flex-col bg-gray-900 rounded border border-gray-700 overflow-hidden">
|
||||
<div
|
||||
ref={containerRef}
|
||||
className="h-full flex flex-col bg-gray-900 rounded border border-gray-700 overflow-hidden"
|
||||
>
|
||||
<Header title={title} onEdit={onEdit} onDelete={onDelete} />
|
||||
{empty ? (
|
||||
<EmptyState />
|
||||
) : (
|
||||
<>
|
||||
<div className="flex-1 min-h-0">
|
||||
{children}
|
||||
</div>
|
||||
{legendContainerRef && <>
|
||||
<div
|
||||
onMouseDown={handleMouseDown}
|
||||
className="shrink-0 h-1.5 cursor-row-resize bg-gray-800 hover:bg-gray-700 active:bg-gray-600"
|
||||
/>
|
||||
<div
|
||||
ref={legendContainerRef}
|
||||
className="shrink-0 overflow-y-auto px-2 py-1 text-[10px] text-gray-400 [&_.u-legend]:w-full [&_.u-series]:flex [&_.u-series]:items-center [&_.u-series_th]:flex [&_.u-series_th]:items-center [&_.u-series_th]:gap-1 [&_.u-marker]:w-3 [&_.u-marker]:h-0.5 [&_.u-marker]:shrink-0 [&_.u-label]:truncate [&_.u-value]:ml-auto [&_.u-value]:font-mono [&_.u-value]:shrink-0"
|
||||
style={legendHeight != null ? { height: legendHeight, maxHeight: legendHeight } : { maxHeight: '25%' }}
|
||||
/>
|
||||
<style>{'.u-legend .u-series:first-child { display: none; }'}</style>
|
||||
</>}
|
||||
<div className="flex-1 min-h-0">{children}</div>
|
||||
{legendContainerRef && (
|
||||
<>
|
||||
<div
|
||||
onMouseDown={handleMouseDown}
|
||||
className="shrink-0 h-1.5 cursor-row-resize bg-gray-800 hover:bg-gray-700 active:bg-gray-600"
|
||||
/>
|
||||
<div
|
||||
ref={legendContainerRef}
|
||||
className="shrink-0 overflow-y-auto px-2 py-1 text-[10px] text-gray-400 [&_.u-legend]:w-full [&_.u-series]:flex [&_.u-series]:items-center [&_.u-series_th]:flex [&_.u-series_th]:items-center [&_.u-series_th]:gap-1 [&_.u-marker]:w-3 [&_.u-marker]:h-0.5 [&_.u-marker]:shrink-0 [&_.u-label]:truncate [&_.u-value]:ml-auto [&_.u-value]:font-mono [&_.u-value]:shrink-0"
|
||||
style={
|
||||
legendHeight != null
|
||||
? { height: legendHeight, maxHeight: legendHeight }
|
||||
: { maxHeight: '25%' }
|
||||
}
|
||||
/>
|
||||
<style>{'.u-legend .u-series:first-child { display: none; }'}</style>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user