feat(measurement-table) Display support for measurements from DICOM Structured Reports (#225)
This commit is contained in:
1 parent
e9832f62f7
commit
d94f0eec16
64 files changed
+1797
-78
No files matched your search
@@ -1,4 +1,5 @@
|
||||
import './association';
|
||||
import './caseProgress';
|
||||
import './measurementTable';
|
||||
import './measurementLightTable';
|
||||
import './measureFlow';
|
||||
@@ -0,0 +1,22 @@
|
||||
// Measurement Table Components imports
|
||||
|
||||
import './measurementEditDescription/measurementEditDescription.html';
|
||||
import './measurementEditDescription/measurementEditDescription.js';
|
||||
|
||||
import './measurementLightTable.html';
|
||||
import './measurementLightTable.styl';
|
||||
|
||||
import './measurementLightTableHeaderRow/measurementLightTableHeaderRow.html';
|
||||
import './measurementLightTableHeaderRow/measurementLightTableHeaderRow.styl';
|
||||
|
||||
import './measurementLightTableRow/measurementLightTableRow.html';
|
||||
import './measurementLightTableRow/measurementLightTableRow.styl';
|
||||
import './measurementLightTableRow/measurementLightTableRow.js';
|
||||
|
||||
import './measurementLightTableView/measurementLightTableView.html';
|
||||
import './measurementLightTableView/measurementLightTableView.styl';
|
||||
import './measurementLightTableView/measurementLightTableView.js';
|
||||
|
||||
import './measurementRelabel/measurementRelabel.html';
|
||||
import './measurementRelabel/measurementRelabel.styl';
|
||||
import './measurementRelabel/measurementRelabel.js';
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
<template name="measurementEditDescription">
|
||||
{{#dialogForm (extend this
|
||||
dialogClass='modal-sm'
|
||||
api=instance.api
|
||||
)}}
|
||||
{{>inputText
|
||||
labelClass='form-group'
|
||||
key='description'
|
||||
hideSearch=true
|
||||
options=(clone placeholder='Add a description')
|
||||
}}
|
||||
{{/dialogForm}}
|
||||
</template>
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
import { Template } from 'meteor/templating';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
|
||||
Template.measurementEditDescription.onRendered(() => {
|
||||
const instance = Template.instance();
|
||||
const form = instance.$('form').data('component');
|
||||
const measurementData = instance.data.measurementData;
|
||||
const collection = OHIF.viewer.measurementApi.tools[measurementData.toolType];
|
||||
const currentMeasurement = collection.findOne({ _id: measurementData._id });
|
||||
|
||||
if (currentMeasurement.description) {
|
||||
form.value({
|
||||
description: currentMeasurement.description
|
||||
});
|
||||
}
|
||||
|
||||
// Update the description after confirming the dialog data
|
||||
instance.data.promise.then(formData => {
|
||||
collection.update({
|
||||
_id: measurementData._id,
|
||||
}, {
|
||||
$set: { description: formData.description }
|
||||
});
|
||||
});
|
||||
});
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
<template name="measurementLightTable">
|
||||
<div id="measurementLightTableContainer" class="flex-v">
|
||||
<div class="measurementLightTableHeaderContainer">
|
||||
<div class="measurementLightTableHeader">
|
||||
<div class="studyDateLabel">
|
||||
Study date:
|
||||
</div>
|
||||
<div class="studyDate">
|
||||
{{formatDA this.timepointApi.all.[0].latestDate "DD-MMM-YY"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{#scrollArea class='measurementLightTableView flex-grow fit' scrollStep=63}}
|
||||
{{>measurementLightTableView (clone this)}}
|
||||
{{/scrollArea}}
|
||||
</div>
|
||||
</template>
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
@require '{ohif:design}/app'
|
||||
|
||||
#measurementLightTableContainer
|
||||
theme('background-color', '$primaryBackgroundColor')
|
||||
height: 100%
|
||||
width: 100%
|
||||
|
||||
.measurementLightTableHeaderContainer
|
||||
display: flex
|
||||
padding: 0 2px 0 44px
|
||||
position: relative
|
||||
|
||||
.measurementLightTableHeader
|
||||
flex: 1
|
||||
justify-content: space-around
|
||||
padding-top: 2px
|
||||
position: relative
|
||||
margin: 0.4em 0
|
||||
|
||||
.studyDateLabel, .studyDate
|
||||
theme('border-left', '%s solid $uiBorderColor' % $uiBorderThickness)
|
||||
font-weight: 400
|
||||
padding-left: 12px
|
||||
text-align: left
|
||||
|
||||
.studyDateLabel
|
||||
theme('color', '$textSecondaryColor')
|
||||
font-size: 12px
|
||||
line-height: 12px
|
||||
|
||||
.studyDate
|
||||
theme('color', '$textPrimaryColor')
|
||||
font-size: 14px
|
||||
line-height: 20px
|
||||
padding-bottom: 6px
|
||||
|
||||
.measurementLightTableLayoutChanger
|
||||
margin: 0 auto
|
||||
padding: 20px
|
||||
text-align: center
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
<template name="measurementLightTableHeaderRow">
|
||||
<div class="measurementLightTableHeaderRow">
|
||||
<div class="type">{{toolGroup.name}}</div>
|
||||
<div class="numberOfMeasurements">{{measurementRows.length}}</div>
|
||||
</div>
|
||||
</template>
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
@import "{ohif:design}/app"
|
||||
|
||||
$headerRowHeight = 63px
|
||||
|
||||
.measurementLightTableHeaderRow
|
||||
theme('background-color', '$uiGrayDarker')
|
||||
theme('color', '$textSecondaryColor')
|
||||
display: flex
|
||||
theme('fill', '$textSecondaryColor')
|
||||
height: $headerRowHeight
|
||||
line-height: $headerRowHeight
|
||||
margin-top: 2px
|
||||
width: 100%
|
||||
|
||||
div
|
||||
align-items: stretch
|
||||
flex: 1
|
||||
justify-content: space-around
|
||||
text-align: center
|
||||
|
||||
.type
|
||||
theme('color', '$textSecondaryColor')
|
||||
font-size: 22px
|
||||
font-weight: 300
|
||||
line-height: $headerRowHeight
|
||||
padding: 0 10px
|
||||
text-align: left
|
||||
|
||||
.numberOfMeasurements
|
||||
theme('color', '$uiSkyBlue')
|
||||
float: right
|
||||
font-weight: 300
|
||||
font-size: 40px
|
||||
max-width: 54px
|
||||
height: $headerRowHeight
|
||||
line-height: 66px
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
<template name="measurementLightTableRow">
|
||||
<div class="measurementLightTableRow" data-measurementid="{{_id}}">
|
||||
<div class='measurementRowSidebar'>
|
||||
<div class="measurementNumber">
|
||||
{{rowItem.measurementNumber}}
|
||||
</div>
|
||||
{{#if rowItem.responseStatus}}
|
||||
<div class="response-status-icon">
|
||||
{{rowItem.responseStatus}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="measurementRowContent">
|
||||
<div class="measurementDetails">
|
||||
<label class="location">
|
||||
{{#if rowItem.location}}
|
||||
{{rowItem.location}}
|
||||
{{else}}
|
||||
(No Location)
|
||||
{{/if}}
|
||||
{{#if rowItem.description}}
|
||||
({{rowItem.description}})
|
||||
{{/if}}
|
||||
</label>
|
||||
<div class="value">
|
||||
{{#if displayData}}
|
||||
{{{displayData}}}
|
||||
{{else}}
|
||||
...
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="rowOptions">
|
||||
<div class="rowAction js-edit-label pull-left m-r-2" tabindex="1">
|
||||
<svg class="edit-icon">
|
||||
<use xlink:href={{absoluteUrl "packages/ohif_viewerbase/assets/icons.svg#icon-measurements-additional"}}></use>
|
||||
</svg>
|
||||
Relabel
|
||||
</div>
|
||||
<div class="rowAction js-edit-description pull-left m-r-2" tabindex="1">
|
||||
<svg class="edit-icon">
|
||||
<use xlink:href={{absoluteUrl "packages/ohif_viewerbase/assets/icons.svg#icon-measurements-additional"}}></use>
|
||||
</svg>
|
||||
Description
|
||||
</div>
|
||||
<div class="rowAction js-delete pull-left" tabindex="1">
|
||||
<svg class="close-icon">
|
||||
<use xlink:href={{absoluteUrl "packages/ohif_viewerbase/assets/icons.svg#icon-ui-close"}}></use>
|
||||
</svg>
|
||||
Delete
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
import { Template } from 'meteor/templating';
|
||||
import { _ } from 'meteor/underscore';
|
||||
import { $ } from 'meteor/jquery';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { cornerstone } from 'meteor/ohif:cornerstone';
|
||||
|
||||
const getPosition = event => {
|
||||
return {
|
||||
x: event.clientX,
|
||||
y: event.clientY
|
||||
};
|
||||
};
|
||||
|
||||
Template.measurementLightTableRow.helpers({
|
||||
displayData() {
|
||||
const instance = Template.instance();
|
||||
const { rowItem } = instance.data;
|
||||
|
||||
const data = rowItem.entries[0];
|
||||
|
||||
const config = OHIF.measurements.MeasurementApi.getConfiguration();
|
||||
const measurementTools = config.measurementTools;
|
||||
|
||||
const toolGroup = measurementTools.find( toolGroup => toolGroup.id === rowItem.measurementTypeId);
|
||||
const tool = toolGroup.childTools.find( childTool => childTool.id === data.toolType );
|
||||
if (!tool) {
|
||||
return 'No measurement value';
|
||||
}
|
||||
|
||||
const { displayFunction } = tool.options.measurementTable;
|
||||
return displayFunction(data);
|
||||
}
|
||||
});
|
||||
|
||||
Template.measurementLightTableRow.events({
|
||||
'click .measurementLightTableRow'(event, instance) {
|
||||
const $row = instance.$('.measurementLightTableRow');
|
||||
const rowItem = instance.data.rowItem;
|
||||
const timepoints = instance.data.timepointApi.all();
|
||||
|
||||
$row.closest('.measurementLightTableView').find('.measurementLightTableRow').not($row).removeClass('active');
|
||||
$row.toggleClass('active');
|
||||
|
||||
const childToolKey = $(event.target).attr('data-child');
|
||||
OHIF.measurements.jumpToRowItem(rowItem, timepoints, childToolKey);
|
||||
},
|
||||
|
||||
'click .js-edit-label'(event, instance) {
|
||||
event.stopPropagation();
|
||||
const rowItem = instance.data.rowItem;
|
||||
const entry = rowItem.entries[0];
|
||||
|
||||
// Show the measure flow for measurements
|
||||
OHIF.measurements.openLocationModal({
|
||||
measurement: entry,
|
||||
element: document.body,
|
||||
measurementApi: instance.data.measurementApi,
|
||||
position: getPosition(event),
|
||||
autoClick: true
|
||||
});
|
||||
},
|
||||
|
||||
'click .js-edit-description'(event, instance) {
|
||||
const rowItem = instance.data.rowItem;
|
||||
const entry = rowItem.entries[0];
|
||||
OHIF.ui.showDialog('measurementEditDescription', {
|
||||
event,
|
||||
title: 'Edit Description',
|
||||
element: event.element,
|
||||
measurementData: entry
|
||||
});
|
||||
},
|
||||
|
||||
'click .js-delete'(event, instance) {
|
||||
event.stopPropagation();
|
||||
const dialogSettings = {
|
||||
class: 'themed',
|
||||
title: 'Delete measurements',
|
||||
message: 'Are you sure you want to delete the measurement?',
|
||||
position: getPosition(event)
|
||||
};
|
||||
|
||||
OHIF.ui.showDialog('dialogConfirm', dialogSettings).then(formData => {
|
||||
const measurementTypeId = instance.data.rowItem.measurementTypeId;
|
||||
const measurement = instance.data.rowItem.entries[0];
|
||||
const measurementNumber = measurement.measurementNumber;
|
||||
const { timepointApi, measurementApi } = instance.data;
|
||||
|
||||
// Remove all the measurements with the given type and number
|
||||
measurementApi.deleteMeasurements(measurementTypeId, { measurementNumber });
|
||||
|
||||
// Sync the new measurement data with cornerstone tools
|
||||
const baseline = timepointApi.baseline();
|
||||
measurementApi.sortMeasurements(baseline.timepointId);
|
||||
|
||||
// Repaint the images on all viewports without the removed measurements
|
||||
_.each($('.imageViewerViewport'), element => cornerstone.updateImage(element));
|
||||
|
||||
// Notify that viewer suffered changes
|
||||
OHIF.measurements.triggerTimepointUnsavedChanges('deleted');
|
||||
});
|
||||
}
|
||||
});
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
@import "{ohif:design}/app"
|
||||
|
||||
.measurementLightTableRow
|
||||
display: flex
|
||||
margin-left: -6px
|
||||
margin-top: 2px
|
||||
padding-left: 6px
|
||||
opacity: 0.7
|
||||
transform(scale(1))
|
||||
width: calc(100% + 6px)
|
||||
|
||||
&:hover
|
||||
opacity 1
|
||||
|
||||
&.active
|
||||
opacity 1
|
||||
.measurementRowSidebar
|
||||
theme('color', '$activeColor')
|
||||
|
||||
.rowOptions
|
||||
height: 35px
|
||||
visibility: visible
|
||||
|
||||
.rowOptions
|
||||
theme('background-color', '$uiGrayDarker')
|
||||
height: 0
|
||||
overflow: hidden
|
||||
transition(all 0.3s ease)
|
||||
visibility: hidden
|
||||
padding-left: 14px
|
||||
|
||||
.rowAction
|
||||
theme('color', '$defaultColor')
|
||||
cursor: pointer
|
||||
line-height: 35px
|
||||
transition(all 0.3s ease)
|
||||
|
||||
&:hover, &:active
|
||||
theme('color', '$textPrimaryColor')
|
||||
|
||||
svg
|
||||
theme('fill', '$textPrimaryColor')
|
||||
theme('stroke', '$textPrimaryColor')
|
||||
|
||||
svg
|
||||
theme('fill', '$defaultColor')
|
||||
theme('stroke', '$defaultColor')
|
||||
transition(all 0.3s ease)
|
||||
|
||||
&.edit-icon
|
||||
width: 14px
|
||||
height: 13px
|
||||
|
||||
&.close-icon
|
||||
width: 11px
|
||||
height: 11px
|
||||
|
||||
.measurementRowSidebar
|
||||
theme('background', '$uiGray')
|
||||
theme('color', '$textSecondaryColor')
|
||||
cursor: pointer
|
||||
flex: 1
|
||||
max-width: 30px
|
||||
transition(all 0.3s ease)
|
||||
|
||||
.measurementNumber
|
||||
font-size: 14px
|
||||
font-weight: 400
|
||||
margin-right: 5px
|
||||
padding-top: 10px
|
||||
text-align: center
|
||||
|
||||
.measurementRowContent
|
||||
flex: 1
|
||||
|
||||
.measurementDetails
|
||||
padding: 5px 2px 0 14px
|
||||
line-height: 30px
|
||||
font-size: 14px
|
||||
|
||||
.location
|
||||
theme('color', '$textSecondaryColor')
|
||||
font-weight: 400
|
||||
margin-left: -2px
|
||||
|
||||
.value
|
||||
theme('color', '$textPrimaryColor')
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
<template name="measurementLightTableView">
|
||||
{{#let config=measurementConfiguration groups=measurementGroups.get}}
|
||||
{{#each measurementGroup in groups}}
|
||||
{{>measurementLightTableHeaderRow (clone this
|
||||
toolGroup=measurementGroup.toolGroup
|
||||
measurementRows=measurementGroup.measurementRows)}}
|
||||
{{#each rowItem in measurementGroup.measurementRows}}
|
||||
{{>measurementLightTableRow (clone this rowItem=rowItem)}}
|
||||
{{/each}}
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</template>
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
import { Template } from 'meteor/templating';
|
||||
import { ReactiveVar } from 'meteor/reactive-var';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
Template.measurementLightTableView.onCreated(() => {
|
||||
const instance = Template.instance();
|
||||
const { measurementApi, timepointApi } = instance.data;
|
||||
|
||||
instance.data.measurementGroups = new ReactiveVar();
|
||||
|
||||
instance.autorun(() => {
|
||||
measurementApi.changeObserver.depend();
|
||||
const data = OHIF.measurements.getMeasurementsGroupedByNumber(measurementApi, timepointApi);
|
||||
instance.data.measurementGroups.set(data);
|
||||
});
|
||||
});
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
@import "{ohif:design}/app"
|
||||
|
||||
.measurementLightTableView
|
||||
.report-area
|
||||
theme('background-color', '$uiGrayDarker')
|
||||
margin-top: 2px
|
||||
padding: 10px 0
|
||||
text-align: center
|
||||
|
||||
.btn
|
||||
theme('background-color', '$activeColor')
|
||||
theme('border', '1px solid $uiBorderColorActive')
|
||||
color: #000
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
<template name="measurementRelabel">
|
||||
<div class="measurement-relabel {{#if this.threeColumns}}tree-columns{{/if}} {{instance.state.get}}" tabindex="-1">
|
||||
</div>
|
||||
</template>
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { Template } from 'meteor/templating';
|
||||
import { Blaze } from 'meteor/blaze';
|
||||
import { ReactiveVar } from 'meteor/reactive-var';
|
||||
import { Tracker } from 'meteor/tracker';
|
||||
import { $ } from 'meteor/jquery';
|
||||
import {
|
||||
segmentedTerminologyList,
|
||||
segmentedTerminologyCommonList } from '../../../lib/getLabelTerminologyList';
|
||||
|
||||
Template.measurementRelabel.onCreated(() => {
|
||||
const instance = Template.instance();
|
||||
|
||||
instance.value = instance.data.currentValue || '';
|
||||
|
||||
instance.state = new ReactiveVar('closed');
|
||||
|
||||
instance.items = segmentedTerminologyList;
|
||||
instance.commonItems = segmentedTerminologyCommonList;
|
||||
});
|
||||
|
||||
Template.measurementRelabel.onRendered(() => {
|
||||
const instance = Template.instance();
|
||||
const $measurementRelabel = instance.$('.measurement-relabel');
|
||||
|
||||
// Make the measure flow bounded by the window borders
|
||||
$measurementRelabel.bounded();
|
||||
|
||||
// Wait template rerender before rendering the selectTree
|
||||
Tracker.afterFlush(() => {
|
||||
// Get the click or rendering position
|
||||
const position = {
|
||||
left: event.clientX || instance.data.position.x,
|
||||
top: event.clientY || instance.data.position.y,
|
||||
};
|
||||
|
||||
// Define the data for selectTreeComponent
|
||||
const data = {
|
||||
key: 'label',
|
||||
items: instance.items,
|
||||
commonItems: instance.commonItems,
|
||||
hideCommon: instance.data.hideCommon,
|
||||
label: 'Assign label',
|
||||
search: true,
|
||||
searchPlaceholder: 'Search labels',
|
||||
threeColumns: instance.data.threeColumns,
|
||||
position
|
||||
};
|
||||
|
||||
// Define in which element the selectTree will be rendered in
|
||||
const parentElement = $measurementRelabel[0];
|
||||
|
||||
// Render the selectTree element
|
||||
instance.selectTreeView = Blaze.renderWithData(Template.selectTree, data, parentElement);
|
||||
|
||||
// Focus the measure flow to handle closing
|
||||
$measurementRelabel.focus();
|
||||
});
|
||||
});
|
||||
|
||||
Template.measurementRelabel.events({
|
||||
'click, mousedown, mouseup'(event, instance) {
|
||||
event.stopPropagation();
|
||||
},
|
||||
|
||||
'click .tree-leaf input'(event, instance) {
|
||||
const $target = $(event.currentTarget);
|
||||
const $measureFlow = instance.$('.measurement-relabel');
|
||||
instance.state.set('selected');
|
||||
|
||||
instance.value = $target.data('component').value();
|
||||
instance.data.updateCallback(instance.value);
|
||||
|
||||
$measureFlow.trigger('close')
|
||||
},
|
||||
|
||||
'blur .measurement-relabel'(event, instance) {
|
||||
const $measurementRelabel = $(event.currentTarget);
|
||||
const element = $measurementRelabel[0];
|
||||
Meteor.defer(() => {
|
||||
const focused = $(':focus')[0];
|
||||
if (element !== focused && !$.contains(element, focused)) {
|
||||
$measurementRelabel.trigger('close');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'mouseleave .measurement-relabel'(event, instance) {
|
||||
const $measurementRelabel = $(event.currentTarget);
|
||||
const canClose = instance.state.get() === 'selected';
|
||||
if (canClose && !$.contains($measurementRelabel[0], event.toElement)) {
|
||||
$measurementRelabel.trigger('close');
|
||||
}
|
||||
},
|
||||
|
||||
'mouseenter .measurement-relabel'(event, instance) {
|
||||
// Prevent from closing if user go out and in too fast
|
||||
clearTimeout(instance.closingTimeout);
|
||||
$(event.currentTarget).off('animationend').removeClass('fadeOut');
|
||||
},
|
||||
|
||||
'close .measurement-relabel'(event, instance) {
|
||||
// Clear the timeout to prevent executing the close process twice
|
||||
clearTimeout(instance.closingTimeout);
|
||||
instance.data.doneCallback();
|
||||
}
|
||||
});
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
@import "{ohif:design}/app"
|
||||
|
||||
.measurement-relabel
|
||||
outline: none
|
||||
position: fixed
|
||||
z-index: 1
|
||||
|
||||
&.fadeOut
|
||||
animateFadeOut()
|
||||
|
||||
.select-tree-root>.tree-content
|
||||
width: 140px
|
||||
|
||||
&>.tree-options
|
||||
position: relative
|
||||
z-index: 2
|
||||
|
||||
.tree-inputs
|
||||
position: relative
|
||||
|
||||
&>.tree-leaf
|
||||
position: relative
|
||||
|
||||
.icon-check
|
||||
theme('background-color', '$activeColor')
|
||||
animateZoomIn()
|
||||
left: -46px
|
||||
position: absolute
|
||||
top: 3px
|
||||
|
||||
span
|
||||
background: white
|
||||
font-weight: normal
|
||||
height: 46px
|
||||
line-height: 46px
|
||||
padding: 0 12px
|
||||
|
||||
input, span
|
||||
display: none
|
||||
|
||||
.actions
|
||||
padding-top: 16px
|
||||
opacity: 0
|
||||
|
||||
&:not(.fadeOut)
|
||||
animateFadeIn()
|
||||
animation-delay: 0.3s
|
||||
|
||||
&.fadeOut
|
||||
animateFadeOut()
|
||||
|
||||
&.selected>.tree-leaf
|
||||
|
||||
span
|
||||
display: block
|
||||
|
||||
&.tree-columns
|
||||
|
||||
.select-tree-root
|
||||
|
||||
&.navigated .select-tree-common .content
|
||||
animation-name: none
|
||||
|
||||
&.selected .select-tree-common .content
|
||||
animation-name: selectTreeCommonCloseLeft
|
||||
|
||||
.select-tree-common
|
||||
padding-left: 0
|
||||
padding-right: 6px
|
||||
right: auto
|
||||
left: 0
|
||||
width: 180px
|
||||
|
||||
&>.tree-content
|
||||
transform-origin(0% 50%)
|
||||
width: 280px
|
||||
|
||||
.select-tree-common .content
|
||||
right: -180px
|
||||
|
||||
&.started .select-tree-common .content
|
||||
right: 46px
|
||||
|
||||
&.navigated .select-tree-common .content
|
||||
animation-name: selectTreeCommonCloseRight
|
||||
|
||||
.tree-inputs>label
|
||||
float: left
|
||||
width: 50%
|
||||
|
||||
@keyframes selectTreeCommonCloseRight {
|
||||
from {
|
||||
height: 37px
|
||||
display: table
|
||||
right: 6px
|
||||
opacity: 1
|
||||
visibility: visible
|
||||
}
|
||||
to {
|
||||
height: 100%
|
||||
right: -100%
|
||||
opacity: 0
|
||||
visibility: hidden
|
||||
width: calc(100% - 6px)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user