feat(ui): move to React 18 and base for using shadcn/ui (#4174)
Co-authored-by: IbrahimCSAE <ibrahim.mdev@gmail.com>
This commit is contained in:
parent
72b63dcd6a
commit
70f2c797f4
@ -42,6 +42,7 @@ jobs:
|
|||||||
###
|
###
|
||||||
UNIT_TESTS:
|
UNIT_TESTS:
|
||||||
<<: *defaults
|
<<: *defaults
|
||||||
|
resource_class: large
|
||||||
steps:
|
steps:
|
||||||
# Update yarn
|
# Update yarn
|
||||||
- run: yarn -v
|
- run: yarn -v
|
||||||
@ -98,6 +99,7 @@ jobs:
|
|||||||
###
|
###
|
||||||
BUILD:
|
BUILD:
|
||||||
<<: *defaults
|
<<: *defaults
|
||||||
|
resource_class: large
|
||||||
steps:
|
steps:
|
||||||
# Checkout code and ALL Git Tags
|
# Checkout code and ALL Git Tags
|
||||||
- checkout
|
- checkout
|
||||||
@ -146,6 +148,7 @@ jobs:
|
|||||||
# just to make sure later on we can publish them
|
# just to make sure later on we can publish them
|
||||||
BUILD_PACKAGES_QUICK:
|
BUILD_PACKAGES_QUICK:
|
||||||
<<: *defaults
|
<<: *defaults
|
||||||
|
resource_class: large
|
||||||
steps:
|
steps:
|
||||||
- run: yarn -v
|
- run: yarn -v
|
||||||
# Checkout code and ALL Git Tags
|
# Checkout code and ALL Git Tags
|
||||||
@ -195,6 +198,7 @@ jobs:
|
|||||||
###
|
###
|
||||||
NPM_PUBLISH:
|
NPM_PUBLISH:
|
||||||
<<: *defaults
|
<<: *defaults
|
||||||
|
resource_class: large
|
||||||
steps:
|
steps:
|
||||||
- run: yarn -v
|
- run: yarn -v
|
||||||
# Checkout code and ALL Git Tags
|
# Checkout code and ALL Git Tags
|
||||||
@ -264,6 +268,7 @@ jobs:
|
|||||||
|
|
||||||
DOCKER_RELEASE_PUBLISH:
|
DOCKER_RELEASE_PUBLISH:
|
||||||
<<: *defaults
|
<<: *defaults
|
||||||
|
resource_class: large
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_workspace:
|
||||||
at: ~/repo
|
at: ~/repo
|
||||||
@ -293,6 +298,7 @@ jobs:
|
|||||||
|
|
||||||
DOCKER_BETA_PUBLISH:
|
DOCKER_BETA_PUBLISH:
|
||||||
<<: *defaults
|
<<: *defaults
|
||||||
|
resource_class: large
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_workspace:
|
||||||
at: ~/repo
|
at: ~/repo
|
||||||
@ -397,6 +403,7 @@ jobs:
|
|||||||
default: ''
|
default: ''
|
||||||
description: Directory containing package.json
|
description: Directory containing package.json
|
||||||
type: string
|
type: string
|
||||||
|
resource_class: large
|
||||||
steps:
|
steps:
|
||||||
- cypress/install:
|
- cypress/install:
|
||||||
cypress-cache-key: << parameters.cypress-cache-key >>
|
cypress-cache-key: << parameters.cypress-cache-key >>
|
||||||
|
|||||||
@ -98,6 +98,38 @@ module.exports = (env, argv, { SRC_DIR, ENTRY }) => {
|
|||||||
module: {
|
module: {
|
||||||
noParse: [/(codec)/, /(dicomicc)/],
|
noParse: [/(codec)/, /(dicomicc)/],
|
||||||
rules: [
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.svg?$/,
|
||||||
|
oneOf: [
|
||||||
|
{
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: '@svgr/webpack',
|
||||||
|
options: {
|
||||||
|
svgoConfig: {
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
name: 'preset-default',
|
||||||
|
params: {
|
||||||
|
overrides: {
|
||||||
|
removeViewBox: false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
prettier: false,
|
||||||
|
svgo: true,
|
||||||
|
titleProp: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
issuer: {
|
||||||
|
and: [/\.(ts|tsx|js|jsx|md|mdx)$/],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
test: /\.js$/,
|
test: /\.js$/,
|
||||||
enforce: 'pre',
|
enforce: 'pre',
|
||||||
|
|||||||
@ -5,23 +5,6 @@ module.exports = {
|
|||||||
babelrcRoots: ['./platform/*', './extensions/*', './modes/*'],
|
babelrcRoots: ['./platform/*', './extensions/*', './modes/*'],
|
||||||
presets: ['@babel/preset-env', '@babel/preset-react', '@babel/preset-typescript'],
|
presets: ['@babel/preset-env', '@babel/preset-react', '@babel/preset-typescript'],
|
||||||
plugins: [
|
plugins: [
|
||||||
[
|
|
||||||
'inline-react-svg',
|
|
||||||
{
|
|
||||||
svgo: {
|
|
||||||
plugins: [
|
|
||||||
{
|
|
||||||
name: 'preset-default',
|
|
||||||
params: {
|
|
||||||
overrides: {
|
|
||||||
removeViewBox: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
['@babel/plugin-proposal-class-properties', { loose: true }],
|
['@babel/plugin-proposal-class-properties', { loose: true }],
|
||||||
'@babel/plugin-transform-typescript',
|
'@babel/plugin-transform-typescript',
|
||||||
['@babel/plugin-proposal-private-property-in-object', { loose: true }],
|
['@babel/plugin-proposal-private-property-in-object', { loose: true }],
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: ['inline-react-svg', '@babel/plugin-proposal-class-properties'],
|
plugins: ['@babel/plugin-proposal-class-properties'],
|
||||||
env: {
|
env: {
|
||||||
test: {
|
test: {
|
||||||
presets: [
|
presets: [
|
||||||
|
|||||||
@ -38,8 +38,8 @@
|
|||||||
"@ohif/extension-default": "3.9.0-beta.21",
|
"@ohif/extension-default": "3.9.0-beta.21",
|
||||||
"@ohif/i18n": "3.9.0-beta.21",
|
"@ohif/i18n": "3.9.0-beta.21",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^17.0.2",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^18.3.1",
|
||||||
"react-i18next": "^10.11.0",
|
"react-i18next": "^10.11.0",
|
||||||
"react-router": "^6.3.0",
|
"react-router": "^6.3.0",
|
||||||
"react-router-dom": "^6.3.0"
|
"react-router-dom": "^6.3.0"
|
||||||
|
|||||||
@ -358,11 +358,6 @@ OHIFCornerstoneRTViewport.propTypes = {
|
|||||||
viewportId: PropTypes.string.isRequired,
|
viewportId: PropTypes.string.isRequired,
|
||||||
dataSource: PropTypes.object,
|
dataSource: PropTypes.object,
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
customProps: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
OHIFCornerstoneRTViewport.defaultProps = {
|
|
||||||
customProps: {},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function _getReferencedDisplaySetMetadata(referencedDisplaySet) {
|
function _getReferencedDisplaySetMetadata(referencedDisplaySet) {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: ['inline-react-svg', '@babel/plugin-proposal-class-properties'],
|
plugins: ['@babel/plugin-proposal-class-properties'],
|
||||||
env: {
|
env: {
|
||||||
test: {
|
test: {
|
||||||
presets: [
|
presets: [
|
||||||
|
|||||||
@ -38,8 +38,8 @@
|
|||||||
"@ohif/extension-default": "3.9.0-beta.21",
|
"@ohif/extension-default": "3.9.0-beta.21",
|
||||||
"@ohif/i18n": "3.9.0-beta.21",
|
"@ohif/i18n": "3.9.0-beta.21",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^17.0.2",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^18.3.1",
|
||||||
"react-i18next": "^12.2.2",
|
"react-i18next": "^12.2.2",
|
||||||
"react-router": "^6.8.1",
|
"react-router": "^6.8.1",
|
||||||
"react-router-dom": "^6.8.1"
|
"react-router-dom": "^6.8.1"
|
||||||
|
|||||||
@ -367,11 +367,6 @@ OHIFCornerstoneSEGViewport.propTypes = {
|
|||||||
viewportId: PropTypes.string.isRequired,
|
viewportId: PropTypes.string.isRequired,
|
||||||
dataSource: PropTypes.object,
|
dataSource: PropTypes.object,
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
customProps: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
OHIFCornerstoneSEGViewport.defaultProps = {
|
|
||||||
customProps: {},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function _getReferencedDisplaySetMetadata(referencedDisplaySet, segDisplaySet) {
|
function _getReferencedDisplaySetMetadata(referencedDisplaySet, segDisplaySet) {
|
||||||
|
|||||||
@ -42,7 +42,7 @@
|
|||||||
"dicom-parser": "^1.8.9",
|
"dicom-parser": "^1.8.9",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^17.0.2"
|
"react": "^18.3.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
|
|||||||
@ -367,16 +367,11 @@ OHIFCornerstoneSRViewport.propTypes = {
|
|||||||
dataSource: PropTypes.object,
|
dataSource: PropTypes.object,
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
viewportLabel: PropTypes.string,
|
viewportLabel: PropTypes.string,
|
||||||
customProps: PropTypes.object,
|
|
||||||
viewportOptions: PropTypes.object,
|
viewportOptions: PropTypes.object,
|
||||||
servicesManager: PropTypes.object.isRequired,
|
servicesManager: PropTypes.object.isRequired,
|
||||||
extensionManager: PropTypes.instanceOf(ExtensionManager).isRequired,
|
extensionManager: PropTypes.instanceOf(ExtensionManager).isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
OHIFCornerstoneSRViewport.defaultProps = {
|
|
||||||
customProps: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
async function _getViewportReferencedDisplaySetData(
|
async function _getViewportReferencedDisplaySetData(
|
||||||
displaySet,
|
displaySet,
|
||||||
measurementSelected,
|
measurementSelected,
|
||||||
|
|||||||
@ -38,7 +38,7 @@
|
|||||||
"dicom-parser": "^1.8.21",
|
"dicom-parser": "^1.8.21",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^17.0.2"
|
"react": "^18.3.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
|
|||||||
@ -46,9 +46,9 @@
|
|||||||
"dicom-parser": "^1.8.21",
|
"dicom-parser": "^1.8.21",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^17.0.2",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^18.3.1",
|
||||||
"react-resize-detector": "^6.7.6"
|
"react-resize-detector": "^10.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"lodash": "^4.17.21"
|
"lodash": "^4.17.21"
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import React, { useEffect, useRef, useCallback, useState } from 'react';
|
import React, { useEffect, useRef, useCallback, useState } from 'react';
|
||||||
import ReactResizeDetector from 'react-resize-detector';
|
import { useResizeDetector } from 'react-resize-detector';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import * as cs3DTools from '@cornerstonejs/tools';
|
import * as cs3DTools from '@cornerstonejs/tools';
|
||||||
import {
|
import {
|
||||||
@ -109,7 +109,7 @@ const OHIFCornerstoneViewport = React.memo((props: withAppTypes) => {
|
|||||||
onElementEnabled,
|
onElementEnabled,
|
||||||
// eslint-disable-next-line react/prop-types
|
// eslint-disable-next-line react/prop-types
|
||||||
onElementDisabled,
|
onElementDisabled,
|
||||||
isJumpToMeasurementDisabled,
|
isJumpToMeasurementDisabled = false,
|
||||||
// Note: you SHOULD NOT use the initialImageIdOrIndex for manipulation
|
// Note: you SHOULD NOT use the initialImageIdOrIndex for manipulation
|
||||||
// of the imageData in the OHIFCornerstoneViewport. This prop is used
|
// of the imageData in the OHIFCornerstoneViewport. This prop is used
|
||||||
// to set the initial state of the viewport's first image to render
|
// to set the initial state of the viewport's first image to render
|
||||||
@ -140,7 +140,7 @@ const OHIFCornerstoneViewport = React.memo((props: withAppTypes) => {
|
|||||||
|
|
||||||
const [scrollbarHeight, setScrollbarHeight] = useState('100px');
|
const [scrollbarHeight, setScrollbarHeight] = useState('100px');
|
||||||
const [enabledVPElement, setEnabledVPElement] = useState(null);
|
const [enabledVPElement, setEnabledVPElement] = useState(null);
|
||||||
const elementRef = useRef();
|
const elementRef = useRef() as React.MutableRefObject<HTMLDivElement>;
|
||||||
const [appConfig] = useAppConfig();
|
const [appConfig] = useAppConfig();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -417,19 +417,21 @@ const OHIFCornerstoneViewport = React.memo((props: withAppTypes) => {
|
|||||||
});
|
});
|
||||||
}, [displaySets, viewportId, viewportActionCornersService, servicesManager, commandsManager]);
|
}, [displaySets, viewportId, viewportActionCornersService, servicesManager, commandsManager]);
|
||||||
|
|
||||||
|
const { ref: resizeRef } = useResizeDetector({
|
||||||
|
onResize,
|
||||||
|
});
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<div className="viewport-wrapper">
|
<div className="viewport-wrapper">
|
||||||
<ReactResizeDetector
|
|
||||||
onResize={onResize}
|
|
||||||
targetRef={elementRef.current}
|
|
||||||
/>
|
|
||||||
<div
|
<div
|
||||||
className="cornerstone-viewport-element"
|
className="cornerstone-viewport-element"
|
||||||
style={{ height: '100%', width: '100%' }}
|
style={{ height: '100%', width: '100%' }}
|
||||||
onContextMenu={e => e.preventDefault()}
|
onContextMenu={e => e.preventDefault()}
|
||||||
onMouseDown={e => e.preventDefault()}
|
onMouseDown={e => e.preventDefault()}
|
||||||
ref={elementRef}
|
ref={el => {
|
||||||
|
resizeRef.current = el;
|
||||||
|
elementRef.current = el;
|
||||||
|
}}
|
||||||
></div>
|
></div>
|
||||||
<CornerstoneOverlays
|
<CornerstoneOverlays
|
||||||
viewportId={viewportId}
|
viewportId={viewportId}
|
||||||
@ -683,10 +685,6 @@ function _rehydrateSynchronizers(
|
|||||||
// Component displayName
|
// Component displayName
|
||||||
OHIFCornerstoneViewport.displayName = 'OHIFCornerstoneViewport';
|
OHIFCornerstoneViewport.displayName = 'OHIFCornerstoneViewport';
|
||||||
|
|
||||||
OHIFCornerstoneViewport.defaultProps = {
|
|
||||||
isJumpToMeasurementDisabled: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
OHIFCornerstoneViewport.propTypes = {
|
OHIFCornerstoneViewport.propTypes = {
|
||||||
displaySets: PropTypes.array.isRequired,
|
displaySets: PropTypes.array.isRequired,
|
||||||
dataSource: PropTypes.object.isRequired,
|
dataSource: PropTypes.object.isRequired,
|
||||||
|
|||||||
@ -78,14 +78,8 @@ function ViewportImageSliceLoadingIndicator({ viewportData, element }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ViewportImageSliceLoadingIndicator.propTypes = {
|
ViewportImageSliceLoadingIndicator.propTypes = {
|
||||||
percentComplete: PropTypes.number,
|
|
||||||
error: PropTypes.object,
|
error: PropTypes.object,
|
||||||
element: PropTypes.object,
|
element: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
ViewportImageSliceLoadingIndicator.defaultProps = {
|
|
||||||
percentComplete: 0,
|
|
||||||
error: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ViewportImageSliceLoadingIndicator;
|
export default ViewportImageSliceLoadingIndicator;
|
||||||
|
|||||||
@ -136,16 +136,6 @@ function ViewportOrientationMarkers({
|
|||||||
return <div className="ViewportOrientationMarkers select-none">{markers}</div>;
|
return <div className="ViewportOrientationMarkers select-none">{markers}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewportOrientationMarkers.propTypes = {
|
|
||||||
percentComplete: PropTypes.number,
|
|
||||||
error: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
ViewportOrientationMarkers.defaultProps = {
|
|
||||||
percentComplete: 0,
|
|
||||||
error: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Computes the orientation labels on a Cornerstone-enabled Viewport element
|
* Computes the orientation labels on a Cornerstone-enabled Viewport element
|
||||||
|
|||||||
@ -6,7 +6,7 @@ function _getVolumesFromViewport(viewport) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _getVolumeFromViewport(viewport) {
|
function _getVolumeFromViewport(viewport) {
|
||||||
const volumes = _getVolumesFromViewport(viewport);
|
const volumes = _getVolumesFromViewport(viewport).filter(volume => volume);
|
||||||
const dynamicVolume = volumes.find(volume => volume.isDynamicVolume());
|
const dynamicVolume = volumes.find(volume => volume.isDynamicVolume());
|
||||||
|
|
||||||
return dynamicVolume ?? volumes[0];
|
return dynamicVolume ?? volumes[0];
|
||||||
|
|||||||
@ -37,8 +37,8 @@
|
|||||||
"dcmjs": "^0.29.12",
|
"dcmjs": "^0.29.12",
|
||||||
"dicomweb-client": "^0.10.4",
|
"dicomweb-client": "^0.10.4",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^17.0.2",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^18.3.1",
|
||||||
"react-i18next": "^12.2.2",
|
"react-i18next": "^12.2.2",
|
||||||
"react-window": "^1.8.9",
|
"react-window": "^1.8.9",
|
||||||
"webpack": "^5.50.0",
|
"webpack": "^5.50.0",
|
||||||
|
|||||||
@ -2,7 +2,13 @@ import React, { useEffect, useState, useCallback } from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { LayoutSelector as OHIFLayoutSelector, ToolbarButton } from '@ohif/ui';
|
import { LayoutSelector as OHIFLayoutSelector, ToolbarButton } from '@ohif/ui';
|
||||||
|
|
||||||
function LegacyLayoutSelectorWithServices({ servicesManager, ...props }: withAppTypes) {
|
function LegacyLayoutSelectorWithServices({
|
||||||
|
servicesManager,
|
||||||
|
rows = 3,
|
||||||
|
columns = 3,
|
||||||
|
onLayoutChange = () => {},
|
||||||
|
...props
|
||||||
|
}) {
|
||||||
const { toolbarService } = servicesManager.services;
|
const { toolbarService } = servicesManager.services;
|
||||||
|
|
||||||
const onSelection = useCallback(
|
const onSelection = useCallback(
|
||||||
@ -78,10 +84,4 @@ LayoutSelector.propTypes = {
|
|||||||
servicesManager: PropTypes.object.isRequired,
|
servicesManager: PropTypes.object.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
LayoutSelector.defaultProps = {
|
|
||||||
rows: 3,
|
|
||||||
columns: 3,
|
|
||||||
onLayoutChange: () => {},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default LegacyLayoutSelectorWithServices;
|
export default LegacyLayoutSelectorWithServices;
|
||||||
|
|||||||
@ -124,8 +124,9 @@ function ToolbarLayoutSelectorWithServices({
|
|||||||
}
|
}
|
||||||
|
|
||||||
function LayoutSelector({
|
function LayoutSelector({
|
||||||
rows,
|
rows = 3,
|
||||||
columns,
|
columns = 4,
|
||||||
|
onLayoutChange = () => {},
|
||||||
className,
|
className,
|
||||||
onSelection,
|
onSelection,
|
||||||
onSelectionPreset,
|
onSelectionPreset,
|
||||||
@ -242,10 +243,4 @@ LayoutSelector.propTypes = {
|
|||||||
servicesManager: PropTypes.object.isRequired,
|
servicesManager: PropTypes.object.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
LayoutSelector.defaultProps = {
|
|
||||||
columns: 4,
|
|
||||||
rows: 3,
|
|
||||||
onLayoutChange: () => {},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ToolbarLayoutSelectorWithServices;
|
export default ToolbarLayoutSelectorWithServices;
|
||||||
|
|||||||
@ -54,7 +54,6 @@ function ToolbarSplitButtonWithServices({
|
|||||||
}
|
}
|
||||||
|
|
||||||
ToolbarSplitButtonWithServices.propTypes = {
|
ToolbarSplitButtonWithServices.propTypes = {
|
||||||
isRadio: PropTypes.bool,
|
|
||||||
groupId: PropTypes.string,
|
groupId: PropTypes.string,
|
||||||
primary: PropTypes.shape({
|
primary: PropTypes.shape({
|
||||||
id: PropTypes.string.isRequired,
|
id: PropTypes.string.isRequired,
|
||||||
@ -87,9 +86,4 @@ ToolbarSplitButtonWithServices.propTypes = {
|
|||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
ToolbarSplitButtonWithServices.defaultProps = {
|
|
||||||
isRadio: false,
|
|
||||||
isAction: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ToolbarSplitButtonWithServices;
|
export default ToolbarSplitButtonWithServices;
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { ToolbarButton } from '@ohif/ui';
|
import { ToolbarButton } from '@ohif/ui';
|
||||||
|
|
||||||
function NestedMenu({ children, label, icon, isActive }) {
|
function NestedMenu({ children, label = 'More', icon = 'tool-more-menu', isActive }) {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
const toggleNestedMenu = () => setIsOpen(!isOpen);
|
const toggleNestedMenu = () => setIsOpen(!isOpen);
|
||||||
@ -39,9 +39,4 @@ NestedMenu.propTypes = {
|
|||||||
label: PropTypes.string,
|
label: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
NestedMenu.defaultProps = {
|
|
||||||
icon: 'tool-more-menu',
|
|
||||||
label: 'More',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default NestedMenu;
|
export default NestedMenu;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: ['inline-react-svg', '@babel/plugin-proposal-class-properties'],
|
plugins: ['@babel/plugin-proposal-class-properties'],
|
||||||
env: {
|
env: {
|
||||||
test: {
|
test: {
|
||||||
presets: [
|
presets: [
|
||||||
|
|||||||
@ -35,8 +35,8 @@
|
|||||||
"@ohif/i18n": "3.9.0-beta.21",
|
"@ohif/i18n": "3.9.0-beta.21",
|
||||||
"@ohif/ui": "3.9.0-beta.21",
|
"@ohif/ui": "3.9.0-beta.21",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^17.0.2",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^18.3.1",
|
||||||
"react-i18next": "^10.11.0",
|
"react-i18next": "^10.11.0",
|
||||||
"react-router": "^6.8.1",
|
"react-router": "^6.8.1",
|
||||||
"react-router-dom": "^6.8.1"
|
"react-router-dom": "^6.8.1"
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import ReactResizeDetector from 'react-resize-detector';
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import debounce from 'lodash.debounce';
|
|
||||||
import { LoadingIndicatorProgress } from '@ohif/ui';
|
import { LoadingIndicatorProgress } from '@ohif/ui';
|
||||||
|
|
||||||
import './DicomMicroscopyViewport.css';
|
import './DicomMicroscopyViewport.css';
|
||||||
@ -23,18 +21,12 @@ class DicomMicroscopyViewport extends Component {
|
|||||||
|
|
||||||
container = React.createRef();
|
container = React.createRef();
|
||||||
overlayElement = React.createRef();
|
overlayElement = React.createRef();
|
||||||
debouncedResize: () => any;
|
|
||||||
|
|
||||||
constructor(props: any) {
|
constructor(props: any) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
const { microscopyService } = this.props.servicesManager.services;
|
const { microscopyService } = this.props.servicesManager.services;
|
||||||
this.microscopyService = microscopyService;
|
this.microscopyService = microscopyService;
|
||||||
this.debouncedResize = debounce(() => {
|
|
||||||
if (this.viewer) {
|
|
||||||
this.viewer.resize();
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
@ -54,6 +46,7 @@ class DicomMicroscopyViewport extends Component {
|
|||||||
servicesManager: PropTypes.object,
|
servicesManager: PropTypes.object,
|
||||||
extensionManager: PropTypes.object,
|
extensionManager: PropTypes.object,
|
||||||
commandsManager: PropTypes.object,
|
commandsManager: PropTypes.object,
|
||||||
|
resizeRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({ current: PropTypes.any })]),
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -298,13 +291,16 @@ class DicomMicroscopyViewport extends Component {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{ReactResizeDetector && (
|
|
||||||
<ReactResizeDetector handleWidth handleHeight onResize={this.onWindowResize} />
|
|
||||||
)}
|
|
||||||
{this.state.error ? (
|
{this.state.error ? (
|
||||||
<h2>{JSON.stringify(this.state.error)}</h2>
|
<h2>{JSON.stringify(this.state.error)}</h2>
|
||||||
) : (
|
) : (
|
||||||
<div style={style} ref={this.container} />
|
<div
|
||||||
|
style={style}
|
||||||
|
ref={(ref: any) => {
|
||||||
|
this.container.current = ref;
|
||||||
|
this.props.resizeRef.current = ref;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
{this.state.isLoaded ? null : (
|
{this.state.isLoaded ? null : (
|
||||||
<LoadingIndicatorProgress className={'h-full w-full bg-black'} />
|
<LoadingIndicatorProgress className={'h-full w-full bg-black'} />
|
||||||
@ -312,10 +308,6 @@ class DicomMicroscopyViewport extends Component {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onWindowResize = () => {
|
|
||||||
this.debouncedResize();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DicomMicroscopyViewport;
|
export default DicomMicroscopyViewport;
|
||||||
|
|||||||
@ -8,6 +8,8 @@ import { useViewportGrid } from '@ohif/ui';
|
|||||||
import getDicomMicroscopySopClassHandler from './DicomMicroscopySopClassHandler';
|
import getDicomMicroscopySopClassHandler from './DicomMicroscopySopClassHandler';
|
||||||
import getDicomMicroscopySRSopClassHandler from './DicomMicroscopySRSopClassHandler';
|
import getDicomMicroscopySRSopClassHandler from './DicomMicroscopySRSopClassHandler';
|
||||||
import MicroscopyService from './services/MicroscopyService';
|
import MicroscopyService from './services/MicroscopyService';
|
||||||
|
import { useResizeDetector } from 'react-resize-detector';
|
||||||
|
import debounce from 'lodash.debounce';
|
||||||
|
|
||||||
const Component = React.lazy(() => {
|
const Component = React.lazy(() => {
|
||||||
return import('./DicomMicroscopyViewport');
|
return import('./DicomMicroscopyViewport');
|
||||||
@ -59,14 +61,25 @@ const extension: Types.Extensions.Extension = {
|
|||||||
const [viewportGrid, viewportGridService] = useViewportGrid();
|
const [viewportGrid, viewportGridService] = useViewportGrid();
|
||||||
const { activeViewportId } = viewportGrid;
|
const { activeViewportId } = viewportGrid;
|
||||||
|
|
||||||
// a unique identifier based on the contents of displaySets.
|
|
||||||
// since we changed our rendering pipeline and if there is no
|
|
||||||
// element size change nor viewportId change we won't re-render
|
|
||||||
// we need a way to force re-rendering when displaySets change.
|
|
||||||
const displaySetsKey = useMemo(() => {
|
const displaySetsKey = useMemo(() => {
|
||||||
return props.displaySets.map(ds => ds.displaySetInstanceUID).join('-');
|
return props.displaySets.map(ds => ds.displaySetInstanceUID).join('-');
|
||||||
}, [props.displaySets]);
|
}, [props.displaySets]);
|
||||||
|
|
||||||
|
const onResize = debounce(() => {
|
||||||
|
const { microscopyService } = servicesManager.services;
|
||||||
|
const managedViewer = microscopyService.getAllManagedViewers();
|
||||||
|
|
||||||
|
if (managedViewer && managedViewer.length > 0) {
|
||||||
|
managedViewer[0].viewer.resize();
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
const { ref: resizeRef } = useResizeDetector({
|
||||||
|
onResize,
|
||||||
|
handleHeight: true,
|
||||||
|
handleWidth: true,
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MicroscopyViewport
|
<MicroscopyViewport
|
||||||
key={displaySetsKey}
|
key={displaySetsKey}
|
||||||
@ -78,6 +91,7 @@ const extension: Types.Extensions.Extension = {
|
|||||||
viewportGridService.setActiveViewportId(viewportId);
|
viewportGridService.setActiveViewportId(viewportId);
|
||||||
}}
|
}}
|
||||||
viewportData={viewportOptions}
|
viewportData={viewportOptions}
|
||||||
|
resizeRef={resizeRef}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -628,6 +628,15 @@ export default class MicroscopyService extends PubSubService {
|
|||||||
setROIStyle(uid, styleOptions) {
|
setROIStyle(uid, styleOptions) {
|
||||||
this.managedViewers.forEach(mv => mv.setROIStyle(uid, styleOptions));
|
this.managedViewers.forEach(mv => mv.setROIStyle(uid, styleOptions));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all managed viewers
|
||||||
|
*
|
||||||
|
* @returns {Array} managedViewers
|
||||||
|
*/
|
||||||
|
getAllManagedViewers() {
|
||||||
|
return Array.from(this.managedViewers);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { EVENTS };
|
export { EVENTS };
|
||||||
|
|||||||
@ -36,7 +36,7 @@
|
|||||||
"dicom-parser": "^1.8.9",
|
"dicom-parser": "^1.8.9",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^17.0.2"
|
"react": "^18.3.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
|
|||||||
@ -36,7 +36,7 @@
|
|||||||
"dicom-parser": "^1.8.9",
|
"dicom-parser": "^1.8.9",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^17.0.2"
|
"react": "^18.3.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
|
|||||||
@ -41,8 +41,8 @@
|
|||||||
"dcmjs": "^0.29.12",
|
"dcmjs": "^0.29.12",
|
||||||
"lodash.debounce": "^4.17.21",
|
"lodash.debounce": "^4.17.21",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^17.0.2",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^18.3.1",
|
||||||
"webpack": "^5.50.0",
|
"webpack": "^5.50.0",
|
||||||
"webpack-merge": "^5.7.3"
|
"webpack-merge": "^5.7.3"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -242,11 +242,6 @@ TrackedCornerstoneViewport.propTypes = {
|
|||||||
viewportId: PropTypes.string.isRequired,
|
viewportId: PropTypes.string.isRequired,
|
||||||
dataSource: PropTypes.object,
|
dataSource: PropTypes.object,
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
customProps: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
TrackedCornerstoneViewport.defaultProps = {
|
|
||||||
customProps: {},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function _getNextMeasurementUID(
|
function _getNextMeasurementUID(
|
||||||
|
|||||||
@ -36,7 +36,7 @@
|
|||||||
"dicom-parser": "^1.8.9",
|
"dicom-parser": "^1.8.9",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^17.0.2"
|
"react": "^18.3.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
|
|||||||
@ -36,7 +36,7 @@
|
|||||||
"dicom-parser": "^1.8.9",
|
"dicom-parser": "^1.8.9",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^17.0.2"
|
"react": "^18.3.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: ['inline-react-svg', '@babel/plugin-proposal-class-properties'],
|
plugins: ['@babel/plugin-proposal-class-properties'],
|
||||||
env: {
|
env: {
|
||||||
test: {
|
test: {
|
||||||
presets: [
|
presets: [
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: ['inline-react-svg', '@babel/plugin-proposal-class-properties'],
|
plugins: ['@babel/plugin-proposal-class-properties'],
|
||||||
env: {
|
env: {
|
||||||
test: {
|
test: {
|
||||||
presets: [
|
presets: [
|
||||||
|
|||||||
@ -51,6 +51,38 @@ const config = {
|
|||||||
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
test: /\.svg?$/,
|
||||||
|
oneOf: [
|
||||||
|
{
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: '@svgr/webpack',
|
||||||
|
options: {
|
||||||
|
svgoConfig: {
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
name: 'preset-default',
|
||||||
|
params: {
|
||||||
|
overrides: {
|
||||||
|
removeViewBox: false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
prettier: false,
|
||||||
|
svgo: true,
|
||||||
|
titleProp: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
issuer: {
|
||||||
|
and: [/\.(ts|tsx|js|jsx|md|mdx)$/],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: ['inline-react-svg', '@babel/plugin-proposal-class-properties'],
|
plugins: [ '@babel/plugin-proposal-class-properties'],
|
||||||
env: {
|
env: {
|
||||||
test: {
|
test: {
|
||||||
presets: [
|
presets: [
|
||||||
|
|||||||
@ -63,7 +63,7 @@
|
|||||||
"@babel/preset-typescript": "^7.13.0",
|
"@babel/preset-typescript": "^7.13.0",
|
||||||
"babel-eslint": "^10.1.0",
|
"babel-eslint": "^10.1.0",
|
||||||
"babel-loader": "^8.0.0-beta.4",
|
"babel-loader": "^8.0.0-beta.4",
|
||||||
"babel-plugin-inline-react-svg": "^2.0.1",
|
"@svgr/webpack": "^8.1.0",
|
||||||
"clean-webpack-plugin": "^4.0.0",
|
"clean-webpack-plugin": "^4.0.0",
|
||||||
"copy-webpack-plugin": "^10.2.0",
|
"copy-webpack-plugin": "^10.2.0",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
|
|||||||
@ -65,8 +65,8 @@
|
|||||||
"core-js": "^3.2.1"
|
"core-js": "^3.2.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "17.0.2",
|
"react": "^18.3.1",
|
||||||
"react-dom": "17.0.2"
|
"react-dom": "^18.3.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.23.2",
|
"@babel/core": "^7.23.2",
|
||||||
@ -82,13 +82,13 @@
|
|||||||
"@babel/preset-env": "^7.23.2",
|
"@babel/preset-env": "^7.23.2",
|
||||||
"@babel/preset-react": "^7.16.7",
|
"@babel/preset-react": "^7.16.7",
|
||||||
"@babel/preset-typescript": "^7.13.0",
|
"@babel/preset-typescript": "^7.13.0",
|
||||||
|
"@svgr/webpack": "^8.1.0",
|
||||||
"@types/jest": "^27.5.0",
|
"@types/jest": "^27.5.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.3.0",
|
"@typescript-eslint/eslint-plugin": "^6.3.0",
|
||||||
"@typescript-eslint/parser": "^6.3.0",
|
"@typescript-eslint/parser": "^6.3.0",
|
||||||
"autoprefixer": "^10.4.4",
|
"autoprefixer": "^10.4.4",
|
||||||
"babel-eslint": "9.x",
|
"babel-eslint": "9.x",
|
||||||
"babel-loader": "^8.2.4",
|
"babel-loader": "^8.2.4",
|
||||||
"babel-plugin-inline-react-svg": "^2.0.2",
|
|
||||||
"babel-plugin-module-resolver": "^5.0.0",
|
"babel-plugin-module-resolver": "^5.0.0",
|
||||||
"clean-webpack-plugin": "^3.0.0",
|
"clean-webpack-plugin": "^3.0.0",
|
||||||
"copy-webpack-plugin": "^9.0.1",
|
"copy-webpack-plugin": "^9.0.1",
|
||||||
|
|||||||
@ -28,6 +28,7 @@ export default defineConfig({
|
|||||||
defaultCommandTimeout: 10000,
|
defaultCommandTimeout: 10000,
|
||||||
requestTimeout: 10000,
|
requestTimeout: 10000,
|
||||||
responseTimeout: 10000,
|
responseTimeout: 10000,
|
||||||
|
pageLoadTimeout: 10000,
|
||||||
specPattern: 'cypress/integration/**/*.spec.[jt]s',
|
specPattern: 'cypress/integration/**/*.spec.[jt]s',
|
||||||
projectId: '4oe38f',
|
projectId: '4oe38f',
|
||||||
video: true,
|
video: true,
|
||||||
|
|||||||
@ -78,8 +78,8 @@ describe('OHIF MPR', () => {
|
|||||||
const fOR = Object.keys(fORMap)[0];
|
const fOR = Object.keys(fORMap)[0];
|
||||||
const fORAnnotation = fORMap[fOR];
|
const fORAnnotation = fORMap[fOR];
|
||||||
|
|
||||||
// it should have crosshairs as the only key
|
// it should have crosshairs as the only key (references lines make this 2)
|
||||||
expect(Object.keys(fORAnnotation)).to.have.length(1);
|
expect(Object.keys(fORAnnotation)).to.have.length(2);
|
||||||
|
|
||||||
const crosshairs = fORAnnotation.Crosshairs;
|
const crosshairs = fORAnnotation.Crosshairs;
|
||||||
|
|
||||||
|
|||||||
@ -61,8 +61,8 @@ export function initStudyListAliasesOnDesktop() {
|
|||||||
|
|
||||||
// We can't use data attributes (e.g. data--cy) for these since
|
// We can't use data attributes (e.g. data--cy) for these since
|
||||||
// they are using third party libraries (i.e. react-dates, react-select)
|
// they are using third party libraries (i.e. react-dates, react-select)
|
||||||
cy.get('#date-range-studyDate-start-date').as('studyListStartDate');
|
cy.get('[data-cy="input-date-range-start"').as('studyListStartDate');
|
||||||
cy.get('#date-range-studyDate-end-date').as('studyListEndDate');
|
cy.get('[data-cy="input-date-range-end"').as('studyListEndDate');
|
||||||
cy.get('#input-modalities').as('modalities');
|
cy.get('#input-modalities').as('modalities');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -71,7 +71,9 @@
|
|||||||
"@ohif/mode-microscopy": "3.9.0-beta.21",
|
"@ohif/mode-microscopy": "3.9.0-beta.21",
|
||||||
"@ohif/mode-test": "3.9.0-beta.21",
|
"@ohif/mode-test": "3.9.0-beta.21",
|
||||||
"@ohif/ui": "3.9.0-beta.21",
|
"@ohif/ui": "3.9.0-beta.21",
|
||||||
"@types/react": "^17.0.38",
|
"@ohif/ui-next": "3.9.0-beta.14",
|
||||||
|
"@svgr/webpack": "^8.1.0",
|
||||||
|
"@types/react": "^18.3.3",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
"core-js": "^3.16.1",
|
"core-js": "^3.16.1",
|
||||||
"cornerstone-math": "^0.1.9",
|
"cornerstone-math": "^0.1.9",
|
||||||
@ -87,11 +89,11 @@
|
|||||||
"oidc-client": "1.11.5",
|
"oidc-client": "1.11.5",
|
||||||
"prop-types": "^15.7.2",
|
"prop-types": "^15.7.2",
|
||||||
"query-string": "^6.12.1",
|
"query-string": "^6.12.1",
|
||||||
"react": "^17.0.2",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^18.3.1",
|
||||||
"react-dropzone": "^10.1.7",
|
"react-dropzone": "^10.1.7",
|
||||||
"react-i18next": "^12.2.2",
|
"react-i18next": "^12.2.2",
|
||||||
"react-resize-detector": "^9.1.0",
|
"react-resize-detector": "^10.0.1",
|
||||||
"react-router": "^6.8.1",
|
"react-router": "^6.8.1",
|
||||||
"react-router-dom": "^6.8.1"
|
"react-router-dom": "^6.8.1"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
// External
|
// External
|
||||||
|
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import i18n from '@ohif/i18n';
|
import i18n from '@ohif/i18n';
|
||||||
@ -23,6 +24,7 @@ import {
|
|||||||
UserAuthenticationProvider,
|
UserAuthenticationProvider,
|
||||||
ToolboxProvider,
|
ToolboxProvider,
|
||||||
} from '@ohif/ui';
|
} from '@ohif/ui';
|
||||||
|
import { ThemeWrapper as ThemeWrapperNext, NotificationProvider } from '@ohif/ui-next';
|
||||||
// Viewer Project
|
// Viewer Project
|
||||||
// TODO: Should this influence study list?
|
// TODO: Should this influence study list?
|
||||||
import { AppConfigProvider } from '@state';
|
import { AppConfigProvider } from '@state';
|
||||||
@ -36,7 +38,27 @@ let commandsManager: CommandsManager,
|
|||||||
serviceProvidersManager: ServiceProvidersManager,
|
serviceProvidersManager: ServiceProvidersManager,
|
||||||
hotkeysManager: HotkeysManager;
|
hotkeysManager: HotkeysManager;
|
||||||
|
|
||||||
function App({ config, defaultExtensions, defaultModes }) {
|
function App({
|
||||||
|
config = {
|
||||||
|
/**
|
||||||
|
* Relative route from domain root that OHIF instance is installed at.
|
||||||
|
* For example:
|
||||||
|
*
|
||||||
|
* Hosted at: https://ohif.org/where-i-host-the/viewer/
|
||||||
|
* Value: `/where-i-host-the/viewer/`
|
||||||
|
* */
|
||||||
|
routerBaseName: '/',
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
showLoadingIndicator: true,
|
||||||
|
showStudyList: true,
|
||||||
|
oidc: [],
|
||||||
|
extensions: [],
|
||||||
|
},
|
||||||
|
defaultExtensions = [],
|
||||||
|
defaultModes = [],
|
||||||
|
}) {
|
||||||
const [init, setInit] = useState(null);
|
const [init, setInit] = useState(null);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const run = async () => {
|
const run = async () => {
|
||||||
@ -83,11 +105,13 @@ function App({ config, defaultExtensions, defaultModes }) {
|
|||||||
[AppConfigProvider, { value: appConfigState }],
|
[AppConfigProvider, { value: appConfigState }],
|
||||||
[UserAuthenticationProvider, { service: userAuthenticationService }],
|
[UserAuthenticationProvider, { service: userAuthenticationService }],
|
||||||
[I18nextProvider, { i18n }],
|
[I18nextProvider, { i18n }],
|
||||||
|
[ThemeWrapperNext],
|
||||||
[ThemeWrapper],
|
[ThemeWrapper],
|
||||||
[ToolboxProvider],
|
[ToolboxProvider],
|
||||||
[ViewportGridProvider, { service: viewportGridService }],
|
[ViewportGridProvider, { service: viewportGridService }],
|
||||||
[ViewportDialogProvider, { service: uiViewportDialogService }],
|
[ViewportDialogProvider, { service: uiViewportDialogService }],
|
||||||
[CineProvider, { service: cineService }],
|
[CineProvider, { service: cineService }],
|
||||||
|
// [NotificationProvider, { service: uiNotificationService }],
|
||||||
[SnackbarProvider, { service: uiNotificationService }],
|
[SnackbarProvider, { service: uiNotificationService }],
|
||||||
[DialogProvider, { service: uiDialogService }],
|
[DialogProvider, { service: uiDialogService }],
|
||||||
[ModalProvider, { service: uiModalService, modal: Modal }],
|
[ModalProvider, { service: uiModalService, modal: Modal }],
|
||||||
@ -153,27 +177,9 @@ App.propTypes = {
|
|||||||
/* Extensions that are "bundled" or "baked-in" to the application.
|
/* Extensions that are "bundled" or "baked-in" to the application.
|
||||||
* These would be provided at build time as part of they entry point. */
|
* These would be provided at build time as part of they entry point. */
|
||||||
defaultExtensions: PropTypes.array,
|
defaultExtensions: PropTypes.array,
|
||||||
};
|
/* Modes that are "bundled" or "baked-in" to the application.
|
||||||
|
* These would be provided at build time as part of they entry point. */
|
||||||
App.defaultProps = {
|
defaultModes: PropTypes.array,
|
||||||
config: {
|
|
||||||
/**
|
|
||||||
* Relative route from domain root that OHIF instance is installed at.
|
|
||||||
* For example:
|
|
||||||
*
|
|
||||||
* Hosted at: https://ohif.org/where-i-host-the/viewer/
|
|
||||||
* Value: `/where-i-host-the/viewer/`
|
|
||||||
* */
|
|
||||||
routerBaseName: '/',
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
showLoadingIndicator: true,
|
|
||||||
showStudyList: true,
|
|
||||||
oidc: [],
|
|
||||||
extensions: [],
|
|
||||||
},
|
|
||||||
defaultExtensions: [],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import React, { useEffect, useCallback, useRef, useState } from 'react';
|
import React, { useEffect, useCallback, useRef, useState } from 'react';
|
||||||
import ReactResizeDetector from 'react-resize-detector';
|
import { useResizeDetector } from 'react-resize-detector';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Types, MeasurementService } from '@ohif/core';
|
import { Types, MeasurementService } from '@ohif/core';
|
||||||
import { ViewportGrid, ViewportPane, useViewportGrid } from '@ohif/ui';
|
import { ViewportGrid, ViewportPane, useViewportGrid } from '@ohif/ui';
|
||||||
@ -8,16 +8,22 @@ import classNames from 'classnames';
|
|||||||
import { useAppConfig } from '@state';
|
import { useAppConfig } from '@state';
|
||||||
|
|
||||||
function ViewerViewportGrid(props: withAppTypes) {
|
function ViewerViewportGrid(props: withAppTypes) {
|
||||||
const { servicesManager, viewportComponents, dataSource } = props;
|
const { servicesManager, viewportComponents = [], dataSource } = props;
|
||||||
const [viewportGrid, viewportGridService] = useViewportGrid();
|
const [viewportGrid, viewportGridService] = useViewportGrid();
|
||||||
const [appConfig] = useAppConfig();
|
const [appConfig] = useAppConfig();
|
||||||
|
|
||||||
const { layout, activeViewportId, viewports, isHangingProtocolLayout } = viewportGrid;
|
const { layout, activeViewportId, viewports, isHangingProtocolLayout } = viewportGrid;
|
||||||
const { numCols, numRows } = layout;
|
const { numCols, numRows } = layout;
|
||||||
const elementRef = useRef(null);
|
const { ref: resizeRef } = useResizeDetector({
|
||||||
|
refreshMode: 'debounce',
|
||||||
|
refreshRate: 7,
|
||||||
|
refreshOptions: { leading: true },
|
||||||
|
onResize: () => {
|
||||||
|
viewportGridService.setViewportGridSizeChanged();
|
||||||
|
},
|
||||||
|
});
|
||||||
const layoutHash = useRef(null);
|
const layoutHash = useRef(null);
|
||||||
|
|
||||||
// TODO -> Need some way of selecting which displaySets hit the viewports.
|
|
||||||
const { displaySetService, measurementService, hangingProtocolService, uiNotificationService } =
|
const { displaySetService, measurementService, hangingProtocolService, uiNotificationService } =
|
||||||
servicesManager.services;
|
servicesManager.services;
|
||||||
|
|
||||||
@ -198,50 +204,6 @@ function ViewerViewportGrid(props: withAppTypes) {
|
|||||||
};
|
};
|
||||||
}, [viewports]);
|
}, [viewports]);
|
||||||
|
|
||||||
/**
|
|
||||||
const onDoubleClick = viewportId => {
|
|
||||||
// TODO -> Disabled for now.
|
|
||||||
// onNewImage on a cornerstone viewport is firing setDisplaySetsForViewport.
|
|
||||||
// Which it really really shouldn't. We need a larger fix for jump to
|
|
||||||
// measurements and all cornerstone "imageIndex" state to fix this.
|
|
||||||
if (cachedLayout) {
|
|
||||||
viewportGridService.set({
|
|
||||||
numCols: cachedLayout.numCols,
|
|
||||||
numRows: cachedLayout.numRows,
|
|
||||||
activeViewportId: cachedLayout.activeViewportId,
|
|
||||||
viewports: cachedLayout.viewports,
|
|
||||||
cachedLayout: null,
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cachedViewports = viewports.map(viewport => {
|
|
||||||
return {
|
|
||||||
displaySetInstanceUID: viewport.displaySetInstanceUID,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
viewportGridService.set({
|
|
||||||
numCols: 1,
|
|
||||||
numRows: 1,
|
|
||||||
activeViewportId: 0,
|
|
||||||
viewports: [
|
|
||||||
{
|
|
||||||
displaySetInstanceUID: viewports[viewportId].displaySetInstanceUID,
|
|
||||||
imageIndex: undefined,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
cachedLayout: {
|
|
||||||
numCols,
|
|
||||||
numRows,
|
|
||||||
viewports: cachedViewports,
|
|
||||||
activeViewportId: viewportId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
const onDropHandler = (viewportId, { displaySetInstanceUID }) => {
|
const onDropHandler = (viewportId, { displaySetInstanceUID }) => {
|
||||||
const updatedViewports = _getUpdatedViewports(viewportId, displaySetInstanceUID);
|
const updatedViewports = _getUpdatedViewports(viewportId, displaySetInstanceUID);
|
||||||
viewportGridService.setDisplaySetsForViewports(updatedViewports);
|
viewportGridService.setDisplaySetsForViewports(updatedViewports);
|
||||||
@ -363,21 +325,13 @@ function ViewerViewportGrid(props: withAppTypes) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={elementRef}
|
ref={resizeRef}
|
||||||
className="h-full w-full"
|
className="h-full w-full"
|
||||||
>
|
>
|
||||||
<ViewportGrid
|
<ViewportGrid
|
||||||
numRows={numRows}
|
numRows={numRows}
|
||||||
numCols={numCols}
|
numCols={numCols}
|
||||||
>
|
>
|
||||||
<ReactResizeDetector
|
|
||||||
refreshMode="debounce"
|
|
||||||
refreshRate={7} // ms seems to be fine for 10 viewports
|
|
||||||
onResize={() => {
|
|
||||||
viewportGridService.setViewportGridSizeChanged();
|
|
||||||
}}
|
|
||||||
targetRef={elementRef.current}
|
|
||||||
/>
|
|
||||||
{getViewportPanes()}
|
{getViewportPanes()}
|
||||||
</ViewportGrid>
|
</ViewportGrid>
|
||||||
</div>
|
</div>
|
||||||
@ -389,10 +343,6 @@ ViewerViewportGrid.propTypes = {
|
|||||||
servicesManager: PropTypes.instanceOf(Object).isRequired,
|
servicesManager: PropTypes.instanceOf(Object).isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
ViewerViewportGrid.defaultProps = {
|
|
||||||
viewportComponents: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
function _getViewportComponent(displaySets, viewportComponents, uiNotificationService) {
|
function _getViewportComponent(displaySets, viewportComponents, uiNotificationService) {
|
||||||
if (!displaySets || !displaySets.length) {
|
if (!displaySets || !displaySets.length) {
|
||||||
return EmptyViewport;
|
return EmptyViewport;
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
* Entry point for development and production PWA builds.
|
* Entry point for development and production PWA builds.
|
||||||
*/
|
*/
|
||||||
import 'regenerator-runtime/runtime';
|
import 'regenerator-runtime/runtime';
|
||||||
|
import { createRoot } from 'react-dom/client';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
@ -35,10 +36,10 @@ loadDynamicConfig(window.config).then(config_json => {
|
|||||||
defaultModes,
|
defaultModes,
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Create App */
|
const container = document.getElementById('root');
|
||||||
const app = React.createElement(App, appProps, null);
|
|
||||||
/** Render */
|
const root = createRoot(container);
|
||||||
ReactDOM.render(app, document.getElementById('root'));
|
root.render(React.createElement(App, appProps));
|
||||||
});
|
});
|
||||||
|
|
||||||
export { history };
|
export { history };
|
||||||
|
|||||||
@ -306,9 +306,11 @@ export default function ModeRoute({
|
|||||||
}
|
}
|
||||||
// The unsubscriptions must occur before the extension onModeExit
|
// The unsubscriptions must occur before the extension onModeExit
|
||||||
// in order to prevent exceptions during cleanup caused by spurious events
|
// in order to prevent exceptions during cleanup caused by spurious events
|
||||||
unsubscriptions.forEach(unsub => {
|
if (unsubscriptions) {
|
||||||
unsub();
|
unsubscriptions.forEach(unsub => {
|
||||||
});
|
unsub();
|
||||||
|
});
|
||||||
|
}
|
||||||
// The extension manager must be called after the mode, this is
|
// The extension manager must be called after the mode, this is
|
||||||
// expected to cleanup the state to a standard setup.
|
// expected to cleanup the state to a standard setup.
|
||||||
extensionManager.onModeExit();
|
extensionManager.onModeExit();
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
// Todo: we probably should add external installed extensions/modes here as well.
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
// Note: in Tailwind 3.0, JIT will purge unused styles by default
|
// Note: in Tailwind 3.0, JIT will purge unused styles by default
|
||||||
// but in development, it is often useful to disable this to see
|
// but in development, it is often useful to disable this to see
|
||||||
@ -7,6 +6,7 @@ module.exports = {
|
|||||||
// ...(process.env.NODE_ENV === 'development' && {
|
// ...(process.env.NODE_ENV === 'development' && {
|
||||||
// safelist: [{ pattern: /.*/ }],
|
// safelist: [{ pattern: /.*/ }],
|
||||||
// }),
|
// }),
|
||||||
|
presets: [require('../ui/tailwind.config.js'), require('../ui-next/tailwind.config.js')],
|
||||||
content: [
|
content: [
|
||||||
'./src/**/*.{jsx,js,ts,tsx, css}',
|
'./src/**/*.{jsx,js,ts,tsx, css}',
|
||||||
'../../extensions/**/*.{jsx,js,ts,tsx, css}',
|
'../../extensions/**/*.{jsx,js,ts,tsx, css}',
|
||||||
@ -14,256 +14,10 @@ module.exports = {
|
|||||||
'../../modes/**/*.{jsx,js,ts,tsx, css}',
|
'../../modes/**/*.{jsx,js,ts,tsx, css}',
|
||||||
'./node_modules/@ohif/ui/src/**/*.{js,jsx,ts,tsx, css}',
|
'./node_modules/@ohif/ui/src/**/*.{js,jsx,ts,tsx, css}',
|
||||||
'../../node_modules/@ohif/ui/src/**/*.{js,jsx,ts,tsx,css}',
|
'../../node_modules/@ohif/ui/src/**/*.{js,jsx,ts,tsx,css}',
|
||||||
'../../node_modules/@ohif/ui/src/**/*.{js,jsx,ts,tsx,css}',
|
'../../node_modules/@ohif/ui-next/src/**/*.{js,jsx,ts,tsx,css}',
|
||||||
'../../node_modules/@ohif/extension-*/src/**/*.{js,jsx,css, ts,tsx}',
|
'../../node_modules/@ohif/extension-*/src/**/*.{js,jsx,css, ts,tsx}',
|
||||||
],
|
],
|
||||||
theme: {
|
theme: {
|
||||||
screens: {
|
|
||||||
sm: '640px',
|
|
||||||
md: '768px',
|
|
||||||
lg: '1024px',
|
|
||||||
xl: '1280px',
|
|
||||||
},
|
|
||||||
colors: {
|
|
||||||
overlay: 'rgba(0, 0, 0, 0.8)',
|
|
||||||
transparent: 'transparent',
|
|
||||||
black: '#000',
|
|
||||||
white: '#fff',
|
|
||||||
initial: 'initial',
|
|
||||||
inherit: 'inherit',
|
|
||||||
|
|
||||||
indigo: {
|
|
||||||
dark: '#0b1a42',
|
|
||||||
},
|
|
||||||
aqua: {
|
|
||||||
pale: '#7bb2ce',
|
|
||||||
},
|
|
||||||
|
|
||||||
primary: {
|
|
||||||
light: '#5acce6',
|
|
||||||
main: '#0944b3',
|
|
||||||
dark: '#090c29',
|
|
||||||
active: '#348cfd',
|
|
||||||
},
|
|
||||||
|
|
||||||
inputfield: {
|
|
||||||
main: '#3a3f99',
|
|
||||||
disabled: '#2b166b',
|
|
||||||
focus: '#5acce6',
|
|
||||||
placeholder: '#39383f',
|
|
||||||
},
|
|
||||||
|
|
||||||
secondary: {
|
|
||||||
light: '#3a3f99',
|
|
||||||
main: '#2b166b',
|
|
||||||
dark: '#041c4a',
|
|
||||||
active: '#1f1f27',
|
|
||||||
},
|
|
||||||
|
|
||||||
common: {
|
|
||||||
bright: '#e1e1e1',
|
|
||||||
light: '#a19fad',
|
|
||||||
main: '#fff',
|
|
||||||
dark: '#726f7e',
|
|
||||||
active: '#2c3074',
|
|
||||||
},
|
|
||||||
|
|
||||||
customgreen: {
|
|
||||||
100: '#05D97C',
|
|
||||||
200: '#0FD97C',
|
|
||||||
},
|
|
||||||
|
|
||||||
customblue: {
|
|
||||||
10: '#0A163F',
|
|
||||||
20: '#0B1F54',
|
|
||||||
30: '#09286e',
|
|
||||||
40: '#0E307F',
|
|
||||||
50: '#0F3A94',
|
|
||||||
80: '#1454D4',
|
|
||||||
100: '#c4fdff',
|
|
||||||
200: '#38daff',
|
|
||||||
300: '#1D204D',
|
|
||||||
400: '#90A0C1',
|
|
||||||
},
|
|
||||||
|
|
||||||
customgray: {
|
|
||||||
100: '#262943',
|
|
||||||
},
|
|
||||||
|
|
||||||
gray: {
|
|
||||||
100: '#f7fafc',
|
|
||||||
200: '#edf2f7',
|
|
||||||
300: '#e2e8f0',
|
|
||||||
400: '#cbd5e0',
|
|
||||||
500: '#a0aec0',
|
|
||||||
600: '#718096',
|
|
||||||
700: '#4a5568',
|
|
||||||
800: '#2d3748',
|
|
||||||
900: '#1a202c',
|
|
||||||
},
|
|
||||||
red: {
|
|
||||||
100: '#fff5f5',
|
|
||||||
200: '#fed7d7',
|
|
||||||
300: '#feb2b2',
|
|
||||||
400: '#fc8181',
|
|
||||||
500: '#f56565',
|
|
||||||
600: '#e53e3e',
|
|
||||||
700: '#c53030',
|
|
||||||
800: '#9b2c2c',
|
|
||||||
900: '#742a2a',
|
|
||||||
},
|
|
||||||
orange: {
|
|
||||||
100: '#fffaf0',
|
|
||||||
200: '#feebc8',
|
|
||||||
300: '#fbd38d',
|
|
||||||
400: '#f6ad55',
|
|
||||||
500: '#ed8936',
|
|
||||||
600: '#dd6b20',
|
|
||||||
700: '#c05621',
|
|
||||||
800: '#9c4221',
|
|
||||||
900: '#7b341e',
|
|
||||||
},
|
|
||||||
yellow: {
|
|
||||||
100: '#fffff0',
|
|
||||||
200: '#fefcbf',
|
|
||||||
300: '#faf089',
|
|
||||||
400: '#f6e05e',
|
|
||||||
500: '#ecc94b',
|
|
||||||
600: '#d69e2e',
|
|
||||||
700: '#b7791f',
|
|
||||||
800: '#975a16',
|
|
||||||
900: '#744210',
|
|
||||||
},
|
|
||||||
green: {
|
|
||||||
100: '#f0fff4',
|
|
||||||
200: '#c6f6d5',
|
|
||||||
300: '#9ae6b4',
|
|
||||||
400: '#68d391',
|
|
||||||
500: '#48bb78',
|
|
||||||
600: '#38a169',
|
|
||||||
700: '#2f855a',
|
|
||||||
800: '#276749',
|
|
||||||
900: '#22543d',
|
|
||||||
},
|
|
||||||
teal: {
|
|
||||||
100: '#e6fffa',
|
|
||||||
200: '#b2f5ea',
|
|
||||||
300: '#81e6d9',
|
|
||||||
400: '#4fd1c5',
|
|
||||||
500: '#38b2ac',
|
|
||||||
600: '#319795',
|
|
||||||
700: '#2c7a7b',
|
|
||||||
800: '#285e61',
|
|
||||||
900: '#234e52',
|
|
||||||
},
|
|
||||||
blue: {
|
|
||||||
100: '#ebf8ff',
|
|
||||||
200: '#bee3f8',
|
|
||||||
300: '#90cdf4',
|
|
||||||
400: '#63b3ed',
|
|
||||||
500: '#4299e1',
|
|
||||||
600: '#3182ce',
|
|
||||||
700: '#2b6cb0',
|
|
||||||
800: '#2c5282',
|
|
||||||
900: '#2a4365',
|
|
||||||
},
|
|
||||||
indigo: {
|
|
||||||
100: '#ebf4ff',
|
|
||||||
200: '#c3dafe',
|
|
||||||
300: '#a3bffa',
|
|
||||||
400: '#7f9cf5',
|
|
||||||
500: '#667eea',
|
|
||||||
600: '#5a67d8',
|
|
||||||
700: '#4c51bf',
|
|
||||||
800: '#434190',
|
|
||||||
900: '#3c366b',
|
|
||||||
},
|
|
||||||
purple: {
|
|
||||||
100: '#faf5ff',
|
|
||||||
200: '#e9d8fd',
|
|
||||||
300: '#d6bcfa',
|
|
||||||
400: '#b794f4',
|
|
||||||
500: '#9f7aea',
|
|
||||||
600: '#805ad5',
|
|
||||||
700: '#6b46c1',
|
|
||||||
800: '#553c9a',
|
|
||||||
900: '#44337a',
|
|
||||||
},
|
|
||||||
pink: {
|
|
||||||
100: '#fff5f7',
|
|
||||||
200: '#fed7e2',
|
|
||||||
300: '#fbb6ce',
|
|
||||||
400: '#f687b3',
|
|
||||||
500: '#ed64a6',
|
|
||||||
600: '#d53f8c',
|
|
||||||
700: '#b83280',
|
|
||||||
800: '#97266d',
|
|
||||||
900: '#702459',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
backgroundColor: theme => theme('colors'),
|
|
||||||
backgroundPosition: {
|
|
||||||
bottom: 'bottom',
|
|
||||||
center: 'center',
|
|
||||||
left: 'left',
|
|
||||||
'left-bottom': 'left bottom',
|
|
||||||
'left-top': 'left top',
|
|
||||||
right: 'right',
|
|
||||||
'right-bottom': 'right bottom',
|
|
||||||
'right-top': 'right top',
|
|
||||||
top: 'top',
|
|
||||||
},
|
|
||||||
backgroundSize: {
|
|
||||||
auto: 'auto',
|
|
||||||
cover: 'cover',
|
|
||||||
contain: 'contain',
|
|
||||||
},
|
|
||||||
borderColor: theme => ({
|
|
||||||
...theme('colors'),
|
|
||||||
DEFAULT: theme('colors.gray.300', 'currentColor'),
|
|
||||||
}),
|
|
||||||
boxShadow: {
|
|
||||||
xs: '0 0 0 1px rgba(0, 0, 0, 0.05)',
|
|
||||||
sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
|
|
||||||
DEFAULT: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
|
|
||||||
md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
|
|
||||||
lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
|
|
||||||
xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
|
|
||||||
'2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
|
|
||||||
inner: 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)',
|
|
||||||
outline: '0 0 0 3px rgba(66, 153, 225, 0.5)',
|
|
||||||
none: 'none',
|
|
||||||
},
|
|
||||||
container: {},
|
|
||||||
cursor: {
|
|
||||||
auto: 'auto',
|
|
||||||
default: 'default',
|
|
||||||
pointer: 'pointer',
|
|
||||||
wait: 'wait',
|
|
||||||
text: 'text',
|
|
||||||
move: 'move',
|
|
||||||
'not-allowed': 'not-allowed',
|
|
||||||
},
|
|
||||||
fill: {
|
|
||||||
current: 'currentColor',
|
|
||||||
},
|
|
||||||
flex: {
|
|
||||||
1: '1 1 0%',
|
|
||||||
0.3: '0.3 0.3 0%',
|
|
||||||
0.5: '0.5 0.5 0%',
|
|
||||||
auto: '1 1 auto',
|
|
||||||
initial: '0 1 auto',
|
|
||||||
none: 'none',
|
|
||||||
static: '0 0 auto',
|
|
||||||
},
|
|
||||||
flexGrow: {
|
|
||||||
0: '0',
|
|
||||||
DEFAULT: '1',
|
|
||||||
},
|
|
||||||
flexShrink: {
|
|
||||||
0: '0',
|
|
||||||
DEFAULT: '1',
|
|
||||||
},
|
|
||||||
fontFamily: {
|
fontFamily: {
|
||||||
sans: [
|
sans: [
|
||||||
'Inter',
|
'Inter',
|
||||||
@ -296,500 +50,5 @@ module.exports = {
|
|||||||
'5xl': '3rem',
|
'5xl': '3rem',
|
||||||
'6xl': '4rem',
|
'6xl': '4rem',
|
||||||
},
|
},
|
||||||
fontWeight: {
|
|
||||||
hairline: '100',
|
|
||||||
thin: '200',
|
|
||||||
light: '300',
|
|
||||||
normal: '300',
|
|
||||||
medium: '500',
|
|
||||||
semibold: '600',
|
|
||||||
bold: '700',
|
|
||||||
extrabold: '800',
|
|
||||||
black: '900',
|
|
||||||
},
|
|
||||||
height: theme => ({
|
|
||||||
auto: 'auto',
|
|
||||||
...theme('spacing'),
|
|
||||||
full: '100%',
|
|
||||||
screen: '100vh',
|
|
||||||
inherit: 'inherit',
|
|
||||||
}),
|
|
||||||
inset: theme => ({
|
|
||||||
...theme('spacing'),
|
|
||||||
0: '0',
|
|
||||||
auto: 'auto',
|
|
||||||
full: '100%',
|
|
||||||
viewport: '0.5rem',
|
|
||||||
'1/2': '50%',
|
|
||||||
'viewport-scrollbar': '1.3rem',
|
|
||||||
}),
|
|
||||||
minHeight: theme => ({
|
|
||||||
...theme('spacing'),
|
|
||||||
0: '0',
|
|
||||||
full: '100%',
|
|
||||||
screen: '100vh',
|
|
||||||
}),
|
|
||||||
letterSpacing: {
|
|
||||||
tighter: '-0.05em',
|
|
||||||
tight: '-0.025em',
|
|
||||||
normal: '0',
|
|
||||||
wide: '0.025em',
|
|
||||||
wider: '0.05em',
|
|
||||||
widest: '0.1em',
|
|
||||||
},
|
|
||||||
lineHeight: {
|
|
||||||
none: '1',
|
|
||||||
tight: '1.25',
|
|
||||||
snug: '1.375',
|
|
||||||
normal: '1.5',
|
|
||||||
relaxed: '1.625',
|
|
||||||
loose: '2',
|
|
||||||
3: '.75rem',
|
|
||||||
4: '1rem',
|
|
||||||
5: '1.25rem',
|
|
||||||
6: '1.5rem',
|
|
||||||
7: '1.75rem',
|
|
||||||
8: '2rem',
|
|
||||||
9: '2.25rem',
|
|
||||||
10: '2.5rem',
|
|
||||||
},
|
|
||||||
listStyleType: {
|
|
||||||
none: 'none',
|
|
||||||
disc: 'disc',
|
|
||||||
decimal: 'decimal',
|
|
||||||
},
|
|
||||||
margin: (theme, { negative }) => ({
|
|
||||||
auto: 'auto',
|
|
||||||
...theme('spacing'),
|
|
||||||
...negative(theme('spacing')),
|
|
||||||
}),
|
|
||||||
maxHeight: theme => ({
|
|
||||||
full: '100%',
|
|
||||||
screen: '100vh',
|
|
||||||
...theme('spacing'),
|
|
||||||
}),
|
|
||||||
maxWidth: (theme, { breakpoints }) => ({
|
|
||||||
none: 'none',
|
|
||||||
xs: '20rem',
|
|
||||||
sm: '24rem',
|
|
||||||
md: '28rem',
|
|
||||||
lg: '32rem',
|
|
||||||
xl: '36rem',
|
|
||||||
'2xl': '42rem',
|
|
||||||
'3xl': '48rem',
|
|
||||||
'4xl': '56rem',
|
|
||||||
'5xl': '64rem',
|
|
||||||
'6xl': '72rem',
|
|
||||||
full: '100%',
|
|
||||||
...breakpoints(theme('screens')),
|
|
||||||
...theme('spacing'),
|
|
||||||
}),
|
|
||||||
minWidth: theme => ({
|
|
||||||
...theme('spacing'),
|
|
||||||
0: '0',
|
|
||||||
xs: '2rem',
|
|
||||||
sm: '4rem',
|
|
||||||
md: '6rem',
|
|
||||||
lg: '8rem',
|
|
||||||
xl: '10rem',
|
|
||||||
full: '100%',
|
|
||||||
}),
|
|
||||||
objectPosition: {
|
|
||||||
bottom: 'bottom',
|
|
||||||
center: 'center',
|
|
||||||
left: 'left',
|
|
||||||
'left-bottom': 'left bottom',
|
|
||||||
'left-top': 'left top',
|
|
||||||
right: 'right',
|
|
||||||
'right-bottom': 'right bottom',
|
|
||||||
'right-top': 'right top',
|
|
||||||
top: 'top',
|
|
||||||
},
|
|
||||||
opacity: {
|
|
||||||
0: '0',
|
|
||||||
5: '.5',
|
|
||||||
10: '.10',
|
|
||||||
15: '.15',
|
|
||||||
20: '.20',
|
|
||||||
25: '.25',
|
|
||||||
30: '.30',
|
|
||||||
35: '.35',
|
|
||||||
40: '.40',
|
|
||||||
45: '.45',
|
|
||||||
50: '.50',
|
|
||||||
55: '.55',
|
|
||||||
60: '.60',
|
|
||||||
65: '.65',
|
|
||||||
70: '.70',
|
|
||||||
75: '.75',
|
|
||||||
80: '.80',
|
|
||||||
85: '.85',
|
|
||||||
90: '.90',
|
|
||||||
95: '.95',
|
|
||||||
100: '1',
|
|
||||||
},
|
|
||||||
order: {
|
|
||||||
first: '-9999',
|
|
||||||
last: '9999',
|
|
||||||
none: '0',
|
|
||||||
1: '1',
|
|
||||||
2: '2',
|
|
||||||
3: '3',
|
|
||||||
4: '4',
|
|
||||||
5: '5',
|
|
||||||
6: '6',
|
|
||||||
7: '7',
|
|
||||||
8: '8',
|
|
||||||
9: '9',
|
|
||||||
10: '10',
|
|
||||||
11: '11',
|
|
||||||
12: '12',
|
|
||||||
},
|
|
||||||
padding: theme => theme('spacing'),
|
|
||||||
placeholderColor: theme => theme('colors'),
|
|
||||||
stroke: theme => ({
|
|
||||||
...theme('colors'),
|
|
||||||
current: 'currentColor',
|
|
||||||
}),
|
|
||||||
strokeWidth: {
|
|
||||||
0: '0',
|
|
||||||
1: '1',
|
|
||||||
2: '2',
|
|
||||||
},
|
|
||||||
textColor: theme => theme('colors'),
|
|
||||||
width: theme => ({
|
|
||||||
auto: 'auto',
|
|
||||||
...theme('spacing'),
|
|
||||||
'1/2': '50%',
|
|
||||||
'1/3': '33.333333%',
|
|
||||||
'2/3': '66.666667%',
|
|
||||||
'1/4': '25%',
|
|
||||||
'2/4': '50%',
|
|
||||||
'3/4': '75%',
|
|
||||||
'1/5': '20%',
|
|
||||||
'2/5': '40%',
|
|
||||||
'3/5': '60%',
|
|
||||||
'4/5': '80%',
|
|
||||||
'1/6': '16.666667%',
|
|
||||||
'2/6': '33.333333%',
|
|
||||||
'3/6': '50%',
|
|
||||||
'4/6': '66.666667%',
|
|
||||||
'5/6': '83.333333%',
|
|
||||||
'1/12': '8.333333%',
|
|
||||||
'2/12': '16.666667%',
|
|
||||||
'3/12': '25%',
|
|
||||||
'4/12': '33.333333%',
|
|
||||||
'5/12': '41.666667%',
|
|
||||||
'6/12': '50%',
|
|
||||||
'7/12': '58.333333%',
|
|
||||||
'8/12': '66.666667%',
|
|
||||||
'9/12': '75%',
|
|
||||||
'10/12': '83.333333%',
|
|
||||||
'11/12': '91.666667%',
|
|
||||||
'1/24': '4.166666667%',
|
|
||||||
'2/24': '8.333333333%',
|
|
||||||
'3/24': '12.5%',
|
|
||||||
'4/24': '16.66666667%',
|
|
||||||
'5/24': '20.83333333%',
|
|
||||||
'6/24': '25%',
|
|
||||||
'7/24': '29.16666667%',
|
|
||||||
'8/24': '33.33333333%',
|
|
||||||
'9/24': '37.5%',
|
|
||||||
'10/24': '41.66666667%',
|
|
||||||
'11/24': '45.83333333%',
|
|
||||||
'12/24': '50%',
|
|
||||||
'13/24': '54.16666667%',
|
|
||||||
'14/24': '58.33333333%',
|
|
||||||
'15/24': '62.5%',
|
|
||||||
'16/24': '66.66666667%',
|
|
||||||
'17/24': '70.83333333%',
|
|
||||||
'18/24': '75%',
|
|
||||||
'19/24': '79.16666667%',
|
|
||||||
'20/24': '83.33333333%',
|
|
||||||
'21/24': '87.5%',
|
|
||||||
'22/24': '91.66666667%',
|
|
||||||
'23/24': '95.83333333%',
|
|
||||||
full: '100%',
|
|
||||||
screen: '100vw',
|
|
||||||
'max-content': 'max-content',
|
|
||||||
}),
|
|
||||||
zIndex: {
|
|
||||||
auto: 'auto',
|
|
||||||
0: '0',
|
|
||||||
10: '10',
|
|
||||||
20: '20',
|
|
||||||
30: '30',
|
|
||||||
40: '40',
|
|
||||||
50: '50',
|
|
||||||
},
|
|
||||||
gap: theme => theme('spacing'),
|
|
||||||
gridTemplateColumns: {
|
|
||||||
none: 'none',
|
|
||||||
1: 'repeat(1, minmax(0, 1fr))',
|
|
||||||
2: 'repeat(2, minmax(0, 1fr))',
|
|
||||||
3: 'repeat(3, minmax(0, 1fr))',
|
|
||||||
4: 'repeat(4, minmax(0, 1fr))',
|
|
||||||
5: 'repeat(5, minmax(0, 1fr))',
|
|
||||||
6: 'repeat(6, minmax(0, 1fr))',
|
|
||||||
7: 'repeat(7, minmax(0, 1fr))',
|
|
||||||
8: 'repeat(8, minmax(0, 1fr))',
|
|
||||||
9: 'repeat(9, minmax(0, 1fr))',
|
|
||||||
10: 'repeat(10, minmax(0, 1fr))',
|
|
||||||
11: 'repeat(11, minmax(0, 1fr))',
|
|
||||||
12: 'repeat(12, minmax(0, 1fr))',
|
|
||||||
},
|
|
||||||
gridColumn: {
|
|
||||||
auto: 'auto',
|
|
||||||
'span-1': 'span 1 / span 1',
|
|
||||||
'span-2': 'span 2 / span 2',
|
|
||||||
'span-3': 'span 3 / span 3',
|
|
||||||
'span-4': 'span 4 / span 4',
|
|
||||||
'span-5': 'span 5 / span 5',
|
|
||||||
'span-6': 'span 6 / span 6',
|
|
||||||
'span-7': 'span 7 / span 7',
|
|
||||||
'span-8': 'span 8 / span 8',
|
|
||||||
'span-9': 'span 9 / span 9',
|
|
||||||
'span-10': 'span 10 / span 10',
|
|
||||||
'span-11': 'span 11 / span 11',
|
|
||||||
'span-12': 'span 12 / span 12',
|
|
||||||
},
|
|
||||||
gridColumnStart: {
|
|
||||||
auto: 'auto',
|
|
||||||
1: '1',
|
|
||||||
2: '2',
|
|
||||||
3: '3',
|
|
||||||
4: '4',
|
|
||||||
5: '5',
|
|
||||||
6: '6',
|
|
||||||
7: '7',
|
|
||||||
8: '8',
|
|
||||||
9: '9',
|
|
||||||
10: '10',
|
|
||||||
11: '11',
|
|
||||||
12: '12',
|
|
||||||
13: '13',
|
|
||||||
},
|
|
||||||
gridColumnEnd: {
|
|
||||||
auto: 'auto',
|
|
||||||
1: '1',
|
|
||||||
2: '2',
|
|
||||||
3: '3',
|
|
||||||
4: '4',
|
|
||||||
5: '5',
|
|
||||||
6: '6',
|
|
||||||
7: '7',
|
|
||||||
8: '8',
|
|
||||||
9: '9',
|
|
||||||
10: '10',
|
|
||||||
11: '11',
|
|
||||||
12: '12',
|
|
||||||
13: '13',
|
|
||||||
},
|
|
||||||
gridTemplateRows: {
|
|
||||||
none: 'none',
|
|
||||||
1: 'repeat(1, minmax(0, 1fr))',
|
|
||||||
2: 'repeat(2, minmax(0, 1fr))',
|
|
||||||
3: 'repeat(3, minmax(0, 1fr))',
|
|
||||||
4: 'repeat(4, minmax(0, 1fr))',
|
|
||||||
5: 'repeat(5, minmax(0, 1fr))',
|
|
||||||
6: 'repeat(6, minmax(0, 1fr))',
|
|
||||||
},
|
|
||||||
gridRow: {
|
|
||||||
auto: 'auto',
|
|
||||||
'span-1': 'span 1 / span 1',
|
|
||||||
'span-2': 'span 2 / span 2',
|
|
||||||
'span-3': 'span 3 / span 3',
|
|
||||||
'span-4': 'span 4 / span 4',
|
|
||||||
'span-5': 'span 5 / span 5',
|
|
||||||
'span-6': 'span 6 / span 6',
|
|
||||||
},
|
|
||||||
gridRowStart: {
|
|
||||||
auto: 'auto',
|
|
||||||
1: '1',
|
|
||||||
2: '2',
|
|
||||||
3: '3',
|
|
||||||
4: '4',
|
|
||||||
5: '5',
|
|
||||||
6: '6',
|
|
||||||
7: '7',
|
|
||||||
},
|
|
||||||
gridRowEnd: {
|
|
||||||
auto: 'auto',
|
|
||||||
1: '1',
|
|
||||||
2: '2',
|
|
||||||
3: '3',
|
|
||||||
4: '4',
|
|
||||||
5: '5',
|
|
||||||
6: '6',
|
|
||||||
7: '7',
|
|
||||||
},
|
|
||||||
transformOrigin: {
|
|
||||||
center: 'center',
|
|
||||||
top: 'top',
|
|
||||||
'top-right': 'top right',
|
|
||||||
right: 'right',
|
|
||||||
'bottom-right': 'bottom right',
|
|
||||||
bottom: 'bottom',
|
|
||||||
'bottom-left': 'bottom left',
|
|
||||||
left: 'left',
|
|
||||||
'top-left': 'top left',
|
|
||||||
},
|
|
||||||
scale: {
|
|
||||||
0: '0',
|
|
||||||
50: '.5',
|
|
||||||
75: '.75',
|
|
||||||
90: '.9',
|
|
||||||
95: '.95',
|
|
||||||
100: '1',
|
|
||||||
105: '1.05',
|
|
||||||
110: '1.1',
|
|
||||||
125: '1.25',
|
|
||||||
150: '1.5',
|
|
||||||
},
|
|
||||||
rotate: {
|
|
||||||
'-180': '-180deg',
|
|
||||||
'-90': '-90deg',
|
|
||||||
'-45': '-45deg',
|
|
||||||
0: '0',
|
|
||||||
45: '45deg',
|
|
||||||
90: '90deg',
|
|
||||||
180: '180deg',
|
|
||||||
},
|
|
||||||
translate: (theme, { negative }) => ({
|
|
||||||
...theme('spacing'),
|
|
||||||
...negative(theme('spacing')),
|
|
||||||
'-full': '-100%',
|
|
||||||
'-1/2': '-50%',
|
|
||||||
'1/2': '50%',
|
|
||||||
full: '100%',
|
|
||||||
}),
|
|
||||||
skew: {
|
|
||||||
'-12': '-12deg',
|
|
||||||
'-6': '-6deg',
|
|
||||||
'-3': '-3deg',
|
|
||||||
0: '0',
|
|
||||||
3: '3deg',
|
|
||||||
6: '6deg',
|
|
||||||
12: '12deg',
|
|
||||||
},
|
|
||||||
transitionProperty: {
|
|
||||||
none: 'none',
|
|
||||||
all: 'all',
|
|
||||||
height: 'height',
|
|
||||||
DEFAULT:
|
|
||||||
'background-color, border-color, color, fill, stroke, opacity, box-shadow, transform',
|
|
||||||
colors: 'background-color, border-color, color, fill, stroke',
|
|
||||||
opacity: 'opacity',
|
|
||||||
shadow: 'box-shadow',
|
|
||||||
transform: 'transform',
|
|
||||||
},
|
|
||||||
transitionTimingFunction: {
|
|
||||||
linear: 'linear',
|
|
||||||
in: 'cubic-bezier(0.4, 0, 1, 1)',
|
|
||||||
out: 'cubic-bezier(0, 0, 0.2, 1)',
|
|
||||||
'in-out': 'cubic-bezier(0.4, 0, 0.2, 1)',
|
|
||||||
},
|
|
||||||
transitionDuration: {
|
|
||||||
75: '75ms',
|
|
||||||
100: '100ms',
|
|
||||||
150: '150ms',
|
|
||||||
200: '200ms',
|
|
||||||
300: '300ms',
|
|
||||||
500: '500ms',
|
|
||||||
700: '700ms',
|
|
||||||
1000: '1000ms',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
variants: {
|
|
||||||
accessibility: ['responsive', 'focus'],
|
|
||||||
alignContent: ['responsive'],
|
|
||||||
alignItems: ['responsive'],
|
|
||||||
alignSelf: ['responsive'],
|
|
||||||
appearance: ['responsive'],
|
|
||||||
backgroundAttachment: ['responsive'],
|
|
||||||
backgroundColor: ['responsive', 'hover', 'focus', 'active', 'group-focus', 'group-hover'],
|
|
||||||
backgroundPosition: ['responsive'],
|
|
||||||
backgroundRepeat: ['responsive'],
|
|
||||||
backgroundSize: ['responsive'],
|
|
||||||
borderCollapse: ['responsive'],
|
|
||||||
borderColor: ['responsive', 'hover', 'focus', 'active', 'group-focus', 'group-hover'],
|
|
||||||
borderRadius: ['responsive', 'focus', 'first', 'last'],
|
|
||||||
borderStyle: ['responsive', 'focus'],
|
|
||||||
borderWidth: ['responsive', 'focus', 'first', 'last'],
|
|
||||||
boxShadow: ['responsive', 'hover', 'focus'],
|
|
||||||
boxSizing: ['responsive'],
|
|
||||||
cursor: ['responsive'],
|
|
||||||
display: ['responsive'],
|
|
||||||
fill: ['responsive'],
|
|
||||||
flex: ['responsive'],
|
|
||||||
flexDirection: ['responsive'],
|
|
||||||
flexGrow: ['responsive'],
|
|
||||||
flexShrink: ['responsive'],
|
|
||||||
flexWrap: ['responsive'],
|
|
||||||
float: ['responsive'],
|
|
||||||
clear: ['responsive'],
|
|
||||||
fontFamily: ['responsive'],
|
|
||||||
fontSize: ['responsive'],
|
|
||||||
fontSmoothing: ['responsive'],
|
|
||||||
fontStyle: ['responsive'],
|
|
||||||
fontWeight: ['responsive', 'hover', 'focus'],
|
|
||||||
height: ['responsive'],
|
|
||||||
inset: ['responsive'],
|
|
||||||
justifyContent: ['responsive'],
|
|
||||||
letterSpacing: ['responsive'],
|
|
||||||
lineHeight: ['responsive'],
|
|
||||||
listStylePosition: ['responsive'],
|
|
||||||
listStyleType: ['responsive'],
|
|
||||||
margin: ['responsive'],
|
|
||||||
maxHeight: ['responsive'],
|
|
||||||
maxWidth: ['responsive'],
|
|
||||||
minHeight: ['responsive'],
|
|
||||||
minWidth: ['responsive'],
|
|
||||||
objectFit: ['responsive'],
|
|
||||||
objectPosition: ['responsive'],
|
|
||||||
opacity: ['responsive', 'hover', 'focus', 'active'],
|
|
||||||
order: ['responsive'],
|
|
||||||
outline: ['responsive', 'focus'],
|
|
||||||
overflow: ['responsive'],
|
|
||||||
padding: ['responsive', 'first'],
|
|
||||||
placeholderColor: ['responsive', 'focus'],
|
|
||||||
pointerEvents: ['responsive'],
|
|
||||||
position: ['responsive'],
|
|
||||||
resize: ['responsive'],
|
|
||||||
stroke: ['responsive'],
|
|
||||||
strokeWidth: ['responsive'],
|
|
||||||
tableLayout: ['responsive'],
|
|
||||||
textAlign: ['responsive'],
|
|
||||||
textColor: ['responsive', 'hover', 'focus', 'active', 'group-hover'],
|
|
||||||
textDecoration: ['responsive', 'hover', 'focus'],
|
|
||||||
textTransform: ['responsive'],
|
|
||||||
userSelect: ['responsive'],
|
|
||||||
verticalAlign: ['responsive'],
|
|
||||||
visibility: ['responsive'],
|
|
||||||
whitespace: ['responsive'],
|
|
||||||
width: ['responsive'],
|
|
||||||
wordBreak: ['responsive'],
|
|
||||||
zIndex: ['responsive'],
|
|
||||||
gap: ['responsive'],
|
|
||||||
gridAutoFlow: ['responsive'],
|
|
||||||
gridTemplateColumns: ['responsive'],
|
|
||||||
gridColumn: ['responsive'],
|
|
||||||
gridColumnStart: ['responsive'],
|
|
||||||
gridColumnEnd: ['responsive'],
|
|
||||||
gridTemplateRows: ['responsive'],
|
|
||||||
gridRow: ['responsive'],
|
|
||||||
gridRowStart: ['responsive'],
|
|
||||||
gridRowEnd: ['responsive'],
|
|
||||||
transform: ['responsive'],
|
|
||||||
transformOrigin: ['responsive'],
|
|
||||||
scale: ['responsive', 'hover', 'focus'],
|
|
||||||
rotate: ['responsive', 'hover', 'focus'],
|
|
||||||
translate: ['responsive', 'hover', 'focus'],
|
|
||||||
skew: ['responsive', 'hover', 'focus'],
|
|
||||||
transitionProperty: ['responsive'],
|
|
||||||
transitionTimingFunction: ['responsive'],
|
|
||||||
transitionDuration: ['responsive'],
|
|
||||||
},
|
|
||||||
corePlugins: {},
|
|
||||||
plugins: [],
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -43,7 +43,40 @@ const config = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
module: {
|
module: {
|
||||||
|
|
||||||
rules: [
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.svg?$/,
|
||||||
|
oneOf: [
|
||||||
|
{
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: '@svgr/webpack',
|
||||||
|
options: {
|
||||||
|
svgoConfig: {
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
name: 'preset-default',
|
||||||
|
params: {
|
||||||
|
overrides: {
|
||||||
|
removeViewBox: false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
prettier: false,
|
||||||
|
svgo: true,
|
||||||
|
titleProp: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
issuer: {
|
||||||
|
and: [/\.(ts|tsx|js|jsx|md|mdx)$/],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
test: /(\.jsx|\.js|\.tsx|\.ts)$/,
|
test: /(\.jsx|\.js|\.tsx|\.ts)$/,
|
||||||
loader: 'babel-loader',
|
loader: 'babel-loader',
|
||||||
|
|||||||
@ -1,21 +1,5 @@
|
|||||||
// https://babeljs.io/docs/en/options#babelrcroots
|
|
||||||
const { extendDefaultPlugins } = require('svgo');
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: [
|
plugins: [
|
||||||
[
|
|
||||||
'inline-react-svg',
|
|
||||||
{
|
|
||||||
svgo: {
|
|
||||||
plugins: extendDefaultPlugins([
|
|
||||||
{
|
|
||||||
name: 'removeViewBox',
|
|
||||||
active: false,
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
['@babel/plugin-proposal-class-properties', { loose: true }],
|
['@babel/plugin-proposal-class-properties', { loose: true }],
|
||||||
'@babel/plugin-transform-typescript',
|
'@babel/plugin-transform-typescript',
|
||||||
['@babel/plugin-proposal-private-property-in-object', { loose: true }],
|
['@babel/plugin-proposal-private-property-in-object', { loose: true }],
|
||||||
|
|||||||
@ -20,8 +20,8 @@
|
|||||||
"@ohif/extension-cornerstone": "^3.0.0",
|
"@ohif/extension-cornerstone": "^3.0.0",
|
||||||
"@ohif/i18n": "^1.0.0",
|
"@ohif/i18n": "^1.0.0",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^17.0.2",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^18.3.1",
|
||||||
"react-i18next": "^12.2.2",
|
"react-i18next": "^12.2.2",
|
||||||
"react-router": "^6.8.1",
|
"react-router": "^6.8.1",
|
||||||
"react-router-dom": "^6.8.1",
|
"react-router-dom": "^6.8.1",
|
||||||
@ -47,7 +47,7 @@
|
|||||||
"@babel/plugin-proposal-private-property-in-object": "7.21.11",
|
"@babel/plugin-proposal-private-property-in-object": "7.21.11",
|
||||||
"babel-eslint": "9.x",
|
"babel-eslint": "9.x",
|
||||||
"babel-loader": "^8.2.4",
|
"babel-loader": "^8.2.4",
|
||||||
"babel-plugin-inline-react-svg": "^2.0.2",
|
"@svgr/webpack": "^8.1.0",
|
||||||
"babel-plugin-module-resolver": "^5.0.0",
|
"babel-plugin-module-resolver": "^5.0.0",
|
||||||
"clean-webpack-plugin": "^4.0.0",
|
"clean-webpack-plugin": "^4.0.0",
|
||||||
"copy-webpack-plugin": "^10.2.0",
|
"copy-webpack-plugin": "^10.2.0",
|
||||||
|
|||||||
@ -49,6 +49,38 @@ const config = {
|
|||||||
],
|
],
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.svg?$/,
|
||||||
|
oneOf: [
|
||||||
|
{
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: '@svgr/webpack',
|
||||||
|
options: {
|
||||||
|
svgoConfig: {
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
name: 'preset-default',
|
||||||
|
params: {
|
||||||
|
overrides: {
|
||||||
|
removeViewBox: false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
prettier: false,
|
||||||
|
svgo: true,
|
||||||
|
titleProp: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
issuer: {
|
||||||
|
and: [/\.(ts|tsx|js|jsx|md|mdx)$/],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
test: /(\.jsx|\.js|\.tsx|\.ts)$/,
|
test: /(\.jsx|\.js|\.tsx|\.ts)$/,
|
||||||
loader: 'babel-loader',
|
loader: 'babel-loader',
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: ['inline-react-svg', '@babel/plugin-proposal-class-properties'],
|
plugins: ['@babel/plugin-proposal-class-properties'],
|
||||||
env: {
|
env: {
|
||||||
test: {
|
test: {
|
||||||
presets: [
|
presets: [
|
||||||
|
|||||||
@ -37,7 +37,7 @@
|
|||||||
"@babel/preset-typescript": "^7.13.0",
|
"@babel/preset-typescript": "^7.13.0",
|
||||||
"babel-eslint": "^8.0.3",
|
"babel-eslint": "^8.0.3",
|
||||||
"babel-loader": "^8.0.0-beta.4",
|
"babel-loader": "^8.0.0-beta.4",
|
||||||
"babel-plugin-inline-react-svg": "^2.0.1",
|
"@svgr/webpack": "^8.1.0",
|
||||||
"clean-webpack-plugin": "^4.0.0",
|
"clean-webpack-plugin": "^4.0.0",
|
||||||
"copy-webpack-plugin": "^10.2.0",
|
"copy-webpack-plugin": "^10.2.0",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
|
|||||||
@ -47,8 +47,8 @@
|
|||||||
"url-loader": "^4.1.1"
|
"url-loader": "^4.1.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^17.0.2",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^17.0.2"
|
"react-dom": "^18.3.1"
|
||||||
},
|
},
|
||||||
"browserslist": {
|
"browserslist": {
|
||||||
"production": [
|
"production": [
|
||||||
|
|||||||
@ -33,8 +33,8 @@
|
|||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"i18next": "^17.0.3",
|
"i18next": "^17.0.3",
|
||||||
"i18next-browser-languagedetector": "^3.0.1",
|
"i18next-browser-languagedetector": "^3.0.1",
|
||||||
"react": "^17.0.2",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^18.3.1",
|
||||||
"react-i18next": "^12.2.2"
|
"react-i18next": "^12.2.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -46,8 +46,8 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"i18next": "^17.0.3",
|
"i18next": "^17.0.3",
|
||||||
"i18next-browser-languagedetector": "^3.0.1",
|
"i18next-browser-languagedetector": "^3.0.1",
|
||||||
"react": "^17.0.2",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^18.3.1",
|
||||||
"react-i18next": "^12.2.2",
|
"react-i18next": "^12.2.2",
|
||||||
"webpack-merge": "^5.7.3"
|
"webpack-merge": "^5.7.3"
|
||||||
}
|
}
|
||||||
|
|||||||
17
platform/ui-next/components.json
Normal file
17
platform/ui-next/components.json
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://ui.shadcn.com/schema.json",
|
||||||
|
"style": "new-york",
|
||||||
|
"rsc": false,
|
||||||
|
"tsx": true,
|
||||||
|
"tailwind": {
|
||||||
|
"config": "tailwind.config.js",
|
||||||
|
"css": "src/tailwind.css",
|
||||||
|
"baseColor": "slate",
|
||||||
|
"cssVariables": true,
|
||||||
|
"prefix": ""
|
||||||
|
},
|
||||||
|
"aliases": {
|
||||||
|
"components": "src/components",
|
||||||
|
"utils": "src/lib/utils"
|
||||||
|
}
|
||||||
|
}
|
||||||
37
platform/ui-next/package.json
Normal file
37
platform/ui-next/package.json
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"name": "@ohif/ui-next",
|
||||||
|
"version": "3.9.0-beta.14",
|
||||||
|
"description": "Next version of OHIF Viewers UI, more customizable using shadcn/ui",
|
||||||
|
"main": "index.ts",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"exports": {
|
||||||
|
"./tailwind.config": "./tailwind.config.ts",
|
||||||
|
"./lib/*": "./src/lib/*.ts",
|
||||||
|
"./components/*": "./src/components/*.tsx",
|
||||||
|
".": "./src/index.ts"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/react-dialog": "^1.0.5",
|
||||||
|
"@radix-ui/react-icons": "^1.3.0",
|
||||||
|
"@radix-ui/react-popover": "^1.0.7",
|
||||||
|
"@radix-ui/react-slot": "^1.0.2",
|
||||||
|
"class-variance-authority": "^0.7.0",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
|
"cmdk": "^1.0.0",
|
||||||
|
"date-fns": "^3.6.0",
|
||||||
|
"framer-motion": "6.2.4",
|
||||||
|
"lucide-react": "^0.379.0",
|
||||||
|
"next-themes": "^0.3.0",
|
||||||
|
"react": "^18.3.1",
|
||||||
|
"react-day-picker": "^8.10.1",
|
||||||
|
"sonner": "^1.4.41",
|
||||||
|
"tailwind-merge": "^2.3.0",
|
||||||
|
"tailwindcss": "3.2.4",
|
||||||
|
"tailwindcss-animate": "^1.0.7"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "OHIF",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
||||||
54
platform/ui-next/src/components/Button/Button.tsx
Normal file
54
platform/ui-next/src/components/Button/Button.tsx
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { Slot } from '@radix-ui/react-slot';
|
||||||
|
import { cva, type VariantProps } from 'class-variance-authority';
|
||||||
|
|
||||||
|
import { cn } from '../../lib/utils';
|
||||||
|
|
||||||
|
const buttonVariants = cva(
|
||||||
|
'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50',
|
||||||
|
{
|
||||||
|
variants: {
|
||||||
|
variant: {
|
||||||
|
default: 'bg-primary text-primary-foreground shadow hover:bg-primary/90',
|
||||||
|
destructive: 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
|
||||||
|
outline:
|
||||||
|
'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',
|
||||||
|
secondary: 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',
|
||||||
|
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
||||||
|
link: 'text-primary underline-offset-4 hover:underline',
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
default: 'h-9 px-4 py-2',
|
||||||
|
sm: 'h-8 rounded-md px-3 text-xs',
|
||||||
|
lg: 'h-10 rounded-md px-8',
|
||||||
|
icon: 'h-9 w-9',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
variant: 'default',
|
||||||
|
size: 'default',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export interface ButtonProps
|
||||||
|
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||||
|
VariantProps<typeof buttonVariants> {
|
||||||
|
asChild?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||||
|
({ className, variant, size, asChild = false, ...props }, ref) => {
|
||||||
|
const Comp = asChild ? Slot : 'button';
|
||||||
|
return (
|
||||||
|
<Comp
|
||||||
|
className={cn(buttonVariants({ variant, size, className }))}
|
||||||
|
ref={ref}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
Button.displayName = 'Button';
|
||||||
|
|
||||||
|
export { Button, buttonVariants };
|
||||||
1
platform/ui-next/src/components/Button/index.ts
Normal file
1
platform/ui-next/src/components/Button/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { Button , buttonVariants} from "./Button"
|
||||||
61
platform/ui-next/src/components/Calendar/Calendar.tsx
Normal file
61
platform/ui-next/src/components/Calendar/Calendar.tsx
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { ChevronLeft, ChevronRight } from 'lucide-react';
|
||||||
|
import { DayPicker } from 'react-day-picker';
|
||||||
|
|
||||||
|
import { cn } from '../../lib/utils';
|
||||||
|
|
||||||
|
import { buttonVariants } from '../Button';
|
||||||
|
|
||||||
|
export type CalendarProps = React.ComponentProps<typeof DayPicker>;
|
||||||
|
|
||||||
|
function Calendar({ className, classNames, showOutsideDays = true, ...props }: CalendarProps) {
|
||||||
|
return (
|
||||||
|
<DayPicker
|
||||||
|
showOutsideDays={showOutsideDays}
|
||||||
|
className={cn('p-3', className)}
|
||||||
|
captionLayout="dropdown"
|
||||||
|
fromYear={1945}
|
||||||
|
toYear={2024}
|
||||||
|
labels={{
|
||||||
|
labelMonthDropdown: () => undefined,
|
||||||
|
labelYearDropdown: () => undefined,
|
||||||
|
}}
|
||||||
|
classNames={{
|
||||||
|
months: 'flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0',
|
||||||
|
month: 'space-y-4',
|
||||||
|
caption: 'flex justify-between items-center px-2',
|
||||||
|
|
||||||
|
caption_dropdowns: 'flex space-x-2',
|
||||||
|
caption_label: 'hidden',
|
||||||
|
nav: 'space-x-1 flex items-center',
|
||||||
|
table: 'w-full border-collapse space-y-1',
|
||||||
|
head_row: 'flex',
|
||||||
|
head_cell: 'text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]',
|
||||||
|
row: 'flex w-full mt-2',
|
||||||
|
cell: 'h-9 w-9 text-center text-sm p-0 relative [&:has([aria-selected].day-range-end)]:rounded-r-md [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected])]:bg-accent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20',
|
||||||
|
day: cn(
|
||||||
|
buttonVariants({ variant: 'ghost' }),
|
||||||
|
'h-9 w-9 p-0 font-normal aria-selected:opacity-100'
|
||||||
|
),
|
||||||
|
day_range_end: 'day-range-end',
|
||||||
|
day_selected:
|
||||||
|
'bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground',
|
||||||
|
day_today: 'bg-accent text-accent-foreground',
|
||||||
|
day_outside:
|
||||||
|
'day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30',
|
||||||
|
day_disabled: 'text-muted-foreground opacity-50',
|
||||||
|
day_range_middle: 'aria-selected:bg-accent aria-selected:text-accent-foreground',
|
||||||
|
day_hidden: 'invisible',
|
||||||
|
...classNames,
|
||||||
|
}}
|
||||||
|
components={{
|
||||||
|
IconLeft: ({ ...props }) => <ChevronLeft className="h-4 w-4" />,
|
||||||
|
IconRight: ({ ...props }) => <ChevronRight className="h-4 w-4" />,
|
||||||
|
}}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Calendar.displayName = 'Calendar';
|
||||||
|
|
||||||
|
export { Calendar };
|
||||||
3
platform/ui-next/src/components/Calendar/index.tsx
Normal file
3
platform/ui-next/src/components/Calendar/index.tsx
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { Calendar } from './Calendar';
|
||||||
|
|
||||||
|
export default Calendar;
|
||||||
66
platform/ui-next/src/components/Combobox/Combobox.tsx
Normal file
66
platform/ui-next/src/components/Combobox/Combobox.tsx
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { Check, ChevronsUpDown } from 'lucide-react';
|
||||||
|
|
||||||
|
import { cn } from '../../lib/utils';
|
||||||
|
import { Button } from '../Button/Button';
|
||||||
|
import {
|
||||||
|
Command,
|
||||||
|
CommandEmpty,
|
||||||
|
CommandGroup,
|
||||||
|
CommandInput,
|
||||||
|
CommandItem,
|
||||||
|
CommandList,
|
||||||
|
} from '../Command/Command';
|
||||||
|
import { Popover, PopoverContent, PopoverTrigger } from '../Popover/Popover';
|
||||||
|
|
||||||
|
export function Combobox({ data = [], placeholder = 'Select item...' }) {
|
||||||
|
const [open, setOpen] = React.useState(false);
|
||||||
|
const [value, setValue] = React.useState('');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Popover
|
||||||
|
open={open}
|
||||||
|
onOpenChange={setOpen}
|
||||||
|
>
|
||||||
|
<PopoverTrigger asChild>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
role="combobox"
|
||||||
|
aria-expanded={open}
|
||||||
|
className="w-[200px] justify-between"
|
||||||
|
>
|
||||||
|
{value ? data.find(item => item.value === value)?.label : placeholder}
|
||||||
|
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||||
|
</Button>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent className="w-[200px] p-0">
|
||||||
|
<Command>
|
||||||
|
<CommandInput placeholder={`Search ${placeholder.toLowerCase()}...`} />
|
||||||
|
<CommandEmpty>No {placeholder.toLowerCase()} found.</CommandEmpty>
|
||||||
|
<CommandList>
|
||||||
|
<CommandGroup>
|
||||||
|
{data.map(item => (
|
||||||
|
<CommandItem
|
||||||
|
key={item.value}
|
||||||
|
value={item.value}
|
||||||
|
onSelect={currentValue => {
|
||||||
|
setValue(currentValue === value ? '' : currentValue);
|
||||||
|
setOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Check
|
||||||
|
className={cn(
|
||||||
|
'mr-2 h-4 w-4',
|
||||||
|
value === item.value ? 'opacity-100' : 'opacity-0'
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
{item.label}
|
||||||
|
</CommandItem>
|
||||||
|
))}
|
||||||
|
</CommandGroup>
|
||||||
|
</CommandList>
|
||||||
|
</Command>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
);
|
||||||
|
}
|
||||||
3
platform/ui-next/src/components/Combobox/index.ts
Normal file
3
platform/ui-next/src/components/Combobox/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { Combobox } from './Combobox';
|
||||||
|
|
||||||
|
export default Combobox;
|
||||||
150
platform/ui-next/src/components/Command/Command.tsx
Normal file
150
platform/ui-next/src/components/Command/Command.tsx
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { type DialogProps } from '@radix-ui/react-dialog';
|
||||||
|
import { MagnifyingGlassIcon } from '@radix-ui/react-icons';
|
||||||
|
import { Command as CommandPrimitive } from 'cmdk';
|
||||||
|
|
||||||
|
import { cn } from '../../lib/utils';
|
||||||
|
import { Dialog, DialogContent } from '../Dialog/Dialog';
|
||||||
|
|
||||||
|
const Command = React.forwardRef<
|
||||||
|
React.ElementRef<typeof CommandPrimitive>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof CommandPrimitive>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<CommandPrimitive
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
'bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
Command.displayName = CommandPrimitive.displayName;
|
||||||
|
|
||||||
|
interface CommandDialogProps extends DialogProps {}
|
||||||
|
|
||||||
|
const CommandDialog = ({ children, ...props }: CommandDialogProps) => {
|
||||||
|
return (
|
||||||
|
<Dialog {...props}>
|
||||||
|
<DialogContent className="overflow-hidden p-0">
|
||||||
|
<Command className="[&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
|
||||||
|
{children}
|
||||||
|
</Command>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const CommandInput = React.forwardRef<
|
||||||
|
React.ElementRef<typeof CommandPrimitive.Input>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<div
|
||||||
|
className="flex items-center border-b px-3"
|
||||||
|
cmdk-input-wrapper=""
|
||||||
|
>
|
||||||
|
<MagnifyingGlassIcon className="mr-2 h-4 w-4 shrink-0 opacity-50" />
|
||||||
|
<CommandPrimitive.Input
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
'placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none disabled:cursor-not-allowed disabled:opacity-50',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
));
|
||||||
|
|
||||||
|
CommandInput.displayName = CommandPrimitive.Input.displayName;
|
||||||
|
|
||||||
|
const CommandList = React.forwardRef<
|
||||||
|
React.ElementRef<typeof CommandPrimitive.List>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<CommandPrimitive.List
|
||||||
|
ref={ref}
|
||||||
|
className={cn('max-h-[300px] overflow-y-auto overflow-x-hidden', className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
|
||||||
|
CommandList.displayName = CommandPrimitive.List.displayName;
|
||||||
|
|
||||||
|
const CommandEmpty = React.forwardRef<
|
||||||
|
React.ElementRef<typeof CommandPrimitive.Empty>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
|
||||||
|
>((props, ref) => (
|
||||||
|
<CommandPrimitive.Empty
|
||||||
|
ref={ref}
|
||||||
|
className="py-6 text-center text-sm"
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
|
||||||
|
CommandEmpty.displayName = CommandPrimitive.Empty.displayName;
|
||||||
|
|
||||||
|
const CommandGroup = React.forwardRef<
|
||||||
|
React.ElementRef<typeof CommandPrimitive.Group>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<CommandPrimitive.Group
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
'text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
|
||||||
|
CommandGroup.displayName = CommandPrimitive.Group.displayName;
|
||||||
|
|
||||||
|
const CommandSeparator = React.forwardRef<
|
||||||
|
React.ElementRef<typeof CommandPrimitive.Separator>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<CommandPrimitive.Separator
|
||||||
|
ref={ref}
|
||||||
|
className={cn('bg-border -mx-1 h-px', className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
CommandSeparator.displayName = CommandPrimitive.Separator.displayName;
|
||||||
|
|
||||||
|
const CommandItem = React.forwardRef<
|
||||||
|
React.ElementRef<typeof CommandPrimitive.Item>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<CommandPrimitive.Item
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
'aria-selected:bg-accent aria-selected:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
|
||||||
|
CommandItem.displayName = CommandPrimitive.Item.displayName;
|
||||||
|
|
||||||
|
const CommandShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
className={cn('text-muted-foreground ml-auto text-xs tracking-widest', className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
CommandShortcut.displayName = 'CommandShortcut';
|
||||||
|
|
||||||
|
export {
|
||||||
|
Command,
|
||||||
|
CommandDialog,
|
||||||
|
CommandInput,
|
||||||
|
CommandList,
|
||||||
|
CommandEmpty,
|
||||||
|
CommandGroup,
|
||||||
|
CommandItem,
|
||||||
|
CommandShortcut,
|
||||||
|
CommandSeparator,
|
||||||
|
};
|
||||||
3
platform/ui-next/src/components/Command/index.ts
Normal file
3
platform/ui-next/src/components/Command/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import * as CommandComponents from './Command';
|
||||||
|
|
||||||
|
export default CommandComponents;
|
||||||
153
platform/ui-next/src/components/DateRange/DateRange.tsx
Normal file
153
platform/ui-next/src/components/DateRange/DateRange.tsx
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { format, parse, isValid } from 'date-fns';
|
||||||
|
import { Calendar as CalendarIcon } from 'lucide-react';
|
||||||
|
import { cn } from '../../lib/utils';
|
||||||
|
import Calendar from '../Calendar';
|
||||||
|
import Popover from '../Popover';
|
||||||
|
|
||||||
|
export type DatePickerWithRangeProps = {
|
||||||
|
id: string;
|
||||||
|
/** YYYYMMDD (19921022) */
|
||||||
|
startDate: string;
|
||||||
|
/** YYYYMMDD (19921022) */
|
||||||
|
endDate: string;
|
||||||
|
/** Callback that received { startDate: string(YYYYMMDD), endDate: string(YYYYMMDD)} */
|
||||||
|
onChange: (value: { startDate: string; endDate: string }) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function DatePickerWithRange({
|
||||||
|
className,
|
||||||
|
id,
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
onChange,
|
||||||
|
...props
|
||||||
|
}: React.HTMLAttributes<HTMLDivElement> & DatePickerWithRangeProps) {
|
||||||
|
const [start, setStart] = React.useState<string>(
|
||||||
|
startDate ? format(parse(startDate, 'yyyyMMdd', new Date()), 'yyyy-MM-dd') : ''
|
||||||
|
);
|
||||||
|
const [end, setEnd] = React.useState<string>(
|
||||||
|
endDate ? format(parse(endDate, 'yyyyMMdd', new Date()), 'yyyy-MM-dd') : ''
|
||||||
|
);
|
||||||
|
const [openEnd, setOpenEnd] = React.useState(false);
|
||||||
|
|
||||||
|
const handleStartSelect = (selectedDate: Date | undefined) => {
|
||||||
|
if (selectedDate) {
|
||||||
|
const formattedDate = format(selectedDate, 'yyyy-MM-dd');
|
||||||
|
setStart(formattedDate);
|
||||||
|
setOpenEnd(true);
|
||||||
|
onChange({
|
||||||
|
startDate: format(selectedDate, 'yyyyMMdd'),
|
||||||
|
endDate: end.replace(/-/g, ''),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEndSelect = (selectedDate: Date | undefined) => {
|
||||||
|
if (selectedDate) {
|
||||||
|
const formattedDate = format(selectedDate, 'yyyy-MM-dd');
|
||||||
|
setEnd(formattedDate);
|
||||||
|
setOpenEnd(false);
|
||||||
|
onChange({
|
||||||
|
startDate: start.replace(/-/g, ''),
|
||||||
|
endDate: format(selectedDate, 'yyyyMMdd'),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>, type: 'start' | 'end') => {
|
||||||
|
const value = e.target.value;
|
||||||
|
const date = parse(value, 'yyyy-MM-dd', new Date());
|
||||||
|
if (type === 'start') {
|
||||||
|
setStart(value);
|
||||||
|
if (isValid(date)) {
|
||||||
|
handleStartSelect(date);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setEnd(value);
|
||||||
|
if (isValid(date)) {
|
||||||
|
handleEndSelect(date);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
setStart(startDate ? format(parse(startDate, 'yyyyMMdd', new Date()), 'yyyy-MM-dd') : '');
|
||||||
|
setEnd(endDate ? format(parse(endDate, 'yyyyMMdd', new Date()), 'yyyy-MM-dd') : '');
|
||||||
|
}, [startDate, endDate]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={cn('flex gap-2', className)}>
|
||||||
|
<Popover.Popover>
|
||||||
|
<Popover.PopoverTrigger asChild>
|
||||||
|
<div className="relative w-full">
|
||||||
|
<CalendarIcon className="absolute right-2 top-1/2 h-4 w-4 -translate-y-1/2 transform text-white" />
|
||||||
|
<input
|
||||||
|
id={`${id}-start`}
|
||||||
|
type="text"
|
||||||
|
placeholder="Start date"
|
||||||
|
autoComplete="off"
|
||||||
|
value={start}
|
||||||
|
onChange={e => handleInputChange(e, 'start')}
|
||||||
|
className={cn(
|
||||||
|
'border-inputfield-main focus:border-inputfield-focus h-full w-full justify-start rounded border bg-black py-[6.5px] pl-[6.5px] pr-[6.5px] text-left text-sm font-normal hover:bg-black hover:text-white',
|
||||||
|
!start && 'text-muted-foreground'
|
||||||
|
)}
|
||||||
|
data-cy="input-date-range-start"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Popover.PopoverTrigger>
|
||||||
|
<Popover.PopoverContent
|
||||||
|
className="w-auto p-0"
|
||||||
|
align="start"
|
||||||
|
>
|
||||||
|
<Calendar
|
||||||
|
initialFocus
|
||||||
|
mode="single"
|
||||||
|
defaultMonth={start ? parse(start, 'yyyy-MM-dd', new Date()) : new Date()}
|
||||||
|
selected={start ? parse(start, 'yyyy-MM-dd', new Date()) : undefined}
|
||||||
|
onSelect={handleStartSelect}
|
||||||
|
numberOfMonths={1}
|
||||||
|
/>
|
||||||
|
</Popover.PopoverContent>
|
||||||
|
</Popover.Popover>
|
||||||
|
|
||||||
|
<Popover.Popover
|
||||||
|
open={openEnd}
|
||||||
|
onOpenChange={setOpenEnd}
|
||||||
|
>
|
||||||
|
<Popover.PopoverTrigger asChild>
|
||||||
|
<div className="relative w-full">
|
||||||
|
<CalendarIcon className="absolute right-2 top-1/2 h-4 w-4 -translate-y-1/2 transform text-white" />
|
||||||
|
<input
|
||||||
|
id={`${id}-end`}
|
||||||
|
type="text"
|
||||||
|
placeholder="End date"
|
||||||
|
autoComplete="off"
|
||||||
|
value={end}
|
||||||
|
onChange={e => handleInputChange(e, 'end')}
|
||||||
|
className={cn(
|
||||||
|
'border-inputfield-main focus:border-inputfield-focus h-full w-full justify-start rounded border bg-black py-[6.5px] pl-[6.5px] pr-[6.5px] text-left text-sm font-normal hover:bg-black hover:text-white',
|
||||||
|
!end && 'text-muted-foreground'
|
||||||
|
)}
|
||||||
|
data-cy="input-date-range-end"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Popover.PopoverTrigger>
|
||||||
|
<Popover.PopoverContent
|
||||||
|
className="w-auto p-0"
|
||||||
|
align="start"
|
||||||
|
>
|
||||||
|
<Calendar
|
||||||
|
initialFocus
|
||||||
|
mode="single"
|
||||||
|
defaultMonth={start ? parse(start, 'yyyy-MM-dd', new Date()) : new Date()}
|
||||||
|
selected={end ? parse(end, 'yyyy-MM-dd', new Date()) : undefined}
|
||||||
|
onSelect={handleEndSelect}
|
||||||
|
numberOfMonths={1}
|
||||||
|
/>
|
||||||
|
</Popover.PopoverContent>
|
||||||
|
</Popover.Popover>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
3
platform/ui-next/src/components/DateRange/index.ts
Normal file
3
platform/ui-next/src/components/DateRange/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { DatePickerWithRange } from "./DateRange";
|
||||||
|
|
||||||
|
export default DatePickerWithRange;
|
||||||
105
platform/ui-next/src/components/Dialog/Dialog.tsx
Normal file
105
platform/ui-next/src/components/Dialog/Dialog.tsx
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
||||||
|
import { Cross2Icon } from '@radix-ui/react-icons';
|
||||||
|
|
||||||
|
import { cn } from '../../lib/utils';
|
||||||
|
|
||||||
|
const Dialog = DialogPrimitive.Root;
|
||||||
|
|
||||||
|
const DialogTrigger = DialogPrimitive.Trigger;
|
||||||
|
|
||||||
|
const DialogPortal = DialogPrimitive.Portal;
|
||||||
|
|
||||||
|
const DialogClose = DialogPrimitive.Close;
|
||||||
|
|
||||||
|
const DialogOverlay = React.forwardRef<
|
||||||
|
React.ElementRef<typeof DialogPrimitive.Overlay>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<DialogPrimitive.Overlay
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
||||||
|
|
||||||
|
const DialogContent = React.forwardRef<
|
||||||
|
React.ElementRef<typeof DialogPrimitive.Content>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
|
||||||
|
>(({ className, children, ...props }, ref) => (
|
||||||
|
<DialogPortal>
|
||||||
|
<DialogOverlay />
|
||||||
|
<DialogPrimitive.Content
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
<DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none">
|
||||||
|
<Cross2Icon className="h-4 w-4" />
|
||||||
|
<span className="sr-only">Close</span>
|
||||||
|
</DialogPrimitive.Close>
|
||||||
|
</DialogPrimitive.Content>
|
||||||
|
</DialogPortal>
|
||||||
|
));
|
||||||
|
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
||||||
|
|
||||||
|
const DialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
||||||
|
<div
|
||||||
|
className={cn('flex flex-col space-y-1.5 text-center sm:text-left', className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
DialogHeader.displayName = 'DialogHeader';
|
||||||
|
|
||||||
|
const DialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
||||||
|
<div
|
||||||
|
className={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
DialogFooter.displayName = 'DialogFooter';
|
||||||
|
|
||||||
|
const DialogTitle = React.forwardRef<
|
||||||
|
React.ElementRef<typeof DialogPrimitive.Title>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<DialogPrimitive.Title
|
||||||
|
ref={ref}
|
||||||
|
className={cn('text-lg font-semibold leading-none tracking-tight', className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
||||||
|
|
||||||
|
const DialogDescription = React.forwardRef<
|
||||||
|
React.ElementRef<typeof DialogPrimitive.Description>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<DialogPrimitive.Description
|
||||||
|
ref={ref}
|
||||||
|
className={cn('text-muted-foreground text-sm', className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
||||||
|
|
||||||
|
export {
|
||||||
|
Dialog,
|
||||||
|
DialogPortal,
|
||||||
|
DialogOverlay,
|
||||||
|
DialogTrigger,
|
||||||
|
DialogClose,
|
||||||
|
DialogContent,
|
||||||
|
DialogHeader,
|
||||||
|
DialogFooter,
|
||||||
|
DialogTitle,
|
||||||
|
DialogDescription,
|
||||||
|
};
|
||||||
3
platform/ui-next/src/components/Dialog/index.ts
Normal file
3
platform/ui-next/src/components/Dialog/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import * as DialogComponents from './Dialog';
|
||||||
|
|
||||||
|
export default DialogComponents;
|
||||||
31
platform/ui-next/src/components/Popover/Popover.tsx
Normal file
31
platform/ui-next/src/components/Popover/Popover.tsx
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
||||||
|
|
||||||
|
import { cn } from '../../lib/utils';
|
||||||
|
|
||||||
|
const Popover = PopoverPrimitive.Root;
|
||||||
|
|
||||||
|
const PopoverTrigger = PopoverPrimitive.Trigger;
|
||||||
|
|
||||||
|
const PopoverAnchor = PopoverPrimitive.Anchor;
|
||||||
|
|
||||||
|
const PopoverContent = React.forwardRef<
|
||||||
|
React.ElementRef<typeof PopoverPrimitive.Content>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
|
||||||
|
>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (
|
||||||
|
<PopoverPrimitive.Portal>
|
||||||
|
<PopoverPrimitive.Content
|
||||||
|
ref={ref}
|
||||||
|
align={align}
|
||||||
|
sideOffset={sideOffset}
|
||||||
|
className={cn(
|
||||||
|
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 rounded-md border p-4 shadow-md outline-none',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</PopoverPrimitive.Portal>
|
||||||
|
));
|
||||||
|
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
|
||||||
|
|
||||||
|
export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor };
|
||||||
3
platform/ui-next/src/components/Popover/index.ts
Normal file
3
platform/ui-next/src/components/Popover/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import * as Popover from './Popover';
|
||||||
|
|
||||||
|
export default Popover;
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import '../../tailwind.css';
|
||||||
|
|
||||||
|
export const ThemeWrapper = ({ children }) => <React.Fragment>{children}</React.Fragment>;
|
||||||
1
platform/ui-next/src/components/ThemeWrapper/index.ts
Normal file
1
platform/ui-next/src/components/ThemeWrapper/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { ThemeWrapper } from './ThemeWrapper';
|
||||||
10
platform/ui-next/src/components/index.ts
Normal file
10
platform/ui-next/src/components/index.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { Button, buttonVariants } from './Button';
|
||||||
|
import { ThemeWrapper } from './ThemeWrapper';
|
||||||
|
import Command from './Command';
|
||||||
|
import Dialog from './Dialog';
|
||||||
|
import Combobox from './Combobox';
|
||||||
|
import Popover from './Popover';
|
||||||
|
import Calendar from './Calendar';
|
||||||
|
import DatePickerWithRange from './DateRange';
|
||||||
|
|
||||||
|
export { Button, buttonVariants, ThemeWrapper, Command, Dialog, Combobox, Popover, Calendar, DatePickerWithRange};
|
||||||
@ -0,0 +1,85 @@
|
|||||||
|
import React, { useState, createContext, useContext, useCallback, useEffect } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { Toaster, toast } from 'sonner';
|
||||||
|
|
||||||
|
const NotificationContext = createContext(null);
|
||||||
|
|
||||||
|
export const useNotification = () => useContext(NotificationContext);
|
||||||
|
|
||||||
|
const NotificationProvider = ({ children, service }) => {
|
||||||
|
const DEFAULT_OPTIONS = {
|
||||||
|
title: '',
|
||||||
|
message: '',
|
||||||
|
duration: 5000,
|
||||||
|
position: 'bottom-right', // Aligning to Sonner's positioning system
|
||||||
|
type: 'info', // info, success, error
|
||||||
|
};
|
||||||
|
|
||||||
|
const [notificationItems, setNotificationItems] = useState([]);
|
||||||
|
|
||||||
|
const show = useCallback(options => {
|
||||||
|
const { title, message, duration, position, type } = { ...DEFAULT_OPTIONS, ...options };
|
||||||
|
const id = toast[type](message, {
|
||||||
|
duration,
|
||||||
|
position,
|
||||||
|
render: () => (
|
||||||
|
<div>
|
||||||
|
<strong>{title}</strong>
|
||||||
|
<p>{message}</p>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
setNotificationItems(state => [...state, { id, ...options }]);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const hide = useCallback(id => {
|
||||||
|
toast.dismiss(id);
|
||||||
|
setNotificationItems(state => state.filter(item => item.id !== id));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const hideAll = useCallback(() => {
|
||||||
|
toast.dismiss();
|
||||||
|
setNotificationItems([]);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
window.notification = { show, hide, hideAll };
|
||||||
|
}, [show, hide, hideAll]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the implementation of a notification service that can be used by extensions.
|
||||||
|
*
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
useEffect(() => {
|
||||||
|
if (service) {
|
||||||
|
service.setServiceImplementation({ hide, show });
|
||||||
|
}
|
||||||
|
}, [service, hide, show]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NotificationContext.Provider value={{ show, hide, hideAll, notificationItems }}>
|
||||||
|
<Toaster position="bottom-right" />
|
||||||
|
{children}
|
||||||
|
</NotificationContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
NotificationProvider.propTypes = {
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const withNotification = Component => {
|
||||||
|
return function WrappedComponent(props) {
|
||||||
|
const notificationContext = useNotification();
|
||||||
|
return (
|
||||||
|
<Component
|
||||||
|
{...props}
|
||||||
|
notificationContext={notificationContext}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default NotificationProvider;
|
||||||
3
platform/ui-next/src/contextProviders/index.ts
Normal file
3
platform/ui-next/src/contextProviders/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import NotificationProvider, { useNotification } from './NotificationProvider';
|
||||||
|
|
||||||
|
export { useNotification, NotificationProvider };
|
||||||
28
platform/ui-next/src/index.ts
Normal file
28
platform/ui-next/src/index.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Button,
|
||||||
|
buttonVariants,
|
||||||
|
ThemeWrapper,
|
||||||
|
Dialog,
|
||||||
|
Command,
|
||||||
|
Popover,
|
||||||
|
Combobox,
|
||||||
|
Calendar,
|
||||||
|
DatePickerWithRange,
|
||||||
|
} from './components';
|
||||||
|
import { useNotification, NotificationProvider } from './contextProviders';
|
||||||
|
|
||||||
|
export {
|
||||||
|
// components
|
||||||
|
Button,
|
||||||
|
Dialog,
|
||||||
|
Command,
|
||||||
|
Popover,
|
||||||
|
Combobox,
|
||||||
|
buttonVariants,
|
||||||
|
ThemeWrapper,
|
||||||
|
Calendar,
|
||||||
|
DatePickerWithRange,
|
||||||
|
// contextProviders
|
||||||
|
NotificationProvider,
|
||||||
|
useNotification,
|
||||||
|
};
|
||||||
6
platform/ui-next/src/lib/utils.ts
Normal file
6
platform/ui-next/src/lib/utils.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { type ClassValue, clsx } from 'clsx';
|
||||||
|
import { twMerge } from 'tailwind-merge';
|
||||||
|
|
||||||
|
export function cn(...inputs: ClassValue[]) {
|
||||||
|
return twMerge(clsx(inputs));
|
||||||
|
}
|
||||||
67
platform/ui-next/src/tailwind.css
Normal file
67
platform/ui-next/src/tailwind.css
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
:root {
|
||||||
|
--background: 0 0% 100%;
|
||||||
|
--foreground: 222.2 84% 4.9%;
|
||||||
|
|
||||||
|
--card: 0 0% 100%;
|
||||||
|
--card-foreground: 222.2 84% 4.9%;
|
||||||
|
|
||||||
|
--popover: 0 0% 100%;
|
||||||
|
--popover-foreground: 222.2 84% 4.9%;
|
||||||
|
|
||||||
|
--primary: 222.2 47.4% 11.2%;
|
||||||
|
--primary-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--secondary: 210 40% 96.1%;
|
||||||
|
--secondary-foreground: 222.2 47.4% 11.2%;
|
||||||
|
|
||||||
|
--muted: 210 40% 96.1%;
|
||||||
|
--muted-foreground: 215.4 16.3% 46.9%;
|
||||||
|
|
||||||
|
--accent: 210 40% 96.1%;
|
||||||
|
--accent-foreground: 222.2 47.4% 11.2%;
|
||||||
|
|
||||||
|
--destructive: 0 84.2% 60.2%;
|
||||||
|
--destructive-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--border: 214.3 31.8% 91.4%;
|
||||||
|
--input: 214.3 31.8% 91.4%;
|
||||||
|
--ring: 222.2 84% 4.9%;
|
||||||
|
|
||||||
|
--radius: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
--background: 222.2 84% 4.9%;
|
||||||
|
--foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--card: 222.2 84% 4.9%;
|
||||||
|
--card-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--popover: 222.2 84% 4.9%;
|
||||||
|
--popover-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--primary: 210 40% 98%;
|
||||||
|
--primary-foreground: 222.2 47.4% 11.2%;
|
||||||
|
|
||||||
|
--secondary: 217.2 32.6% 17.5%;
|
||||||
|
--secondary-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--muted: 217.2 32.6% 17.5%;
|
||||||
|
--muted-foreground: 215 20.2% 65.1%;
|
||||||
|
|
||||||
|
--accent: 217.2 32.6% 17.5%;
|
||||||
|
--accent-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--destructive: 0 62.8% 30.6%;
|
||||||
|
--destructive-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--border: 217.2 32.6% 17.5%;
|
||||||
|
--input: 217.2 32.6% 17.5%;
|
||||||
|
--ring: 212.7 26.8% 83.9%;
|
||||||
|
}
|
||||||
|
}
|
||||||
70
platform/ui-next/tailwind.config.js
Normal file
70
platform/ui-next/tailwind.config.js
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
presets: [require('../ui/tailwind.config.js')],
|
||||||
|
content: [
|
||||||
|
'./pages/**/*.{ts,tsx}',
|
||||||
|
'./components/**/*.{ts,tsx}',
|
||||||
|
'./app/**/*.{ts,tsx}',
|
||||||
|
'./src/**/*.{ts,tsx}',
|
||||||
|
],
|
||||||
|
prefix: '',
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
border: 'hsl(var(--border))',
|
||||||
|
input: 'hsl(var(--input))',
|
||||||
|
ring: 'hsl(var(--ring))',
|
||||||
|
background: 'hsl(var(--background))',
|
||||||
|
foreground: 'hsl(var(--foreground))',
|
||||||
|
primary: {
|
||||||
|
DEFAULT: 'hsl(var(--primary))',
|
||||||
|
foreground: 'hsl(var(--primary-foreground))',
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
DEFAULT: 'hsl(var(--secondary))',
|
||||||
|
foreground: 'hsl(var(--secondary-foreground))',
|
||||||
|
},
|
||||||
|
destructive: {
|
||||||
|
DEFAULT: 'hsl(var(--destructive))',
|
||||||
|
foreground: 'hsl(var(--destructive-foreground))',
|
||||||
|
},
|
||||||
|
muted: {
|
||||||
|
DEFAULT: 'hsl(var(--muted))',
|
||||||
|
foreground: 'hsl(var(--muted-foreground))',
|
||||||
|
},
|
||||||
|
accent: {
|
||||||
|
DEFAULT: 'hsl(var(--accent))',
|
||||||
|
foreground: 'hsl(var(--accent-foreground))',
|
||||||
|
},
|
||||||
|
popover: {
|
||||||
|
DEFAULT: 'hsl(var(--popover))',
|
||||||
|
foreground: 'hsl(var(--popover-foreground))',
|
||||||
|
},
|
||||||
|
card: {
|
||||||
|
DEFAULT: 'hsl(var(--card))',
|
||||||
|
foreground: 'hsl(var(--card-foreground))',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
borderRadius: {
|
||||||
|
lg: 'var(--radius)',
|
||||||
|
md: 'calc(var(--radius) - 2px)',
|
||||||
|
sm: 'calc(var(--radius) - 4px)',
|
||||||
|
},
|
||||||
|
keyframes: {
|
||||||
|
'accordion-down': {
|
||||||
|
from: { height: '0' },
|
||||||
|
to: { height: 'var(--radix-accordion-content-height)' },
|
||||||
|
},
|
||||||
|
'accordion-up': {
|
||||||
|
from: { height: 'var(--radix-accordion-content-height)' },
|
||||||
|
to: { height: '0' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
animation: {
|
||||||
|
'accordion-down': 'accordion-down 0.2s ease-out',
|
||||||
|
'accordion-up': 'accordion-up 0.2s ease-out',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [require('tailwindcss-animate')],
|
||||||
|
};
|
||||||
11
platform/ui-next/tsconfig.json
Normal file
11
platform/ui-next/tsconfig.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@ui/*": ["./src/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
||||||
@ -29,8 +29,8 @@
|
|||||||
"build-storybook": "storybook build"
|
"build-storybook": "storybook build"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "17.0.2",
|
"react": "^18.3.1",
|
||||||
"react-dom": "17.0.2"
|
"react-dom": "^18.3.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@testing-library/react-hooks": "^3.2.1",
|
"@testing-library/react-hooks": "^3.2.1",
|
||||||
@ -46,11 +46,11 @@
|
|||||||
"lodash.debounce": "4.0.8",
|
"lodash.debounce": "4.0.8",
|
||||||
"moment": "2.29.4",
|
"moment": "2.29.4",
|
||||||
"mousetrap": "^1.6.5",
|
"mousetrap": "^1.6.5",
|
||||||
"react": "^17.0.2",
|
"react": "^18.3.1",
|
||||||
"react-dates": "^21.8.0",
|
"react-dates": "^21.8.0",
|
||||||
"react-dnd": "14.0.2",
|
"react-dnd": "14.0.2",
|
||||||
"react-dnd-html5-backend": "14.0.0",
|
"react-dnd-html5-backend": "14.0.0",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^18.3.1",
|
||||||
"react-draggable": "4.4.3",
|
"react-draggable": "4.4.3",
|
||||||
"react-error-boundary": "^3.1.3",
|
"react-error-boundary": "^3.1.3",
|
||||||
"react-modal": "3.11.2",
|
"react-modal": "3.11.2",
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
|||||||
|
|
||||||
import { Button, ButtonEnums } from '../../components';
|
import { Button, ButtonEnums } from '../../components';
|
||||||
|
|
||||||
function ActionButtons({ actions, disabled, t }) {
|
function ActionButtons({ actions, disabled = false, t }) {
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{actions.map((action, index) => (
|
{actions.map((action, index) => (
|
||||||
@ -33,8 +33,4 @@ ActionButtons.propTypes = {
|
|||||||
disabled: PropTypes.bool,
|
disabled: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
ActionButtons.defaultProps = {
|
|
||||||
disabled: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ActionButtons;
|
export default ActionButtons;
|
||||||
|
|||||||
@ -58,7 +58,7 @@ const defaults = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Button = ({
|
const Button = ({
|
||||||
children,
|
children = '',
|
||||||
size = defaults.size,
|
size = defaults.size,
|
||||||
disabled = defaults.disabled,
|
disabled = defaults.disabled,
|
||||||
type = defaults.type,
|
type = defaults.type,
|
||||||
@ -66,7 +66,7 @@ const Button = ({
|
|||||||
endIcon: endIconProp,
|
endIcon: endIconProp,
|
||||||
name,
|
name,
|
||||||
className,
|
className,
|
||||||
onClick,
|
onClick = () => {},
|
||||||
dataCY,
|
dataCY,
|
||||||
startIconTooltip = null,
|
startIconTooltip = null,
|
||||||
endIconTooltip = null,
|
endIconTooltip = null,
|
||||||
@ -121,14 +121,6 @@ const Button = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Button.defaultProps = {
|
|
||||||
disabled: false,
|
|
||||||
children: '',
|
|
||||||
onClick: () => {},
|
|
||||||
type: defaults.type,
|
|
||||||
size: defaults.size,
|
|
||||||
};
|
|
||||||
|
|
||||||
Button.propTypes = {
|
Button.propTypes = {
|
||||||
/** What is inside the button, can be text or react component */
|
/** What is inside the button, can be text or react component */
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
|
|||||||
@ -31,15 +31,15 @@ const fpsButtonClassNames =
|
|||||||
|
|
||||||
const CinePlayer: React.FC<CinePlayerProps> = ({
|
const CinePlayer: React.FC<CinePlayerProps> = ({
|
||||||
className,
|
className,
|
||||||
isPlaying,
|
isPlaying = false,
|
||||||
minFrameRate,
|
minFrameRate = 1,
|
||||||
maxFrameRate,
|
maxFrameRate = 90,
|
||||||
stepFrameRate,
|
stepFrameRate = 1,
|
||||||
frameRate: defaultFrameRate,
|
frameRate: defaultFrameRate = 24,
|
||||||
|
onFrameRateChange = () => {},
|
||||||
|
onPlayPauseChange = () => {},
|
||||||
|
onClose = () => {},
|
||||||
dynamicInfo = {},
|
dynamicInfo = {},
|
||||||
onFrameRateChange,
|
|
||||||
onPlayPauseChange,
|
|
||||||
onClose,
|
|
||||||
updateDynamicInfo,
|
updateDynamicInfo,
|
||||||
}) => {
|
}) => {
|
||||||
const isDynamic = !!dynamicInfo?.numTimePoints;
|
const isDynamic = !!dynamicInfo?.numTimePoints;
|
||||||
@ -163,21 +163,6 @@ const CinePlayer: React.FC<CinePlayerProps> = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const noop = () => {};
|
|
||||||
|
|
||||||
CinePlayer.defaultProps = {
|
|
||||||
isPlaying: false,
|
|
||||||
minFrameRate: 1,
|
|
||||||
maxFrameRate: 90,
|
|
||||||
stepFrameRate: 1,
|
|
||||||
frameRate: 24,
|
|
||||||
onPlayPauseChange: noop,
|
|
||||||
onFrameRateChange: noop,
|
|
||||||
onClose: noop,
|
|
||||||
isDynamic: false,
|
|
||||||
dynamicInfo: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
CinePlayer.propTypes = {
|
CinePlayer.propTypes = {
|
||||||
/** Minimum value for range slider */
|
/** Minimum value for range slider */
|
||||||
minFrameRate: PropTypes.number,
|
minFrameRate: PropTypes.number,
|
||||||
|
|||||||
@ -29,7 +29,7 @@ const renderYearsOptions = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const DateRange = props => {
|
const DateRange = props => {
|
||||||
const { id, onChange, startDate, endDate } = props;
|
const { id = '', onChange, startDate = null, endDate = null } = props;
|
||||||
const [focusedInput, setFocusedInput] = useState(null);
|
const [focusedInput, setFocusedInput] = useState(null);
|
||||||
const renderYearsOptionsCallback = useCallback(renderYearsOptions, []);
|
const renderYearsOptionsCallback = useCallback(renderYearsOptions, []);
|
||||||
const { t } = useTranslation('DatePicker');
|
const { t } = useTranslation('DatePicker');
|
||||||
@ -165,12 +165,6 @@ const DateRange = props => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
DateRange.defaultProps = {
|
|
||||||
id: '',
|
|
||||||
startDate: null,
|
|
||||||
endDate: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
DateRange.propTypes = {
|
DateRange.propTypes = {
|
||||||
id: PropTypes.string,
|
id: PropTypes.string,
|
||||||
/** YYYYMMDD (19921022) */
|
/** YYYYMMDD (19921022) */
|
||||||
|
|||||||
@ -15,10 +15,10 @@ const Dialog = ({
|
|||||||
actions,
|
actions,
|
||||||
onShow,
|
onShow,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
header: HeaderComponent,
|
header: HeaderComponent = Header,
|
||||||
body: BodyComponent,
|
body: BodyComponent = Body,
|
||||||
footer: FooterComponent,
|
footer: FooterComponent = Footer,
|
||||||
value: defaultValue,
|
value: defaultValue = {},
|
||||||
}) => {
|
}) => {
|
||||||
const [value, setValue] = useState(defaultValue);
|
const [value, setValue] = useState(defaultValue);
|
||||||
|
|
||||||
@ -78,13 +78,7 @@ Dialog.propTypes = {
|
|||||||
type: PropTypes.oneOf(['primary', 'secondary', 'cancel']).isRequired,
|
type: PropTypes.oneOf(['primary', 'secondary', 'cancel']).isRequired,
|
||||||
})
|
})
|
||||||
).isRequired,
|
).isRequired,
|
||||||
};
|
onShow: PropTypes.func,
|
||||||
|
|
||||||
Dialog.defaultProps = {
|
|
||||||
header: Header,
|
|
||||||
footer: Footer,
|
|
||||||
body: Body,
|
|
||||||
value: {},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Dialog;
|
export default Dialog;
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
|
|||||||
|
|
||||||
import Button, { ButtonEnums } from '../Button';
|
import Button, { ButtonEnums } from '../Button';
|
||||||
|
|
||||||
const Footer = ({ actions, className, onSubmit, value }) => {
|
const Footer = ({ actions = [], className, onSubmit = () => {}, value }) => {
|
||||||
const flex = 'flex items-center justify-end';
|
const flex = 'flex items-center justify-end';
|
||||||
const padding = 'pt-[20px]';
|
const padding = 'pt-[20px]';
|
||||||
|
|
||||||
@ -47,9 +47,4 @@ Footer.propTypes = {
|
|||||||
).isRequired,
|
).isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
Footer.defaultProps = {
|
|
||||||
onSubmit: noop,
|
|
||||||
actions: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Footer;
|
export default Footer;
|
||||||
|
|||||||
@ -20,7 +20,7 @@ CloseButton.propTypes = {
|
|||||||
onClick: PropTypes.func,
|
onClick: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
const Header = ({ title, noCloseButton, onClose }) => {
|
const Header = ({ title, noCloseButton = false, onClose }) => {
|
||||||
const theme = 'bg-primary-dark';
|
const theme = 'bg-primary-dark';
|
||||||
const flex = 'flex items-center justify-between';
|
const flex = 'flex items-center justify-between';
|
||||||
const padding = 'pb-[20px]';
|
const padding = 'pb-[20px]';
|
||||||
@ -46,8 +46,4 @@ Header.propTypes = {
|
|||||||
onClose: PropTypes.func,
|
onClose: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
Header.defaultProps = {
|
|
||||||
noCloseButton: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Header;
|
export default Header;
|
||||||
|
|||||||
@ -11,15 +11,15 @@ const borderStyle = 'border-b last:border-b-0 border-secondary-main';
|
|||||||
const Dropdown = ({
|
const Dropdown = ({
|
||||||
id,
|
id,
|
||||||
children,
|
children,
|
||||||
showDropdownIcon,
|
showDropdownIcon = true,
|
||||||
list,
|
list,
|
||||||
itemsClassName,
|
itemsClassName,
|
||||||
titleClassName,
|
titleClassName,
|
||||||
showBorders,
|
showBorders = true,
|
||||||
alignment,
|
alignment,
|
||||||
// By default the max characters per line is the longest title
|
// By default the max characters per line is the longest title
|
||||||
// if you wish to override this, you can pass in a number
|
// if you wish to override this, you can pass in a number
|
||||||
maxCharactersPerLine,
|
maxCharactersPerLine = 20,
|
||||||
}) => {
|
}) => {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const elementRef = useRef(null);
|
const elementRef = useRef(null);
|
||||||
@ -199,11 +199,6 @@ const Dropdown = ({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
Dropdown.defaultProps = {
|
|
||||||
showDropdownIcon: true,
|
|
||||||
maxCharactersPerLine: 20,
|
|
||||||
showBorders: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
Dropdown.propTypes = {
|
Dropdown.propTypes = {
|
||||||
id: PropTypes.string,
|
id: PropTypes.string,
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import Icon from '../Icon';
|
|||||||
import Typography from '../Typography';
|
import Typography from '../Typography';
|
||||||
|
|
||||||
// TODO: Add loading spinner to OHIF + use it here.
|
// TODO: Add loading spinner to OHIF + use it here.
|
||||||
const EmptyStudies = ({ className }) => {
|
const EmptyStudies = ({ className = '' }) => {
|
||||||
const { t } = useTranslation('StudyList');
|
const { t } = useTranslation('StudyList');
|
||||||
return (
|
return (
|
||||||
<div className={classnames('inline-flex flex-col items-center', className)}>
|
<div className={classnames('inline-flex flex-col items-center', className)}>
|
||||||
@ -25,10 +25,6 @@ const EmptyStudies = ({ className }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
EmptyStudies.defaultProps = {
|
|
||||||
className: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
EmptyStudies.propTypes = {
|
EmptyStudies.propTypes = {
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import IconButton from '../IconButton';
|
|||||||
|
|
||||||
const isProduction = process.env.NODE_ENV === 'production';
|
const isProduction = process.env.NODE_ENV === 'production';
|
||||||
|
|
||||||
const DefaultFallback = ({ error, context, resetErrorBoundary, fallbackRoute }) => {
|
const DefaultFallback = ({ error, context, resetErrorBoundary = () => {}, fallbackRoute }) => {
|
||||||
const { t } = useTranslation('ErrorBoundary');
|
const { t } = useTranslation('ErrorBoundary');
|
||||||
const [showDetails, setShowDetails] = useState(false);
|
const [showDetails, setShowDetails] = useState(false);
|
||||||
const title = `${t('Something went wrong')}${!isProduction && ` ${t('in')} ${context}`}.`;
|
const title = `${t('Something went wrong')}${!isProduction && ` ${t('in')} ${context}`}.`;
|
||||||
@ -57,25 +57,19 @@ const DefaultFallback = ({ error, context, resetErrorBoundary, fallbackRoute })
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const noop = () => {};
|
|
||||||
|
|
||||||
DefaultFallback.propTypes = {
|
DefaultFallback.propTypes = {
|
||||||
error: PropTypes.object.isRequired,
|
error: PropTypes.object.isRequired,
|
||||||
resetErrorBoundary: PropTypes.func,
|
resetErrorBoundary: PropTypes.func,
|
||||||
componentStack: PropTypes.string,
|
componentStack: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
DefaultFallback.defaultProps = {
|
|
||||||
resetErrorBoundary: noop,
|
|
||||||
};
|
|
||||||
|
|
||||||
const ErrorBoundary = ({
|
const ErrorBoundary = ({
|
||||||
context,
|
context = 'OHIF',
|
||||||
onReset,
|
onReset = () => {},
|
||||||
onError,
|
onError = () => {},
|
||||||
fallbackComponent: FallbackComponent,
|
fallbackComponent: FallbackComponent = DefaultFallback,
|
||||||
children,
|
children,
|
||||||
fallbackRoute,
|
fallbackRoute = null,
|
||||||
isPage,
|
isPage,
|
||||||
}) => {
|
}) => {
|
||||||
const [isOpen, setIsOpen] = useState(true);
|
const [isOpen, setIsOpen] = useState(true);
|
||||||
@ -132,12 +126,4 @@ ErrorBoundary.propTypes = {
|
|||||||
fallbackRoute: PropTypes.string,
|
fallbackRoute: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
ErrorBoundary.defaultProps = {
|
|
||||||
context: 'OHIF',
|
|
||||||
onReset: noop,
|
|
||||||
onError: noop,
|
|
||||||
fallbackComponent: DefaultFallback,
|
|
||||||
fallbackRoute: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ErrorBoundary;
|
export default ErrorBoundary;
|
||||||
|
|||||||
@ -8,14 +8,14 @@ import Icon from '../Icon';
|
|||||||
import './ExpandableToolbarButton.css';
|
import './ExpandableToolbarButton.css';
|
||||||
|
|
||||||
const ExpandableToolbarButton = ({
|
const ExpandableToolbarButton = ({
|
||||||
type,
|
type = 'primary',
|
||||||
id,
|
id = '',
|
||||||
isActive,
|
isActive = false,
|
||||||
onClick,
|
onClick = () => {},
|
||||||
icon,
|
icon = 'clipboard',
|
||||||
className,
|
className,
|
||||||
content: Content,
|
content: Content = null,
|
||||||
contentProps,
|
contentProps = {},
|
||||||
}) => {
|
}) => {
|
||||||
const classes = {
|
const classes = {
|
||||||
type: {
|
type: {
|
||||||
@ -71,15 +71,6 @@ const ExpandableToolbarButton = ({
|
|||||||
|
|
||||||
const noop = () => {};
|
const noop = () => {};
|
||||||
|
|
||||||
ExpandableToolbarButton.defaultProps = {
|
|
||||||
id: '',
|
|
||||||
icon: 'clipboard',
|
|
||||||
isActive: false,
|
|
||||||
type: 'primary',
|
|
||||||
content: null,
|
|
||||||
onClick: noop,
|
|
||||||
};
|
|
||||||
|
|
||||||
ExpandableToolbarButton.propTypes = {
|
ExpandableToolbarButton.propTypes = {
|
||||||
/* Influences background/hover styling */
|
/* Influences background/hover styling */
|
||||||
type: PropTypes.oneOf(['primary', 'secondary']),
|
type: PropTypes.oneOf(['primary', 'secondary']),
|
||||||
|
|||||||
@ -14,9 +14,9 @@ import { PatientInfoVisibility } from '../../types/PatientInfoVisibility';
|
|||||||
function Header({
|
function Header({
|
||||||
children,
|
children,
|
||||||
menuOptions,
|
menuOptions,
|
||||||
isReturnEnabled,
|
isReturnEnabled = true,
|
||||||
onClickReturnButton,
|
onClickReturnButton,
|
||||||
isSticky,
|
isSticky = false,
|
||||||
WhiteLabeling,
|
WhiteLabeling,
|
||||||
showPatientInfo = PatientInfoVisibility.VISIBLE_COLLAPSED,
|
showPatientInfo = PatientInfoVisibility.VISIBLE_COLLAPSED,
|
||||||
servicesManager,
|
servicesManager,
|
||||||
@ -113,9 +113,4 @@ Header.propTypes = {
|
|||||||
servicesManager: PropTypes.object,
|
servicesManager: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
Header.defaultProps = {
|
|
||||||
isReturnEnabled: true,
|
|
||||||
isSticky: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Header;
|
export default Header;
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import { getKeys, formatKeysForInput } from './utils';
|
|||||||
* @param {string} props.className input classes
|
* @param {string} props.className input classes
|
||||||
* @param {Array[]} props.modifierKeys
|
* @param {Array[]} props.modifierKeys
|
||||||
*/
|
*/
|
||||||
const HotkeyField = ({ disabled, keys, onChange, className, modifierKeys, hotkeys }) => {
|
const HotkeyField = ({ disabled = false, keys, onChange, className, modifierKeys, hotkeys }) => {
|
||||||
const inputValue = formatKeysForInput(keys);
|
const inputValue = formatKeysForInput(keys);
|
||||||
|
|
||||||
const onInputKeyDown = event => {
|
const onInputKeyDown = event => {
|
||||||
@ -58,8 +58,4 @@ HotkeyField.propTypes = {
|
|||||||
}).isRequired,
|
}).isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
HotkeyField.defaultProps = {
|
|
||||||
disabled: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default HotkeyField;
|
export default HotkeyField;
|
||||||
|
|||||||
@ -11,10 +11,10 @@ import { MODIFIER_KEYS } from './hotkeysConfig';
|
|||||||
import { validate, splitHotkeyDefinitionsAndCreateTuples } from './utils';
|
import { validate, splitHotkeyDefinitionsAndCreateTuples } from './utils';
|
||||||
|
|
||||||
const HotkeysPreferences = ({
|
const HotkeysPreferences = ({
|
||||||
disabled,
|
disabled = false,
|
||||||
hotkeyDefinitions,
|
hotkeyDefinitions,
|
||||||
errors: controlledErrors,
|
errors: controlledErrors,
|
||||||
onChange,
|
onChange = () => {},
|
||||||
hotkeysModule,
|
hotkeysModule,
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation('UserPreferencesModal');
|
const { t } = useTranslation('UserPreferencesModal');
|
||||||
@ -127,8 +127,6 @@ const HotkeysPreferences = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const noop = () => {};
|
|
||||||
|
|
||||||
HotkeysPreferences.propTypes = {
|
HotkeysPreferences.propTypes = {
|
||||||
onChange: PropTypes.func,
|
onChange: PropTypes.func,
|
||||||
disabled: PropTypes.bool,
|
disabled: PropTypes.bool,
|
||||||
@ -142,9 +140,4 @@ HotkeysPreferences.propTypes = {
|
|||||||
}).isRequired,
|
}).isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
HotkeysPreferences.defaultProps = {
|
|
||||||
onChange: noop,
|
|
||||||
disabled: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default HotkeysPreferences;
|
export default HotkeysPreferences;
|
||||||
|
|||||||
@ -1,179 +1,179 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
// Icons
|
|
||||||
|
|
||||||
import arrowDown from './../../assets/icons/arrow-down.svg';
|
import { ReactComponent as arrowDown } from './../../assets/icons/arrow-down.svg';
|
||||||
import arrowLeft from './../../assets/icons/arrow-left.svg';
|
import { ReactComponent as arrowLeft } from './../../assets/icons/arrow-left.svg';
|
||||||
import arrowRight from './../../assets/icons/arrow-right.svg';
|
import { ReactComponent as arrowRight } from './../../assets/icons/arrow-right.svg';
|
||||||
import arrowLeftSmall from './../../assets/icons/arrow-left-small.svg';
|
import { ReactComponent as arrowLeftSmall } from './../../assets/icons/arrow-left-small.svg';
|
||||||
import arrowRightSmall from './../../assets/icons/arrow-right-small.svg';
|
import { ReactComponent as arrowRightSmall } from './../../assets/icons/arrow-right-small.svg';
|
||||||
import calendar from './../../assets/icons/calendar.svg';
|
import { ReactComponent as calendar } from './../../assets/icons/calendar.svg';
|
||||||
import cancel from './../../assets/icons/cancel.svg';
|
import { ReactComponent as cancel } from './../../assets/icons/cancel.svg';
|
||||||
import clipboard from './../../assets/icons/clipboard.svg';
|
import { ReactComponent as clipboard } from './../../assets/icons/clipboard.svg';
|
||||||
import close from './../../assets/icons/closeIcon.svg';
|
import { ReactComponent as close } from './../../assets/icons/closeIcon.svg';
|
||||||
import dottedCircle from './../../assets/icons/dotted-circle.svg';
|
import { ReactComponent as dottedCircle } from './../../assets/icons/dotted-circle.svg';
|
||||||
import circledCheckmark from './../../assets/icons/circled-checkmark.svg';
|
import { ReactComponent as circledCheckmark } from './../../assets/icons/circled-checkmark.svg';
|
||||||
import chevronDown from './../../assets/icons/chevron-down.svg';
|
import { ReactComponent as chevronDown } from './../../assets/icons/chevron-down.svg';
|
||||||
import chevronLeft from './../../assets/icons/chevron-left.svg';
|
import { ReactComponent as chevronLeft } from './../../assets/icons/chevron-left.svg';
|
||||||
import chevronMenu from './../../assets/icons/chevron-menu.svg';
|
import { ReactComponent as chevronMenu } from './../../assets/icons/chevron-menu.svg';
|
||||||
import chevronNext from './../../assets/icons/chevron-next.svg';
|
import { ReactComponent as chevronNext } from './../../assets/icons/chevron-next.svg';
|
||||||
import chevronPrev from './../../assets/icons/chevron-prev.svg';
|
import { ReactComponent as chevronPrev } from './../../assets/icons/chevron-prev.svg';
|
||||||
import chevronRight from './../../assets/icons/chevron-right.svg';
|
import { ReactComponent as chevronRight } from './../../assets/icons/chevron-right.svg';
|
||||||
import contentNext from './../../assets/icons/content-next.svg';
|
import { ReactComponent as contentNext } from './../../assets/icons/content-next.svg';
|
||||||
import contentPrev from './../../assets/icons/content-prev.svg';
|
import { ReactComponent as contentPrev } from './../../assets/icons/content-prev.svg';
|
||||||
import eyeVisible from './../../assets/icons/eye-visible.svg';
|
import { ReactComponent as eyeVisible } from './../../assets/icons/eye-visible.svg';
|
||||||
import eyeHidden from './../../assets/icons/eye-hidden.svg';
|
import { ReactComponent as eyeHidden } from './../../assets/icons/eye-hidden.svg';
|
||||||
import exclamation from './../../assets/icons/exclamation.svg';
|
import { ReactComponent as exclamation } from './../../assets/icons/exclamation.svg';
|
||||||
import externalLink from './../../assets/icons/external-link.svg';
|
import { ReactComponent as externalLink } from './../../assets/icons/external-link.svg';
|
||||||
import groupLayers from './../../assets/icons/group-layers.svg';
|
import { ReactComponent as groupLayers } from './../../assets/icons/group-layers.svg';
|
||||||
import info from './../../assets/icons/info.svg';
|
import { ReactComponent as info } from './../../assets/icons/info.svg';
|
||||||
import infoAction from './../../assets/icons/info-action.svg';
|
import { ReactComponent as infoAction } from './../../assets/icons/info-action.svg';
|
||||||
import infoLink from './../../assets/icons/info-link.svg';
|
import { ReactComponent as infoLink } from './../../assets/icons/info-link.svg';
|
||||||
import launchArrow from './../../assets/icons/launch-arrow.svg';
|
import { ReactComponent as launchArrow } from './../../assets/icons/launch-arrow.svg';
|
||||||
import launchInfo from './../../assets/icons/launch-info.svg';
|
import { ReactComponent as launchInfo } from './../../assets/icons/launch-info.svg';
|
||||||
import link from './../../assets/icons/tool-stack-image-sync.svg';
|
import { ReactComponent as link } from './../../assets/icons/tool-stack-image-sync.svg';
|
||||||
import listBullets from './../../assets/icons/list-bullets.svg';
|
import { ReactComponent as listBullets } from './../../assets/icons/list-bullets.svg';
|
||||||
import lock from './../../assets/icons/lock.svg';
|
import { ReactComponent as lock } from './../../assets/icons/lock.svg';
|
||||||
import logoOhifSmall from './../../assets/icons/logo-ohif-small.svg';
|
import { ReactComponent as logoOhifSmall } from './../../assets/icons/logo-ohif-small.svg';
|
||||||
import logoDarkBackGround from './../../assets/icons/ohif-logo-color-darkbg.svg';
|
import { ReactComponent as logoDarkBackGround } from './../../assets/icons/ohif-logo-color-darkbg.svg';
|
||||||
import magnifier from './../../assets/icons/magnifier.svg';
|
import { ReactComponent as magnifier } from './../../assets/icons/magnifier.svg';
|
||||||
import notificationwarningDiamond from './../../assets/icons/notificationwarning-diamond.svg';
|
import { ReactComponent as notificationwarningDiamond } from './../../assets/icons/notificationwarning-diamond.svg';
|
||||||
import pencil from './../../assets/icons/pencil.svg';
|
import { ReactComponent as pencil } from './../../assets/icons/pencil.svg';
|
||||||
import powerOff from './../../assets/icons/power-off.svg';
|
import { ReactComponent as powerOff } from './../../assets/icons/power-off.svg';
|
||||||
import profile from './../../assets/icons/profile.svg';
|
import { ReactComponent as profile } from './../../assets/icons/profile.svg';
|
||||||
import pushLeft from './../../assets/icons/push-left.svg';
|
import { ReactComponent as pushLeft } from './../../assets/icons/push-left.svg';
|
||||||
import pushRight from './../../assets/icons/push-right.svg';
|
import { ReactComponent as pushRight } from './../../assets/icons/push-right.svg';
|
||||||
import settings from './../../assets/icons/settings.svg';
|
import { ReactComponent as settings } from './../../assets/icons/settings.svg';
|
||||||
import sidePanelCloseLeft from './../../assets/icons/side-panel-close-left.svg';
|
import { ReactComponent as sidePanelCloseLeft } from './../../assets/icons/side-panel-close-left.svg';
|
||||||
import sidePanelCloseRight from './../../assets/icons/side-panel-close-right.svg';
|
import { ReactComponent as sidePanelCloseRight } from './../../assets/icons/side-panel-close-right.svg';
|
||||||
import sorting from './../../assets/icons/sorting.svg';
|
import { ReactComponent as sorting } from './../../assets/icons/sorting.svg';
|
||||||
import sortingActiveDown from './../../assets/icons/sorting-active-down.svg';
|
import { ReactComponent as sortingActiveDown } from './../../assets/icons/sorting-active-down.svg';
|
||||||
import sortingActiveUp from './../../assets/icons/sorting-active-up.svg';
|
import { ReactComponent as sortingActiveUp } from './../../assets/icons/sorting-active-up.svg';
|
||||||
import statusAlertWarning from './../../assets/icons/status-alert-warning.svg';
|
import { ReactComponent as statusAlertWarning } from './../../assets/icons/status-alert-warning.svg';
|
||||||
import statusAlert from './../../assets/icons/status-alert.svg';
|
import { ReactComponent as statusAlert } from './../../assets/icons/status-alert.svg';
|
||||||
import statusLocked from './../../assets/icons/status-locked.svg';
|
import { ReactComponent as statusLocked } from './../../assets/icons/status-locked.svg';
|
||||||
import statusTracked from './../../assets/icons/status-tracked.svg';
|
import { ReactComponent as statusTracked } from './../../assets/icons/status-tracked.svg';
|
||||||
import statusUntracked from './../../assets/icons/status-untracked.svg';
|
import { ReactComponent as statusUntracked } from './../../assets/icons/status-untracked.svg';
|
||||||
import tracked from './../../assets/icons/tracked.svg';
|
import { ReactComponent as tracked } from './../../assets/icons/tracked.svg';
|
||||||
import unlink from './../../assets/icons/unlink.svg';
|
import { ReactComponent as unlink } from './../../assets/icons/unlink.svg';
|
||||||
import checkboxChecked from './../../assets/icons/checkbox-checked.svg';
|
import { ReactComponent as checkboxChecked } from './../../assets/icons/checkbox-checked.svg';
|
||||||
import checkboxUnchecked from './../../assets/icons/checkbox-unchecked.svg';
|
import { ReactComponent as checkboxUnchecked } from './../../assets/icons/checkbox-unchecked.svg';
|
||||||
import iconAlertOutline from './../../assets/icons/icons-alert-outline.svg';
|
import { ReactComponent as iconAlertOutline } from './../../assets/icons/icons-alert-outline.svg';
|
||||||
import iconAlertSmall from './../../assets/icons/icon-alert-small.svg';
|
import { ReactComponent as iconAlertSmall } from './../../assets/icons/icon-alert-small.svg';
|
||||||
import iconClose from './../../assets/icons/icon-close.svg';
|
import { ReactComponent as iconClose } from './../../assets/icons/icon-close.svg';
|
||||||
import iconClearField from './../../assets/icons/icon-clear-field.svg';
|
import { ReactComponent as iconClearField } from './../../assets/icons/icon-clear-field.svg';
|
||||||
import iconNextInactive from './../../assets/icons/icon-next-inactive.svg';
|
import { ReactComponent as iconNextInactive } from './../../assets/icons/icon-next-inactive.svg';
|
||||||
import iconNext from './../../assets/icons/icon-next.svg';
|
import { ReactComponent as iconNext } from './../../assets/icons/icon-next.svg';
|
||||||
import iconPlay from './../../assets/icons/icon-play.svg';
|
import { ReactComponent as iconPlay } from './../../assets/icons/icon-play.svg';
|
||||||
import iconPause from './../../assets/icons/icon-pause.svg';
|
import { ReactComponent as iconPause } from './../../assets/icons/icon-pause.svg';
|
||||||
import iconPrevInactive from './../../assets/icons/icon-prev-inactive.svg';
|
import { ReactComponent as iconPrevInactive } from './../../assets/icons/icon-prev-inactive.svg';
|
||||||
import iconPrev from './../../assets/icons/icon-prev.svg';
|
import { ReactComponent as iconPrev } from './../../assets/icons/icon-prev.svg';
|
||||||
import iconSearch from './../../assets/icons/icon-search.svg';
|
import { ReactComponent as iconSearch } from './../../assets/icons/icon-search.svg';
|
||||||
import iconStatusAlert from './../../assets/icons/icon-status-alert.svg';
|
import { ReactComponent as iconStatusAlert } from './../../assets/icons/icon-status-alert.svg';
|
||||||
import iconTransferring from './../../assets/icons/icon-transferring.svg';
|
import { ReactComponent as iconTransferring } from './../../assets/icons/icon-transferring.svg';
|
||||||
import iconUpload from './../../assets/icons/icon-upload.svg';
|
import { ReactComponent as iconUpload } from './../../assets/icons/icon-upload.svg';
|
||||||
import navigationPanelRightHide from './../../assets/icons/navigation-panel-right-hide.svg';
|
import { ReactComponent as navigationPanelRightHide } from './../../assets/icons/navigation-panel-right-hide.svg';
|
||||||
import navigationPanelRightReveal from './../../assets/icons/navigation-panel-right-reveal.svg';
|
import { ReactComponent as navigationPanelRightReveal } from './../../assets/icons/navigation-panel-right-reveal.svg';
|
||||||
import tabLinear from './../../assets/icons/tab-linear.svg';
|
import { ReactComponent as tabLinear } from './../../assets/icons/tab-linear.svg';
|
||||||
import tabPatientInfo from './../../assets/icons/tab-patient-info.svg';
|
import { ReactComponent as tabPatientInfo } from './../../assets/icons/tab-patient-info.svg';
|
||||||
import tabROIThreshold from './../../assets/icons/tab-roi-threshold.svg';
|
import { ReactComponent as tabROIThreshold } from './../../assets/icons/tab-roi-threshold.svg';
|
||||||
import tabSegmentation from './../../assets/icons/tab-segmentation.svg';
|
import { ReactComponent as tabSegmentation } from './../../assets/icons/tab-segmentation.svg';
|
||||||
import tabStudies from './../../assets/icons/tab-studies.svg';
|
import { ReactComponent as tabStudies } from './../../assets/icons/tab-studies.svg';
|
||||||
import uiArrowDown from './../../assets/icons/ui-arrow-down.svg';
|
import { ReactComponent as uiArrowDown } from './../../assets/icons/ui-arrow-down.svg';
|
||||||
import uiArrowUp from './../../assets/icons/ui-arrow-up.svg';
|
import { ReactComponent as uiArrowUp } from './../../assets/icons/ui-arrow-up.svg';
|
||||||
import uiArrowLeft from './../../assets/icons/ui-arrow-left.svg';
|
import { ReactComponent as uiArrowLeft } from './../../assets/icons/ui-arrow-left.svg';
|
||||||
import uiArrowRight from './../../assets/icons/ui-arrow-right.svg';
|
import { ReactComponent as uiArrowRight } from './../../assets/icons/ui-arrow-right.svg';
|
||||||
import loadingOHIFMark from './../../assets/icons/loading-ohif-mark.svg';
|
import { ReactComponent as loadingOHIFMark } from './../../assets/icons/loading-ohif-mark.svg';
|
||||||
import notificationsInfo from './../../assets/icons/notifications-info.svg';
|
import { ReactComponent as notificationsInfo } from './../../assets/icons/notifications-info.svg';
|
||||||
import notificationsWarning from './../../assets/icons/notifications-warning.svg';
|
import { ReactComponent as notificationsWarning } from './../../assets/icons/notifications-warning.svg';
|
||||||
import notificationsError from './../../assets/icons/notifications-error.svg';
|
import { ReactComponent as notificationsError } from './../../assets/icons/notifications-error.svg';
|
||||||
import notificationsSuccess from './../../assets/icons/notifications-success.svg';
|
import { ReactComponent as notificationsSuccess } from './../../assets/icons/notifications-success.svg';
|
||||||
import nextArrow from './../../assets/icons/next-arrow.svg';
|
import { ReactComponent as nextArrow } from './../../assets/icons/next-arrow.svg';
|
||||||
import prevArrow from './../../assets/icons/prev-arrow.svg';
|
import { ReactComponent as prevArrow } from './../../assets/icons/prev-arrow.svg';
|
||||||
import viewportStatusTracked from './../../assets/icons/viewport-status-tracked.svg';
|
import { ReactComponent as viewportStatusTracked } from './../../assets/icons/viewport-status-tracked.svg';
|
||||||
|
import { ReactComponent as toggleDicomOverlay } from './../../assets/icons/tool-toggle-dicom-overlay.svg';
|
||||||
|
import { ReactComponent as toolZoom } from './../../assets/icons/tool-zoom.svg';
|
||||||
|
import { ReactComponent as toolCapture } from './../../assets/icons/tool-capture.svg';
|
||||||
|
import { ReactComponent as toolLayout } from './../../assets/icons/tool-layout-default.svg';
|
||||||
|
import { ReactComponent as toolMore } from './../../assets/icons/tool-more-menu.svg';
|
||||||
|
import { ReactComponent as toolMove } from './../../assets/icons/tool-move.svg';
|
||||||
|
import { ReactComponent as toolWindow } from './../../assets/icons/tool-window-level.svg';
|
||||||
|
import { ReactComponent as toolAnnotate } from './../../assets/icons/tool-annotate.svg';
|
||||||
|
import { ReactComponent as toolBidirectional } from './../../assets/icons/tool-bidirectional.svg';
|
||||||
|
import { ReactComponent as toolElipse } from './../../assets/icons/tool-measure-elipse.svg';
|
||||||
|
import { ReactComponent as toolCircle } from './../../assets/icons/tool-circle.svg';
|
||||||
|
import { ReactComponent as toolLength } from './../../assets/icons/tool-length.svg';
|
||||||
|
import { ReactComponent as toolStackScroll } from './../../assets/icons/tool-stack-scroll.svg';
|
||||||
|
import { ReactComponent as toolMagnify } from './../../assets/icons/tool-quick-magnify.svg';
|
||||||
|
import { ReactComponent as toolFlipHorizontal } from './../../assets/icons/tool-flip-horizontal.svg';
|
||||||
|
import { ReactComponent as toolInvert } from './../../assets/icons/tool-invert.svg';
|
||||||
|
import { ReactComponent as toolRotateRight } from './../../assets/icons/tool-rotate-right.svg';
|
||||||
|
import { ReactComponent as toolCine } from './../../assets/icons/tool-cine.svg';
|
||||||
|
import { ReactComponent as toolCrosshair } from './../../assets/icons/tool-crosshair.svg';
|
||||||
|
import { ReactComponent as toolProbe } from './../../assets/icons/focus-frame-target.svg';
|
||||||
|
import { ReactComponent as toolAngle } from './../../assets/icons/tool-angle.svg';
|
||||||
|
import { ReactComponent as toolReset } from './../../assets/icons/tool-reset.svg';
|
||||||
|
import { ReactComponent as toolRectangle } from './../../assets/icons/tool-rectangle.svg';
|
||||||
|
import { ReactComponent as toolFusionColor } from './../../assets/icons/tool-fusion-color.svg';
|
||||||
|
import { ReactComponent as toolCreateThreshold } from './../../assets/icons/tool-create-threshold.svg';
|
||||||
|
import { ReactComponent as toolCalibration } from './../../assets/icons/tool-calibrate.svg';
|
||||||
|
import { ReactComponent as toolFreehand } from './../../assets/icons/tool-freehand.svg';
|
||||||
|
import { ReactComponent as toolFreehandPolygon } from './../../assets/icons/tool-freehand-polygon.svg';
|
||||||
|
import { ReactComponent as toolPolygon } from './../../assets/icons/tool-polygon.svg';
|
||||||
|
import { ReactComponent as editPatient } from './../../assets/icons/edit-patient.svg';
|
||||||
|
import { ReactComponent as panelGroupMore } from './../../assets/icons/panel-group-more.svg';
|
||||||
|
import { ReactComponent as panelGroupOpenClose } from './../../assets/icons/panel-group-open-close.svg';
|
||||||
|
import { ReactComponent as rowAdd } from './../../assets/icons/row-add.svg';
|
||||||
|
import { ReactComponent as rowEdit } from './../../assets/icons/row-edit.svg';
|
||||||
|
import { ReactComponent as rowHidden } from './../../assets/icons/row-hidden.svg';
|
||||||
|
import { ReactComponent as rowShown } from './../../assets/icons/row-shown.svg';
|
||||||
|
import { ReactComponent as rowLock } from './../../assets/icons/row-lock.svg';
|
||||||
|
import { ReactComponent as rowUnlock } from './../../assets/icons/row-unlock.svg';
|
||||||
|
import { ReactComponent as iconMPR } from './../../assets/icons/icon-mpr-alt.svg';
|
||||||
|
import { ReactComponent as checkboxDefault } from './../../assets/icons/checkbox-default.svg';
|
||||||
|
import { ReactComponent as checkboxActive } from './../../assets/icons/checkbox-active.svg';
|
||||||
|
import { ReactComponent as referenceLines } from './../../assets/icons/tool-reference-lines.svg';
|
||||||
|
import { ReactComponent as chevronDownNew } from './../../assets/icons/icon-disclosure-close.svg';
|
||||||
|
import { ReactComponent as chevronLeftNew } from './../../assets/icons/icon-disclosure-open.svg';
|
||||||
|
import { ReactComponent as settingsBars } from './../../assets/icons/icon-display-settings.svg';
|
||||||
|
import { ReactComponent as iconAdd } from './../../assets/icons/icon-add.svg';
|
||||||
|
import { ReactComponent as iconRename } from './../../assets/icons/icon-rename.svg';
|
||||||
|
import { ReactComponent as iconDelete } from './../../assets/icons/icon-delete.svg';
|
||||||
|
import { ReactComponent as iconMoreMenu } from './../../assets/icons/icon-more-menu.svg';
|
||||||
|
import { ReactComponent as iconToolBrush } from './../../assets/icons/tool-seg-brush.svg';
|
||||||
|
import { ReactComponent as iconToolEraser } from './../../assets/icons/tool-seg-eraser.svg';
|
||||||
|
import { ReactComponent as iconToolScissor } from './../../assets/icons/icon-tool-scissor.svg';
|
||||||
|
import { ReactComponent as iconToolShape } from './../../assets/icons/tool-seg-shape.svg';
|
||||||
|
import { ReactComponent as iconToolThreshold } from './../../assets/icons/tool-seg-threshold.svg';
|
||||||
|
import { ReactComponent as viewportWindowLevel } from './../../assets/icons/viewport-window-level.svg';
|
||||||
|
import { ReactComponent as dicomTagBrowser } from './../../assets/icons/tool-dicom-tag-browser.svg';
|
||||||
|
import { ReactComponent as iconToolFreehandRoi } from './../../assets/icons/tool-freehand-roi.svg';
|
||||||
|
import { ReactComponent as iconToolLivewire } from './../../assets/icons/tool-magnetic-roi.svg';
|
||||||
|
import { ReactComponent as iconToolSplineRoi } from './../../assets/icons/tool-spline-roi.svg';
|
||||||
|
import { ReactComponent as iconToolUltrasoundBidirectional } from './../../assets/icons/tool-ultrasound-bidirectional.svg';
|
||||||
|
import { ReactComponent as iconToolLoupe } from './../../assets/icons/tool-magnify.svg';
|
||||||
|
import { ReactComponent as oldTrash } from './../../assets/icons/old-trash.svg';
|
||||||
|
import { ReactComponent as oldPlay } from './../../assets/icons/old-play.svg';
|
||||||
|
import { ReactComponent as oldStop } from './../../assets/icons/old-stop.svg';
|
||||||
|
import { ReactComponent as iconColorLUT } from './../../assets/icons/icon-color-lut.svg';
|
||||||
|
import { ReactComponent as iconChevronPatient } from './../../assets/icons/icon-chevron-patient.svg';
|
||||||
|
import { ReactComponent as iconPatient } from './../../assets/icons/icon-patient.svg';
|
||||||
|
import { ReactComponent as iconSettings } from './../../assets/icons/icon-settings.svg';
|
||||||
|
import { ReactComponent as iconToolbarBack } from './../../assets/icons/icon-toolbar-back.svg';
|
||||||
|
import { ReactComponent as iconMultiplePatients } from './../../assets/icons/icon-multiple-patients.svg';
|
||||||
|
import { ReactComponent as layoutAdvanced3DFourUp } from './../../assets/icons/layout-advanced-3d-four-up.svg';
|
||||||
|
import { ReactComponent as layoutAdvanced3DMain } from './../../assets/icons/layout-advanced-3d-main.svg';
|
||||||
|
import { ReactComponent as layoutAdvanced3DOnly } from './../../assets/icons/layout-advanced-3d-only.svg';
|
||||||
|
import { ReactComponent as layoutAdvanced3DPrimary } from './../../assets/icons/layout-advanced-3d-primary.svg';
|
||||||
|
import { ReactComponent as layoutAdvancedAxialPrimary } from './../../assets/icons/layout-advanced-axial-primary.svg';
|
||||||
|
import { ReactComponent as layoutAdvancedMPR } from './../../assets/icons/layout-advanced-mpr.svg';
|
||||||
|
import { ReactComponent as layoutCommon1x1 } from './../../assets/icons/layout-common-1x1.svg';
|
||||||
|
import { ReactComponent as layoutCommon1x2 } from './../../assets/icons/layout-common-1x2.svg';
|
||||||
|
import { ReactComponent as layoutCommon2x2 } from './../../assets/icons/layout-common-2x2.svg';
|
||||||
|
import { ReactComponent as layoutCommon2x3 } from './../../assets/icons/layout-common-2x3.svg';
|
||||||
|
import { ReactComponent as iconToolRotate } from './../../assets/icons/tool-3d-rotate.svg';
|
||||||
|
import { ReactComponent as tab4D } from './../../assets/icons/tab-4d.svg';
|
||||||
|
import { ReactComponent as investigationalUse } from './../../assets/icons/illustration-investigational-use.svg';
|
||||||
|
import { ReactComponent as actionNewDialog } from './../../assets/icons/action-new-dialog.svg';
|
||||||
|
|
||||||
/** Tools */
|
|
||||||
import toggleDicomOverlay from './../../assets/icons/tool-toggle-dicom-overlay.svg';
|
|
||||||
import toolZoom from './../../assets/icons/tool-zoom.svg';
|
|
||||||
import toolCapture from './../../assets/icons/tool-capture.svg';
|
|
||||||
import toolLayout from './../../assets/icons/tool-layout-default.svg';
|
|
||||||
import toolMore from './../../assets/icons/tool-more-menu.svg';
|
|
||||||
import toolMove from './../../assets/icons/tool-move.svg';
|
|
||||||
import toolWindow from './../../assets/icons/tool-window-level.svg';
|
|
||||||
import toolAnnotate from './../../assets/icons/tool-annotate.svg';
|
|
||||||
import toolBidirectional from './../../assets/icons/tool-bidirectional.svg';
|
|
||||||
import toolElipse from './../../assets/icons/tool-measure-elipse.svg';
|
|
||||||
import toolCircle from './../../assets/icons/tool-circle.svg';
|
|
||||||
import toolLength from './../../assets/icons/tool-length.svg';
|
|
||||||
import toolStackScroll from './../../assets/icons/tool-stack-scroll.svg';
|
|
||||||
import toolMagnify from './../../assets/icons/tool-quick-magnify.svg';
|
|
||||||
import toolFlipHorizontal from './../../assets/icons/tool-flip-horizontal.svg';
|
|
||||||
import toolInvert from './../../assets/icons/tool-invert.svg';
|
|
||||||
import toolRotateRight from './../../assets/icons/tool-rotate-right.svg';
|
|
||||||
import toolCine from './../../assets/icons/tool-cine.svg';
|
|
||||||
import toolCrosshair from './../../assets/icons/tool-crosshair.svg';
|
|
||||||
import toolProbe from './../../assets/icons/focus-frame-target.svg';
|
|
||||||
import toolAngle from './../../assets/icons/tool-angle.svg';
|
|
||||||
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-calibrate.svg';
|
|
||||||
import toolFreehand from './../../assets/icons/tool-freehand.svg';
|
|
||||||
import toolFreehandPolygon from './../../assets/icons/tool-freehand-polygon.svg';
|
|
||||||
import toolPolygon from './../../assets/icons/tool-polygon.svg';
|
|
||||||
import toolBrush from './../../assets/icons/tool-brush.svg';
|
|
||||||
import toolEraser from './../../assets/icons/tool-eraser.svg';
|
|
||||||
import toolScissorRect from './../../assets/icons/tool-scissor-rect.svg';
|
|
||||||
import toolScissorCircle from './../../assets/icons/tool-scissor-circle.svg';
|
|
||||||
import toolPaintFill from './../../assets/icons/tool-paint-fill.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';
|
|
||||||
import rowAdd from './../../assets/icons/row-add.svg';
|
|
||||||
import rowEdit from './../../assets/icons/row-edit.svg';
|
|
||||||
import rowHidden from './../../assets/icons/row-hidden.svg';
|
|
||||||
import rowShown from './../../assets/icons/row-shown.svg';
|
|
||||||
import rowLock from './../../assets/icons/row-lock.svg';
|
|
||||||
import rowUnlock from './../../assets/icons/row-unlock.svg';
|
|
||||||
import iconMPR from './../../assets/icons/icon-mpr-alt.svg';
|
|
||||||
import checkboxDefault from './../../assets/icons/checkbox-default.svg';
|
|
||||||
import checkboxActive from './../../assets/icons/checkbox-active.svg';
|
|
||||||
import referenceLines from './../../assets/icons/tool-reference-lines.svg';
|
|
||||||
import chevronDownNew from './../../assets/icons/icon-disclosure-close.svg';
|
|
||||||
import chevronLeftNew from './../../assets/icons/icon-disclosure-open.svg';
|
|
||||||
import settingsBars from './../../assets/icons/icon-display-settings.svg';
|
|
||||||
import iconAdd from './../../assets/icons/icon-add.svg';
|
|
||||||
import iconRename from './../../assets/icons/icon-rename.svg';
|
|
||||||
import iconDelete from './../../assets/icons/icon-delete.svg';
|
|
||||||
import iconMoreMenu from './../../assets/icons/icon-more-menu.svg';
|
|
||||||
import iconToolBrush from './../../assets/icons/tool-seg-brush.svg';
|
|
||||||
import iconToolEraser from './../../assets/icons/tool-seg-eraser.svg';
|
|
||||||
import iconToolScissor from './../../assets/icons/icon-tool-scissor.svg';
|
|
||||||
import iconToolShape from './../../assets/icons/tool-seg-shape.svg';
|
|
||||||
import iconToolThreshold from './../../assets/icons/tool-seg-threshold.svg';
|
|
||||||
import viewportWindowLevel from './../../assets/icons/viewport-window-level.svg';
|
|
||||||
import dicomTagBrowser from './../../assets/icons/tool-dicom-tag-browser.svg';
|
|
||||||
import iconToolFreehandRoi from './../../assets/icons/tool-freehand-roi.svg';
|
|
||||||
import iconToolLivewire from './../../assets/icons/tool-magnetic-roi.svg';
|
|
||||||
import iconToolSplineRoi from './../../assets/icons/tool-spline-roi.svg';
|
|
||||||
import iconToolUltrasoundBidirectional from './../../assets/icons/tool-ultrasound-bidirectional.svg';
|
|
||||||
import iconToolLoupe from './../../assets/icons/tool-magnify.svg';
|
|
||||||
/** Old OHIF */
|
|
||||||
import oldTrash from './../../assets/icons/old-trash.svg';
|
|
||||||
import oldPlay from './../../assets/icons/old-play.svg';
|
|
||||||
import oldStop from './../../assets/icons/old-stop.svg';
|
|
||||||
|
|
||||||
/** ColorLut */
|
|
||||||
import iconColorLUT from './../../assets/icons/icon-color-lut.svg';
|
|
||||||
|
|
||||||
/** New Patient Info Toolbar */
|
|
||||||
import iconChevronPatient from './../../assets/icons/icon-chevron-patient.svg';
|
|
||||||
import iconPatient from './../../assets/icons/icon-patient.svg';
|
|
||||||
import iconSettings from './../../assets/icons/icon-settings.svg';
|
|
||||||
import iconToolbarBack from './../../assets/icons/icon-toolbar-back.svg';
|
|
||||||
import iconMultiplePatients from './../../assets/icons/icon-multiple-patients.svg';
|
|
||||||
|
|
||||||
/** Volume Rendering */
|
|
||||||
import CTAAA from './../../assets/icons/CT-AAA.png';
|
import CTAAA from './../../assets/icons/CT-AAA.png';
|
||||||
import CTAAA2 from './../../assets/icons/CT-AAA2.png';
|
import CTAAA2 from './../../assets/icons/CT-AAA2.png';
|
||||||
import CTAir from './../../assets/icons/CT-Air.png';
|
import CTAir from './../../assets/icons/CT-Air.png';
|
||||||
@ -201,27 +201,6 @@ import MRDefault from './../../assets/icons/MR-Default.png';
|
|||||||
import MRMIP from './../../assets/icons/MR-MIP.png';
|
import MRMIP from './../../assets/icons/MR-MIP.png';
|
||||||
import MRT2Brain from './../../assets/icons/MR-T2-Brain.png';
|
import MRT2Brain from './../../assets/icons/MR-T2-Brain.png';
|
||||||
import VolumeRendering from './../../assets/icons/VolumeRendering.png';
|
import VolumeRendering from './../../assets/icons/VolumeRendering.png';
|
||||||
import actionNewDialog from './../../assets/icons/action-new-dialog.svg';
|
|
||||||
|
|
||||||
/** LAYOUT */
|
|
||||||
|
|
||||||
import layoutAdvanced3DFourUp from './../../assets/icons/layout-advanced-3d-four-up.svg';
|
|
||||||
import layoutAdvanced3DMain from './../../assets/icons/layout-advanced-3d-main.svg';
|
|
||||||
import layoutAdvanced3DOnly from './../../assets/icons/layout-advanced-3d-only.svg';
|
|
||||||
import layoutAdvanced3DPrimary from './../../assets/icons/layout-advanced-3d-primary.svg';
|
|
||||||
import layoutAdvancedAxialPrimary from './../../assets/icons/layout-advanced-axial-primary.svg';
|
|
||||||
import layoutAdvancedMPR from './../../assets/icons/layout-advanced-mpr.svg';
|
|
||||||
import layoutCommon1x1 from './../../assets/icons/layout-common-1x1.svg';
|
|
||||||
import layoutCommon1x2 from './../../assets/icons/layout-common-1x2.svg';
|
|
||||||
import layoutCommon2x2 from './../../assets/icons/layout-common-2x2.svg';
|
|
||||||
import layoutCommon2x3 from './../../assets/icons/layout-common-2x3.svg';
|
|
||||||
import iconToolRotate from './../../assets/icons/tool-3d-rotate.svg';
|
|
||||||
|
|
||||||
//
|
|
||||||
import tab4D from './../../assets/icons/tab-4d.svg';
|
|
||||||
|
|
||||||
/** New investigational use */
|
|
||||||
import investigationalUse from './../../assets/icons/illustration-investigational-use.svg';
|
|
||||||
|
|
||||||
const ICONS = {
|
const ICONS = {
|
||||||
'arrow-down': arrowDown,
|
'arrow-down': arrowDown,
|
||||||
|
|||||||
@ -74,14 +74,14 @@ const fullWidthClasses = {
|
|||||||
|
|
||||||
const IconButton = ({
|
const IconButton = ({
|
||||||
children,
|
children,
|
||||||
variant,
|
variant = 'contained',
|
||||||
color,
|
color = 'default',
|
||||||
size,
|
size = 'medium',
|
||||||
rounded,
|
rounded = 'medium',
|
||||||
disabled,
|
disabled = false,
|
||||||
type,
|
type = 'button',
|
||||||
fullWidth,
|
fullWidth = false,
|
||||||
onClick,
|
onClick = () => {},
|
||||||
className,
|
className,
|
||||||
id,
|
id,
|
||||||
...rest
|
...rest
|
||||||
@ -122,17 +122,6 @@ const IconButton = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
IconButton.defaultProps = {
|
|
||||||
onClick: () => {},
|
|
||||||
color: 'default',
|
|
||||||
disabled: false,
|
|
||||||
fullWidth: false,
|
|
||||||
rounded: 'medium',
|
|
||||||
size: 'medium',
|
|
||||||
type: 'button',
|
|
||||||
variant: 'contained',
|
|
||||||
};
|
|
||||||
|
|
||||||
IconButton.propTypes = {
|
IconButton.propTypes = {
|
||||||
children: PropTypes.node.isRequired,
|
children: PropTypes.node.isRequired,
|
||||||
size: PropTypes.oneOf(['small', 'medium', 'large', 'initial', 'toolbar', 'toolbox']),
|
size: PropTypes.oneOf(['small', 'medium', 'large', 'initial', 'toolbar', 'toolbox']),
|
||||||
|
|||||||
@ -20,10 +20,12 @@ class ImageScrollbar extends PureComponent {
|
|||||||
width: `${this.props.height}`,
|
width: `${this.props.height}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const { onContextMenu = e => e.preventDefault() } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="scroll"
|
className="scroll"
|
||||||
onContextMenu={this.props.onContextMenu}
|
onContextMenu={onContextMenu}
|
||||||
>
|
>
|
||||||
<div className="scroll-holder">
|
<div className="scroll-holder">
|
||||||
<input
|
<input
|
||||||
@ -70,8 +72,4 @@ class ImageScrollbar extends PureComponent {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageScrollbar.defaultProps = {
|
|
||||||
onContextMenu: e => e.preventDefault(),
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ImageScrollbar;
|
export default ImageScrollbar;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user