feat(Calibration Tool): add a calibration tool that can manually recalibrate an image and measurements on it (#3136)
* minor bug fix - reading modalities * react error log fix - button props * react warn fix - Typography color prop * calibration tool without persistence * added toolbar button for calibration tool * icon change for calibration tool * important bug fix for calibration - length and calibration rate calculation * fix weird autocorrection * [fix] bugs after merging upstream * [refactor] conform to the new service names
This commit is contained in:
parent
7a36363735
commit
b15988359f
@ -12,12 +12,12 @@ import {
|
||||
} from '@cornerstonejs/tools';
|
||||
import { ServicesManager } from '@ohif/core';
|
||||
|
||||
import { getEnabledElement as OHIFgetEnabledElement } from './state';
|
||||
import CornerstoneViewportDownloadForm from './utils/CornerstoneViewportDownloadForm';
|
||||
import callInputDialog from './utils/callInputDialog';
|
||||
import { setColormap } from './utils/colormap/transferFunctionHelpers';
|
||||
import toggleMPRHangingProtocol from './utils/mpr/toggleMPRHangingProtocol';
|
||||
import toggleStackImageSync from './utils/stackSync/toggleStackImageSync';
|
||||
import getActiveViewportEnabledElement from './utils/getActiveViewportEnabledElement';
|
||||
|
||||
const commandsModule = ({ servicesManager }) => {
|
||||
const {
|
||||
@ -32,10 +32,7 @@ const commandsModule = ({ servicesManager }) => {
|
||||
} = (servicesManager as ServicesManager).services;
|
||||
|
||||
function _getActiveViewportEnabledElement() {
|
||||
const { activeViewportIndex } = viewportGridService.getState();
|
||||
const { element } = OHIFgetEnabledElement(activeViewportIndex) || {};
|
||||
const enabledElement = getEnabledElement(element);
|
||||
return enabledElement;
|
||||
return getActiveViewportEnabledElement(viewportGridService);
|
||||
}
|
||||
|
||||
function _getToolGroup(toolGroupId) {
|
||||
|
||||
@ -12,6 +12,7 @@ import {
|
||||
volumeLoader,
|
||||
imageLoadPoolManager,
|
||||
Settings,
|
||||
utilities as csUtilities,
|
||||
} from '@cornerstonejs/core';
|
||||
import { Enums, utilities, ReferenceLinesTool } from '@cornerstonejs/tools';
|
||||
import { cornerstoneStreamingImageVolumeLoader } from '@cornerstonejs/streaming-image-volume-loader';
|
||||
@ -126,6 +127,12 @@ export default async function init({
|
||||
);
|
||||
hangingProtocolService.registerImageLoadStrategy('nth', nthLoader);
|
||||
|
||||
// add metadata providers
|
||||
metaData.addProvider(
|
||||
csUtilities.calibratedPixelSpacingMetadataProvider.get.bind(
|
||||
csUtilities.calibratedPixelSpacingMetadataProvider
|
||||
)
|
||||
); // this provider is required for Calibration tool
|
||||
metaData.addProvider(metadataProvider.get.bind(metadataProvider), 9999);
|
||||
|
||||
imageLoadPoolManager.maxNumRequests = {
|
||||
@ -138,9 +145,7 @@ export default async function init({
|
||||
|
||||
/* Measurement Service */
|
||||
const measurementServiceSource = connectToolsToMeasurementService(
|
||||
measurementService,
|
||||
displaySetService,
|
||||
cornerstoneViewportService
|
||||
servicesManager
|
||||
);
|
||||
|
||||
initCineService(cineService);
|
||||
|
||||
@ -25,6 +25,8 @@ import {
|
||||
ReferenceLinesTool,
|
||||
} from '@cornerstonejs/tools';
|
||||
|
||||
import CalibrationLineTool from './tools/CalibrationLineTool';
|
||||
|
||||
export default function initCornerstoneTools(configuration = {}) {
|
||||
init(configuration);
|
||||
addTool(PanTool);
|
||||
@ -48,6 +50,7 @@ export default function initCornerstoneTools(configuration = {}) {
|
||||
addTool(CrosshairsTool);
|
||||
addTool(SegmentationDisplayTool);
|
||||
addTool(ReferenceLinesTool);
|
||||
addTool(CalibrationLineTool);
|
||||
|
||||
// Modify annotation tools to use dashed lines on SR
|
||||
const annotationStyle = {
|
||||
@ -86,6 +89,7 @@ const toolNames = {
|
||||
Crosshairs: CrosshairsTool.toolName,
|
||||
SegmentationDisplay: SegmentationDisplayTool.toolName,
|
||||
ReferenceLines: ReferenceLinesTool.toolName,
|
||||
CalibrationLine: CalibrationLineTool.toolName,
|
||||
};
|
||||
|
||||
export { toolNames };
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { eventTarget } from '@cornerstonejs/core';
|
||||
import { Enums, annotation } from '@cornerstonejs/tools';
|
||||
import { DicomMetadataStore, MeasurementService } from '@ohif/core';
|
||||
import { DicomMetadataStore } from '@ohif/core';
|
||||
import { toolNames } from './initCornerstoneTools';
|
||||
import { onCompletedCalibrationLine } from './tools/CalibrationLineTool';
|
||||
|
||||
import measurementServiceMappingsFactory from './utils/measurementServiceMappings/measurementServiceMappingsFactory';
|
||||
import getSOPInstanceAttributes from './utils/measurementServiceMappings/utils/getSOPInstanceAttributes';
|
||||
@ -102,14 +104,25 @@ const initMeasurementService = (
|
||||
PlanarFreehandROI.toMeasurement
|
||||
);
|
||||
|
||||
// On the UI side, the Calibration Line tool will work almost the same as the
|
||||
// Length tool
|
||||
measurementService.addMapping(
|
||||
csTools3DVer1MeasurementSource,
|
||||
'CalibrationLine',
|
||||
Length.matchingCriteria,
|
||||
Length.toAnnotation,
|
||||
Length.toMeasurement
|
||||
);
|
||||
|
||||
return csTools3DVer1MeasurementSource;
|
||||
};
|
||||
|
||||
const connectToolsToMeasurementService = (
|
||||
measurementService,
|
||||
displaySetService,
|
||||
cornerstoneViewportService
|
||||
) => {
|
||||
const connectToolsToMeasurementService = servicesManager => {
|
||||
const {
|
||||
measurementService,
|
||||
displaySetService,
|
||||
cornerstoneViewportService,
|
||||
} = servicesManager.services;
|
||||
const csTools3DVer1MeasurementSource = initMeasurementService(
|
||||
measurementService,
|
||||
displaySetService,
|
||||
@ -131,15 +144,38 @@ const connectToolsToMeasurementService = (
|
||||
} = annotationAddedEventDetail;
|
||||
const { toolName } = metadata;
|
||||
|
||||
// To force the measurementUID be the same as the annotationUID
|
||||
// Todo: this should be changed when a measurement can include multiple annotations
|
||||
// in the future
|
||||
annotationAddedEventDetail.uid = annotationUID;
|
||||
annotationToMeasurement(toolName, annotationAddedEventDetail);
|
||||
if (
|
||||
csToolsEvent.type === completedEvt &&
|
||||
toolName === toolNames.CalibrationLine
|
||||
) {
|
||||
// show modal to input the measurement (mm)
|
||||
onCompletedCalibrationLine(servicesManager, csToolsEvent)
|
||||
.then(
|
||||
() => {
|
||||
console.log('calibration applied');
|
||||
},
|
||||
() => true
|
||||
)
|
||||
.finally(() => {
|
||||
// we don't need the calibration line lingering around, remove the
|
||||
// annotation from the display
|
||||
removeAnnotation(annotationUID);
|
||||
removeMeasurement(csToolsEvent);
|
||||
// this will ensure redrawing of annotations
|
||||
cornerstoneViewportService.resize();
|
||||
});
|
||||
} else {
|
||||
// To force the measurementUID be the same as the annotationUID
|
||||
// Todo: this should be changed when a measurement can include multiple annotations
|
||||
// in the future
|
||||
annotationAddedEventDetail.uid = annotationUID;
|
||||
annotationToMeasurement(toolName, annotationAddedEventDetail);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Failed to update measurement:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function updateMeasurement(csToolsEvent) {
|
||||
try {
|
||||
const annotationModifiedEventDetail = csToolsEvent.detail;
|
||||
|
||||
134
extensions/cornerstone/src/tools/CalibrationLineTool.ts
Normal file
134
extensions/cornerstone/src/tools/CalibrationLineTool.ts
Normal file
@ -0,0 +1,134 @@
|
||||
import { metaData } from '@cornerstonejs/core';
|
||||
import { LengthTool } from '@cornerstonejs/tools';
|
||||
import { calibrateImageSpacing } from '@cornerstonejs/tools/dist/esm/utilities';
|
||||
import callInputDialog from '../utils/callInputDialog';
|
||||
import getActiveViewportEnabledElement from '../utils/getActiveViewportEnabledElement';
|
||||
|
||||
/**
|
||||
* Calibration Line tool works almost the same as the
|
||||
*/
|
||||
class CalibrationLineTool extends LengthTool {
|
||||
static toolName = 'CalibrationLine';
|
||||
|
||||
_renderingViewport: any;
|
||||
_lengthToolRenderAnnotation = this.renderAnnotation;
|
||||
|
||||
renderAnnotation = (enabledElement, svgDrawingHelper) => {
|
||||
const { viewport } = enabledElement;
|
||||
this._renderingViewport = viewport;
|
||||
return this._lengthToolRenderAnnotation(enabledElement, svgDrawingHelper);
|
||||
};
|
||||
|
||||
_getTextLines(data, targetId) {
|
||||
const [canvasPoint1, canvasPoint2] = data.handles.points.map(p =>
|
||||
this._renderingViewport.worldToCanvas(p)
|
||||
);
|
||||
// for display, round to 2 decimal points
|
||||
const lengthPx =
|
||||
Math.round(calculateLength2(canvasPoint1, canvasPoint2) * 100) / 100;
|
||||
|
||||
const textLines = [`${lengthPx}px`];
|
||||
|
||||
return textLines;
|
||||
}
|
||||
}
|
||||
|
||||
function calculateLength2(point1, point2) {
|
||||
const dx = point1[0] - point2[0];
|
||||
const dy = point1[1] - point2[1];
|
||||
return Math.sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
function calculateLength3(pos1, pos2) {
|
||||
const dx = pos1[0] - pos2[0];
|
||||
const dy = pos1[1] - pos2[1];
|
||||
const dz = pos1[2] - pos2[2];
|
||||
|
||||
return Math.sqrt(dx * dx + dy * dy + dz * dz);
|
||||
}
|
||||
|
||||
export default CalibrationLineTool;
|
||||
|
||||
export function onCompletedCalibrationLine(servicesManager, csToolsEvent) {
|
||||
const { uiDialogService, viewportGridService } = servicesManager.services;
|
||||
|
||||
// calculate length (mm) with the current Pixel Spacing
|
||||
const annotationAddedEventDetail = csToolsEvent.detail;
|
||||
const {
|
||||
annotation: { metadata, data: annotationData },
|
||||
} = annotationAddedEventDetail;
|
||||
const { referencedImageId: imageId } = metadata;
|
||||
const enabledElement = getActiveViewportEnabledElement(viewportGridService);
|
||||
const { viewport } = enabledElement;
|
||||
|
||||
const length =
|
||||
Math.round(
|
||||
calculateLength3(
|
||||
annotationData.handles.points[0],
|
||||
annotationData.handles.points[1]
|
||||
) * 100
|
||||
) / 100;
|
||||
|
||||
// calculate the currently applied pixel spacing on the viewport
|
||||
const calibratedPixelSpacing = metaData.get(
|
||||
'calibratedPixelSpacing',
|
||||
imageId
|
||||
);
|
||||
const imagePlaneModule = metaData.get('imagePlaneModule', imageId);
|
||||
const currentRowPixelSpacing =
|
||||
calibratedPixelSpacing?.[0] || imagePlaneModule?.rowPixelSpacing || 1;
|
||||
const currentColumnPixelSpacing =
|
||||
calibratedPixelSpacing?.[1] || imagePlaneModule?.columnPixelSpacing || 1;
|
||||
|
||||
const adjustCalibration = newLength => {
|
||||
const spacingScale = newLength / length;
|
||||
const rowSpacing = spacingScale * currentRowPixelSpacing;
|
||||
const colSpacing = spacingScale * currentColumnPixelSpacing;
|
||||
|
||||
// trigger resize of the viewport to adjust the world/pixel mapping
|
||||
calibrateImageSpacing(
|
||||
imageId,
|
||||
viewport.getRenderingEngine(),
|
||||
rowSpacing,
|
||||
colSpacing
|
||||
);
|
||||
};
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!uiDialogService) {
|
||||
reject('UIDialogService is not initiated');
|
||||
return;
|
||||
}
|
||||
|
||||
callInputDialog(
|
||||
uiDialogService,
|
||||
{
|
||||
text: '',
|
||||
label: `${length}`,
|
||||
},
|
||||
(value, id) => {
|
||||
if (id === 'save') {
|
||||
adjustCalibration(Number.parseFloat(value));
|
||||
resolve(true);
|
||||
} else {
|
||||
reject('cancel');
|
||||
}
|
||||
},
|
||||
false,
|
||||
{
|
||||
dialogTitle: 'Calibration',
|
||||
inputLabel: 'Actual Physical distance (mm)',
|
||||
|
||||
// the input value must be a number
|
||||
validateFunc: val => {
|
||||
try {
|
||||
const v = Number.parseFloat(val);
|
||||
return !isNaN(v) && v !== 0.0;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
@ -9,23 +9,35 @@ import { Input, Dialog } from '@ohif/ui';
|
||||
* @param {*} event
|
||||
* @param {*} callback
|
||||
* @param {*} isArrowAnnotateInputDialog
|
||||
* @param {*} dialogConfig
|
||||
* @param {string?} dialogConfig.dialogTitle - title of the input dialog
|
||||
* @param {string?} dialogConfig.inputLabel - show label above the input
|
||||
*/
|
||||
function callInputDialog(
|
||||
uiDialogService,
|
||||
data,
|
||||
callback,
|
||||
isArrowAnnotateInputDialog = true
|
||||
isArrowAnnotateInputDialog = true,
|
||||
dialogConfig: any = {}
|
||||
) {
|
||||
const dialogId = 'enter-annotation';
|
||||
const dialogId = 'dialog-enter-annotation';
|
||||
const label = data
|
||||
? isArrowAnnotateInputDialog
|
||||
? data.text
|
||||
: data.label
|
||||
: '';
|
||||
const {
|
||||
dialogTitle = 'Enter your annotation',
|
||||
inputLabel = '',
|
||||
validateFunc = value => true,
|
||||
} = dialogConfig;
|
||||
|
||||
const onSubmitHandler = ({ action, value }) => {
|
||||
switch (action.id) {
|
||||
case 'save':
|
||||
if (typeof validateFunc === 'function' && !validateFunc(value.label))
|
||||
return;
|
||||
|
||||
callback(value.label, action.id);
|
||||
break;
|
||||
case 'cancel':
|
||||
@ -43,7 +55,7 @@ function callInputDialog(
|
||||
showOverlay: true,
|
||||
content: Dialog,
|
||||
contentProps: {
|
||||
title: 'Enter your annotation',
|
||||
title: dialogTitle,
|
||||
value: { label },
|
||||
noCloseButton: true,
|
||||
onClose: () => uiDialogService.dismiss({ id: dialogId }),
|
||||
@ -61,6 +73,8 @@ function callInputDialog(
|
||||
type="text"
|
||||
id="annotation"
|
||||
containerClassName="mr-2"
|
||||
label={inputLabel}
|
||||
labelClassName="text-primary-light"
|
||||
value={value.label}
|
||||
onChange={event => {
|
||||
event.persist();
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
import { getEnabledElement } from '@cornerstonejs/core';
|
||||
import { IEnabledElement } from '@cornerstonejs/core/dist/esm/types';
|
||||
|
||||
import { getEnabledElement as OHIFgetEnabledElement } from '../state';
|
||||
|
||||
export default function getActiveViewportEnabledElement(
|
||||
viewportGridService
|
||||
): IEnabledElement {
|
||||
const { activeViewportIndex } = viewportGridService.getState();
|
||||
const { element } = OHIFgetEnabledElement(activeViewportIndex) || {};
|
||||
const enabledElement = getEnabledElement(element);
|
||||
return enabledElement;
|
||||
}
|
||||
@ -83,6 +83,7 @@ function modeFactory({ modeConfiguration }) {
|
||||
{ toolName: toolNames.EllipticalROI },
|
||||
{ toolName: toolNames.RectangleROI },
|
||||
{ toolName: toolNames.StackScroll },
|
||||
{ toolName: toolNames.CalibrationLine },
|
||||
],
|
||||
// enabled
|
||||
// disabled
|
||||
|
||||
@ -323,6 +323,21 @@ const toolbarButtons = [
|
||||
],
|
||||
'Invert Colors'
|
||||
),
|
||||
_createToolButton(
|
||||
'CalibrationLine',
|
||||
'tool-calibration',
|
||||
'Calibration',
|
||||
[
|
||||
{
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: {
|
||||
toolName: 'CalibrationLine',
|
||||
},
|
||||
context: 'CORNERSTONE',
|
||||
},
|
||||
],
|
||||
'Calibration Line'
|
||||
),
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
@ -39,6 +39,7 @@ function initDefaultToolGroup(
|
||||
{ toolName: toolNames.PlanarFreehandROI },
|
||||
{ toolName: toolNames.Magnify },
|
||||
{ toolName: toolNames.SegmentationDisplay },
|
||||
{ toolName: toolNames.CalibrationLine },
|
||||
],
|
||||
// enabled
|
||||
// disabled
|
||||
|
||||
@ -555,6 +555,21 @@ const toolbarButtons = [
|
||||
],
|
||||
'Rectangle'
|
||||
),
|
||||
_createToolButton(
|
||||
'CalibrationLine',
|
||||
'tool-calibration',
|
||||
'Calibration',
|
||||
[
|
||||
{
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: {
|
||||
toolName: 'CalibrationLine',
|
||||
},
|
||||
context: 'CORNERSTONE',
|
||||
},
|
||||
],
|
||||
'Calibration Line'
|
||||
),
|
||||
_createActionButton(
|
||||
'TagBrowser',
|
||||
'list-bullets',
|
||||
|
||||
@ -8,6 +8,10 @@ export default function getModalities(Modality, ModalitiesInStudy) {
|
||||
Value: [],
|
||||
};
|
||||
|
||||
// Rare case, depending on the DICOM server we are using, but sometimes,
|
||||
// modalities.Value is undefined or null.
|
||||
modalities.Value = modalities.Value || [];
|
||||
|
||||
if (ModalitiesInStudy) {
|
||||
if (modalities.vr && modalities.vr === ModalitiesInStudy.vr) {
|
||||
for (let i = 0; i < ModalitiesInStudy.Value.length; i++) {
|
||||
|
||||
@ -24,6 +24,7 @@ The basic viewer comes with the following default measurement tools:
|
||||
- Bidirectional Tool: Creates a measurement of the longest diameter (LD) and longest perpendicular diameter (LPD) in *mm*
|
||||
- Annotation: Used to create a qualitative marker with a freetext label
|
||||
- Ellipse: Measures an elliptical area in *mm<sup>2</sup>* and Hounsfield Units (HU)
|
||||
- Calibration Tool: Calibrate (or override) the Pixel Spacing Attribute (Physical distance in the patient between the center of each pixel, specified by a numeric pair - adjacent row spacing (delimiter) adjacent column spacing in mm)
|
||||
|
||||
When a measurement tool is selected from the toolbar, it becomes the `active` tool. Use the caret to expand the measurement tools and select another tool.
|
||||
<!-- We should add a smaller screenshot for each measurement tool. Maybe have a matrix with 4 identical sized screenshots in a box? Also we should make sure the screenshots have more realistic measurements -->
|
||||
|
||||
@ -24,6 +24,7 @@ The basic viewer comes with the following default measurement tools:
|
||||
- Bidirectional Tool: Creates a measurement of the longest diameter (LD) and longest perpendicular diameter (LPD) in *mm*
|
||||
- Annotation: Used to create a qualitative marker with a freetext label
|
||||
- Ellipse: Measures an elliptical area in *mm<sup>2</sup>* and Hounsfield Units (HU)
|
||||
- Calibration Tool: Calibrate (or override) the Pixel Spacing Attribute (Physical distance in the patient between the center of each pixel, specified by a numeric pair - adjacent row spacing (delimiter) adjacent column spacing in mm)
|
||||
|
||||
When a measurement tool is selected from the toolbar, it becomes the `active` tool. Use the caret to expand the measurement tools and select another tool.
|
||||
<!-- We should add a smaller screenshot for each measurement tool. Maybe have a matrix with 4 identical sized screenshots in a box? Also we should make sure the screenshots have more realistic measurements -->
|
||||
|
||||
21
platform/ui/src/assets/icons/tool-calibration.svg
Normal file
21
platform/ui/src/assets/icons/tool-calibration.svg
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="25px" height="25px" viewBox="0 0 25 25" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="color" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="measure-calibrate" transform="translate(0.500000, 4.000000)" stroke="currentColor">
|
||||
<g id="calibrate" transform="translate(0.500000, 11.500000)" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="1.25">
|
||||
<polyline id="Path" points="20 6 23 3 20 0"></polyline>
|
||||
<line x1="1" y1="3" x2="22" y2="3" id="Path"></line>
|
||||
<polyline id="Path" points="3 6 0 3 3 0"></polyline>
|
||||
</g>
|
||||
<rect id="Rectangle" stroke-width="1.25" x="0" y="0" width="24" height="6" rx="2"></rect>
|
||||
<line x1="4.5" y1="5.5" x2="4.5" y2="3.5" id="Line-5" stroke-linecap="round"></line>
|
||||
<line x1="7.5" y1="5.5" x2="7.5" y2="3.5" id="Line-5" stroke-linecap="round"></line>
|
||||
<line x1="10.5" y1="5.5" x2="10.5" y2="3.5" id="Line-5" stroke-linecap="round"></line>
|
||||
<line x1="13.5" y1="5.5" x2="13.5" y2="3.5" id="Line-5" stroke-linecap="round"></line>
|
||||
<line x1="16.5" y1="5.5" x2="16.5" y2="3.5" id="Line-5" stroke-linecap="round"></line>
|
||||
<line x1="19.5" y1="5.5" x2="19.5" y2="3.5" id="Line-5" stroke-linecap="round"></line>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
@ -227,6 +227,7 @@ Button.propTypes = {
|
||||
/** Button corner roundness */
|
||||
rounded: PropTypes.oneOf(['none', 'small', 'medium', 'large', 'full']),
|
||||
variant: PropTypes.oneOf(['text', 'outlined', 'contained', 'disabled']),
|
||||
/* color prop must have all the possible keys of variants defined above */
|
||||
color: PropTypes.oneOf([
|
||||
'default',
|
||||
'primary',
|
||||
|
||||
@ -82,6 +82,7 @@ import toolReset from './../../assets/icons/tool-reset.svg';
|
||||
import toolRectangle from './../../assets/icons/tool-rectangle.svg';
|
||||
import toolFusionColor from './../../assets/icons/tool-fusion-color.svg';
|
||||
import toolCreateThreshold from './../../assets/icons/tool-create-threshold.svg';
|
||||
import toolCalibration from './../../assets/icons/tool-calibration.svg';
|
||||
import editPatient from './../../assets/icons/edit-patient.svg';
|
||||
import panelGroupMore from './../../assets/icons/panel-group-more.svg';
|
||||
import panelGroupOpenClose from './../../assets/icons/panel-group-open-close.svg';
|
||||
@ -185,6 +186,7 @@ const ICONS = {
|
||||
'tool-rectangle': toolRectangle,
|
||||
'tool-fusion-color': toolFusionColor,
|
||||
'tool-create-threshold': toolCreateThreshold,
|
||||
'tool-calibration': toolCalibration,
|
||||
'edit-patient': editPatient,
|
||||
'icon-mpr': iconMPR,
|
||||
'icon-next-inactive': iconNextInactive,
|
||||
|
||||
@ -133,6 +133,7 @@ Typography.propTypes = {
|
||||
'primaryActive',
|
||||
'secondary',
|
||||
'error',
|
||||
'primaryActive',
|
||||
]),
|
||||
className: PropTypes.string,
|
||||
children: PropTypes.node,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user