feat: Group findings table values with custom components/grouping functions (#4712)

This commit is contained in:
Bill Wallace authored and GitHub committed 2025-03-20 09:22:45 -04:00
1 parent 0522d58d9b
commit df8efba82c
48 files changed
+1256 -631

No files matched your search

@@ -35,8 +35,14 @@ const AccordionTrigger = React.forwardRef<
)}
{...props}
>
{children}
<ChevronDownIcon className="text-primary h-4 w-4 shrink-0 transition-transform duration-200" />
{props.asChild ? (
children
) : (
<>
{children}
<ChevronDownIcon className="text-primary h-4 w-4 shrink-0 transition-transform duration-200" />
</>
)}
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
));
@@ -0,0 +1,12 @@
import React from 'react';
export function ColorCircle({ colorHex, className = 'inline-flex' }) {
return (
<div className={`h-5 w-5 ${className} items-center justify-center`}>
<span
className="ml-2 h-2 w-2 rounded-full"
style={{ backgroundColor: colorHex, marginLeft: 0 }}
/>
</div>
);
}
@@ -63,25 +63,25 @@ interface DataRowProps {
details?: { primary: string[]; secondary: string[] };
//
isSelected?: boolean;
onSelect?: () => void;
onSelect?: (e) => void;
//
isVisible: boolean;
onToggleVisibility: () => void;
onToggleVisibility: (e) => void;
//
isLocked: boolean;
onToggleLocked: () => void;
onToggleLocked: (e) => void;
//
title: string;
onRename: () => void;
onRename: (e) => void;
//
onDelete: () => void;
onDelete: (e) => void;
//
colorHex?: string;
onColor: () => void;
onColor: (e) => void;
className?: string;
}
const DataRow: React.FC<DataRowProps> = ({
export const DataRow: React.FC<DataRowProps> = ({
number,
title,
colorHex,
@@ -114,16 +114,16 @@ const DataRow: React.FC<DataRowProps> = ({
e.stopPropagation();
switch (action) {
case 'Rename':
onRename();
onRename(e);
break;
case 'Lock':
onToggleLocked();
onToggleLocked(e);
break;
case 'Delete':
onDelete();
onDelete(e);
break;
case 'Color':
onColor();
onColor(e);
break;
}
};
@@ -269,7 +269,7 @@ const DataRow: React.FC<DataRowProps> = ({
aria-label={isVisible ? 'Hide' : 'Show'}
onClick={e => {
e.stopPropagation();
onToggleVisibility();
onToggleVisibility(e);
}}
>
{isVisible ? <Icons.Hide className="h-6 w-6" /> : <Icons.Show className="h-6 w-6" />}
@@ -1,3 +1 @@
import DataRow from './DataRow';
export { DataRow };
export * from './DataRow';
@@ -5,13 +5,9 @@ import { createContext } from '../../lib/createContext';
interface MeasurementTableContext {
data?: any[];
onClick?: (uid: string) => void;
onDelete?: (uid: string) => void;
onToggleVisibility?: (uid: string) => void;
onToggleLocked?: (uid: string) => void;
onRename?: (uid: string) => void;
onColor?: (uid: string) => void;
onAction?: (e, command: string | string[], uid: string) => void;
disableEditing?: boolean;
isExpanded: boolean;
}
const [MeasurementTableProvider, useMeasurementTableContext] =
@@ -24,12 +20,8 @@ interface MeasurementDataProps extends MeasurementTableContext {
const MeasurementTable = ({
data = [],
onClick,
onDelete,
onToggleVisibility,
onToggleLocked,
onRename,
onColor,
onAction,
isExpanded = true,
title,
children,
disableEditing = false,
@@ -40,19 +32,18 @@ const MeasurementTable = ({
return (
<MeasurementTableProvider
data={data}
onClick={onClick}
onDelete={onDelete}
onToggleVisibility={onToggleVisibility}
onToggleLocked={onToggleLocked}
onRename={onRename}
onColor={onColor}
onAction={onAction}
isExpanded={isExpanded}
disableEditing={disableEditing}
>
<PanelSection defaultOpen={true}>
<PanelSection.Header className="bg-secondary-dark">
<PanelSection.Header
key="measurementTableHeader"
className="bg-secondary-dark"
>
<span>{`${t(title)} (${amount})`}</span>
</PanelSection.Header>
<PanelSection.Content>{children}</PanelSection.Content>
<PanelSection.Content key="measurementTableContent">{children}</PanelSection.Content>
</PanelSection>
</MeasurementTableProvider>
);
@@ -99,6 +90,7 @@ interface MeasurementItem {
isVisible: boolean;
isLocked: boolean;
toolName: string;
isExpanded: boolean;
}
interface RowProps {
@@ -107,16 +99,10 @@ interface RowProps {
}
const Row = ({ item, index }: RowProps) => {
const {
onClick,
onDelete,
onToggleVisibility,
onToggleLocked,
onRename,
onColor,
disableEditing,
} = useMeasurementTableContext('MeasurementTable.Row');
const { onAction, isExpanded, disableEditing } =
useMeasurementTableContext('MeasurementTable.Row');
const { uid } = item;
return (
<DataRow
key={item.uid}
@@ -126,15 +112,15 @@ const Row = ({ item, index }: RowProps) => {
colorHex={item.colorHex}
isSelected={item.isSelected}
details={item.displayText}
onSelect={() => onClick(item.uid)}
onDelete={() => onDelete(item.uid)}
onDelete={e => onAction(e, 'removeMeasurement', uid)}
onSelect={e => onAction(e, 'jumpToMeasurement', uid)}
onRename={e => onAction(e, 'renameMeasurement', uid)}
onToggleVisibility={e => onAction(e, 'toggleVisibilityMeasurement', uid)}
onToggleLocked={e => onAction(e, 'toggleLockMeasurement', uid)}
disableEditing={disableEditing}
isExpanded={isExpanded}
isVisible={item.isVisible}
isLocked={item.isLocked}
onToggleVisibility={() => onToggleVisibility(item.uid)}
onToggleLocked={() => onToggleLocked(item.uid)}
onRename={() => onRename(item.uid)}
// onColor={() => onColor(item.uid)}
/>
);
};
@@ -14,7 +14,10 @@ interface StudySummaryProps {
*/
const StudySummary: React.FC<StudySummaryProps> = ({ date, description }) => {
return (
<div className="mx-2 my-0">
<div
className="mx-2 my-0"
style={{ textAlign: 'left' }}
>
<div className="text-foreground text-sm">{date}</div>
<div className="text-muted-foreground pb-1 text-sm">{description}</div>
</div>
+3 -4
View File
@@ -79,8 +79,8 @@ import {
} from './DropdownMenu';
import { Onboarding } from './Onboarding';
import { DoubleSlider } from './DoubleSlider';
import { DataRow } from './DataRow';
import { MeasurementTable } from './MeasurementTable';
export { DataRow } from './DataRow';
export { MeasurementTable } from './MeasurementTable';
import {
SegmentationTable,
useSegmentationTableContext,
@@ -90,6 +90,7 @@ import {
import { Toaster, toast } from './Sonner';
import { StudySummary } from './StudySummary';
import { ErrorBoundary } from './Errorboundary';
export * from './ColorCircle';
import { Header } from './Header';
import { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } from './Card';
import {
@@ -208,8 +209,6 @@ export {
TooltipTrigger,
TooltipContent,
TooltipProvider,
DataRow,
MeasurementTable,
Toaster,
toast,
SegmentationTable,
+3 -251
View File
@@ -1,254 +1,6 @@
import {
Button,
buttonVariants,
ThemeWrapper,
Dialog,
Command,
Popover,
Combobox,
Calendar,
DatePickerWithRange,
Separator,
Tabs,
TabsContent,
TabsList,
Clipboard,
TabsTrigger,
Toggle,
toggleVariants,
ToggleGroup,
ToggleGroupItem,
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
Icons,
SidePanel,
StudyItem,
StudyBrowser,
StudyBrowserSort,
StudyBrowserViewOptions,
Thumbnail,
ThumbnailList,
PanelSection,
DisplaySetMessageListTooltip,
ToolboxUI,
ToolSettings,
DoubleSlider,
Label,
Slider,
Input,
Switch,
Checkbox,
Onboarding,
PopoverAnchor,
PopoverContent,
PopoverTrigger,
ResizablePanelGroup,
ResizablePanel,
ResizableHandle,
Select,
SelectTrigger,
SelectContent,
SelectItem,
SelectValue,
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuCheckboxItem,
DropdownMenuRadioItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuGroup,
DropdownMenuPortal,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuRadioGroup,
Card,
CardHeader,
CardFooter,
CardTitle,
CardDescription,
CardContent,
ScrollArea,
MeasurementTable,
SegmentationTable,
useSegmentationTableContext,
useSegmentationExpanded,
useSegmentStatistics,
TooltipProvider,
Tooltip,
TooltipTrigger,
TooltipContent,
StudySummary,
ErrorBoundary,
Header,
ViewportActionButton,
PatientInfo,
ViewportActionBar,
ViewportActionArrows,
ViewportPane,
ViewportActionCorners,
ViewportActionCornersLocations,
ViewportOverlay,
ViewportGrid,
ToolButton,
ToolButtonList,
ToolButtonListDefault,
ToolButtonListDropDown,
ToolButtonListItem,
ToolButtonListDivider,
Numeric,
InputDialog,
PresetDialog,
Modal,
AboutModal,
ImageModal,
UserPreferencesModal,
FooterAction,
InputFilter,
} from './components';
import { DataRow } from './components/DataRow';
export * from './components';
export * from './contextProviders';
import {
useNotification,
NotificationProvider,
useModal,
ModalProvider,
DialogProvider,
useDialog,
ManagedDialog,
} from './contextProviders';
import { ViewportGridContext, ViewportGridProvider, useViewportGrid } from './contextProviders';
import * as utils from './utils';
export {
ErrorBoundary,
// components
Button,
Dialog,
Command,
Popover,
Combobox,
Checkbox,
DoubleSlider,
buttonVariants,
ThemeWrapper,
Calendar,
DatePickerWithRange,
Clipboard,
// contextProviders
NotificationProvider,
useNotification,
ViewportGridContext,
ViewportGridProvider,
useViewportGrid,
Separator,
Tabs,
TabsContent,
TabsList,
TabsTrigger,
Toggle,
toggleVariants,
ToggleGroup,
ToggleGroupItem,
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
Icons,
SidePanel,
StudyItem,
StudyBrowser,
StudyBrowserSort,
StudyBrowserViewOptions,
Thumbnail,
ThumbnailList,
PanelSection,
DisplaySetMessageListTooltip,
ToolboxUI,
Label,
Slider,
Input,
Switch,
Onboarding,
PopoverAnchor,
PopoverContent,
PopoverTrigger,
ResizablePanelGroup,
ResizablePanel,
ResizableHandle,
Select,
SelectTrigger,
SelectContent,
SelectItem,
SelectValue,
DataRow,
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuCheckboxItem,
DropdownMenuRadioItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuGroup,
DropdownMenuPortal,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuRadioGroup,
Card,
CardHeader,
CardFooter,
CardTitle,
CardDescription,
CardContent,
ScrollArea,
MeasurementTable,
SegmentationTable,
useSegmentationTableContext,
useSegmentationExpanded,
TooltipProvider,
Tooltip,
TooltipTrigger,
TooltipContent,
StudySummary,
Header,
ViewportActionButton,
PatientInfo,
ViewportActionBar,
ViewportActionArrows,
ViewportPane,
ViewportActionCorners,
ViewportActionCornersLocations,
ViewportOverlay,
ViewportGrid,
ToolButton,
ToolButtonList,
ToolButtonListDefault,
ToolButtonListDropDown,
ToolButtonListItem,
ToolButtonListDivider,
utils,
Numeric,
AboutModal,
ImageModal,
UserPreferencesModal,
InputDialog,
PresetDialog,
Modal,
useModal,
ModalProvider,
FooterAction,
DialogProvider,
useDialog,
ManagedDialog,
ToolSettings,
useSegmentStatistics,
InputFilter,
};
export { utils };