@lunit/oui 3.0.1 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Chip/Chip.utils.js +0 -1
- package/dist/components/Dropdown/Dropdown.js +1 -3
- package/dist/components/Dropdown/IconDropdown.js +1 -3
- package/dist/components/List/ListItemCaption.styled.js +0 -1
- package/dist/components/LoadingIndicator/LoadingIndicator.js +0 -1
- package/dist/components/NoMatchContainer/NoMatchContainer.js +3 -3
- package/dist/components/Radio/RadioGroup.styled.js +0 -1
- package/dist/components/TextField/TextInput.styled.js +2 -6
- package/dist/components/Toggle/Toggle.js +12 -7
- package/dist/components/UploadManager/UploadManager.js +9 -5
- package/dist/presentations/AnalysisBar/AnalysisBar.styled.js +12 -7
- package/dist/presentations/FreeText/FreeText.js +50 -28
- package/dist/presentations/HorizonDivider/HorizonDivider.js +1 -1
- package/dist/presentations/Threshold/Threshold.js +11 -9
- package/dist/presentations/Threshold/Threshold.styled.js +56 -58
- package/dist/presentations/Threshold/Threshold.utils.js +27 -18
- package/dist/types/components/Tooltip/Tooltip.types.d.ts +2 -2
- package/dist/types/presentations/Threshold/Threshold.d.ts +1 -1
- package/dist/types/presentations/Threshold/Threshold.types.d.ts +16 -4
- package/dist/types/presentations/Threshold/Threshold.utils.d.ts +18 -16
- package/package.json +17 -4
|
@@ -31,9 +31,7 @@ const Dropdown = (({ children, placeholder, value, error, helperMsg, onChange, s
|
|
|
31
31
|
setTimeout(() => {
|
|
32
32
|
document.activeElement.blur();
|
|
33
33
|
}, 0);
|
|
34
|
-
}, onChange: handleChange, error: !!error, open:
|
|
35
|
-
// eslint-disable-next-line no-nested-ternary
|
|
36
|
-
typeof otherProps.open !== 'undefined'
|
|
34
|
+
}, onChange: handleChange, error: !!error, open: typeof otherProps.open !== 'undefined'
|
|
37
35
|
? otherProps.open
|
|
38
36
|
: otherProps.disabled
|
|
39
37
|
? false
|
|
@@ -13,9 +13,7 @@ const IconDropdown = ({ open, disabled, children, ...otherProps }) => {
|
|
|
13
13
|
cursor: 'pointer',
|
|
14
14
|
transform: 'scaleY(-1)',
|
|
15
15
|
}
|
|
16
|
-
: undefined })), open:
|
|
17
|
-
// eslint-disable-next-line no-nested-ternary
|
|
18
|
-
typeof open !== 'undefined' ? open : disabled ? false : isOpen, disabled: disabled, multiple: false, onClick: () => {
|
|
16
|
+
: undefined })), open: typeof open !== 'undefined' ? open : disabled ? false : isOpen, disabled: disabled, multiple: false, onClick: () => {
|
|
19
17
|
if (!disabled)
|
|
20
18
|
setOpen(!isOpen);
|
|
21
19
|
}, MenuProps: {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
3
2
|
import { Player } from '@lottiefiles/react-lottie-player';
|
|
4
3
|
import { LoadingOverlay, LoadingIndicatorBox, LoadingMessage, LoadingDetails, } from './LoadingIndicator.styled';
|
|
5
4
|
const DotLoadingAnimation = require('./assets/DotLoadingAnimation.json');
|
|
@@ -12,11 +12,11 @@ const NoMatchContainer = () => {
|
|
|
12
12
|
flexDirection: 'column',
|
|
13
13
|
alignItems: 'center',
|
|
14
14
|
}, children: [_jsx(Typography, { variant: "h7", sx: {
|
|
15
|
-
color:
|
|
15
|
+
color: 'neutralGrey.25',
|
|
16
16
|
mt: '100px',
|
|
17
|
-
mb: '16px'
|
|
17
|
+
mb: '16px',
|
|
18
18
|
}, children: "Nothing matches your search" }), _jsx(Typography, { variant: "h9", sx: {
|
|
19
|
-
color:
|
|
19
|
+
color: 'neutralGrey.25',
|
|
20
20
|
}, children: "Please try again!" })] }) }));
|
|
21
21
|
};
|
|
22
22
|
export default NoMatchContainer;
|
|
@@ -26,9 +26,7 @@ const BaseTextInput = styled('input', {
|
|
|
26
26
|
})(({ theme, large, error, leftIcon, width, type }) => {
|
|
27
27
|
let resultStyle = {
|
|
28
28
|
...baseTextInputStyle(theme),
|
|
29
|
-
width:
|
|
30
|
-
// eslint-disable-next-line no-nested-ternary
|
|
31
|
-
typeof width !== 'undefined' ? (typeof width === 'number' ? `${width}px` : width) : width,
|
|
29
|
+
width: typeof width !== 'undefined' ? (typeof width === 'number' ? `${width}px` : width) : width,
|
|
32
30
|
};
|
|
33
31
|
if (error) {
|
|
34
32
|
resultStyle = {
|
|
@@ -64,9 +62,7 @@ const FileInputLabel = styled('label', {
|
|
|
64
62
|
})(({ theme, large, error, leftIcon, width, disabled, readOnly }) => {
|
|
65
63
|
let resultStyle = {
|
|
66
64
|
...baseTextInputStyle(theme),
|
|
67
|
-
width:
|
|
68
|
-
// eslint-disable-next-line no-nested-ternary
|
|
69
|
-
typeof width !== 'undefined' ? (typeof width === 'number' ? `${width}px` : width) : width,
|
|
65
|
+
width: typeof width !== 'undefined' ? (typeof width === 'number' ? `${width}px` : width) : width,
|
|
70
66
|
};
|
|
71
67
|
if (error) {
|
|
72
68
|
resultStyle = {
|
|
@@ -7,13 +7,18 @@ const Toggle = ({ value, name, checked, defaultChecked, disabled, required, onCh
|
|
|
7
7
|
return (_jsxs(Container, { ...rootProps, className: clsx('toggle', { 'is-disabled': disabled }, rootProps.className), component: label != null ? 'label' : 'span', children: [_jsx(ToggleComponent, { disableRipple: true, value: true, name: name,
|
|
8
8
|
// indeterminate가 true인 Toggle을 클릭했을 때
|
|
9
9
|
// 발생하는 change event target의 checked property의 일관성을 보장함
|
|
10
|
-
checked: indeterminate ? true : checked, defaultChecked: defaultChecked, disabled: disabled, required: required, onChange: onChange, onChangeCapture: onChangeCapture, slotProps: { input: { ...inputProps, ref: inputRef } }, focusRipple: false, toggleColor: toggleColor }), label && (_jsx(Typography, { variant: "body_m1", sx: [
|
|
10
|
+
checked: indeterminate ? true : checked, defaultChecked: defaultChecked, disabled: disabled, required: required, onChange: onChange, onChangeCapture: onChangeCapture, slotProps: { input: { ...inputProps, ref: inputRef } }, focusRipple: false, toggleColor: toggleColor }), label && (_jsx(Typography, { variant: "body_m1", sx: [
|
|
11
|
+
{
|
|
11
12
|
display: 'flex',
|
|
12
|
-
alignItems: 'center'
|
|
13
|
-
},
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
alignItems: 'center',
|
|
14
|
+
},
|
|
15
|
+
labelPlacement === 'left'
|
|
16
|
+
? {
|
|
17
|
+
order: -1,
|
|
18
|
+
}
|
|
19
|
+
: {
|
|
20
|
+
order: 1,
|
|
21
|
+
},
|
|
22
|
+
], children: label }))] }));
|
|
18
23
|
};
|
|
19
24
|
export default Toggle;
|
|
@@ -83,10 +83,14 @@ const UploadManager = ({ title, subTitle, files, onClose, onCancel, onRetry, })
|
|
|
83
83
|
bottom: '20px',
|
|
84
84
|
right: '20px',
|
|
85
85
|
zIndex: 10,
|
|
86
|
-
}, children: _jsxs(StyledPaper, { elevation: 1, children: [_jsxs(StyledToolbar, { children: [_jsx(Typography, { variant: "h9", children: title }), _jsx(Typography, { variant: "body1", sx: { marginLeft: '8px' }, children: subTitle }), _jsxs(StyledToolbarButtonContainer, { children: [_jsx(Tooltip, { title: expanded ? 'Minimize' : 'Maximize', children: _jsx(Box, { children: _jsx(Button, { onClick: handleExpandClick, variant: "ghost", color: "secondary", icon: _jsx(ArrowUp, { style: { color: theme.palette.neutralGrey[40] } }), size: "small", sx: [
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
86
|
+
}, children: _jsxs(StyledPaper, { elevation: 1, children: [_jsxs(StyledToolbar, { children: [_jsx(Typography, { variant: "h9", children: title }), _jsx(Typography, { variant: "body1", sx: { marginLeft: '8px' }, children: subTitle }), _jsxs(StyledToolbarButtonContainer, { children: [_jsx(Tooltip, { title: expanded ? 'Minimize' : 'Maximize', children: _jsx(Box, { children: _jsx(Button, { onClick: handleExpandClick, variant: "ghost", color: "secondary", icon: _jsx(ArrowUp, { style: { color: theme.palette.neutralGrey[40] } }), size: "small", sx: [
|
|
87
|
+
expanded
|
|
88
|
+
? {
|
|
89
|
+
transform: 'rotate(0deg)',
|
|
90
|
+
}
|
|
91
|
+
: {
|
|
92
|
+
transform: 'rotate(180deg)',
|
|
93
|
+
},
|
|
94
|
+
] }) }) }), _jsx(Tooltip, { title: "Close", children: _jsx(Box, { children: _jsx(Button, { onClick: onClose, variant: "ghost", color: "secondary", icon: _jsx(Close, { style: { color: theme.palette.neutralGrey[40] } }), size: "small" }) }) })] })] }), expanded && _jsx(Divider, { orientation: "horizontal" }), _jsx(StyledCollapse, { in: expanded, timeout: "auto", unmountOnExit: true, children: files.map((download, index) => (_jsxs(Fragment, { children: [_jsx(UploadFile, { file: download, onCancel: onCancel, onRetry: onRetry }), index !== files.length - 1 && _jsx(Divider, { orientation: "horizontal" })] }, download.id))) })] }) }));
|
|
91
95
|
};
|
|
92
96
|
export default UploadManager;
|
|
@@ -52,13 +52,18 @@ export const GraphScoreIndicator = ({ value, isCutoff, isJet, }) => {
|
|
|
52
52
|
leftPos = '20px';
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
|
-
return (_jsxs(GraphScoreIndicatorContainer, { className: "analysis-bar-score-indicator", sx: [
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
55
|
+
return (_jsxs(GraphScoreIndicatorContainer, { className: "analysis-bar-score-indicator", sx: [
|
|
56
|
+
{
|
|
57
|
+
left: leftPos,
|
|
58
|
+
},
|
|
59
|
+
isJet
|
|
60
|
+
? {
|
|
61
|
+
transform: 'translateX(-50%) translateY(8px)',
|
|
62
|
+
}
|
|
63
|
+
: {
|
|
64
|
+
transform: 'translateX(-50%)',
|
|
65
|
+
},
|
|
66
|
+
], isJet: isJet, children: [_jsx(Typography, { variant: "small_body_sb1", sx: { textAlign: 'center' }, children: value }), _jsx(GraphScoreIndicatorPip, {})] }));
|
|
62
67
|
};
|
|
63
68
|
const GraphAxisLabelContainer = styled('span')(() => {
|
|
64
69
|
return {
|
|
@@ -7,26 +7,41 @@ const FreeText = ({ componentType = 'freeText', size = 'medium', content, height
|
|
|
7
7
|
throw new Error("The 'componentType' prop is required.");
|
|
8
8
|
if (!content)
|
|
9
9
|
throw new Error("The 'content' prop is required.");
|
|
10
|
-
return (_jsx(Box, { sx: [
|
|
10
|
+
return (_jsx(Box, { sx: [
|
|
11
|
+
{
|
|
11
12
|
display: 'flex',
|
|
12
|
-
overflowY: 'auto'
|
|
13
|
-
},
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
13
|
+
overflowY: 'auto',
|
|
14
|
+
},
|
|
15
|
+
background
|
|
16
|
+
? {
|
|
17
|
+
padding: '8px 6px 8px 16px',
|
|
18
|
+
}
|
|
19
|
+
: {
|
|
20
|
+
padding: 0,
|
|
21
|
+
},
|
|
22
|
+
background
|
|
23
|
+
? {
|
|
24
|
+
borderRadius: '8px',
|
|
25
|
+
}
|
|
26
|
+
: {
|
|
27
|
+
borderRadius: 0,
|
|
28
|
+
},
|
|
29
|
+
background
|
|
30
|
+
? {
|
|
31
|
+
backgroundColor: theme.palette.neutralGrey[75],
|
|
32
|
+
}
|
|
33
|
+
: {
|
|
34
|
+
backgroundColor: 'transparent',
|
|
35
|
+
},
|
|
36
|
+
height
|
|
37
|
+
? {
|
|
38
|
+
height: height,
|
|
39
|
+
}
|
|
40
|
+
: {
|
|
41
|
+
height: 'auto',
|
|
42
|
+
},
|
|
43
|
+
], children: _jsx(PresentationTypography, { size: size, sx: [
|
|
44
|
+
{
|
|
30
45
|
display: 'block',
|
|
31
46
|
whiteSpace: 'pre-wrap',
|
|
32
47
|
overflow: 'auto',
|
|
@@ -37,15 +52,22 @@ const FreeText = ({ componentType = 'freeText', size = 'medium', content, height
|
|
|
37
52
|
width: '6px',
|
|
38
53
|
backgroundColor: theme.palette.neutralGrey[65],
|
|
39
54
|
borderRadius: '6px',
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
background
|
|
58
|
+
? {
|
|
59
|
+
color: '#FFFFFF',
|
|
60
|
+
}
|
|
61
|
+
: {
|
|
62
|
+
color: 'inherit',
|
|
63
|
+
},
|
|
64
|
+
height
|
|
65
|
+
? {
|
|
66
|
+
height: '100%',
|
|
40
67
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}, height ? {
|
|
46
|
-
height: '100%'
|
|
47
|
-
} : {
|
|
48
|
-
height: 'auto'
|
|
49
|
-
}], children: content }) }));
|
|
68
|
+
: {
|
|
69
|
+
height: 'auto',
|
|
70
|
+
},
|
|
71
|
+
], children: content }) }));
|
|
50
72
|
};
|
|
51
73
|
export default FreeText;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { Divider } from '../../components';
|
|
2
|
+
import { Divider } from '../../components/Divider';
|
|
3
3
|
const HorizonDivider = ({ componentType = 'divider' }) => {
|
|
4
4
|
if (!componentType)
|
|
5
5
|
throw new Error("The 'componentType' prop is required.");
|
|
@@ -6,25 +6,27 @@ import { BaseSlider, Container } from './Threshold.styled';
|
|
|
6
6
|
import { Score } from '../Score';
|
|
7
7
|
import { Statistic } from '../Statistic';
|
|
8
8
|
import { PresentationTypography } from '../presentations.styled';
|
|
9
|
-
import { Button
|
|
9
|
+
import { Button } from '../../components/Button';
|
|
10
|
+
import { Dropdown, DropdownItem } from '../../components/Dropdown';
|
|
10
11
|
import { HorizonDivider } from '../HorizonDivider';
|
|
11
12
|
import { FreeText } from '../FreeText';
|
|
12
|
-
import { baseSliderMarks,
|
|
13
|
-
const Threshold = ({ componentType = 'threshold', title, totalScore, totalCells, statisticItems, options, description, controlStep = 1, isLoading = false, thresholdState, onChangeDropdown, onChangeSlider, onSliderChangeCommitted, onClickUpdateConfiguration, }) => {
|
|
13
|
+
import { NO_LABEL_ONLY_MARK, baseSliderMarks, getLabelOnlyMarkIndex, getSliderMarks, } from './Threshold.utils';
|
|
14
|
+
const Threshold = ({ componentType = 'threshold', title, totalScore, totalCells, statisticItems, options, description, controlStep = 1, showDefaultMark = false, isLoading = false, thresholdState, onChangeDropdown, onChangeSlider, onSliderChangeCommitted, onClickUpdateConfiguration, }) => {
|
|
14
15
|
if (!componentType)
|
|
15
16
|
throw new Error("The 'componentType' prop is required.");
|
|
16
|
-
if (!totalScore)
|
|
17
|
-
throw new Error("The 'totalScore' prop is required.");
|
|
18
17
|
if (!statisticItems.length)
|
|
19
18
|
throw new Error("The 'statisticItems' prop must contain at least one item.");
|
|
20
19
|
if (!options.length)
|
|
21
20
|
throw new Error("The 'options' prop must contain at least one item.");
|
|
22
21
|
const [isThresholdChanged, setIsThresholdChanged] = useState(false);
|
|
23
22
|
const selectedOptionValue = useMemo(() => {
|
|
24
|
-
return (options.find((option) => option.title === thresholdState?.selectedItem)?.value
|
|
23
|
+
return (options.find((option) => option.title === thresholdState?.selectedItem)?.value ??
|
|
25
24
|
options[0].value);
|
|
26
25
|
}, [options, thresholdState?.selectedItem]);
|
|
27
|
-
const
|
|
26
|
+
const sliderMarks = useMemo(() => (showDefaultMark ? getSliderMarks(selectedOptionValue) : baseSliderMarks), [showDefaultMark, selectedOptionValue]);
|
|
27
|
+
const labelOnlyMarkIndex = useMemo(() => showDefaultMark
|
|
28
|
+
? getLabelOnlyMarkIndex(sliderMarks, selectedOptionValue)
|
|
29
|
+
: NO_LABEL_ONLY_MARK, [showDefaultMark, sliderMarks, selectedOptionValue]);
|
|
28
30
|
const handleDropdownChange = useCallback((event) => {
|
|
29
31
|
onChangeDropdown(event);
|
|
30
32
|
setIsThresholdChanged(false);
|
|
@@ -37,11 +39,11 @@ const Threshold = ({ componentType = 'threshold', title, totalScore, totalCells,
|
|
|
37
39
|
onClickUpdateConfiguration();
|
|
38
40
|
setIsThresholdChanged(false);
|
|
39
41
|
}, [onClickUpdateConfiguration]);
|
|
40
|
-
return (_jsxs(Container, { children: [_jsx(Score, { ...totalScore }), _jsx(Statistic, { ...totalCells }), statisticItems.map((item) => {
|
|
42
|
+
return (_jsxs(Container, { children: [totalScore && _jsx(Score, { ...totalScore }), _jsx(Statistic, { ...totalCells }), statisticItems.map((item) => {
|
|
41
43
|
return (_jsx(Statistic, { ...item }, uuidV4()));
|
|
42
44
|
}), _jsx(HorizonDivider, { componentType: "divider" }), _jsx(PresentationTypography, { size: "medium", children: title }), _jsx(Dropdown, { value: thresholdState?.selectedItem, onChange: handleDropdownChange, sx: { width: '258px' }, children: options.map((option) => {
|
|
43
45
|
return (_jsx(DropdownItem, { value: option.title, children: option.title }, option.title));
|
|
44
|
-
}) }), _jsxs(Box, { sx: { display: 'flex', flexDirection: 'column', paddingTop: '36px', gap: '6px' }, children: [_jsx(BaseSlider, { disabled: thresholdState?.isPresetSelected, step: controlStep, value: thresholdState?.sliderValue, valueLabelDisplay: "on",
|
|
46
|
+
}) }), _jsxs(Box, { sx: { display: 'flex', flexDirection: 'column', paddingTop: '36px', gap: '6px' }, children: [_jsx(BaseSlider, { disabled: thresholdState?.isPresetSelected, step: controlStep, value: thresholdState?.sliderValue, valueLabelDisplay: "on", marks: sliderMarks, labelOnlyMarkIndex: labelOnlyMarkIndex, onChange: handleSliderChange, onChangeCommitted: onSliderChangeCommitted }), !thresholdState?.isPresetSelected && (_jsx(Button, { id: "update-threshold-config-btn", label: "Update Configuration", sx: {
|
|
45
47
|
width: '100%',
|
|
46
48
|
}, disabled: !isThresholdChanged || isLoading, onClick: handleUpdateConfiguration, loading: isLoading })), thresholdState?.isPresetSelected && description?.preset && (_jsx(FreeText, { componentType: "freeText", size: "small-dimmed", content: description.preset })), !thresholdState?.isPresetSelected && description?.user && (_jsx(FreeText, { componentType: "freeText", size: "small-dimmed", content: description.user }))] })] }));
|
|
47
49
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Box, Slider, styled } from '@mui/material';
|
|
2
|
+
import { NO_LABEL_ONLY_MARK } from './Threshold.utils';
|
|
2
3
|
import theme from '../../theme';
|
|
3
4
|
export const Container = styled(Box)({
|
|
4
5
|
display: 'flex',
|
|
@@ -6,67 +7,64 @@ export const Container = styled(Box)({
|
|
|
6
7
|
gap: '12px',
|
|
7
8
|
});
|
|
8
9
|
export const BaseSlider = styled(Slider, {
|
|
9
|
-
shouldForwardProp: (prop) => prop !== '
|
|
10
|
-
})(({
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
10
|
+
shouldForwardProp: (prop) => prop !== 'labelOnlyMarkIndex',
|
|
11
|
+
})(({ disabled, labelOnlyMarkIndex = NO_LABEL_ONLY_MARK }) => ({
|
|
12
|
+
'& .MuiSlider-rail': {
|
|
13
|
+
background: theme.palette.neutralGrey[75],
|
|
14
|
+
height: '8px',
|
|
15
|
+
},
|
|
16
|
+
'& .MuiSlider-track': {
|
|
17
|
+
display: 'none',
|
|
18
|
+
},
|
|
19
|
+
'& .MuiSlider-thumb': {
|
|
20
|
+
background: theme.palette.neutralGrey[0],
|
|
21
|
+
'&:hover': {
|
|
22
|
+
boxShadow: `0px 0px 0px 8px rgba(255, 0, 0, 0.2)`,
|
|
21
23
|
},
|
|
22
|
-
'
|
|
23
|
-
|
|
24
|
+
'&.Mui-focusVisible': {
|
|
25
|
+
boxShadow: `0px 0px 0px 8px rgba(255, 0, 0, 0.2)`,
|
|
24
26
|
},
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
},
|
|
28
|
+
'& .MuiSlider-mark': {
|
|
29
|
+
background: theme.palette.neutralGrey[40],
|
|
30
|
+
height: '6px',
|
|
31
|
+
width: '6px',
|
|
32
|
+
borderRadius: '50%',
|
|
33
|
+
},
|
|
34
|
+
'& .MuiSlider-markLabel': {
|
|
35
|
+
fontFamily: 'Pretendard,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"',
|
|
36
|
+
fontSize: '8px',
|
|
37
|
+
fontStyle: 'normal',
|
|
38
|
+
fontWeight: '500',
|
|
39
|
+
lineHeight: '12px',
|
|
40
|
+
},
|
|
41
|
+
'& .MuiSlider-valueLabel': {
|
|
42
|
+
fontFamily: 'Pretendard,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"',
|
|
43
|
+
fontSize: '12px',
|
|
44
|
+
fontWeight: '700',
|
|
45
|
+
lineHeight: '16px',
|
|
46
|
+
background: 'unset',
|
|
47
|
+
padding: 0,
|
|
48
|
+
width: 32,
|
|
49
|
+
height: 32,
|
|
50
|
+
borderRadius: '50% 50% 50% 0',
|
|
51
|
+
backgroundColor: disabled ? theme.palette.neutralGrey[60] : theme.palette.lunitTeal[40],
|
|
52
|
+
transformOrigin: 'bottom left',
|
|
53
|
+
transform: 'translate(50%, -100%) rotate(-45deg) scale(0)',
|
|
54
|
+
'&:before': { display: 'none' },
|
|
55
|
+
'&.MuiSlider-valueLabelOpen': {
|
|
56
|
+
transform: 'translate(50%, -100%) rotate(-45deg) scale(1)',
|
|
33
57
|
},
|
|
34
|
-
'&
|
|
35
|
-
|
|
36
|
-
height: '6px',
|
|
37
|
-
width: '6px',
|
|
38
|
-
borderRadius: '50%',
|
|
58
|
+
'& > *': {
|
|
59
|
+
transform: 'rotate(45deg)',
|
|
39
60
|
},
|
|
40
|
-
'
|
|
41
|
-
|
|
42
|
-
fontSize: '8px',
|
|
43
|
-
fontStyle: 'normal',
|
|
44
|
-
fontWeight: '500',
|
|
45
|
-
lineHeight: '12px',
|
|
61
|
+
'&.Mui-disabled': {
|
|
62
|
+
visibility: 'visible',
|
|
46
63
|
},
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
lineHeight: '16px',
|
|
52
|
-
background: 'unset',
|
|
53
|
-
padding: 0,
|
|
54
|
-
width: 32,
|
|
55
|
-
height: 32,
|
|
56
|
-
borderRadius: '50% 50% 50% 0',
|
|
57
|
-
backgroundColor: disabled ? theme.palette.neutralGrey[60] : theme.palette.lunitTeal[40],
|
|
58
|
-
transformOrigin: 'bottom left',
|
|
59
|
-
transform: 'translate(50%, -100%) rotate(-45deg) scale(0)',
|
|
60
|
-
'&:before': { display: 'none' },
|
|
61
|
-
'&.MuiSlider-valueLabelOpen': {
|
|
62
|
-
transform: 'translate(50%, -100%) rotate(-45deg) scale(1)',
|
|
63
|
-
},
|
|
64
|
-
'& > *': {
|
|
65
|
-
transform: 'rotate(45deg)',
|
|
66
|
-
},
|
|
67
|
-
'&.Mui-disabled': {
|
|
68
|
-
visibility: 'visible',
|
|
69
|
-
},
|
|
64
|
+
},
|
|
65
|
+
...(labelOnlyMarkIndex > NO_LABEL_ONLY_MARK && {
|
|
66
|
+
[`& .MuiSlider-mark[data-index="${labelOnlyMarkIndex}"]`]: {
|
|
67
|
+
display: 'none',
|
|
70
68
|
},
|
|
71
|
-
}
|
|
72
|
-
});
|
|
69
|
+
}),
|
|
70
|
+
}));
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const DEFAULT_MARK_LABEL_PREFIX = 'Default: ';
|
|
2
|
+
export const NO_LABEL_ONLY_MARK = -1;
|
|
1
3
|
export const baseSliderMarks = [
|
|
2
4
|
{ value: 0, label: '0' },
|
|
3
5
|
{ value: 10 },
|
|
@@ -11,24 +13,31 @@ export const baseSliderMarks = [
|
|
|
11
13
|
{ value: 90 },
|
|
12
14
|
{ value: 100, label: '100' },
|
|
13
15
|
];
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Builds the slider marks with the default threshold labelled.
|
|
18
|
+
*
|
|
19
|
+
* @param defaultThreshold - Default threshold of the selected option
|
|
20
|
+
* @returns Marks ordered by value, including an extra mark when the default sits between intervals
|
|
21
|
+
*/
|
|
22
|
+
export const getSliderMarks = (defaultThreshold) => {
|
|
23
|
+
const defaultLabel = `${DEFAULT_MARK_LABEL_PREFIX}${defaultThreshold}`;
|
|
24
|
+
const marks = baseSliderMarks.map((mark) => mark.value === defaultThreshold ? { ...mark, label: defaultLabel } : mark);
|
|
25
|
+
if (baseSliderMarks.some((mark) => mark.value === defaultThreshold))
|
|
26
|
+
return marks;
|
|
27
|
+
const insertIndex = marks.findIndex((mark) => mark.value > defaultThreshold);
|
|
28
|
+
marks.splice(insertIndex < 0 ? marks.length : insertIndex, 0, {
|
|
29
|
+
value: defaultThreshold,
|
|
30
|
+
label: defaultLabel,
|
|
28
31
|
});
|
|
29
|
-
if (!baseSliderMarks.find((mark) => mark.value === presetValue)) {
|
|
30
|
-
const index = Math.floor(presetValue / 10);
|
|
31
|
-
marks.splice(index + 1, 0, { value: presetValue, label: `Preset: ${presetValue}` });
|
|
32
|
-
}
|
|
33
32
|
return marks;
|
|
34
33
|
};
|
|
34
|
+
/**
|
|
35
|
+
* Finds the mark that exists only to label the default threshold.
|
|
36
|
+
*
|
|
37
|
+
* @param marks - Marks built by `getSliderMarks`
|
|
38
|
+
* @param defaultThreshold - Default threshold of the selected option
|
|
39
|
+
* @returns Index of the mark whose dot should stay hidden, or `-1` when the default sits on an interval
|
|
40
|
+
*/
|
|
41
|
+
export const getLabelOnlyMarkIndex = (marks, defaultThreshold) => baseSliderMarks.some((mark) => mark.value === defaultThreshold)
|
|
42
|
+
? NO_LABEL_ONLY_MARK
|
|
43
|
+
: marks.findIndex((mark) => mark.value === defaultThreshold);
|
|
@@ -2,10 +2,10 @@ import { ReactNode } from 'react';
|
|
|
2
2
|
import type { TooltipClasses, TooltipProps as MuiTooltipProps } from '@mui/material';
|
|
3
3
|
export type Position = Pick<TooltipProps, 'placement'>;
|
|
4
4
|
export type TooltipSizes = 'small' | 'large';
|
|
5
|
-
export
|
|
5
|
+
export interface TooltipSize {
|
|
6
6
|
width: number;
|
|
7
7
|
height: number;
|
|
8
|
-
}
|
|
8
|
+
}
|
|
9
9
|
export type TooltipPlacement = TooltipClasses['tooltipPlacementBottom'] | TooltipClasses['tooltipPlacementLeft'] | TooltipClasses['tooltipPlacementRight'] | TooltipClasses['tooltipPlacementTop'];
|
|
10
10
|
export type ArrowSizeBySize = Record<TooltipSizes, TooltipSize>;
|
|
11
11
|
export type TooltipPlacementToSize = Record<TooltipPlacement, ArrowSizeBySize>;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { ThresholdProps } from './Threshold.types';
|
|
2
|
-
declare const Threshold: ({ componentType, title, totalScore, totalCells, statisticItems, options, description, controlStep, isLoading, thresholdState, onChangeDropdown, onChangeSlider, onSliderChangeCommitted, onClickUpdateConfiguration, }: ThresholdProps) => import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
declare const Threshold: ({ componentType, title, totalScore, totalCells, statisticItems, options, description, controlStep, showDefaultMark, isLoading, thresholdState, onChangeDropdown, onChangeSlider, onSliderChangeCommitted, onClickUpdateConfiguration, }: ThresholdProps) => import("react/jsx-runtime").JSX.Element;
|
|
3
3
|
export default Threshold;
|
|
@@ -9,18 +9,29 @@ export interface ThresholdOption {
|
|
|
9
9
|
value: number;
|
|
10
10
|
isPreset?: boolean;
|
|
11
11
|
}
|
|
12
|
+
export interface ThresholdMark {
|
|
13
|
+
/** Position of the mark on the 0-100 intensity scale */
|
|
14
|
+
value: number;
|
|
15
|
+
/** Text rendered under the mark; marks without a label render as a dot only */
|
|
16
|
+
label?: string;
|
|
17
|
+
}
|
|
12
18
|
export interface ThresholdSpec {
|
|
13
19
|
componentType: 'threshold';
|
|
14
|
-
|
|
20
|
+
/** Overall score summary shown above the cell statistics; omitted when the analysis has no score */
|
|
21
|
+
totalScore?: ScoreProps;
|
|
15
22
|
totalCells: StatisticProps;
|
|
16
23
|
statisticItems: StatisticProps[];
|
|
17
24
|
title?: string;
|
|
18
25
|
description?: {
|
|
19
|
-
preset
|
|
20
|
-
|
|
26
|
+
/** Guidance shown while a preset option is selected */
|
|
27
|
+
preset?: string;
|
|
28
|
+
/** Guidance shown while a user-adjustable option is selected */
|
|
29
|
+
user?: string;
|
|
21
30
|
};
|
|
22
31
|
options: ThresholdOption[];
|
|
23
32
|
controlStep?: number;
|
|
33
|
+
/** Labels the selected option's threshold on the slider, e.g. `Default: 40`; off by default */
|
|
34
|
+
showDefaultMark?: boolean;
|
|
24
35
|
}
|
|
25
36
|
export interface ThresholdProps extends ThresholdSpec {
|
|
26
37
|
thresholdState?: {
|
|
@@ -35,5 +46,6 @@ export interface ThresholdProps extends ThresholdSpec {
|
|
|
35
46
|
isLoading?: boolean;
|
|
36
47
|
}
|
|
37
48
|
export interface BaseSliderProps extends SliderProps {
|
|
38
|
-
|
|
49
|
+
/** Index of the mark that renders its label without a dot; `-1` hides nothing */
|
|
50
|
+
labelOnlyMarkIndex?: number;
|
|
39
51
|
}
|
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
export declare const getSliderMarks: (
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
import { ThresholdMark } from './Threshold.types';
|
|
2
|
+
export declare const NO_LABEL_ONLY_MARK = -1;
|
|
3
|
+
export declare const baseSliderMarks: ThresholdMark[];
|
|
4
|
+
/**
|
|
5
|
+
* Builds the slider marks with the default threshold labelled.
|
|
6
|
+
*
|
|
7
|
+
* @param defaultThreshold - Default threshold of the selected option
|
|
8
|
+
* @returns Marks ordered by value, including an extra mark when the default sits between intervals
|
|
9
|
+
*/
|
|
10
|
+
export declare const getSliderMarks: (defaultThreshold: number) => ThresholdMark[];
|
|
11
|
+
/**
|
|
12
|
+
* Finds the mark that exists only to label the default threshold.
|
|
13
|
+
*
|
|
14
|
+
* @param marks - Marks built by `getSliderMarks`
|
|
15
|
+
* @param defaultThreshold - Default threshold of the selected option
|
|
16
|
+
* @returns Index of the mark whose dot should stay hidden, or `-1` when the default sits on an interval
|
|
17
|
+
*/
|
|
18
|
+
export declare const getLabelOnlyMarkIndex: (marks: ThresholdMark[], defaultThreshold: number) => number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunit/oui",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"validate-branch-name": {
|
|
5
5
|
"pattern": "^(main|develop)|(feature|fix|release|hotfix|qe)/.+$",
|
|
6
6
|
"errorMsg": "The branch name is not correct. Please check the pattern. (ex. feature/add-something)"
|
|
@@ -8,14 +8,25 @@
|
|
|
8
8
|
"peerDependencies": {
|
|
9
9
|
"@emotion/react": "^11.11.1",
|
|
10
10
|
"@emotion/styled": "^11.11.0",
|
|
11
|
+
"@lottiefiles/react-lottie-player": "^3.5.3",
|
|
11
12
|
"@mui/icons-material": "^9.0.0",
|
|
12
13
|
"@mui/lab": "^9.0.0",
|
|
13
14
|
"@mui/material": "^9.0.0",
|
|
14
15
|
"@mui/system": "^9.0.0",
|
|
16
|
+
"@mui/x-data-grid": "^9.0.0",
|
|
17
|
+
"@mui/x-data-grid-pro": "^9.0.0",
|
|
15
18
|
"@mui/x-date-pickers": "^9.0.0",
|
|
16
19
|
"react": "^18.2.0",
|
|
17
20
|
"react-dom": "^18.2.0"
|
|
18
21
|
},
|
|
22
|
+
"peerDependenciesMeta": {
|
|
23
|
+
"@lottiefiles/react-lottie-player": {
|
|
24
|
+
"optional": true
|
|
25
|
+
},
|
|
26
|
+
"@mui/x-data-grid-pro": {
|
|
27
|
+
"optional": true
|
|
28
|
+
}
|
|
29
|
+
},
|
|
19
30
|
"dependencies": {
|
|
20
31
|
"@date-io/date-fns": "^3.2.1",
|
|
21
32
|
"@lunit/design-system-icons": "2.1.0",
|
|
@@ -31,6 +42,7 @@
|
|
|
31
42
|
},
|
|
32
43
|
"scripts": {
|
|
33
44
|
"prettier": "prettier --write \"src/**/*.{js,jsx,ts,tsx,json,css,md}\"",
|
|
45
|
+
"test": "jest",
|
|
34
46
|
"build": "npm run build:transpile",
|
|
35
47
|
"build:transpile": "tsc -p tsconfig.build.json",
|
|
36
48
|
"build:cjs": "NODE_ENV=production webpack -c config/cjs.config.js",
|
|
@@ -82,7 +94,7 @@
|
|
|
82
94
|
"^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
|
|
83
95
|
},
|
|
84
96
|
"transformIgnorePatterns": [
|
|
85
|
-
"[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|cjs|ts|tsx)$",
|
|
97
|
+
"[/\\\\]node_modules[/\\\\](?!uuid[/\\\\]).+\\.(js|jsx|mjs|cjs|ts|tsx)$",
|
|
86
98
|
"^.+\\.module\\.(css|sass|scss)$"
|
|
87
99
|
],
|
|
88
100
|
"modulePaths": [],
|
|
@@ -120,7 +132,7 @@
|
|
|
120
132
|
"@emotion/react": "11.11.1",
|
|
121
133
|
"@emotion/styled": "11.11.0",
|
|
122
134
|
"@lottiefiles/react-lottie-player": "^3.5.3",
|
|
123
|
-
"@lunit/eslint-config": "^2.0.
|
|
135
|
+
"@lunit/eslint-config": "^2.0.1",
|
|
124
136
|
"@mui/icons-material": "9.1.0",
|
|
125
137
|
"@mui/lab": "9.0.0-beta.3",
|
|
126
138
|
"@mui/material": "9.1.0",
|
|
@@ -164,7 +176,7 @@
|
|
|
164
176
|
"css-minimizer-webpack-plugin": "^8.0.0",
|
|
165
177
|
"dotenv": "^10.0.0",
|
|
166
178
|
"dotenv-expand": "^5.1.0",
|
|
167
|
-
"eslint": "^
|
|
179
|
+
"eslint": "^9.39.5",
|
|
168
180
|
"eslint-config-prettier": "^9.1.0",
|
|
169
181
|
"eslint-config-react-app": "^7.0.1",
|
|
170
182
|
"eslint-plugin-prettier": "^5.1.0",
|
|
@@ -176,6 +188,7 @@
|
|
|
176
188
|
"husky": "^8.0.0",
|
|
177
189
|
"identity-obj-proxy": "^3.0.0",
|
|
178
190
|
"jest": "^30.3.0",
|
|
191
|
+
"jest-environment-jsdom": "^30.4.1",
|
|
179
192
|
"jest-resolve": "^27.4.2",
|
|
180
193
|
"jest-watch-typeahead": "^1.0.0",
|
|
181
194
|
"lint-staged": "^15.2.0",
|