wip on switching from docz to docusaurus

This commit is contained in:
Erik Ziegler committed 2021-07-13 23:48:16 +02:00
1 parent 69e36106e3
commit 09469e6ac5
97 files changed
+1505 -7132

No files matched your search

@@ -0,0 +1,27 @@
---
name: AboutModal
menu: General
route: components/aboutModal
---
import { AboutModal } from '@ohif/ui';
# AboutModal
AboutModal are used to show application version information.
## Import
```javascript
import { AboutModal } from '@ohif/ui';
```
## Usage
```jsx live
<div className="p-4">
<AboutModal />
</div>
```
## Properties
@@ -0,0 +1,444 @@
---
name: Button
menu: General
route: components/button
---
import { Button, IconButton, Icon } from '@ohif/ui';
# Button
Buttons are used to execute actions when users interacts with them.
## Import
```javascript
import { Button } from '@ohif/ui';
```
## Outlined Buttons
````jsx live
<div className="p-4">
<Button variant="outlined" className="m-1">
Default
</Button>
<Button variant="outlined" color="primary" className="m-1">
Primary
</Button>
<Button variant="outlined" color="secondary" className="m-1">
Secondary
</Button>
<Button variant="outlined" color="white" className="m-1">
White
</Button>
</div>
```
## Contained Buttons
```jsx live
<div className="p-4">
<Button variant="contained" className="m-1">
Default
</Button>
<Button variant="contained" color="primary" className="m-1">
Primary
</Button>
<Button variant="contained" color="secondary" className="m-1">
Secondary
</Button>
<Button variant="contained" color="white" className="m-1">
White
</Button>
</div>
```
## Text Buttons
```jsx live
<div className="p-4">
<Button variant="text" className="m-1">
Default
</Button>
<Button variant="text" color="primary" className="m-1">
Primary
</Button>
<Button variant="text" color="secondary" className="m-1">
Secondary
</Button>
<Button variant="text" color="white" className="m-1">
White
</Button>
</div>
```
## Rounded Buttons
```jsx live
<div className="p-4">
<div className="mb-2">
<Button variant="contained" rounded="none" className="m-1">
Non Rounded
</Button>
<Button variant="contained" rounded="small" className="m-1">
Small Rounded
</Button>
<Button variant="contained" rounded="medium" className="m-1">
Medium Rounded
</Button>
<Button variant="contained" rounded="large" className="m-1">
Large Rounded
</Button>
<Button variant="contained" rounded="full" className="m-1">
Full Rounded
</Button>
</div>
<div className="mb-2">
<Button
variant="contained"
rounded="none"
color="primary"
className="m-1"
>
Non Rounded
</Button>
<Button
variant="contained"
rounded="small"
color="primary"
className="m-1"
>
Small Rounded
</Button>
<Button
variant="contained"
rounded="medium"
color="primary"
className="m-1"
>
Medium Rounded
</Button>
<Button
variant="contained"
rounded="large"
color="primary"
className="m-1"
>
Large Rounded
</Button>
<Button
variant="contained"
rounded="full"
color="primary"
className="m-1"
>
Full Rounded
</Button>
</div>
<div className="mb-2">
<Button
variant="contained"
rounded="none"
color="secondary"
className="m-1"
>
Non Rounded
</Button>
<Button
variant="contained"
rounded="small"
color="secondary"
className="m-1"
>
Small Rounded
</Button>
<Button
variant="contained"
rounded="medium"
color="secondary"
className="m-1"
>
Medium Rounded
</Button>
<Button
variant="contained"
rounded="large"
color="secondary"
className="m-1"
>
Large Rounded
</Button>
<Button
variant="contained"
rounded="full"
color="secondary"
className="m-1"
>
Full Rounded
</Button>
</div>
<div className="mb-2">
<Button variant="contained" rounded="none" color="white" className="m-1">
Non Rounded
</Button>
<Button variant="contained" rounded="small" color="white" className="m-1">
Small Rounded
</Button>
<Button
variant="contained"
rounded="medium"
color="white"
className="m-1"
>
Medium Rounded
</Button>
<Button variant="contained" rounded="large" color="white" className="m-1">
Large Rounded
</Button>
<Button variant="contained" rounded="full" color="white" className="m-1">
Full Rounded
</Button>
</div>
</div>
```
## Sizes
```jsx live
<div className="p-4">
<div>
<Button variant="contained" size="small" className="m-1">
Small
</Button>
<Button variant="contained" size="medium" className="m-1">
Medium
</Button>
<Button variant="contained" size="large" className="m-1">
Large
</Button>
</div>
<div>
<Button
variant="contained"
size="small"
color="primary"
className="m-1"
>
Small
</Button>
<Button
variant="contained"
size="medium"
color="primary"
className="m-1"
>
Medium
</Button>
<Button
variant="contained"
size="large"
color="primary"
className="m-1"
>
Large
</Button>
</div>
<div>
<Button
variant="contained"
size="small"
color="secondary"
className="m-1"
>
Small
</Button>
<Button
variant="contained"
size="medium"
color="secondary"
className="m-1"
>
Medium
</Button>
<Button
variant="contained"
size="large"
color="secondary"
className="m-1"
>
Large
</Button>
</div>
<div>
<Button
variant="contained"
size="small"
color="white"
className="m-1"
>
Small
</Button>
<Button
variant="contained"
size="medium"
color="white"
className="m-1"
>
Medium
</Button>
<Button
variant="contained"
size="large"
color="white"
className="m-1"
>
Large
</Button>
</div>
</div>
```
## Buttons with icons
```jsx live
<div className="p-4 flex">
<Button
variant="contained"
color="primary"
className="m-1"
startIcon={<Icon name="settings" />}
>
Settings
</Button>
<Button
variant="contained"
color="primary"
className="m-1"
endIcon={<Icon name="settings" />}
>
Download
</Button>
<Button
variant="outlined"
rounded="full"
color="default"
className="m-1"
endIcon={<Icon name="settings" />}
>
Download
</Button>
</div>
```
## Icon Buttons
Icon buttons are generally used in toolbars.
```javascript
import { IconButton } from '@ohif/ui';
````
````jsx live
<div className="p-4 flex flex-col items-center">
<div className="">
<IconButton className="m-2">
<Icon name="settings" />
</IconButton>
<IconButton className="m-2" variant="text">
<Icon name="settings" />
</IconButton>
<IconButton className="m-2" variant="outlined">
<Icon name="settings" />
</IconButton>
</div>
<div>
<IconButton className="m-2" color="primary">
<Icon name="launch-arrow" />
</IconButton>
<IconButton className="m-2" color="primary" variant="text">
<Icon name="launch-arrow" />
</IconButton>
<IconButton className="m-2" color="primary" variant="outlined">
<Icon name="launch-arrow" />
</IconButton>
</div>
<div>
<IconButton className="m-2" color="secondary">
<Icon name="cancel" />
</IconButton>
<IconButton className="m-2" color="secondary" variant="text">
<Icon name="cancel" />
</IconButton>
<IconButton className="m-2" color="secondary" variant="outlined">
<Icon name="cancel" />
</IconButton>
</div>
<div>
<IconButton className="m-2" color="white">
<Icon name="settings" />
</IconButton>
<IconButton className="m-2" variant="text" color="white">
<Icon name="launch-arrow" />
</IconButton>
<IconButton className="m-2" variant="outlined" color="white">
<Icon name="cancel" />
</IconButton>
</div>
</div>
```
```jsx live
<div className="p-4">
<div className="">
<IconButton className="m-2">
<Icon name="settings" />
</IconButton>
<IconButton className="m-2" variant="outlined">
<Icon name="settings" />
</IconButton>
<IconButton className="m-2" variant="text">
<Icon name="settings" />
</IconButton>
</div>
<div>
<IconButton className="m-2" color="primary">
<Icon name="launch-arrow" />
</IconButton>
<IconButton className="m-2" color="primary" variant="text">
<Icon name="launch-arrow" />
</IconButton>
<IconButton className="m-2" color="primary" variant="outlined">
<Icon name="launch-arrow" />
</IconButton>
</div>
<div>
<IconButton className="m-2" color="secondary">
<Icon name="cancel" />
</IconButton>
<IconButton className="m-2" color="secondary" variant="text">
<Icon name="cancel" />
</IconButton>
<IconButton className="m-2" color="secondary" variant="outlined">
<Icon name="cancel" />
</IconButton>
</div>
<div>
<IconButton className="m-2" color="white">
<Icon name="settings" />
</IconButton>
<IconButton className="m-2" variant="text" color="white">
<Icon name="launch-arrow" />
</IconButton>
<IconButton className="m-2" variant="outlined" color="white">
<Icon name="cancel" />
</IconButton>
</div>
</div>
```
## Properties
<Props of={Button} />
````
@@ -0,0 +1,111 @@
---
name: ButtonGroup
menu: General
route: components/buttonGroup
---
import { ButtonGroup, Button, IconButton, Icon } from '@ohif/ui';
# ButtonGroup
Group Button display buttons together sharing its configurations
## Import
```javascript
import { ButtonGroup } from '@ohif/ui';
```
## Basic button group
````jsx live
<div className="p-4 flex flex-col items-center">
<ButtonGroup color="primary" className="m-2">
<Button>One</Button>
<Button>Two</Button>
<Button>Tree</Button>
</ButtonGroup>
<ButtonGroup color="primary" variant="contained" className="m-2">
<Button>One</Button>
<Button>Two</Button>
<Button>Tree</Button>
</ButtonGroup>
<ButtonGroup color="primary" variant="text" className="m-2">
<Button>One</Button>
<Button>Two</Button>
<Button>Tree</Button>
</ButtonGroup>
</div>
```
## Group sizes and colorss
```jsx live
<div className="p-4 flex flex-col items-center">
<ButtonGroup color="default" size="small" className="m-2">
<Button>One</Button>
<Button>Two</Button>
<Button>Tree</Button>
</ButtonGroup>
<ButtonGroup color="primary" size="medium" className="m-2">
<Button>One</Button>
<Button>Two</Button>
<Button>Tree</Button>
</ButtonGroup>
<ButtonGroup color="secondary" size="large" className="m-2">
<Button>One</Button>
<Button>Two</Button>
<Button>Tree</Button>
</ButtonGroup>
</div>
```
## Group orientation
```jsx live
<div className="p-4 flex flex-row justify-center">
<ButtonGroup orientation="vertical" color="primary" className="m-2">
<Button>One</Button>
<Button>Two</Button>
<Button>Tree</Button>
</ButtonGroup>
<ButtonGroup
orientation="vertical"
color="primary"
variant="contained"
className="m-2"
>
<Button>One</Button>
<Button>Two</Button>
<Button>Tree</Button>
</ButtonGroup>
<ButtonGroup
orientation="vertical"
color="primary"
variant="text"
className="m-2"
>
<Button>One</Button>
<Button>Two</Button>
<Button>Tree</Button>
</ButtonGroup>
</div>
```
## Split Button
```jsx live
<div className="p-4 flex flex-col items-center">
<ButtonGroup color="primary" className="m-2">
<Button>Options</Button>
<IconButton className="mr-2">
<Icon name="settings" />
</IconButton>
</ButtonGroup>
</div>
```
## Properties
<Props of={ButtonGroup} />
````
@@ -0,0 +1,44 @@
---
name: CinePlayer
menu: General
route: components/CinePlayer
---
import { useState } from 'react';
import { CinePlayer } from '@ohif/ui';
# Input Text
## Import
```javascript
import { CinePlayer } from '@ohif/ui';
```
## Basic usage
```jsx live
{
() => {
return (
<div className="flex flex-col flex-1 p-4 items-center">
<div className="w-56">
<CinePlayer
cineMinFrameRate={1}
cineMaxFrameRate={90}
cineStepFrameRate={1}
cineFrameRate={24}
isPlaying={false}
/>
</div>
</div>
);
};
}
```
## Properties
<Props of={CinePlayer} />
```
@@ -0,0 +1,51 @@
---
name: Context Menu
menu: General
route: components/contextMenu
---
import { ContextMenu } from '@ohif/ui';
# Context Menu
...
## Import
```javascript
import { ContextMenu } from '@ohif/ui';
```
```jsx live
{
() => {
const items = [
{
label: 'Delete measurement',
actionType: 'Delete',
action: () => alert('Delete'),
},
{
label: 'Relabel',
actionType: 'setLabel',
action: () => alert('Relabel'),
},
{
label: 'Add Description',
actionType: 'setDescription',
action: () => alert('Add Description'),
},
];
return (
<div className="p-4">
<ContextMenu items={items} />
</div>
);
};
}
```
## Properties
<Props of={ContextMenu} />
```
@@ -0,0 +1,48 @@
---
name: Date Range
menu: Form
route: components/date-range
---
import { useState } from 'react';
import { DateRange } from '@ohif/ui';
# Date Range
Date Range is used to select a range of dates.
## Import
```javascript
import { DateRange } from '@ohif/ui';
```
## Date Range
```jsx live
{
() => {
const [dates, setDates] = useState({
startDate: null,
endDate: null,
});
return (
<div className="p-4 flex flex-col items-center">
<DateRange
startDate={dates.startDate}
endDate={dates.endDate}
onChange={({ startDate, endDate }) =>
setDates({ startDate, endDate })
}
/>
</div>
);
};
}
```
## Properties
<Props of={DateRange} />
```
@@ -0,0 +1,70 @@
---
name: Dropdown
menu: General
route: components/dropdown
---
import { Dropdown, IconButton, Icon } from '@ohif/ui';
# Dropdown
This component is used when there are more than a few options to choose from. By
hovering or clicking on the trigger, a dropdown menu will appear, which allows
you to choose an option and execute the relevant action.
## Import
```javascript
import { Dropdown } from '@ohif/ui';
```
```jsx live
{
() => {
const handleClick = () => {
alert('Clicked');
};
return (
<div className="py-4">
<Dropdown
showDropdownIcon={false}
list={[
{
title: 'Option 1',
icon: 'info',
onClick: handleClick,
},
{
title: 'Option 2',
icon: 'settings',
onClick: handleClick,
},
]}
>
<IconButton
variant="text"
color="inherit"
size="initial"
className="text-primary-active"
>
<Icon name="settings" />
</IconButton>
<IconButton
variant="text"
color="inherit"
size="initial"
className="text-primary-active"
>
<Icon name="chevron-down" />
</IconButton>
</Dropdown>
</div>
);
};
}
```
## Properties
<Props of={Dropdown} />
```
@@ -0,0 +1,30 @@
---
name: Empty Studies
menu: Data Display
route: components/empty-studies
---
import { EmptyStudies } from '@ohif/ui';
# Empty Studies
This component can be used to display a message when there are no studies.
## Import
```javascript
import { EmptyStudies } from '@ohif/ui';
```
## Basic usage
```jsx live
<div className="p-4">
<EmptyStudies />
</div>
```
## Properties
<Props of={EmptyStudies} />
```
@@ -0,0 +1,59 @@
---
name: Error Boundary
menu: Data Display
route: components/errorBoundary
---
import { ErrorBoundary } from '@ohif/ui';
# Error Boundary
This component can be used to display a message or handle unhandled errors.
## Import
```javascript
import { ErrorBoundary } from '@ohif/ui';
```
## Basic usage
````jsx live
<div className="p-4">
<ErrorBoundary context="Somewhere">
{() => {
throw new Error('Error!');
return <p></p>;
}}
</ErrorBoundary>
</div>
```
## Custom error fallback
```jsx live
{() => {
const CustomFallback = ({ error, componentStack, resetErrorBoundary }) => {
return (
<div>
<p>This is a custom fallback!</p>
</div>
);
};
return (
<div className="p-4">
<ErrorBoundary context="Somewhere" fallbackComponent={CustomFallback}>
{() => {
throw new Error('Error!');
return <p></p>;
}}
</ErrorBoundary>
</div>
);
}}
```
## Properties
<Props of={ErrorBoundary} />
````
@@ -0,0 +1,90 @@
---
name: Expandable Toolbar Button
menu: General
route: components/expandableToolbarButton
---
import { useState } from 'react';
import { ExpandableToolbarButton, ListMenu } from '@ohif/ui';
# Toolbar Button
Expandable Toolbar Buttons are used to populate the Toolbar.
## Import
```javascript
import { ExpandableToolbarButton, ListMenu } from '@ohif/ui';
```
```jsx live
{
() => {
const props = {
content: ListMenu,
contentProps: {
options: [
{
value: 'windowLevelPreset1',
title: 'Soft tissue',
subtitle: '400 / 40',
},
{
value: 'windowLevelPreset2',
title: 'Lung',
subtitle: '1500 / -600',
},
{ value: 'windowLevelPreset3', title: 'Liver', subtitle: '150 / 90' },
{ value: 'windowLevelPreset4', title: 'Bone', subtitle: '80 / 40' },
{
value: 'windowLevelPreset5',
title: 'Brain',
subtitle: '2500 / 480',
},
],
renderer: ({ title, subtitle, isActive, index }) => (
<>
<div>
<span
className={classnames(
isActive ? 'text-black' : 'text-white',
'mr-2 text-base'
)}
>
{title}
</span>
<span
className={classnames(
isActive ? 'text-black' : 'text-aqua-pale',
'font-thin text-sm'
)}
>
{subtitle}
</span>
</div>
<span
className={classnames(
isActive ? 'text-black' : 'text-primary-active',
'text-sm'
)}
>
{index + 1}
</span>
</>
),
},
};
return (
<div className="py-10 flex justify-center">
<ExpandableToolbarButton {...props} />
</div>
);
};
}
```
## Properties
<Props of={ExpandableToolbarButton} />
```
@@ -0,0 +1,41 @@
---
name: Input
menu: Form
route: components/input
---
import { Input } from '@ohif/ui';
# Input
## Import
```javascript
import { Input } from '@ohif/ui';
```
## Basic usage
```jsx live
{
() => {
const [inputValue, setInputValue] = React.useState('');
return (
<div className="p-4">
<Input
transparent
containerClassName="mb-3"
label="Label"
placeholder="With Label"
/>
<Input placeholder="Without label" />
</div>
);
};
}
```
## Properties
<Props of={Input} />
```
@@ -0,0 +1,46 @@
---
name: InputDateRange
menu: Form
route: components/InputDateRange
---
import { useState } from 'react';
import { InputDateRange } from '@ohif/ui';
# Input Date Range
## Import
```javascript
import { InputDateRange } from '@ohif/ui';
```
## Basic usage
```jsx live
{
() => {
const [dates, setDates] = useState({
startDate: null,
endDate: null,
});
return (
<div className="p-4 flex flex-col items-center">
<div className="w-56">
<InputDateRange
label="Dates"
value={dates}
onChange={dates => setDates(dates)}
/>
</div>
</div>
);
};
}
```
## Properties
<Props of={InputDateRange} />
```
@@ -0,0 +1,93 @@
---
name: InputGroup
menu: Form
route: components/InputGroup
---
import { useState } from 'react';
import { InputGroup } from '@ohif/ui';
# Input Group
## Import
```javascript
import { InputGroup } from '@ohif/ui';
```
## Basic usage
```jsx live
{
() => {
const [filterValues, setFilterValues] = useState({
patient: '',
studyDate: {
startDate: null,
endDate: null,
},
modality: [],
});
const [filterSorting, setFilterSorting] = useState({
sortBy: '',
sortDirection: 'none',
});
const filtersMeta = [
{
name: 'patient',
displayName: 'Patient Name',
inputType: 'Text',
isSortable: true,
gridCol: 6,
},
{
name: 'studyDate',
displayName: 'Study date',
inputType: 'DateRange',
isSortable: true,
gridCol: 6,
},
{
name: 'modality',
displayName: 'Modality',
inputType: 'MultiSelect',
inputProps: {
options: [
{ value: 'SEG', label: 'SEG' },
{ value: 'CT', label: 'CT' },
{ value: 'MR', label: 'MR' },
{ value: 'SR', label: 'SR' },
],
},
isSortable: true,
gridCol: 6,
},
{
name: 'numberOfInstance',
displayName: 'Number of Instances',
inputType: 'None',
isSortable: true,
gridCol: 6,
},
];
return (
<div className="py-4">
<InputGroup
inputMeta={filtersMeta}
values={filterValues}
onValuesChange={setFilterValues}
sorting={filterSorting}
onSortingChange={setFilterSorting}
isSortingEnable={true}
/>
</div>
);
};
}
```
## Properties
<Props of={InputGroup} />
```
@@ -0,0 +1,51 @@
---
name: InputMultiSelect
menu: Form
route: components/InputMultiSelect
---
import { useState } from 'react';
import { InputMultiSelect } from '@ohif/ui';
# Input Multi Select
## Import
```javascript
import { InputMultiSelect } from '@ohif/ui';
```
## Basic usage
```jsx live
{
() => {
const [values, setValues] = useState([]);
return (
<div className="flex flex-col flex-1 p-4 items-center">
<div className="w-56">
<InputMultiSelect
label="Modality"
options={[
{ value: 'SEG', label: 'SEG' },
{ value: 'CT', label: 'CT' },
{ value: 'MR', label: 'MR' },
{ value: 'SR', label: 'SR' },
]}
value={values}
onChange={values => {
setValues(values);
}}
/>
</div>
</div>
);
};
}
```
## Properties
<Props of={InputMultiSelect} />
```
@@ -0,0 +1,45 @@
---
name: InputText
menu: Form
route: components/InputText
---
import { useState } from 'react';
import { InputText } from '@ohif/ui';
# Input Text
## Import
```javascript
import { InputText } from '@ohif/ui';
```
## Basic usage
```jsx live
{
() => {
const [text, setText] = useState('');
return (
<div className="flex flex-col flex-1 p-4 items-center">
<div className="w-56">
<InputText
label="Name"
value={text}
onChange={value => {
setText(value);
}}
/>
</div>
</div>
);
};
}
```
## Properties
<Props of={InputText} />
```
@@ -0,0 +1,34 @@
---
name: Label
menu: Form
route: components/label
---
import { Label } from '@ohif/ui';
# Label
## Import
```javascript
import { Label } from '@ohif/ui';
```
## Basic usage
```jsx live
{
() => {
return (
<div className="p-4">
<Label text="Label" />
</div>
);
};
}
```
## Properties
<Props of={Label} />
```
@@ -0,0 +1,84 @@
---
name: List Menu
menu: General
route: components/listMenu
---
import { useState } from 'react';
import { ListMenu, ToolbarButton } from '@ohif/ui';
# List Menu
List Menus are used to populate expandable Toolbar.
## Import
```javascript
import { ListMenu, ToolbarButton } from '@ohif/ui';
```
```jsx live
{
() => {
return (
<ToolbarButton
items={[
{
value: 'windowLevelPreset1',
title: 'Soft tissue',
subtitle: '400 / 40',
},
{
value: 'windowLevelPreset2',
title: 'Lung',
subtitle: '1500 / -600',
},
{ value: 'windowLevelPreset3', title: 'Liver', subtitle: '150 / 90' },
{ value: 'windowLevelPreset4', title: 'Bone', subtitle: '80 / 40' },
{
value: 'windowLevelPreset5',
title: 'Brain',
subtitle: '2500 / 480',
},
]}
renderer={({ title, subtitle, isActive, index }) => (
<>
<div>
<span
className={classnames(
isActive ? 'text-black' : 'text-white',
'mr-2 text-base'
)}
>
{title}
</span>
<span
className={classnames(
isActive ? 'text-black' : 'text-aqua-pale',
'font-thin text-sm'
)}
>
{subtitle}
</span>
</div>
<span
className={classnames(
isActive ? 'text-black' : 'text-primary-active',
'text-sm'
)}
>
{index + 1}
</span>
</>
)}
/>
);
};
}
```
## Properties
<Props of={ListMenu} />
```
@@ -0,0 +1,59 @@
---
name: Measurement Table
menu: Data Display
route: components/measurementTable
---
import { useState } from 'react';
import { MeasurementTable } from '@ohif/ui';
# Measurement Table
## Import
```javascript
import { MeasurementTable } from '@ohif/ui';
```
## Basic usage
````jsx live
{() => {
const [activeMeasurementItem, setActiveMeasurementItem] = useState(null);
const measurementTableData = {
title: 'Measurements',
amount: 10,
data: new Array(10).fill({}).map((el, i) => ({
id: i + 1,
label: 'Label short description',
displayText: ['24.0 x 24.0 mm (S:4, I:22)'],
isActive: activeMeasurementItem === i + 1,
})),
onClick: id => setActiveMeasurementItem(s => (s === id ? null : id)),
onEdit: id => alert(`Edit: ${id}`),
};
return (
<div className="p-4 w-80">
<MeasurementTable {...measurementTableData} />
</div>
);
}}
```
## Empty Data
```jsx live
{() => {
return (
<div className="p-4 w-80">
<MeasurementTable title="Measurements" />
</div>
);
}}
```
## Properties
<Props of={MeasurementTable} />
````
@@ -0,0 +1,30 @@
---
name: NavBar
menu: Navigation
route: components/navBar
---
import { NavBar, Typography } from '@ohif/ui';
# NavBar
## Import
```javascript
import { NavBar } from '@ohif/ui';
```
## Basic usage
```jsx live
<NavBar className="justify-center">
<Typography variant="h3" className="m-2">
Header content
</Typography>
</NavBar>
```
## Properties
<Props of={NavBar} />
```
@@ -0,0 +1,60 @@
---
name: Notification
menu: Feedback
route: components/notification
---
import { Notification } from '@ohif/ui';
# Notification
A notification displays a short message in a way that attracts the user's
attention without interrupting the user's task.
## Import
```javascript
import { Notification } from '@ohif/ui';
```
## Basic usage
```jsx live
{
() => {
return (
<div className="p-4 w-full lg:w-2/3">
<Notification
message="Track all measurement for this series?"
type="info"
actions={[
{
type: 'cancel',
text: 'No',
value: 0,
},
{
type: 'secondary',
text: 'No, do not ask again',
value: -1,
},
{
type: 'primary',
text: 'Yes',
value: 1,
},
]}
onSubmit={value => {
window.alert(value);
}}
/>
</div>
);
};
}
```
## Properties
<Props of={Notification} />
```
@@ -0,0 +1,39 @@
---
name: Segmentation Table
menu: Data Display
route: components/segmentationTable
---
import { SegmentationTable } from '@ohif/ui';
# Segmentation Table
## Import
```javascript
import { SegmentationTable } from '@ohif/ui';
```
## Basic usage
```jsx live
{
() => {
const tableData = {
title: 'Segments',
amount: 12,
data: new Array(12).fill(''),
};
return (
<div className="p-4 w-80">
<SegmentationTable {...tableData} />
</div>
);
};
}
```
## Properties
<Props of={SegmentationTable} />
```
@@ -0,0 +1,70 @@
---
name: Select
menu: Form
route: components/select
---
import { Select } from '@ohif/ui';
# Select
## Import
```javascript
import { Select } from '@ohif/ui';
```
## Basic usage
````jsx live
<div className="flex flex-col flex-1 p-4 items-center">
<div className="w-56">
<Select
options={[
{ value: 'ONE', label: 'ONE' },
{ value: 'TWO', label: 'TWO' },
{ value: 'THREE', label: 'THREE' },
{ value: 'FOUR', label: 'FOUR' },
]}
/>
</div>
</div>
```
## Disabled
```jsx live
<div className="flex flex-col flex-1 p-4 items-center">
<div className="w-56">
<Select
isDisabled
options={[
{ value: 'ONE', label: 'ONE' },
{ value: 'TWO', label: 'TWO' },
{ value: 'THREE', label: 'THREE' },
{ value: 'FOUR', label: 'FOUR' },
]}
/>
</div>
</div>
```
## No Options
```jsx live
<div className="flex flex-col flex-1 p-4 items-center">
<div className="w-56">
<Select
noOptionsMessage={() => {
'No Options';
}}
options={[]}
/>
</div>
</div>
```
## Properties
<Props of={Select} />
````
@@ -0,0 +1,75 @@
---
name: SidePanel
menu: General
route: components/sidePanel
---
import { SidePanel } from '@ohif/ui';
# SidePanel
## Import
```javascript
import { SidePanel } from '@ohif/ui';
```
## Basic usage
````jsx live
<div
className="flex flex-row flex-no-wrap flex-1 items-stretch overflow-hidden w-full"
style={{ height: '500px' }}
>
<SidePanel
side="left"
childComponents={{
iconName: "group-layers",
iconLabel: "Studies",
name: "studies",
label: "Studies",
content: <div className="flex justify-center text-white p-2">panel content</div>,
}}
/>
<div className="flex flex-1 h-100 overflow-hidden bg-primary-main items-center justify-center text-white">
CONTENT
</div>
</div>
```
## Multiple panels
```jsx live
<div
className="flex flex-row flex-no-wrap flex-1 items-stretch overflow-hidden w-full"
style={{ height: '500px' }}
>
<SidePanel
side="left"
childComponents={[{
iconName: "group-layers",
iconLabel: "Studies",
name: "studies",
label: "Studies",
content: <div className="flex justify-center text-white p-2">studies panel content</div>,
},
{
iconName: "list-bullets",
iconLabel: "Measure",
name: "measurements",
label: "Measurements",
content: <div className="flex justify-center text-white p-2">measure panel content</div>,
}]}
/>
<div className="flex flex-1 h-100 overflow-hidden bg-primary-main items-center justify-center text-white">
CONTENT
</div>
</div>
```
## Properties
<Props of={SidePanel} />
````
@@ -0,0 +1,90 @@
---
name: Split Button
menu: General
route: components/splitButton
---
import { useState } from 'react';
import { SplitButton, WindowLevelMenuItem } from '@ohif/ui';
# Split Button
Split Buttons are used to populate the Toolbar.
## Import
```javascript
import { SplitButton, WindowLevelMenuItem } from '@ohif/ui';
```
```jsx live
{
() => {
const mockedProps = {
bState: {
primaryToolId: 'WWWC',
toggles: {},
},
primary: {
tooltip: 'W/L',
type: 'tool',
icon: 'tool-window-level',
onClick: args => console.debug('Primary click!', args),
},
secondary: {
icon: 'chevron-down',
label: '',
isActive: true,
tooltip: 'More Measure Tools',
},
items: [
{
id: '1',
icon: 'tool-layout',
label: 'Layout',
onClick: args => console.debug('Item click!', args),
},
{
id: '2',
icon: 'tool-window-level',
label: 'W/L',
onClick: args => console.debug('Item click!', args),
},
{
id: '3',
icon: 'tool-length',
label: 'Length',
onClick: args => console.debug('Item click!', args),
},
],
onClick: args => console.debug('Any click!', args),
};
return (
<div className="mb-2">
<div className="flex flex-row w-full justify-center items-center bg-secondary-dark">
<SplitButton {...mockedProps} isRadio />
<SplitButton
{...mockedProps}
isAction
renderer={WindowLevelMenuItem}
items={[
{ id: '1', value: 1, title: 'Soft tissue', subtitle: '400 / 40' },
{ id: '2', value: 2, title: 'Lung', subtitle: '1500 / -600' },
{ id: '3', value: 3, title: 'Liver', subtitle: '150 / 90' },
{ id: '4', value: 4, title: 'Bone', subtitle: '80 / 40' },
{ id: '5', value: 5, title: 'Brain', subtitle: '2500 / 480' },
]}
/>
<SplitButton {...mockedProps} />
</div>
</div>
);
};
}
```
## Properties
<Props of={SplitButton} />
```
@@ -0,0 +1,113 @@
---
name: StudyBrowser
menu: General
route: components/studyBrowser
---
import { StudyBrowser } from '@ohif/ui';
# StudyBrowser
## Import
```javascript
import { StudyBrowser } from '@ohif/ui';
```
## Basic usage
```jsx live
{
() => {
const studyWithSR = {
studyInstanceUid: '1',
date: '07-Sept-2010',
description: 'CHEST/ABD/PELVIS W/CONTRAST',
numInstances: 902,
modalities: 'CT,SR',
displaySets: [
{
displaySetInstanceUID: 'f69f6asdasd48c-223e-db7f-c4af-b8906641a66e',
description: 'Multiple line image series description lorem sit',
seriesNumber: 1,
numInstances: 68,
componentType: 'thumbnailTracked',
viewportIdentificator: 'A',
isTracked: true,
},
{
displaySetInstanceUID: 'f69f648c-223e-db7f-c4asdasdaf-b8906641a66e',
description: 'Multiple line image series description lorem sit',
seriesNumber: 1,
numInstances: 68,
componentType: 'thumbnailTracked',
viewportIdentificator: 'B',
},
{
displaySetInstanceUID: 'f69f648c-223e-dasdasdb7f-c4af-b8906641a66e',
description: 'Multiple line image series description lorem sit',
seriesNumber: 1,
numInstances: 68,
componentType: 'thumbnailTracked',
},
{
displaySetInstanceUID: 'f69f648c-223e-db7f-c4afas-b8906asd641a66e',
description: 'Multiple line description lorem ipsum dolor sit amet',
modality: 'SR',
componentType: 'thumbnailNoImage',
seriesDate: '07-Sept-2010',
},
],
};
const studySimple = {
studyInstanceUid: '2',
date: '07-Sept-2010',
description: 'CHEST/ABD/PELVIS W/CONTRAST',
numInstances: 902,
modalities: 'CT',
displaySets: [
{
displaySetInstanceUID: 'f69f648c-223e-db7f-c4af-b8906641a66e',
description: 'Multiple line image series description lorem sit',
seriesNumber: 1,
numInstances: 68,
componentType: 'thumbnailTracked',
},
],
};
const tabs = [
{
name: 'primary',
label: 'Primary',
studies: [studySimple],
},
{
name: 'recent',
label: 'Recent',
studies: [studyWithSR, studySimple],
},
{
name: 'all',
label: 'All',
studies: [studySimple, studyWithSR],
},
];
return (
<div className="flex flex-1" style={{ height: '400px' }}>
<div className="overflow-hidden w-64">
<StudyBrowser
tabs={tabs}
activeTabName="primary"
expandedStudyInstanceUIDs={[]}
/>
</div>
</div>
);
};
}
```
## Properties
<Props of={StudyBrowser} />
```
@@ -0,0 +1,49 @@
---
name: StudyItem
menu: General
route: components/studyItem
---
import { useState } from 'react';
import { StudyItem } from '@ohif/ui';
# StudyItem
Used to expose study information as a card
## Import
```javascript
import { StudyItem } from '@ohif/ui';
```
## Basic usage
```jsx live
{
() => {
const [studyActive, setStudyActive] = useState(null);
return (
<div className="flex flex-1 items-center justify-center p-4">
<div className="w-56">
<StudyItem
studyInstanceUid="1"
date="07-Sept-2010"
description="CHEST/ABD/PELVIS W/CONTRAST"
numInstances={902}
modalities="CT,SR"
isActive={studyActive}
onClick={() => setStudyActive(studyActive === '1' ? null : '1')}
/>
</div>
</div>
);
};
}
```
## Properties
<Props of={StudyItem} />
```
@@ -0,0 +1,124 @@
---
name: Study List Filter
menu: Data Display
route: components/studyListFilter
---
import { useState } from 'react';
import { StudyListFilter, Modal } from '@ohif/ui';
import { ModalProvider } from '@ohif/ui';
# Study List Filter
## Import
```javascript
import { StudyListFilter, ModalProvider, Modal } from '@ohif/ui';
```
## Basic usage
```jsx live
{
() => {
const defaultFilterValues = {
patientName: '',
mrn: '',
studyDate: {
startDate: null,
endDate: null,
},
description: '',
modality: undefined,
accession: '',
sortBy: '',
sortDirection: 'none',
page: 0,
resultsPerPage: 25,
};
const [filterValues, setFilterValues] = useState(defaultFilterValues);
const filtersMeta = [
{
name: 'patientName',
displayName: 'Patient Name',
inputType: 'Text',
isSortable: true,
gridCol: 4,
},
{
name: 'mrn',
displayName: 'MRN',
inputType: 'Text',
isSortable: true,
gridCol: 2,
},
{
name: 'studyDate',
displayName: 'Study date',
inputType: 'DateRange',
isSortable: true,
gridCol: 5,
},
{
name: 'description',
displayName: 'Description',
inputType: 'Text',
isSortable: true,
gridCol: 4,
},
{
name: 'modality',
displayName: 'Modality',
inputType: 'MultiSelect',
inputProps: {
options: [
{ value: 'SEG', label: 'SEG' },
{ value: 'CT', label: 'CT' },
{ value: 'MR', label: 'MR' },
{ value: 'SR', label: 'SR' },
],
},
isSortable: true,
gridCol: 3,
},
{
name: 'accession',
displayName: 'Accession',
inputType: 'Text',
isSortable: true,
gridCol: 4,
},
{
name: 'instances',
displayName: 'Instances',
inputType: 'None',
isSortable: true,
gridCol: 2,
},
];
const isFiltering = (filterValues, defaultFilterValues) => {
return Object.keys(defaultFilterValues).some(name => {
return filterValues[name] !== defaultFilterValues[name];
});
};
return (
<ModalProvider modal={Modal}>
<StudyListFilter
numOfStudies={100}
filtersMeta={filtersMeta}
filterValues={filterValues}
onChange={setFilterValues}
clearFilters={() => setFilterValues(defaultFilterValues)}
isFiltering={isFiltering(filterValues, defaultFilterValues)}
/>
</ModalProvider>
);
};
}
```
## Properties
<Props of={StudyListFilter} />
```
@@ -0,0 +1,48 @@
---
name: Study List Pagination
menu: Navigation
route: components/studyListPagination
---
import { useState } from 'react';
import { StudyListPagination } from '@ohif/ui';
# StudyListPagination
## Import
```javascript
import { StudyListPagination } from '@ohif/ui';
```
## Basic usage
```jsx live
{
() => {
const [currentPage, setCurrentPage] = useState(1);
const [perPage, setPerPage] = useState(25);
const onChangePage = page => {
setCurrentPage(page);
};
const onChangePerPage = perPage => {
setPerPage(perPage);
setCurrentPage(1);
};
return (
<StudyListPagination
onChangePage={onChangePage}
onChangePerPage={onChangePerPage}
currentPage={currentPage}
perPage={perPage}
/>
);
};
}
```
## Properties
<Props of={StudyListPagination} />
```
@@ -0,0 +1,65 @@
---
name: Study List Table
menu: Data Display
route: components/studyListTable
---
import { useState } from 'react';
import { StudyListTable } from '@ohif/ui';
# StudyListTable
This component is used to display a studies list.
## Import
```javascript
import { StudyListTable } from '@ohif/ui';
```
## Basic usage
```jsx live
{
() => {
const studies = new Array(10).fill('');
const [expandedRows, setExpandedRows] = useState([]);
const tableDataSource = studies.map((study, key) => {
const rowKey = key + 1;
const isExpanded = expandedRows.some(k => k === rowKey);
return {
row: [
{ key: 'Cell 01', content: 'Cell 01', gridCol: 2 },
{ key: 'Cell 02', content: 'Cell 02', gridCol: 4 },
{ key: 'Cell 03', content: 'Cell 03', gridCol: 4 },
{ key: 'Cell 04', content: 'Cell 04', gridCol: 4 },
],
expandedContent: (
<td className="w-full p-8">
Custom expanded content for row {rowKey}
</td>
),
onClickRow: () =>
setExpandedRows(rows =>
isExpanded ? rows.filter(n => rowKey !== n) : [...rows, rowKey]
),
isExpanded,
};
});
return (
<div className="py-4">
<StudyListTable
tableDataSource={tableDataSource}
numOfStudies={studies.length}
/>
</div>
);
};
}
```
## Properties
<Props of={StudyListTable} />
```
@@ -0,0 +1,78 @@
---
name: Table
menu: Data Display
route: components/table
---
import { Table, TableHead, TableBody, TableRow, TableCell } from '@ohif/ui';
# Table
Tables display sets of data.
_The Table component and its components in the tree are built using divs._
## Import
Check the given example below to see how to import each component to create a
table.
```javascript
import { Table, TableBody, TableCell, TableHead, TableRow } from '@ohif/ui';
```
## Basic usage
```jsx live
<div className="p-4">
<Table>
<TableHead>
<TableRow>
<TableCell>Item 01</TableCell>
<TableCell>Item 02</TableCell>
<TableCell>Item 03</TableCell>
<TableCell>Item 04</TableCell>
</TableRow>
</TableHead>
<TableBody>
{new Array(25).fill('').map(row => (
<TableRow>
<TableCell>Content 01</TableCell>
<TableCell>Content 02</TableCell>
<TableCell>Content 03</TableCell>
<TableCell>Content 04</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
```
## Table width
Table has full width by default. If you want to change its width, you will have
to set the `fullWidth` prop to `false` and then define your own table width by
passing a `className` or `style`.
## Properties
### Table Props
<Props of={Table} />
### TableHead Props
<Props of={TableHead} />
### TableBody Props
<Props of={TableBody} />
### TableRow Props
<Props of={TableRow} />
### TableCell Props
<Props of={TableCell} />
```
@@ -0,0 +1,40 @@
---
name: Thumbnail
menu: General
route: components/thumbnail
---
import { Thumbnail } from '../';
# Thumbnail
Used to expose a display set showing some information about the group of images
and a thumbnail
## Import
```javascript
import { Thumbnail } from '@ohif/ui';
```
## Basic usage
```jsx live
<div className="flex flex-1 items-center justify-center p-4">
<div className="w-56">
<Thumbnail
imageAltText="DisplaySet thumbnail image"
description="Multiple line image series description lorem sit"
seriesNumber={4}
numInstances={902}
onClick={() => alert('Thumbnail was clicked!')}
isActive={false}
/>
</div>
</div>
```
## Properties
<Props of={Thumbnail} />
@@ -0,0 +1,37 @@
---
name: ThumbnailNoImage
menu: General
route: components/ThumbnailNoImage
---
import { ThumbnailNoImage } from '../';
# ThumbnailNoImage
Used to expose
## Import
```javascript
import { Thumbnail } from '@ohif/ui';
```
## Basic usage
```jsx live
<div className="flex flex-1 items-center justify-center p-4">
<div className="w-64">
<ThumbnailNoImage
modality={'SR'}
seriesDate="13-Mar-1999"
description="Multiple line image series description lorem sit"
onClick={() => alert('ThumbnailNoImage was clicked!')}
/>
</div>
</div>
```
## Properties
<Props of={ThumbnailNoImage} />
@@ -0,0 +1,39 @@
---
name: ThumbnailTracked
menu: General
route: components/ThumbnailTracked
---
import { ThumbnailTracked } from '../';
# ThumbnailTracked
## Import
```javascript
import { ThumbnailTracked } from '@ohif/ui';
```
## Basic usage
```jsx live
<div className="flex flex-1 items-center justify-center p-4">
<div className="w-64">
<ThumbnailTracked
imageAltText="DisplaySet thumbnail image"
description="Multiple line image series description lorem sit"
seriesNumber={4}
numInstances={902}
onClick={() => alert('Thumbnail was clicked!')}
viewportIdentificator={["A"]}
isTracked={true}
isActive={false}
/>
</div>
</div>
```
## Properties
<Props of={ThumbnailTracked} />
@@ -0,0 +1,46 @@
---
name: Toolbar Button
menu: General
route: components/toolbarButton
---
import { useState } from 'react';
import { ToolbarButton } from '@ohif/ui';
# Toolbar Button
Toolbar Buttons are used to populate the Toolbar.
## Import
```javascript
import { ToolbarButton } from '@ohif/ui';
```
```jsx live
function ToolbarButtonExample(props) {
// const [isActive, setIsActive] = useState(false);
const tool = {
id: 'Zoom',
label: 'Zoom',
icon: 'tool-zoom',
type: null,
commandName: 'setToolActive',
commandOptions: { toolName: 'Zoom' },
//onClick: () => setIsActive(true),
isActive: true,
};
return (
<div className="py-10 flex justify-center">
<ToolbarButton {...tool} />
</div>
);
}
```
## Properties
<Props of={ToolbarButton} />
```
@@ -0,0 +1,40 @@
---
name: Tooltip
menu: Data Display
route: components/tooltip
---
import { Tooltip, Typography } from '@ohif/ui';
# Tooltip
Tooltips display informative content when users hover over, focus on, or tap an
element.
## Import
```javascript
import { Tooltip } from '@ohif/ui';
```
```jsx live
function TooltipExample(props) {
const tooltips = ['bottom', 'bottom-left', 'bottom-right', 'left', 'right'];
return (
<div className="py-10 flex flex-col items-center justify-center">
{tooltips.map(tooltip => (
<div className="mb-16">
<Tooltip content="Tooltip content" position={tooltip}>
<Typography>Tooltip {tooltip}</Typography>
</Tooltip>
</div>
))}
</div>
);
}
```
## Properties
<Props of={Tooltip} />
```
@@ -0,0 +1,26 @@
---
name: TooltipClipboard
menu: Data Display
route: components/tooltipClipboard
---
import { TooltipClipboard } from '@ohif/ui';
# Tooltip Clipboard
Tooltips display informative content when users hover over, focus on, or tap an
element.
## Import
```jsx live
import { TooltipClipboard } from '@ohif/ui';
<div className="p-4">
<TooltipClipboard>Text to be copied</TooltipClipboard>
</div>;
```
## Properties
<Props of={TooltipClipboard} />
@@ -0,0 +1,69 @@
---
name: Typography
menu: General
route: components/typography
---
import { Typography } from '@ohif/ui';
# Typography
Use typography to display text using the available props for customizing your
content.
## Import
```javascript
import { Typography } from '@ohif/ui';
```
## Basic usage
````jsx live
<div className="p-4">
<Typography variant="h1">
h1. The five boxing wizards jump quickly.
</Typography>
<Typography variant="h2">
h2. The five boxing wizards jump quickly.
</Typography>
<Typography variant="h3">
h3. The five boxing wizards jump quickly.
</Typography>
<Typography variant="h4">
h4. The five boxing wizards jump quickly.
</Typography>
<Typography variant="h5">
h5. The five boxing wizards jump quickly.
</Typography>
<Typography variant="h6">
h6. The five boxing wizards jump quickly.
</Typography>
<Typography variant="subtitle">
subtitle. The five boxing wizards jump quickly.
</Typography>
<Typography variant="body">
body. The five boxing wizards jump quickly.
</Typography>
</div>
```
## Changing the HTML element
There are different semantic elements to be used in the Typography component.
You can use the prop `component` to associate the component to be rendered with
a semantic element. The style of a Typography is independent of the semantic
element.
```jsx live
<div className="p-4">
<Typography variant="h1" component="h2">
This is a h2 using the h1 styles.
</Typography>
</div>
```
## Properties
<Props of={Typography} />
````
@@ -0,0 +1,55 @@
---
name: Viewport
menu: Data Display
route: components/viewport
---
import { Viewport } from '@ohif/ui';
# Viewport
Viewport component to be used in the ViewportGrid.
## Import
```javascript
import { Viewport } from '@ohif/ui';
```
## Basic usage
```jsx live
<div className="p-4 h-screen">
<Viewport
viewportIndex={0}
onSeriesChange={direction => alert(`Series ${direction}`)}
studyData={{
label: 'A',
isTracked: true,
isLocked: false,
isRehydratable: false,
studyDate: '07-Sep-2011',
currentSeries: 1,
seriesDescription:
'Series description lorem ipsum dolor sit Series description lorem ipsum dolor sit Series description lorem ipsum dolor sit ',
modality: 'CT',
patientInformation: {
patientName: 'Smith, Jane',
patientSex: 'F',
patientAge: '59',
MRN: '10000001',
thickness: '5.0mm',
spacing: '1.25mm',
scanner: 'Aquilion',
},
}}
>
<div className="flex justify-center items-center h-full">CONTENT</div>
</Viewport>
</div>
```
## Properties
<Props of={Viewport} />
```
@@ -0,0 +1,136 @@
---
name: Viewport Action Bar
menu: Data Display
route: components/viewportActionBar
---
import { ViewportActionBar } from '@ohif/ui';
# Viewport Action Bar
Used to display an Action Bar in the viewer.
## Import
```javascript
import { ViewportActionBar } from '@ohif/ui';
```
## Basic usage
````jsx live
<div className="p-4 h-64">
<ViewportActionBar
onSeriesChange={direction => alert(`Series ${direction}`)}
studyData={{
label: 'A',
isTracked: true,
isLocked: false,
isRehydratable: false,
studyDate: '07-Sep-2010',
currentSeries: 1,
seriesDescription:
'Series description lorem ipsum dolor sit Series description lorem ipsum dolor sit Series description lorem ipsum dolor sit ',
modality: 'CT',
patientInformation: {
patientName: 'Smith, Jane',
patientSex: 'F',
patientAge: '59',
MRN: '10000001',
thickness: '2.0mm',
spacing: '1.25mm',
scanner: 'Aquilion',
},
}}
/>
</div>
```
```jsx live
<div className="p-4 h-64">
<ViewportActionBar
onSeriesChange={direction => alert(`Series ${direction}`)}
studyData={{
label: 'A',
isTracked: false,
isLocked: false,
isRehydratable: true,
studyDate: '07-Sep-2010',
currentSeries: 1,
seriesDescription:
'Series description lorem ipsum dolor sit Series description lorem ipsum dolor sit Series description lorem ipsum dolor sit ',
modality: 'CT',
patientInformation: {
patientName: 'Smith, Jane',
patientSex: 'F',
patientAge: '59',
MRN: '10000001',
thickness: '2.0mm',
spacing: '1.25mm',
scanner: 'Aquilion',
},
}}
/>
</div>
```
```jsx live
<div className="p-4 h-64">
<ViewportActionBar
onSeriesChange={direction => alert(`Series ${direction}`)}
studyData={{
label: 'A',
isTracked: false,
isLocked: false,
isRehydratable: false,
studyDate: '07-Sep-2010',
currentSeries: 1,
seriesDescription:
'Series description lorem ipsum dolor sit Series description lorem ipsum dolor sit Series description lorem ipsum dolor sit ',
modality: 'SR',
patientInformation: {
patientName: 'Smith, Jane',
patientSex: 'F',
patientAge: '59',
MRN: '10000001',
thickness: '2.0mm',
spacing: '1.25mm',
scanner: 'Aquilion',
},
}}
/>
</div>
```
```jsx live
<div className="p-4 h-64">
<ViewportActionBar
onSeriesChange={direction => alert(`Series ${direction}`)}
studyData={{
label: 'A',
isTracked: false,
isLocked: false,
isRehydratable: true,
studyDate: '07-Sep-2010',
currentSeries: 1,
seriesDescription:
'Series description lorem ipsum dolor sit Series description lorem ipsum dolor sit Series description lorem ipsum dolor sit ',
modality: 'SR',
patientInformation: {
patientName: 'Smith, Jane',
patientSex: 'F',
patientAge: '59',
MRN: '10000001',
thickness: '2.0mm',
spacing: '1.25mm',
scanner: 'Aquilion',
},
}}
/>
</div>
```
</>
## Properties
<Props of={ViewportActionBar} />
````
@@ -0,0 +1,39 @@
---
name: ViewportGrid
menu: General
route: components/viewportGrid
---
import { DragAndDropProvider, ViewportGrid } from '@ohif/ui';
# ViewportGrid
Used to display viewports in the viewer page.
## Import
```javascript
import { ViewportGrid } from '@ohif/ui';
```
## Basic usage
```jsx live
<DragAndDropProvider>
<div className="p-4 h-56">
<ViewportGrid numRows={1} numCols={2}>
<div className="flex items-center justify-center h-full text-white">
Viewport1
</div>
<div className="flex items-center justify-center h-full text-white">
Viewport2
</div>
</ViewportGrid>
</div>
</DragAndDropProvider>
```
## Properties
<Props of={ViewportGrid} />
```
@@ -0,0 +1,35 @@
---
name: ViewportPane
menu: General
route: components/viewport-pane
---
import { ViewportGrid, ViewportPane, DragAndDropProvider } from '@ohif/ui';
# ViewportPane
Used to display viewports in the viewer page.
## Import
```javascript
import { ViewportPane } from '@ohif/ui';
```
## Basic usage
```jsx live
<div className="p-4 h-56">
<DragAndDropProvider>
<ViewportGrid numRows={1} numCols={2}>
<ViewportPane onDrop={() => {}} isActive={true}><h3>Hello</h3></ViewportPane>
<ViewportPane onDrop={() => {}} isActive={false}><h3>World</h3></ViewportPane>
</ViewportGrid>
</DragAndDropProvider>
</div>
```
## Properties
<Props of={ViewportPane} />
@@ -0,0 +1,36 @@
---
name: Window Level Menu Item
menu: General
route: components/windowLevelMenuItem
---
import { useState } from 'react';
import { ListMenu, WindowLevelMenuItem } from '@ohif/ui';
# Window Level Menu Item
Window Level Menu Item are used as renderer of the ListMenu.
## Import
```javascript
import { WindowLevelMenuItem, ListMenu } from '@ohif/ui';
```
```jsx live
{
() => {
return (
<div className="py-10 flex justify-center">
<ListMenu renderer={WindowLevelMenuItem} items={[]} />
</div>
);
};
}
```
## Properties
<Props of={WindowLevelMenuItem} />
```
@@ -0,0 +1,53 @@
---
name: Icon
menu: General
route: components/icon
---
import { Icon, ICONS } from '@ohif/ui';
# Icon
## Import
```javascript
import { Icon } from '@ohif/ui';
```
## Basic usage
```jsx live
<div className="p-4">
<Icon name="series-active" className="text-primary-light m-4" />
</div>
```
## All Icons
<div className="p-4 flex flex-wrap items-center bg-black py-8">
{Object.keys(ICONS)
.sort()
.map((name, i) => {
return (
<React.Fragment key={i}>
<div className="flex flex-col items-center w-48 py-4">
<div className="flex items-center justify-center rounded border border-primary-light p-4 m-2 w-20 h-20">
<Icon name={name} className="text-primary-light w-6" />
</div>
<div className="break-normal text-white">{name}</div>
</div>
</React.Fragment>
);
})}
</div>
## Properties
<Props of={Icon} />
The `Icon` component takes a single prop of `name`, which indicates which Icon
should be displayed. The icon inherit the component text/font styles.
```
```
@@ -0,0 +1,117 @@
---
name: ModalProvider
route: customHooks/modalProvider
---
import { ModalComponent, ModalProvider } from '@ohif/ui';
# Modal Context Provider
This is a context provider that allow the application to share the modal
component across all application.
## ModalProvider
Properties:
<Props of={ModalProvider} />
Usage example:
```javascript
import { ModalProvider } from '@ohif/ui';
import YourModalComponent from 'your-modal-component';
const App = () => {
return (
<ModalProvider modal={YourModalComponent}>
/** You app content */
</ModalComponent>;
)
};
export default App;
```
## useModal
Used for React Functional Components. Should be used in the body of the
functional component to get access to the context together with the `show/hide`
functions.
Usage example:
```javascript
import { withModal } from '@ohif/ui';
const SampleComponent = () => {
const { show, hide } = useModal();
const openModal = () => {
show({
content: <div> Modal Content </div>,
title: 'Modal title',
});
}
const closeModal = () => {
hide();
}
return (
<button onClick={openModal}>
Open modal
</button>
<button onClick={closeModal}>
Close modal
</button>
);
};
export default SampleComponent;
```
## withModal
Used for React Class Components. This function show receive a Component as a
property and this component will have access to the context through its own
properties.
Usage example:
```javascript
import { withModal } from '@ohif/ui';
import React from 'react';
class SampleComponent extends React.Component {
openModal() {
this.props.modal.show({
content: <div> Modal Content </div>,
title: 'Modal title',
});
}
closeModal() = {
this.props.modal.hide();
}
render() {
return (
<button onClick={this.openModal}>
Open modal
</button>
<button onClick={this.closeModal}>
Close modal
</button>
);
}
}
export default withModal(SampleComponent);
```
## Modal Properties
The Modal Properties that can be override are:
<Props of={ModalComponent} />
@@ -0,0 +1,183 @@
---
name: ViewportDialogProvider
route: customHooks/viewportDialogProvider
---
<!-- This is a workaround to import things from ohif/core as docz does not allow us to access window element and @ohif/core does use it once we import to instanciate cornerstone -->
<!-- import UIViewportDialogService from './../../../core/src/services/UIViewportDialogService';
import ServicesManager from './../../../core/src/services/ServicesManager'; !-->
import {
Dialog,
Button,
Notification,
ViewportDialogProvider,
useViewportDialog,
} from '@ohif/ui';
# Viewport Dialog Provider
This is a context provider that allow the application to share the modal
component across all application.
## Sample
````jsx live
{() => {
const ViewportNotification = ({ hide }) => {
return (
<Notification
message="Track all measurement for this series?"
type="info"
actions={[
{
type: 'cancel',
text: 'No',
value: 0,
},
{
type: 'secondary',
text: 'No, do not ask again',
value: -1,
},
{
type: 'primary',
text: 'Yes',
value: 1,
},
]}
onSubmit={value => {
if (typeof window !== 'undefined') {
window.alert(value);
}
}}
/>
);
};
const ViewportActionButtons = () => {
const [dialogState, dialogApi] = useViewportDialog();
return (
<Button onClick={() => dialogApi.show({ content: ViewportNotification })}>
Open Dialog
</Button>
);
};
return (
<div className="w-full flex flex-row p-4" style={{height: '400px'}}>
<div className="flex flex-1 items-center justify-center h-full w-full bg-black text-white border border-primary-main">
<ViewportDialogProvider dialog={Dialog}>
<div className="flex flex-1 flex-col items-center justify-center h-full">
<ViewportActionButtons />
<span>CONTENT 1</span>
</div>
</ViewportDialogProvider>
</div>
<div className="flex flex-1 items-center justify-center h-full w-full bg-black text-white border border-primary-main">
<ViewportDialogProvider dialog={Dialog}>
<div className="flex flex-1 flex-col items-center justify-center h-full">
<ViewportActionButtons />
<span>CONTENT 1</span>
</div>
</ViewportDialogProvider>
</div>
</div>
);
}}
```
## Example using UIViewportDialogService
```jsx live
{() => {
const ViewportNotification = ({ hide }) => {
return (
<Notification
message="Track all measurement for this series?"
type="info"
actions={[
{
type: 'cancel',
text: 'No',
value: 0,
},
{
type: 'secondary',
text: 'No, do not ask again',
value: -1,
},
{
type: 'primary',
text: 'Yes',
value: 1,
},
]}
onSubmit={value => {
if (typeof window !== 'undefined') {
window.alert(value);
}
}}
/>
);
};
// Creating servicesManager and register services should be in the root of your app
const servicesManager = new ServicesManager();
servicesManager.registerServices([UIViewportDialogService]);
// Get service instance
const _UIViewportDialogService =
servicesManager.services.UIViewportDialogService;
console.log(_UIViewportDialogService);
return (
<div className="w-full flex flex-col p-4" style={{height: '400px'}}>
<div className="flex flex-2">
<Button
className="mr-4 mb-4"
onClick={() =>
_UIViewportDialogService.show({
content: ViewportNotification,
viewportIndex: 0,
})
}
>
Open dialog on 0
</Button>
<Button
className="mr-4 mb-4"
onClick={() =>
_UIViewportDialogService.show({
content: ViewportNotification,
viewportIndex: 1,
})
}
>
Open dialog on 1
</Button>
</div>
<div className="flex flex-1 w-full flex-row">
<ViewportDialogProvider
dialog={Dialog}
service={_UIViewportDialogService}
viewportIndex={0}
>
<div className="flex flex-1 items-center justify-center h-full bg-black text-white border border-primary-main">
CONTENT 0
</div>
</ViewportDialogProvider>
<ViewportDialogProvider
dialog={Dialog}
service={_UIViewportDialogService}
viewportIndex={1}
>
<div className="flex flex-1 items-center justify-center h-full bg-black text-white border border-primary-main">
CONTENT 1
</div>
</ViewportDialogProvider>
</div>
</div>
);
}}
```
## Properties:
<Props of={ViewportDialogProvider} />
````
@@ -0,0 +1,178 @@
---
name: ViewportDialogProvider
route: customHooks/viewportDialogProvider
---
<!-- This is a workaround to import things from ohif/core as docz does not allow us to access window element and @ohif/core does use it once we import to instanciate cornerstone -->
import UIViewportDialogService from './../../../core/src/services/UIViewportDialogService';
import ServicesManager from './../../../core/src/services/ServicesManager';
import { Dialog, Button, Notification, ViewportDialogProvider, useViewportDialog } from '@ohif/ui';
# Viewport Dialog Provider
This is a context provider that allow the application to share the modal
component across all application.
## Sample
```jsx live
{() => {
const ViewportNotification = ({ hide }) => {
return (
<Notification
message="Track all measurement for this series?"
type="info"
actions={[
{
type: 'cancel',
text: 'No',
value: 0,
},
{
type: 'secondary',
text: 'No, do not ask again',
value: -1,
},
{
type: 'primary',
text: 'Yes',
value: 1,
},
]}
onSubmit={value => {
if (typeof window !== 'undefined') {
window.alert(value);
}
}}
/>
);
};
const ViewportActionButtons = () => {
const [dialogState, dialogApi] = useViewportDialog();
return (
<Button onClick={() => dialogApi.show({ content: ViewportNotification })}>
Open Dialog
</Button>
);
};
return (
<div className="w-full flex flex-row p-4" style={{height: '400px'}}>
<div className="flex flex-1 items-center justify-center h-full w-full bg-black text-white border border-primary-main">
<ViewportDialogProvider dialog={Dialog}>
<div className="flex flex-1 flex-col items-center justify-center h-full">
<ViewportActionButtons />
<span>CONTENT 1</span>
</div>
</ViewportDialogProvider>
</div>
<div className="flex flex-1 items-center justify-center h-full w-full bg-black text-white border border-primary-main">
<ViewportDialogProvider dialog={Dialog}>
<div className="flex flex-1 flex-col items-center justify-center h-full">
<ViewportActionButtons />
<span>CONTENT 1</span>
</div>
</ViewportDialogProvider>
</div>
</div>
);
}}
```
## Example using UIViewportDialogService
```jsx live
{() => {
const ViewportNotification = ({ hide }) => {
return (
<Notification
message="Track all measurement for this series?"
type="info"
actions={[
{
type: 'cancel',
text: 'No',
value: 0,
},
{
type: 'secondary',
text: 'No, do not ask again',
value: -1,
},
{
type: 'primary',
text: 'Yes',
value: 1,
},
]}
onSubmit={value => {
if (typeof window !== 'undefined') {
window.alert(value);
}
}}
/>
);
};
// Creating servicesManager and register services should be in the root of your app
const servicesManager = new ServicesManager();
servicesManager.registerServices([UIViewportDialogService]);
// Get service instance
const _UIViewportDialogService =
servicesManager.services.UIViewportDialogService;
console.log(_UIViewportDialogService);
return (
<div className="w-full flex flex-col p-4" style={{height: '400px'}}>
<div className="flex flex-2">
<Button
className="mr-4 mb-4"
onClick={() =>
_UIViewportDialogService.show({
content: ViewportNotification,
viewportIndex: 0,
})
}
>
Open dialog on 0
</Button>
<Button
className="mr-4 mb-4"
onClick={() =>
_UIViewportDialogService.show({
content: ViewportNotification,
viewportIndex: 1,
})
}
>
Open dialog on 1
</Button>
</div>
<div className="flex flex-1 w-full flex-row">
<ViewportDialogProvider
dialog={Dialog}
service={_UIViewportDialogService}
viewportIndex={0}
>
<div className="flex flex-1 items-center justify-center h-full bg-black text-white border border-primary-main">
CONTENT 0
</div>
</ViewportDialogProvider>
<ViewportDialogProvider
dialog={Dialog}
service={_UIViewportDialogService}
viewportIndex={1}
>
<div className="flex flex-1 items-center justify-center h-full bg-black text-white border border-primary-main">
CONTENT 1
</div>
</ViewportDialogProvider>
</div>
</div>
);
}}
```
## Properties:
<Props of={ViewportDialogProvider} />
@@ -0,0 +1,82 @@
---
name: Colors
route: system/colors
---
import BackgroundColor from '@ohif/ui';
# Color System
`@ohif/ui` offers a color system with a handful of color utility classes.
As `@ohif/ui` uses Tailwind as a base styling library, you will be able to use
all the default colors from Tailwind, besides our custom colors too.
# How to use
To apply color in your element, you will use the same way Tailwind does.
- Background - `bg-primary-main`
- Border - `border-primary-main`
- Text - `text-primary-main`
- Placeholder - `placeholder-primary-main`
Check [Tailwind's documentation](https://tailwindcss.com/docs) to see more
details about color classes.
# Examples
## Text
````jsx live
<div className="p-8">
<p className="text-common-bright">text-common-bright</p>
<p className="text-common-light">text-common-light</p>
<p className="text-common-main">text-common-main</p>
<p className="text-common-dark">text-common-dark</p>
<p className="text-common-active">text-common-active</p>
</div>
```
## Background
<div className="flex">
<div className="mr-8">
<BackgroundColor color="primary-light" />
<BackgroundColor color="primary-main" />
<BackgroundColor color="primary-dark" />
<BackgroundColor color="primary-active" />
</div>
<div>
<BackgroundColor color="secondary-light" />
<BackgroundColor color="secondary-main" />
<BackgroundColor color="secondary-dark" />
<BackgroundColor color="secondary-active" />
</div>
</div>
# Color palette
```javascript
primary: {
light: '#5acce6',
main: '#0944b3',
dark: '#090c29',
active: '#348cfd',
},
secondary: {
light: '#3a3f99',
main: '#2b166b',
dark: '#041c4a',
active: '#1f1f27',
},
common: {
bright: '#e1e1e1',
light: '#a19fad',
main: '#fff',
dark: '#726f7e',
active: '#2c3074',
},
````
@@ -0,0 +1,46 @@
---
name: Getting Started
route: /
---
import { Button } from '@ohif/ui';
# Getting Started
`@ohif/ui` is a collection of components and utilities that power OHIF's
zero-footprint DICOM viewer.
It's maintained in a monorepo, in the
[OHIF's repository](https://github.com/OHIF/Viewers/).
## Installation
Install `@ohif/ui` from your terminal:
```bash
// with npm
npm i @ohif/ui --save-exact
​
// with yarn
yarn add @ohif/ui --exact
```
## Usage
```javascript
// Import and use components
import { Button } from '@ohif/ui';
```
```jsx live
<div className="p-8">
<Button onClick={() => alert('Hello!')}>Click here!</Button>
</div>
```
## Examples
In the **Examples** section you can check many examples on how to build your
application using `@ohif/ui` components.
...
@@ -0,0 +1,346 @@
---
name: Study List
menu: Views
route: examples/studyList
---
import { useState } from 'react';
import {
Icon,
StudyListExpandedRow,
Button,
NavBar,
Svg,
IconButton,
EmptyStudies,
StudyListTable,
StudyListPagination,
StudyListFilter
} from '@ohif/ui';
import utils from '../../utils';
import classnames from 'classnames';
import moment from 'moment';
# Study List
This example shows you how you can build a Study List page using the available
components.
```jsx live
{() => {
const defaultFilterValues = {
patientName: '',
mrn: '',
studyDate: {
startDate: null,
endDate: null,
},
description: '',
modality: undefined,
accession: '',
sortBy: '',
sortDirection: 'none',
page: 0,
resultsPerPage: 25,
};
const [filterValues, setFilterValues] = useState(defaultFilterValues);
const [studies, setStudies] = useState([]);
const numOfStudies = studies.length;
const [expandedRows, setExpandedRows] = useState([]);
const filtersMeta = [
{
name: 'patientName',
displayName: 'Patient Name',
inputType: 'Text',
isSortable: true,
gridCol: 4,
},
{
name: 'mrn',
displayName: 'MRN',
inputType: 'Text',
isSortable: true,
gridCol: 2,
},
{
name: 'studyDate',
displayName: 'Study date',
inputType: 'DateRange',
isSortable: true,
gridCol: 5,
},
{
name: 'description',
displayName: 'Description',
inputType: 'Text',
isSortable: true,
gridCol: 4,
},
{
name: 'modality',
displayName: 'Modality',
inputType: 'MultiSelect',
inputProps: {
options: [
{ value: 'SEG', label: 'SEG' },
{ value: 'CT', label: 'CT' },
{ value: 'MR', label: 'MR' },
{ value: 'SR', label: 'SR' },
],
},
isSortable: true,
gridCol: 3,
},
{
name: 'accession',
displayName: 'Accession',
inputType: 'Text',
isSortable: true,
gridCol: 4,
},
{
name: 'instances',
displayName: 'Instances',
inputType: 'None',
isSortable: true,
gridCol: 2,
},
];
const isFiltering = (filterValues, defaultFilterValues) => {
return Object.keys(defaultFilterValues).some((name) => {
return filterValues[name] !== defaultFilterValues[name];
});
};
const tableDataSource = studies.map((study, key) => {
const rowKey = key + 1;
const isExpanded = expandedRows.some((k) => k === rowKey);
const {
AccessionNumber,
Modalities,
Instances,
StudyDescription,
PatientId,
PatientName,
StudyDate,
series,
} = study;
const seriesTableColumns = {
description: 'Description',
seriesNumber: 'Series',
modality: 'Modality',
Instances: 'Instances',
};
const seriesTableDataSource = series.map((seriesItem) => {
const { SeriesNumber, Modality, instances } = seriesItem;
return {
description: 'Patient Protocol',
seriesNumber: SeriesNumber,
modality: Modality,
Instances: instances.length,
};
});
return {
row: [
{
key: 'patientName',
content: PatientName,
gridCol: 4,
},
{
key: 'mrn',
content: PatientId,
gridCol: 2,
},
{
key: 'studyDate',
content: (
<div>
<span className="mr-4">
{moment(StudyDate).format('MMM-DD-YYYY')}
</span>
<span>{moment(StudyDate).format('hh:mm A')}</span>
</div>
),
gridCol: 5,
},
{
key: 'description',
content: StudyDescription,
gridCol: 4,
},
{
key: 'modality',
content: Modalities,
gridCol: 3,
},
{
key: 'accession',
content: AccessionNumber,
gridCol: 4,
},
{
key: 'instances',
content: (
<>
<Icon
name="group-layers"
className={classnames('inline-flex mr-2 w-4', {
'text-primary-active': isExpanded,
'text-secondary-light': !isExpanded,
})}
/>
{Instances}
</>
),
gridCol: 4,
},
],
expandedContent: (
<StudyListExpandedRow
seriesTableColumns={seriesTableColumns}
seriesTableDataSource={seriesTableDataSource}
>
<Button
rounded="full"
variant="contained"
className="mr-4 font-bold"
endIcon={
<Icon name="launch-arrow" style={{ color: '#21a7c6' }} />
}
>
Basic Viewer
</Button>
<Button
rounded="full"
variant="contained"
className="mr-4 font-bold"
endIcon={
<Icon name="launch-arrow" style={{ color: '#21a7c6' }} />
}
>
Segmentation
</Button>
<Button
rounded="full"
variant="outlined"
endIcon={<Icon name="launch-info" />}
className="font-bold"
>
Module 3
</Button>
<div className="ml-5 text-lg text-common-bright inline-flex items-center">
<Icon
name="notificationwarning-diamond"
className="mr-2 w-5 h-5"
/>
Feedback text lorem ipsum dolor sit amet
</div>
</StudyListExpandedRow>
),
onClickRow: () =>
setExpandedRows((s) =>
isExpanded ? s.filter((n) => rowKey !== n) : [...s, rowKey]
),
isExpanded,
};
});
const handleStudyList = (number) => {
const studies = utils.getMockedStudies(number);
setStudies(studies);
setCurrentPage(1);
};
const [currentPage, setCurrentPage] = useState(1);
const [perPage, setPerPage] = useState(25);
const totalPages = Math.floor(numOfStudies / perPage);
const onChangePage = (page) => {
if (page > totalPages) {
return;
}
setCurrentPage(page);
};
const onChangePerPage = (perPage) => {
setPerPage(perPage);
setCurrentPage(1);
};
const hasStudies = numOfStudies > 0;
return (
<div>
<div className="bg-white p-4">
<Button className="mr-2" onClick={() => handleStudyList(0)}>
0 Studies
</Button>
<Button className="mr-2" onClick={() => handleStudyList(50)}>
50 Studies
</Button>
<Button className="mr-2" onClick={() => handleStudyList(100)}>
100 Studies
</Button>
<Button className="mr-2" onClick={() => handleStudyList(1000)}>
1000 Studies
</Button>
</div>
<div
className={classnames('bg-black h-full', {
'h-screen': !hasStudies,
})}
>
<NavBar className="justify-between border-b-4 border-black" isSticky>
<div className="flex items-center">
<div className="mx-3">
<Svg name="logo-ohif" />
</div>
</div>
<div className="flex items-center">
<span className="mr-3 text-common-light text-lg">
FOR INVESTIGATIONAL USE ONLY
</span>
<IconButton
variant="text"
color="inherit"
className="text-primary-active"
onClick={() => {}}
>
<React.Fragment>
<Icon name="settings" />
<Icon name="chevron-down" />
</React.Fragment>
</IconButton>
</div>
</NavBar>
<StudyListFilter
numOfStudies={numOfStudies}
filtersMeta={filtersMeta}
filterValues={filterValues}
onChange={setFilterValues}
clearFilters={() => setFilterValues(defaultFilterValues)}
isFiltering={isFiltering(filterValues, defaultFilterValues)}
/>
{hasStudies ? (
<>
<StudyListTable
tableDataSource={tableDataSource.slice(
(currentPage - 1) * perPage,
(currentPage - 1) * perPage + perPage
)}
numOfStudies={numOfStudies}
filtersMeta={filtersMeta}
/>
<StudyListPagination
onChangePage={onChangePage}
onChangePerPage={onChangePerPage}
currentPage={currentPage}
perPage={perPage}
/>
</>
) : (
<div className="flex flex-col items-center justify-center pt-48">
<EmptyStudies />
</div>
)}
</div>
</div>
);
}}
```
@@ -0,0 +1,178 @@
---
name: Viewer
menu: Views
route: examples/viewer
---
import { useState } from 'react';
import {
NavBar,
SidePanel,
Svg,
SegmentationTable,
ButtonGroup,
Button,
Icon,
IconButton,
StudyBrowser,
ViewportActionBar,
Notification,
Viewport,
ViewportGrid,
ViewportPane,
StudySummary,
MeasurementTable,
Header,
DragAndDropProvider,
} from '@ohif/ui';
import { tabs } from './studyBrowserMockData';
# Viewer
```jsx live
{() => {
const [activeMeasurementItem, setActiveMeasurementItem] = useState(null);
const descriptionData = {
date: '07-Sep-2010',
modality: 'CT',
description: 'CHEST/ABD/PELVIS W CONTRAST',
};
const measurementTableData = {
title: 'Measurements',
amount: 10,
data: new Array(10).fill({}).map((el, i) => ({
id: i + 1,
label: 'Label short description',
displayText: '24.0 x 24.0 mm (S:4, I:22)',
isActive: activeMeasurementItem === i + 1,
})),
onClick: (id) => setActiveMeasurementItem((s) => (s === id ? null : id)),
onEdit: (id) => alert(`Edit: ${id}`),
};
const [activeViewportIndex, setActiveViewportIndex] = useState(0);
return (
<DragAndDropProvider>
<Header />
<div
className="flex flex-row flex-no-wrap items-stretch overflow-hidden w-full"
style={{ height: 'calc(100vh - 52px' }}
>
{/* LEFT SIDEPANELS */}
<SidePanel
side="left"
defaultComponentOpen='studies'
childComponents={{
iconName: 'group-layers',
iconLabel: 'Studies',
label: 'Studies',
name: 'studies',
content: <StudyBrowser tabs={tabs} />
}}
/>
{/* TOOLBAR + GRID */}
<div className="flex flex-col flex-1 h-full">
<div className="flex flex-2 w-100 border-b border-transparent h-12">
{/* <ViewportToolbar /> Secondary Toolbar */}
</div>
{/* VIEWPORT GRID CONTAINER */}
<div className="flex flex-1 h-full overflow-hidden bg-black items-center justify-center pb-2 pt-1">
<ViewportGrid numRows={1} numCols={2}>
{[0, 1].map(viewportIndex => (
<ViewportPane key={viewportIndex} className="m-1" isActive={false} onDrop={() => {}}>
<Viewport
viewportIndex={viewportIndex}
onSeriesChange={(direction) => alert(`Series ${direction}`)}
studyData={{
label: 'A',
isTracked: true,
isLocked: false,
isRehydratable: false,
studyDate: '07-Sep-2011',
currentSeries: 1,
seriesDescription:
'Series description lorem ipsum dolor sit Series description lorem ipsum dolor sit Series description lorem ipsum dolor sit ',
modality: 'CT',
patientInformation: {
patientName: 'Smith, Jane',
patientSex: 'F',
patientAge: '59',
MRN: '10000001',
thickness: '5.0mm',
spacing: '1.25mm',
scanner: 'Aquilion',
},
}}
>
<div className="flex justify-center items-center h-full">
CONTENT
</div>
</Viewport>
</ViewportPane>)
)}
</ViewportGrid>
</div>
</div>
<SidePanel
side="right"
defaultComponentOpen="measurements"
childComponents={{
iconName: 'list-bullets',
iconLabel: 'Measure',
label: 'Measurements',
name: 'measurements',
content: (
<>
<div className="overflow-x-hidden overflow-y-auto invisible-scrollbar">
<StudySummary
date={descriptionData.date}
modality={descriptionData.modality}
description={descriptionData.description}
/>
<MeasurementTable
title="Measurements"
amount={measurementTableData.data.length}
data={measurementTableData.data}
onClick={() => {}}
onEdit={id => alert(`Edit: ${id}`)}
/>
</div>
<div className="flex justify-center p-4">
<React.Fragment>
<ButtonGroup onClick={() => alert('Export')}>
<Button
className="text-white border-primary-main bg-black text-base py-2 px-2"
size="initial"
color="inherit"
>
Export
</Button>
<IconButton
className="bg-black border-primary-main px-2 text-white px-2"
color="inherit"
size="initial"
>
<Icon name="arrow-down" />
</IconButton>
</ButtonGroup>
<Button
className="text-white border border-primary-main bg-black text-base py-2 px-2 ml-2"
variant="outlined"
size="initial"
color="inherit"
onClick={() => alert('Create Report')}
>
Create Report
</Button>
</React.Fragment>
</div>
</>
)
}}
/>
</div>
</DragAndDropProvider>
);
}}
```
+35 -11
View File
@@ -72,6 +72,7 @@ const isI18nStaging = process.env.I18N_STAGING === 'true';
// },
themes: ['@docusaurus/theme-live-codeblock'],
plugins: [
path.resolve(__dirname, './pluginOHIFWebpackConfig.js'),
'plugin-image-zoom', // 3rd party plugin for image click to pop
[
'@docusaurus/plugin-client-redirects',
@@ -80,10 +81,13 @@ const isI18nStaging = process.env.I18N_STAGING === 'true';
redirects: [
{
// we need this for https://cloud.google.com/healthcare/docs/how-tos/dicom-viewers
to: "/deployment/recipes/google-cloud-healthcare",
from: ['/connecting-to-image-archives/google-cloud-healthcare', '/connecting-to-image-archives/google-cloud-healthcare.html']
}
]
to: '/deployment/recipes/google-cloud-healthcare',
from: [
'/connecting-to-image-archives/google-cloud-healthcare',
'/connecting-to-image-archives/google-cloud-healthcare.html',
],
},
],
// createRedirects: function(path) {
// // redirect to /docs from /docs/introduction,
// // as introduction has been made the home doc
@@ -275,8 +279,18 @@ const isI18nStaging = process.env.I18N_STAGING === 'true';
srcDark: 'img/ohif-logo.svg',
},
items: [
{ to: 'https://ohif.org/get-started', label: 'Get Started', target: '_self', position: 'left' },
{ to: 'https://ohif.org/examples', label: 'Examples', target: '_self', position: 'left' },
{
to: 'https://ohif.org/get-started',
label: 'Get Started',
target: '_self',
position: 'left',
},
{
to: 'https://ohif.org/examples',
label: 'Examples',
target: '_self',
position: 'left',
},
{
position: 'left',
to: '/',
@@ -284,8 +298,18 @@ const isI18nStaging = process.env.I18N_STAGING === 'true';
docId: 'Introduction',
label: 'Docs',
},
{ to: 'https://ohif.org/community', label: 'Community', target: '_self', position: 'left' },
{ to: 'next/help', activeBaseRegex: '(^/help$)|(/next/help)', label: 'Help', position: 'right' },
{
to: 'https://ohif.org/community',
label: 'Community',
target: '_self',
position: 'left',
},
{
to: 'next/help',
activeBaseRegex: '(^/help$)|(/next/help)',
label: 'Help',
position: 'right',
},
// { to: 'https://react.ohif.org/', label: 'UI Component Library', position: 'left' },
// {to: 'showcase', label: 'Showcase', position: 'left'},
// right
@@ -299,7 +323,8 @@ const isI18nStaging = process.env.I18N_STAGING === 'true';
position: 'right',
dropdownItemsAfter: [
{
to: 'next/viewer/internationalization#contributing-with-new-languages',
to:
'next/viewer/internationalization#contributing-with-new-languages',
label: 'Help Us Translate',
},
],
@@ -308,12 +333,11 @@ const isI18nStaging = process.env.I18N_STAGING === 'true';
to: 'https://github.com/OHIF/Viewers',
position: 'right',
className: 'header-github-link',
'aria-label': 'GitHub Repository'
'aria-label': 'GitHub Repository',
},
],
},
footer: {
style: 'dark',
links: [
{
+1
View File
@@ -25,6 +25,7 @@
"write-heading-ids": "docusaurus write-heading-ids"
},
"dependencies": {
"@ohif/ui": "^2.0.0",
"@docusaurus/core": "2.0.0-beta.3",
"@docusaurus/plugin-client-redirects": "2.0.0-beta.3",
"@docusaurus/plugin-ideal-image": "2.0.0-beta.3",
+25
View File
@@ -0,0 +1,25 @@
module.exports = function(context, options) {
return {
name: 'plugin-ohif-webpack-config',
configureWebpack(config, isServer, utils) {
return {
resolve: {
fallback: {
fs: false,
path: false,
},
},
module: {
rules: [
{
test: /\.m?jsx?$/,
resolve: {
fullySpecified: false,
},
},
],
},
};
},
};
};
@@ -0,0 +1,18 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import React from 'react';
import * as ui from '@ohif/ui';
// Add react-live imports you need here
const ReactLiveScope = {
React,
...React,
...ui,
};
export default ReactLiveScope;