ng-cornerstone
Version:
[](https://github.com/prettier/prettier) [](http://commitizen.git
949 lines (935 loc) • 127 kB
JavaScript
import { coerceBooleanProperty, _isNumberValue, coerceCssPixelValue } from '@angular/cdk/coercion';
import * as cornerstone from '@cornerstonejs/core';
import { utilities, volumeLoader, cornerstoneStreamingImageVolumeLoader, cornerstoneStreamingDynamicImageVolumeLoader, imageLoader, init, RenderingEngine, eventTarget, cache, metaData, StackViewport, Enums, getRenderingEngine, setVolumesForViewports, CONSTANTS } from '@cornerstonejs/core';
import { cornerstoneNiftiImageLoader, createNiftiImageIdsAndCacheMetadata } from '@cornerstonejs/nifti-volume-loader';
import * as polySeg from '@cornerstonejs/polymorphic-segmentation';
import * as i0 from '@angular/core';
import { Injectable, Input, ChangeDetectionStrategy, Component, EventEmitter, HostBinding, Output, HostListener, ContentChildren, Inject, Optional, NgModule, SkipSelf, ElementRef, ViewChild, Directive, ViewChildren, ViewEncapsulation, APP_INITIALIZER } from '@angular/core';
import { init as init$1, destroy, StackScrollTool, WindowLevelTool, PanTool, ZoomTool, TrackballRotateTool, EllipticalROITool, RectangleROITool, LengthTool, AngleTool, ArrowAnnotateTool, ToolGroupManager, state, addTool, Enums as Enums$1, segmentation } from '@cornerstonejs/tools';
import cornerstoneDICOMImageLoader from '@cornerstonejs/dicom-image-loader';
import { api } from 'dicomweb-client';
import dcmjs from 'dcmjs';
import { calculateSUVScalingFactors } from '@cornerstonejs/calculate-suv';
import { __decorate } from 'tslib';
import { Subject, from, merge, filter, startWith, debounceTime, BehaviorSubject, combineLatest, map } from 'rxjs';
import * as i2 from '@angular/common';
import { DOCUMENT, CommonModule } from '@angular/common';
import { takeUntil, switchMap } from 'rxjs/operators';
var RequestSchema;
(function (RequestSchema) {
RequestSchema["wadoRs"] = "wadors:";
RequestSchema["wadoUri"] = "wadouri:";
RequestSchema["nifti"] = "nifti:";
})(RequestSchema || (RequestSchema = {}));
var VolumeLoaderSchema;
(function (VolumeLoaderSchema) {
VolumeLoaderSchema["stream"] = "cornerstoneStreamingImageVolume";
VolumeLoaderSchema["dynamicStream"] = "cornerstoneStreamingDynamicImageVolume";
VolumeLoaderSchema["nifti"] = "nifti";
})(VolumeLoaderSchema || (VolumeLoaderSchema = {}));
function imageInfoToUniqueId(imageInfo) {
if (imageInfo) {
if (imageInfo.schema === RequestSchema.wadoRs) {
return RequestSchema.wadoRs + imageInfo?.studyInstanceUID + imageInfo?.seriesInstanceUID;
}
else if (imageInfo.schema === RequestSchema.nifti) {
return RequestSchema.nifti + imageInfo.urlRoot;
}
else {
console.error('Unsupported request schema');
return '';
}
}
return '';
}
/**
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
*/
function toBoolean(value) {
return coerceBooleanProperty(value);
}
function toNumber(value, fallbackValue = 0) {
return _isNumberValue(value) ? Number(value) : fallbackValue;
}
function toCssPixel(value) {
return coerceCssPixelValue(value);
}
// eslint-disable no-invalid-this
/**
* Get the function-property type's value
*/
function valueFunctionProp(prop, ...args) {
return typeof prop === 'function' ? prop(...args) : prop;
}
function propDecoratorFactory(name, fallback) {
function propDecorator(target, propName, originalDescriptor) {
const privatePropName = `$$__zorroPropDecorator__${propName}`;
if (Object.prototype.hasOwnProperty.call(target, privatePropName)) {
console.warn(`The prop "${privatePropName}" is already exist, it will be overrided by ${name} decorator.`);
}
Object.defineProperty(target, privatePropName, {
configurable: true,
writable: true,
});
return {
get() {
return originalDescriptor && originalDescriptor.get
? originalDescriptor.get.bind(this)()
: this[privatePropName];
},
set(value) {
if (originalDescriptor && originalDescriptor.set) {
originalDescriptor.set.bind(this)(fallback(value));
}
this[privatePropName] = fallback(value);
},
};
}
return propDecorator;
}
/**
* Input decorator that handle a prop to do get/set automatically with toBoolean
*
* Why not using @InputBoolean alone without @Input? AOT needs @Input to be visible
*
* @howToUse
* ```
* @Input() @InputBoolean() visible: boolean = false;
*
* // Act as below:
* // @Input()
* // get visible() { return this.__visible; }
* // set visible(value) { this.__visible = value; }
* // __visible = false;
* ```
*/
function InputBoolean() {
return propDecoratorFactory('InputBoolean', toBoolean);
}
function InputCssPixel() {
return propDecoratorFactory('InputCssPixel', toCssPixel);
}
function InputNumber(fallbackValue) {
return propDecoratorFactory('InputNumber', (value) => toNumber(value, fallbackValue));
}
const scalingPerImageId = {};
function addInstance(imageId, scalingMetaData) {
const imageURI = utilities.imageIdToURI(imageId);
scalingPerImageId[imageURI] = scalingMetaData;
}
function get(type, imageId) {
if (type === 'scalingModule') {
const imageURI = utilities.imageIdToURI(imageId);
return scalingPerImageId[imageURI];
}
}
var ptScalingMetaDataProvider = { addInstance, get };
const { calibratedPixelSpacingMetadataProvider } = cornerstone.utilities;
function initProviders() {
cornerstone.metaData.addProvider(ptScalingMetaDataProvider.get.bind(ptScalingMetaDataProvider), 10000);
cornerstone.metaData.addProvider(calibratedPixelSpacingMetadataProvider.get.bind(calibratedPixelSpacingMetadataProvider), 11000);
}
function initVolumeLoader() {
volumeLoader.registerUnknownVolumeLoader(cornerstoneStreamingImageVolumeLoader);
volumeLoader.registerVolumeLoader(VolumeLoaderSchema.stream, cornerstoneStreamingImageVolumeLoader);
volumeLoader.registerVolumeLoader(VolumeLoaderSchema.dynamicStream, cornerstoneStreamingDynamicImageVolumeLoader);
imageLoader.registerImageLoader(VolumeLoaderSchema.nifti, cornerstoneNiftiImageLoader);
}
class CornerstoneService {
constructor() {
this.renderingEngineId = 'RENDERING_ENGINE_ID';
this.initialized = false;
}
async init() {
try {
if (this.initialized) {
return;
}
initProviders();
cornerstoneDICOMImageLoader.init();
initVolumeLoader();
await Promise.all([
init(),
init$1({
addons: {
polySeg: polySeg,
},
}),
]);
this.renderingEngine = new RenderingEngine(this.renderingEngineId);
this.initialized = true;
console.debug('CornerstoneService initialized');
}
catch (error) {
console.error('Failed to initialize CornerstoneService:', error);
throw error;
}
}
checkInitialized() {
if (!this.initialized) {
throw new Error('CornerstoneService not initialized');
}
}
setToolGroup(toolGroup) {
this.toolGroup = toolGroup;
}
getRenderingEngine() {
this.checkInitialized();
return this.renderingEngine;
}
getRenderingEngineId() {
return this.renderingEngineId;
}
getToolGroup() {
return this.toolGroup;
}
ngOnDestroy() {
this.renderingEngine.destroy();
eventTarget.reset();
cache.purgeCache();
destroy();
metaData.removeAllProviders();
imageLoader.unregisterAllImageLoaders();
console.debug('cs service destroyed');
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CornerstoneService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CornerstoneService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CornerstoneService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
}]
}], ctorParameters: () => [] });
// See https://github.com/OHIF/Viewers/blob/94a9067fe3d291d30e25a1bda5913511388edea2/platform/core/src/utils/metadataProvider/getPixelSpacingInformation.js
function getPixelSpacingInformation(instance) {
// See http://gdcm.sourceforge.net/wiki/index.php/Imager_Pixel_Spacing
// TODO: Add Ultrasound region spacing
// TODO: Add manual calibration
// TODO: Use ENUMS from dcmjs
const projectionRadiographSOPClassUIDs = [
'1.2.840.10008.5.1.4.1.1.1', // CR Image Storage
'1.2.840.10008.5.1.4.1.1.1.1', // Digital X-Ray Image Storage – for Presentation
'1.2.840.10008.5.1.4.1.1.1.1.1', // Digital X-Ray Image Storage – for Processing
'1.2.840.10008.5.1.4.1.1.1.2', // Digital Mammography X-Ray Image Storage – for Presentation
'1.2.840.10008.5.1.4.1.1.1.2.1', // Digital Mammography X-Ray Image Storage – for Processing
'1.2.840.10008.5.1.4.1.1.1.3', // Digital Intra – oral X-Ray Image Storage – for Presentation
'1.2.840.10008.5.1.4.1.1.1.3.1', // Digital Intra – oral X-Ray Image Storage – for Processing
'1.2.840.10008.5.1.4.1.1.12.1', // X-Ray Angiographic Image Storage
'1.2.840.10008.5.1.4.1.1.12.1.1', // Enhanced XA Image Storage
'1.2.840.10008.5.1.4.1.1.12.2', // X-Ray Radiofluoroscopic Image Storage
'1.2.840.10008.5.1.4.1.1.12.2.1', // Enhanced XRF Image Storage
'1.2.840.10008.5.1.4.1.1.12.3', // X-Ray Angiographic Bi-plane Image Storage Retired
];
const { PixelSpacing, ImagerPixelSpacing, SOPClassUID, PixelSpacingCalibrationType, PixelSpacingCalibrationDescription, EstimatedRadiographicMagnificationFactor, SequenceOfUltrasoundRegions, } = instance;
const isProjection = projectionRadiographSOPClassUIDs.includes(SOPClassUID);
const TYPES = {
NOT_APPLICABLE: 'NOT_APPLICABLE',
UNKNOWN: 'UNKNOWN',
CALIBRATED: 'CALIBRATED',
DETECTOR: 'DETECTOR',
};
if (!isProjection) {
return PixelSpacing;
}
if (isProjection && !ImagerPixelSpacing) {
// If only Pixel Spacing is present, and this is a projection radiograph,
// PixelSpacing should be used, but the user should be informed that
// what it means is unknown
return {
PixelSpacing,
type: TYPES.UNKNOWN,
isProjection,
};
}
else if (PixelSpacing && ImagerPixelSpacing && PixelSpacing === ImagerPixelSpacing) {
// If Imager Pixel Spacing and Pixel Spacing are present and they have the same values,
// then the user should be informed that the measurements are at the detector plane
return {
PixelSpacing,
type: TYPES.DETECTOR,
isProjection,
};
}
else if (PixelSpacing && ImagerPixelSpacing && PixelSpacing !== ImagerPixelSpacing) {
// If Imager Pixel Spacing and Pixel Spacing are present and they have different values,
// then the user should be informed that these are "calibrated"
// (in some unknown manner if Pixel Spacing Calibration Type and/or
// Pixel Spacing Calibration Description are absent)
return {
PixelSpacing,
type: TYPES.CALIBRATED,
isProjection,
PixelSpacingCalibrationType,
PixelSpacingCalibrationDescription,
};
}
else if (!PixelSpacing && ImagerPixelSpacing) {
let CorrectedImagerPixelSpacing = ImagerPixelSpacing;
if (EstimatedRadiographicMagnificationFactor) {
// Note that in IHE Mammo profile compliant displays, the value of Imager Pixel Spacing is required to be corrected by
// Estimated Radiographic Magnification Factor and the user informed of that.
// TODO: should this correction be done before all of this logic?
CorrectedImagerPixelSpacing = ImagerPixelSpacing.map((pixelSpacing) => pixelSpacing / EstimatedRadiographicMagnificationFactor);
}
else {
console.warn('EstimatedRadiographicMagnificationFactor was not present. Unable to correct ImagerPixelSpacing.');
}
return {
PixelSpacing: CorrectedImagerPixelSpacing,
isProjection,
};
}
else if (SequenceOfUltrasoundRegions && typeof SequenceOfUltrasoundRegions === 'object') {
const { PhysicalDeltaX, PhysicalDeltaY } = SequenceOfUltrasoundRegions;
const USPixelSpacing = [PhysicalDeltaX * 10, PhysicalDeltaY * 10];
return {
PixelSpacing: USPixelSpacing,
};
}
else if (SequenceOfUltrasoundRegions &&
Array.isArray(SequenceOfUltrasoundRegions) &&
SequenceOfUltrasoundRegions.length > 1) {
console.warn('Sequence of Ultrasound Regions > one entry. This is not yet implemented, all measurements will be shown in pixels.');
}
else if (!isProjection && !ImagerPixelSpacing) {
// If only Pixel Spacing is present, and this is not a projection radiograph,
// we can stop here
return {
PixelSpacing,
type: TYPES.NOT_APPLICABLE,
isProjection,
};
}
console.warn('Unknown combination of PixelSpacing and ImagerPixelSpacing identified. Unable to determine spacing.');
}
function getPTImageIdInstanceMetadata(imageId) {
const petSequenceModule = metaData.get('petIsotopeModule', imageId);
const generalSeriesModule = metaData.get('generalSeriesModule', imageId);
const patientStudyModule = metaData.get('patientStudyModule', imageId);
const ptSeriesModule = metaData.get('petSeriesModule', imageId);
const ptImageModule = metaData.get('petImageModule', imageId);
if (!petSequenceModule) {
throw new Error('petSequenceModule metadata is required');
}
const radiopharmaceuticalInfo = petSequenceModule.radiopharmaceuticalInfo;
const { seriesDate, seriesTime, acquisitionDate, acquisitionTime } = generalSeriesModule;
const { patientWeight } = patientStudyModule;
const { correctedImage, units, decayCorrection } = ptSeriesModule;
if (seriesDate === undefined ||
seriesTime === undefined ||
patientWeight === undefined ||
acquisitionDate === undefined ||
acquisitionTime === undefined ||
correctedImage === undefined ||
units === undefined ||
decayCorrection === undefined ||
radiopharmaceuticalInfo.radionuclideTotalDose === undefined ||
radiopharmaceuticalInfo.radionuclideHalfLife === undefined ||
(radiopharmaceuticalInfo.radiopharmaceuticalStartDateTime === undefined &&
seriesDate === undefined &&
radiopharmaceuticalInfo.radiopharmaceuticalStartTime === undefined)
//
) {
throw new Error('required metadata are missing');
}
const instanceMetadata = {
CorrectedImage: correctedImage,
Units: units,
RadionuclideHalfLife: radiopharmaceuticalInfo.radionuclideHalfLife,
RadionuclideTotalDose: radiopharmaceuticalInfo.radionuclideTotalDose,
DecayCorrection: decayCorrection,
PatientWeight: patientWeight,
SeriesDate: seriesDate,
SeriesTime: seriesTime,
AcquisitionDate: acquisitionDate,
AcquisitionTime: acquisitionTime,
};
if (radiopharmaceuticalInfo.radiopharmaceuticalStartDateTime &&
radiopharmaceuticalInfo.radiopharmaceuticalStartDateTime !== undefined &&
typeof radiopharmaceuticalInfo.radiopharmaceuticalStartDateTime === 'string') {
instanceMetadata.RadiopharmaceuticalStartDateTime = radiopharmaceuticalInfo.radiopharmaceuticalStartDateTime;
}
if (radiopharmaceuticalInfo.radiopharmaceuticalStartDateTime &&
radiopharmaceuticalInfo.radiopharmaceuticalStartDateTime !== undefined &&
typeof radiopharmaceuticalInfo.radiopharmaceuticalStartDateTime !== 'string') {
const dateString = convertInterfaceDateToString(radiopharmaceuticalInfo.radiopharmaceuticalStartDateTime);
instanceMetadata.RadiopharmaceuticalStartDateTime = dateString;
}
if (instanceMetadata.AcquisitionDate &&
instanceMetadata.AcquisitionDate !== undefined &&
typeof instanceMetadata.AcquisitionDate !== 'string') {
const dateString = convertInterfaceDateToString(instanceMetadata.AcquisitionDate);
instanceMetadata.AcquisitionDate = dateString;
}
if (instanceMetadata.SeriesDate &&
instanceMetadata.SeriesDate !== undefined &&
typeof instanceMetadata.SeriesDate !== 'string') {
const dateString = convertInterfaceDateToString(instanceMetadata.SeriesDate);
instanceMetadata.SeriesDate = dateString;
}
if (radiopharmaceuticalInfo.radiopharmaceuticalStartTime &&
radiopharmaceuticalInfo.radiopharmaceuticalStartTime !== undefined &&
typeof radiopharmaceuticalInfo.radiopharmaceuticalStartTime === 'string') {
instanceMetadata.RadiopharmaceuticalStartTime = radiopharmaceuticalInfo.radiopharmaceuticalStartTime;
}
if (radiopharmaceuticalInfo.radiopharmaceuticalStartTime &&
radiopharmaceuticalInfo.radiopharmaceuticalStartTime !== undefined &&
typeof radiopharmaceuticalInfo.radiopharmaceuticalStartTime !== 'string') {
const timeString = convertInterfaceTimeToString(radiopharmaceuticalInfo.radiopharmaceuticalStartTime);
instanceMetadata.RadiopharmaceuticalStartTime = timeString;
}
if (instanceMetadata.AcquisitionTime &&
instanceMetadata.AcquisitionTime !== undefined &&
typeof instanceMetadata.AcquisitionTime !== 'string') {
const timeString = convertInterfaceTimeToString(instanceMetadata.AcquisitionTime);
instanceMetadata.AcquisitionTime = timeString;
}
if (instanceMetadata.SeriesTime &&
instanceMetadata.SeriesTime !== undefined &&
typeof instanceMetadata.SeriesTime !== 'string') {
const timeString = convertInterfaceTimeToString(instanceMetadata.SeriesTime);
instanceMetadata.SeriesTime = timeString;
}
if (ptImageModule.frameReferenceTime && ptImageModule.frameReferenceTime !== undefined) {
instanceMetadata.FrameReferenceTime = ptImageModule.frameReferenceTime;
}
if (ptImageModule.actualFrameDuration && ptImageModule.actualFrameDuration !== undefined) {
instanceMetadata.ActualFrameDuration = ptImageModule.actualFrameDuration;
}
if (patientStudyModule.patientSex && patientStudyModule.patientSex !== undefined) {
instanceMetadata.PatientSex = patientStudyModule.patientSex;
}
if (patientStudyModule.patientSize && patientStudyModule.patientSize !== undefined) {
instanceMetadata.PatientSize = patientStudyModule.patientSize;
}
// Todo: add private tags
// if (
// dicomMetaData['70531000'] ||
// dicomMetaData['70531000'] !== undefined ||
// dicomMetaData['70531009'] ||
// dicomMetaData['70531009'] !== undefined
// ) {
// const philipsPETPrivateGroup: PhilipsPETPrivateGroup = {
// SUVScaleFactor: dicomMetaData['70531000'],
// ActivityConcentrationScaleFactor: dicomMetaData['70531009'],
// };
// instanceMetadata.PhilipsPETPrivateGroup = philipsPETPrivateGroup;
// }
// if (dicomMetaData['0009100d'] && dicomMetaData['0009100d'] !== undefined) {
// instanceMetadata.GEPrivatePostInjectionDateTime = dicomMetaData['0009100d'];
// }
return instanceMetadata;
}
function convertInterfaceTimeToString(time) {
const hours = `${time.hours || '00'}`.padStart(2, '0');
const minutes = `${time.minutes || '00'}`.padStart(2, '0');
const seconds = `${time.seconds || '00'}`.padStart(2, '0');
const fractionalSeconds = `${time.fractionalSeconds || '000000'}`.padEnd(6, '0');
const timeString = `${hours}${minutes}${seconds}.${fractionalSeconds}`;
return timeString;
}
function convertInterfaceDateToString(date) {
const month = `${date.month}`.padStart(2, '0');
const day = `${date.day}`.padStart(2, '0');
const dateString = `${date.year}${month}${day}`;
return dateString;
}
const { DicomMetaDictionary } = dcmjs.data;
class ImageIdService {
constructor() { }
async wadoRsCreateImageIdsAndCacheMetaData(imageInfo) {
const MODALITY = '00080060';
const SOP_INSTANCE_UID = '00080018';
const { urlRoot, studyInstanceUID, seriesInstanceUID } = imageInfo;
const client = new api.DICOMwebClient({ url: urlRoot });
const instances = await client.retrieveSeriesMetadata({
studyInstanceUID,
seriesInstanceUID,
});
const modality = instances[0][MODALITY].Value[0];
let sopInstanceUIDSet;
if (imageInfo?.sopInstanceUIDs && imageInfo?.sopInstanceUIDs.length >= 0) {
sopInstanceUIDSet = new Set(imageInfo?.sopInstanceUIDs);
}
else {
const instanceUIDs = instances.map((instanceMetaData) => {
return instanceMetaData[SOP_INSTANCE_UID].Value[0];
});
sopInstanceUIDSet = new Set(instanceUIDs);
imageInfo.sopInstanceUIDs = instanceUIDs;
}
let imageIds = [];
instances.forEach((instanceMetaData) => {
const sopInstanceUID = instanceMetaData[SOP_INSTANCE_UID].Value[0];
if (sopInstanceUIDSet.has(sopInstanceUID)) {
const imageId = ImageIdService.wadoRsCreateImageIds({
...imageInfo,
sopInstanceUIDs: [sopInstanceUID],
});
imageIds.push(...imageId); // only one image id
cornerstoneDICOMImageLoader.wadors.metaDataManager.add(imageId[0], instanceMetaData);
}
});
imageIds = this.convertMultiframeImageIds(imageIds);
this.pixelSpacingProvider(imageIds);
if (modality === 'PT') {
this.ptProvider(imageIds);
}
return imageIds;
}
static createImageIds(imageInfo) {
if (imageInfo?.schema === RequestSchema.wadoRs) {
return ImageIdService.wadoRsCreateImageIds(imageInfo);
}
else if (imageInfo?.schema === RequestSchema.wadoUri) {
return ImageIdService.wadoURICreateImageIds(imageInfo);
}
return [];
}
static wadoURICreateImageIds(imageInfo) {
if (!imageInfo.sopInstanceUIDs || imageInfo.sopInstanceUIDs.length === 0) {
console.error('Invalid image info', imageInfo);
return [];
}
const { urlRoot, studyInstanceUID, seriesInstanceUID, sopInstanceUIDs } = imageInfo;
const wadoURIRoot = `${RequestSchema.wadoUri}${urlRoot}?requestType=WADO&studyUID=${studyInstanceUID}&seriesUID=${seriesInstanceUID}&contentType=application%2Fdicom`;
return sopInstanceUIDs.map((uid) => {
return `${wadoURIRoot}&objectUID=${uid}`;
});
}
static wadoRsCreateImageIds(imageInfo) {
if (!imageInfo.sopInstanceUIDs || imageInfo.sopInstanceUIDs.length === 0) {
console.error('Invalid image info', imageInfo);
return [];
}
const { urlRoot, studyInstanceUID, seriesInstanceUID, sopInstanceUIDs } = imageInfo;
const wadoURIRoot = `${RequestSchema.wadoRs}${urlRoot}/studies/${studyInstanceUID}/series/${seriesInstanceUID}`;
return sopInstanceUIDs.map((uid) => {
return `${wadoURIRoot}/instances/${uid}/frames/1`;
});
}
convertMultiframeImageIds(imageIds) {
const newImageIds = [];
imageIds.forEach((imageId) => {
const { imageIdFrameless } = this.getFrameInformation(imageId);
const instanceMetaData = metaData.get('multiframeModule', imageId);
if (instanceMetaData && instanceMetaData.NumberOfFrames && instanceMetaData.NumberOfFrames > 1) {
const NumberOfFrames = instanceMetaData.NumberOfFrames;
for (let i = 0; i < NumberOfFrames; i++) {
const newImageId = imageIdFrameless + (i + 1);
newImageIds.push(newImageId);
}
}
else
newImageIds.push(imageId);
});
return newImageIds;
}
getFrameInformation(imageId) {
if (imageId.includes('wadors:')) {
const frameIndex = imageId.indexOf('/frames/');
const imageIdFrameless = frameIndex > 0 ? imageId.slice(0, frameIndex + 8) : imageId;
return {
frameIndex,
imageIdFrameless,
};
}
else {
const frameIndex = imageId.indexOf('&frame=');
let imageIdFrameless = frameIndex > 0 ? imageId.slice(0, frameIndex + 7) : imageId;
if (!imageIdFrameless.includes('&frame=')) {
imageIdFrameless = imageIdFrameless + '&frame=';
}
return {
frameIndex,
imageIdFrameless,
};
}
}
pixelSpacingProvider(imageIds) {
imageIds.forEach((imageId) => {
let instanceMetaData = cornerstoneDICOMImageLoader.wadors.metaDataManager.get(imageId);
// It was using JSON.parse(JSON.stringify(...)) before but it is 8x slower
instanceMetaData = this.removeInvalidTags(instanceMetaData);
if (instanceMetaData) {
// Add calibrated pixel spacing
const metadata = DicomMetaDictionary.naturalizeDataset(instanceMetaData);
const pixelSpacing = getPixelSpacingInformation(metadata);
if (pixelSpacing) {
utilities.calibratedPixelSpacingMetadataProvider.add(imageId, pixelSpacing.map((s) => parseFloat(s)));
}
}
});
}
ptProvider(imageIds) {
const instanceMetadataArray = [];
imageIds.forEach((imageId) => {
const instanceMetadata = getPTImageIdInstanceMetadata(imageId);
// TODO: Temporary fix because static-wado is producing a string, not an array of values
// (or maybe dcmjs isn't parsing it correctly?)
// It's showing up like 'DECY\\ATTN\\SCAT\\DTIM\\RAN\\RADL\\DCAL\\SLSENS\\NORM'
// but calculate-suv expects ['DECY', 'ATTN', ...]
if (typeof instanceMetadata.CorrectedImage === 'string') {
instanceMetadata.CorrectedImage = instanceMetadata.CorrectedImage.split('\\');
}
if (instanceMetadata) {
instanceMetadataArray.push(instanceMetadata);
}
});
if (instanceMetadataArray.length) {
const suvScalingFactors = calculateSUVScalingFactors(instanceMetadataArray);
instanceMetadataArray.forEach((instanceMetadata, index) => {
ptScalingMetaDataProvider.addInstance(imageIds[index], suvScalingFactors[index]);
});
}
}
removeInvalidTags(srcMetadata) {
// Object.create(null) make it ~9% faster
const dstMetadata = Object.create(null);
const tagIds = Object.keys(srcMetadata);
let tagValue;
tagIds.forEach((tagId) => {
tagValue = srcMetadata[tagId];
if (tagValue !== undefined && tagValue !== null) {
dstMetadata[tagId] = tagValue;
}
});
return dstMetadata;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ImageIdService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ImageIdService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ImageIdService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
}]
}], ctorParameters: () => [] });
const windowWidth = 400;
const windowCenter = 40;
const lower = windowCenter - windowWidth / 2.0;
const upper = windowCenter + windowWidth / 2.0;
const ctVoiRange = { lower, upper };
function setCtTransferFunctionForVolumeActor({ volumeActor }) {
volumeActor.getProperty().getRGBTransferFunction(0).setMappingRange(lower, upper);
}
/**
* Similar to {@link addVolumesToViewports} it adds volumes to viewports; however,
* this method will Set the volumes on the viewports which means that the previous
* volumes will be removed.
*
* @param renderingEngine - The rendering engine to use to get viewports from
* @param volumeInputs - Array of volume inputs including volumeId. Other properties
* such as visibility, callback, blendMode, slabThickness are optional
* @param viewportIds - Array of viewport IDs to add the volume to
* @param immediateRender - If true, the volumes will be rendered immediately
* @returns A promise that resolves when all volumes have been added
*/
async function setStacksForViewports(renderingEngine, viewportIds, imageIds, currentImageIdIndex) {
// Check if all viewports are StackViewport
viewportIds.forEach((viewportId) => {
const viewport = renderingEngine.getViewport(viewportId);
if (!viewport) {
throw new Error(`Viewport with Id ${viewportId} does not exist`);
}
// if not instance of VolumeViewport, throw
if (!(viewport instanceof StackViewport)) {
throw new Error('setStacksForViewports only supports StackViewport');
}
});
const setStackPromises = viewportIds.map(async (viewportId) => {
const viewport = renderingEngine.getViewport(viewportId);
await viewport.setStack(imageIds, currentImageIdIndex);
// Set the VOI of the stack
viewport.setProperties({ voiRange: ctVoiRange });
// Render the image
viewport.render();
});
await Promise.all(setStackPromises);
return;
}
var LayoutEnum;
(function (LayoutEnum) {
LayoutEnum[LayoutEnum["LAYOUT_1x1"] = 0] = "LAYOUT_1x1";
LayoutEnum[LayoutEnum["LAYOUT_1x2"] = 1] = "LAYOUT_1x2";
LayoutEnum[LayoutEnum["LAYOUT_1x3"] = 2] = "LAYOUT_1x3";
LayoutEnum[LayoutEnum["LAYOUT_2x2"] = 3] = "LAYOUT_2x2";
})(LayoutEnum || (LayoutEnum = {}));
const STACK_VIEWPORT_INPUTS = [
{
viewportId: 'viewport-stack',
type: Enums.ViewportType.STACK,
defaultOptions: {
background: [0, 0, 0],
},
},
];
const SAGITTAL_VIEWPORT_INPUTS = [
{
viewportId: 'viewport-mpr-sagittal',
type: Enums.ViewportType.ORTHOGRAPHIC,
defaultOptions: {
background: [0, 0, 0],
orientation: Enums.OrientationAxis.SAGITTAL,
},
},
];
const CORONAL_VIEWPORT_INPUTS = [
{
viewportId: 'viewport-mpr-coronal',
type: Enums.ViewportType.ORTHOGRAPHIC,
defaultOptions: {
background: [0, 0, 0],
orientation: Enums.OrientationAxis.CORONAL,
},
},
];
const AXIAL_VIEWPORT_INPUTS = [
{
viewportId: 'viewport-mpr-axial',
type: Enums.ViewportType.ORTHOGRAPHIC,
defaultOptions: {
background: [0, 0, 0],
orientation: Enums.OrientationAxis.AXIAL,
},
},
];
const VOLUME_3D_VIEWPORT_INPUTS = [
{
viewportId: 'viewport-volume',
type: Enums.ViewportType.VOLUME_3D,
defaultOptions: {
background: [0.2, 0, 0.2],
},
},
];
function generateViewportInputs(layout, suffix, imageInfo) {
const viewportType = imageInfo?.viewportType || Enums.ViewportType.STACK;
const isStack = viewportType === Enums.ViewportType.STACK;
const result = [];
switch (layout) {
case LayoutEnum.LAYOUT_1x1:
// 1x1 layout: set viewportType according to imageType
if (viewportType === Enums.ViewportType.STACK) {
const viewportInput = structuredClone(STACK_VIEWPORT_INPUTS[0]);
viewportInput.viewportId = `viewport-stack-${suffix}`;
result.push(viewportInput);
}
else if (viewportType === Enums.ViewportType.VOLUME_3D) {
const viewportInput = structuredClone(VOLUME_3D_VIEWPORT_INPUTS[0]);
viewportInput.viewportId = `viewport-volume-${suffix}`;
result.push(viewportInput);
}
else {
const viewportInput = structuredClone(SAGITTAL_VIEWPORT_INPUTS[0]);
viewportInput.viewportId = `viewport-sagittal-${suffix}`;
result.push(viewportInput);
}
break;
case LayoutEnum.LAYOUT_1x2:
// 1x2 layout: all stack when imageType is stack, otherwise one volume3D one sagittal
if (isStack) {
for (let i = 0; i < 2; i++) {
const viewportInput = structuredClone(STACK_VIEWPORT_INPUTS[0]);
viewportInput.viewportId = `viewport-stack-${i + 1}${suffix}`;
result.push(viewportInput);
}
}
else {
const sagittalViewport = structuredClone(SAGITTAL_VIEWPORT_INPUTS[0]);
sagittalViewport.viewportId = `viewport-sagittal-${suffix}`;
result.push(sagittalViewport);
const volumeViewport = structuredClone(VOLUME_3D_VIEWPORT_INPUTS[0]);
volumeViewport.viewportId = `viewport-volume-${suffix}`;
result.push(volumeViewport);
}
break;
case LayoutEnum.LAYOUT_1x3:
// 1x3 layout: all stack when imageType is stack, otherwise one volume3D one sagittal one axial
if (isStack) {
for (let i = 0; i < 3; i++) {
const viewportInput = structuredClone(STACK_VIEWPORT_INPUTS[0]);
viewportInput.viewportId = `viewport-stack-${i + 1}${suffix}`;
result.push(viewportInput);
}
}
else {
const sagittalViewport = structuredClone(SAGITTAL_VIEWPORT_INPUTS[0]);
sagittalViewport.viewportId = `viewport-sagittal-${suffix}`;
result.push(sagittalViewport);
const axialViewport = structuredClone(AXIAL_VIEWPORT_INPUTS[0]);
axialViewport.viewportId = `viewport-axial-${suffix}`;
result.push(axialViewport);
const volumeViewport = structuredClone(VOLUME_3D_VIEWPORT_INPUTS[0]);
volumeViewport.viewportId = `viewport-volume-${suffix}`;
result.push(volumeViewport);
}
break;
case LayoutEnum.LAYOUT_2x2:
// 2x2 layout: all stack when imageType is stack, otherwise one volume3D one sagittal one axial one coronal
if (isStack) {
for (let i = 0; i < 4; i++) {
const viewportInput = structuredClone(STACK_VIEWPORT_INPUTS[0]);
viewportInput.viewportId = `viewport-stack-${i + 1}${suffix}`;
result.push(viewportInput);
}
}
else {
const sagittalViewport = structuredClone(SAGITTAL_VIEWPORT_INPUTS[0]);
sagittalViewport.viewportId = `viewport-sagittal-${suffix}`;
result.push(sagittalViewport);
const axialViewport = structuredClone(AXIAL_VIEWPORT_INPUTS[0]);
axialViewport.viewportId = `viewport-axial-${suffix}`;
result.push(axialViewport);
const coronalViewport = structuredClone(CORONAL_VIEWPORT_INPUTS[0]);
coronalViewport.viewportId = `viewport-coronal-${suffix}`;
result.push(coronalViewport);
const volumeViewport = structuredClone(VOLUME_3D_VIEWPORT_INPUTS[0]);
volumeViewport.viewportId = `viewport-volume-${suffix}`;
result.push(volumeViewport);
}
break;
}
return result;
}
function generateRandomString(length = 6) {
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
for (let i = 0; i < length; i++) {
const randomIndex = Math.floor(Math.random() * characters.length);
result += characters[randomIndex];
}
return '-' + result;
}
class IconComponent {
constructor() {
this.iconfont = '';
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: IconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: IconComponent, selector: "i[nc-icon]", inputs: { iconfont: "iconfont" }, ngImport: i0, template: `
<svg class="icon" aria-hidden="true">
<use attr.xlink:href="#{{ iconfont }}"></use>
</svg>
`, isInline: true, styles: [":host{display:inline-block;line-height:0}.icon{fill:currentColor;height:1em;overflow:hidden;vertical-align:-.15em;width:1em}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: IconComponent, decorators: [{
type: Component,
args: [{ selector: 'i[nc-icon]', template: `
<svg class="icon" aria-hidden="true">
<use attr.xlink:href="#{{ iconfont }}"></use>
</svg>
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:inline-block;line-height:0}.icon{fill:currentColor;height:1em;overflow:hidden;vertical-align:-.15em;width:1em}\n"] }]
}], propDecorators: { iconfont: [{
type: Input
}] } });
class ButtonComponent {
onClick(event) {
if (this.disabled) {
event.preventDefault();
event.stopImmediatePropagation();
}
else if (this.isToggle) {
this.pressed = !this.pressed;
}
}
get pressedChange$() {
return this._pressedChange$.asObservable();
}
/**
* Controls button pressed state
**/
get pressed() {
return this._pressed;
}
set pressed(value) {
if (this.pressed !== coerceBooleanProperty(value)) {
this._pressed = !this.pressed;
this.pressedChange.emit(this.pressed);
this._pressedChange$.next({ source: this, pressed: this.pressed });
}
}
constructor(_elementRef, cd) {
this._elementRef = _elementRef;
this.cd = cd;
this.disabled = false;
this.tabIndex = null;
this.type = 'default';
this.shape = 'default';
this.content = 'default';
this.size = 'default';
this.isToggle = false;
this.icon = null;
this.text = null;
/**
* Emits whenever button pressed state change
**/
this.pressedChange = new EventEmitter();
this._pressedChange$ = new Subject();
this._pressed = false;
this.destroy$ = new Subject();
}
_getHostElement() {
return this._elementRef.nativeElement;
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
/**
* @docs-private
*/
_updatePressed(value) {
this.pressed = value;
this.cd.markForCheck();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ButtonComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: ButtonComponent, selector: "button[nc-button], a[nc-button]", inputs: { disabled: "disabled", tabIndex: "tabIndex", type: "type", shape: "shape", content: "content", size: "size", isToggle: "isToggle", icon: "icon", text: "text", value: "value" }, outputs: { pressedChange: "pressedChange" }, host: { listeners: { "click": "onClick($event)" }, properties: { "class.btn-type-primary": "type === 'primary'", "class.btn-type-default": "type === 'default'", "class.btn-content-icon-text": "content === 'icon-text'", "class.btn-content-icon": "content === 'icon'", "class.btn-content-text": "content === 'text'", "class.btn-shape-round": "shape === 'round'", "class.btn-shape-circle": "shape === 'circle'", "class.btn-size-lg": "size === 'large'", "class.btn-size-sm": "size === 'small'", "attr.tabindex": "disabled ? -1 : (tabIndex === null ? null : tabIndex)", "attr.disabled": "disabled || null", "class.pressed": "this.pressed" }, classAttribute: "nc-btn" }, exportAs: ["ncButton"], ngImport: i0, template: "<ng-container [ngSwitch]=\"content\">\n <ng-container *ngSwitchCase=\"'icon-text'\">\n <i nc-icon [iconfont]=\"icon\"></i>\n <span class=\"text\">{{ text }}</span>\n </ng-container>\n <div *ngSwitchCase=\"'text'\">\n <span>{{ text }}</span>\n </div>\n <div *ngSwitchCase=\"'icon'\">\n <i nc-icon [iconfont]=\"icon\"></i>\n </div>\n <ng-content *ngSwitchDefault></ng-content>\n</ng-container>\n", styles: ["@charset \"UTF-8\";.h1,h1,.headline{font-size:24px;line-height:32px;font-weight:400;font-family:roboto,Noto Sans SC,sans-serif;letter-spacing:normal}.h2,h2,.title{font-size:20px;line-height:32px;font-weight:500;font-family:roboto,Noto Sans SC,sans-serif;letter-spacing:normal}.h3,h3,.subheading{font-size:16px;line-height:28px;font-weight:400;font-family:roboto,Noto Sans SC,sans-serif;letter-spacing:normal}.h4,h4,.body{font-size:14px;line-height:24px;font-weight:500;font-family:roboto,Noto Sans SC,sans-serif;letter-spacing:normal}.h5,h5,.button,:host.nc-btn{font-size:14px;line-height:14px;font-weight:500;font-family:roboto,Noto Sans SC,sans-serif;letter-spacing:normal}:host.nc-btn{cursor:pointer;outline:none;border:none;-webkit-tap-highlight-color:transparent;box-sizing:border-box;position:relative;appearance:none;text-align:center;display:inline-flex;align-items:center;justify-content:center;white-space:nowrap;vertical-align:middle;-webkit-user-select:none;user-select:none;text-decoration:none;margin:0;min-width:0;padding:2px;overflow:visible;border-radius:0;border-width:1px;border-style:solid;border-color:transparent;font-size:16px;line-height:20px}:host.nc-btn::-moz-focus-inner{border:0}:host.nc-btn:disabled{cursor:not-allowed;color:#595959d9}:host.nc-btn.transition{transition-duration:.15s;transition-property:background-color,border-color,box-shadow,color;transition-timing-function:ease-in}:host.btn-type-primary{color:#f2f2f2d9;background-color:#3bdbdf}:host.btn-type-primary:hover:not(:disabled){background-color:#93ebed}:host.btn-type-primary:active:not(:disabled){background-color:#3bdbdf}:host.btn-type-primary.pressed:not(:disabled){background-color:#93ebed}:host.btn-type-default{color:#f2f2f2d9;background-color:transparent}:host.btn-type-default:hover:not(:disabled){border:1px transparent solid!important;color:#3bdbdfd9}:host.btn-type-default:focus:not(:disabled){border:1px rgba(59,219,223,.85) solid}:host.btn-type-default:active:not(:disabled){border:1px transparent solid!important;color:#3bdbdfd9}:host.btn-type-default.pressed:not(:disabled){border:1px transparent solid!important;color:#3bdbdfd9}:host.btn-content-icon-text{flex-flow:column nowrap;align-items:center;justify-content:space-evenly;height:42px}:host.btn-content-icon-text i{font-size:20px}:host.btn-content-icon-text span{font-size:12px;line-height:16px}:host.btn-content-icon{font-size:20px;line-height:24px}:host.btn-content-text{font-size:16px;line-height:20px}:host.btn-shape-round{border-radius:2px}:host.btn-shape-circle{border-radius:50%}\n"], dependencies: [{ kind: "directive", type: i2.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i2.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i2.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "component", type: IconComponent, selector: "i[nc-icon]", inputs: ["iconfont"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
__decorate([
InputBoolean()
], ButtonComponent.prototype, "disabled", void 0);
__decorate([
InputBoolean()
], ButtonComponent.prototype, "isToggle", void 0);
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ButtonComponent, decorators: [{
type: Component,
args: [{ selector: 'button[nc-button], a[nc-button]', exportAs: 'ncButton', changeDetection: ChangeDetectionStrategy.OnPush, host: {
class: 'nc-btn',
'[class.btn-type-primary]': `type === 'primary'`,
'[class.btn-type-default]': `type === 'default'`,
'[class.btn-content-icon-text]': `content === 'icon-text'`,
'[class.btn-content-icon]': `content === 'icon'`,
'[class.btn-content-text]': `content === 'text'`,
'[class.btn-shape-round]': `shape === 'round'`,
'[class.btn-shape-circle]': `shape === 'circle'`,
'[class.btn-size-lg]': `size === 'large'`,
'[class.btn-size-sm]': `size === 'small'`,
'[attr.tabindex]': 'disabled ? -1 : (tabIndex === null ? null : tabIndex)',
'[attr.disabled]': 'disabled || null',
}, template: "<ng-container [ngSwitch]=\"content\">\n <ng-container *ngSwitchCase=\"'icon-text'\">\n <i nc-icon [iconfont]=\"icon\"></i>\n <span class=\"text\">{{ text }}</span>\n </ng-container>\n <div *ngSwitchCase=\"'text'\">\n <span>{{ text }}</span>\n </div>\n <div *ngSwitchCase=\"'icon'\">\n <i nc-icon [iconfont]=\"icon\"></i>\n </div>\n <ng-content *ngSwitchDefault></ng-content>\n</ng-container>\n", styles: ["@charset \"UTF-8\";.h1,h1,.headline{font-size:24px;line-height:32px;font-weight:400;font-family:roboto,Noto Sans SC,sans-serif;letter-spacing:normal}.h2,h2,.title{font-size:20px;line-height:32px;font-weight:500;font-family:roboto,Noto Sans SC,sans-serif;letter-spacing:normal}.h3,h3,.subheading{font-size:16px;line-height:28px;font-weight:400;font-family:roboto,Noto Sans SC,sans-serif;letter-spacing:normal}.h4,h4,.body{font-size:14px;line-height:24px;font-weight:500;font-family:roboto,Noto Sans SC,sans-serif;letter-spacing:normal}.h5,h5,.button,:host.nc-btn{font-size:14px;line-height:14px;font-weight:500;font-family:roboto,Noto Sans SC,sans-serif;letter-spacing:normal}:host.nc-btn{cursor:pointer;outline:none;border:none;-webkit-tap-highlight-color:transparent;box-sizing:border-box;position:relative;appearance:none;text-align:center;display:inline-flex;align-items:center;justify-content:center;white-space:nowrap;vertical-align:middle;-webkit-user-select:none;user-select:none;text-decoration:none;margin:0;min-width:0;padding:2px;overflow:visible;border-radius:0;border-width:1px;border-style:solid;border-color:transparent;font-size:16px;line-height:20px}:host.nc-btn::-moz-focus-inner{border:0}:host.nc-btn:disabled{cursor:not-allowed;color:#595959d9}:host.nc-btn.transition{transition-duration:.15s;transition-property:background-color,border-color,box-shadow,color;transition-timing-function:ease-in}:host.btn-type-primary{color:#f2f2f2d9;background-color:#3bdbdf}:host.btn-type-primary:hover:not(:disabled){background-color:#93ebed}:host.btn-type-primary:active:not(:disabled){background-color:#3bdbdf}:host.btn-type-primary.pressed:not(:disabled){background-color:#93ebed}:host.btn-type-default{color:#f2f2f2d9;background-color:transparent}:host.btn-type-default:hover:not(:disabled){border:1px transparent solid!important;color:#3bdbdfd9}:host.btn-type-default:focus:not(:disabled){border:1px rgba(59,219,223,.85) solid}:host.btn-type-default:active:not(:disabled){border:1px transparent solid!important;color:#3bdbdfd9}:host.btn-type-default.pressed:not(:disabled){border:1px transparent solid!important;color:#3bdbdfd9}:host.btn-content-icon-text{flex-flow:column nowrap;align-items:center;justify-content:space-evenly;height:42px}:host.btn-content-icon-text i{font-size:20px}:host.btn-content-icon-text span{font-size:12px;line-height:16px}:host.btn-content-icon{font-size:20px;line-height:24px}:host.btn-content-text{font-size:16px;line-height:20px}:host.btn-shape-round{border-radius:2px}:host.btn-shape-circle{border-radius:50%}\n"] }]
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }], propDecorators: { disabled: [{
type: Input
}], tabIndex: [{
type: Input
}], type: [{
type: Input
}], shape: [{
type: Input
}], content: [{
type: Input
}], size: [{
type: Input
}], isToggle: [{
type: Input
}], icon: [{
type: Input
}], text: [{
type: Input
}], value: [{
type: Input
}], onClick: [{
type: HostListener,
args: ['click', ['$event']]
}], pressedChang