cloudmr-ux 0.0.1

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.
Files changed (60) hide show
  1. package/README.md +30 -0
  2. package/dist/index.css +17 -0
  3. package/dist/index.js +174 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/index.modern.js +167 -0
  6. package/dist/index.modern.js.map +1 -0
  7. package/package.json +99 -0
  8. package/src/.eslintrc +5 -0
  9. package/src/common/components/Cmr-components/avatar/Avatar.scss +0 -0
  10. package/src/common/components/Cmr-components/avatar/Avatar.tsx +25 -0
  11. package/src/common/components/Cmr-components/button/Button.scss +0 -0
  12. package/src/common/components/Cmr-components/button/Button.tsx +14 -0
  13. package/src/common/components/Cmr-components/checkbox/Checkbox.scss +11 -0
  14. package/src/common/components/Cmr-components/checkbox/Checkbox.tsx +29 -0
  15. package/src/common/components/Cmr-components/collapse/Collapse.scss +3 -0
  16. package/src/common/components/Cmr-components/collapse/Collapse.tsx +75 -0
  17. package/src/common/components/Cmr-components/dialogue/Confirmation.tsx +48 -0
  18. package/src/common/components/Cmr-components/dialogue/DeletionDialog.tsx +61 -0
  19. package/src/common/components/Cmr-components/dialogue/EditConfirmation.tsx +72 -0
  20. package/src/common/components/Cmr-components/double-slider/DualSlider.tsx +198 -0
  21. package/src/common/components/Cmr-components/double-slider/InvertibleDualSlider.tsx +224 -0
  22. package/src/common/components/Cmr-components/dropdown/Dropdown.scss +36 -0
  23. package/src/common/components/Cmr-components/dropdown/Dropdown.tsx +83 -0
  24. package/src/common/components/Cmr-components/gui-slider/ControlledSlider.tsx +139 -0
  25. package/src/common/components/Cmr-components/gui-slider/Slider.tsx +170 -0
  26. package/src/common/components/Cmr-components/header/Header.scss +20 -0
  27. package/src/common/components/Cmr-components/header/Header.tsx +101 -0
  28. package/src/common/components/Cmr-components/input/Input.scss +0 -0
  29. package/src/common/components/Cmr-components/input/Input.tsx +39 -0
  30. package/src/common/components/Cmr-components/input-number/InputNumber.scss +0 -0
  31. package/src/common/components/Cmr-components/input-number/InputNumber.tsx +29 -0
  32. package/src/common/components/Cmr-components/label/Label.scss +13 -0
  33. package/src/common/components/Cmr-components/label/Label.tsx +20 -0
  34. package/src/common/components/Cmr-components/option/Option.scss +0 -0
  35. package/src/common/components/Cmr-components/option/Option.tsx +24 -0
  36. package/src/common/components/Cmr-components/panel/Panel.scss +0 -0
  37. package/src/common/components/Cmr-components/panel/Panel.tsx +54 -0
  38. package/src/common/components/Cmr-components/progress/Progress.scss +0 -0
  39. package/src/common/components/Cmr-components/progress/Progress.tsx +38 -0
  40. package/src/common/components/Cmr-components/radio/Radio.scss +0 -0
  41. package/src/common/components/Cmr-components/radio/Radio.tsx +23 -0
  42. package/src/common/components/Cmr-components/radio-group/RadioGroup.scss +0 -0
  43. package/src/common/components/Cmr-components/radio-group/RadioGroup.tsx +32 -0
  44. package/src/common/components/Cmr-components/rename/edit.tsx +94 -0
  45. package/src/common/components/Cmr-components/select/Select.scss +3 -0
  46. package/src/common/components/Cmr-components/select/Select.tsx +33 -0
  47. package/src/common/components/Cmr-components/select-upload/SelectUpload.scss +0 -0
  48. package/src/common/components/Cmr-components/select-upload/SelectUpload.tsx +133 -0
  49. package/src/common/components/Cmr-components/slider/Slider.scss +0 -0
  50. package/src/common/components/Cmr-components/slider/Slider.tsx +66 -0
  51. package/src/common/components/Cmr-components/spin/Spin.scss +0 -0
  52. package/src/common/components/Cmr-components/spin/Spin.tsx +31 -0
  53. package/src/common/components/Cmr-components/tooltip/Tooltip.scss +0 -0
  54. package/src/common/components/Cmr-components/tooltip/Tooltip.tsx +50 -0
  55. package/src/common/components/Cmr-components/upload/Upload.scss +5 -0
  56. package/src/common/components/Cmr-components/upload/Upload.tsx +188 -0
  57. package/src/common/components/Cmr-components/upload/UploadWindow.tsx +355 -0
  58. package/src/index.js +8 -0
  59. package/src/index.test.js +7 -0
  60. package/src/styles.module.css +9 -0
@@ -0,0 +1,75 @@
1
+ import React, {cloneElement} from 'react';
2
+ import { Collapse } from 'antd';
3
+ import { CollapsibleType } from 'antd/es/collapse/CollapsePanel';
4
+ import { ExpandIconPosition } from 'antd/es/collapse/Collapse';
5
+ import './Collapse.scss';
6
+
7
+ interface CmrCollapseProps {
8
+ accordion?: boolean;
9
+ activeKey?: Array<string | number>|number;
10
+ bordered?: boolean;
11
+ collapsible?: CollapsibleType;
12
+ defaultActiveKey?: Array<string | number>;
13
+ destroyInactivePanel?: boolean;
14
+ expandIconPosition?: ExpandIconPosition;
15
+ ghost?: boolean;
16
+ onChange?: (key:Array<string | number>|number) => void;
17
+ children?: JSX.Element[]|JSX.Element;
18
+ }
19
+
20
+ export const CmrCollapse = (props: CmrCollapseProps) => {
21
+ let {activeKey, defaultActiveKey, onChange, children}=props;
22
+ defaultActiveKey = (defaultActiveKey)?defaultActiveKey:[];
23
+ let [activeKeys, setActiveKeys] = React.useState(defaultActiveKey);
24
+ if(activeKey!=undefined&&activeKey!=activeKeys){
25
+ console.log(activeKey);
26
+ if(activeKey instanceof Array)
27
+ setActiveKeys(activeKey);
28
+ else setActiveKeys([activeKey]);
29
+ }
30
+ return (
31
+ <div className="cmr-collapse">
32
+ <div>
33
+ {(children&&Array.isArray(children))?children.map((child,index)=>{
34
+ let props = {expanded:activeKeys.indexOf(index)>=0,
35
+ panelKey: index,
36
+ onToggle: (key:number)=>{
37
+ let i = activeKeys.indexOf(key);
38
+ if(i<0) {
39
+ let newKeys = [...activeKeys];
40
+ newKeys.push(index);
41
+ setActiveKeys(newKeys);
42
+ if(onChange!=undefined)
43
+ onChange(newKeys);
44
+ }
45
+ else {
46
+ let newKeys = [...activeKeys];
47
+ newKeys.splice(i,1);
48
+ setActiveKeys(newKeys);
49
+ if(onChange!=undefined)
50
+ onChange(newKeys);
51
+ }
52
+ }};
53
+ return cloneElement(child, props)
54
+ }):((children?cloneElement(children,{expanded:activeKeys.indexOf(0)>=0,
55
+ panelKey: 0,
56
+ onToggle: (key:number)=>{
57
+ let i = activeKeys.indexOf(key);
58
+ if(i<0) {
59
+ let newKeys = [...activeKeys];
60
+ newKeys.push(0);
61
+ setActiveKeys(newKeys);
62
+ }
63
+ else {
64
+ let newKeys = [...activeKeys];
65
+ newKeys.splice(i,1);
66
+ setActiveKeys(newKeys);
67
+ }
68
+ if(onChange!=undefined)
69
+ onChange([0]);
70
+ }}):undefined))}
71
+ </div>
72
+ </div>
73
+ );
74
+ };
75
+
@@ -0,0 +1,48 @@
1
+ import * as React from 'react';
2
+ import TextField from '@mui/material/TextField';
3
+ import Dialog from '@mui/material/Dialog';
4
+ import DialogActions from '@mui/material/DialogActions';
5
+ import DialogContent from '@mui/material/DialogContent';
6
+ import DialogContentText from '@mui/material/DialogContentText';
7
+ import DialogTitle from '@mui/material/DialogTitle';
8
+ import CmrButton from '../button/Button';
9
+ import {StyledComponentProps} from "@mui/material";
10
+
11
+ export default function Confirmation({ name,message,cancelText='Cancel',
12
+ color, open, setOpen, confirmCallback=()=>{},confirmText='Confirm', cancellable=false, cancelCallback=()=>{}, width}: { name: string | undefined; cancelText?:string; message:string|undefined;
13
+ color?: "inherit" | "primary" | "secondary" | "success" | "error" | "info" | "warning" | undefined, open:boolean, setOpen:(open:boolean)=>void, confirmCallback?:()=>void,
14
+ cancellable?:boolean, cancelCallback?:()=>void, width?:number, confirmText?:string}) {
15
+ const [text, setText] = React.useState('');
16
+
17
+ const handleClose = () => {
18
+ setOpen(false);
19
+ };
20
+
21
+ const handleConfirm=()=>{
22
+ confirmCallback();
23
+ handleClose();
24
+ }
25
+
26
+ const handleCancel=()=>{
27
+ cancelCallback();
28
+ handleClose();
29
+ }
30
+
31
+
32
+ return (
33
+ <Dialog open={open} onClose={handleClose}>
34
+ <DialogTitle>{name?name:'Confirmation'}</DialogTitle>
35
+ <DialogContent sx={{width:width}}>
36
+ <DialogContentText alignContent={'center'}>
37
+ {message}
38
+ </DialogContentText>
39
+ <DialogActions className={'mt-4'}>
40
+ {cancellable&&
41
+ <CmrButton variant={"outlined"} color={'inherit'} sx={{color:'#333'}} onClick={handleCancel}>{cancelText}</CmrButton>
42
+ }
43
+ <CmrButton variant={"contained"} color={color} onClick={handleConfirm}>{confirmText}</CmrButton>
44
+ </DialogActions>
45
+ </DialogContent>
46
+ </Dialog>
47
+ );
48
+ }
@@ -0,0 +1,61 @@
1
+ import * as React from 'react';
2
+ import Button from '@mui/material/Button';
3
+ import TextField from '@mui/material/TextField';
4
+ import Dialog from '@mui/material/Dialog';
5
+ import DialogActions from '@mui/material/DialogActions';
6
+ import DialogContent from '@mui/material/DialogContent';
7
+ import DialogContentText from '@mui/material/DialogContentText';
8
+ import DialogTitle from '@mui/material/DialogTitle';
9
+
10
+ export default function DeletionDialog(props: { name: string | undefined; deletionCallback: () => void; }) {
11
+ const [open, setOpen] = React.useState(true);
12
+ const [text, setText] = React.useState('');
13
+
14
+ const handleClickOpen = () => {
15
+ setOpen(true);
16
+ };
17
+
18
+ const handleClose = () => {
19
+ setOpen(false);
20
+ };
21
+
22
+ const handleConfirm = () => {
23
+ if(text===props.name){
24
+ props.deletionCallback();
25
+ setOpen(false);
26
+ }
27
+ };
28
+
29
+ const handleTextFieldChange=(e: { target: { value: React.SetStateAction<string>; }; })=>{
30
+ setText( e.target.value);
31
+ }
32
+
33
+ return (
34
+ <div>
35
+ <Dialog open={open} onClose={handleClose}>
36
+ <DialogTitle>Confirmation</DialogTitle>
37
+ <DialogContent>
38
+ <DialogContentText>
39
+ To delete the files, please type your full name below and confirm.
40
+ </DialogContentText>
41
+
42
+ <TextField
43
+ autoFocus
44
+ margin="dense"
45
+ id="name"
46
+ type="email"
47
+ placeholder = {props.name}
48
+ fullWidth
49
+ inputProps={{style: {fontSize: "16pt"}}}
50
+ variant="standard"
51
+ onChange={handleTextFieldChange}
52
+ />
53
+ </DialogContent>
54
+ <DialogActions>
55
+ <button className='btn btn-secondary' onClick={handleClose}>Cancel</button>
56
+ <button className='btn btn-danger' onClick={handleConfirm}>Confirm</button>
57
+ </DialogActions>
58
+ </Dialog>
59
+ </div>
60
+ );
61
+ }
@@ -0,0 +1,72 @@
1
+ import * as React from 'react';
2
+ import TextField from '@mui/material/TextField';
3
+ import Dialog from '@mui/material/Dialog';
4
+ import DialogActions from '@mui/material/DialogActions';
5
+ import DialogContent from '@mui/material/DialogContent';
6
+ import DialogContentText from '@mui/material/DialogContentText';
7
+ import DialogTitle from '@mui/material/DialogTitle';
8
+ import CmrButton from '../button/Button';
9
+ import { InputAdornment } from '@mui/material';
10
+ import {useEffect} from "react";
11
+
12
+ export interface EditConfirmationProps{
13
+ name?: string; // Equivalent to string | undefined
14
+ defaultText?: string;
15
+ message?: string;
16
+ color?: "inherit" | "primary" | "secondary" | "success" | "error" | "info" | "warning";
17
+ open: boolean;
18
+ setOpen: (open: boolean) => void;
19
+ confirmCallback?: (text: string) => void;
20
+ cancellable?: boolean;
21
+ cancelCallback?: (edit: string) => void;
22
+ suffix?:string;
23
+ }
24
+
25
+ export default function EditConfirmation({ name,message, defaultText='',
26
+ color, open, setOpen, confirmCallback=()=>{}, cancellable=false, cancelCallback=()=>{},suffix=''}:EditConfirmationProps) {
27
+ const [text, setText] = React.useState(defaultText);
28
+ useEffect(() => {
29
+ if(open)
30
+ setText(defaultText);
31
+ }, [open]);
32
+ const handleClose = () => {
33
+ setOpen(false);
34
+ };
35
+
36
+ const handleConfirm=()=>{
37
+ confirmCallback(text+suffix);
38
+ handleClose();
39
+ }
40
+
41
+ const handleCancel=()=>{
42
+ cancelCallback(text+suffix);
43
+ handleClose();
44
+ }
45
+
46
+
47
+ return (
48
+ <Dialog maxWidth="xs" fullWidth={true} open={open} onClose={handleCancel}>
49
+ <DialogTitle>{name?name:'Confirmation'}</DialogTitle>
50
+ <DialogContent>
51
+ <DialogContentText alignContent={'center'}>
52
+ {message}
53
+ </DialogContentText>
54
+ <DialogActions>
55
+ <TextField fullWidth variant='standard'
56
+ InputProps={{
57
+ endAdornment: (
58
+ <InputAdornment position="end" sx={{ whiteSpace: 'nowrap' }}>{suffix}</InputAdornment>
59
+ ),
60
+ }}
61
+ defaultValue={text} onChange={(e)=>setText(e.target.value)}/>
62
+ </DialogActions>
63
+ <DialogActions>
64
+ {cancellable&&
65
+ <CmrButton variant={"outlined"} color={'inherit'} sx={{color:'#333'}} onClick={handleCancel}>Cancel</CmrButton>
66
+ }
67
+ <CmrButton variant={"contained"} color={color} onClick={handleConfirm}>Confirm</CmrButton>
68
+ </DialogActions>
69
+ </DialogContent>
70
+ </Dialog>
71
+ );
72
+ }
@@ -0,0 +1,198 @@
1
+ import {Box} from "@mui/material";
2
+ import {useRef, useState} from "react";
3
+
4
+ /**
5
+ * This dual slider (lil-gui styled) allows users to control the max and min of an interval simultaneously.
6
+ * The rendered interval (and number control) can be masked by a transformation - inverse pair.
7
+ * @param name
8
+ * @param min
9
+ * @param max
10
+ * @param setMin
11
+ * @param setMax
12
+ * @param transform transform and inverse are a pair that masks the rendered values and rendered inputs by a transformation
13
+ * @param inverse transform and inverse are a pair that masks the rendered values and rendered inputs by a transformation
14
+ * @constructor
15
+ */
16
+ export const DualSlider = ({name,min,max,setMin,setMax,
17
+ transform=x=>x,inverse=x=>x}:
18
+ {name:string,min:number,max:number, setMin?:(min:number)=>void,
19
+ setMax?:(max:number)=>void,transform?:(x:number)=>number,
20
+ inverse?:(x:number)=>number})=>{
21
+ const [leftSliderPosition, setLeftSliderPosition] = useState(0); // Initial percentage for the left slider
22
+ const [rightSliderPosition, setRightSliderPosition] = useState(100); // Initial percentage for the right slider
23
+ const [isHovering, setIsHovering] = useState(false);
24
+ const [leftEditing, setLeftEditing] = useState(false);
25
+
26
+ const [minOverride, setMinOverride] = useState<any>(undefined);
27
+ const [maxOverride, setMaxOverride] = useState<any>(undefined);
28
+
29
+ if(minOverride)
30
+ min = minOverride;
31
+ if(maxOverride)
32
+ max = maxOverride;
33
+
34
+ const a = transform((max-min)*leftSliderPosition/100+min);
35
+ const b = transform((max-min)*rightSliderPosition/100+min);
36
+ const left = Math.min(a,b);
37
+ const right = Math.max(a,b);
38
+
39
+ const sliderRef = useRef(null); // Ref for the parent box
40
+
41
+ const handleDragStart = (e:any, slider:string) => {
42
+ // Prevent default behavior
43
+ e.preventDefault();
44
+ setLeftEditing(false);
45
+ setLeftIsNaN(false)
46
+ leftRef.current.blur();
47
+
48
+ setRightEditing(false);
49
+ setRightIsNaN(false);
50
+ rightRef.current.blur();
51
+
52
+ // Calculate initial positions
53
+ const startX = e.clientX;
54
+ // @ts-ignore
55
+ const sliderWidth = sliderRef.current.offsetWidth;
56
+
57
+ const handleMouseMove = (e:any) => {
58
+ const moveX = e.clientX - startX;
59
+ const newPosition = ((moveX / sliderWidth) * 100) + (slider === 'left' ? leftSliderPosition : rightSliderPosition);
60
+
61
+
62
+ // Prevent the slider from going outside the parent box
63
+ const clampedPosition = Math.min(100, Math.max(0, newPosition));
64
+
65
+ // Update the position of the slider
66
+ if (slider === 'left') {
67
+ setLeftSliderPosition(clampedPosition);
68
+ const a = (max-min)*clampedPosition/100+min;
69
+ const b = (max-min)*rightSliderPosition/100+min;
70
+ setMin&&setMin(Math.min(a,b));
71
+ setMax&&setMax(Math.max(a,b));
72
+
73
+ } else if (slider === 'right') {
74
+ setRightSliderPosition(clampedPosition);
75
+ const a = (max-min)*leftSliderPosition/100+min;
76
+ const b = (max-min)*clampedPosition/100+min;
77
+ setMin&&setMin(Math.min(a,b));
78
+ setMax&&setMax(Math.max(a,b));
79
+ }
80
+
81
+ };
82
+
83
+ const handleMouseUp = () => {
84
+ // Remove event listeners once dragging is complete
85
+ document.removeEventListener('mousemove', handleMouseMove);
86
+ document.removeEventListener('mouseup', handleMouseUp);
87
+ };
88
+
89
+ // Add mouse move and mouse up listeners to document to handle drag
90
+ document.addEventListener('mousemove', handleMouseMove);
91
+ document.addEventListener('mouseup', handleMouseUp);
92
+ };
93
+
94
+ const leftText = Math.abs(left)<0.01&&left!=0?Number(left).toExponential(3).toUpperCase():Number(left).toFixed(3);
95
+ const [leftEditedText,setLeftEditedText] = useState('');
96
+ const [leftIsNaN, setLeftIsNaN] = useState(false);
97
+ const leftRef = useRef<any>(null);
98
+
99
+ const [rightEditing, setRightEditing] = useState(false);
100
+ const [rightEditedText, setRightEditedText] = useState('');
101
+ const [rightIsNaN, setRightIsNaN] = useState(false);
102
+ const rightRef = useRef<any>(null);
103
+
104
+ // Logic to handle right value box editing...
105
+ const rightText = Math.abs(right) < 0.01 && right != 0 ? Number(right).toExponential(3).toUpperCase() : Number(right).toFixed(3);
106
+
107
+ return <Box sx={{display:'flex',flexDirection:'row', paddingLeft:'4px',paddingRight:'4px'}} height={20}>
108
+ <Box flex={0.322} fontSize={16} color={'#3D3D3D'} alignItems={'center'} display={'flex'} marginBottom={'1pt'}
109
+ fontFamily={'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif'}>
110
+ {name}
111
+ </Box>
112
+ <Box sx={{display:'flex',flexDirection:'row'}} flex={1}>
113
+ <input ref={leftRef} style={{backgroundColor:'#f0f0f0',width:'45px', borderRadius:'2px', outline:"none",borderStyle:'none',paddingLeft:'3px',paddingRight:'3px', lineHeight:'20px',
114
+ whiteSpace:'nowrap',fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif',fontSize:'11px',color:leftIsNaN?'red':'black'}} value={
115
+ (leftEditing)?leftEditedText:leftText
116
+ } onKeyDown={(e) => {
117
+ if (e.key === 'Enter'&&!leftIsNaN) {
118
+ //@ts-ignore
119
+ e.target.blur(); // This will cause the input to lose focus
120
+ }
121
+ }} onFocus={(e)=>{
122
+ setLeftEditedText(e.target.value);
123
+ setLeftEditing(true);
124
+ }} onChange={(event)=>{
125
+ setLeftIsNaN(isNaN(Number(event.target.value)));
126
+ setLeftEditedText(event.target.value);
127
+ }} onBlur={(e)=>{
128
+ let val = inverse(Number(leftEditedText));
129
+ if(isNaN(val)) {
130
+ return e.preventDefault();
131
+ }
132
+ setLeftEditing(false);
133
+ setMin&&setMin(val);
134
+ let newMin = min;
135
+ if(val<min) {
136
+ setMinOverride(val);
137
+ newMin = val;
138
+ }
139
+ let leftPosition = (val-newMin)/(max-newMin)*100;
140
+ setLeftSliderPosition(leftPosition);
141
+ }}/>
142
+
143
+ <Box sx={{ backgroundColor: '#f0f0f0', flex: 1, marginLeft: '4px', marginRight: '4px', borderRadius: '2px', position: 'relative',
144
+ overflow:'hidden', opacity:isHovering?0.75:1
145
+ }} ref={sliderRef}
146
+ onMouseEnter={() => setIsHovering(true)} onMouseLeave={() => setIsHovering(false)}>
147
+ {/* Central gray block with two vertical black components */}
148
+ <Box sx={{ position: 'absolute', left: `calc(${leftSliderPosition*0.97}% - 10px)`, width: '20px', height: '100%', cursor: 'ew-resize', zIndex: 1 }}
149
+ onMouseDown={(e) => handleDragStart(e, 'left')}>
150
+ {/* Visual representation of the slider */}
151
+ <Box sx={{ position: 'absolute', left: '10px', width: '2px', height: '100%', backgroundColor: 'black' }} />
152
+ </Box>
153
+
154
+ {/* Transparent hitbox for the right slider */}
155
+ <Box sx={{ position: 'absolute', right: `calc(${(100 - rightSliderPosition)*0.97}% - 10px)`, width: '20px', height: '100%', cursor: 'ew-resize', zIndex: 1 }}
156
+ onMouseDown={(e) => handleDragStart(e, 'right')}>
157
+ {/* Visual representation of the slider */}
158
+ <Box sx={{ position: 'absolute', right: '10px', width: '2px', height: '100%', backgroundColor: 'black' }} />
159
+ </Box>
160
+ </Box>
161
+
162
+ <input style={{backgroundColor: '#f0f0f0', width: '45px', borderRadius: '2px', outline: "none", borderStyle: 'none', paddingLeft: '3px', paddingRight: '3px', lineHeight: '20px',
163
+ whiteSpace: 'nowrap', fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif', fontSize: '11px', color: rightIsNaN ? 'red' : 'black'}}
164
+ value={(rightEditing) ? rightEditedText : rightText}
165
+ ref={rightRef}
166
+ onKeyDown={(e) => {
167
+ if (e.key === 'Enter' && !rightIsNaN) {
168
+ //@ts-ignore
169
+ e.target.blur(); // This will cause the input to lose focus
170
+ }
171
+ }}
172
+ onFocus={(e) => {
173
+ setRightEditedText(e.target.value);
174
+ setRightEditing(true);
175
+ }}
176
+ onChange={(event) => {
177
+ setRightIsNaN(isNaN(Number(event.target.value)));
178
+ setRightEditedText(event.target.value);
179
+ }}
180
+ onBlur={(e) => {
181
+ let val = inverse(Number(rightEditedText));
182
+ if (isNaN(val)) {
183
+ return e.preventDefault();
184
+ }
185
+ setRightEditing(false);
186
+ setMax && setMax(val);
187
+ let newMax = max;
188
+ if (val > max) {
189
+ setMaxOverride(val);
190
+ newMax = val;
191
+ }
192
+ let rightPosition = (val - min) / (newMax - min) * 100;
193
+ setRightSliderPosition(rightPosition);
194
+ }}
195
+ />
196
+ </Box>
197
+ </Box>
198
+ }