@etsoo/materialui 1.2.10 → 1.2.12

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.
@@ -1,10 +1,10 @@
1
- import { DataTypes } from '@etsoo/shared';
2
- import { AutocompleteProps } from '@mui/material';
3
- import { ChangeEventHandler } from 'react';
1
+ import { DataTypes } from "@etsoo/shared";
2
+ import { AutocompleteProps } from "@mui/material";
3
+ import { ChangeEventHandler } from "react";
4
4
  /**
5
5
  * Autocomplete extended props
6
6
  */
7
- export type AutocompleteExtendedProps<T extends object, D extends DataTypes.Keys<T>, M extends boolean | undefined = boolean | undefined> = Omit<AutocompleteProps<T, M, false, false>, 'renderInput' | 'options' | 'multiple'> & {
7
+ export type AutocompleteExtendedProps<T extends object, D extends DataTypes.Keys<T>, M extends boolean | undefined = boolean | undefined> = Omit<AutocompleteProps<T, M, false, false>, "renderInput" | "options" | "multiple"> & {
8
8
  /**
9
9
  * Id field
10
10
  */
@@ -30,7 +30,7 @@ export type AutocompleteExtendedProps<T extends object, D extends DataTypes.Keys
30
30
  * If `dense` or `normal`, will adjust vertical spacing of this and contained components.
31
31
  * @default 'none'
32
32
  */
33
- inputMargin?: 'dense' | 'normal' | 'none';
33
+ inputMargin?: "dense" | "normal" | "none";
34
34
  /**
35
35
  * Input onChange hanlder
36
36
  */
@@ -44,7 +44,7 @@ export type AutocompleteExtendedProps<T extends object, D extends DataTypes.Keys
44
44
  * The variant to use.
45
45
  * @default 'outlined'
46
46
  */
47
- inputVariant?: 'standard' | 'outlined' | 'filled';
47
+ inputVariant?: "standard" | "outlined" | "filled";
48
48
  /**
49
49
  * Label of the field
50
50
  */
@@ -61,4 +61,9 @@ export type AutocompleteExtendedProps<T extends object, D extends DataTypes.Keys
61
61
  * Is search field?
62
62
  */
63
63
  search?: boolean;
64
+ /**
65
+ * Value change handler
66
+ * @param value New value
67
+ */
68
+ onValueChange?: (value: T | null) => void;
64
69
  };
package/lib/ComboBox.js CHANGED
@@ -15,7 +15,7 @@ export function ComboBox(props) {
15
15
  // Labels
16
16
  const labels = globalApp === null || globalApp === void 0 ? void 0 : globalApp.getLabels("noOptions", "loading", "open");
17
17
  // Destruct
18
- const { search = false, autoAddBlankItem = search, 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, disableCloseOnSelect = false, getOptionLabel = (option) => `${option[labelField]}`, sx = { minWidth: "150px" }, noOptionsText = labels === null || labels === void 0 ? void 0 : labels.noOptions, loadingText = labels === null || labels === void 0 ? void 0 : labels.loading, openText = labels === null || labels === void 0 ? void 0 : labels.open, ...rest } = props;
18
+ const { search = false, autoAddBlankItem = search, idField = "id", idValue, inputError, inputHelperText, inputMargin, inputOnChange, inputRequired, inputVariant, defaultValue, label, labelField = "label", loadData, onLoadData, name, inputAutoComplete = "off", options, dataReadonly = true, readOnly, onChange, onValueChange, openOnFocus = true, value, disableCloseOnSelect = false, getOptionLabel = (option) => `${option[labelField]}`, sx = { minWidth: "150px" }, noOptionsText = labels === null || labels === void 0 ? void 0 : labels.noOptions, loadingText = labels === null || labels === void 0 ? void 0 : labels.loading, openText = labels === null || labels === void 0 ? void 0 : labels.open, ...rest } = props;
19
19
  // Value input ref
20
20
  const inputRef = React.createRef();
21
21
  // Options state
@@ -43,6 +43,8 @@ export function ComboBox(props) {
43
43
  React.useEffect(() => {
44
44
  if (localValue != null && localValue != stateValue) {
45
45
  setStateValue(localValue);
46
+ if (onValueChange)
47
+ onValueChange(localValue);
46
48
  }
47
49
  }, [localValue]);
48
50
  // Add readOnly
@@ -114,5 +116,7 @@ export function ComboBox(props) {
114
116
  // Custom
115
117
  if (onChange != null)
116
118
  onChange(event, value, reason, details);
119
+ if (onValueChange)
120
+ onValueChange(value);
117
121
  }, 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, noOptionsText: noOptionsText, loadingText: loadingText, openText: openText, ...rest })));
118
122
  }
@@ -4,7 +4,7 @@ import { AutocompleteExtendedProps } from "./AutocompleteExtendedProps";
4
4
  /**
5
5
  * ComboBox multiple props
6
6
  */
7
- export type ComboBoxMultipleProps<T extends object = ListType, D extends DataTypes.Keys<T> = IdDefaultType<T>, L extends DataTypes.Keys<T, string> = LabelDefaultType<T>> = AutocompleteExtendedProps<T, D, true> & {
7
+ export type ComboBoxMultipleProps<T extends object = ListType, D extends DataTypes.Keys<T> = IdDefaultType<T>, L extends DataTypes.Keys<T, string> = LabelDefaultType<T>> = Omit<AutocompleteExtendedProps<T, D, true>, "onValueChange"> & {
8
8
  /**
9
9
  * Auto add blank item
10
10
  */
@@ -23,5 +23,10 @@ export type ComboBoxProProps<D extends ListType2 = ListType2> = Omit<Autocomplet
23
23
  * Input props
24
24
  */
25
25
  inputProps?: Omit<InputFieldProps, "onChange">;
26
+ /**
27
+ * Value change handler
28
+ * @param value New value
29
+ */
30
+ onValueChange?: (value: D | null) => void;
26
31
  };
27
32
  export declare function ComboBoxPro<D extends ListType2 = ListType2>(props: ComboBoxProProps<D>): JSX.Element;
@@ -7,7 +7,7 @@ export function ComboBoxPro(props) {
7
7
  // Labels
8
8
  const { noOptions, loading: loadingLabel, open: openDefault } = (_a = globalApp === null || globalApp === void 0 ? void 0 : globalApp.getLabels("noOptions", "loading", "open")) !== null && _a !== void 0 ? _a : {};
9
9
  // Destruct
10
- const { noOptionsText = noOptions, loadingText = loadingLabel, openText = openDefault, options, openOnFocus = true, label, inputProps, name, value, idValue, onChange, ...rest } = props;
10
+ const { noOptionsText = noOptions, loadingText = loadingLabel, openText = openDefault, options, openOnFocus = true, label, inputProps, name, value, idValue, onChange, onValueChange, ...rest } = props;
11
11
  const [open, setOpen] = React.useState(false);
12
12
  const [localOptions, setOptions] = React.useState([]);
13
13
  const [localValue, setValue] = React.useState(null);
@@ -21,11 +21,14 @@ export function ComboBoxPro(props) {
21
21
  if (idValue == null)
22
22
  return;
23
23
  const option = localOptions.find((option) => option.id === idValue);
24
- if (option)
24
+ if (option) {
25
25
  setValue(option);
26
+ if (onValueChange)
27
+ onValueChange(option);
28
+ }
26
29
  else
27
30
  setValue(null);
28
- }, [localOptions]);
31
+ }, [localOptions, idValue]);
29
32
  React.useEffect(() => {
30
33
  if (typeof options === "function") {
31
34
  setLoading(true);
@@ -54,5 +57,9 @@ export function ComboBoxPro(props) {
54
57
  setValue(value);
55
58
  if (onChange)
56
59
  onChange(event, value, reason, details);
60
+ if (onValueChange) {
61
+ if (typeof value === "object")
62
+ onValueChange(value == null ? null : value);
63
+ }
57
64
  }, ...rest }));
58
65
  }
package/lib/ItemList.d.ts CHANGED
@@ -41,7 +41,7 @@ export interface ItemListProps<T extends object, D extends DataTypes.Keys<T>, L
41
41
  */
42
42
  onClose?(item: T | undefined, changed: boolean): void;
43
43
  /**
44
- * Current selected language
44
+ * Current selected id
45
45
  */
46
46
  selectedValue?: T[D];
47
47
  /**
@@ -0,0 +1,8 @@
1
+ /// <reference types="react" />
2
+ import { CircularProgressProps, TypographyProps } from "@mui/material";
3
+ export type PercentCircularProgressProps = CircularProgressProps & {
4
+ value: number;
5
+ valueUnit?: string;
6
+ textProps?: TypographyProps<"div">;
7
+ };
8
+ export declare function PercentCircularProgress(props: PercentCircularProgressProps): JSX.Element;
@@ -0,0 +1,20 @@
1
+ import { Box, CircularProgress, Typography } from "@mui/material";
2
+ import React from "react";
3
+ export function PercentCircularProgress(props) {
4
+ // Destruct
5
+ const { textProps, valueUnit = "%", ...rest } = props;
6
+ // Component
7
+ return (React.createElement(Box, { sx: { position: "relative", display: "inline-flex" } },
8
+ React.createElement(CircularProgress, { variant: "determinate", ...rest }),
9
+ React.createElement(Box, { sx: {
10
+ top: 0,
11
+ left: 0,
12
+ bottom: 0,
13
+ right: 0,
14
+ position: "absolute",
15
+ display: "flex",
16
+ alignItems: "center",
17
+ justifyContent: "center"
18
+ } },
19
+ React.createElement(Typography, { variant: "caption", component: "div", color: "text.secondary", ...textProps }, `${Math.round(props.value)}${valueUnit}`))));
20
+ }
@@ -0,0 +1,8 @@
1
+ /// <reference types="react" />
2
+ import { LinearProgressProps, TypographyProps } from "@mui/material";
3
+ export type PercentLinearProgressProps = LinearProgressProps & {
4
+ value: number;
5
+ valueUnit?: string;
6
+ textProps?: TypographyProps;
7
+ };
8
+ export declare function PercentLinearProgress(props: PercentLinearProgressProps): JSX.Element;
@@ -0,0 +1,12 @@
1
+ import { Box, LinearProgress, Typography } from "@mui/material";
2
+ import React from "react";
3
+ export function PercentLinearProgress(props) {
4
+ // Destruct
5
+ const { textProps, valueUnit = "%", ...rest } = props;
6
+ // Component
7
+ return (React.createElement(Box, { sx: { display: "flex", alignItems: "center" } },
8
+ React.createElement(Box, { sx: { width: "100%", mr: 1 } },
9
+ React.createElement(LinearProgress, { variant: "determinate", ...rest })),
10
+ React.createElement(Box, { sx: { minWidth: 35 } },
11
+ React.createElement(Typography, { variant: "caption", color: "text.secondary", ...textProps }, `${Math.round(props.value)}${valueUnit}`))));
12
+ }
package/lib/Tiplist.js CHANGED
@@ -15,7 +15,7 @@ export function Tiplist(props) {
15
15
  // Labels
16
16
  const { noOptions, loading, more, open: openDefault } = (_a = globalApp === null || globalApp === void 0 ? void 0 : globalApp.getLabels("noOptions", "loading", "more", "open")) !== null && _a !== void 0 ? _a : {};
17
17
  // Destruct
18
- const { search = false, idField = "id", idValue, inputAutoComplete = "off", inputError, inputHelperText, inputMargin, inputOnChange, inputRequired, inputVariant, label, loadData, defaultValue, value, maxItems = 16, width, name, readOnly, onChange, openOnFocus = true, noOptionsText = noOptions, loadingText = loading, openText = openDefault, getOptionLabel, getOptionDisabled, sx = {}, ...rest } = props;
18
+ const { search = false, idField = "id", idValue, inputAutoComplete = "off", inputError, inputHelperText, inputMargin, inputOnChange, inputRequired, inputVariant, label, loadData, defaultValue, value, maxItems = 16, width, name, readOnly, onChange, onValueChange, openOnFocus = true, noOptionsText = noOptions, loadingText = loading, openText = openDefault, getOptionLabel, getOptionDisabled, sx = {}, ...rest } = props;
19
19
  if (width && sx)
20
20
  Object.assign(sx, { width: `${width}px` });
21
21
  // Value input ref
@@ -90,6 +90,11 @@ export function Tiplist(props) {
90
90
  if (options != null && options.length >= maxItems) {
91
91
  options.push({ [idField]: "n/a" });
92
92
  }
93
+ if (id && options && onValueChange) {
94
+ const option = options.find((o) => o[idField] === id);
95
+ if (option)
96
+ onValueChange(option);
97
+ }
93
98
  // Indicates loading completed
94
99
  stateUpdate({
95
100
  loading: false,
@@ -141,6 +146,8 @@ export function Tiplist(props) {
141
146
  // Custom
142
147
  if (onChange != null)
143
148
  onChange(event, value, reason, details);
149
+ if (onValueChange)
150
+ onValueChange(value);
144
151
  // For clear case
145
152
  if (reason === "clear") {
146
153
  stateUpdate({ options: [] });
@@ -38,6 +38,11 @@ export type TiplistProProps<T extends ListType2 = ListType2> = Omit<Autocomplete
38
38
  * Input props
39
39
  */
40
40
  inputProps?: Omit<InputFieldProps, "onChange">;
41
+ /**
42
+ * Value change handler
43
+ * @param value New value
44
+ */
45
+ onValueChange?: (value: T | null) => void;
41
46
  };
42
47
  /**
43
48
  * TiplistPro
package/lib/TiplistPro.js CHANGED
@@ -13,7 +13,7 @@ export function TiplistPro(props) {
13
13
  // Labels
14
14
  const { noOptions, loading, more, open: openDefault } = (_a = globalApp === null || globalApp === void 0 ? void 0 : globalApp.getLabels("noOptions", "loading", "more", "open")) !== null && _a !== void 0 ? _a : {};
15
15
  // Destruct
16
- const { label, loadData, defaultValue, value, idValue, maxItems = 16, width, name, inputOnChange, inputProps, sx, openOnFocus = true, noOptionsText = noOptions, loadingText = loading, openText = openDefault, getOptionDisabled, getOptionLabel, onChange, ...rest } = props;
16
+ const { label, loadData, defaultValue, value, idValue, maxItems = 16, width, name, inputOnChange, inputProps, sx, openOnFocus = true, noOptionsText = noOptions, loadingText = loading, openText = openDefault, getOptionDisabled, getOptionLabel, onChange, onValueChange, ...rest } = props;
17
17
  if (width && sx)
18
18
  Object.assign(sx, { width: `${width}px` });
19
19
  // Value input ref
@@ -82,6 +82,11 @@ export function TiplistPro(props) {
82
82
  if (options != null && options.length >= maxItems) {
83
83
  options.push({ id: -1, name: "n/a" });
84
84
  }
85
+ if (id && options && onValueChange) {
86
+ const option = options.find((o) => o["id"] === id);
87
+ if (option)
88
+ onValueChange(option);
89
+ }
85
90
  // Indicates loading completed
86
91
  stateUpdate({
87
92
  loading: false,
@@ -135,6 +140,10 @@ export function TiplistPro(props) {
135
140
  // Custom
136
141
  if (onChange != null)
137
142
  onChange(event, value, reason, details);
143
+ if (onValueChange) {
144
+ if (typeof value === "object")
145
+ onValueChange(value == null ? null : value);
146
+ }
138
147
  // For clear case
139
148
  if (reason === "clear") {
140
149
  stateUpdate({ options: [] });
package/lib/index.d.ts CHANGED
@@ -69,6 +69,8 @@ export * from "./MUGlobal";
69
69
  export * from "./NotifierMU";
70
70
  export * from "./OptionBool";
71
71
  export * from "./OptionGroup";
72
+ export * from "./PercentCircularProgress";
73
+ export * from "./PercentLinearProgress";
72
74
  export * from "./PList";
73
75
  export * from "./ProgressCount";
74
76
  export * from "./PullToRefreshUI";
package/lib/index.js CHANGED
@@ -69,6 +69,8 @@ export * from "./MUGlobal";
69
69
  export * from "./NotifierMU";
70
70
  export * from "./OptionBool";
71
71
  export * from "./OptionGroup";
72
+ export * from "./PercentCircularProgress";
73
+ export * from "./PercentLinearProgress";
72
74
  export * from "./PList";
73
75
  export * from "./ProgressCount";
74
76
  export * from "./PullToRefreshUI";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/materialui",
3
- "version": "1.2.10",
3
+ "version": "1.2.12",
4
4
  "description": "TypeScript Material-UI Implementation",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -50,7 +50,7 @@
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.92",
53
+ "@etsoo/appscript": "^1.3.94",
54
54
  "@etsoo/notificationbase": "^1.1.24",
55
55
  "@etsoo/react": "^1.6.67",
56
56
  "@etsoo/shared": "^1.2.1",
@@ -1,84 +1,90 @@
1
- import { DataTypes } from '@etsoo/shared';
2
- import { AutocompleteProps } from '@mui/material';
3
- import { ChangeEventHandler } from 'react';
1
+ import { DataTypes } from "@etsoo/shared";
2
+ import { AutocompleteProps } from "@mui/material";
3
+ import { ChangeEventHandler } from "react";
4
4
 
5
5
  /**
6
6
  * Autocomplete extended props
7
7
  */
8
8
  export type AutocompleteExtendedProps<
9
- T extends object,
10
- D extends DataTypes.Keys<T>,
11
- M extends boolean | undefined = boolean | undefined
9
+ T extends object,
10
+ D extends DataTypes.Keys<T>,
11
+ M extends boolean | undefined = boolean | undefined
12
12
  > = Omit<
13
- AutocompleteProps<T, M, false, false>,
14
- 'renderInput' | 'options' | 'multiple'
13
+ AutocompleteProps<T, M, false, false>,
14
+ "renderInput" | "options" | "multiple"
15
15
  > & {
16
- /**
17
- * Id field
18
- */
19
- idField?: D;
16
+ /**
17
+ * Id field
18
+ */
19
+ idField?: D;
20
20
 
21
- /**
22
- * Id value
23
- */
24
- idValue?: T[D];
21
+ /**
22
+ * Id value
23
+ */
24
+ idValue?: T[D];
25
25
 
26
- /**
27
- * Autocomplete for the input
28
- */
29
- inputAutoComplete?: string;
26
+ /**
27
+ * Autocomplete for the input
28
+ */
29
+ inputAutoComplete?: string;
30
30
 
31
- /**
32
- * If `true`, the label is displayed in an error state.
33
- * @default false
34
- */
35
- inputError?: boolean;
31
+ /**
32
+ * If `true`, the label is displayed in an error state.
33
+ * @default false
34
+ */
35
+ inputError?: boolean;
36
36
 
37
- /**
38
- * The helper text content.
39
- */
40
- inputHelperText?: React.ReactNode;
37
+ /**
38
+ * The helper text content.
39
+ */
40
+ inputHelperText?: React.ReactNode;
41
41
 
42
- /**
43
- * If `dense` or `normal`, will adjust vertical spacing of this and contained components.
44
- * @default 'none'
45
- */
46
- inputMargin?: 'dense' | 'normal' | 'none';
42
+ /**
43
+ * If `dense` or `normal`, will adjust vertical spacing of this and contained components.
44
+ * @default 'none'
45
+ */
46
+ inputMargin?: "dense" | "normal" | "none";
47
47
 
48
- /**
49
- * Input onChange hanlder
50
- */
51
- inputOnChange?: ChangeEventHandler<HTMLInputElement> | undefined;
48
+ /**
49
+ * Input onChange hanlder
50
+ */
51
+ inputOnChange?: ChangeEventHandler<HTMLInputElement> | undefined;
52
52
 
53
- /**
54
- * If `true`, the label will indicate that the `input` is required.
55
- * @default false
56
- */
57
- inputRequired?: boolean;
53
+ /**
54
+ * If `true`, the label will indicate that the `input` is required.
55
+ * @default false
56
+ */
57
+ inputRequired?: boolean;
58
58
 
59
- /**
60
- * The variant to use.
61
- * @default 'outlined'
62
- */
63
- inputVariant?: 'standard' | 'outlined' | 'filled';
59
+ /**
60
+ * The variant to use.
61
+ * @default 'outlined'
62
+ */
63
+ inputVariant?: "standard" | "outlined" | "filled";
64
64
 
65
- /**
66
- * Label of the field
67
- */
68
- label: string;
65
+ /**
66
+ * Label of the field
67
+ */
68
+ label: string;
69
69
 
70
- /**
71
- * Name of the field
72
- */
73
- name: string;
70
+ /**
71
+ * Name of the field
72
+ */
73
+ name: string;
74
74
 
75
- /**
76
- * Is the field read only?
77
- */
78
- readOnly?: boolean;
75
+ /**
76
+ * Is the field read only?
77
+ */
78
+ readOnly?: boolean;
79
79
 
80
- /**
81
- * Is search field?
82
- */
83
- search?: boolean;
80
+ /**
81
+ * Is search field?
82
+ */
83
+ search?: boolean;
84
+
85
+ /**
86
+ * Value change handler
87
+ * @param value New value
88
+ */
89
+ onValueChange?: (value: T | null) => void;
84
90
  };
package/src/ComboBox.tsx CHANGED
@@ -89,6 +89,7 @@ export function ComboBox<
89
89
  dataReadonly = true,
90
90
  readOnly,
91
91
  onChange,
92
+ onValueChange,
92
93
  openOnFocus = true,
93
94
  value,
94
95
  disableCloseOnSelect = false,
@@ -135,6 +136,7 @@ export function ComboBox<
135
136
  React.useEffect(() => {
136
137
  if (localValue != null && localValue != stateValue) {
137
138
  setStateValue(localValue);
139
+ if (onValueChange) onValueChange(localValue);
138
140
  }
139
141
  }, [localValue]);
140
142
 
@@ -232,6 +234,8 @@ export function ComboBox<
232
234
 
233
235
  // Custom
234
236
  if (onChange != null) onChange(event, value, reason, details);
237
+
238
+ if (onValueChange) onValueChange(value);
235
239
  }}
236
240
  openOnFocus={openOnFocus}
237
241
  sx={sx}
@@ -31,7 +31,7 @@ export type ComboBoxMultipleProps<
31
31
  T extends object = ListType,
32
32
  D extends DataTypes.Keys<T> = IdDefaultType<T>,
33
33
  L extends DataTypes.Keys<T, string> = LabelDefaultType<T>
34
- > = AutocompleteExtendedProps<T, D, true> & {
34
+ > = Omit<AutocompleteExtendedProps<T, D, true>, "onValueChange"> & {
35
35
  /**
36
36
  * Auto add blank item
37
37
  */
@@ -32,6 +32,12 @@ export type ComboBoxProProps<D extends ListType2 = ListType2> = Omit<
32
32
  * Input props
33
33
  */
34
34
  inputProps?: Omit<InputFieldProps, "onChange">;
35
+
36
+ /**
37
+ * Value change handler
38
+ * @param value New value
39
+ */
40
+ onValueChange?: (value: D | null) => void;
35
41
  };
36
42
 
37
43
  export function ComboBoxPro<D extends ListType2 = ListType2>(
@@ -57,6 +63,7 @@ export function ComboBoxPro<D extends ListType2 = ListType2>(
57
63
  value,
58
64
  idValue,
59
65
  onChange,
66
+ onValueChange,
60
67
  ...rest
61
68
  } = props;
62
69
 
@@ -73,9 +80,11 @@ export function ComboBoxPro<D extends ListType2 = ListType2>(
73
80
  React.useEffect(() => {
74
81
  if (idValue == null) return;
75
82
  const option = localOptions.find((option) => option.id === idValue);
76
- if (option) setValue(option);
77
- else setValue(null);
78
- }, [localOptions]);
83
+ if (option) {
84
+ setValue(option);
85
+ if (onValueChange) onValueChange(option);
86
+ } else setValue(null);
87
+ }, [localOptions, idValue]);
79
88
 
80
89
  React.useEffect(() => {
81
90
  if (typeof options === "function") {
@@ -131,6 +140,10 @@ export function ComboBoxPro<D extends ListType2 = ListType2>(
131
140
  onChange={(event, value, reason, details) => {
132
141
  setValue(value);
133
142
  if (onChange) onChange(event, value, reason, details);
143
+ if (onValueChange) {
144
+ if (typeof value === "object")
145
+ onValueChange(value == null ? null : value);
146
+ }
134
147
  }}
135
148
  {...rest}
136
149
  />
package/src/ItemList.tsx CHANGED
@@ -69,7 +69,7 @@ export interface ItemListProps<
69
69
  onClose?(item: T | undefined, changed: boolean): void;
70
70
 
71
71
  /**
72
- * Current selected language
72
+ * Current selected id
73
73
  */
74
74
  selectedValue?: T[D];
75
75
 
@@ -0,0 +1,45 @@
1
+ import {
2
+ Box,
3
+ CircularProgress,
4
+ CircularProgressProps,
5
+ Typography,
6
+ TypographyProps
7
+ } from "@mui/material";
8
+ import React from "react";
9
+
10
+ export type PercentCircularProgressProps = CircularProgressProps & {
11
+ value: number;
12
+ valueUnit?: string;
13
+ textProps?: TypographyProps<"div">;
14
+ };
15
+
16
+ export function PercentCircularProgress(props: PercentCircularProgressProps) {
17
+ // Destruct
18
+ const { textProps, valueUnit = "%", ...rest } = props;
19
+
20
+ // Component
21
+ return (
22
+ <Box sx={{ position: "relative", display: "inline-flex" }}>
23
+ <CircularProgress variant="determinate" {...rest} />
24
+ <Box
25
+ sx={{
26
+ top: 0,
27
+ left: 0,
28
+ bottom: 0,
29
+ right: 0,
30
+ position: "absolute",
31
+ display: "flex",
32
+ alignItems: "center",
33
+ justifyContent: "center"
34
+ }}
35
+ >
36
+ <Typography
37
+ variant="caption"
38
+ component="div"
39
+ color="text.secondary"
40
+ {...textProps}
41
+ >{`${Math.round(props.value)}${valueUnit}`}</Typography>
42
+ </Box>
43
+ </Box>
44
+ );
45
+ }
@@ -0,0 +1,35 @@
1
+ import {
2
+ Box,
3
+ LinearProgress,
4
+ LinearProgressProps,
5
+ Typography,
6
+ TypographyProps
7
+ } from "@mui/material";
8
+ import React from "react";
9
+
10
+ export type PercentLinearProgressProps = LinearProgressProps & {
11
+ value: number;
12
+ valueUnit?: string;
13
+ textProps?: TypographyProps;
14
+ };
15
+
16
+ export function PercentLinearProgress(props: PercentLinearProgressProps) {
17
+ // Destruct
18
+ const { textProps, valueUnit = "%", ...rest } = props;
19
+
20
+ // Component
21
+ return (
22
+ <Box sx={{ display: "flex", alignItems: "center" }}>
23
+ <Box sx={{ width: "100%", mr: 1 }}>
24
+ <LinearProgress variant="determinate" {...rest} />
25
+ </Box>
26
+ <Box sx={{ minWidth: 35 }}>
27
+ <Typography
28
+ variant="caption"
29
+ color="text.secondary"
30
+ {...textProps}
31
+ >{`${Math.round(props.value)}${valueUnit}`}</Typography>
32
+ </Box>
33
+ </Box>
34
+ );
35
+ }
package/src/Tiplist.tsx CHANGED
@@ -80,6 +80,7 @@ export function Tiplist<
80
80
  name,
81
81
  readOnly,
82
82
  onChange,
83
+ onValueChange,
83
84
  openOnFocus = true,
84
85
  noOptionsText = noOptions,
85
86
  loadingText = loading,
@@ -191,6 +192,11 @@ export function Tiplist<
191
192
  options.push({ [idField]: "n/a" } as T);
192
193
  }
193
194
 
195
+ if (id && options && onValueChange) {
196
+ const option = options.find((o) => o[idField] === id);
197
+ if (option) onValueChange(option);
198
+ }
199
+
194
200
  // Indicates loading completed
195
201
  stateUpdate({
196
202
  loading: false,
@@ -262,6 +268,8 @@ export function Tiplist<
262
268
  // Custom
263
269
  if (onChange != null) onChange(event, value, reason, details);
264
270
 
271
+ if (onValueChange) onValueChange(value);
272
+
265
273
  // For clear case
266
274
  if (reason === "clear") {
267
275
  stateUpdate({ options: [] });
@@ -55,6 +55,12 @@ export type TiplistProProps<T extends ListType2 = ListType2> = Omit<
55
55
  * Input props
56
56
  */
57
57
  inputProps?: Omit<InputFieldProps, "onChange">;
58
+
59
+ /**
60
+ * Value change handler
61
+ * @param value New value
62
+ */
63
+ onValueChange?: (value: T | null) => void;
58
64
  };
59
65
 
60
66
  // Multiple states
@@ -101,6 +107,7 @@ export function TiplistPro<T extends ListType2 = ListType2>(
101
107
  getOptionDisabled,
102
108
  getOptionLabel,
103
109
  onChange,
110
+ onValueChange,
104
111
  ...rest
105
112
  } = props;
106
113
 
@@ -198,6 +205,11 @@ export function TiplistPro<T extends ListType2 = ListType2>(
198
205
  options.push({ id: -1, name: "n/a" } as T);
199
206
  }
200
207
 
208
+ if (id && options && onValueChange) {
209
+ const option = options.find((o) => o["id"] === id);
210
+ if (option) onValueChange(option);
211
+ }
212
+
201
213
  // Indicates loading completed
202
214
  stateUpdate({
203
215
  loading: false,
@@ -273,6 +285,11 @@ export function TiplistPro<T extends ListType2 = ListType2>(
273
285
  // Custom
274
286
  if (onChange != null) onChange(event, value, reason, details);
275
287
 
288
+ if (onValueChange) {
289
+ if (typeof value === "object")
290
+ onValueChange(value == null ? null : value);
291
+ }
292
+
276
293
  // For clear case
277
294
  if (reason === "clear") {
278
295
  stateUpdate({ options: [] });
package/src/index.ts CHANGED
@@ -72,6 +72,8 @@ export * from "./MUGlobal";
72
72
  export * from "./NotifierMU";
73
73
  export * from "./OptionBool";
74
74
  export * from "./OptionGroup";
75
+ export * from "./PercentCircularProgress";
76
+ export * from "./PercentLinearProgress";
75
77
  export * from "./PList";
76
78
  export * from "./ProgressCount";
77
79
  export * from "./PullToRefreshUI";