@etsoo/react 1.4.48 → 1.4.52
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/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/mu/ComboBox.d.ts +4 -0
- package/lib/mu/ComboBox.js +13 -4
- package/lib/mu/SelectEx.js +3 -2
- package/lib/mu/Switch.js +11 -4
- package/lib/mu/SwitchAnt.d.ts +25 -0
- package/lib/mu/SwitchAnt.js +40 -0
- package/lib/mu/TextFieldEx.js +2 -1
- package/lib/mu/Tiplist.js +2 -2
- package/package.json +7 -7
- package/src/index.ts +1 -0
- package/src/mu/ComboBox.tsx +21 -3
- package/src/mu/SelectEx.tsx +3 -2
- package/src/mu/Switch.tsx +13 -3
- package/src/mu/SwitchAnt.tsx +95 -0
- package/src/mu/TextFieldEx.tsx +2 -1
- package/src/mu/Tiplist.tsx +2 -0
package/lib/index.d.ts
CHANGED
|
@@ -65,6 +65,7 @@ export * from './mu/SearchField';
|
|
|
65
65
|
export * from './mu/SearchOptionGroup';
|
|
66
66
|
export * from './mu/SelectEx';
|
|
67
67
|
export * from './mu/Switch';
|
|
68
|
+
export * from './mu/SwitchAnt';
|
|
68
69
|
export * from './mu/TabBox';
|
|
69
70
|
export * from './mu/TableEx';
|
|
70
71
|
export * from './mu/TextFieldEx';
|
package/lib/index.js
CHANGED
|
@@ -68,6 +68,7 @@ export * from './mu/SearchField';
|
|
|
68
68
|
export * from './mu/SearchOptionGroup';
|
|
69
69
|
export * from './mu/SelectEx';
|
|
70
70
|
export * from './mu/Switch';
|
|
71
|
+
export * from './mu/SwitchAnt';
|
|
71
72
|
export * from './mu/TabBox';
|
|
72
73
|
export * from './mu/TableEx';
|
|
73
74
|
export * from './mu/TextFieldEx';
|
package/lib/mu/ComboBox.d.ts
CHANGED
|
@@ -5,6 +5,10 @@ import { AutocompleteExtendedProps } from './AutocompleteExtendedProps';
|
|
|
5
5
|
* ComboBox props
|
|
6
6
|
*/
|
|
7
7
|
export interface ComboBoxProps<T extends {}> extends AutocompleteExtendedProps<T> {
|
|
8
|
+
/**
|
|
9
|
+
* Data readonly
|
|
10
|
+
*/
|
|
11
|
+
dataReadonly?: boolean;
|
|
8
12
|
/**
|
|
9
13
|
* Label field
|
|
10
14
|
*/
|
package/lib/mu/ComboBox.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Keyboard } from '@etsoo/shared';
|
|
1
2
|
import { Autocomplete } from '@mui/material';
|
|
2
3
|
import React from 'react';
|
|
3
4
|
import { Utils } from '../app/Utils';
|
|
@@ -10,7 +11,7 @@ import { SearchField } from './SearchField';
|
|
|
10
11
|
*/
|
|
11
12
|
export function ComboBox(props) {
|
|
12
13
|
// Destruct
|
|
13
|
-
const { search = false, idField = 'id', idValue, inputError, inputHelperText, inputMargin, inputOnChange, inputRequired, inputVariant, defaultValue, label, labelField = 'label', loadData, onLoadData, name, inputAutoComplete = 'off', options,
|
|
14
|
+
const { search = false, idField = 'id', idValue, inputError, inputHelperText, inputMargin, inputOnChange, inputRequired, inputVariant, defaultValue, label, labelField = 'label', loadData, onLoadData, name, inputAutoComplete = 'off', options, dataReadonly = true, readOnly, onChange, openOnFocus = true, value, getOptionLabel = (option) => String(Reflect.get(option, labelField)), sx = { minWidth: '150px' }, ...rest } = props;
|
|
14
15
|
// Value input ref
|
|
15
16
|
const inputRef = React.createRef();
|
|
16
17
|
// Options state
|
|
@@ -18,10 +19,11 @@ export function ComboBox(props) {
|
|
|
18
19
|
const isMounted = React.useRef(true);
|
|
19
20
|
// When options change
|
|
20
21
|
// [options] will cause infinite loop
|
|
22
|
+
const propertyWay = loadData == null;
|
|
21
23
|
React.useEffect(() => {
|
|
22
|
-
if (options != null)
|
|
24
|
+
if (propertyWay && options != null)
|
|
23
25
|
setOptions(options);
|
|
24
|
-
}, [JSON.stringify(options)]);
|
|
26
|
+
}, [JSON.stringify(options), propertyWay]);
|
|
25
27
|
// Local default value
|
|
26
28
|
let localValue = idValue != null
|
|
27
29
|
? localOptions.find((o) => Reflect.get(o, idField) === idValue)
|
|
@@ -46,6 +48,13 @@ export function ComboBox(props) {
|
|
|
46
48
|
Object.assign(params.inputProps, { 'data-reset': true });
|
|
47
49
|
}
|
|
48
50
|
}
|
|
51
|
+
if (dataReadonly) {
|
|
52
|
+
params.inputProps.onKeyDown = (event) => {
|
|
53
|
+
if (Keyboard.isTypingContent(event.key)) {
|
|
54
|
+
event.preventDefault();
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
49
58
|
// https://stackoverflow.com/questions/15738259/disabling-chrome-autofill
|
|
50
59
|
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html
|
|
51
60
|
Object.assign(params.inputProps, { autoComplete: inputAutoComplete });
|
|
@@ -88,5 +97,5 @@ export function ComboBox(props) {
|
|
|
88
97
|
// Custom
|
|
89
98
|
if (onChange != null)
|
|
90
99
|
onChange(event, value, reason, details);
|
|
91
|
-
}, sx: sx, renderInput: (params) => search ? (React.createElement(SearchField, { ...addReadOnly(params), label: label, name: name + 'Input', margin: inputMargin, variant: inputVariant, required: inputRequired, error: inputError, helperText: inputHelperText })) : (React.createElement(InputField, { ...addReadOnly(params), label: label, name: name + 'Input', margin: inputMargin, variant: inputVariant, required: inputRequired, error: inputError, helperText: inputHelperText })), options: localOptions, ...rest })));
|
|
100
|
+
}, openOnFocus: openOnFocus, sx: sx, renderInput: (params) => search ? (React.createElement(SearchField, { ...addReadOnly(params), label: label, name: name + 'Input', margin: inputMargin, variant: inputVariant, required: inputRequired, error: inputError, helperText: inputHelperText })) : (React.createElement(InputField, { ...addReadOnly(params), label: label, name: name + 'Input', margin: inputMargin, variant: inputVariant, required: inputRequired, error: inputError, helperText: inputHelperText })), options: localOptions, ...rest })));
|
|
92
101
|
}
|
package/lib/mu/SelectEx.js
CHANGED
|
@@ -17,10 +17,11 @@ export function SelectEx(props) {
|
|
|
17
17
|
const isMounted = React.useRef(true);
|
|
18
18
|
// When options change
|
|
19
19
|
// [options] will cause infinite loop
|
|
20
|
+
const propertyWay = loadData == null;
|
|
20
21
|
React.useEffect(() => {
|
|
21
|
-
if (options != null)
|
|
22
|
+
if (propertyWay && options != null)
|
|
22
23
|
setOptions(options);
|
|
23
|
-
}, [JSON.stringify(options)]);
|
|
24
|
+
}, [JSON.stringify(options), propertyWay]);
|
|
24
25
|
// Local value
|
|
25
26
|
const valueSource = (_a = defaultValue !== null && defaultValue !== void 0 ? defaultValue : value) !== null && _a !== void 0 ? _a : '';
|
|
26
27
|
let localValue;
|
package/lib/mu/Switch.js
CHANGED
|
@@ -8,13 +8,20 @@ import MuiSwitch from '@mui/material/Switch';
|
|
|
8
8
|
* @returns Component
|
|
9
9
|
*/
|
|
10
10
|
export function Switch(props) {
|
|
11
|
+
var _a;
|
|
11
12
|
// Destruct
|
|
12
|
-
const { defaultChecked, defaultValue, readOnly, size, checkbox = false, value = 'true', ...rest } = props;
|
|
13
|
+
const { checked, defaultChecked, defaultValue, onChange, readOnly, size, checkbox = false, value = 'true', ...rest } = props;
|
|
13
14
|
// Checked state
|
|
14
|
-
const [controlChecked, setControlChecked] = React.useState(
|
|
15
|
+
const [controlChecked, setControlChecked] = React.useState((_a = checked !== null && checked !== void 0 ? checked : defaultChecked) !== null && _a !== void 0 ? _a : defaultValue == value);
|
|
16
|
+
React.useEffect(() => {
|
|
17
|
+
if (checked)
|
|
18
|
+
setControlChecked(checked);
|
|
19
|
+
}, [checked]);
|
|
15
20
|
// Handle change
|
|
16
|
-
const handleChange = (event) => {
|
|
17
|
-
|
|
21
|
+
const handleChange = (event, checked) => {
|
|
22
|
+
if (onChange)
|
|
23
|
+
onChange(event, checked);
|
|
24
|
+
setControlChecked(checked);
|
|
18
25
|
};
|
|
19
26
|
// Control
|
|
20
27
|
const control = checkbox ? (React.createElement(MuiCheckbox, { readOnly: readOnly, checked: controlChecked, onChange: handleChange, size: size, value: value })) : (React.createElement(MuiSwitch, { readOnly: readOnly, checked: controlChecked, onChange: handleChange, size: size, value: value }));
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { SwitchProps } from '@mui/material/Switch';
|
|
3
|
+
/**
|
|
4
|
+
* Ant style switch props
|
|
5
|
+
*/
|
|
6
|
+
export interface SwitchAntProps extends SwitchProps {
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
*/
|
|
10
|
+
activeColor?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Start label
|
|
13
|
+
*/
|
|
14
|
+
startLabel: string;
|
|
15
|
+
/**
|
|
16
|
+
* End label
|
|
17
|
+
*/
|
|
18
|
+
endLabel: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Ant style switch
|
|
22
|
+
* @param props Props
|
|
23
|
+
* @returns Component
|
|
24
|
+
*/
|
|
25
|
+
export declare function SwitchAnt(props: SwitchAntProps): JSX.Element;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Stack, Typography } from '@mui/material';
|
|
2
|
+
import Switch from '@mui/material/Switch';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
/**
|
|
5
|
+
* Ant style switch
|
|
6
|
+
* @param props Props
|
|
7
|
+
* @returns Component
|
|
8
|
+
*/
|
|
9
|
+
export function SwitchAnt(props) {
|
|
10
|
+
var _a;
|
|
11
|
+
// Destruct
|
|
12
|
+
const { activeColor, checked, defaultChecked, defaultValue, endLabel, startLabel, onChange, value = 'true', ...rest } = props;
|
|
13
|
+
// Checked state
|
|
14
|
+
const [controlChecked, setControlChecked] = React.useState((_a = checked !== null && checked !== void 0 ? checked : defaultChecked) !== null && _a !== void 0 ? _a : defaultValue == value);
|
|
15
|
+
React.useEffect(() => {
|
|
16
|
+
if (checked)
|
|
17
|
+
setControlChecked(checked);
|
|
18
|
+
}, [checked]);
|
|
19
|
+
// On change
|
|
20
|
+
const onChangeLocal = (event, checked) => {
|
|
21
|
+
if (onChange)
|
|
22
|
+
onChange(event, checked);
|
|
23
|
+
setControlChecked(checked);
|
|
24
|
+
};
|
|
25
|
+
// Layout
|
|
26
|
+
return (React.createElement(Stack, { direction: "row", spacing: 1, alignItems: "center" },
|
|
27
|
+
React.createElement(Typography, { onClick: () => setControlChecked(false), sx: {
|
|
28
|
+
cursor: 'pointer',
|
|
29
|
+
color: controlChecked
|
|
30
|
+
? undefined
|
|
31
|
+
: (theme) => activeColor !== null && activeColor !== void 0 ? activeColor : theme.palette.warning.main
|
|
32
|
+
} }, startLabel),
|
|
33
|
+
React.createElement(Switch, { checked: controlChecked, value: value, onChange: onChangeLocal, ...rest }),
|
|
34
|
+
React.createElement(Typography, { onClick: () => setControlChecked(true), sx: {
|
|
35
|
+
cursor: 'pointer',
|
|
36
|
+
color: controlChecked
|
|
37
|
+
? (theme) => activeColor !== null && activeColor !== void 0 ? activeColor : theme.palette.warning.main
|
|
38
|
+
: undefined
|
|
39
|
+
} }, endLabel)));
|
|
40
|
+
}
|
package/lib/mu/TextFieldEx.js
CHANGED
|
@@ -3,6 +3,7 @@ import { IconButton, InputAdornment, TextField } from '@mui/material';
|
|
|
3
3
|
import { MUGlobal } from './MUGlobal';
|
|
4
4
|
import { Clear, Visibility } from '@mui/icons-material';
|
|
5
5
|
import useCombinedRefs from '../uses/useCombinedRefs';
|
|
6
|
+
import { Keyboard } from '@etsoo/shared';
|
|
6
7
|
export const TextFieldEx = React.forwardRef((props, ref) => {
|
|
7
8
|
// Destructure
|
|
8
9
|
const { changeDelay, error, fullWidth = true, helperText, InputProps = {}, onChange, onKeyPress, onEnter, inputRef, readOnly, showClear, showPassword, type, variant = MUGlobal.textFieldVariant, ...rest } = props;
|
|
@@ -71,7 +72,7 @@ export const TextFieldEx = React.forwardRef((props, ref) => {
|
|
|
71
72
|
const onKeyPressEx = onEnter == null
|
|
72
73
|
? onKeyPress
|
|
73
74
|
: (e) => {
|
|
74
|
-
if (e.key ===
|
|
75
|
+
if (e.key === Keyboard.Keys.Enter) {
|
|
75
76
|
// Enter press callback
|
|
76
77
|
onEnter(e);
|
|
77
78
|
}
|
package/lib/mu/Tiplist.js
CHANGED
|
@@ -11,7 +11,7 @@ import { SearchField } from './SearchField';
|
|
|
11
11
|
*/
|
|
12
12
|
export function Tiplist(props) {
|
|
13
13
|
// Destruct
|
|
14
|
-
const { search = false, idField = 'id', idValue, inputAutoComplete = 'off', inputError, inputHelperText, inputMargin, inputOnChange, inputRequired, inputVariant, label, loadData, defaultValue, value, name, readOnly, onChange, sx = { minWidth: '180px' }, ...rest } = props;
|
|
14
|
+
const { search = false, idField = 'id', idValue, inputAutoComplete = 'off', inputError, inputHelperText, inputMargin, inputOnChange, inputRequired, inputVariant, label, loadData, defaultValue, value, name, readOnly, onChange, openOnFocus = true, sx = { minWidth: '180px' }, ...rest } = props;
|
|
15
15
|
// Value input ref
|
|
16
16
|
const inputRef = React.createRef();
|
|
17
17
|
// Local value
|
|
@@ -145,7 +145,7 @@ export function Tiplist(props) {
|
|
|
145
145
|
stateUpdate({ options: [] });
|
|
146
146
|
loadDataDirect();
|
|
147
147
|
}
|
|
148
|
-
}, open: states.open, onOpen: () => {
|
|
148
|
+
}, open: states.open, openOnFocus: openOnFocus, onOpen: () => {
|
|
149
149
|
// Should load
|
|
150
150
|
const loading = states.loading
|
|
151
151
|
? true
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etsoo/react",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.52",
|
|
4
4
|
"description": "TypeScript ReactJs framework",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -50,11 +50,11 @@
|
|
|
50
50
|
"@emotion/react": "^11.7.1",
|
|
51
51
|
"@emotion/style": "^0.8.0",
|
|
52
52
|
"@emotion/styled": "^11.6.0",
|
|
53
|
-
"@etsoo/appscript": "^1.2.
|
|
53
|
+
"@etsoo/appscript": "^1.2.25",
|
|
54
54
|
"@etsoo/notificationbase": "^1.1.0",
|
|
55
|
-
"@etsoo/shared": "^1.1.
|
|
56
|
-
"@mui/icons-material": "^5.
|
|
57
|
-
"@mui/material": "^5.
|
|
55
|
+
"@etsoo/shared": "^1.1.6",
|
|
56
|
+
"@mui/icons-material": "^5.3.0",
|
|
57
|
+
"@mui/material": "^5.3.0",
|
|
58
58
|
"@reach/router": "^1.3.4",
|
|
59
59
|
"@types/pica": "^5.1.3",
|
|
60
60
|
"@types/pulltorefreshjs": "^0.1.5",
|
|
@@ -83,8 +83,8 @@
|
|
|
83
83
|
"@babel/runtime-corejs3": "^7.16.8",
|
|
84
84
|
"@types/jest": "^27.4.0",
|
|
85
85
|
"@types/react-test-renderer": "^17.0.1",
|
|
86
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
87
|
-
"@typescript-eslint/parser": "^5.
|
|
86
|
+
"@typescript-eslint/eslint-plugin": "^5.10.0",
|
|
87
|
+
"@typescript-eslint/parser": "^5.10.0",
|
|
88
88
|
"eslint": "^8.7.0",
|
|
89
89
|
"eslint-config-airbnb-base": "^15.0.0",
|
|
90
90
|
"eslint-plugin-import": "^2.25.4",
|
package/src/index.ts
CHANGED
|
@@ -72,6 +72,7 @@ export * from './mu/SearchField';
|
|
|
72
72
|
export * from './mu/SearchOptionGroup';
|
|
73
73
|
export * from './mu/SelectEx';
|
|
74
74
|
export * from './mu/Switch';
|
|
75
|
+
export * from './mu/SwitchAnt';
|
|
75
76
|
export * from './mu/TabBox';
|
|
76
77
|
export * from './mu/TableEx';
|
|
77
78
|
export * from './mu/TextFieldEx';
|
package/src/mu/ComboBox.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { IdLabelDto } from '@etsoo/appscript';
|
|
2
|
+
import { Keyboard } from '@etsoo/shared';
|
|
2
3
|
import { Autocomplete, AutocompleteRenderInputParams } from '@mui/material';
|
|
3
4
|
import React from 'react';
|
|
4
5
|
import { Utils } from '../app/Utils';
|
|
@@ -11,6 +12,11 @@ import { SearchField } from './SearchField';
|
|
|
11
12
|
*/
|
|
12
13
|
export interface ComboBoxProps<T extends {}>
|
|
13
14
|
extends AutocompleteExtendedProps<T> {
|
|
15
|
+
/**
|
|
16
|
+
* Data readonly
|
|
17
|
+
*/
|
|
18
|
+
dataReadonly?: boolean;
|
|
19
|
+
|
|
14
20
|
/**
|
|
15
21
|
* Label field
|
|
16
22
|
*/
|
|
@@ -57,8 +63,10 @@ export function ComboBox<T extends {} = IdLabelDto>(props: ComboBoxProps<T>) {
|
|
|
57
63
|
name,
|
|
58
64
|
inputAutoComplete = 'off',
|
|
59
65
|
options,
|
|
60
|
-
|
|
66
|
+
dataReadonly = true,
|
|
67
|
+
readOnly,
|
|
61
68
|
onChange,
|
|
69
|
+
openOnFocus = true,
|
|
62
70
|
value,
|
|
63
71
|
getOptionLabel = (option: T) => String(Reflect.get(option, labelField)),
|
|
64
72
|
sx = { minWidth: '150px' },
|
|
@@ -74,9 +82,10 @@ export function ComboBox<T extends {} = IdLabelDto>(props: ComboBoxProps<T>) {
|
|
|
74
82
|
|
|
75
83
|
// When options change
|
|
76
84
|
// [options] will cause infinite loop
|
|
85
|
+
const propertyWay = loadData == null;
|
|
77
86
|
React.useEffect(() => {
|
|
78
|
-
if (options != null) setOptions(options);
|
|
79
|
-
}, [JSON.stringify(options)]);
|
|
87
|
+
if (propertyWay && options != null) setOptions(options);
|
|
88
|
+
}, [JSON.stringify(options), propertyWay]);
|
|
80
89
|
|
|
81
90
|
// Local default value
|
|
82
91
|
let localValue =
|
|
@@ -108,6 +117,14 @@ export function ComboBox<T extends {} = IdLabelDto>(props: ComboBoxProps<T>) {
|
|
|
108
117
|
}
|
|
109
118
|
}
|
|
110
119
|
|
|
120
|
+
if (dataReadonly) {
|
|
121
|
+
params.inputProps.onKeyDown = (event) => {
|
|
122
|
+
if (Keyboard.isTypingContent(event.key)) {
|
|
123
|
+
event.preventDefault();
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
111
128
|
// https://stackoverflow.com/questions/15738259/disabling-chrome-autofill
|
|
112
129
|
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html
|
|
113
130
|
Object.assign(params.inputProps, { autoComplete: inputAutoComplete });
|
|
@@ -175,6 +192,7 @@ export function ComboBox<T extends {} = IdLabelDto>(props: ComboBoxProps<T>) {
|
|
|
175
192
|
if (onChange != null)
|
|
176
193
|
onChange(event, value, reason, details);
|
|
177
194
|
}}
|
|
195
|
+
openOnFocus={openOnFocus}
|
|
178
196
|
sx={sx}
|
|
179
197
|
renderInput={(params) =>
|
|
180
198
|
search ? (
|
package/src/mu/SelectEx.tsx
CHANGED
|
@@ -92,9 +92,10 @@ export function SelectEx<T extends {} = IdLabelDto>(props: SelectExProps<T>) {
|
|
|
92
92
|
|
|
93
93
|
// When options change
|
|
94
94
|
// [options] will cause infinite loop
|
|
95
|
+
const propertyWay = loadData == null;
|
|
95
96
|
React.useEffect(() => {
|
|
96
|
-
if (options != null) setOptions(options);
|
|
97
|
-
}, [JSON.stringify(options)]);
|
|
97
|
+
if (propertyWay && options != null) setOptions(options);
|
|
98
|
+
}, [JSON.stringify(options), propertyWay]);
|
|
98
99
|
|
|
99
100
|
// Local value
|
|
100
101
|
const valueSource = defaultValue ?? value ?? '';
|
package/src/mu/Switch.tsx
CHANGED
|
@@ -36,8 +36,10 @@ export interface SwitchProps extends Omit<FormControlLabelProps, 'control'> {
|
|
|
36
36
|
export function Switch(props: SwitchProps) {
|
|
37
37
|
// Destruct
|
|
38
38
|
const {
|
|
39
|
+
checked,
|
|
39
40
|
defaultChecked,
|
|
40
41
|
defaultValue,
|
|
42
|
+
onChange,
|
|
41
43
|
readOnly,
|
|
42
44
|
size,
|
|
43
45
|
checkbox = false,
|
|
@@ -47,12 +49,20 @@ export function Switch(props: SwitchProps) {
|
|
|
47
49
|
|
|
48
50
|
// Checked state
|
|
49
51
|
const [controlChecked, setControlChecked] = React.useState(
|
|
50
|
-
defaultChecked ?? defaultValue == value
|
|
52
|
+
checked ?? defaultChecked ?? defaultValue == value
|
|
51
53
|
);
|
|
52
54
|
|
|
55
|
+
React.useEffect(() => {
|
|
56
|
+
if (checked) setControlChecked(checked);
|
|
57
|
+
}, [checked]);
|
|
58
|
+
|
|
53
59
|
// Handle change
|
|
54
|
-
const handleChange = (
|
|
55
|
-
|
|
60
|
+
const handleChange = (
|
|
61
|
+
event: React.ChangeEvent<HTMLInputElement>,
|
|
62
|
+
checked: boolean
|
|
63
|
+
) => {
|
|
64
|
+
if (onChange) onChange(event, checked);
|
|
65
|
+
setControlChecked(checked);
|
|
56
66
|
};
|
|
57
67
|
|
|
58
68
|
// Control
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { Stack, Typography } from '@mui/material';
|
|
2
|
+
import Switch, { SwitchProps } from '@mui/material/Switch';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Ant style switch props
|
|
7
|
+
*/
|
|
8
|
+
export interface SwitchAntProps extends SwitchProps {
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
*/
|
|
12
|
+
activeColor?: string;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Start label
|
|
16
|
+
*/
|
|
17
|
+
startLabel: string;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* End label
|
|
21
|
+
*/
|
|
22
|
+
endLabel: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Ant style switch
|
|
27
|
+
* @param props Props
|
|
28
|
+
* @returns Component
|
|
29
|
+
*/
|
|
30
|
+
export function SwitchAnt(props: SwitchAntProps) {
|
|
31
|
+
// Destruct
|
|
32
|
+
const {
|
|
33
|
+
activeColor,
|
|
34
|
+
checked,
|
|
35
|
+
defaultChecked,
|
|
36
|
+
defaultValue,
|
|
37
|
+
endLabel,
|
|
38
|
+
startLabel,
|
|
39
|
+
onChange,
|
|
40
|
+
value = 'true',
|
|
41
|
+
...rest
|
|
42
|
+
} = props;
|
|
43
|
+
|
|
44
|
+
// Checked state
|
|
45
|
+
const [controlChecked, setControlChecked] = React.useState(
|
|
46
|
+
checked ?? defaultChecked ?? defaultValue == value
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
React.useEffect(() => {
|
|
50
|
+
if (checked) setControlChecked(checked);
|
|
51
|
+
}, [checked]);
|
|
52
|
+
|
|
53
|
+
// On change
|
|
54
|
+
const onChangeLocal = (
|
|
55
|
+
event: React.ChangeEvent<HTMLInputElement>,
|
|
56
|
+
checked: boolean
|
|
57
|
+
) => {
|
|
58
|
+
if (onChange) onChange(event, checked);
|
|
59
|
+
setControlChecked(checked);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// Layout
|
|
63
|
+
return (
|
|
64
|
+
<Stack direction="row" spacing={1} alignItems="center">
|
|
65
|
+
<Typography
|
|
66
|
+
onClick={() => setControlChecked(false)}
|
|
67
|
+
sx={{
|
|
68
|
+
cursor: 'pointer',
|
|
69
|
+
color: controlChecked
|
|
70
|
+
? undefined
|
|
71
|
+
: (theme) => activeColor ?? theme.palette.warning.main
|
|
72
|
+
}}
|
|
73
|
+
>
|
|
74
|
+
{startLabel}
|
|
75
|
+
</Typography>
|
|
76
|
+
<Switch
|
|
77
|
+
checked={controlChecked}
|
|
78
|
+
value={value}
|
|
79
|
+
onChange={onChangeLocal}
|
|
80
|
+
{...rest}
|
|
81
|
+
/>
|
|
82
|
+
<Typography
|
|
83
|
+
onClick={() => setControlChecked(true)}
|
|
84
|
+
sx={{
|
|
85
|
+
cursor: 'pointer',
|
|
86
|
+
color: controlChecked
|
|
87
|
+
? (theme) => activeColor ?? theme.palette.warning.main
|
|
88
|
+
: undefined
|
|
89
|
+
}}
|
|
90
|
+
>
|
|
91
|
+
{endLabel}
|
|
92
|
+
</Typography>
|
|
93
|
+
</Stack>
|
|
94
|
+
);
|
|
95
|
+
}
|
package/src/mu/TextFieldEx.tsx
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
import { MUGlobal } from './MUGlobal';
|
|
9
9
|
import { Clear, Visibility } from '@mui/icons-material';
|
|
10
10
|
import useCombinedRefs from '../uses/useCombinedRefs';
|
|
11
|
+
import { Keyboard } from '@etsoo/shared';
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Extended text field props
|
|
@@ -166,7 +167,7 @@ export const TextFieldEx = React.forwardRef<
|
|
|
166
167
|
onEnter == null
|
|
167
168
|
? onKeyPress
|
|
168
169
|
: (e: React.KeyboardEvent<HTMLDivElement>) => {
|
|
169
|
-
if (e.key ===
|
|
170
|
+
if (e.key === Keyboard.Keys.Enter) {
|
|
170
171
|
// Enter press callback
|
|
171
172
|
onEnter(e);
|
|
172
173
|
}
|
package/src/mu/Tiplist.tsx
CHANGED
|
@@ -54,6 +54,7 @@ export function Tiplist<T extends {} = IdLabelDto>(props: TiplistProps<T>) {
|
|
|
54
54
|
name,
|
|
55
55
|
readOnly,
|
|
56
56
|
onChange,
|
|
57
|
+
openOnFocus = true,
|
|
57
58
|
sx = { minWidth: '180px' },
|
|
58
59
|
...rest
|
|
59
60
|
} = props;
|
|
@@ -242,6 +243,7 @@ export function Tiplist<T extends {} = IdLabelDto>(props: TiplistProps<T>) {
|
|
|
242
243
|
}
|
|
243
244
|
}}
|
|
244
245
|
open={states.open}
|
|
246
|
+
openOnFocus={openOnFocus}
|
|
245
247
|
onOpen={() => {
|
|
246
248
|
// Should load
|
|
247
249
|
const loading = states.loading
|