ui(components): New Dialog and Modal components for ui-next (#4772)

Co-authored-by: sedghi <ar.sedghi@gmail.com>
This commit is contained in:
Dan Rukasandsedghi authored and GitHub committed 2025-02-28 15:17:55 -05:00
1 parent 62b4fa3e89
commit a3b51aa8db
90 files changed
+3459 -1357

No files matched your search

@@ -10,21 +10,19 @@ export function VolumeRenderingPresets({
commandsManager,
volumeRenderingPresets,
}: VolumeRenderingPresetsProps): ReactElement {
const { uiModalService } = servicesManager.services;
const { uiDialogService } = servicesManager.services;
const onClickPresets = () => {
uiModalService.show({
uiDialogService.show({
id: 'volume-rendering-presets',
content: VolumeRenderingPresetsContent,
title: 'Rendering Presets',
movable: true,
isDraggable: true,
contentProps: {
onClose: uiModalService.hide,
presets: volumeRenderingPresets,
viewportId,
commandsManager,
},
containerDimensions: 'h-[543px] w-[460px]',
contentDimensions: 'h-[493px] w-[460px] pl-[12px] pr-[12px]',
});
};
@@ -1,29 +1,24 @@
import { ButtonEnums } from '@ohif/ui';
import { Icons } from '@ohif/ui-next';
import { Icons, FooterAction } from '@ohif/ui-next';
import React, { ReactElement, useState, useCallback } from 'react';
import { Button, InputFilterText } from '@ohif/ui';
import { PresetDialog } from '@ohif/ui-next';
import { ViewportPreset, VolumeRenderingPresetsContentProps } from '../../types/ViewportPresets';
interface Props extends VolumeRenderingPresetsContentProps {
hide: () => void;
}
export function VolumeRenderingPresetsContent({
presets,
viewportId,
commandsManager,
onClose,
}: VolumeRenderingPresetsContentProps): ReactElement {
const [filteredPresets, setFilteredPresets] = useState(presets);
hide,
}: Props): ReactElement {
const [searchValue, setSearchValue] = useState('');
const [selectedPreset, setSelectedPreset] = useState<ViewportPreset | null>(null);
const handleSearchChange = useCallback(
(value: string) => {
setSearchValue(value);
const filtered = value
? presets.filter(preset => preset.name.toLowerCase().includes(value.toLowerCase()))
: presets;
setFilteredPresets(filtered);
},
[presets]
);
const handleSearchChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
setSearchValue(event.target.value);
}, []);
const handleApply = useCallback(
props => {
@@ -34,62 +29,54 @@ export function VolumeRenderingPresetsContent({
[commandsManager]
);
const filteredPresets = searchValue
? presets.filter(preset => preset.name.toLowerCase().includes(searchValue.toLowerCase()))
: presets;
const formatLabel = (label: string, maxChars: number) => {
return label.length > maxChars ? `${label.slice(0, maxChars)}...` : label;
};
return (
<div className="flex min-h-full w-full flex-col justify-between">
<div className="border-secondary-light h-[433px] w-full overflow-hidden rounded border bg-black px-2.5">
<div className="flex h-[46px] w-full items-center justify-start">
<div className="h-[26px] w-[200px]">
<InputFilterText
value={searchValue}
onDebounceChange={handleSearchChange}
placeholder={'Search all'}
/>
</div>
</div>
<div className="ohif-scrollbar overflow h-[385px] w-full overflow-y-auto">
<div className="grid grid-cols-4 gap-3 pt-2 pr-3">
{filteredPresets.map((preset, index) => (
<div
key={index}
className="flex cursor-pointer flex-col items-start"
onClick={() => {
setSelectedPreset(preset);
handleApply({ preset: preset.name, viewportId });
}}
>
<Icons.ByName
name={preset.name}
className={
selectedPreset?.name === preset.name
? 'border-primary-light h-[75px] w-[95px] max-w-none rounded border-2'
: 'hover:border-primary-light h-[75px] w-[95px] max-w-none rounded border-2 border-black'
}
/>
<label className="text-aqua-pale mt-2 text-left text-xs">
{formatLabel(preset.name, 11)}
</label>
</div>
))}
</div>
</div>
</div>
<footer className="flex h-[60px] w-full items-center justify-end">
<div className="flex">
<Button
name="Cancel"
size={ButtonEnums.size.medium}
type={ButtonEnums.type.secondary}
onClick={onClose}
>
{' '}
Cancel{' '}
</Button>
</div>
</footer>
</div>
<PresetDialog className="h-[500px]">
<PresetDialog.PresetBody>
<PresetDialog.PresetFilter>
<PresetDialog.PresetSearch
value={searchValue}
onChange={handleSearchChange}
placeholder="Search all"
/>
</PresetDialog.PresetFilter>
<PresetDialog.PresetGrid>
{filteredPresets.map((preset, index) => (
<div
key={index}
className="flex cursor-pointer flex-col items-start"
onClick={() => {
setSelectedPreset(preset);
handleApply({ preset: preset.name, viewportId });
}}
>
<Icons.ByName
name={preset.name}
className={
selectedPreset?.name === preset.name
? 'border-highlight h-[75px] w-[95px] max-w-none rounded border-2'
: 'hover:border-highlight h-[75px] w-[95px] max-w-none rounded border-2 border-black'
}
/>
<label className="text-muted-foreground mt-1 text-left text-xs">
{formatLabel(preset.name, 11)}
</label>
</div>
))}
</PresetDialog.PresetGrid>
</PresetDialog.PresetBody>
<FooterAction className="mt-4 flex-shrink-0">
<FooterAction.Right>
<FooterAction.Secondary onClick={hide}>Cancel</FooterAction.Secondary>
</FooterAction.Right>
</FooterAction>
</PresetDialog>
);
}
@@ -21,8 +21,9 @@ export function getWindowLevelActionMenu({
const { volumeRenderingPresets, volumeRenderingQualityRange } =
customizationService.getCustomization('cornerstone.3dVolumeRendering');
const WindowLevelActionMenu = customizationService.getCustomization(
'cornerstone.windowLevelActionMenu'
'viewportActionMenu.windowLevelActionMenu'
);
console.debug('🚀 ~ WindowLevelActionMenu:', WindowLevelActionMenu);
const displaySetPresets = displaySets
.filter(displaySet => presets[displaySet.Modality])
.map(displaySet => {
@@ -37,8 +38,10 @@ export function getWindowLevelActionMenu({
return null;
}
const WindowLevelActionMenuComponent = WindowLevelActionMenu?.component;
return (
<WindowLevelActionMenu
<WindowLevelActionMenuComponent
viewportId={viewportId}
element={element}
presets={displaySetPresets}