@etsoo/materialui 1.1.80 → 1.1.82
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/ComboBoxPro.d.ts +3 -10
- package/lib/IntInputField.d.ts +46 -2
- package/lib/IntInputField.js +80 -2
- package/lib/MoneyInputField.d.ts +3 -4
- package/lib/MoneyInputField.js +3 -3
- package/lib/QuickList.d.ts +56 -0
- package/lib/QuickList.js +43 -0
- package/lib/TagListPro.d.ts +3 -10
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/package.json +6 -6
- package/src/ComboBoxPro.tsx +3 -6
- package/src/IntInputField.tsx +137 -6
- package/src/MoneyInputField.tsx +4 -16
- package/src/QuickList.tsx +153 -0
- package/src/TagListPro.tsx +3 -6
- package/src/index.ts +1 -0
package/lib/ComboBoxPro.d.ts
CHANGED
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import { AutocompleteProps } from "@mui/material";
|
|
3
3
|
import { InputFieldProps } from "./InputField";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
} & ({
|
|
7
|
-
label: string;
|
|
8
|
-
} | {
|
|
9
|
-
name: string;
|
|
10
|
-
});
|
|
11
|
-
export type ComboBoxProProps<D extends DataType = DataType> = Omit<AutocompleteProps<D, false, false, true>, "open" | "multiple" | "options" | "renderInput"> & {
|
|
4
|
+
import { ListType2 } from "@etsoo/shared";
|
|
5
|
+
export type ComboBoxProProps<D extends ListType2 = ListType2> = Omit<AutocompleteProps<D, false, false, true>, "open" | "multiple" | "options" | "renderInput"> & {
|
|
12
6
|
/**
|
|
13
7
|
* Label
|
|
14
8
|
*/
|
|
@@ -30,5 +24,4 @@ export type ComboBoxProProps<D extends DataType = DataType> = Omit<AutocompleteP
|
|
|
30
24
|
*/
|
|
31
25
|
inputProps?: Omit<InputFieldProps, "onChange">;
|
|
32
26
|
};
|
|
33
|
-
export declare function ComboBoxPro<D extends
|
|
34
|
-
export {};
|
|
27
|
+
export declare function ComboBoxPro<D extends ListType2 = ListType2>(props: ComboBoxProProps<D>): JSX.Element;
|
package/lib/IntInputField.d.ts
CHANGED
|
@@ -4,8 +4,52 @@ import { InputFieldProps } from "./InputField";
|
|
|
4
4
|
/**
|
|
5
5
|
* Integer input field props
|
|
6
6
|
*/
|
|
7
|
-
export type IntInputFieldProps = Omit<InputFieldProps, "type" | "inputProps"> & InputBaseProps["inputProps"]
|
|
7
|
+
export type IntInputFieldProps = Omit<InputFieldProps, "type" | "inputProps" | "value"> & InputBaseProps["inputProps"] & {
|
|
8
|
+
/**
|
|
9
|
+
* Display minus and plus buttons
|
|
10
|
+
*/
|
|
11
|
+
buttons?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* End symbol
|
|
14
|
+
*/
|
|
15
|
+
endSymbol?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Start (Currency) symbol
|
|
18
|
+
*/
|
|
19
|
+
symbol?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Value
|
|
22
|
+
*/
|
|
23
|
+
value?: number;
|
|
24
|
+
/**
|
|
25
|
+
* On value change callback
|
|
26
|
+
* @param value Value
|
|
27
|
+
*/
|
|
28
|
+
onValueChange?: (value: number | undefined, init: boolean) => void;
|
|
29
|
+
};
|
|
8
30
|
/**
|
|
9
31
|
* Integer input field
|
|
10
32
|
*/
|
|
11
|
-
export declare const IntInputField: React.ForwardRefExoticComponent<Omit<Omit<InputFieldProps, "type" | "inputProps"> & import("@mui/material").InputBaseComponentProps
|
|
33
|
+
export declare const IntInputField: React.ForwardRefExoticComponent<Omit<Omit<InputFieldProps, "type" | "value" | "inputProps"> & import("@mui/material").InputBaseComponentProps & {
|
|
34
|
+
/**
|
|
35
|
+
* Display minus and plus buttons
|
|
36
|
+
*/
|
|
37
|
+
buttons?: boolean | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* End symbol
|
|
40
|
+
*/
|
|
41
|
+
endSymbol?: string | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* Start (Currency) symbol
|
|
44
|
+
*/
|
|
45
|
+
symbol?: string | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* Value
|
|
48
|
+
*/
|
|
49
|
+
value?: number | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* On value change callback
|
|
52
|
+
* @param value Value
|
|
53
|
+
*/
|
|
54
|
+
onValueChange?: ((value: number | undefined, init: boolean) => void) | undefined;
|
|
55
|
+
}, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
package/lib/IntInputField.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { Box, IconButton, InputAdornment } from "@mui/material";
|
|
2
|
+
import AddIcon from "@mui/icons-material/Add";
|
|
3
|
+
import RemoveIcon from "@mui/icons-material/Remove";
|
|
1
4
|
import React from "react";
|
|
2
5
|
import { InputField } from "./InputField";
|
|
3
6
|
/**
|
|
@@ -5,7 +8,82 @@ import { InputField } from "./InputField";
|
|
|
5
8
|
*/
|
|
6
9
|
export const IntInputField = React.forwardRef((props, ref) => {
|
|
7
10
|
// Destruct
|
|
8
|
-
const { min = 0, step = 1, max = 9999999, ...rest } = props;
|
|
11
|
+
const { min = 0, step = 1, max = 9999999, style = { textAlign: "right" }, buttons, endSymbol, symbol, value, defaultValue, onChange, onValueChange, ...rest } = props;
|
|
12
|
+
// State
|
|
13
|
+
const [localValue, setLocalValue] = React.useState();
|
|
14
|
+
const setValue = (value, init = false) => {
|
|
15
|
+
setLocalValue(value);
|
|
16
|
+
if (onValueChange)
|
|
17
|
+
onValueChange(value, init);
|
|
18
|
+
};
|
|
19
|
+
React.useEffect(() => {
|
|
20
|
+
setValue(value, true);
|
|
21
|
+
}, [value]);
|
|
22
|
+
React.useEffect(() => {
|
|
23
|
+
if (defaultValue == null || typeof defaultValue === "object")
|
|
24
|
+
return;
|
|
25
|
+
const value = typeof defaultValue === "number"
|
|
26
|
+
? defaultValue
|
|
27
|
+
: parseFloat(defaultValue);
|
|
28
|
+
if (!isNaN(value))
|
|
29
|
+
setValue(value, true);
|
|
30
|
+
}, [defaultValue]);
|
|
9
31
|
// Layout
|
|
10
|
-
|
|
32
|
+
const layout = (React.createElement(InputField, { ref: ref, type: "number", value: localValue == null ? "" : localValue, inputProps: {
|
|
33
|
+
min,
|
|
34
|
+
step,
|
|
35
|
+
max,
|
|
36
|
+
style,
|
|
37
|
+
inputMode: "numeric"
|
|
38
|
+
}, InputProps: {
|
|
39
|
+
startAdornment: symbol ? (React.createElement(React.Fragment, null,
|
|
40
|
+
React.createElement(InputAdornment, { position: "start" }, symbol))) : undefined,
|
|
41
|
+
endAdornment: endSymbol ? (React.createElement(InputAdornment, { position: "end" }, endSymbol)) : undefined
|
|
42
|
+
}, sx: {
|
|
43
|
+
"& input[type=number]::-webkit-inner-spin-button": {
|
|
44
|
+
WebkitAppearance: "none",
|
|
45
|
+
margin: 0
|
|
46
|
+
},
|
|
47
|
+
"& input[type=number]::-webkit-outer-spin-button": {
|
|
48
|
+
WebkitAppearance: "none",
|
|
49
|
+
margin: 0
|
|
50
|
+
}
|
|
51
|
+
}, onChange: (event) => {
|
|
52
|
+
const value = parseFloat(event.target.value);
|
|
53
|
+
if (isNaN(value))
|
|
54
|
+
setValue(undefined);
|
|
55
|
+
else if (value > max)
|
|
56
|
+
setValue(max);
|
|
57
|
+
else if (value < min)
|
|
58
|
+
setValue(min);
|
|
59
|
+
else
|
|
60
|
+
setValue(value);
|
|
61
|
+
if (onChange)
|
|
62
|
+
onChange(event);
|
|
63
|
+
}, ...rest }));
|
|
64
|
+
if (buttons)
|
|
65
|
+
return (React.createElement(Box, { sx: { display: "flex", alignItems: "flex-end", gap: 0.5 } },
|
|
66
|
+
React.createElement(IconButton, { size: "small", onClick: () => {
|
|
67
|
+
if (localValue == null)
|
|
68
|
+
return;
|
|
69
|
+
if (localValue <= min)
|
|
70
|
+
setValue(undefined);
|
|
71
|
+
else
|
|
72
|
+
setValue(localValue - step);
|
|
73
|
+
} },
|
|
74
|
+
React.createElement(RemoveIcon, null)),
|
|
75
|
+
layout,
|
|
76
|
+
React.createElement(IconButton, { size: "small", onClick: () => {
|
|
77
|
+
if (localValue == null) {
|
|
78
|
+
setValue(min);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (localValue >= max)
|
|
82
|
+
return;
|
|
83
|
+
else
|
|
84
|
+
setValue(localValue + step);
|
|
85
|
+
} },
|
|
86
|
+
React.createElement(AddIcon, { color: localValue == null ? undefined : "primary" }))));
|
|
87
|
+
else
|
|
88
|
+
return layout;
|
|
11
89
|
});
|
package/lib/MoneyInputField.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { InputBaseProps } from "@mui/material";
|
|
2
1
|
import React from "react";
|
|
3
|
-
import {
|
|
2
|
+
import { IntInputFieldProps } from "./IntInputField";
|
|
4
3
|
/**
|
|
5
4
|
* Money input field props
|
|
6
5
|
*/
|
|
7
|
-
export type MoneyInputFieldProps =
|
|
6
|
+
export type MoneyInputFieldProps = IntInputFieldProps & {};
|
|
8
7
|
/**
|
|
9
8
|
* Money input field
|
|
10
9
|
*/
|
|
11
|
-
export declare const MoneyInputField: React.ForwardRefExoticComponent<Omit<
|
|
10
|
+
export declare const MoneyInputField: React.ForwardRefExoticComponent<Omit<MoneyInputFieldProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
package/lib/MoneyInputField.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { IntInputField } from "./IntInputField";
|
|
3
3
|
/**
|
|
4
4
|
* Money input field
|
|
5
5
|
*/
|
|
6
6
|
export const MoneyInputField = React.forwardRef((props, ref) => {
|
|
7
7
|
// Destruct
|
|
8
|
-
const {
|
|
8
|
+
const { step = 0.01, ...rest } = props;
|
|
9
9
|
// Layout
|
|
10
|
-
return
|
|
10
|
+
return React.createElement(IntInputField, { ref: ref, step: step, ...rest });
|
|
11
11
|
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { ListType2 } from "@etsoo/shared";
|
|
2
|
+
import { ListItemButtonProps, ListItemProps, StackProps } from "@mui/material";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { InputFieldProps } from "./InputField";
|
|
5
|
+
/**
|
|
6
|
+
* Quick list props
|
|
7
|
+
*/
|
|
8
|
+
export type QuickListProps<T extends ListType2 = ListType2> = StackProps & {
|
|
9
|
+
/**
|
|
10
|
+
* Button props
|
|
11
|
+
*/
|
|
12
|
+
buttonProps?: ListItemButtonProps;
|
|
13
|
+
/**
|
|
14
|
+
* Label
|
|
15
|
+
*/
|
|
16
|
+
label?: string;
|
|
17
|
+
/**
|
|
18
|
+
* No matches label
|
|
19
|
+
*/
|
|
20
|
+
noMatchesLabel?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Input field props
|
|
23
|
+
*/
|
|
24
|
+
inputProps?: Omit<InputFieldProps, "onChangeDelay">;
|
|
25
|
+
/**
|
|
26
|
+
* Get item label
|
|
27
|
+
* @param item Current item
|
|
28
|
+
* @returns Item label
|
|
29
|
+
*/
|
|
30
|
+
itemLabel?: (item: T) => string;
|
|
31
|
+
/**
|
|
32
|
+
* Item renderer
|
|
33
|
+
* @param item Current item
|
|
34
|
+
* @returns UI
|
|
35
|
+
*/
|
|
36
|
+
itemRenderer?: (item: T) => React.ReactNode;
|
|
37
|
+
/**
|
|
38
|
+
* List item props
|
|
39
|
+
*/
|
|
40
|
+
itemProps?: ListItemProps;
|
|
41
|
+
/**
|
|
42
|
+
* Load data callback
|
|
43
|
+
*/
|
|
44
|
+
loadData: (keyword: string | undefined) => PromiseLike<T[] | undefined>;
|
|
45
|
+
/**
|
|
46
|
+
* On item click
|
|
47
|
+
* @param item Clicked item
|
|
48
|
+
*/
|
|
49
|
+
onItemClick?: (item: T) => void;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Quick list
|
|
53
|
+
* @param props Props
|
|
54
|
+
* @returns Component
|
|
55
|
+
*/
|
|
56
|
+
export declare function QuickList<T extends ListType2 = ListType2>(props: QuickListProps<T>): JSX.Element;
|
package/lib/QuickList.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { LinearProgress, List, ListItem, ListItemButton, Typography } from "@mui/material";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { InputField } from "./InputField";
|
|
4
|
+
import { globalApp } from "./app/ReactApp";
|
|
5
|
+
import { VBox } from "./FlexBox";
|
|
6
|
+
/**
|
|
7
|
+
* Quick list
|
|
8
|
+
* @param props Props
|
|
9
|
+
* @returns Component
|
|
10
|
+
*/
|
|
11
|
+
export function QuickList(props) {
|
|
12
|
+
// Destruct
|
|
13
|
+
const { buttonProps = {}, label, inputProps, itemLabel = (item) => ("label" in item ? item.label : item.name), itemRenderer = (item) => itemLabel(item), itemProps, loadData, noMatchesLabel = globalApp === null || globalApp === void 0 ? void 0 : globalApp.get("noMatches"), gap = 1, height = "480px", onItemClick, ...rest } = props;
|
|
14
|
+
const { onClick, ...buttonRest } = buttonProps;
|
|
15
|
+
// States
|
|
16
|
+
const [loading, setLoading] = React.useState(false);
|
|
17
|
+
const [items, setItems] = React.useState([]);
|
|
18
|
+
const loadDataLocal = (keyword) => {
|
|
19
|
+
setLoading(true);
|
|
20
|
+
loadData(keyword).then((result) => {
|
|
21
|
+
setLoading(false);
|
|
22
|
+
setItems(result !== null && result !== void 0 ? result : []);
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
React.useEffect(() => {
|
|
26
|
+
loadDataLocal();
|
|
27
|
+
}, []);
|
|
28
|
+
// Layout
|
|
29
|
+
return (React.createElement(VBox, { gap: gap, height: height, ...rest },
|
|
30
|
+
React.createElement(InputField, { label: label, changeDelay: 480, onChangeDelay: (event) => {
|
|
31
|
+
// Stop bubble
|
|
32
|
+
event.preventDefault();
|
|
33
|
+
event.stopPropagation();
|
|
34
|
+
loadDataLocal(event.target.value);
|
|
35
|
+
}, fullWidth: true, ...inputProps }),
|
|
36
|
+
loading ? (React.createElement(LinearProgress, null)) : items.length === 0 ? (React.createElement(Typography, { textAlign: "center" }, noMatchesLabel)) : (React.createElement(List, null, items.map((item) => (React.createElement(ListItem, { key: item.id, disablePadding: true, ...itemProps },
|
|
37
|
+
React.createElement(ListItemButton, { onClick: (event) => {
|
|
38
|
+
if (onClick)
|
|
39
|
+
onClick(event);
|
|
40
|
+
if (!event.defaultPrevented && onItemClick)
|
|
41
|
+
onItemClick(item);
|
|
42
|
+
}, ...buttonRest }, itemRenderer(item)))))))));
|
|
43
|
+
}
|
package/lib/TagListPro.d.ts
CHANGED
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import { AutocompleteProps } from "@mui/material";
|
|
3
3
|
import { InputFieldProps } from "./InputField";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
} & ({
|
|
7
|
-
label: string;
|
|
8
|
-
} | {
|
|
9
|
-
name: string;
|
|
10
|
-
});
|
|
11
|
-
export type TagListProProps<D extends DataType = DataType> = Omit<AutocompleteProps<D, true, false, false>, "open" | "multiple" | "options" | "renderInput"> & {
|
|
4
|
+
import { ListType2 } from "@etsoo/shared";
|
|
5
|
+
export type TagListProProps<D extends ListType2 = ListType2> = Omit<AutocompleteProps<D, true, false, false>, "open" | "multiple" | "options" | "renderInput"> & {
|
|
12
6
|
/**
|
|
13
7
|
* Label
|
|
14
8
|
*/
|
|
@@ -26,5 +20,4 @@ export type TagListProProps<D extends DataType = DataType> = Omit<AutocompletePr
|
|
|
26
20
|
*/
|
|
27
21
|
maxItems?: number;
|
|
28
22
|
};
|
|
29
|
-
export declare function TagListPro<D extends
|
|
30
|
-
export {};
|
|
23
|
+
export declare function TagListPro<D extends ListType2 = ListType2>(props: TagListProProps<D>): JSX.Element;
|
package/lib/index.d.ts
CHANGED
|
@@ -71,6 +71,7 @@ export * from "./OptionGroup";
|
|
|
71
71
|
export * from "./PList";
|
|
72
72
|
export * from "./ProgressCount";
|
|
73
73
|
export * from "./PullToRefreshUI";
|
|
74
|
+
export * from "./QuickList";
|
|
74
75
|
export * from "./ResponsibleContainer";
|
|
75
76
|
export * from "./ScrollerListEx";
|
|
76
77
|
export * from "./ScrollTopFab";
|
package/lib/index.js
CHANGED
|
@@ -71,6 +71,7 @@ export * from "./OptionGroup";
|
|
|
71
71
|
export * from "./PList";
|
|
72
72
|
export * from "./ProgressCount";
|
|
73
73
|
export * from "./PullToRefreshUI";
|
|
74
|
+
export * from "./QuickList";
|
|
74
75
|
export * from "./ResponsibleContainer";
|
|
75
76
|
export * from "./ScrollerListEx";
|
|
76
77
|
export * from "./ScrollTopFab";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etsoo/materialui",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.82",
|
|
4
4
|
"description": "TypeScript Material-UI Implementation",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -50,13 +50,13 @@
|
|
|
50
50
|
"@emotion/css": "^11.10.6",
|
|
51
51
|
"@emotion/react": "^11.10.6",
|
|
52
52
|
"@emotion/styled": "^11.10.6",
|
|
53
|
-
"@etsoo/appscript": "^1.3.
|
|
53
|
+
"@etsoo/appscript": "^1.3.86",
|
|
54
54
|
"@etsoo/notificationbase": "^1.1.24",
|
|
55
|
-
"@etsoo/react": "^1.6.
|
|
56
|
-
"@etsoo/shared": "^1.1.
|
|
55
|
+
"@etsoo/react": "^1.6.57",
|
|
56
|
+
"@etsoo/shared": "^1.1.95",
|
|
57
57
|
"@mui/icons-material": "^5.11.11",
|
|
58
58
|
"@mui/material": "^5.11.15",
|
|
59
|
-
"@mui/x-data-grid": "^6.0.
|
|
59
|
+
"@mui/x-data-grid": "^6.0.4",
|
|
60
60
|
"@types/pica": "^9.0.1",
|
|
61
61
|
"@types/pulltorefreshjs": "^0.1.5",
|
|
62
62
|
"@types/react": "^18.0.31",
|
|
@@ -89,6 +89,6 @@
|
|
|
89
89
|
"@typescript-eslint/parser": "^5.57.0",
|
|
90
90
|
"jest": "^29.5.0",
|
|
91
91
|
"jest-environment-jsdom": "^29.5.0",
|
|
92
|
-
"typescript": "^5.0.
|
|
92
|
+
"typescript": "^5.0.3"
|
|
93
93
|
}
|
|
94
94
|
}
|
package/src/ComboBoxPro.tsx
CHANGED
|
@@ -2,12 +2,9 @@ import { Autocomplete, AutocompleteProps } from "@mui/material";
|
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { globalApp } from "./app/ReactApp";
|
|
4
4
|
import { InputField, InputFieldProps } from "./InputField";
|
|
5
|
+
import { ListType2 } from "@etsoo/shared";
|
|
5
6
|
|
|
6
|
-
type
|
|
7
|
-
id: number | string;
|
|
8
|
-
} & ({ label: string } | { name: string });
|
|
9
|
-
|
|
10
|
-
export type ComboBoxProProps<D extends DataType = DataType> = Omit<
|
|
7
|
+
export type ComboBoxProProps<D extends ListType2 = ListType2> = Omit<
|
|
11
8
|
AutocompleteProps<D, false, false, true>,
|
|
12
9
|
"open" | "multiple" | "options" | "renderInput"
|
|
13
10
|
> & {
|
|
@@ -37,7 +34,7 @@ export type ComboBoxProProps<D extends DataType = DataType> = Omit<
|
|
|
37
34
|
inputProps?: Omit<InputFieldProps, "onChange">;
|
|
38
35
|
};
|
|
39
36
|
|
|
40
|
-
export function ComboBoxPro<D extends
|
|
37
|
+
export function ComboBoxPro<D extends ListType2 = ListType2>(
|
|
41
38
|
props: ComboBoxProProps<D>
|
|
42
39
|
) {
|
|
43
40
|
// Labels
|
package/src/IntInputField.tsx
CHANGED
|
@@ -1,12 +1,43 @@
|
|
|
1
|
-
import { InputBaseProps } from "@mui/material";
|
|
1
|
+
import { Box, IconButton, InputAdornment, InputBaseProps } from "@mui/material";
|
|
2
|
+
import AddIcon from "@mui/icons-material/Add";
|
|
3
|
+
import RemoveIcon from "@mui/icons-material/Remove";
|
|
2
4
|
import React from "react";
|
|
3
5
|
import { InputField, InputFieldProps } from "./InputField";
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
* Integer input field props
|
|
7
9
|
*/
|
|
8
|
-
export type IntInputFieldProps = Omit<
|
|
9
|
-
|
|
10
|
+
export type IntInputFieldProps = Omit<
|
|
11
|
+
InputFieldProps,
|
|
12
|
+
"type" | "inputProps" | "value"
|
|
13
|
+
> &
|
|
14
|
+
InputBaseProps["inputProps"] & {
|
|
15
|
+
/**
|
|
16
|
+
* Display minus and plus buttons
|
|
17
|
+
*/
|
|
18
|
+
buttons?: boolean;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* End symbol
|
|
22
|
+
*/
|
|
23
|
+
endSymbol?: string;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Start (Currency) symbol
|
|
27
|
+
*/
|
|
28
|
+
symbol?: string;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Value
|
|
32
|
+
*/
|
|
33
|
+
value?: number;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* On value change callback
|
|
37
|
+
* @param value Value
|
|
38
|
+
*/
|
|
39
|
+
onValueChange?: (value: number | undefined, init: boolean) => void;
|
|
40
|
+
};
|
|
10
41
|
|
|
11
42
|
/**
|
|
12
43
|
* Integer input field
|
|
@@ -16,15 +47,115 @@ export const IntInputField = React.forwardRef<
|
|
|
16
47
|
IntInputFieldProps
|
|
17
48
|
>((props, ref) => {
|
|
18
49
|
// Destruct
|
|
19
|
-
const {
|
|
50
|
+
const {
|
|
51
|
+
min = 0,
|
|
52
|
+
step = 1,
|
|
53
|
+
max = 9999999,
|
|
54
|
+
style = { textAlign: "right" },
|
|
55
|
+
buttons,
|
|
56
|
+
endSymbol,
|
|
57
|
+
symbol,
|
|
58
|
+
value,
|
|
59
|
+
defaultValue,
|
|
60
|
+
onChange,
|
|
61
|
+
onValueChange,
|
|
62
|
+
...rest
|
|
63
|
+
} = props;
|
|
64
|
+
|
|
65
|
+
// State
|
|
66
|
+
const [localValue, setLocalValue] = React.useState<number>();
|
|
67
|
+
|
|
68
|
+
const setValue = (value: number | undefined, init: boolean = false) => {
|
|
69
|
+
setLocalValue(value);
|
|
70
|
+
if (onValueChange) onValueChange(value, init);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
React.useEffect(() => {
|
|
74
|
+
setValue(value, true);
|
|
75
|
+
}, [value]);
|
|
76
|
+
|
|
77
|
+
React.useEffect(() => {
|
|
78
|
+
if (defaultValue == null || typeof defaultValue === "object") return;
|
|
79
|
+
const value =
|
|
80
|
+
typeof defaultValue === "number"
|
|
81
|
+
? defaultValue
|
|
82
|
+
: parseFloat(defaultValue);
|
|
83
|
+
if (!isNaN(value)) setValue(value, true);
|
|
84
|
+
}, [defaultValue]);
|
|
20
85
|
|
|
21
86
|
// Layout
|
|
22
|
-
|
|
87
|
+
const layout = (
|
|
23
88
|
<InputField
|
|
24
89
|
ref={ref}
|
|
25
90
|
type="number"
|
|
26
|
-
|
|
91
|
+
value={localValue == null ? "" : localValue}
|
|
92
|
+
inputProps={{
|
|
93
|
+
min,
|
|
94
|
+
step,
|
|
95
|
+
max,
|
|
96
|
+
style,
|
|
97
|
+
inputMode: "numeric"
|
|
98
|
+
}}
|
|
99
|
+
InputProps={{
|
|
100
|
+
startAdornment: symbol ? (
|
|
101
|
+
<React.Fragment>
|
|
102
|
+
<InputAdornment position="start">{symbol}</InputAdornment>
|
|
103
|
+
</React.Fragment>
|
|
104
|
+
) : undefined,
|
|
105
|
+
endAdornment: endSymbol ? (
|
|
106
|
+
<InputAdornment position="end">{endSymbol}</InputAdornment>
|
|
107
|
+
) : undefined
|
|
108
|
+
}}
|
|
109
|
+
sx={{
|
|
110
|
+
"& input[type=number]::-webkit-inner-spin-button": {
|
|
111
|
+
WebkitAppearance: "none",
|
|
112
|
+
margin: 0
|
|
113
|
+
},
|
|
114
|
+
"& input[type=number]::-webkit-outer-spin-button": {
|
|
115
|
+
WebkitAppearance: "none",
|
|
116
|
+
margin: 0
|
|
117
|
+
}
|
|
118
|
+
}}
|
|
119
|
+
onChange={(event) => {
|
|
120
|
+
const value = parseFloat(event.target.value);
|
|
121
|
+
if (isNaN(value)) setValue(undefined);
|
|
122
|
+
else if (value > max) setValue(max);
|
|
123
|
+
else if (value < min) setValue(min);
|
|
124
|
+
else setValue(value);
|
|
125
|
+
if (onChange) onChange(event);
|
|
126
|
+
}}
|
|
27
127
|
{...rest}
|
|
28
128
|
/>
|
|
29
129
|
);
|
|
130
|
+
|
|
131
|
+
if (buttons)
|
|
132
|
+
return (
|
|
133
|
+
<Box sx={{ display: "flex", alignItems: "flex-end", gap: 0.5 }}>
|
|
134
|
+
<IconButton
|
|
135
|
+
size="small"
|
|
136
|
+
onClick={() => {
|
|
137
|
+
if (localValue == null) return;
|
|
138
|
+
if (localValue <= min) setValue(undefined);
|
|
139
|
+
else setValue(localValue - step);
|
|
140
|
+
}}
|
|
141
|
+
>
|
|
142
|
+
<RemoveIcon />
|
|
143
|
+
</IconButton>
|
|
144
|
+
{layout}
|
|
145
|
+
<IconButton
|
|
146
|
+
size="small"
|
|
147
|
+
onClick={() => {
|
|
148
|
+
if (localValue == null) {
|
|
149
|
+
setValue(min);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (localValue >= max) return;
|
|
153
|
+
else setValue(localValue + step);
|
|
154
|
+
}}
|
|
155
|
+
>
|
|
156
|
+
<AddIcon color={localValue == null ? undefined : "primary"} />
|
|
157
|
+
</IconButton>
|
|
158
|
+
</Box>
|
|
159
|
+
);
|
|
160
|
+
else return layout;
|
|
30
161
|
});
|
package/src/MoneyInputField.tsx
CHANGED
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
import { InputBaseProps } from "@mui/material";
|
|
2
1
|
import React from "react";
|
|
3
|
-
import {
|
|
2
|
+
import { IntInputField, IntInputFieldProps } from "./IntInputField";
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* Money input field props
|
|
7
6
|
*/
|
|
8
|
-
export type MoneyInputFieldProps =
|
|
9
|
-
InputFieldProps,
|
|
10
|
-
"type" | "inputProps"
|
|
11
|
-
> &
|
|
12
|
-
InputBaseProps["inputProps"];
|
|
7
|
+
export type MoneyInputFieldProps = IntInputFieldProps & {};
|
|
13
8
|
|
|
14
9
|
/**
|
|
15
10
|
* Money input field
|
|
@@ -19,15 +14,8 @@ export const MoneyInputField = React.forwardRef<
|
|
|
19
14
|
MoneyInputFieldProps
|
|
20
15
|
>((props, ref) => {
|
|
21
16
|
// Destruct
|
|
22
|
-
const {
|
|
17
|
+
const { step = 0.01, ...rest } = props;
|
|
23
18
|
|
|
24
19
|
// Layout
|
|
25
|
-
return
|
|
26
|
-
<InputField
|
|
27
|
-
ref={ref}
|
|
28
|
-
type="number"
|
|
29
|
-
inputProps={{ min, step, max, inputMode: "numeric" }}
|
|
30
|
-
{...rest}
|
|
31
|
-
/>
|
|
32
|
-
);
|
|
20
|
+
return <IntInputField ref={ref} step={step} {...rest} />;
|
|
33
21
|
});
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { ListType2 } from "@etsoo/shared";
|
|
2
|
+
import {
|
|
3
|
+
LinearProgress,
|
|
4
|
+
List,
|
|
5
|
+
ListItem,
|
|
6
|
+
ListItemButton,
|
|
7
|
+
ListItemButtonProps,
|
|
8
|
+
ListItemProps,
|
|
9
|
+
StackProps,
|
|
10
|
+
Typography
|
|
11
|
+
} from "@mui/material";
|
|
12
|
+
import React from "react";
|
|
13
|
+
import { InputField, InputFieldProps } from "./InputField";
|
|
14
|
+
import { globalApp } from "./app/ReactApp";
|
|
15
|
+
import { VBox } from "./FlexBox";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Quick list props
|
|
19
|
+
*/
|
|
20
|
+
export type QuickListProps<T extends ListType2 = ListType2> = StackProps & {
|
|
21
|
+
/**
|
|
22
|
+
* Button props
|
|
23
|
+
*/
|
|
24
|
+
buttonProps?: ListItemButtonProps;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Label
|
|
28
|
+
*/
|
|
29
|
+
label?: string;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* No matches label
|
|
33
|
+
*/
|
|
34
|
+
noMatchesLabel?: string;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Input field props
|
|
38
|
+
*/
|
|
39
|
+
inputProps?: Omit<InputFieldProps, "onChangeDelay">;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Get item label
|
|
43
|
+
* @param item Current item
|
|
44
|
+
* @returns Item label
|
|
45
|
+
*/
|
|
46
|
+
itemLabel?: (item: T) => string;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Item renderer
|
|
50
|
+
* @param item Current item
|
|
51
|
+
* @returns UI
|
|
52
|
+
*/
|
|
53
|
+
itemRenderer?: (item: T) => React.ReactNode;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* List item props
|
|
57
|
+
*/
|
|
58
|
+
itemProps?: ListItemProps;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Load data callback
|
|
62
|
+
*/
|
|
63
|
+
loadData: (keyword: string | undefined) => PromiseLike<T[] | undefined>;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* On item click
|
|
67
|
+
* @param item Clicked item
|
|
68
|
+
*/
|
|
69
|
+
onItemClick?: (item: T) => void;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Quick list
|
|
74
|
+
* @param props Props
|
|
75
|
+
* @returns Component
|
|
76
|
+
*/
|
|
77
|
+
export function QuickList<T extends ListType2 = ListType2>(
|
|
78
|
+
props: QuickListProps<T>
|
|
79
|
+
) {
|
|
80
|
+
// Destruct
|
|
81
|
+
const {
|
|
82
|
+
buttonProps = {},
|
|
83
|
+
label,
|
|
84
|
+
inputProps,
|
|
85
|
+
itemLabel = (item: T) => ("label" in item ? item.label : item.name),
|
|
86
|
+
itemRenderer = (item: T) => itemLabel(item),
|
|
87
|
+
itemProps,
|
|
88
|
+
loadData,
|
|
89
|
+
noMatchesLabel = globalApp?.get("noMatches"),
|
|
90
|
+
gap = 1,
|
|
91
|
+
height = "480px",
|
|
92
|
+
onItemClick,
|
|
93
|
+
...rest
|
|
94
|
+
} = props;
|
|
95
|
+
|
|
96
|
+
const { onClick, ...buttonRest } = buttonProps;
|
|
97
|
+
|
|
98
|
+
// States
|
|
99
|
+
const [loading, setLoading] = React.useState(false);
|
|
100
|
+
const [items, setItems] = React.useState<T[]>([]);
|
|
101
|
+
|
|
102
|
+
const loadDataLocal = (keyword?: string) => {
|
|
103
|
+
setLoading(true);
|
|
104
|
+
|
|
105
|
+
loadData(keyword).then((result) => {
|
|
106
|
+
setLoading(false);
|
|
107
|
+
setItems(result ?? []);
|
|
108
|
+
});
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
React.useEffect(() => {
|
|
112
|
+
loadDataLocal();
|
|
113
|
+
}, []);
|
|
114
|
+
|
|
115
|
+
// Layout
|
|
116
|
+
return (
|
|
117
|
+
<VBox gap={gap} height={height} {...rest}>
|
|
118
|
+
<InputField
|
|
119
|
+
label={label}
|
|
120
|
+
changeDelay={480}
|
|
121
|
+
onChangeDelay={(event) => {
|
|
122
|
+
// Stop bubble
|
|
123
|
+
event.preventDefault();
|
|
124
|
+
event.stopPropagation();
|
|
125
|
+
loadDataLocal(event.target.value);
|
|
126
|
+
}}
|
|
127
|
+
fullWidth
|
|
128
|
+
{...inputProps}
|
|
129
|
+
/>
|
|
130
|
+
{loading ? (
|
|
131
|
+
<LinearProgress />
|
|
132
|
+
) : items.length === 0 ? (
|
|
133
|
+
<Typography textAlign="center">{noMatchesLabel}</Typography>
|
|
134
|
+
) : (
|
|
135
|
+
<List>
|
|
136
|
+
{items.map((item) => (
|
|
137
|
+
<ListItem key={item.id} disablePadding {...itemProps}>
|
|
138
|
+
<ListItemButton
|
|
139
|
+
onClick={(event) => {
|
|
140
|
+
if (onClick) onClick(event);
|
|
141
|
+
if (!event.defaultPrevented && onItemClick) onItemClick(item);
|
|
142
|
+
}}
|
|
143
|
+
{...buttonRest}
|
|
144
|
+
>
|
|
145
|
+
{itemRenderer(item)}
|
|
146
|
+
</ListItemButton>
|
|
147
|
+
</ListItem>
|
|
148
|
+
))}
|
|
149
|
+
</List>
|
|
150
|
+
)}
|
|
151
|
+
</VBox>
|
|
152
|
+
);
|
|
153
|
+
}
|
package/src/TagListPro.tsx
CHANGED
|
@@ -4,12 +4,9 @@ import CheckBoxIcon from "@mui/icons-material/CheckBox";
|
|
|
4
4
|
import React from "react";
|
|
5
5
|
import { InputField, InputFieldProps } from "./InputField";
|
|
6
6
|
import { globalApp } from "./app/ReactApp";
|
|
7
|
+
import { ListType2 } from "@etsoo/shared";
|
|
7
8
|
|
|
8
|
-
type
|
|
9
|
-
id: number | string;
|
|
10
|
-
} & ({ label: string } | { name: string });
|
|
11
|
-
|
|
12
|
-
export type TagListProProps<D extends DataType = DataType> = Omit<
|
|
9
|
+
export type TagListProProps<D extends ListType2 = ListType2> = Omit<
|
|
13
10
|
AutocompleteProps<D, true, false, false>,
|
|
14
11
|
"open" | "multiple" | "options" | "renderInput"
|
|
15
12
|
> & {
|
|
@@ -37,7 +34,7 @@ export type TagListProProps<D extends DataType = DataType> = Omit<
|
|
|
37
34
|
maxItems?: number;
|
|
38
35
|
};
|
|
39
36
|
|
|
40
|
-
export function TagListPro<D extends
|
|
37
|
+
export function TagListPro<D extends ListType2 = ListType2>(
|
|
41
38
|
props: TagListProProps<D>
|
|
42
39
|
) {
|
|
43
40
|
// Labels
|
package/src/index.ts
CHANGED
|
@@ -74,6 +74,7 @@ export * from "./OptionGroup";
|
|
|
74
74
|
export * from "./PList";
|
|
75
75
|
export * from "./ProgressCount";
|
|
76
76
|
export * from "./PullToRefreshUI";
|
|
77
|
+
export * from "./QuickList";
|
|
77
78
|
export * from "./ResponsibleContainer";
|
|
78
79
|
export * from "./ScrollerListEx";
|
|
79
80
|
export * from "./ScrollTopFab";
|