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

@@ -1,5 +1,6 @@
import React from 'react';
import { Typography, Icon } from '../../components';
import { Typography, Icon } from '../';
import PropTypes from 'prop-types';
import detect from 'browser-detect';
const Link = ({ href, children, showIcon = false }) => {
@@ -41,7 +42,7 @@ const Row = ({ title, value, link }) => {
);
};
const AboutModal = () => {
const AboutModal = ({buildNumber, versionNumber}) => {
const { os, version, name } = detect();
const browser = `${name[0].toUpperCase()}${name.substr(1)} ${version}`;
@@ -89,8 +90,8 @@ const AboutModal = () => {
value="https://github.com/OHIF/Viewers/commits/master"
link="https://github.com/OHIF/Viewers/commits/master"
/>
<Row title="Version Number" value={process.env.VERSION_NUMBER} />
<Row title="Build number" value={process.env.BUILD_NUM} />
<Row title="Version number" value={versionNumber} />
<Row title="Build number" value={buildNumber} />
<Row title="Browser" value={browser} />
<Row title="OS" value={os} />
</div>
@@ -98,4 +99,9 @@ const AboutModal = () => {
);
};
AboutModal.propTypes = {
buildNumber: PropTypes.string,
versionNumber: PropTypes.string,
}
export default AboutModal;
@@ -1,30 +0,0 @@
---
name: AboutModal
menu: General
route: components/aboutModal
---
import { Playground, Props } from 'docz';
import { AboutModal } from '@ohif/ui';
# AboutModal
AboutModal are used to show application version information.
## Import
```javascript
import { AboutModal } from '@ohif/ui';
```
## Usage
<Playground>
<div className="p-4">
<AboutModal />
</div>
</Playground>
## Properties
<Props of={AboutModal} />
@@ -1,444 +0,0 @@
---
name: Button
menu: General
route: components/button
---
import { Playground, Props } from 'docz';
import { Button, IconButton, Icon } from '../';
# Button
Buttons are used to execute actions when users interacts with them.
## Import
```javascript
import { Button } from '@ohif/ui';
```
## Outlined Buttons
<Playground>
<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>
</Playground>
## Contained Buttons
<Playground>
<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>
</Playground>
## Text Buttons
<Playground>
<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>
</Playground>
## Rounded Buttons
<Playground>
<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>
</Playground>
## Sizes
<Playground>
<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>
</Playground>
## Buttons with icons
<Playground>
<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>
</Playground>
## Icon Buttons
Icon buttons are generally used in toolbars.
```javascript
import { IconButton } from '@ohif/ui';
```
<Playground>
<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>
</Playground>
<Playground>
<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>
</Playground>
## Properties
<Props of={Button} />
@@ -1,111 +0,0 @@
---
name: ButtonGroup
menu: General
route: components/buttonGroup
---
import { Playground, Props } from 'docz';
import { ButtonGroup, Button, IconButton, Icon } from '../';
# ButtonGroup
Group Button display buttons together sharing its configurations
## Import
```javascript
import { ButtonGroup } from '@ohif/ui';
```
## Basic button group
<Playground>
<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>
</Playground>
## Group sizes and colorss
<Playground>
<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>
</Playground>
## Group orientation
<Playground>
<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>
</Playground>
## Split Button
<Playground>
<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>
</Playground>
## Properties
<Props of={ButtonGroup} />
@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import debounce from 'lodash.debounce';
import { IconButton, Icon } from '@ohif/ui';
import { IconButton, Icon } from '../';
import './CinePlayerCustomInputRange.css';
@@ -1,42 +0,0 @@
---
name: CinePlayer
menu: General
route: components/CinePlayer
---
import { useState } from 'react';
import { Playground, Props } from 'docz';
import { CinePlayer } from '@ohif/ui';
# Input Text
## Import
```javascript
import { CinePlayer } from '@ohif/ui';
```
## Basic usage
<Playground>
{() => {
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>
)
}}
</Playground>
## Properties
<Props of={CinePlayer} />
@@ -1,49 +0,0 @@
---
name: Context Menu
menu: General
route: components/contextMenu
---
import { Playground, Props } from 'docz';
import { ContextMenu } from '../';
# Context Menu
...
## Import
```javascript
import { ContextMenu } from '@ohif/ui';
```
<Playground>
{() => {
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>
);
}}
</Playground>
## Properties
<Props of={ContextMenu} />
@@ -1,45 +0,0 @@
---
name: Date Range
menu: Form
route: components/date-range
---
import { useState } from 'react';
import { Playground, Props } from 'docz';
import { DateRange } from '../';
# Date Range
Date Range is used to select a range of dates.
## Import
```javascript
import { DateRange } from '@ohif/ui';
```
## Date Range
<Playground>
{() => {
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>
);
}}
</Playground>
## Properties
<Props of={DateRange} />
@@ -1,68 +0,0 @@
---
name: Dropdown
menu: General
route: components/dropdown
---
import { Playground, Props } from 'docz';
import { Dropdown, IconButton, Icon } from '../';
# 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';
```
<Playground>
{() => {
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>
);
}}
</Playground>
## Properties
<Props of={Dropdown} />
@@ -1,30 +0,0 @@
---
name: Empty Studies
menu: Data Display
route: components/empty-studies
---
import { Playground, Props } from 'docz';
import { EmptyStudies } from '../';
# 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
<Playground>
<div className="p-4">
<EmptyStudies />
</div>
</Playground>
## Properties
<Props of={EmptyStudies} />
@@ -1,59 +0,0 @@
---
name: Error Boundary
menu: Data Display
route: components/errorBoundary
---
import { Playground, Props } from 'docz';
import { ErrorBoundary } from '../';
# Error Boundary
This component can be used to display a message or handle unhandled errors.
## Import
```javascript
import { ErrorBoundary } from '@ohif/ui';
```
## Basic usage
<Playground>
<div className="p-4">
<ErrorBoundary context="Somewhere">
{() => {
throw new Error('Error!');
return <p></p>;
}}
</ErrorBoundary>
</div>
</Playground>
## Custom error fallback
<Playground>
{() => {
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>
);
}}
</Playground>
## Properties
<Props of={ErrorBoundary} />
@@ -1,58 +0,0 @@
---
name: Expandable Toolbar Button
menu: General
route: components/expandableToolbarButton
---
import { useState } from 'react';
import { Playground, Props } from 'docz';
import { ExpandableToolbarButton, ListMenu } from '../';
# Toolbar Button
Expandable Toolbar Buttons are used to populate the Toolbar.
## Import
```javascript
import { ExpandableToolbarButton, ListMenu } from '@ohif/ui';
```
<Playground>
{() => {
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>
);
}}
</Playground>
## Properties
<Props of={ExpandableToolbarButton} />
+1 -1
View File
@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import classNames from 'classnames';
import { NavBar, Svg, Icon, IconButton, Dropdown } from '@ohif/ui';
import { NavBar, Svg, Icon, IconButton, Dropdown } from '../';
function Header({ children, menuOptions, isReturnEnabled, onClickReturnButton, isSticky, WhiteLabeling }) {
const { t } = useTranslation('Header');
@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { HotkeyField, Typography } from '@ohif/ui';
import { HotkeyField, Typography } from '../';
import { useTranslation } from 'react-i18next';
-51
View File
@@ -1,51 +0,0 @@
---
name: Icon
menu: General
route: components/icon
---
import { Playground, Props } from 'docz';
import { Icon } from '../';
import { ICONS } from './getIcon';
# Icon
## Import
```javascript
import { Icon } from '@ohif/ui';
```
## Basic usage
<Playground>
<div className="p-4">
<Icon name="series-active" className="text-primary-light m-4" />
</div>
</Playground>
## 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.
@@ -1,39 +0,0 @@
---
name: Input
menu: Form
route: components/input
---
import { Playground, Props } from 'docz';
import { Input } from '../';
# Input
## Import
```javascript
import { Input } from '@ohif/ui';
```
## Basic usage
<Playground>
{() => {
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>
);
}}
</Playground>
## Properties
<Props of={Input} />
@@ -1,43 +0,0 @@
---
name: InputDateRange
menu: Form
route: components/InputDateRange
---
import { useState } from 'react';
import { Playground, Props } from 'docz';
import { InputDateRange } from '../';
# Input Date Range
## Import
```javascript
import { InputDateRange } from '@ohif/ui';
```
## Basic usage
<Playground>
{() => {
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>
);
}}
</Playground>
## Properties
<Props of={InputDateRange} />
@@ -1,90 +0,0 @@
---
name: InputGroup
menu: Form
route: components/InputGroup
---
import { useState } from 'react';
import { Playground, Props } from 'docz';
import { InputGroup } from '../';
# Input Group
## Import
```javascript
import { InputGroup } from '@ohif/ui';
```
## Basic usage
<Playground>
{() => {
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>
);
}}
</Playground>
## Properties
<Props of={InputGroup} />
@@ -1,48 +0,0 @@
---
name: InputMultiSelect
menu: Form
route: components/InputMultiSelect
---
import { useState } from 'react';
import { Playground, Props } from 'docz';
import { InputMultiSelect } from '../';
# Input Multi Select
## Import
```javascript
import { InputMultiSelect } from '@ohif/ui';
```
## Basic usage
<Playground>
{() => {
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>
);
}}
</Playground>
## Properties
<Props of={InputMultiSelect} />
@@ -1,41 +0,0 @@
---
name: InputText
menu: Form
route: components/InputText
---
import { useState } from 'react';
import { Playground, Props } from 'docz';
import { InputText } from '../';
# Input Text
## Import
```javascript
import { InputText } from '@ohif/ui';
```
## Basic usage
<Playground>
{() => {
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>
)
}}
</Playground>
## Properties
<Props of={InputText} />
@@ -1,32 +0,0 @@
---
name: Label
menu: Form
route: components/label
---
import { Playground, Props } from 'docz';
import { Label } from '../';
# Label
## Import
```javascript
import { Label } from '@ohif/ui';
```
## Basic usage
<Playground>
{() => {
return (
<div className="p-4">
<Label text="Label" />
</div>
);
}}
</Playground>
## Properties
<Props of={Label} />
@@ -1,52 +0,0 @@
---
name: List Menu
menu: General
route: components/listMenu
---
import { useState } from 'react';
import { Playground, Props } from 'docz';
import { ListMenu, ToolbarButton } from '../';
# List Menu
List Menus are used to populate expandable Toolbar.
## Import
```javascript
import { ListMenu, ToolbarButton } from '@ohif/ui';
```
<Playground>
{() => {
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>
</>
)}
/>
);
}}
</Playground>
## Properties
<Props of={ListMenu} />
@@ -1,58 +0,0 @@
---
name: Measurement Table
menu: Data Display
route: components/measurementTable
---
import { useState } from 'react';
import { Playground, Props } from 'docz';
import { MeasurementTable } from '../';
# Measurement Table
## Import
```javascript
import { MeasurementTable } from '@ohif/ui';
```
## Basic usage
<Playground>
{() => {
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>
);
}}
</Playground>
## Empty Data
<Playground>
{() => {
return (
<div className="p-4 w-80">
<MeasurementTable title="Measurements" />
</div>
);
}}
</Playground>
## Properties
<Props of={MeasurementTable} />
+2 -2
View File
@@ -4,8 +4,8 @@ import ReactModal from 'react-modal';
import './Modal.css';
import { Typography, Icon } from '../../components';
import { useModal } from '../../contextProviders';
import { Typography, Icon } from '../';
import { useModal } from '../../contextProviders'
if (typeof document !== 'undefined') {
ReactModal.setAppElement(document.getElementById('root'));
@@ -1,30 +0,0 @@
---
name: NavBar
menu: Navigation
route: components/navBar
---
import { Playground, Props } from 'docz';
import { NavBar, Typography } from '../';
# NavBar
## Import
```javascript
import { NavBar } from '@ohif/ui';
```
## Basic usage
<Playground>
<NavBar className="justify-center">
<Typography variant="h3" className="m-2">
Header content
</Typography>
</NavBar>
</Playground>
## Properties
<Props of={NavBar} />
@@ -1,58 +0,0 @@
---
name: Notification
menu: Feedback
route: components/notification
---
import { Playground, Props } from 'docz';
import { Notification } from '../';
# 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
<Playground>
{() => {
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>
);
}}
</Playground>
## Properties
<Props of={Notification} />
@@ -1,37 +0,0 @@
---
name: Segmentation Table
menu: Data Display
route: components/segmentationTable
---
import { Playground, Props } from 'docz';
import { SegmentationTable } from '../';
# Segmentation Table
## Import
```javascript
import { SegmentationTable } from '@ohif/ui';
```
## Basic usage
<Playground>
{() => {
const tableData = {
title: 'Segments',
amount: 12,
data: new Array(12).fill(''),
};
return (
<div className="p-4 w-80">
<SegmentationTable {...tableData} />
</div>
);
}}
</Playground>
## Properties
<Props of={SegmentationTable} />
@@ -1,70 +0,0 @@
---
name: Select
menu: Form
route: components/select
---
import { Playground, Props } from 'docz';
import { Select } from '../';
# Select
## Import
```javascript
import { Select } from '@ohif/ui';
```
## Basic usage
<Playground>
<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>
</Playground>
## Disabled
<Playground>
<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>
</Playground>
## No Options
<Playground>
<div className="flex flex-col flex-1 p-4 items-center">
<div className="w-56">
<Select
noOptionsMessage={() => {
'No Options';
}}
options={[]}
/>
</div>
</div>
</Playground>
## Properties
<Props of={Select} />
@@ -1,75 +0,0 @@
---
name: SidePanel
menu: General
route: components/sidePanel
---
import { Playground, Props } from 'docz';
import { SidePanel } from '../';
# SidePanel
## Import
```javascript
import { SidePanel } from '@ohif/ui';
```
## Basic usage
<Playground>
<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>
</Playground>
## Multiple panels
<Playground>
<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>
</Playground>
## Properties
<Props of={SidePanel} />
@@ -1,6 +1,6 @@
import React from 'react';
import SnackbarItem from './SnackbarItem';
import { useSnackbar } from '../../contextProviders';
import SnackbarItem from './SnackbarItem'
import { useSnackbar } from '../../contextProviders/SnackbarProvider';
import './Snackbar.css';
@@ -4,7 +4,7 @@ import classNames from 'classnames';
import OutsideClickHandler from 'react-outside-click-handler';
import { useTranslation } from 'react-i18next';
import { Icon, Tooltip, ListMenu } from '@ohif/ui';
import { Icon, Tooltip, ListMenu } from '../';
const baseClasses = {
Button:
@@ -1,87 +0,0 @@
---
name: Split Button
menu: General
route: components/splitButton
---
import { useState } from 'react';
import { Playground, Props } from 'docz';
import { SplitButton, WindowLevelMenuItem } from '@ohif/ui';
# Split Button
Split Buttons are used to populate the Toolbar.
## Import
```javascript
import { SplitButton, WindowLevelMenuItem } from '@ohif/ui';
```
<Playground>
{() => {
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>
);
}}
</Playground>
## Properties
<Props of={SplitButton} />
@@ -1,107 +0,0 @@
---
name: StudyBrowser
menu: General
route: components/studyBrowser
---
import { Playground, Props } from 'docz';
import { StudyBrowser } from '../';
# StudyBrowser
## Import
```javascript
import { StudyBrowser } from '@ohif/ui';
```
## Basic usage
<Playground>
{() => {
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>
);
}}
</Playground>
## Properties
<Props of={StudyBrowser} />
@@ -1,46 +0,0 @@
---
name: StudyItem
menu: General
route: components/studyItem
---
import { useState } from 'react';
import { Playground, Props } from 'docz';
import { StudyItem } from '../';
# StudyItem
Used to expose study information as a card
## Import
```javascript
import { StudyItem } from '@ohif/ui';
```
## Basic usage
<Playground>
{() => {
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>
);
}}
</Playground>
## Properties
<Props of={StudyItem} />
@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import { Button, Icon, Typography, InputGroup } from '../../components';
import { Button, Icon, Typography, InputGroup } from '../';
const StudyListFilter = ({
filtersMeta,
@@ -1,121 +0,0 @@
---
name: Study List Filter
menu: Data Display
route: components/studyListFilter
---
import { useState } from 'react';
import { Playground, Props } from 'docz';
import { StudyListFilter, Modal } from '../';
import { ModalProvider } from '../../contextProviders';
# Study List Filter
## Import
```javascript
import { StudyListFilter, ModalProvider, Modal } from '@ohif/ui';
```
## Basic usage
<Playground>
{() => {
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>
);
}}
</Playground>
## Properties
<Props of={StudyListFilter} />
@@ -1,45 +0,0 @@
---
name: Study List Pagination
menu: Navigation
route: components/studyListPagination
---
import { useState } from 'react';
import { Playground, Props } from 'docz';
import { StudyListPagination } from '../';
# StudyListPagination
## Import
```javascript
import { StudyListPagination } from '@ohif/ui';
```
## Basic usage
<Playground>
{() => {
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}
/>
);
}}
</Playground>
## Properties
<Props of={StudyListPagination} />
@@ -1,62 +0,0 @@
---
name: Study List Table
menu: Data Display
route: components/studyListTable
---
import { useState } from 'react';
import { Playground, Props } from 'docz';
import { StudyListTable } from '../';
# StudyListTable
This component is used to display a studies list.
## Import
```javascript
import { StudyListTable } from '@ohif/ui';
```
## Basic usage
<Playground>
{() => {
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>
);
}}
</Playground>
## Properties
<Props of={StudyListTable} />
@@ -1,78 +0,0 @@
---
name: Table
menu: Data Display
route: components/table
---
import { Playground, Props, Link } from 'docz';
import { Table, TableHead, TableBody, TableRow, TableCell } from '../';
# 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
<Playground>
<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>
</Playground>
## 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} />
@@ -1,5 +1,5 @@
import React from 'react';
import '../../gatsby-theme-docz/tailwind.css';
import '../../tailwind.css';
import '../../assets/styles/styles.css';
const ThemeWrapper = ({ children }) => (
@@ -1,40 +0,0 @@
---
name: Thumbnail
menu: General
route: components/thumbnail
---
import { Playground, Props } from 'docz';
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
<Playground>
<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>
</Playground>
## Properties
<Props of={Thumbnail} />
@@ -1,37 +0,0 @@
---
name: ThumbnailNoImage
menu: General
route: components/ThumbnailNoImage
---
import { Playground, Props } from 'docz';
import { ThumbnailNoImage } from '../';
# ThumbnailNoImage
Used to expose
## Import
```javascript
import { Thumbnail } from '@ohif/ui';
```
## Basic usage
<Playground>
<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>
</Playground>
## Properties
<Props of={ThumbnailNoImage} />
@@ -1,39 +0,0 @@
---
name: ThumbnailTracked
menu: General
route: components/ThumbnailTracked
---
import { Playground, Props } from 'docz';
import { ThumbnailTracked } from '../';
# ThumbnailTracked
## Import
```javascript
import { ThumbnailTracked } from '@ohif/ui';
```
## Basic usage
<Playground>
<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>
</Playground>
## Properties
<Props of={ThumbnailTracked} />
@@ -1,44 +0,0 @@
---
name: Toolbar Button
menu: General
route: components/toolbarButton
---
import { useState } from 'react';
import { Playground, Props } from 'docz';
import { ToolbarButton } from '../';
# Toolbar Button
Toolbar Buttons are used to populate the Toolbar.
## Import
```javascript
import { ToolbarButton } from '@ohif/ui';
```
<Playground>
{() => {
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,
};
return (
<div className="py-10 flex justify-center">
<ToolbarButton {...tool} />
</div>
);
}}
</Playground>
## Properties
<Props of={ToolbarButton} />
@@ -1,40 +0,0 @@
---
name: Tooltip
menu: Data Display
route: components/tooltip
---
import { Playground, Props } from 'docz';
import { Tooltip, Typography } from '../';
# Tooltip
Tooltips display informative content when users hover over, focus on, or tap an
element.
## Import
```javascript
import { Tooltip } from '@ohif/ui';
```
<Playground>
{() => {
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>
);
}}
</Playground>
## Properties
<Props of={Tooltip} />
@@ -1,30 +0,0 @@
---
name: TooltipClipboard
menu: Data Display
route: components/tooltipClipboard
---
import { Playground, Props } from 'docz';
import { TooltipClipboard } from '../';
# Tooltip Clipboard
Tooltips display informative content when users hover over, focus on, or tap an
element.
## Import
```javascript
import { TooltipClipboard } from '@ohif/ui';
```
<Playground>
<div className="p-4">
<TooltipClipboard>Text to be copied</TooltipClipboard>
</div>
); }}
</Playground>
## Properties
<Props of={TooltipClipboard} />
@@ -1,69 +0,0 @@
---
name: Typography
menu: General
route: components/typography
---
import { Playground, Props } from 'docz';
import { Typography } from '../';
# Typography
Use typography to display text using the available props for customizing your
content.
## Import
```javascript
import { Typography } from '@ohif/ui';
```
## Basic usage
<Playground>
<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>
</Playground>
## 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.
<Playground>
<div className="p-4">
<Typography variant="h1" component="h2">
This is a h2 using the h1 styles.
</Typography>
</div>
</Playground>
## Properties
<Props of={Typography} />
@@ -1,6 +1,6 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { Select, Typography, Button, HotkeysPreferences } from '@ohif/ui';
import { Select, Typography, Button, HotkeysPreferences } from '../';
import { useTranslation } from 'react-i18next';
const UserPreferences = ({ availableLanguages, defaultLanguage, currentLanguage, disabled, hotkeyDefinitions, hotkeyDefaults, onCancel, onSubmit, onReset }) => {
@@ -1,55 +0,0 @@
---
name: Viewport
menu: Data Display
route: components/viewport
---
import { Playground, Props } from 'docz';
import { Viewport } from '../';
# Viewport
Viewport component to be used in the ViewportGrid.
## Import
```javascript
import { Viewport } from '@ohif/ui';
```
## Basic usage
<Playground>
<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>
</Playground>
## Properties
<Props of={Viewport} />
@@ -1,135 +0,0 @@
---
name: Viewport Action Bar
menu: Data Display
route: components/viewportActionBar
---
import { Playground, Props } from 'docz';
import { ViewportActionBar } from '../';
# Viewport Action Bar
Used to display an Action Bar in the viewer.
## Import
```javascript
import { ViewportActionBar } from '@ohif/ui';
```
## Basic usage
<>
<Playground>
<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>
</Playground>
<Playground>
<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>
</Playground>
<Playground>
<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>
</Playground>
<Playground>
<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>
</Playground>
</>
## Properties
<Props of={ViewportActionBar} />
@@ -1,40 +0,0 @@
---
name: ViewportGrid
menu: General
route: components/viewportGrid
---
import { Playground, Props } from 'docz';
import { DragAndDropProvider } from '../../contextProviders';
import { ViewportGrid } from '../../components';
# ViewportGrid
Used to display viewports in the viewer page.
## Import
```javascript
import { ViewportGrid } from '@ohif/ui';
```
## Basic usage
<Playground>
<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>
</Playground>
## Properties
<Props of={ViewportGrid} />
@@ -1,36 +0,0 @@
---
name: ViewportPane
menu: General
route: components/viewport-pane
---
import { Playground, Props } from 'docz';
import { ViewportGrid, ViewportPane } from '../../components';
import { DragAndDropProvider } from '../../contextProviders';
# ViewportPane
Used to display viewports in the viewer page.
## Import
```javascript
import { ViewportPane } from '@ohif/ui';
```
## Basic usage
<Playground>
<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>
</Playground>
## Properties
<Props of={ViewportPane} />
@@ -1,33 +0,0 @@
---
name: Window Level Menu Item
menu: General
route: components/windowLevelMenuItem
---
import { useState } from 'react';
import { Playground, Props } from 'docz';
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';
```
<Playground>
{() => {
return (
<div className="py-10 flex justify-center">
<ListMenu renderer={WindowLevelMenuItem} items={[]} />
</div>
);
}}
</Playground>
## Properties
<Props of={WindowLevelMenuItem} />
@@ -1,119 +0,0 @@
---
name: ModalProvider
route: customHooks/modalProvider
---
import { Props } from 'docz';
import { ModalProvider } from '../contextProviders';
import ModalComponent from './ModalComponent.jsx';
# 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} />
@@ -7,8 +7,8 @@ import React, {
} from 'react';
import PropTypes from 'prop-types';
import SnackbarContainer from '../components/Snackbar/SnackbarContainer';
import SnackbarTypes from '../components/Snackbar/SnackbarTypes';
import SnackbarContainer from '../components/Snackbar/SnackbarContainer';
const SnackbarContext = createContext(null);
@@ -1,179 +0,0 @@
---
name: ViewportDialogProvider
route: customHooks/viewportDialogProvider
---
import { Playground, Props } from 'docz';
<!-- 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 } from '../components';
import { ViewportDialogProvider, useViewportDialog } from '../contextProviders';
# Viewport Dialog Provider
This is a context provider that allow the application to share the modal
component across all application.
## Sample
<Playground>
{() => {
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>
);
}}
</Playground>
## Example using UIViewportDialogService
<Playground>
{() => {
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>
);
}}
</Playground>
## Properties:
<Props of={ViewportDialogProvider} />
@@ -1,69 +0,0 @@
/** @jsx jsx */
import { jsx, Box, Flex, useColorMode } from 'theme-ui';
import { useConfig, useCurrentDoc } from 'docz';
import * as styles from 'gatsby-theme-docz/src/components/Header/styles';
import {
Edit,
Menu,
Sun,
Github,
} from 'gatsby-theme-docz/src/components/Icons';
import { Logo } from 'gatsby-theme-docz/src/components/Logo';
export const Header = props => {
const { onOpen } = props;
const {
repository,
themeConfig: { showDarkModeSwitch, showMarkdownEditButton },
} = useConfig();
const { edit = true, ...doc } = useCurrentDoc();
const [colorMode, setColorMode] = useColorMode();
const toggleColorMode = () => {
setColorMode(colorMode === 'light' ? 'dark' : 'light');
};
return (
<div sx={styles.wrapper} data-testid="header">
<div sx={styles.innerContainer}>
<div className="flex">
<button className="mr-4" sx={styles.menuButton} onClick={onOpen}>
<Menu size={25} />
</button>
<Logo />
</div>
<Flex>
{repository && (
<Box sx={{ mr: 2 }}>
<a
href={repository}
sx={styles.headerButton}
target="_blank"
rel="noopener noreferrer"
>
<Github size={15} />
</a>
</Box>
)}
{showDarkModeSwitch && (
<button sx={styles.headerButton} onClick={toggleColorMode}>
<Sun size={15} />
</button>
)}
</Flex>
{showMarkdownEditButton && edit && doc.link && (
<a
sx={styles.editButton}
href={doc.link}
target="_blank"
rel="noopener noreferrer"
>
<Edit width={14} />
<Box sx={{ pl: 2 }}>Edit page</Box>
</a>
)}
</div>
</div>
);
};
@@ -1,52 +0,0 @@
/** @jsx jsx */
import { useRef, useState } from 'react';
import { jsx, Layout as BaseLayout, Main } from 'theme-ui';
import classnames from 'classnames';
import { Header } from '../Header';
import { Sidebar } from '../Sidebar';
import * as styles from 'gatsby-theme-docz/src/components/Layout/styles';
const getSidebarStatus = () =>
typeof window !== 'undefined' && window.location.pathname === '/';
export const Layout = ({ children }) => {
const [sidebarOpen, setSidebarOpen] = useState(getSidebarStatus());
const nav = useRef();
const handleSidebarToggle = () => {
setSidebarOpen(s => !s);
};
return (
<BaseLayout sx={{ '& > div': { flex: '1 1 auto' } }} data-testid="layout">
<Main
id="main-layout"
sx={styles.main}
className={classnames({
'overflow-hidden h-screen lg:overflow-auto': sidebarOpen,
})}
>
<Header onOpen={handleSidebarToggle} />
<div className={classnames('flex', {})}>
<Sidebar
ref={nav}
sidebarOpen={sidebarOpen}
onFocus={() => setSidebarOpen(true)}
onBlur={() => setSidebarOpen(false)}
onClick={() => setSidebarOpen(false)}
/>
<div
id="main-container"
className={classnames('py-10 w-full', {
'px-4 lg:px-20': sidebarOpen,
'px-4 lg:px-8': !sidebarOpen,
})}
>
{children}
</div>
</div>
</Main>
</BaseLayout>
);
};
@@ -1,56 +0,0 @@
/** @jsx jsx */
import { jsx } from 'theme-ui';
import React from 'react';
import { useCurrentDoc } from 'docz';
import * as styles from 'gatsby-theme-docz/src/components/NavGroup/styles';
import { NavLink } from 'gatsby-theme-docz/src/components/NavLink';
import { ChevronDown } from 'gatsby-theme-docz/src/components/Icons';
export const NavGroup = ({ item, sidebarRef }) => {
const currentDoc = useCurrentDoc();
const currentDocRef = React.useRef();
const { name, menu } = item;
const [subheadingsVisible, setShowsubheadings] = React.useState(
currentDoc.menu === name
);
const toggleSubheadings = () => setShowsubheadings(!subheadingsVisible);
React.useEffect(() => {
if (sidebarRef.current && currentDocRef.current) {
sidebarRef.current.scrollTo(0, currentDocRef.current.offsetTop);
}
}, [sidebarRef]);
return (
<div sx={styles.wrapper} data-testid="nav-group">
<div
sx={styles.title}
onClick={toggleSubheadings}
role="button"
onKeyDown={toggleSubheadings}
tabIndex="0"
>
{item.name}
<ChevronDown sx={styles.chevron({ active: subheadingsVisible })} />
</div>
<div sx={styles.sublinkWrapper} data-testid="nav-group-links">
{menu &&
subheadingsVisible &&
menu.map(menu => {
if (currentDoc.route === menu.route) {
return (
<NavLink key={menu.id} item={menu} ref={currentDocRef}>
{menu.name}
</NavLink>
);
}
return (
<NavLink key={menu.id} item={menu}>
{menu.name}
</NavLink>
);
})}
</div>
</div>
);
};
@@ -1,141 +0,0 @@
/** @jsx jsx */
/** @jsxFrag React.Fragment */
import React, { useState, useRef, useEffect } from 'react';
import classnames from 'classnames';
import { jsx } from 'theme-ui';
import { useMenus, useCurrentDoc } from 'docz';
import { NavSearch } from 'gatsby-theme-docz/src/components/NavSearch';
import { NavLink } from 'gatsby-theme-docz/src/components/NavLink';
import { NavGroup } from 'gatsby-theme-docz/src/components/NavGroup';
export const Sidebar = React.forwardRef((props, ref) => {
const [query, setQuery] = useState('');
const menus = useMenus({ query });
const currentDoc = useCurrentDoc();
const currentDocRef = useRef();
const handleChange = ev => {
setQuery(ev.target.value);
};
useEffect(() => {
if (ref.current && currentDocRef.current) {
ref.current.scrollTo(0, currentDocRef.current.offsetTop);
}
}, [ref]);
const customMenus = {
Components: [],
'Custom Hooks': [],
System: [],
Examples: [],
};
const MENU_CATEGORIES = {
Components: [
'General',
'Form',
'Navigation',
'Feedback',
'Data Display',
'Other',
],
'Custom Hooks': ['ModalProvider', 'ViewportDialogProvider'],
Examples: ['Views'],
System: ['Colors'],
};
const renderMenuCategories = () => {
return Object.keys(customMenus).map(menuName => {
return (
<div key={menuName}>
<h2 className="pl-2 border-l-8 -ml-4 border-secondary-active">
{menuName}
</h2>
{customMenus[menuName].map(item => item)}
</div>
);
});
};
const getMenuCategory = menuName => {
return Object.keys(MENU_CATEGORIES).find(category => {
if (MENU_CATEGORIES[category].includes(menuName)) {
return category;
}
return null;
});
};
return (
<>
{props.sidebarOpen && (
<>
<div className="block lg:hidden">
<div
role="button"
onClick={() => props.onClick()}
onKeyDown={() => props.onClick()}
className="fixed left-0 w-full h-full bg-black opacity-80"
style={{ top: 81, zIndex: 99999 }}
tabIndex="0"
/>
</div>
<div
ref={ref}
data-testid="sidebar"
className={classnames(
'p-8 flex-col bg-white top-0 overflow-auto border-r border-gray-400 hidden fixed left-0 bottom-0 lg:block lg:sticky lg:h-screen lg:top-0'
)}
style={{
display: props.sidebarOpen ? 'block' : 'none',
zIndex: 99999,
minWidth: 250,
}}
>
<NavSearch
placeholder="Type to search..."
value={query}
onChange={handleChange}
/>
{menus &&
menus.map(menu => {
const isGroup = !!menu.menu;
const Component = isGroup ? NavGroup : NavLink;
const menuCategory = getMenuCategory(menu.name) || null;
if (menuCategory) {
customMenus[menuCategory].push(
<Component key={menu.id} item={menu} sidebarRef={ref}>
{!isGroup && menu.name}
</Component>
);
return null;
}
if (!menu.route) {
return (
<NavGroup key={menu.id} item={menu} sidebarRef={ref} />
);
}
if (menu.route === currentDoc.route) {
return (
<NavLink key={menu.id} item={menu} ref={currentDocRef}>
{menu.name}
</NavLink>
);
}
return (
<NavLink key={menu.id} item={menu}>
{menu.name}
</NavLink>
);
})}
{renderMenuCategories()}
</div>
</>
)}
</>
);
});
@@ -1,24 +0,0 @@
/**
OVERRIDE DOCZ THEME
*/
[data-testid='live-preview'] {
background: #000;
}
#main-layout {
@apply font-sans;
}
#main-container > h2 {
@apply font-bold my-8 text-2xl;
}
#main-container > ul li a,
#main-container > a {
@apply underline text-blue-500;
}
code {
@apply bg-gray-200 text-lg text-black px-2 py-1 rounded;
}
@@ -1,13 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import './tailwind.css';
import './theme.css';
const Wrapper = ({ children }) => <>{children}</>;
Wrapper.propTypes = {
children: PropTypes.node,
};
export default Wrapper;
+102
View File
@@ -0,0 +1,102 @@
/** UTILS */
import utils from './utils';
export { utils };
/** CONTEXT/HOOKS */
export {
useCine,
CineProvider,
DialogProvider,
useDialog,
withDialog,
DragAndDropProvider,
ModalProvider,
ModalConsumer,
useModal,
withModal,
ImageViewerContext,
ImageViewerProvider,
useImageViewer,
SnackbarProvider,
useSnackbar,
withSnackbar,
ViewportDialogProvider,
useViewportDialog,
ViewportGridContext,
ViewportGridProvider,
useViewportGrid,
UserAuthenticationContext,
UserAuthenticationProvider,
useUserAuthentication,
} from './contextProviders';
/** COMPONENTS */
export {
AboutModal,
HotkeyField,
Header,
UserPreferences,
HotkeysPreferences,
Button,
ButtonGroup,
ContextMenu,
CinePlayer,
DateRange,
Dialog,
Dropdown,
EmptyStudies,
ErrorBoundary,
ExpandableToolbarButton,
ListMenu,
Icon,
IconButton,
Input,
InputDateRange,
InputGroup,
InputLabelWrapper,
InputMultiSelect,
InputText,
Label,
LayoutSelector,
MeasurementTable,
Modal,
NavBar,
Notification,
Select,
SegmentationTable,
SidePanel,
SplitButton,
StudyBrowser,
StudyItem,
StudyListExpandedRow,
StudyListFilter,
StudyListPagination,
StudyListTable,
StudyListTableRow,
StudySummary,
Svg,
Table,
TableBody,
TableCell,
TableHead,
TableRow,
ThemeWrapper,
Thumbnail,
ThumbnailNoImage,
ThumbnailTracked,
ThumbnailList,
ToolbarButton,
ContextMenuMeasurements,
Tooltip,
TooltipClipboard,
Typography,
Viewport,
ViewportActionBar,
ViewportDownloadForm,
ViewportGrid,
ViewportPane,
WindowLevelMenuItem,
} from './components';
/** VIEWS */
export { StudyList, Viewer } from './views';
-83
View File
@@ -1,83 +0,0 @@
---
name: Colors
route: system/colors
---
import { Playground, Props } from 'docz';
import BackgroundColor from './BackgroundColor';
# 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
<Playground>
<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>
</Playground>
## 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',
},
```
-47
View File
@@ -1,47 +0,0 @@
---
name: Getting Started
route: /
---
import { Playground } from 'docz';
import { Button } from '../components';
# 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';
```
<Playground className="p-8" style={{ padding: 8 }}>
<div className="p-8">
<Button onClick={() => alert('Hello!')}>Click here!</Button>
</div>
</Playground>
## Examples
In the **Examples** section you can check many examples on how to build your
application using `@ohif/ui` components.
...
File renamed without changes.
+4 -4
View File
@@ -284,10 +284,10 @@ const StudyList = () => {
/>
</>
) : (
<div className="flex flex-col items-center justify-center pt-48">
<EmptyStudies />
</div>
)}
<div className="flex flex-col items-center justify-center pt-48">
<EmptyStudies />
</div>
)}
</div>
);
};
@@ -1,347 +0,0 @@
---
name: Study List
menu: Views
route: examples/studyList
---
import { useState } from 'react';
import { Playground } from 'docz';
import {
Icon,
StudyListExpandedRow,
Button,
NavBar,
Svg,
IconButton,
EmptyStudies,
StudyListTable,
StudyListPagination,
StudyListFilter
} from '../../components';
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.
<Playground>
{() => {
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>
);
}}
</Playground>
@@ -1,178 +0,0 @@
---
name: Viewer
menu: Views
route: examples/viewer
---
import { useState } from 'react';
import { Playground, Props } from 'docz';
import {
NavBar,
SidePanel,
Svg,
SegmentationTable,
ButtonGroup,
Button,
Icon,
IconButton,
StudyBrowser,
ViewportActionBar,
Notification,
Viewport,
ViewportGrid,
ViewportPane,
StudySummary,
MeasurementTable,
} from '../../components';
import Header from './components/Header';
import { DragAndDropProvider } from '../../contextProviders';
import { tabs } from './studyBrowserMockData';
# Viewer
<Playground>
{() => {
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>
);
}}
</Playground>