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:
1 parent
72b63dcd6a
commit
70f2c797f4
153 files changed
+2973
-2043
No files matched your search
@@ -28,6 +28,7 @@ export default defineConfig({
|
||||
defaultCommandTimeout: 10000,
|
||||
requestTimeout: 10000,
|
||||
responseTimeout: 10000,
|
||||
pageLoadTimeout: 10000,
|
||||
specPattern: 'cypress/integration/**/*.spec.[jt]s',
|
||||
projectId: '4oe38f',
|
||||
video: true,
|
||||
|
||||
@@ -78,8 +78,8 @@ describe('OHIF MPR', () => {
|
||||
const fOR = Object.keys(fORMap)[0];
|
||||
const fORAnnotation = fORMap[fOR];
|
||||
|
||||
// it should have crosshairs as the only key
|
||||
expect(Object.keys(fORAnnotation)).to.have.length(1);
|
||||
// it should have crosshairs as the only key (references lines make this 2)
|
||||
expect(Object.keys(fORAnnotation)).to.have.length(2);
|
||||
|
||||
const crosshairs = fORAnnotation.Crosshairs;
|
||||
|
||||
|
||||
@@ -61,8 +61,8 @@ export function initStudyListAliasesOnDesktop() {
|
||||
|
||||
// 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)
|
||||
cy.get('#date-range-studyDate-start-date').as('studyListStartDate');
|
||||
cy.get('#date-range-studyDate-end-date').as('studyListEndDate');
|
||||
cy.get('[data-cy="input-date-range-start"').as('studyListStartDate');
|
||||
cy.get('[data-cy="input-date-range-end"').as('studyListEndDate');
|
||||
cy.get('#input-modalities').as('modalities');
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,9 @@
|
||||
"@ohif/mode-microscopy": "3.9.0-beta.21",
|
||||
"@ohif/mode-test": "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",
|
||||
"core-js": "^3.16.1",
|
||||
"cornerstone-math": "^0.1.9",
|
||||
@@ -87,11 +89,11 @@
|
||||
"oidc-client": "1.11.5",
|
||||
"prop-types": "^15.7.2",
|
||||
"query-string": "^6.12.1",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-dropzone": "^10.1.7",
|
||||
"react-i18next": "^12.2.2",
|
||||
"react-resize-detector": "^9.1.0",
|
||||
"react-resize-detector": "^10.0.1",
|
||||
"react-router": "^6.8.1",
|
||||
"react-router-dom": "^6.8.1"
|
||||
},
|
||||
|
||||
+28
-22
@@ -1,4 +1,5 @@
|
||||
// External
|
||||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import i18n from '@ohif/i18n';
|
||||
@@ -23,6 +24,7 @@ import {
|
||||
UserAuthenticationProvider,
|
||||
ToolboxProvider,
|
||||
} from '@ohif/ui';
|
||||
import { ThemeWrapper as ThemeWrapperNext, NotificationProvider } from '@ohif/ui-next';
|
||||
// Viewer Project
|
||||
// TODO: Should this influence study list?
|
||||
import { AppConfigProvider } from '@state';
|
||||
@@ -36,7 +38,27 @@ let commandsManager: CommandsManager,
|
||||
serviceProvidersManager: ServiceProvidersManager,
|
||||
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);
|
||||
useEffect(() => {
|
||||
const run = async () => {
|
||||
@@ -83,11 +105,13 @@ function App({ config, defaultExtensions, defaultModes }) {
|
||||
[AppConfigProvider, { value: appConfigState }],
|
||||
[UserAuthenticationProvider, { service: userAuthenticationService }],
|
||||
[I18nextProvider, { i18n }],
|
||||
[ThemeWrapperNext],
|
||||
[ThemeWrapper],
|
||||
[ToolboxProvider],
|
||||
[ViewportGridProvider, { service: viewportGridService }],
|
||||
[ViewportDialogProvider, { service: uiViewportDialogService }],
|
||||
[CineProvider, { service: cineService }],
|
||||
// [NotificationProvider, { service: uiNotificationService }],
|
||||
[SnackbarProvider, { service: uiNotificationService }],
|
||||
[DialogProvider, { service: uiDialogService }],
|
||||
[ModalProvider, { service: uiModalService, modal: Modal }],
|
||||
@@ -153,27 +177,9 @@ App.propTypes = {
|
||||
/* Extensions that are "bundled" or "baked-in" to the application.
|
||||
* These would be provided at build time as part of they entry point. */
|
||||
defaultExtensions: PropTypes.array,
|
||||
};
|
||||
|
||||
App.defaultProps = {
|
||||
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: [],
|
||||
/* Modes that are "bundled" or "baked-in" to the application.
|
||||
* These would be provided at build time as part of they entry point. */
|
||||
defaultModes: PropTypes.array,
|
||||
};
|
||||
|
||||
export default App;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
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 { Types, MeasurementService } from '@ohif/core';
|
||||
import { ViewportGrid, ViewportPane, useViewportGrid } from '@ohif/ui';
|
||||
@@ -8,16 +8,22 @@ import classNames from 'classnames';
|
||||
import { useAppConfig } from '@state';
|
||||
|
||||
function ViewerViewportGrid(props: withAppTypes) {
|
||||
const { servicesManager, viewportComponents, dataSource } = props;
|
||||
const { servicesManager, viewportComponents = [], dataSource } = props;
|
||||
const [viewportGrid, viewportGridService] = useViewportGrid();
|
||||
const [appConfig] = useAppConfig();
|
||||
|
||||
const { layout, activeViewportId, viewports, isHangingProtocolLayout } = viewportGrid;
|
||||
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);
|
||||
|
||||
// TODO -> Need some way of selecting which displaySets hit the viewports.
|
||||
const { displaySetService, measurementService, hangingProtocolService, uiNotificationService } =
|
||||
servicesManager.services;
|
||||
|
||||
@@ -198,50 +204,6 @@ function ViewerViewportGrid(props: withAppTypes) {
|
||||
};
|
||||
}, [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 updatedViewports = _getUpdatedViewports(viewportId, displaySetInstanceUID);
|
||||
viewportGridService.setDisplaySetsForViewports(updatedViewports);
|
||||
@@ -363,21 +325,13 @@ function ViewerViewportGrid(props: withAppTypes) {
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={elementRef}
|
||||
ref={resizeRef}
|
||||
className="h-full w-full"
|
||||
>
|
||||
<ViewportGrid
|
||||
numRows={numRows}
|
||||
numCols={numCols}
|
||||
>
|
||||
<ReactResizeDetector
|
||||
refreshMode="debounce"
|
||||
refreshRate={7} // ms seems to be fine for 10 viewports
|
||||
onResize={() => {
|
||||
viewportGridService.setViewportGridSizeChanged();
|
||||
}}
|
||||
targetRef={elementRef.current}
|
||||
/>
|
||||
{getViewportPanes()}
|
||||
</ViewportGrid>
|
||||
</div>
|
||||
@@ -389,10 +343,6 @@ ViewerViewportGrid.propTypes = {
|
||||
servicesManager: PropTypes.instanceOf(Object).isRequired,
|
||||
};
|
||||
|
||||
ViewerViewportGrid.defaultProps = {
|
||||
viewportComponents: [],
|
||||
};
|
||||
|
||||
function _getViewportComponent(displaySets, viewportComponents, uiNotificationService) {
|
||||
if (!displaySets || !displaySets.length) {
|
||||
return EmptyViewport;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Entry point for development and production PWA builds.
|
||||
*/
|
||||
import 'regenerator-runtime/runtime';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import App from './App';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
@@ -35,10 +36,10 @@ loadDynamicConfig(window.config).then(config_json => {
|
||||
defaultModes,
|
||||
};
|
||||
|
||||
/** Create App */
|
||||
const app = React.createElement(App, appProps, null);
|
||||
/** Render */
|
||||
ReactDOM.render(app, document.getElementById('root'));
|
||||
const container = document.getElementById('root');
|
||||
|
||||
const root = createRoot(container);
|
||||
root.render(React.createElement(App, appProps));
|
||||
});
|
||||
|
||||
export { history };
|
||||
@@ -306,9 +306,11 @@ export default function ModeRoute({
|
||||
}
|
||||
// The unsubscriptions must occur before the extension onModeExit
|
||||
// in order to prevent exceptions during cleanup caused by spurious events
|
||||
unsubscriptions.forEach(unsub => {
|
||||
unsub();
|
||||
});
|
||||
if (unsubscriptions) {
|
||||
unsubscriptions.forEach(unsub => {
|
||||
unsub();
|
||||
});
|
||||
}
|
||||
// The extension manager must be called after the mode, this is
|
||||
// expected to cleanup the state to a standard setup.
|
||||
extensionManager.onModeExit();
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// Todo: we probably should add external installed extensions/modes here as well.
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
// Note: in Tailwind 3.0, JIT will purge unused styles by default
|
||||
// but in development, it is often useful to disable this to see
|
||||
@@ -7,6 +6,7 @@ module.exports = {
|
||||
// ...(process.env.NODE_ENV === 'development' && {
|
||||
// safelist: [{ pattern: /.*/ }],
|
||||
// }),
|
||||
presets: [require('../ui/tailwind.config.js'), require('../ui-next/tailwind.config.js')],
|
||||
content: [
|
||||
'./src/**/*.{jsx,js,ts,tsx, css}',
|
||||
'../../extensions/**/*.{jsx,js,ts,tsx, css}',
|
||||
@@ -14,256 +14,10 @@ module.exports = {
|
||||
'../../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-next/src/**/*.{js,jsx,ts,tsx,css}',
|
||||
'../../node_modules/@ohif/extension-*/src/**/*.{js,jsx,css, ts,tsx}',
|
||||
],
|
||||
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: {
|
||||
sans: [
|
||||
'Inter',
|
||||
@@ -296,500 +50,5 @@ module.exports = {
|
||||
'5xl': '3rem',
|
||||
'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: {
|
||||
|
||||
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)$/,
|
||||
loader: 'babel-loader',
|
||||
|
||||
@@ -1,21 +1,5 @@
|
||||
// https://babeljs.io/docs/en/options#babelrcroots
|
||||
const { extendDefaultPlugins } = require('svgo');
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
[
|
||||
'inline-react-svg',
|
||||
{
|
||||
svgo: {
|
||||
plugins: extendDefaultPlugins([
|
||||
{
|
||||
name: 'removeViewBox',
|
||||
active: false,
|
||||
},
|
||||
]),
|
||||
},
|
||||
},
|
||||
],
|
||||
['@babel/plugin-proposal-class-properties', { loose: true }],
|
||||
'@babel/plugin-transform-typescript',
|
||||
['@babel/plugin-proposal-private-property-in-object', { loose: true }],
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
"@ohif/extension-cornerstone": "^3.0.0",
|
||||
"@ohif/i18n": "^1.0.0",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-i18next": "^12.2.2",
|
||||
"react-router": "^6.8.1",
|
||||
"react-router-dom": "^6.8.1",
|
||||
@@ -47,7 +47,7 @@
|
||||
"@babel/plugin-proposal-private-property-in-object": "7.21.11",
|
||||
"babel-eslint": "9.x",
|
||||
"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",
|
||||
"clean-webpack-plugin": "^4.0.0",
|
||||
"copy-webpack-plugin": "^10.2.0",
|
||||
|
||||
@@ -49,6 +49,38 @@ const config = {
|
||||
],
|
||||
module: {
|
||||
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)$/,
|
||||
loader: 'babel-loader',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
module.exports = {
|
||||
plugins: ['inline-react-svg', '@babel/plugin-proposal-class-properties'],
|
||||
plugins: ['@babel/plugin-proposal-class-properties'],
|
||||
env: {
|
||||
test: {
|
||||
presets: [
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
"@babel/preset-typescript": "^7.13.0",
|
||||
"babel-eslint": "^8.0.3",
|
||||
"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",
|
||||
"copy-webpack-plugin": "^10.2.0",
|
||||
"cross-env": "^7.0.3",
|
||||
|
||||
@@ -47,8 +47,8 @@
|
||||
"url-loader": "^4.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2"
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
|
||||
@@ -33,8 +33,8 @@
|
||||
"peerDependencies": {
|
||||
"i18next": "^17.0.3",
|
||||
"i18next-browser-languagedetector": "^3.0.1",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-i18next": "^12.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -46,8 +46,8 @@
|
||||
"devDependencies": {
|
||||
"i18next": "^17.0.3",
|
||||
"i18next-browser-languagedetector": "^3.0.1",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-i18next": "^12.2.2",
|
||||
"webpack-merge": "^5.7.3"
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
@@ -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 };
|
||||
@@ -0,0 +1 @@
|
||||
export { Button , buttonVariants} from "./Button"
|
||||
@@ -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 };
|
||||
@@ -0,0 +1,3 @@
|
||||
import { Calendar } from './Calendar';
|
||||
|
||||
export default Calendar;
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
import { Combobox } from './Combobox';
|
||||
|
||||
export default Combobox;
|
||||
@@ -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,
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
import * as CommandComponents from './Command';
|
||||
|
||||
export default CommandComponents;
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
import { DatePickerWithRange } from "./DateRange";
|
||||
|
||||
export default DatePickerWithRange;
|
||||
@@ -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,
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
import * as DialogComponents from './Dialog';
|
||||
|
||||
export default DialogComponents;
|
||||
@@ -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 };
|
||||
@@ -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>;
|
||||
@@ -0,0 +1 @@
|
||||
export { ThemeWrapper } from './ThemeWrapper';
|
||||
@@ -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;
|
||||
@@ -0,0 +1,3 @@
|
||||
import NotificationProvider, { useNotification } from './NotificationProvider';
|
||||
|
||||
export { useNotification, NotificationProvider };
|
||||
@@ -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,
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
import { type ClassValue, clsx } from 'clsx';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
||||
@@ -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%;
|
||||
}
|
||||
}
|
||||
@@ -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')],
|
||||
};
|
||||
@@ -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"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2"
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@testing-library/react-hooks": "^3.2.1",
|
||||
@@ -46,11 +46,11 @@
|
||||
"lodash.debounce": "4.0.8",
|
||||
"moment": "2.29.4",
|
||||
"mousetrap": "^1.6.5",
|
||||
"react": "^17.0.2",
|
||||
"react": "^18.3.1",
|
||||
"react-dates": "^21.8.0",
|
||||
"react-dnd": "14.0.2",
|
||||
"react-dnd-html5-backend": "14.0.0",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-draggable": "4.4.3",
|
||||
"react-error-boundary": "^3.1.3",
|
||||
"react-modal": "3.11.2",
|
||||
|
||||
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
||||
|
||||
import { Button, ButtonEnums } from '../../components';
|
||||
|
||||
function ActionButtons({ actions, disabled, t }) {
|
||||
function ActionButtons({ actions, disabled = false, t }) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{actions.map((action, index) => (
|
||||
@@ -33,8 +33,4 @@ ActionButtons.propTypes = {
|
||||
disabled: PropTypes.bool,
|
||||
};
|
||||
|
||||
ActionButtons.defaultProps = {
|
||||
disabled: false,
|
||||
};
|
||||
|
||||
export default ActionButtons;
|
||||
@@ -58,7 +58,7 @@ const defaults = {
|
||||
};
|
||||
|
||||
const Button = ({
|
||||
children,
|
||||
children = '',
|
||||
size = defaults.size,
|
||||
disabled = defaults.disabled,
|
||||
type = defaults.type,
|
||||
@@ -66,7 +66,7 @@ const Button = ({
|
||||
endIcon: endIconProp,
|
||||
name,
|
||||
className,
|
||||
onClick,
|
||||
onClick = () => {},
|
||||
dataCY,
|
||||
startIconTooltip = null,
|
||||
endIconTooltip = null,
|
||||
@@ -121,14 +121,6 @@ const Button = ({
|
||||
);
|
||||
};
|
||||
|
||||
Button.defaultProps = {
|
||||
disabled: false,
|
||||
children: '',
|
||||
onClick: () => {},
|
||||
type: defaults.type,
|
||||
size: defaults.size,
|
||||
};
|
||||
|
||||
Button.propTypes = {
|
||||
/** What is inside the button, can be text or react component */
|
||||
children: PropTypes.node,
|
||||
|
||||
@@ -31,15 +31,15 @@ const fpsButtonClassNames =
|
||||
|
||||
const CinePlayer: React.FC<CinePlayerProps> = ({
|
||||
className,
|
||||
isPlaying,
|
||||
minFrameRate,
|
||||
maxFrameRate,
|
||||
stepFrameRate,
|
||||
frameRate: defaultFrameRate,
|
||||
isPlaying = false,
|
||||
minFrameRate = 1,
|
||||
maxFrameRate = 90,
|
||||
stepFrameRate = 1,
|
||||
frameRate: defaultFrameRate = 24,
|
||||
onFrameRateChange = () => {},
|
||||
onPlayPauseChange = () => {},
|
||||
onClose = () => {},
|
||||
dynamicInfo = {},
|
||||
onFrameRateChange,
|
||||
onPlayPauseChange,
|
||||
onClose,
|
||||
updateDynamicInfo,
|
||||
}) => {
|
||||
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 = {
|
||||
/** Minimum value for range slider */
|
||||
minFrameRate: PropTypes.number,
|
||||
|
||||
@@ -29,7 +29,7 @@ const renderYearsOptions = () => {
|
||||
};
|
||||
|
||||
const DateRange = props => {
|
||||
const { id, onChange, startDate, endDate } = props;
|
||||
const { id = '', onChange, startDate = null, endDate = null } = props;
|
||||
const [focusedInput, setFocusedInput] = useState(null);
|
||||
const renderYearsOptionsCallback = useCallback(renderYearsOptions, []);
|
||||
const { t } = useTranslation('DatePicker');
|
||||
@@ -165,12 +165,6 @@ const DateRange = props => {
|
||||
);
|
||||
};
|
||||
|
||||
DateRange.defaultProps = {
|
||||
id: '',
|
||||
startDate: null,
|
||||
endDate: null,
|
||||
};
|
||||
|
||||
DateRange.propTypes = {
|
||||
id: PropTypes.string,
|
||||
/** YYYYMMDD (19921022) */
|
||||
|
||||
@@ -15,10 +15,10 @@ const Dialog = ({
|
||||
actions,
|
||||
onShow,
|
||||
onSubmit,
|
||||
header: HeaderComponent,
|
||||
body: BodyComponent,
|
||||
footer: FooterComponent,
|
||||
value: defaultValue,
|
||||
header: HeaderComponent = Header,
|
||||
body: BodyComponent = Body,
|
||||
footer: FooterComponent = Footer,
|
||||
value: defaultValue = {},
|
||||
}) => {
|
||||
const [value, setValue] = useState(defaultValue);
|
||||
|
||||
@@ -78,13 +78,7 @@ Dialog.propTypes = {
|
||||
type: PropTypes.oneOf(['primary', 'secondary', 'cancel']).isRequired,
|
||||
})
|
||||
).isRequired,
|
||||
};
|
||||
|
||||
Dialog.defaultProps = {
|
||||
header: Header,
|
||||
footer: Footer,
|
||||
body: Body,
|
||||
value: {},
|
||||
onShow: PropTypes.func,
|
||||
};
|
||||
|
||||
export default Dialog;
|
||||
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
|
||||
|
||||
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 padding = 'pt-[20px]';
|
||||
|
||||
@@ -47,9 +47,4 @@ Footer.propTypes = {
|
||||
).isRequired,
|
||||
};
|
||||
|
||||
Footer.defaultProps = {
|
||||
onSubmit: noop,
|
||||
actions: [],
|
||||
};
|
||||
|
||||
export default Footer;
|
||||
@@ -20,7 +20,7 @@ CloseButton.propTypes = {
|
||||
onClick: PropTypes.func,
|
||||
};
|
||||
|
||||
const Header = ({ title, noCloseButton, onClose }) => {
|
||||
const Header = ({ title, noCloseButton = false, onClose }) => {
|
||||
const theme = 'bg-primary-dark';
|
||||
const flex = 'flex items-center justify-between';
|
||||
const padding = 'pb-[20px]';
|
||||
@@ -46,8 +46,4 @@ Header.propTypes = {
|
||||
onClose: PropTypes.func,
|
||||
};
|
||||
|
||||
Header.defaultProps = {
|
||||
noCloseButton: false,
|
||||
};
|
||||
|
||||
export default Header;
|
||||
@@ -11,15 +11,15 @@ const borderStyle = 'border-b last:border-b-0 border-secondary-main';
|
||||
const Dropdown = ({
|
||||
id,
|
||||
children,
|
||||
showDropdownIcon,
|
||||
showDropdownIcon = true,
|
||||
list,
|
||||
itemsClassName,
|
||||
titleClassName,
|
||||
showBorders,
|
||||
showBorders = true,
|
||||
alignment,
|
||||
// By default the max characters per line is the longest title
|
||||
// if you wish to override this, you can pass in a number
|
||||
maxCharactersPerLine,
|
||||
maxCharactersPerLine = 20,
|
||||
}) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const elementRef = useRef(null);
|
||||
@@ -199,11 +199,6 @@ const Dropdown = ({
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Dropdown.defaultProps = {
|
||||
showDropdownIcon: true,
|
||||
maxCharactersPerLine: 20,
|
||||
showBorders: true,
|
||||
};
|
||||
|
||||
Dropdown.propTypes = {
|
||||
id: PropTypes.string,
|
||||
|
||||
@@ -7,7 +7,7 @@ import Icon from '../Icon';
|
||||
import Typography from '../Typography';
|
||||
|
||||
// TODO: Add loading spinner to OHIF + use it here.
|
||||
const EmptyStudies = ({ className }) => {
|
||||
const EmptyStudies = ({ className = '' }) => {
|
||||
const { t } = useTranslation('StudyList');
|
||||
return (
|
||||
<div className={classnames('inline-flex flex-col items-center', className)}>
|
||||
@@ -25,10 +25,6 @@ const EmptyStudies = ({ className }) => {
|
||||
);
|
||||
};
|
||||
|
||||
EmptyStudies.defaultProps = {
|
||||
className: '',
|
||||
};
|
||||
|
||||
EmptyStudies.propTypes = {
|
||||
className: PropTypes.string,
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@ import IconButton from '../IconButton';
|
||||
|
||||
const isProduction = process.env.NODE_ENV === 'production';
|
||||
|
||||
const DefaultFallback = ({ error, context, resetErrorBoundary, fallbackRoute }) => {
|
||||
const DefaultFallback = ({ error, context, resetErrorBoundary = () => {}, fallbackRoute }) => {
|
||||
const { t } = useTranslation('ErrorBoundary');
|
||||
const [showDetails, setShowDetails] = useState(false);
|
||||
const title = `${t('Something went wrong')}${!isProduction && ` ${t('in')} ${context}`}.`;
|
||||
@@ -57,25 +57,19 @@ const DefaultFallback = ({ error, context, resetErrorBoundary, fallbackRoute })
|
||||
);
|
||||
};
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
DefaultFallback.propTypes = {
|
||||
error: PropTypes.object.isRequired,
|
||||
resetErrorBoundary: PropTypes.func,
|
||||
componentStack: PropTypes.string,
|
||||
};
|
||||
|
||||
DefaultFallback.defaultProps = {
|
||||
resetErrorBoundary: noop,
|
||||
};
|
||||
|
||||
const ErrorBoundary = ({
|
||||
context,
|
||||
onReset,
|
||||
onError,
|
||||
fallbackComponent: FallbackComponent,
|
||||
context = 'OHIF',
|
||||
onReset = () => {},
|
||||
onError = () => {},
|
||||
fallbackComponent: FallbackComponent = DefaultFallback,
|
||||
children,
|
||||
fallbackRoute,
|
||||
fallbackRoute = null,
|
||||
isPage,
|
||||
}) => {
|
||||
const [isOpen, setIsOpen] = useState(true);
|
||||
@@ -132,12 +126,4 @@ ErrorBoundary.propTypes = {
|
||||
fallbackRoute: PropTypes.string,
|
||||
};
|
||||
|
||||
ErrorBoundary.defaultProps = {
|
||||
context: 'OHIF',
|
||||
onReset: noop,
|
||||
onError: noop,
|
||||
fallbackComponent: DefaultFallback,
|
||||
fallbackRoute: null,
|
||||
};
|
||||
|
||||
export default ErrorBoundary;
|
||||
@@ -8,14 +8,14 @@ import Icon from '../Icon';
|
||||
import './ExpandableToolbarButton.css';
|
||||
|
||||
const ExpandableToolbarButton = ({
|
||||
type,
|
||||
id,
|
||||
isActive,
|
||||
onClick,
|
||||
icon,
|
||||
type = 'primary',
|
||||
id = '',
|
||||
isActive = false,
|
||||
onClick = () => {},
|
||||
icon = 'clipboard',
|
||||
className,
|
||||
content: Content,
|
||||
contentProps,
|
||||
content: Content = null,
|
||||
contentProps = {},
|
||||
}) => {
|
||||
const classes = {
|
||||
type: {
|
||||
@@ -71,15 +71,6 @@ const ExpandableToolbarButton = ({
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
ExpandableToolbarButton.defaultProps = {
|
||||
id: '',
|
||||
icon: 'clipboard',
|
||||
isActive: false,
|
||||
type: 'primary',
|
||||
content: null,
|
||||
onClick: noop,
|
||||
};
|
||||
|
||||
ExpandableToolbarButton.propTypes = {
|
||||
/* Influences background/hover styling */
|
||||
type: PropTypes.oneOf(['primary', 'secondary']),
|
||||
|
||||
@@ -14,9 +14,9 @@ import { PatientInfoVisibility } from '../../types/PatientInfoVisibility';
|
||||
function Header({
|
||||
children,
|
||||
menuOptions,
|
||||
isReturnEnabled,
|
||||
isReturnEnabled = true,
|
||||
onClickReturnButton,
|
||||
isSticky,
|
||||
isSticky = false,
|
||||
WhiteLabeling,
|
||||
showPatientInfo = PatientInfoVisibility.VISIBLE_COLLAPSED,
|
||||
servicesManager,
|
||||
@@ -113,9 +113,4 @@ Header.propTypes = {
|
||||
servicesManager: PropTypes.object,
|
||||
};
|
||||
|
||||
Header.defaultProps = {
|
||||
isReturnEnabled: true,
|
||||
isSticky: false,
|
||||
};
|
||||
|
||||
export default Header;
|
||||
@@ -15,7 +15,7 @@ import { getKeys, formatKeysForInput } from './utils';
|
||||
* @param {string} props.className input classes
|
||||
* @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 onInputKeyDown = event => {
|
||||
@@ -58,8 +58,4 @@ HotkeyField.propTypes = {
|
||||
}).isRequired,
|
||||
};
|
||||
|
||||
HotkeyField.defaultProps = {
|
||||
disabled: false,
|
||||
};
|
||||
|
||||
export default HotkeyField;
|
||||
@@ -11,10 +11,10 @@ import { MODIFIER_KEYS } from './hotkeysConfig';
|
||||
import { validate, splitHotkeyDefinitionsAndCreateTuples } from './utils';
|
||||
|
||||
const HotkeysPreferences = ({
|
||||
disabled,
|
||||
disabled = false,
|
||||
hotkeyDefinitions,
|
||||
errors: controlledErrors,
|
||||
onChange,
|
||||
onChange = () => {},
|
||||
hotkeysModule,
|
||||
}) => {
|
||||
const { t } = useTranslation('UserPreferencesModal');
|
||||
@@ -127,8 +127,6 @@ const HotkeysPreferences = ({
|
||||
);
|
||||
};
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
HotkeysPreferences.propTypes = {
|
||||
onChange: PropTypes.func,
|
||||
disabled: PropTypes.bool,
|
||||
@@ -142,9 +140,4 @@ HotkeysPreferences.propTypes = {
|
||||
}).isRequired,
|
||||
};
|
||||
|
||||
HotkeysPreferences.defaultProps = {
|
||||
onChange: noop,
|
||||
disabled: false,
|
||||
};
|
||||
|
||||
export default HotkeysPreferences;
|
||||
@@ -1,179 +1,179 @@
|
||||
import React from 'react';
|
||||
// Icons
|
||||
|
||||
import arrowDown from './../../assets/icons/arrow-down.svg';
|
||||
import arrowLeft from './../../assets/icons/arrow-left.svg';
|
||||
import arrowRight from './../../assets/icons/arrow-right.svg';
|
||||
import arrowLeftSmall from './../../assets/icons/arrow-left-small.svg';
|
||||
import arrowRightSmall from './../../assets/icons/arrow-right-small.svg';
|
||||
import calendar from './../../assets/icons/calendar.svg';
|
||||
import cancel from './../../assets/icons/cancel.svg';
|
||||
import clipboard from './../../assets/icons/clipboard.svg';
|
||||
import close from './../../assets/icons/closeIcon.svg';
|
||||
import dottedCircle from './../../assets/icons/dotted-circle.svg';
|
||||
import circledCheckmark from './../../assets/icons/circled-checkmark.svg';
|
||||
import chevronDown from './../../assets/icons/chevron-down.svg';
|
||||
import chevronLeft from './../../assets/icons/chevron-left.svg';
|
||||
import chevronMenu from './../../assets/icons/chevron-menu.svg';
|
||||
import chevronNext from './../../assets/icons/chevron-next.svg';
|
||||
import chevronPrev from './../../assets/icons/chevron-prev.svg';
|
||||
import chevronRight from './../../assets/icons/chevron-right.svg';
|
||||
import contentNext from './../../assets/icons/content-next.svg';
|
||||
import contentPrev from './../../assets/icons/content-prev.svg';
|
||||
import eyeVisible from './../../assets/icons/eye-visible.svg';
|
||||
import eyeHidden from './../../assets/icons/eye-hidden.svg';
|
||||
import exclamation from './../../assets/icons/exclamation.svg';
|
||||
import externalLink from './../../assets/icons/external-link.svg';
|
||||
import groupLayers from './../../assets/icons/group-layers.svg';
|
||||
import info from './../../assets/icons/info.svg';
|
||||
import infoAction from './../../assets/icons/info-action.svg';
|
||||
import infoLink from './../../assets/icons/info-link.svg';
|
||||
import launchArrow from './../../assets/icons/launch-arrow.svg';
|
||||
import launchInfo from './../../assets/icons/launch-info.svg';
|
||||
import link from './../../assets/icons/tool-stack-image-sync.svg';
|
||||
import listBullets from './../../assets/icons/list-bullets.svg';
|
||||
import lock from './../../assets/icons/lock.svg';
|
||||
import logoOhifSmall from './../../assets/icons/logo-ohif-small.svg';
|
||||
import logoDarkBackGround from './../../assets/icons/ohif-logo-color-darkbg.svg';
|
||||
import magnifier from './../../assets/icons/magnifier.svg';
|
||||
import notificationwarningDiamond from './../../assets/icons/notificationwarning-diamond.svg';
|
||||
import pencil from './../../assets/icons/pencil.svg';
|
||||
import powerOff from './../../assets/icons/power-off.svg';
|
||||
import profile from './../../assets/icons/profile.svg';
|
||||
import pushLeft from './../../assets/icons/push-left.svg';
|
||||
import pushRight from './../../assets/icons/push-right.svg';
|
||||
import settings from './../../assets/icons/settings.svg';
|
||||
import sidePanelCloseLeft from './../../assets/icons/side-panel-close-left.svg';
|
||||
import sidePanelCloseRight from './../../assets/icons/side-panel-close-right.svg';
|
||||
import sorting from './../../assets/icons/sorting.svg';
|
||||
import sortingActiveDown from './../../assets/icons/sorting-active-down.svg';
|
||||
import sortingActiveUp from './../../assets/icons/sorting-active-up.svg';
|
||||
import statusAlertWarning from './../../assets/icons/status-alert-warning.svg';
|
||||
import statusAlert from './../../assets/icons/status-alert.svg';
|
||||
import statusLocked from './../../assets/icons/status-locked.svg';
|
||||
import statusTracked from './../../assets/icons/status-tracked.svg';
|
||||
import statusUntracked from './../../assets/icons/status-untracked.svg';
|
||||
import tracked from './../../assets/icons/tracked.svg';
|
||||
import unlink from './../../assets/icons/unlink.svg';
|
||||
import checkboxChecked from './../../assets/icons/checkbox-checked.svg';
|
||||
import checkboxUnchecked from './../../assets/icons/checkbox-unchecked.svg';
|
||||
import iconAlertOutline from './../../assets/icons/icons-alert-outline.svg';
|
||||
import iconAlertSmall from './../../assets/icons/icon-alert-small.svg';
|
||||
import iconClose from './../../assets/icons/icon-close.svg';
|
||||
import iconClearField from './../../assets/icons/icon-clear-field.svg';
|
||||
import iconNextInactive from './../../assets/icons/icon-next-inactive.svg';
|
||||
import iconNext from './../../assets/icons/icon-next.svg';
|
||||
import iconPlay from './../../assets/icons/icon-play.svg';
|
||||
import iconPause from './../../assets/icons/icon-pause.svg';
|
||||
import iconPrevInactive from './../../assets/icons/icon-prev-inactive.svg';
|
||||
import iconPrev from './../../assets/icons/icon-prev.svg';
|
||||
import iconSearch from './../../assets/icons/icon-search.svg';
|
||||
import iconStatusAlert from './../../assets/icons/icon-status-alert.svg';
|
||||
import iconTransferring from './../../assets/icons/icon-transferring.svg';
|
||||
import iconUpload from './../../assets/icons/icon-upload.svg';
|
||||
import navigationPanelRightHide from './../../assets/icons/navigation-panel-right-hide.svg';
|
||||
import navigationPanelRightReveal from './../../assets/icons/navigation-panel-right-reveal.svg';
|
||||
import tabLinear from './../../assets/icons/tab-linear.svg';
|
||||
import tabPatientInfo from './../../assets/icons/tab-patient-info.svg';
|
||||
import tabROIThreshold from './../../assets/icons/tab-roi-threshold.svg';
|
||||
import tabSegmentation from './../../assets/icons/tab-segmentation.svg';
|
||||
import tabStudies from './../../assets/icons/tab-studies.svg';
|
||||
import uiArrowDown from './../../assets/icons/ui-arrow-down.svg';
|
||||
import uiArrowUp from './../../assets/icons/ui-arrow-up.svg';
|
||||
import uiArrowLeft from './../../assets/icons/ui-arrow-left.svg';
|
||||
import uiArrowRight from './../../assets/icons/ui-arrow-right.svg';
|
||||
import loadingOHIFMark from './../../assets/icons/loading-ohif-mark.svg';
|
||||
import notificationsInfo from './../../assets/icons/notifications-info.svg';
|
||||
import notificationsWarning from './../../assets/icons/notifications-warning.svg';
|
||||
import notificationsError from './../../assets/icons/notifications-error.svg';
|
||||
import notificationsSuccess from './../../assets/icons/notifications-success.svg';
|
||||
import nextArrow from './../../assets/icons/next-arrow.svg';
|
||||
import prevArrow from './../../assets/icons/prev-arrow.svg';
|
||||
import viewportStatusTracked from './../../assets/icons/viewport-status-tracked.svg';
|
||||
import { ReactComponent as arrowDown } from './../../assets/icons/arrow-down.svg';
|
||||
import { ReactComponent as arrowLeft } from './../../assets/icons/arrow-left.svg';
|
||||
import { ReactComponent as arrowRight } from './../../assets/icons/arrow-right.svg';
|
||||
import { ReactComponent as arrowLeftSmall } from './../../assets/icons/arrow-left-small.svg';
|
||||
import { ReactComponent as arrowRightSmall } from './../../assets/icons/arrow-right-small.svg';
|
||||
import { ReactComponent as calendar } from './../../assets/icons/calendar.svg';
|
||||
import { ReactComponent as cancel } from './../../assets/icons/cancel.svg';
|
||||
import { ReactComponent as clipboard } from './../../assets/icons/clipboard.svg';
|
||||
import { ReactComponent as close } from './../../assets/icons/closeIcon.svg';
|
||||
import { ReactComponent as dottedCircle } from './../../assets/icons/dotted-circle.svg';
|
||||
import { ReactComponent as circledCheckmark } from './../../assets/icons/circled-checkmark.svg';
|
||||
import { ReactComponent as chevronDown } from './../../assets/icons/chevron-down.svg';
|
||||
import { ReactComponent as chevronLeft } from './../../assets/icons/chevron-left.svg';
|
||||
import { ReactComponent as chevronMenu } from './../../assets/icons/chevron-menu.svg';
|
||||
import { ReactComponent as chevronNext } from './../../assets/icons/chevron-next.svg';
|
||||
import { ReactComponent as chevronPrev } from './../../assets/icons/chevron-prev.svg';
|
||||
import { ReactComponent as chevronRight } from './../../assets/icons/chevron-right.svg';
|
||||
import { ReactComponent as contentNext } from './../../assets/icons/content-next.svg';
|
||||
import { ReactComponent as contentPrev } from './../../assets/icons/content-prev.svg';
|
||||
import { ReactComponent as eyeVisible } from './../../assets/icons/eye-visible.svg';
|
||||
import { ReactComponent as eyeHidden } from './../../assets/icons/eye-hidden.svg';
|
||||
import { ReactComponent as exclamation } from './../../assets/icons/exclamation.svg';
|
||||
import { ReactComponent as externalLink } from './../../assets/icons/external-link.svg';
|
||||
import { ReactComponent as groupLayers } from './../../assets/icons/group-layers.svg';
|
||||
import { ReactComponent as info } from './../../assets/icons/info.svg';
|
||||
import { ReactComponent as infoAction } from './../../assets/icons/info-action.svg';
|
||||
import { ReactComponent as infoLink } from './../../assets/icons/info-link.svg';
|
||||
import { ReactComponent as launchArrow } from './../../assets/icons/launch-arrow.svg';
|
||||
import { ReactComponent as launchInfo } from './../../assets/icons/launch-info.svg';
|
||||
import { ReactComponent as link } from './../../assets/icons/tool-stack-image-sync.svg';
|
||||
import { ReactComponent as listBullets } from './../../assets/icons/list-bullets.svg';
|
||||
import { ReactComponent as lock } from './../../assets/icons/lock.svg';
|
||||
import { ReactComponent as logoOhifSmall } from './../../assets/icons/logo-ohif-small.svg';
|
||||
import { ReactComponent as logoDarkBackGround } from './../../assets/icons/ohif-logo-color-darkbg.svg';
|
||||
import { ReactComponent as magnifier } from './../../assets/icons/magnifier.svg';
|
||||
import { ReactComponent as notificationwarningDiamond } from './../../assets/icons/notificationwarning-diamond.svg';
|
||||
import { ReactComponent as pencil } from './../../assets/icons/pencil.svg';
|
||||
import { ReactComponent as powerOff } from './../../assets/icons/power-off.svg';
|
||||
import { ReactComponent as profile } from './../../assets/icons/profile.svg';
|
||||
import { ReactComponent as pushLeft } from './../../assets/icons/push-left.svg';
|
||||
import { ReactComponent as pushRight } from './../../assets/icons/push-right.svg';
|
||||
import { ReactComponent as settings } from './../../assets/icons/settings.svg';
|
||||
import { ReactComponent as sidePanelCloseLeft } from './../../assets/icons/side-panel-close-left.svg';
|
||||
import { ReactComponent as sidePanelCloseRight } from './../../assets/icons/side-panel-close-right.svg';
|
||||
import { ReactComponent as sorting } from './../../assets/icons/sorting.svg';
|
||||
import { ReactComponent as sortingActiveDown } from './../../assets/icons/sorting-active-down.svg';
|
||||
import { ReactComponent as sortingActiveUp } from './../../assets/icons/sorting-active-up.svg';
|
||||
import { ReactComponent as statusAlertWarning } from './../../assets/icons/status-alert-warning.svg';
|
||||
import { ReactComponent as statusAlert } from './../../assets/icons/status-alert.svg';
|
||||
import { ReactComponent as statusLocked } from './../../assets/icons/status-locked.svg';
|
||||
import { ReactComponent as statusTracked } from './../../assets/icons/status-tracked.svg';
|
||||
import { ReactComponent as statusUntracked } from './../../assets/icons/status-untracked.svg';
|
||||
import { ReactComponent as tracked } from './../../assets/icons/tracked.svg';
|
||||
import { ReactComponent as unlink } from './../../assets/icons/unlink.svg';
|
||||
import { ReactComponent as checkboxChecked } from './../../assets/icons/checkbox-checked.svg';
|
||||
import { ReactComponent as checkboxUnchecked } from './../../assets/icons/checkbox-unchecked.svg';
|
||||
import { ReactComponent as iconAlertOutline } from './../../assets/icons/icons-alert-outline.svg';
|
||||
import { ReactComponent as iconAlertSmall } from './../../assets/icons/icon-alert-small.svg';
|
||||
import { ReactComponent as iconClose } from './../../assets/icons/icon-close.svg';
|
||||
import { ReactComponent as iconClearField } from './../../assets/icons/icon-clear-field.svg';
|
||||
import { ReactComponent as iconNextInactive } from './../../assets/icons/icon-next-inactive.svg';
|
||||
import { ReactComponent as iconNext } from './../../assets/icons/icon-next.svg';
|
||||
import { ReactComponent as iconPlay } from './../../assets/icons/icon-play.svg';
|
||||
import { ReactComponent as iconPause } from './../../assets/icons/icon-pause.svg';
|
||||
import { ReactComponent as iconPrevInactive } from './../../assets/icons/icon-prev-inactive.svg';
|
||||
import { ReactComponent as iconPrev } from './../../assets/icons/icon-prev.svg';
|
||||
import { ReactComponent as iconSearch } from './../../assets/icons/icon-search.svg';
|
||||
import { ReactComponent as iconStatusAlert } from './../../assets/icons/icon-status-alert.svg';
|
||||
import { ReactComponent as iconTransferring } from './../../assets/icons/icon-transferring.svg';
|
||||
import { ReactComponent as iconUpload } from './../../assets/icons/icon-upload.svg';
|
||||
import { ReactComponent as navigationPanelRightHide } from './../../assets/icons/navigation-panel-right-hide.svg';
|
||||
import { ReactComponent as navigationPanelRightReveal } from './../../assets/icons/navigation-panel-right-reveal.svg';
|
||||
import { ReactComponent as tabLinear } from './../../assets/icons/tab-linear.svg';
|
||||
import { ReactComponent as tabPatientInfo } from './../../assets/icons/tab-patient-info.svg';
|
||||
import { ReactComponent as tabROIThreshold } from './../../assets/icons/tab-roi-threshold.svg';
|
||||
import { ReactComponent as tabSegmentation } from './../../assets/icons/tab-segmentation.svg';
|
||||
import { ReactComponent as tabStudies } from './../../assets/icons/tab-studies.svg';
|
||||
import { ReactComponent as uiArrowDown } from './../../assets/icons/ui-arrow-down.svg';
|
||||
import { ReactComponent as uiArrowUp } from './../../assets/icons/ui-arrow-up.svg';
|
||||
import { ReactComponent as uiArrowLeft } from './../../assets/icons/ui-arrow-left.svg';
|
||||
import { ReactComponent as uiArrowRight } from './../../assets/icons/ui-arrow-right.svg';
|
||||
import { ReactComponent as loadingOHIFMark } from './../../assets/icons/loading-ohif-mark.svg';
|
||||
import { ReactComponent as notificationsInfo } from './../../assets/icons/notifications-info.svg';
|
||||
import { ReactComponent as notificationsWarning } from './../../assets/icons/notifications-warning.svg';
|
||||
import { ReactComponent as notificationsError } from './../../assets/icons/notifications-error.svg';
|
||||
import { ReactComponent as notificationsSuccess } from './../../assets/icons/notifications-success.svg';
|
||||
import { ReactComponent as nextArrow } from './../../assets/icons/next-arrow.svg';
|
||||
import { ReactComponent as prevArrow } from './../../assets/icons/prev-arrow.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 CTAAA2 from './../../assets/icons/CT-AAA2.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 MRT2Brain from './../../assets/icons/MR-T2-Brain.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 = {
|
||||
'arrow-down': arrowDown,
|
||||
|
||||
@@ -74,14 +74,14 @@ const fullWidthClasses = {
|
||||
|
||||
const IconButton = ({
|
||||
children,
|
||||
variant,
|
||||
color,
|
||||
size,
|
||||
rounded,
|
||||
disabled,
|
||||
type,
|
||||
fullWidth,
|
||||
onClick,
|
||||
variant = 'contained',
|
||||
color = 'default',
|
||||
size = 'medium',
|
||||
rounded = 'medium',
|
||||
disabled = false,
|
||||
type = 'button',
|
||||
fullWidth = false,
|
||||
onClick = () => {},
|
||||
className,
|
||||
id,
|
||||
...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 = {
|
||||
children: PropTypes.node.isRequired,
|
||||
size: PropTypes.oneOf(['small', 'medium', 'large', 'initial', 'toolbar', 'toolbox']),
|
||||
|
||||
@@ -20,10 +20,12 @@ class ImageScrollbar extends PureComponent {
|
||||
width: `${this.props.height}`,
|
||||
};
|
||||
|
||||
const { onContextMenu = e => e.preventDefault() } = this.props;
|
||||
|
||||
return (
|
||||
<div
|
||||
className="scroll"
|
||||
onContextMenu={this.props.onContextMenu}
|
||||
onContextMenu={onContextMenu}
|
||||
>
|
||||
<div className="scroll-holder">
|
||||
<input
|
||||
@@ -70,8 +72,4 @@ class ImageScrollbar extends PureComponent {
|
||||
};
|
||||
}
|
||||
|
||||
ImageScrollbar.defaultProps = {
|
||||
onContextMenu: e => e.preventDefault(),
|
||||
};
|
||||
|
||||
export default ImageScrollbar;
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import DateRange from '../DateRange';
|
||||
import { DatePickerWithRange } from '@ohif/ui-next';
|
||||
import InputLabelWrapper from '../InputLabelWrapper';
|
||||
|
||||
const InputDateRange = ({
|
||||
@@ -9,8 +9,8 @@ const InputDateRange = ({
|
||||
label,
|
||||
isSortable,
|
||||
sortDirection,
|
||||
onLabelClick,
|
||||
value,
|
||||
onLabelClick = () => {},
|
||||
value = {},
|
||||
onChange,
|
||||
}) => {
|
||||
const { startDate, endDate } = value;
|
||||
@@ -26,9 +26,11 @@ const InputDateRange = ({
|
||||
isSortable={isSortable}
|
||||
sortDirection={sortDirection}
|
||||
onLabelClick={onClickHandler}
|
||||
className="xl:min-w-[284px]"
|
||||
>
|
||||
<div className="relative">
|
||||
<DateRange
|
||||
<div className="relative xl:max-w-[246px]">
|
||||
<DatePickerWithRange
|
||||
className="mt-2"
|
||||
id={id}
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
@@ -39,13 +41,6 @@ const InputDateRange = ({
|
||||
);
|
||||
};
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
InputDateRange.defaultProps = {
|
||||
value: {},
|
||||
onLabelClick: noop,
|
||||
};
|
||||
|
||||
InputDateRange.propTypes = {
|
||||
id: PropTypes.string,
|
||||
label: PropTypes.string.isRequired,
|
||||
|
||||
@@ -25,20 +25,20 @@ type InputDoubleRangeProps = {
|
||||
const InputDoubleRange: React.FC<InputDoubleRangeProps> = ({
|
||||
values,
|
||||
onChange,
|
||||
minValue,
|
||||
maxValue,
|
||||
step,
|
||||
unit,
|
||||
containerClassName,
|
||||
inputClassName,
|
||||
labelClassName,
|
||||
labelVariant,
|
||||
showLabel,
|
||||
labelPosition,
|
||||
trackColor,
|
||||
allowNumberEdit,
|
||||
minValue = 0,
|
||||
maxValue = 100,
|
||||
step = 1,
|
||||
unit = '',
|
||||
containerClassName = '',
|
||||
inputClassName = '',
|
||||
labelClassName = '',
|
||||
labelVariant = 'body1',
|
||||
showLabel = false,
|
||||
labelPosition = 'left',
|
||||
trackColor = 'primary',
|
||||
allowNumberEdit = false,
|
||||
allowOutOfRange = false,
|
||||
showAdjustmentArrows,
|
||||
showAdjustmentArrows = false,
|
||||
}) => {
|
||||
// Set initial thumb positions as percentages
|
||||
const initialPercentageStart = Math.round(((values[0] - minValue) / (maxValue - minValue)) * 100);
|
||||
@@ -235,20 +235,4 @@ const InputDoubleRange: React.FC<InputDoubleRangeProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
InputDoubleRange.defaultProps = {
|
||||
minValue: 0,
|
||||
maxValue: 100,
|
||||
step: 1,
|
||||
unit: '',
|
||||
containerClassName: '',
|
||||
inputClassName: '',
|
||||
labelClassName: '',
|
||||
labelVariant: 'body1',
|
||||
showLabel: false,
|
||||
labelPosition: 'left',
|
||||
trackColor: 'primary',
|
||||
allowNumberEdit: false,
|
||||
showAdjustmentArrows: false,
|
||||
};
|
||||
|
||||
export default InputDoubleRange;
|
||||
@@ -17,7 +17,7 @@ const InputLabelWrapper = ({
|
||||
isSortable,
|
||||
sortDirection,
|
||||
onLabelClick,
|
||||
className,
|
||||
className = '',
|
||||
children,
|
||||
}) => {
|
||||
const onClickHandler = e => {
|
||||
@@ -53,10 +53,6 @@ const InputLabelWrapper = ({
|
||||
);
|
||||
};
|
||||
|
||||
InputLabelWrapper.defaultProps = {
|
||||
className: '',
|
||||
};
|
||||
|
||||
InputLabelWrapper.propTypes = {
|
||||
label: PropTypes.string.isRequired,
|
||||
isSortable: PropTypes.bool.isRequired,
|
||||
|
||||
@@ -10,9 +10,9 @@ const InputMultiSelect = ({
|
||||
isSortable,
|
||||
sortDirection,
|
||||
onLabelClick,
|
||||
value,
|
||||
placeholder,
|
||||
options,
|
||||
value = [],
|
||||
placeholder = '',
|
||||
options = [],
|
||||
onChange,
|
||||
}) => {
|
||||
return (
|
||||
@@ -50,12 +50,6 @@ const InputMultiSelect = ({
|
||||
);
|
||||
};
|
||||
|
||||
InputMultiSelect.defaultProps = {
|
||||
value: [],
|
||||
placeholder: '',
|
||||
options: [],
|
||||
};
|
||||
|
||||
InputMultiSelect.propTypes = {
|
||||
id: PropTypes.string,
|
||||
label: PropTypes.string.isRequired,
|
||||
|
||||
@@ -4,7 +4,15 @@ import PropTypes from 'prop-types';
|
||||
import Input from '../Input';
|
||||
import InputLabelWrapper from '../InputLabelWrapper';
|
||||
|
||||
const InputText = ({ id, label, isSortable, sortDirection, onLabelClick, value, onChange }) => {
|
||||
const InputText = ({
|
||||
id,
|
||||
label,
|
||||
isSortable = false,
|
||||
sortDirection = 'none',
|
||||
onLabelClick = () => {},
|
||||
value = '',
|
||||
onChange,
|
||||
}) => {
|
||||
return (
|
||||
<InputLabelWrapper
|
||||
label={label}
|
||||
@@ -26,13 +34,6 @@ const InputText = ({ id, label, isSortable, sortDirection, onLabelClick, value,
|
||||
);
|
||||
};
|
||||
|
||||
InputText.defaultProps = {
|
||||
value: '',
|
||||
isSortable: false,
|
||||
onLabelClick: () => {},
|
||||
sortDirection: 'none',
|
||||
};
|
||||
|
||||
InputText.propTypes = {
|
||||
id: PropTypes.string,
|
||||
label: PropTypes.string.isRequired,
|
||||
|
||||
@@ -9,7 +9,11 @@ export enum showDialogOption {
|
||||
ShowOnceAndConfigure = 'configure',
|
||||
}
|
||||
|
||||
const InvestigationalUseDialog = ({ dialogConfiguration }) => {
|
||||
const InvestigationalUseDialog = ({
|
||||
dialogConfiguration = {
|
||||
option: showDialogOption.AlwaysShowDialog,
|
||||
},
|
||||
}) => {
|
||||
const { option, days } = dialogConfiguration;
|
||||
const [isHidden, setIsHidden] = useState(true);
|
||||
|
||||
@@ -97,13 +101,7 @@ InvestigationalUseDialog.propTypes = {
|
||||
dialogConfiguration: PropTypes.shape({
|
||||
option: PropTypes.oneOf(Object.values(showDialogOption)).isRequired,
|
||||
days: PropTypes.number,
|
||||
}).isRequired,
|
||||
};
|
||||
|
||||
InvestigationalUseDialog.defaultProps = {
|
||||
dialogConfiguration: {
|
||||
option: showDialogOption.AlwaysShowDialog,
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
export default InvestigationalUseDialog;
|
||||
@@ -4,7 +4,7 @@ import classNames from 'classnames';
|
||||
import Icon from '../Icon/Icon';
|
||||
|
||||
function LayoutPreset({
|
||||
onSelection,
|
||||
onSelection = () => {},
|
||||
title,
|
||||
icon,
|
||||
commandOptions,
|
||||
@@ -27,10 +27,6 @@ function LayoutPreset({
|
||||
);
|
||||
}
|
||||
|
||||
LayoutPreset.defaultProps = {
|
||||
onSelection: () => {},
|
||||
};
|
||||
|
||||
LayoutPreset.propTypes = {
|
||||
onSelection: PropTypes.func.isRequired,
|
||||
title: PropTypes.string,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
function LayoutSelector({ onSelection, rows, columns }) {
|
||||
function LayoutSelector({ onSelection = () => {}, rows = 3, columns = 4 }) {
|
||||
const [hoveredIndex, setHoveredIndex] = useState();
|
||||
const hoverX = hoveredIndex % columns;
|
||||
const hoverY = Math.floor(hoveredIndex / columns);
|
||||
@@ -48,12 +48,6 @@ function LayoutSelector({ onSelection, rows, columns }) {
|
||||
);
|
||||
}
|
||||
|
||||
LayoutSelector.defaultProps = {
|
||||
onSelection: () => {},
|
||||
columns: 4,
|
||||
rows: 3,
|
||||
};
|
||||
|
||||
LayoutSelector.propTypes = {
|
||||
onSelection: PropTypes.func.isRequired,
|
||||
columns: PropTypes.number.isRequired,
|
||||
|
||||
@@ -137,7 +137,7 @@ const fullWidthClasses = {
|
||||
};
|
||||
|
||||
const LegacyButton = ({
|
||||
children,
|
||||
children = '',
|
||||
variant = defaults.variant,
|
||||
color = defaults.color,
|
||||
border = defaults.border,
|
||||
@@ -151,7 +151,7 @@ const LegacyButton = ({
|
||||
endIcon: endIconProp,
|
||||
name,
|
||||
className,
|
||||
onClick,
|
||||
onClick = () => {},
|
||||
/** TODO: All possible props should be explicitly defined -- avoid spreading props */
|
||||
...rest
|
||||
}) => {
|
||||
@@ -206,13 +206,6 @@ const LegacyButton = ({
|
||||
);
|
||||
};
|
||||
|
||||
LegacyButton.defaultProps = {
|
||||
color: defaults.color,
|
||||
disabled: false,
|
||||
children: '',
|
||||
onClick: () => {},
|
||||
};
|
||||
|
||||
LegacyButton.propTypes = {
|
||||
/** What is inside the button, can be text or react component */
|
||||
children: PropTypes.node,
|
||||
|
||||
@@ -8,14 +8,14 @@ import Icon from '../Icon';
|
||||
import './LegacyCinePlayerCustomInputRange.css';
|
||||
|
||||
const LegacyCinePlayer = ({
|
||||
isPlaying,
|
||||
minFrameRate,
|
||||
maxFrameRate,
|
||||
stepFrameRate,
|
||||
frameRate: defaultFrameRate,
|
||||
onFrameRateChange,
|
||||
onPlayPauseChange,
|
||||
onClose,
|
||||
isPlaying = false,
|
||||
minFrameRate = 1,
|
||||
maxFrameRate = 90,
|
||||
stepFrameRate = 1,
|
||||
frameRate: defaultFrameRate = 24,
|
||||
onFrameRateChange = () => {},
|
||||
onPlayPauseChange = () => {},
|
||||
onClose = () => {},
|
||||
}) => {
|
||||
const [frameRate, setFrameRate] = useState(defaultFrameRate);
|
||||
const debouncedSetFrameRate = debounce(onFrameRateChange, 300);
|
||||
@@ -74,17 +74,6 @@ const LegacyCinePlayer = ({
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
LegacyCinePlayer.defaultProps = {
|
||||
isPlaying: false,
|
||||
minFrameRate: 1,
|
||||
maxFrameRate: 90,
|
||||
stepFrameRate: 1,
|
||||
frameRate: 24,
|
||||
onPlayPauseChange: noop,
|
||||
onFrameRateChange: noop,
|
||||
onClose: noop,
|
||||
};
|
||||
|
||||
LegacyCinePlayer.propTypes = {
|
||||
/** Minimum value for range slider */
|
||||
minFrameRate: PropTypes.number.isRequired,
|
||||
|
||||
@@ -283,10 +283,6 @@ const LegacySidePanel = ({
|
||||
);
|
||||
};
|
||||
|
||||
LegacySidePanel.defaultProps = {
|
||||
defaultComponentOpen: null,
|
||||
};
|
||||
|
||||
LegacySidePanel.propTypes = {
|
||||
servicesManager: PropTypes.object.isRequired,
|
||||
side: PropTypes.oneOf(['left', 'right']).isRequired,
|
||||
|
||||
@@ -72,10 +72,10 @@ const LegacySplitButton = ({
|
||||
primary,
|
||||
secondary,
|
||||
items,
|
||||
renderer,
|
||||
renderer = null,
|
||||
onInteraction,
|
||||
Component,
|
||||
isActive,
|
||||
Component = null,
|
||||
isActive = false,
|
||||
}) => {
|
||||
const { t } = useTranslation('Buttons');
|
||||
const [state, setState] = useState({ isHovering: false, isExpanded: false });
|
||||
@@ -149,7 +149,6 @@ const LegacySplitButton = ({
|
||||
};
|
||||
|
||||
LegacySplitButton.propTypes = {
|
||||
isToggle: PropTypes.bool,
|
||||
groupId: PropTypes.string.isRequired,
|
||||
primary: PropTypes.object.isRequired,
|
||||
secondary: PropTypes.object.isRequired,
|
||||
@@ -160,11 +159,4 @@ LegacySplitButton.propTypes = {
|
||||
Component: PropTypes.elementType,
|
||||
};
|
||||
|
||||
LegacySplitButton.defaultProps = {
|
||||
isToggle: false,
|
||||
renderer: null,
|
||||
isActive: false,
|
||||
Component: null,
|
||||
};
|
||||
|
||||
export default LegacySplitButton;
|
||||
@@ -11,11 +11,11 @@ import LegacyCinePlayer from '../LegacyCinePlayer';
|
||||
|
||||
const LegacyViewportActionBar = ({
|
||||
studyData,
|
||||
showNavArrows,
|
||||
showStatus,
|
||||
showCine,
|
||||
cineProps,
|
||||
showPatientInfo: patientInfoVisibility,
|
||||
showNavArrows = true,
|
||||
showStatus = true,
|
||||
showCine = false,
|
||||
cineProps = {},
|
||||
showPatientInfo: patientInfoVisibility = false,
|
||||
onArrowsClick,
|
||||
onDoubleClick,
|
||||
getStatusComponent,
|
||||
@@ -166,14 +166,8 @@ LegacyViewportActionBar.propTypes = {
|
||||
}),
|
||||
}).isRequired,
|
||||
getStatusComponent: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
LegacyViewportActionBar.defaultProps = {
|
||||
cineProps: {},
|
||||
showCine: false,
|
||||
showStatus: true,
|
||||
showNavArrows: true,
|
||||
showPatientInfo: false,
|
||||
onDoubleClick: PropTypes.func.isRequired,
|
||||
showStatus: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default LegacyViewportActionBar;
|
||||
@@ -10,11 +10,11 @@ const LineChart = ({
|
||||
height: heightProp,
|
||||
axis,
|
||||
series,
|
||||
showAxisLabels,
|
||||
showAxisGrid,
|
||||
showLegend,
|
||||
legendWidth,
|
||||
transparentChartBackground,
|
||||
showAxisLabels = true,
|
||||
showAxisGrid = true,
|
||||
showLegend = false,
|
||||
legendWidth = 120,
|
||||
transparentChartBackground = false,
|
||||
containerClassName,
|
||||
chartContainerClassName,
|
||||
}: {
|
||||
@@ -105,14 +105,6 @@ const LineChart = ({
|
||||
);
|
||||
};
|
||||
|
||||
LineChart.defaultProps = {
|
||||
showAxisLabels: true,
|
||||
showAxisGrid: true,
|
||||
showLegend: false,
|
||||
legendWidth: 120,
|
||||
transparentChartBackground: false,
|
||||
};
|
||||
|
||||
LineChart.propTypes = {
|
||||
title: PropTypes.string,
|
||||
width: PropTypes.number,
|
||||
|
||||
@@ -5,7 +5,7 @@ import PropTypes from 'prop-types';
|
||||
const flex = 'flex flex-row justify-between items-center';
|
||||
const theme = 'bg-indigo-dark text-white';
|
||||
|
||||
const ListMenu = ({ items = [], renderer, onClick }) => {
|
||||
const ListMenu = ({ items = [], renderer, onClick = () => {} }) => {
|
||||
const [selectedIndex, setSelectedIndex] = useState(null);
|
||||
|
||||
const ListItem = ({ item, index, isSelected }) => {
|
||||
@@ -48,16 +48,10 @@ const ListMenu = ({ items = [], renderer, onClick }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
ListMenu.propTypes = {
|
||||
items: PropTypes.array.isRequired,
|
||||
renderer: PropTypes.func.isRequired,
|
||||
onClick: PropTypes.func,
|
||||
};
|
||||
|
||||
ListMenu.defaultProps = {
|
||||
onClick: noop,
|
||||
};
|
||||
|
||||
export default ListMenu;
|
||||
@@ -9,7 +9,7 @@ const MeasurementItem = ({
|
||||
index,
|
||||
label,
|
||||
displayText,
|
||||
isActive,
|
||||
isActive = false,
|
||||
onClick,
|
||||
onEdit,
|
||||
onDelete,
|
||||
@@ -110,8 +110,4 @@ MeasurementItem.propTypes = {
|
||||
onDelete: PropTypes.func,
|
||||
};
|
||||
|
||||
MeasurementItem.defaultProps = {
|
||||
isActive: false,
|
||||
};
|
||||
|
||||
export default MeasurementItem;
|
||||
@@ -5,10 +5,10 @@ import { useTranslation } from 'react-i18next';
|
||||
import MeasurementItem from './MeasurementItem';
|
||||
|
||||
const MeasurementTable = ({
|
||||
data,
|
||||
data = [],
|
||||
title,
|
||||
onClick,
|
||||
onEdit,
|
||||
onClick = () => {},
|
||||
onEdit = () => {},
|
||||
onDelete,
|
||||
servicesManager,
|
||||
}: withAppTypes) => {
|
||||
@@ -71,12 +71,6 @@ const MeasurementTable = ({
|
||||
);
|
||||
};
|
||||
|
||||
MeasurementTable.defaultProps = {
|
||||
data: [],
|
||||
onClick: () => {},
|
||||
onEdit: () => {},
|
||||
};
|
||||
|
||||
MeasurementTable.propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
data: PropTypes.arrayOf(
|
||||
|
||||
@@ -15,12 +15,12 @@ if (typeof document !== 'undefined') {
|
||||
|
||||
const Modal = ({
|
||||
closeButton,
|
||||
shouldCloseOnEsc,
|
||||
shouldCloseOnEsc = true,
|
||||
isOpen,
|
||||
title,
|
||||
onClose,
|
||||
children,
|
||||
shouldCloseOnOverlayClick,
|
||||
shouldCloseOnOverlayClick = true,
|
||||
movable = false,
|
||||
containerDimensions = null,
|
||||
contentDimensions = null,
|
||||
@@ -99,14 +99,6 @@ const Modal = ({
|
||||
);
|
||||
};
|
||||
|
||||
Modal.defaultProps = {
|
||||
shouldCloseOnEsc: true,
|
||||
shouldCloseOnOverlayClick: true,
|
||||
movable: false,
|
||||
containerDimensions: null,
|
||||
contentDimensions: null,
|
||||
};
|
||||
|
||||
Modal.propTypes = {
|
||||
closeButton: PropTypes.bool,
|
||||
shouldCloseOnEsc: PropTypes.bool,
|
||||
|
||||
@@ -5,7 +5,15 @@ import PropTypes from 'prop-types';
|
||||
import Button, { ButtonEnums } from '../Button';
|
||||
import Icon from '../Icon';
|
||||
|
||||
const Notification = ({ id, type, message, actions, onSubmit, onOutsideClick, onKeyPress }) => {
|
||||
const Notification = ({
|
||||
id,
|
||||
type = 'info',
|
||||
message,
|
||||
actions,
|
||||
onSubmit,
|
||||
onOutsideClick = () => {},
|
||||
onKeyPress,
|
||||
}) => {
|
||||
const notificationRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -99,11 +107,6 @@ const Notification = ({ id, type, message, actions, onSubmit, onOutsideClick, on
|
||||
);
|
||||
};
|
||||
|
||||
Notification.defaultProps = {
|
||||
type: 'info',
|
||||
onOutsideClick: () => {},
|
||||
};
|
||||
|
||||
Notification.propTypes = {
|
||||
type: PropTypes.oneOf(['error', 'warning', 'info', 'success']),
|
||||
message: PropTypes.string.isRequired,
|
||||
|
||||
@@ -49,8 +49,6 @@ const PanelSection = ({ title, children, actionIcons = [], childrenClassName })
|
||||
);
|
||||
};
|
||||
|
||||
PanelSection.defaultProps = {};
|
||||
|
||||
PanelSection.propTypes = {
|
||||
title: PropTypes.string,
|
||||
children: PropTypes.node,
|
||||
|
||||
@@ -7,7 +7,7 @@ function SegmentationDropDownRow({
|
||||
segmentations = [],
|
||||
activeSegmentation,
|
||||
onActiveSegmentationChange,
|
||||
disableEditing,
|
||||
disableEditing = false,
|
||||
onToggleSegmentationVisibility,
|
||||
onSegmentationEdit,
|
||||
onSegmentationDownload,
|
||||
@@ -180,9 +180,4 @@ SegmentationDropDownRow.propTypes = {
|
||||
onSegmentationAdd: PropTypes.func,
|
||||
};
|
||||
|
||||
SegmentationDropDownRow.defaultProps = {
|
||||
segmentations: [],
|
||||
disableEditing: false,
|
||||
};
|
||||
|
||||
export default SegmentationDropDownRow;
|
||||
@@ -8,7 +8,7 @@ const SegmentItem = ({
|
||||
segmentIndex,
|
||||
segmentationId,
|
||||
label,
|
||||
isActive,
|
||||
isActive = false,
|
||||
isVisible,
|
||||
color,
|
||||
showDelete,
|
||||
@@ -236,8 +236,4 @@ SegmentItem.propTypes = {
|
||||
displayText: PropTypes.string,
|
||||
};
|
||||
|
||||
SegmentItem.defaultProps = {
|
||||
isActive: false,
|
||||
};
|
||||
|
||||
export default SegmentItem;
|
||||
@@ -9,39 +9,34 @@ import SegmentationGroupSegment from './SegmentationGroupSegment';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const SegmentationGroupTable = ({
|
||||
segmentations,
|
||||
// segmentation initial config
|
||||
segmentations = [],
|
||||
segmentationConfig,
|
||||
// UI show/hide
|
||||
disableEditing,
|
||||
showAddSegmentation,
|
||||
showAddSegment,
|
||||
showDeleteSegment,
|
||||
// segmentation/segment handlers
|
||||
onSegmentationAdd,
|
||||
onSegmentationEdit,
|
||||
onSegmentationClick,
|
||||
onSegmentationDelete,
|
||||
onSegmentationDownload,
|
||||
onSegmentationDownloadRTSS,
|
||||
storeSegmentation,
|
||||
// segment handlers
|
||||
onSegmentClick,
|
||||
onSegmentAdd,
|
||||
onSegmentDelete,
|
||||
onSegmentEdit,
|
||||
onToggleSegmentationVisibility,
|
||||
onToggleSegmentVisibility,
|
||||
onToggleSegmentLock,
|
||||
onSegmentColorClick,
|
||||
// segmentation config handlers
|
||||
setFillAlpha,
|
||||
setFillAlphaInactive,
|
||||
setOutlineWidthActive,
|
||||
setOutlineOpacityActive,
|
||||
setRenderFill,
|
||||
setRenderInactiveSegmentations,
|
||||
setRenderOutline,
|
||||
disableEditing = false,
|
||||
showAddSegmentation = true,
|
||||
showAddSegment = true,
|
||||
showDeleteSegment = true,
|
||||
onSegmentationAdd = () => {},
|
||||
onSegmentationEdit = () => {},
|
||||
onSegmentationClick = () => {},
|
||||
onSegmentationDelete = () => {},
|
||||
onSegmentationDownload = () => {},
|
||||
onSegmentationDownloadRTSS = () => {},
|
||||
storeSegmentation = () => {},
|
||||
onSegmentClick = () => {},
|
||||
onSegmentAdd = () => {},
|
||||
onSegmentDelete = () => {},
|
||||
onSegmentEdit = () => {},
|
||||
onToggleSegmentationVisibility = () => {},
|
||||
onToggleSegmentVisibility = () => {},
|
||||
onToggleSegmentLock = () => {},
|
||||
onSegmentColorClick = () => {},
|
||||
setFillAlpha = () => {},
|
||||
setFillAlphaInactive = () => {},
|
||||
setOutlineWidthActive = () => {},
|
||||
setOutlineOpacityActive = () => {},
|
||||
setRenderFill = () => {},
|
||||
setRenderInactiveSegmentations = () => {},
|
||||
setRenderOutline = () => {},
|
||||
addSegmentationClassName,
|
||||
}) => {
|
||||
const [isConfigOpen, setIsConfigOpen] = useState(false);
|
||||
@@ -216,33 +211,4 @@ SegmentationGroupTable.propTypes = {
|
||||
setRenderOutline: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
SegmentationGroupTable.defaultProps = {
|
||||
segmentations: [],
|
||||
disableEditing: false,
|
||||
showAddSegmentation: true,
|
||||
showAddSegment: true,
|
||||
showDeleteSegment: true,
|
||||
onSegmentationAdd: () => {},
|
||||
onSegmentationEdit: () => {},
|
||||
onSegmentationClick: () => {},
|
||||
onSegmentationDelete: () => {},
|
||||
onSegmentationDownload: () => {},
|
||||
onSemgnetationDownloadRTSS: () => {},
|
||||
storeSegmentation: () => {},
|
||||
onSegmentClick: () => {},
|
||||
onSegmentAdd: () => {},
|
||||
onSegmentDelete: () => {},
|
||||
onSegmentEdit: () => {},
|
||||
onToggleSegmentationVisibility: () => {},
|
||||
onToggleSegmentVisibility: () => {},
|
||||
onToggleSegmentLock: () => {},
|
||||
onSegmentColorClick: () => {},
|
||||
setFillAlpha: () => {},
|
||||
setFillAlphaInactive: () => {},
|
||||
setOutlineWidthActive: () => {},
|
||||
setOutlineOpacityActive: () => {},
|
||||
setRenderFill: () => {},
|
||||
setRenderInactiveSegmentations: () => {},
|
||||
setRenderOutline: () => {},
|
||||
};
|
||||
export default SegmentationGroupTable;
|
||||
+27
-61
@@ -7,39 +7,34 @@ import { useTranslation } from 'react-i18next';
|
||||
import SegmentationItem from './SegmentationItem';
|
||||
|
||||
const SegmentationGroupTableExpanded = ({
|
||||
segmentations,
|
||||
// segmentation initial config
|
||||
segmentations = [],
|
||||
segmentationConfig,
|
||||
// UI show/hide
|
||||
disableEditing,
|
||||
showAddSegmentation,
|
||||
showAddSegment,
|
||||
showDeleteSegment,
|
||||
// segmentation/segment handlers
|
||||
onSegmentationAdd,
|
||||
onSegmentationEdit,
|
||||
onSegmentationClick,
|
||||
onSegmentationDelete,
|
||||
onSegmentationDownload,
|
||||
onSegmentationDownloadRTSS,
|
||||
storeSegmentation,
|
||||
// segment handlers
|
||||
onSegmentClick,
|
||||
onSegmentAdd,
|
||||
onSegmentDelete,
|
||||
onSegmentEdit,
|
||||
onToggleSegmentationVisibility,
|
||||
onToggleSegmentVisibility,
|
||||
onToggleSegmentLock,
|
||||
onSegmentColorClick,
|
||||
// segmentation config handlers
|
||||
setFillAlpha,
|
||||
setFillAlphaInactive,
|
||||
setOutlineWidthActive,
|
||||
setOutlineOpacityActive,
|
||||
setRenderFill,
|
||||
setRenderInactiveSegmentations,
|
||||
setRenderOutline,
|
||||
disableEditing = false,
|
||||
showAddSegmentation = true,
|
||||
showAddSegment = true,
|
||||
showDeleteSegment = true,
|
||||
onSegmentationAdd = () => {},
|
||||
onSegmentationEdit = () => {},
|
||||
onSegmentationClick = () => {},
|
||||
onSegmentationDelete = () => {},
|
||||
onSegmentationDownload = () => {},
|
||||
onSegmentationDownloadRTSS = () => {},
|
||||
storeSegmentation = () => {},
|
||||
onSegmentClick = () => {},
|
||||
onSegmentAdd = () => {},
|
||||
onSegmentDelete = () => {},
|
||||
onSegmentEdit = () => {},
|
||||
onToggleSegmentationVisibility = () => {},
|
||||
onToggleSegmentVisibility = () => {},
|
||||
onToggleSegmentLock = () => {},
|
||||
onSegmentColorClick = () => {},
|
||||
setFillAlpha = () => {},
|
||||
setFillAlphaInactive = () => {},
|
||||
setOutlineWidthActive = () => {},
|
||||
setOutlineOpacityActive = () => {},
|
||||
setRenderFill = () => {},
|
||||
setRenderInactiveSegmentations = () => {},
|
||||
setRenderOutline = () => {},
|
||||
}) => {
|
||||
const [isConfigOpen, setIsConfigOpen] = useState(false);
|
||||
const [activeSegmentationId, setActiveSegmentationId] = useState(null);
|
||||
@@ -179,33 +174,4 @@ SegmentationGroupTableExpanded.propTypes = {
|
||||
setRenderOutline: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
SegmentationGroupTableExpanded.defaultProps = {
|
||||
segmentations: [],
|
||||
disableEditing: false,
|
||||
showAddSegmentation: true,
|
||||
showAddSegment: true,
|
||||
showDeleteSegment: true,
|
||||
onSegmentationAdd: () => {},
|
||||
onSegmentationEdit: () => {},
|
||||
onSegmentationClick: () => {},
|
||||
onSegmentationDelete: () => {},
|
||||
onSegmentationDownload: () => {},
|
||||
onSemgnetationDownloadRTSS: () => {},
|
||||
storeSegmentation: () => {},
|
||||
onSegmentClick: () => {},
|
||||
onSegmentAdd: () => {},
|
||||
onSegmentDelete: () => {},
|
||||
onSegmentEdit: () => {},
|
||||
onToggleSegmentationVisibility: () => {},
|
||||
onToggleSegmentVisibility: () => {},
|
||||
onToggleSegmentLock: () => {},
|
||||
onSegmentColorClick: () => {},
|
||||
setFillAlpha: () => {},
|
||||
setFillAlphaInactive: () => {},
|
||||
setOutlineWidthActive: () => {},
|
||||
setOutlineOpacityActive: () => {},
|
||||
setRenderFill: () => {},
|
||||
setRenderInactiveSegmentations: () => {},
|
||||
setRenderOutline: () => {},
|
||||
};
|
||||
export default SegmentationGroupTableExpanded;
|
||||
@@ -8,8 +8,8 @@ import SegmentationGroupSegment from './SegmentationGroupSegment';
|
||||
import { Tooltip } from '../../components';
|
||||
|
||||
function SegmentationItem({
|
||||
segmentation,
|
||||
disableEditing,
|
||||
segmentation = {},
|
||||
disableEditing = false,
|
||||
onSegmentationEdit,
|
||||
onSegmentationDownload,
|
||||
onSegmentationDownloadRTSS,
|
||||
@@ -203,9 +203,4 @@ SegmentationItem.propTypes = {
|
||||
activeSegmentationId: PropTypes.string,
|
||||
};
|
||||
|
||||
SegmentationItem.defaultProps = {
|
||||
segmentation: null,
|
||||
disableEditing: false,
|
||||
};
|
||||
|
||||
export default SegmentationItem;
|
||||
@@ -8,8 +8,8 @@ const SegmentationItem = ({
|
||||
id,
|
||||
index,
|
||||
label,
|
||||
displayText,
|
||||
isActive,
|
||||
displayText = [],
|
||||
isActive = false,
|
||||
isVisible,
|
||||
onClick,
|
||||
onEdit,
|
||||
@@ -138,9 +138,4 @@ SegmentationItem.propTypes = {
|
||||
toggleVisibility: PropTypes.func,
|
||||
};
|
||||
|
||||
SegmentationItem.defaultProps = {
|
||||
isActive: false,
|
||||
displayText: [],
|
||||
};
|
||||
|
||||
export default SegmentationItem;
|
||||
@@ -5,14 +5,14 @@ import SegmentationItem from './SegmentationItem';
|
||||
import Icon from '../Icon';
|
||||
|
||||
const SegmentationTable = ({
|
||||
title,
|
||||
segmentations,
|
||||
activeSegmentationId,
|
||||
onClick,
|
||||
onEdit,
|
||||
onDelete,
|
||||
onToggleVisibility,
|
||||
onToggleVisibilityAll,
|
||||
title = '',
|
||||
segmentations = [],
|
||||
activeSegmentationId = '',
|
||||
onClick = () => {},
|
||||
onEdit = () => {},
|
||||
onDelete = () => {},
|
||||
onToggleVisibility = () => {},
|
||||
onToggleVisibilityAll = () => {},
|
||||
}) => {
|
||||
const [hiddenSegmentationIds, setHiddenSegmentationIds] = useState([]);
|
||||
const amount = segmentations.length;
|
||||
@@ -112,14 +112,4 @@ SegmentationTable.propTypes = {
|
||||
onToggleVisibilityAll: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
SegmentationTable.defaultProps = {
|
||||
title: '',
|
||||
segmentations: [],
|
||||
activeSegmentationId: '',
|
||||
onClick: () => {},
|
||||
onEdit: () => {},
|
||||
onToggleVisibility: () => {},
|
||||
onToggleVisibilityAll: () => {},
|
||||
};
|
||||
|
||||
export default SegmentationTable;
|
||||
@@ -42,20 +42,20 @@ const Option = props => {
|
||||
|
||||
const Select = ({
|
||||
id,
|
||||
className,
|
||||
closeMenuOnSelect,
|
||||
hideSelectedOptions,
|
||||
isClearable,
|
||||
isDisabled,
|
||||
isMulti,
|
||||
isSearchable,
|
||||
className = '',
|
||||
closeMenuOnSelect = true,
|
||||
hideSelectedOptions = false,
|
||||
isClearable = true,
|
||||
isDisabled = false,
|
||||
isMulti = false,
|
||||
isSearchable = true,
|
||||
onChange,
|
||||
options,
|
||||
placeholder,
|
||||
noIcons,
|
||||
menuPlacement,
|
||||
components,
|
||||
value,
|
||||
noIcons = false,
|
||||
menuPlacement = 'auto',
|
||||
components = {},
|
||||
value = [],
|
||||
}) => {
|
||||
const _noIconComponents = {
|
||||
DropdownIndicator: () => null,
|
||||
@@ -96,11 +96,9 @@ const Select = ({
|
||||
options={options}
|
||||
blurInputOnSelect={true}
|
||||
menuPortalTarget={document.body}
|
||||
styles={
|
||||
{
|
||||
menuPortal: base => ({ ...base, zIndex: 9999 }),
|
||||
}
|
||||
}
|
||||
styles={{
|
||||
menuPortal: base => ({ ...base, zIndex: 9999 }),
|
||||
}}
|
||||
value={value && Array.isArray(value) ? selectedOptions : value}
|
||||
onChange={(selectedOptions, { action }) => {
|
||||
const newSelection = !selectedOptions.length
|
||||
@@ -112,20 +110,6 @@ const Select = ({
|
||||
);
|
||||
};
|
||||
|
||||
Select.defaultProps = {
|
||||
className: '',
|
||||
closeMenuOnSelect: true,
|
||||
hideSelectedOptions: false,
|
||||
isClearable: true,
|
||||
components: {},
|
||||
isDisabled: false,
|
||||
isMulti: false,
|
||||
isSearchable: true,
|
||||
noIcons: false,
|
||||
menuPlacement: 'auto',
|
||||
value: [],
|
||||
};
|
||||
|
||||
Select.propTypes = {
|
||||
className: PropTypes.string,
|
||||
closeMenuOnSelect: PropTypes.bool,
|
||||
|
||||
@@ -161,7 +161,7 @@ const createBaseStyle = (expandedWidth: number) => {
|
||||
const SidePanel = ({
|
||||
side,
|
||||
className,
|
||||
activeTabIndex: activeTabIndexProp,
|
||||
activeTabIndex: activeTabIndexProp = null,
|
||||
tabs,
|
||||
onOpen,
|
||||
expandedWidth = 248,
|
||||
@@ -400,11 +400,6 @@ const SidePanel = ({
|
||||
);
|
||||
};
|
||||
|
||||
SidePanel.defaultProps = {
|
||||
defaultComponentOpen: null,
|
||||
activeTabIndex: null, // the default is to close the side panel
|
||||
};
|
||||
|
||||
SidePanel.propTypes = {
|
||||
side: PropTypes.oneOf(['left', 'right']).isRequired,
|
||||
className: PropTypes.string,
|
||||
|
||||
@@ -91,9 +91,9 @@ const SplitButton = ({
|
||||
primary,
|
||||
secondary,
|
||||
items,
|
||||
renderer,
|
||||
renderer = null,
|
||||
onInteraction,
|
||||
Component,
|
||||
Component = Icon,
|
||||
}) => {
|
||||
const { t } = useTranslation('Buttons');
|
||||
const [state, setState] = useState({ isHovering: false, isExpanded: false });
|
||||
@@ -172,7 +172,6 @@ const SplitButton = ({
|
||||
};
|
||||
|
||||
SplitButton.propTypes = {
|
||||
isToggle: PropTypes.bool,
|
||||
groupId: PropTypes.string.isRequired,
|
||||
primary: PropTypes.object.isRequired,
|
||||
secondary: PropTypes.object.isRequired,
|
||||
@@ -184,11 +183,4 @@ SplitButton.propTypes = {
|
||||
interactionType: PropTypes.oneOf(['action', 'tool', 'toggle']),
|
||||
};
|
||||
|
||||
SplitButton.defaultProps = {
|
||||
isToggle: false,
|
||||
renderer: null,
|
||||
isActive: false,
|
||||
Component: null,
|
||||
};
|
||||
|
||||
export default SplitButton;
|
||||
@@ -19,15 +19,17 @@ const getTrackedSeries = displaySets => {
|
||||
return trackedSeries;
|
||||
};
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
const StudyBrowser = ({
|
||||
tabs,
|
||||
activeTabName,
|
||||
expandedStudyInstanceUIDs,
|
||||
onClickTab,
|
||||
onClickStudy,
|
||||
onClickThumbnail,
|
||||
onDoubleClickThumbnail,
|
||||
onClickUntrack,
|
||||
onClickTab = noop,
|
||||
onClickStudy = noop,
|
||||
onClickThumbnail = noop,
|
||||
onDoubleClickThumbnail = noop,
|
||||
onClickUntrack = noop,
|
||||
activeDisplaySetInstanceUIDs,
|
||||
servicesManager,
|
||||
}: withAppTypes) => {
|
||||
@@ -168,14 +170,4 @@ StudyBrowser.propTypes = {
|
||||
),
|
||||
};
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
StudyBrowser.defaultProps = {
|
||||
onClickTab: noop,
|
||||
onClickStudy: noop,
|
||||
onClickThumbnail: noop,
|
||||
onDoubleClickThumbnail: noop,
|
||||
onClickUntrack: noop,
|
||||
};
|
||||
|
||||
export default StudyBrowser;
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
// Svgs
|
||||
import logoOhif from './../../assets/svgs/ohif-logo.svg';
|
||||
import { ReactComponent as logoOhif } from './../../assets/svgs/ohif-logo.svg';
|
||||
|
||||
const SVGS = {
|
||||
'logo-ohif': logoOhif,
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
|
||||
const Table = ({ children, className, fullWidth, style }) => {
|
||||
const Table = ({ children, className = '', fullWidth = true, style = {} }) => {
|
||||
const classes = {
|
||||
base: 'text-lg text-white',
|
||||
fullWidth: {
|
||||
@@ -21,12 +21,6 @@ const Table = ({ children, className, fullWidth, style }) => {
|
||||
);
|
||||
};
|
||||
|
||||
Table.defaultProps = {
|
||||
className: '',
|
||||
fullWidth: true,
|
||||
style: {},
|
||||
};
|
||||
|
||||
Table.propTypes = {
|
||||
fullWidth: PropTypes.bool,
|
||||
children: PropTypes.node.isRequired,
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
|
||||
const TableBody = ({ children, className, style }) => {
|
||||
const TableBody = ({ children, className = '', style = {} }) => {
|
||||
return (
|
||||
<div
|
||||
className={classnames('ohif-scrollbar mt-2 max-h-48 overflow-y-scroll', className)}
|
||||
@@ -17,11 +17,6 @@ const TableBody = ({ children, className, style }) => {
|
||||
);
|
||||
};
|
||||
|
||||
TableBody.defaultProps = {
|
||||
className: '',
|
||||
style: {},
|
||||
};
|
||||
|
||||
TableBody.propTypes = {
|
||||
children: function (props, propName, componentName) {
|
||||
const elements = React.Children.toArray(props.children);
|
||||
|
||||
@@ -4,14 +4,14 @@ import classnames from 'classnames';
|
||||
|
||||
const TableCell = ({
|
||||
children,
|
||||
className,
|
||||
colSpan,
|
||||
className = '',
|
||||
colSpan = 1,
|
||||
// ignored because we don't want to expose this prop
|
||||
// eslint-disable-next-line react/prop-types
|
||||
cellsNum,
|
||||
isTableHead,
|
||||
align,
|
||||
style,
|
||||
isTableHead = false,
|
||||
align = 'left',
|
||||
style = {},
|
||||
}) => {
|
||||
const classes = {
|
||||
align: {
|
||||
@@ -42,14 +42,6 @@ const TableCell = ({
|
||||
);
|
||||
};
|
||||
|
||||
TableCell.defaultProps = {
|
||||
align: 'left',
|
||||
className: '',
|
||||
colSpan: 1,
|
||||
isTableHead: false,
|
||||
style: {},
|
||||
};
|
||||
|
||||
TableCell.propTypes = {
|
||||
align: PropTypes.oneOf(['left', 'center', 'right', 'justify']),
|
||||
children: PropTypes.node.isRequired,
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
|
||||
const TableHead = ({ children, className, style }) => {
|
||||
const TableHead = ({ children, className = '', style = {} }) => {
|
||||
return (
|
||||
<div
|
||||
className={classnames(
|
||||
@@ -20,11 +20,6 @@ const TableHead = ({ children, className, style }) => {
|
||||
);
|
||||
};
|
||||
|
||||
TableHead.defaultProps = {
|
||||
className: '',
|
||||
style: {},
|
||||
};
|
||||
|
||||
TableHead.propTypes = {
|
||||
children: function (props, propName, componentName) {
|
||||
const elements = React.Children.toArray(props.children);
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
|
||||
const TableRow = ({ children, className, isTableHead, style }) => {
|
||||
const TableRow = ({ children, className = '', isTableHead = false, style = {} }) => {
|
||||
const childrens = React.Children.map(children, child => {
|
||||
const isValidReactElement = React.isValidElement(child);
|
||||
|
||||
@@ -21,12 +21,6 @@ const TableRow = ({ children, className, isTableHead, style }) => {
|
||||
);
|
||||
};
|
||||
|
||||
TableRow.defaultProps = {
|
||||
isTableHead: false,
|
||||
className: '',
|
||||
style: {},
|
||||
};
|
||||
|
||||
TableRow.propTypes = {
|
||||
isTableHead: PropTypes.bool,
|
||||
children: function (props, propName, componentName) {
|
||||
|
||||
@@ -19,7 +19,7 @@ const Thumbnail = ({
|
||||
numInstances,
|
||||
countIcon,
|
||||
messages,
|
||||
dragData,
|
||||
dragData = {},
|
||||
isActive,
|
||||
onClick,
|
||||
onDoubleClick,
|
||||
@@ -130,8 +130,4 @@ Thumbnail.propTypes = {
|
||||
onDoubleClick: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
Thumbnail.defaultProps = {
|
||||
dragData: {},
|
||||
};
|
||||
|
||||
export default Thumbnail;
|
||||
@@ -12,7 +12,7 @@ const ToolbarButton = ({
|
||||
label,
|
||||
commands,
|
||||
onInteraction,
|
||||
dropdownContent,
|
||||
dropdownContent = null,
|
||||
//
|
||||
className,
|
||||
disabled,
|
||||
@@ -65,10 +65,6 @@ const ToolbarButton = ({
|
||||
);
|
||||
};
|
||||
|
||||
ToolbarButton.defaultProps = {
|
||||
dropdownContent: null,
|
||||
};
|
||||
|
||||
ToolbarButton.propTypes = {
|
||||
/* Influences background/hover styling */
|
||||
id: PropTypes.string.isRequired,
|
||||
|
||||
Loaded 100 of 153 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user