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

@@ -0,0 +1,40 @@
import React from 'react';
import { AboutModal } from '@ohif/ui-next';
import detect from 'browser-detect';
function AboutModalDefault() {
const { os, version, name } = detect();
const browser = `${name[0].toUpperCase()}${name.substr(1)} ${version}`;
const versionNumber = process.env.VERSION_NUMBER;
const commitHash = process.env.COMMIT_HASH;
const [main, beta] = versionNumber.split('-');
return (
<AboutModal className="w-[400px]">
<AboutModal.ProductName>OHIF Viewer</AboutModal.ProductName>
<AboutModal.ProductVersion>{main}</AboutModal.ProductVersion>
{beta && <AboutModal.ProductBeta>{beta}</AboutModal.ProductBeta>}
<AboutModal.Body>
<AboutModal.DetailItem
label="Commit Hash"
value={commitHash}
/>
<AboutModal.DetailItem
label="Current Browser & OS"
value={`${browser}, ${os}`}
/>
<AboutModal.SocialItem
icon="SocialGithub"
url="OHIF/Viewers"
text="github.com/OHIF/Viewers"
/>
</AboutModal.Body>
</AboutModal>
);
}
export default {
'ohif.aboutModal': AboutModalDefault,
};
@@ -0,0 +1,91 @@
import React, { useState } from 'react';
import { InputDialog } from '@ohif/ui-next';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@ohif/ui-next';
type DataSource = {
value: string;
label: string;
placeHolder: string;
};
type ReportDialogProps = {
dataSources: DataSource[];
hide: () => void;
onSave: (data: { reportName: string; dataSource: string | null }) => void;
onCancel: () => void;
};
function ReportDialog({ dataSources, hide, onSave, onCancel }: ReportDialogProps) {
const [selectedDataSource, setSelectedDataSource] = useState<string | null>(
dataSources?.[0]?.value ?? null
);
const handleSave = (reportName: string) => {
onSave({
reportName,
dataSource: selectedDataSource,
});
hide();
};
const handleCancel = () => {
onCancel();
hide();
};
const showDataSourceSelect = dataSources?.length > 1;
return (
<div className="text-foreground mt-2 flex min-w-[400px] max-w-md flex-col gap-4">
<div className="flex flex-col gap-3">
<div className={showDataSourceSelect ? 'flex gap-4' : ''}>
{showDataSourceSelect && (
<div className="mt-1 w-1/3">
<Select
value={selectedDataSource}
onValueChange={setSelectedDataSource}
>
<SelectTrigger>
<SelectValue placeholder="Select a data source" />
</SelectTrigger>
<SelectContent>
{dataSources.map(source => (
<SelectItem
key={source.value}
value={source.value}
>
{source.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
)}
<div className={showDataSourceSelect ? 'mt-1 w-2/3' : 'w-full'}>
<InputDialog>
<InputDialog.Field>
<InputDialog.Input placeholder="Report name" />
</InputDialog.Field>
</InputDialog>
</div>
</div>
<div className="flex justify-end gap-2">
<InputDialog>
<InputDialog.Actions>
<InputDialog.ActionsSecondary onClick={handleCancel}>
Cancel
</InputDialog.ActionsSecondary>
<InputDialog.ActionsPrimary onClick={handleSave}>Save</InputDialog.ActionsPrimary>
</InputDialog.Actions>
</InputDialog>
</div>
</div>
</div>
);
}
export { ReportDialog };
export default {
'ohif.createReportDialog': ReportDialog,
};
@@ -0,0 +1,140 @@
import React, { useState } from 'react';
import { useSystem, hotkeys as hotkeysModule } from '@ohif/core';
import { UserPreferencesModal, FooterAction } from '@ohif/ui-next';
import { useTranslation } from 'react-i18next';
import i18n from '@ohif/i18n';
import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from '@ohif/ui-next';
const { availableLanguages, defaultLanguage, currentLanguage: currentLanguageFn } = i18n;
interface HotkeyDefinition {
keys: string;
label: string;
}
interface HotkeyDefinitions {
[key: string]: HotkeyDefinition;
}
function UserPreferencesModalDefault({ hide }: { hide: () => void }) {
const { hotkeysManager } = useSystem();
const { t } = useTranslation('UserPreferencesModal');
const { hotkeyDefinitions = {}, hotkeyDefaults = {} } = hotkeysManager;
const currentLanguage = currentLanguageFn();
const [state, setState] = useState({
hotkeyDefinitions: hotkeyDefinitions as HotkeyDefinitions,
languageValue: currentLanguage.value,
});
const onLanguageChangeHandler = (value: string) => {
setState(state => ({ ...state, languageValue: value }));
};
const onHotkeyChangeHandler = (id: string, newKeys: string) => {
setState(state => ({
...state,
hotkeyDefinitions: {
...state.hotkeyDefinitions,
[id]: {
...state.hotkeyDefinitions[id],
keys: newKeys,
},
},
}));
};
const onResetHandler = () => {
setState(state => ({
...state,
languageValue: defaultLanguage.value,
hotkeyDefinitions: hotkeyDefaults as HotkeyDefinitions,
}));
hotkeysManager.restoreDefaultBindings();
};
return (
<UserPreferencesModal>
<UserPreferencesModal.Body>
{/* Language Section */}
<div className="mb-3 flex items-center space-x-14">
<UserPreferencesModal.SubHeading>{t('Language')}</UserPreferencesModal.SubHeading>
<Select
defaultValue={state.languageValue}
onValueChange={onLanguageChangeHandler}
>
<SelectTrigger
className="w-60"
aria-label="Language"
>
<SelectValue placeholder={t('Select language')} />
</SelectTrigger>
<SelectContent>
{availableLanguages.map(lang => (
<SelectItem
key={lang.value}
value={lang.value}
>
{lang.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<UserPreferencesModal.SubHeading>{t('Hotkeys')}</UserPreferencesModal.SubHeading>
<UserPreferencesModal.HotkeysGrid>
{Object.entries(state.hotkeyDefinitions).map(([id, definition]) => (
<UserPreferencesModal.Hotkey
key={id}
label={t(definition.label)}
value={definition.keys}
onChange={newKeys => onHotkeyChangeHandler(id, newKeys)}
placeholder={definition.keys}
hotkeys={hotkeysModule}
/>
))}
</UserPreferencesModal.HotkeysGrid>
</UserPreferencesModal.Body>
<FooterAction>
<FooterAction.Left>
<FooterAction.Auxiliary onClick={onResetHandler}>
{t('Reset to defaults')}
</FooterAction.Auxiliary>
</FooterAction.Left>
<FooterAction.Right>
<FooterAction.Secondary
onClick={() => {
hotkeysModule.stopRecord();
hotkeysModule.unpause();
hide();
}}
>
{t('Cancel')}
</FooterAction.Secondary>
<FooterAction.Primary
onClick={() => {
if (state.languageValue !== currentLanguage.value) {
i18n.changeLanguage(state.languageValue);
}
hotkeysManager.setHotkeys(state.hotkeyDefinitions);
hotkeysModule.stopRecord();
hotkeysModule.unpause();
hide();
}}
>
{t('Save')}
</FooterAction.Primary>
</FooterAction.Right>
</FooterAction>
</UserPreferencesModal>
);
}
export default {
'ohif.userPreferencesModal': UserPreferencesModalDefault,
};